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
signature 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 {...@@ -30,6 +30,7 @@ pub fn build(b: *std.Build) !void {
30 const test_step = b.step("test", "Run all the tests");30 const test_step = b.step("test", "Run all the tests");
31 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;31 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;
32 const skip_install_langref = b.option(bool, "no-langref", "skip copying of langref to the installation prefix") orelse skip_install_lib_files;32 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
34 const docgen_exe = b.addExecutable(.{35 const docgen_exe = b.addExecutable(.{
35 .name = "docgen",36 .name = "docgen",
...@@ -166,6 +167,7 @@ pub fn build(b: *std.Build) !void {...@@ -166,6 +167,7 @@ pub fn build(b: *std.Build) !void {
166 exe.pie = pie;167 exe.pie = pie;
167 exe.sanitize_thread = sanitize_thread;168 exe.sanitize_thread = sanitize_thread;
168 exe.entitlements = entitlements;169 exe.entitlements = entitlements;
170 if (no_bin) exe.emit_bin = .no_emit;
169171
170 exe.build_id = b.option(172 exe.build_id = b.option(
171 std.Build.Step.Compile.BuildId,173 std.Build.Step.Compile.BuildId,
doc/langref.html.in+1-1
...@@ -10176,7 +10176,7 @@ pub fn main() void {...@@ -10176,7 +10176,7 @@ pub fn main() void {
1017610176
10177 {#header_open|Invalid Error Set Cast#}10177 {#header_open|Invalid Error Set Cast#}
10178 <p>At compile-time:</p>10178 <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}'#}
10180const Set1 = error{10180const Set1 = error{
10181 A,10181 A,
10182 B,10182 B,
lib/std/array_list.zig+44
...@@ -459,6 +459,28 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -459,6 +459,28 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
459 return self.items[prev_len..][0..n];459 return self.items[prev_len..][0..n];
460 }460 }
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
462 /// Remove and return the last element from the list.484 /// Remove and return the last element from the list.
463 /// Asserts the list has at least one item.485 /// Asserts the list has at least one item.
464 /// Invalidates pointers to the removed element.486 /// Invalidates pointers to the removed element.
...@@ -949,6 +971,28 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -949,6 +971,28 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
949 return self.items[prev_len..][0..n];971 return self.items[prev_len..][0..n];
950 }972 }
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
952 /// Remove and return the last element from the list.996 /// Remove and return the last element from the list.
953 /// Asserts the list has at least one item.997 /// Asserts the list has at least one item.
954 /// Invalidates pointers to last element.998 /// Invalidates pointers to last element.
lib/std/builtin.zig+3-3
...@@ -143,7 +143,7 @@ pub const Mode = OptimizeMode;...@@ -143,7 +143,7 @@ pub const Mode = OptimizeMode;
143143
144/// This data structure is used by the Zig language code generation and144/// This data structure is used by the Zig language code generation and
145/// therefore must be kept in sync with the compiler implementation.145/// therefore must be kept in sync with the compiler implementation.
146pub const CallingConvention = enum {146pub const CallingConvention = enum(u8) {
147 /// This is the default Zig calling convention used when not using `export` on `fn`147 /// This is the default Zig calling convention used when not using `export` on `fn`
148 /// and no other calling convention is specified.148 /// and no other calling convention is specified.
149 Unspecified,149 Unspecified,
...@@ -190,7 +190,7 @@ pub const CallingConvention = enum {...@@ -190,7 +190,7 @@ pub const CallingConvention = enum {
190190
191/// This data structure is used by the Zig language code generation and191/// This data structure is used by the Zig language code generation and
192/// therefore must be kept in sync with the compiler implementation.192/// therefore must be kept in sync with the compiler implementation.
193pub const AddressSpace = enum {193pub const AddressSpace = enum(u5) {
194 generic,194 generic,
195 gs,195 gs,
196 fs,196 fs,
...@@ -283,7 +283,7 @@ pub const Type = union(enum) {...@@ -283,7 +283,7 @@ pub const Type = union(enum) {
283283
284 /// This data structure is used by the Zig language code generation and284 /// This data structure is used by the Zig language code generation and
285 /// therefore must be kept in sync with the compiler implementation.285 /// therefore must be kept in sync with the compiler implementation.
286 pub const Size = enum {286 pub const Size = enum(u2) {
287 One,287 One,
288 Many,288 Many,
289 Slice,289 Slice,
lib/std/child_process.zig+2-2
...@@ -530,7 +530,7 @@ pub const ChildProcess = struct {...@@ -530,7 +530,7 @@ pub const ChildProcess = struct {
530 // can fail between fork() and execve().530 // can fail between fork() and execve().
531 // Therefore, we do all the allocation for the execve() before the fork().531 // Therefore, we do all the allocation for the execve() before the fork().
532 // This means we must do the null-termination of argv and env vars here.532 // 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);
534 for (self.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;534 for (self.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
535535
536 const envp = m: {536 const envp = m: {
...@@ -542,7 +542,7 @@ pub const ChildProcess = struct {...@@ -542,7 +542,7 @@ pub const ChildProcess = struct {
542 } else if (builtin.output_mode == .Exe) {542 } else if (builtin.output_mode == .Exe) {
543 // Then we have Zig start code and this works.543 // Then we have Zig start code and this works.
544 // TODO type-safety for null-termination of `os.environ`.544 // 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);
546 } else {546 } else {
547 // TODO come up with a solution for this.547 // TODO come up with a solution for this.
548 @compileError("missing std lib enhancement: ChildProcess implementation has no way to collect the environment variables to forward to the child process");548 @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 {...@@ -1256,10 +1256,8 @@ fn limitedOverlapCopy(frag: []u8, in: usize) void {
1256 // A single, non-overlapping memcpy suffices.1256 // A single, non-overlapping memcpy suffices.
1257 @memcpy(frag[0..first.len], first);1257 @memcpy(frag[0..first.len], first);
1258 } else {1258 } else {
1259 // Need two memcpy calls because one alone would overlap.1259 // One memcpy call would overlap, so just do this instead.
1260 @memcpy(frag[0..in], first[0..in]);1260 std.mem.copyForwards(u8, frag, first);
1261 const leftover = first.len - in;
1262 @memcpy(frag[in..][0..leftover], first[in..][0..leftover]);
1263 }1261 }
1264}1262}
12651263
lib/std/dwarf.zig+1
...@@ -936,6 +936,7 @@ pub const DwarfInfo = struct {...@@ -936,6 +936,7 @@ pub const DwarfInfo = struct {
936 const ranges_val = compile_unit.die.getAttr(AT.ranges) orelse continue;936 const ranges_val = compile_unit.die.getAttr(AT.ranges) orelse continue;
937 const ranges_offset = switch (ranges_val.*) {937 const ranges_offset = switch (ranges_val.*) {
938 .SecOffset => |off| off,938 .SecOffset => |off| off,
939 .Const => |c| try c.asUnsignedLe(),
939 .RangeListOffset => |idx| off: {940 .RangeListOffset => |idx| off: {
940 if (compile_unit.is_64) {941 if (compile_unit.is_64) {
941 const offset_loc = @intCast(usize, compile_unit.rnglists_base + 8 * idx);942 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");...@@ -36,6 +36,20 @@ const xxhash = @import("hash/xxhash.zig");
36pub const XxHash64 = xxhash.XxHash64;36pub const XxHash64 = xxhash.XxHash64;
37pub const XxHash32 = xxhash.XxHash32;37pub 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
39test {53test {
40 _ = adler;54 _ = adler;
41 _ = auto_hash;55 _ = 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 {...@@ -91,15 +91,21 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
9191
92 // Help the optimizer see that hashing an int is easy by inlining!92 // Help the optimizer see that hashing an int is easy by inlining!
93 // TODO Check if the situation is better after #561 is resolved.93 // TODO Check if the situation is better after #561 is resolved.
94 .Int => {94 .Int => |int| switch (int.signedness) {
95 if (comptime meta.trait.hasUniqueRepresentation(Key)) {95 .signed => hash(hasher, @bitCast(@Type(.{ .Int = .{
96 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });96 .bits = int.bits,
97 } else {97 .signedness = .unsigned,
98 // Take only the part containing the key value, the remaining98 } }), key), strat),
99 // bytes are undefined and must not be hashed!99 .unsigned => {
100 const byte_size = comptime std.math.divCeil(comptime_int, @bitSizeOf(Key), 8) catch unreachable;100 if (comptime meta.trait.hasUniqueRepresentation(Key)) {
101 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key)[0..byte_size] });101 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });
102 }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 },
103 },109 },
104110
105 .Bool => hash(hasher, @boolToInt(key), strat),111 .Bool => hash(hasher, @boolToInt(key), strat),
lib/std/math/big/int.zig+5-2
...@@ -2158,6 +2158,9 @@ pub const Const = struct {...@@ -2158,6 +2158,9 @@ pub const Const = struct {
2158 pub fn to(self: Const, comptime T: type) ConvertError!T {2158 pub fn to(self: Const, comptime T: type) ConvertError!T {
2159 switch (@typeInfo(T)) {2159 switch (@typeInfo(T)) {
2160 .Int => |info| {2160 .Int => |info| {
2161 // Make sure -0 is handled correctly.
2162 if (self.eqZero()) return 0;
2163
2161 const UT = std.meta.Int(.unsigned, info.bits);2164 const UT = std.meta.Int(.unsigned, info.bits);
21622165
2163 if (!self.fitsInTwosComp(info.signedness, info.bits)) {2166 if (!self.fitsInTwosComp(info.signedness, info.bits)) {
...@@ -2509,7 +2512,7 @@ pub const Const = struct {...@@ -2509,7 +2512,7 @@ pub const Const = struct {
2509 return total_limb_lz + bits - total_limb_bits;2512 return total_limb_lz + bits - total_limb_bits;
2510 }2513 }
25112514
2512 pub fn ctz(a: Const) Limb {2515 pub fn ctz(a: Const, bits: Limb) Limb {
2513 // Limbs are stored in little-endian order.2516 // Limbs are stored in little-endian order.
2514 var result: Limb = 0;2517 var result: Limb = 0;
2515 for (a.limbs) |limb| {2518 for (a.limbs) |limb| {
...@@ -2517,7 +2520,7 @@ pub const Const = struct {...@@ -2517,7 +2520,7 @@ pub const Const = struct {
2517 result += limb_tz;2520 result += limb_tz;
2518 if (limb_tz != @sizeOf(Limb) * 8) break;2521 if (limb_tz != @sizeOf(Limb) * 8) break;
2519 }2522 }
2520 return result;2523 return @min(result, bits);
2521 }2524 }
2522};2525};
25232526
lib/std/mem.zig+2-1
...@@ -4226,7 +4226,8 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {...@@ -4226,7 +4226,8 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {
4226/// The alignment must be a power of 2 and greater than 0.4226/// The alignment must be a power of 2 and greater than 0.
4227/// Asserts that rounding up the address does not cause integer overflow.4227/// Asserts that rounding up the address does not cause integer overflow.
4228pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {4228pub 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));
4230 return alignBackwardGeneric(T, addr + (alignment - 1), alignment);4231 return alignBackwardGeneric(T, addr + (alignment - 1), alignment);
4231}4232}
42324233
lib/std/process.zig+2-2
...@@ -1131,7 +1131,7 @@ pub fn execve(...@@ -1131,7 +1131,7 @@ pub fn execve(
1131 defer arena_allocator.deinit();1131 defer arena_allocator.deinit();
1132 const arena = arena_allocator.allocator();1132 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);
1135 for (argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;1135 for (argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
11361136
1137 const envp = m: {1137 const envp = m: {
...@@ -1143,7 +1143,7 @@ pub fn execve(...@@ -1143,7 +1143,7 @@ pub fn execve(
1143 } else if (builtin.output_mode == .Exe) {1143 } else if (builtin.output_mode == .Exe) {
1144 // Then we have Zig start code and this works.1144 // Then we have Zig start code and this works.
1145 // TODO type-safety for null-termination of `os.environ`.1145 // 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);
1147 } else {1147 } else {
1148 // TODO come up with a solution for this.1148 // TODO come up with a solution for this.
1149 @compileError("missing std lib enhancement: std.process.execv implementation has no way to collect the environment variables to forward to the child process");1149 @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 @@...@@ -5,16 +5,18 @@
55
6const std = @import("std");6const std = @import("std");
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const Value = @import("value.zig").Value;
9const Type = @import("type.zig").Type;
10const assert = std.debug.assert;8const assert = std.debug.assert;
9
11const Air = @This();10const 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
13instructions: std.MultiArrayList(Inst).Slice,16instructions: std.MultiArrayList(Inst).Slice,
14/// The meaning of this data is determined by `Inst.Tag` value.17/// The meaning of this data is determined by `Inst.Tag` value.
15/// The first few indexes are reserved. See `ExtraIndex` for the values.18/// The first few indexes are reserved. See `ExtraIndex` for the values.
16extra: []const u32,19extra: []const u32,
17values: []const Value,
1820
19pub const ExtraIndex = enum(u32) {21pub const ExtraIndex = enum(u32) {
20 /// Payload index of the main `Block` in the `extra` array.22 /// Payload index of the main `Block` in the `extra` array.
...@@ -183,6 +185,18 @@ pub const Inst = struct {...@@ -183,6 +185,18 @@ pub const Inst = struct {
183 /// Allocates stack local memory.185 /// Allocates stack local memory.
184 /// Uses the `ty` field.186 /// Uses the `ty` field.
185 alloc,187 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,
186 /// If the function will pass the result by-ref, this instruction returns the200 /// If the function will pass the result by-ref, this instruction returns the
187 /// result pointer. Otherwise it is equivalent to `alloc`.201 /// result pointer. Otherwise it is equivalent to `alloc`.
188 /// Uses the `ty` field.202 /// Uses the `ty` field.
...@@ -394,11 +408,9 @@ pub const Inst = struct {...@@ -394,11 +408,9 @@ pub const Inst = struct {
394 /// was executed on the operand.408 /// was executed on the operand.
395 /// Uses the `ty_pl` field. Payload is `TryPtr`.409 /// Uses the `ty_pl` field. Payload is `TryPtr`.
396 try_ptr,410 try_ptr,
397 /// A comptime-known value. Uses the `ty_pl` field, payload is index of411 /// A comptime-known value via an index into the InternPool.
398 /// `values` array.412 /// Uses the `interned` field.
399 constant,413 interned,
400 /// A comptime-known type. Uses the `ty` field.
401 const_ty,
402 /// Notes the beginning of a source code statement and marks the line and column.414 /// Notes the beginning of a source code statement and marks the line and column.
403 /// Result type is always void.415 /// Result type is always void.
404 /// Uses the `dbg_stmt` field.416 /// Uses the `dbg_stmt` field.
...@@ -408,10 +420,10 @@ pub const Inst = struct {...@@ -408,10 +420,10 @@ pub const Inst = struct {
408 /// Marks the end of a semantic scope for debug info variables.420 /// Marks the end of a semantic scope for debug info variables.
409 dbg_block_end,421 dbg_block_end,
410 /// Marks the start of an inline call.422 /// 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.
412 dbg_inline_begin,424 dbg_inline_begin,
413 /// Marks the end of an inline call.425 /// 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.
415 dbg_inline_end,427 dbg_inline_end,
416 /// Marks the beginning of a local variable. The operand is a pointer pointing428 /// Marks the beginning of a local variable. The operand is a pointer pointing
417 /// to the storage for the variable. The local may be a const or a var.429 /// to the storage for the variable. The local may be a const or a var.
...@@ -837,7 +849,96 @@ pub const Inst = struct {...@@ -837,7 +849,96 @@ pub const Inst = struct {
837 /// The position of an AIR instruction within the `Air` instructions array.849 /// The position of an AIR instruction within the `Air` instructions array.
838 pub const Index = u32;850 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
842 /// All instructions have an 8-byte payload, which is contained within943 /// All instructions have an 8-byte payload, which is contained within
843 /// this union. `Tag` determines which union field is active, as well as944 /// this union. `Tag` determines which union field is active, as well as
...@@ -845,6 +946,7 @@ pub const Inst = struct {...@@ -845,6 +946,7 @@ pub const Inst = struct {
845 pub const Data = union {946 pub const Data = union {
846 no_op: void,947 no_op: void,
847 un_op: Ref,948 un_op: Ref,
949 interned: InternPool.Index,
848950
849 bin_op: struct {951 bin_op: struct {
850 lhs: Ref,952 lhs: Ref,
...@@ -864,6 +966,10 @@ pub const Inst = struct {...@@ -864,6 +966,10 @@ pub const Inst = struct {
864 // Index into a different array.966 // Index into a different array.
865 payload: u32,967 payload: u32,
866 },968 },
969 ty_fn: struct {
970 ty: Ref,
971 func: Module.Fn.Index,
972 },
867 br: struct {973 br: struct {
868 block_inst: Index,974 block_inst: Index,
869 operand: Ref,975 operand: Ref,
...@@ -896,6 +1002,19 @@ pub const Inst = struct {...@@ -896,6 +1002,19 @@ pub const Inst = struct {
896 // Index into a different array.1002 // Index into a different array.
897 payload: u32,1003 payload: u32,
898 },1004 },
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
900 // Make sure we don't accidentally add a field to make this union1019 // Make sure we don't accidentally add a field to make this union
901 // bigger than expected. Note that in Debug builds, Zig is allowed1020 // bigger than expected. Note that in Debug builds, Zig is allowed
...@@ -974,8 +1093,7 @@ pub const FieldParentPtr = struct {...@@ -974,8 +1093,7 @@ pub const FieldParentPtr = struct {
974pub const Shuffle = struct {1093pub const Shuffle = struct {
975 a: Inst.Ref,1094 a: Inst.Ref,
976 b: Inst.Ref,1095 b: Inst.Ref,
977 // index to air_values1096 mask: InternPool.Index,
978 mask: u32,
979 mask_len: u32,1097 mask_len: u32,
980};1098};
9811099
...@@ -1064,15 +1182,15 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {...@@ -1064,15 +1182,15 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {
1064 return air.extra[extra.end..][0..extra.data.body_len];1182 return air.extra[extra.end..][0..extra.data.body_len];
1065}1183}
10661184
1067pub fn typeOf(air: Air, inst: Air.Inst.Ref) Type {1185pub fn typeOf(air: Air, inst: Air.Inst.Ref, ip: *const InternPool) Type {
1068 const ref_int = @enumToInt(inst);1186 const ref_int = @enumToInt(inst);
1069 if (ref_int < Air.Inst.Ref.typed_value_map.len) {1187 if (ref_int < InternPool.static_keys.len) {
1070 return Air.Inst.Ref.typed_value_map[ref_int].ty;1188 return InternPool.static_keys[ref_int].typeOf().toType();
1071 }1189 }
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);
1073}1191}
10741192
1075pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {1193pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: *const InternPool) Type {
1076 const datas = air.instructions.items(.data);1194 const datas = air.instructions.items(.data);
1077 switch (air.instructions.items(.tag)[inst]) {1195 switch (air.instructions.items(.tag)[inst]) {
1078 .add,1196 .add,
...@@ -1114,7 +1232,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1114,7 +1232,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1114 .div_exact_optimized,1232 .div_exact_optimized,
1115 .rem_optimized,1233 .rem_optimized,
1116 .mod_optimized,1234 .mod_optimized,
1117 => return air.typeOf(datas[inst].bin_op.lhs),1235 => return air.typeOf(datas[inst].bin_op.lhs, ip),
11181236
1119 .sqrt,1237 .sqrt,
1120 .sin,1238 .sin,
...@@ -1132,7 +1250,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1132,7 +1250,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1132 .trunc_float,1250 .trunc_float,
1133 .neg,1251 .neg,
1134 .neg_optimized,1252 .neg_optimized,
1135 => return air.typeOf(datas[inst].un_op),1253 => return air.typeOf(datas[inst].un_op, ip),
11361254
1137 .cmp_lt,1255 .cmp_lt,
1138 .cmp_lte,1256 .cmp_lte,
...@@ -1159,8 +1277,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1159,8 +1277,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1159 .error_set_has_value,1277 .error_set_has_value,
1160 => return Type.bool,1278 => return Type.bool,
11611279
1162 .const_ty => return Type.type,
1163
1164 .alloc,1280 .alloc,
1165 .ret_ptr,1281 .ret_ptr,
1166 .err_return_trace,1282 .err_return_trace,
...@@ -1171,7 +1287,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1171,7 +1287,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11711287
1172 .assembly,1288 .assembly,
1173 .block,1289 .block,
1174 .constant,
1175 .struct_field_ptr,1290 .struct_field_ptr,
1176 .struct_field_val,1291 .struct_field_val,
1177 .slice_elem_ptr,1292 .slice_elem_ptr,
...@@ -1194,6 +1309,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1194,6 +1309,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1194 .try_ptr,1309 .try_ptr,
1195 => return air.getRefType(datas[inst].ty_pl.ty),1310 => return air.getRefType(datas[inst].ty_pl.ty),
11961311
1312 .interned => return ip.typeOf(datas[inst].interned).toType(),
1313
1197 .not,1314 .not,
1198 .bitcast,1315 .bitcast,
1199 .load,1316 .load,
...@@ -1243,7 +1360,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1243,7 +1360,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1243 .ret_load,1360 .ret_load,
1244 .unreach,1361 .unreach,
1245 .trap,1362 .trap,
1246 => return Type.initTag(.noreturn),1363 => return Type.noreturn,
12471364
1248 .breakpoint,1365 .breakpoint,
1249 .dbg_stmt,1366 .dbg_stmt,
...@@ -1280,63 +1397,67 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1280,63 +1397,67 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1280 .wasm_memory_grow => return Type.i32,1397 .wasm_memory_grow => return Type.i32,
1281 .wasm_memory_size => return Type.u32,1398 .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
1287 .call, .call_always_tail, .call_never_tail, .call_never_inline => {1404 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
1288 const callee_ty = air.typeOf(datas[inst].pl_op.operand);1405 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1289 switch (callee_ty.zigTypeTag()) {1406 return callee_ty.fnReturnTypeIp(ip);
1290 .Fn => return callee_ty.fnReturnType(),
1291 .Pointer => return callee_ty.childType().fnReturnType(),
1292 else => unreachable,
1293 }
1294 },1407 },
12951408
1296 .slice_elem_val, .ptr_elem_val, .array_elem_val => {1409 .slice_elem_val, .ptr_elem_val, .array_elem_val => {
1297 const ptr_ty = air.typeOf(datas[inst].bin_op.lhs);1410 const ptr_ty = air.typeOf(datas[inst].bin_op.lhs, ip);
1298 return ptr_ty.elemType();1411 return ptr_ty.childTypeIp(ip);
1299 },1412 },
1300 .atomic_load => {1413 .atomic_load => {
1301 const ptr_ty = air.typeOf(datas[inst].atomic_load.ptr);1414 const ptr_ty = air.typeOf(datas[inst].atomic_load.ptr, ip);
1302 return ptr_ty.elemType();1415 return ptr_ty.childTypeIp(ip);
1303 },1416 },
1304 .atomic_rmw => {1417 .atomic_rmw => {
1305 const ptr_ty = air.typeOf(datas[inst].pl_op.operand);1418 const ptr_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1306 return ptr_ty.elemType();1419 return ptr_ty.childTypeIp(ip);
1307 },1420 },
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),
1312 .select => {1428 .select => {
1313 const extra = air.extraData(Air.Bin, datas[inst].pl_op.payload).data;1429 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);
1315 },1431 },
13161432
1317 .@"try" => {1433 .@"try" => {
1318 const err_union_ty = air.typeOf(datas[inst].pl_op.operand);1434 const err_union_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1319 return err_union_ty.errorUnionPayload();1435 return ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type.toType();
1320 },1436 },
13211437
1322 .work_item_id,1438 .work_item_id,
1323 .work_group_size,1439 .work_group_size,
1324 .work_group_id,1440 .work_group_id,
1325 => return Type.u32,1441 => return Type.u32,
1442
1443 .inferred_alloc => unreachable,
1444 .inferred_alloc_comptime => unreachable,
1326 }1445 }
1327}1446}
13281447
1329pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {1448pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {
1330 const ref_int = @enumToInt(ref);1449 const ref_int = @enumToInt(ref);
1331 if (ref_int < Air.Inst.Ref.typed_value_map.len) {1450 if (ref_int < ref_start_index) {
1332 var buffer: Value.ToTypeBuffer = undefined;1451 const ip_index = @intToEnum(InternPool.Index, ref_int);
1333 return Air.Inst.Ref.typed_value_map[ref_int].val.toType(&buffer);1452 return ip_index.toType();
1334 }1453 }
1335 const inst_index = ref_int - Air.Inst.Ref.typed_value_map.len;1454 const inst_index = ref_int - ref_start_index;
1336 const air_tags = air.instructions.items(.tag);1455 const air_tags = air.instructions.items(.tag);
1337 const air_datas = air.instructions.items(.data);1456 const air_datas = air.instructions.items(.data);
1338 assert(air_tags[inst_index] == .const_ty);1457 return switch (air_tags[inst_index]) {
1339 return air_datas[inst_index].ty;1458 .interned => air_datas[inst_index].interned.toType(),
1459 else => unreachable,
1460 };
1340}1461}
13411462
1342/// Returns the requested data, as well as the new index which is at the start of the1463/// 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...@@ -1350,7 +1471,8 @@ pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end
1350 u32 => air.extra[i],1471 u32 => air.extra[i],
1351 Inst.Ref => @intToEnum(Inst.Ref, air.extra[i]),1472 Inst.Ref => @intToEnum(Inst.Ref, air.extra[i]),
1352 i32 => @bitCast(i32, air.extra[i]),1473 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)),
1354 };1476 };
1355 i += 1;1477 i += 1;
1356 }1478 }
...@@ -1363,17 +1485,17 @@ pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end...@@ -1363,17 +1485,17 @@ pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end
1363pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {1485pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {
1364 air.instructions.deinit(gpa);1486 air.instructions.deinit(gpa);
1365 gpa.free(air.extra);1487 gpa.free(air.extra);
1366 gpa.free(air.values);
1367 air.* = undefined;1488 air.* = undefined;
1368}1489}
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 {1493pub fn indexToRef(inst: Inst.Index) Inst.Ref {
1373 return @intToEnum(Air.Inst.Ref, ref_start_index + inst);1494 return @intToEnum(Inst.Ref, ref_start_index + inst);
1374}1495}
13751496
1376pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {1497pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
1498 assert(inst != .none);
1377 const ref_int = @enumToInt(inst);1499 const ref_int = @enumToInt(inst);
1378 if (ref_int >= ref_start_index) {1500 if (ref_int >= ref_start_index) {
1379 return ref_int - ref_start_index;1501 return ref_int - ref_start_index;
...@@ -1382,18 +1504,23 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {...@@ -1382,18 +1504,23 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
1382 }1504 }
1383}1505}
13841506
1507pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
1508 if (inst == .none) return null;
1509 return refToIndex(inst);
1510}
1511
1385/// Returns `null` if runtime-known.1512/// 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 {
1387 const ref_int = @enumToInt(inst);1514 const ref_int = @enumToInt(inst);
1388 if (ref_int < Air.Inst.Ref.typed_value_map.len) {1515 if (ref_int < ref_start_index) {
1389 return Air.Inst.Ref.typed_value_map[ref_int].val;1516 const ip_index = @intToEnum(InternPool.Index, ref_int);
1517 return ip_index.toValue();
1390 }1518 }
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);
1392 const air_datas = air.instructions.items(.data);1520 const air_datas = air.instructions.items(.data);
1393 switch (air.instructions.items(.tag)[inst_index]) {1521 switch (air.instructions.items(.tag)[inst_index]) {
1394 .constant => return air.values[air_datas[inst_index].ty_pl.payload],1522 .interned => return air_datas[inst_index].interned.toValue(),
1395 .const_ty => unreachable,1523 else => return air.typeOfIndex(inst_index, &mod.intern_pool).onePossibleValue(mod),
1396 else => return air.typeOfIndex(inst_index).onePossibleValue(),
1397 }1524 }
1398}1525}
13991526
...@@ -1406,10 +1533,11 @@ pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {...@@ -1406,10 +1533,11 @@ pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {
1406 return bytes[0..end :0];1533 return bytes[0..end :0];
1407}1534}
14081535
1409/// Returns whether the given instruction must always be lowered, for instance because it can cause1536/// Returns whether the given instruction must always be lowered, for instance
1410/// side effects. If an instruction does not need to be lowered, and Liveness determines its result1537/// because it can cause side effects. If an instruction does not need to be
1411/// is unused, backends should avoid lowering it.1538/// lowered, and Liveness determines its result is unused, backends should
1412pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {1539/// avoid lowering it.
1540pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1413 const data = air.instructions.items(.data)[inst];1541 const data = air.instructions.items(.data)[inst];
1414 return switch (air.instructions.items(.tag)[inst]) {1542 return switch (air.instructions.items(.tag)[inst]) {
1415 .arg,1543 .arg,
...@@ -1498,6 +1626,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {...@@ -1498,6 +1626,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
1498 .mul_with_overflow,1626 .mul_with_overflow,
1499 .shl_with_overflow,1627 .shl_with_overflow,
1500 .alloc,1628 .alloc,
1629 .inferred_alloc,
1630 .inferred_alloc_comptime,
1501 .ret_ptr,1631 .ret_ptr,
1502 .bit_and,1632 .bit_and,
1503 .bit_or,1633 .bit_or,
...@@ -1546,8 +1676,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {...@@ -1546,8 +1676,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
1546 .cmp_neq_optimized,1676 .cmp_neq_optimized,
1547 .cmp_vector,1677 .cmp_vector,
1548 .cmp_vector_optimized,1678 .cmp_vector_optimized,
1549 .constant,1679 .interned,
1550 .const_ty,
1551 .is_null,1680 .is_null,
1552 .is_non_null,1681 .is_non_null,
1553 .is_null_ptr,1682 .is_null_ptr,
...@@ -1616,8 +1745,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {...@@ -1616,8 +1745,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
1616 => false,1745 => false,
16171746
1618 .assembly => @truncate(u1, air.extraData(Air.Asm, data.ty_pl.payload).data.flags >> 31) != 0,1747 .assembly => @truncate(u1, air.extraData(Air.Asm, data.ty_pl.payload).data.flags >> 31) != 0,
1619 .load => air.typeOf(data.ty_op.operand).isVolatilePtr(),1748 .load => air.typeOf(data.ty_op.operand, ip).isVolatilePtrIp(ip),
1620 .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs).isVolatilePtr(),1749 .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs, ip).isVolatilePtrIp(ip),
1621 .atomic_load => air.typeOf(data.atomic_load.ptr).isVolatilePtr(),1750 .atomic_load => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip),
1622 };1751 };
1623}1752}
src/AstGen.zig+41-24
...@@ -3934,7 +3934,7 @@ fn fnDecl(...@@ -3934,7 +3934,7 @@ fn fnDecl(
3934 var section_gz = decl_gz.makeSubBlock(params_scope);3934 var section_gz = decl_gz.makeSubBlock(params_scope);
3935 defer section_gz.unstack();3935 defer section_gz.unstack();
3936 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {3936 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);
3938 if (section_gz.instructionsSlice().len == 0) {3938 if (section_gz.instructionsSlice().len == 0) {
3939 // In this case we will send a len=0 body which can be encoded more efficiently.3939 // In this case we will send a len=0 body which can be encoded more efficiently.
3940 break :inst inst;3940 break :inst inst;
...@@ -4137,7 +4137,7 @@ fn globalVarDecl(...@@ -4137,7 +4137,7 @@ fn globalVarDecl(
4137 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);4137 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);
4138 };4138 };
4139 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {4139 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);
4141 };4141 };
4142 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;4142 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
4143 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);4143 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
...@@ -4497,7 +4497,7 @@ fn testDecl(...@@ -4497,7 +4497,7 @@ fn testDecl(
4497 .cc_gz = null,4497 .cc_gz = null,
4498 .align_ref = .none,4498 .align_ref = .none,
4499 .align_gz = null,4499 .align_gz = null,
4500 .ret_ref = .void_type,4500 .ret_ref = .anyerror_void_error_union_type,
4501 .ret_gz = null,4501 .ret_gz = null,
4502 .section_ref = .none,4502 .section_ref = .none,
4503 .section_gz = null,4503 .section_gz = null,
...@@ -4510,7 +4510,7 @@ fn testDecl(...@@ -4510,7 +4510,7 @@ fn testDecl(
4510 .body_gz = &fn_block,4510 .body_gz = &fn_block,
4511 .lib_name = 0,4511 .lib_name = 0,
4512 .is_var_args = false,4512 .is_var_args = false,
4513 .is_inferred_error = true,4513 .is_inferred_error = false,
4514 .is_test = true,4514 .is_test = true,
4515 .is_extern = false,4515 .is_extern = false,
4516 .is_noinline = false,4516 .is_noinline = false,
...@@ -7878,7 +7878,7 @@ fn unionInit(...@@ -7878,7 +7878,7 @@ fn unionInit(
7878 params: []const Ast.Node.Index,7878 params: []const Ast.Node.Index,
7879) InnerError!Zir.Inst.Ref {7879) InnerError!Zir.Inst.Ref {
7880 const union_type = try typeExpr(gz, scope, params[0]);7880 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]);
7882 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{7882 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
7883 .container_type = union_type,7883 .container_type = union_type,
7884 .field_name = field_name,7884 .field_name = field_name,
...@@ -8100,12 +8100,12 @@ fn builtinCall(...@@ -8100,12 +8100,12 @@ fn builtinCall(
8100 if (ri.rl == .ref) {8100 if (ri.rl == .ref) {
8101 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{8101 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
8102 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),8102 .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]),
8104 });8104 });
8105 }8105 }
8106 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{8106 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
8107 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),8107 .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]),
8109 });8109 });
8110 return rvalue(gz, ri, result, node);8110 return rvalue(gz, ri, result, node);
8111 },8111 },
...@@ -8271,11 +8271,11 @@ fn builtinCall(...@@ -8271,11 +8271,11 @@ fn builtinCall(
8271 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),8271 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),
82728272
8273 .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int),8273 .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),
8275 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota),8275 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota),
8276 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),8276 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),
8277 .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int),8277 .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),
8279 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),8279 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),
8280 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),8280 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),
8281 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),8281 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),
...@@ -8334,7 +8334,7 @@ fn builtinCall(...@@ -8334,7 +8334,7 @@ fn builtinCall(
8334 },8334 },
8335 .panic => {8335 .panic => {
8336 try emitDbgNode(gz, node);8336 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);
8338 },8338 },
8339 .trap => {8339 .trap => {
8340 try emitDbgNode(gz, node);8340 try emitDbgNode(gz, node);
...@@ -8450,7 +8450,7 @@ fn builtinCall(...@@ -8450,7 +8450,7 @@ fn builtinCall(
8450 },8450 },
8451 .c_define => {8451 .c_define => {
8452 if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});8452 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]);
8454 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);8454 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
8455 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{8455 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
8456 .node = gz.nodeIndexToRelative(node),8456 .node = gz.nodeIndexToRelative(node),
...@@ -8530,7 +8530,7 @@ fn builtinCall(...@@ -8530,7 +8530,7 @@ fn builtinCall(
8530 return rvalue(gz, ri, result, node);8530 return rvalue(gz, ri, result, node);
8531 },8531 },
8532 .call => {8532 .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]);
8534 const callee = try expr(gz, scope, .{ .rl = .none }, params[1]);8534 const callee = try expr(gz, scope, .{ .rl = .none }, params[1]);
8535 const args = try expr(gz, scope, .{ .rl = .none }, params[2]);8535 const args = try expr(gz, scope, .{ .rl = .none }, params[2]);
8536 const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{8536 const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{
...@@ -8546,7 +8546,7 @@ fn builtinCall(...@@ -8546,7 +8546,7 @@ fn builtinCall(
8546 },8546 },
8547 .field_parent_ptr => {8547 .field_parent_ptr => {
8548 const parent_type = try typeExpr(gz, scope, params[0]);8548 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]);
8550 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{8550 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
8551 .parent_type = parent_type,8551 .parent_type = parent_type,
8552 .field_name = field_name,8552 .field_name = field_name,
...@@ -8701,7 +8701,7 @@ fn hasDeclOrField(...@@ -8701,7 +8701,7 @@ fn hasDeclOrField(
8701 tag: Zir.Inst.Tag,8701 tag: Zir.Inst.Tag,
8702) InnerError!Zir.Inst.Ref {8702) InnerError!Zir.Inst.Ref {
8703 const container_type = try typeExpr(gz, scope, lhs_node);8703 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);
8705 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8705 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8706 .lhs = container_type,8706 .lhs = container_type,
8707 .rhs = name,8707 .rhs = name,
...@@ -8851,7 +8851,7 @@ fn simpleCBuiltin(...@@ -8851,7 +8851,7 @@ fn simpleCBuiltin(
8851) InnerError!Zir.Inst.Ref {8851) InnerError!Zir.Inst.Ref {
8852 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";8852 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
8853 if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});8853 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);
8855 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{8855 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
8856 .node = gz.nodeIndexToRelative(node),8856 .node = gz.nodeIndexToRelative(node),
8857 .operand = operand,8857 .operand = operand,
...@@ -8869,7 +8869,7 @@ fn offsetOf(...@@ -8869,7 +8869,7 @@ fn offsetOf(
8869 tag: Zir.Inst.Tag,8869 tag: Zir.Inst.Tag,
8870) InnerError!Zir.Inst.Ref {8870) InnerError!Zir.Inst.Ref {
8871 const type_inst = try typeExpr(gz, scope, lhs_node);8871 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);
8873 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8873 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8874 .lhs = type_inst,8874 .lhs = type_inst,
8875 .rhs = field_name,8875 .rhs = field_name,
...@@ -10271,6 +10271,8 @@ fn rvalue(...@@ -10271,6 +10271,8 @@ fn rvalue(
10271 as_ty | @enumToInt(Zir.Inst.Ref.i32_type),10271 as_ty | @enumToInt(Zir.Inst.Ref.i32_type),
10272 as_ty | @enumToInt(Zir.Inst.Ref.u64_type),10272 as_ty | @enumToInt(Zir.Inst.Ref.u64_type),
10273 as_ty | @enumToInt(Zir.Inst.Ref.i64_type),10273 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),
10274 as_ty | @enumToInt(Zir.Inst.Ref.usize_type),10276 as_ty | @enumToInt(Zir.Inst.Ref.usize_type),
10275 as_ty | @enumToInt(Zir.Inst.Ref.isize_type),10277 as_ty | @enumToInt(Zir.Inst.Ref.isize_type),
10276 as_ty | @enumToInt(Zir.Inst.Ref.c_char_type),10278 as_ty | @enumToInt(Zir.Inst.Ref.c_char_type),
...@@ -10296,15 +10298,30 @@ fn rvalue(...@@ -10296,15 +10298,30 @@ fn rvalue(
10296 as_ty | @enumToInt(Zir.Inst.Ref.comptime_int_type),10298 as_ty | @enumToInt(Zir.Inst.Ref.comptime_int_type),
10297 as_ty | @enumToInt(Zir.Inst.Ref.comptime_float_type),10299 as_ty | @enumToInt(Zir.Inst.Ref.comptime_float_type),
10298 as_ty | @enumToInt(Zir.Inst.Ref.noreturn_type),10300 as_ty | @enumToInt(Zir.Inst.Ref.noreturn_type),
10301 as_ty | @enumToInt(Zir.Inst.Ref.anyframe_type),
10299 as_ty | @enumToInt(Zir.Inst.Ref.null_type),10302 as_ty | @enumToInt(Zir.Inst.Ref.null_type),
10300 as_ty | @enumToInt(Zir.Inst.Ref.undefined_type),10303 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),
10307 as_ty | @enumToInt(Zir.Inst.Ref.enum_literal_type),10304 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),
10308 as_comptime_int | @enumToInt(Zir.Inst.Ref.zero),10325 as_comptime_int | @enumToInt(Zir.Inst.Ref.zero),
10309 as_comptime_int | @enumToInt(Zir.Inst.Ref.one),10326 as_comptime_int | @enumToInt(Zir.Inst.Ref.one),
10310 as_bool | @enumToInt(Zir.Inst.Ref.bool_true),10327 as_bool | @enumToInt(Zir.Inst.Ref.bool_true),
...@@ -10677,8 +10694,8 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {...@@ -10677,8 +10694,8 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {
10677 const string_bytes = &astgen.string_bytes;10694 const string_bytes = &astgen.string_bytes;
10678 const str_index = @intCast(u32, string_bytes.items.len);10695 const str_index = @intCast(u32, string_bytes.items.len);
10679 try astgen.appendIdentStr(ident_token, string_bytes);10696 try astgen.appendIdentStr(ident_token, string_bytes);
10680 const key = string_bytes.items[str_index..];10697 const key: []const u8 = string_bytes.items[str_index..];
10681 const gop = try astgen.string_table.getOrPutContextAdapted(gpa, @as([]const u8, key), StringIndexAdapter{10698 const gop = try astgen.string_table.getOrPutContextAdapted(gpa, key, StringIndexAdapter{
10682 .bytes = string_bytes,10699 .bytes = string_bytes,
10683 }, StringIndexContext{10700 }, StringIndexContext{
10684 .bytes = string_bytes,10701 .bytes = string_bytes,
src/Autodoc.zig+23-24
...@@ -8,6 +8,7 @@ const CompilationModule = @import("Module.zig");...@@ -8,6 +8,7 @@ const CompilationModule = @import("Module.zig");
8const File = CompilationModule.File;8const File = CompilationModule.File;
9const Module = @import("Package.zig");9const Module = @import("Package.zig");
10const Tokenizer = std.zig.Tokenizer;10const Tokenizer = std.zig.Tokenizer;
11const InternPool = @import("InternPool.zig");
11const Zir = @import("Zir.zig");12const Zir = @import("Zir.zig");
12const Ref = Zir.Inst.Ref;13const Ref = Zir.Inst.Ref;
13const log = std.log.scoped(.autodoc);14const log = std.log.scoped(.autodoc);
...@@ -95,8 +96,6 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -95,8 +96,6 @@ pub fn generateZirData(self: *Autodoc) !void {
95 }96 }
96 }97 }
9798
98 log.debug("Ref map size: {}", .{Ref.typed_value_map.len});
99
100 const root_src_dir = self.comp_module.main_pkg.root_src_directory;99 const root_src_dir = self.comp_module.main_pkg.root_src_directory;
101 const root_src_path = self.comp_module.main_pkg.root_src_path;100 const root_src_path = self.comp_module.main_pkg.root_src_path;
102 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});101 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});
...@@ -108,18 +107,20 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -108,18 +107,20 @@ pub fn generateZirData(self: *Autodoc) !void {
108 const file = self.comp_module.import_table.get(abs_root_src_path).?; // file is expected to be present in the import table107 const file = self.comp_module.import_table.get(abs_root_src_path).?; // file is expected to be present in the import table
109 // Append all the types in Zir.Inst.Ref.108 // Append all the types in Zir.Inst.Ref.
110 {109 {
111 try self.types.append(self.arena, .{110 comptime std.debug.assert(@enumToInt(InternPool.Index.first_type) == 0);
112 .ComptimeExpr = .{ .name = "ComptimeExpr" },111 var i: u32 = 0;
113 });112 while (i <= @enumToInt(InternPool.Index.last_type)) : (i += 1) {
114113 const ip_index = @intToEnum(InternPool.Index, i);
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) {
118 var tmpbuf = std.ArrayList(u8).init(self.arena);114 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 }
120 try self.types.append(121 try self.types.append(
121 self.arena,122 self.arena,
122 switch (@intToEnum(Ref, i)) {123 switch (ip_index) {
123 else => blk: {124 else => blk: {
124 // TODO: map the remaining refs to a correct type125 // TODO: map the remaining refs to a correct type
125 // instead of just assinging "array" to them.126 // instead of just assinging "array" to them.
...@@ -1040,7 +1041,7 @@ fn walkInstruction(...@@ -1040,7 +1041,7 @@ fn walkInstruction(
1040 .ret_load => {1041 .ret_load => {
1041 const un_node = data[inst_index].un_node;1042 const un_node = data[inst_index].un_node;
1042 const res_ptr_ref = un_node.operand;1043 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).?;
1044 // TODO: this instruction doesn't let us know trivially if there's1045 // TODO: this instruction doesn't let us know trivially if there's
1045 // branching involved or not. For now here's the strat:1046 // branching involved or not. For now here's the strat:
1046 // We search backwarts until `ret_ptr` for `store_node`,1047 // We search backwarts until `ret_ptr` for `store_node`,
...@@ -2157,11 +2158,10 @@ fn walkInstruction(...@@ -2157,11 +2158,10 @@ fn walkInstruction(
2157 const lhs_ref = blk: {2158 const lhs_ref = blk: {
2158 var lhs_extra = extra;2159 var lhs_extra = extra;
2159 while (true) {2160 while (true) {
2160 if (@enumToInt(lhs_extra.data.lhs) < Ref.typed_value_map.len) {2161 const lhs = Zir.refToIndex(lhs_extra.data.lhs) orelse {
2161 break :blk lhs_extra.data.lhs;2162 break :blk lhs_extra.data.lhs;
2162 }2163 };
21632164
2164 const lhs = @enumToInt(lhs_extra.data.lhs) - Ref.typed_value_map.len;
2165 if (tags[lhs] != .field_val and2165 if (tags[lhs] != .field_val and
2166 tags[lhs] != .field_ptr and2166 tags[lhs] != .field_ptr and
2167 tags[lhs] != .field_type) break :blk lhs_extra.data.lhs;2167 tags[lhs] != .field_type) break :blk lhs_extra.data.lhs;
...@@ -2188,8 +2188,7 @@ fn walkInstruction(...@@ -2188,8 +2188,7 @@ fn walkInstruction(
2188 // TODO: double check that we really don't need type info here2188 // TODO: double check that we really don't need type info here
21892189
2190 const wr = blk: {2190 const wr = blk: {
2191 if (@enumToInt(lhs_ref) >= Ref.typed_value_map.len) {2191 if (Zir.refToIndex(lhs_ref)) |lhs_inst| {
2192 const lhs_inst = @enumToInt(lhs_ref) - Ref.typed_value_map.len;
2193 if (tags[lhs_inst] == .call or tags[lhs_inst] == .field_call) {2192 if (tags[lhs_inst] == .call or tags[lhs_inst] == .field_call) {
2194 break :blk DocData.WalkResult{2193 break :blk DocData.WalkResult{
2195 .expr = .{2194 .expr = .{
...@@ -4672,16 +4671,19 @@ fn walkRef(...@@ -4672,16 +4671,19 @@ fn walkRef(
4672 ref: Ref,4671 ref: Ref,
4673 need_type: bool, // true when the caller needs also a typeRef for the return value4672 need_type: bool, // true when the caller needs also a typeRef for the return value
4674) AutodocErrors!DocData.WalkResult {4673) AutodocErrors!DocData.WalkResult {
4675 const enum_value = @enumToInt(ref);4674 if (ref == .none) {
4676 if (enum_value <= @enumToInt(Ref.anyerror_void_error_union_type)) {4675 return .{ .expr = .{ .comptimeExpr = 0 } };
4676 } else if (@enumToInt(ref) <= @enumToInt(InternPool.Index.last_type)) {
4677 // We can just return a type that indexes into `types` with the4677 // We can just return a type that indexes into `types` with the
4678 // enum value because in the beginning we pre-filled `types` with4678 // enum value because in the beginning we pre-filled `types` with
4679 // the types that are listed in `Ref`.4679 // the types that are listed in `Ref`.
4680 return DocData.WalkResult{4680 return DocData.WalkResult{
4681 .typeRef = .{ .type = @enumToInt(std.builtin.TypeId.Type) },4681 .typeRef = .{ .type = @enumToInt(std.builtin.TypeId.Type) },
4682 .expr = .{ .type = enum_value },4682 .expr = .{ .type = @enumToInt(ref) },
4683 };4683 };
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 {
4685 switch (ref) {4687 switch (ref) {
4686 else => {4688 else => {
4687 panicWithContext(4689 panicWithContext(
...@@ -4774,9 +4776,6 @@ fn walkRef(...@@ -4774,9 +4776,6 @@ fn walkRef(
4774 // } };4776 // } };
4775 // },4777 // },
4776 }4778 }
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);
4780 }4779 }
4781}4780}
47824781
src/Compilation.zig+38-26
...@@ -87,6 +87,7 @@ clang_preprocessor_mode: ClangPreprocessorMode,...@@ -87,6 +87,7 @@ clang_preprocessor_mode: ClangPreprocessorMode,
87/// Whether to print clang argvs to stdout.87/// Whether to print clang argvs to stdout.
88verbose_cc: bool,88verbose_cc: bool,
89verbose_air: bool,89verbose_air: bool,
90verbose_intern_pool: bool,
90verbose_llvm_ir: ?[]const u8,91verbose_llvm_ir: ?[]const u8,
91verbose_llvm_bc: ?[]const u8,92verbose_llvm_bc: ?[]const u8,
92verbose_cimport: bool,93verbose_cimport: bool,
...@@ -226,7 +227,7 @@ const Job = union(enum) {...@@ -226,7 +227,7 @@ const Job = union(enum) {
226 /// Write the constant value for a Decl to the output file.227 /// Write the constant value for a Decl to the output file.
227 codegen_decl: Module.Decl.Index,228 codegen_decl: Module.Decl.Index,
228 /// Write the machine code for a function to the output file.229 /// Write the machine code for a function to the output file.
229 codegen_func: *Module.Fn,230 codegen_func: Module.Fn.Index,
230 /// Render the .h file snippet for the Decl.231 /// Render the .h file snippet for the Decl.
231 emit_h_decl: Module.Decl.Index,232 emit_h_decl: Module.Decl.Index,
232 /// The Decl needs to be analyzed and possibly export itself.233 /// The Decl needs to be analyzed and possibly export itself.
...@@ -593,6 +594,7 @@ pub const InitOptions = struct {...@@ -593,6 +594,7 @@ pub const InitOptions = struct {
593 verbose_cc: bool = false,594 verbose_cc: bool = false,
594 verbose_link: bool = false,595 verbose_link: bool = false,
595 verbose_air: bool = false,596 verbose_air: bool = false,
597 verbose_intern_pool: bool = false,
596 verbose_llvm_ir: ?[]const u8 = null,598 verbose_llvm_ir: ?[]const u8 = null,
597 verbose_llvm_bc: ?[]const u8 = null,599 verbose_llvm_bc: ?[]const u8 = null,
598 verbose_cimport: bool = false,600 verbose_cimport: bool = false,
...@@ -1315,9 +1317,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1315,9 +1317,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1315 .global_zir_cache = global_zir_cache,1317 .global_zir_cache = global_zir_cache,
1316 .local_zir_cache = local_zir_cache,1318 .local_zir_cache = local_zir_cache,
1317 .emit_h = emit_h,1319 .emit_h = emit_h,
1318 .error_name_list = .{},1320 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
1319 };1321 };
1320 try module.error_name_list.append(gpa, "(no error)");1322 try module.init();
13211323
1322 break :blk module;1324 break :blk module;
1323 } else blk: {1325 } else blk: {
...@@ -1574,6 +1576,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1574,6 +1576,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1574 .clang_preprocessor_mode = options.clang_preprocessor_mode,1576 .clang_preprocessor_mode = options.clang_preprocessor_mode,
1575 .verbose_cc = options.verbose_cc,1577 .verbose_cc = options.verbose_cc,
1576 .verbose_air = options.verbose_air,1578 .verbose_air = options.verbose_air,
1579 .verbose_intern_pool = options.verbose_intern_pool,
1577 .verbose_llvm_ir = options.verbose_llvm_ir,1580 .verbose_llvm_ir = options.verbose_llvm_ir,
1578 .verbose_llvm_bc = options.verbose_llvm_bc,1581 .verbose_llvm_bc = options.verbose_llvm_bc,
1579 .verbose_cimport = options.verbose_cimport,1582 .verbose_cimport = options.verbose_cimport,
...@@ -2026,6 +2029,13 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2026,6 +2029,13 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2026 try comp.performAllTheWork(main_progress_node);2029 try comp.performAllTheWork(main_progress_node);
20272030
2028 if (comp.bin_file.options.module) |module| {2031 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
2029 if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {2039 if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
2030 // The `test_functions` decl has been intentionally postponed until now,2040 // The `test_functions` decl has been intentionally postponed until now,
2031 // at which point we must populate it with the list of test functions that2041 // 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...@@ -2042,7 +2052,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2042 assert(decl.deletion_flag);2052 assert(decl.deletion_flag);
2043 assert(decl.dependants.count() == 0);2053 assert(decl.dependants.count() == 0);
2044 const is_anon = if (decl.zir_decl_index == 0) blk: {2054 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);
2046 } else false;2056 } else false;
20472057
2048 try module.clearDecl(decl_index, null);2058 try module.clearDecl(decl_index, null);
...@@ -2523,8 +2533,7 @@ pub fn totalErrorCount(self: *Compilation) u32 {...@@ -2523,8 +2533,7 @@ pub fn totalErrorCount(self: *Compilation) u32 {
2523 // the previous parse success, including compile errors, but we cannot2533 // the previous parse success, including compile errors, but we cannot
2524 // emit them until the file succeeds parsing.2534 // emit them until the file succeeds parsing.
2525 for (module.failed_decls.keys()) |key| {2535 for (module.failed_decls.keys()) |key| {
2526 const decl = module.declPtr(key);2536 if (module.declFileScope(key).okToReportErrors()) {
2527 if (decl.getFileScope().okToReportErrors()) {
2528 total += 1;2537 total += 1;
2529 if (module.cimport_errors.get(key)) |errors| {2538 if (module.cimport_errors.get(key)) |errors| {
2530 total += errors.len;2539 total += errors.len;
...@@ -2533,8 +2542,7 @@ pub fn totalErrorCount(self: *Compilation) u32 {...@@ -2533,8 +2542,7 @@ pub fn totalErrorCount(self: *Compilation) u32 {
2533 }2542 }
2534 if (module.emit_h) |emit_h| {2543 if (module.emit_h) |emit_h| {
2535 for (emit_h.failed_decls.keys()) |key| {2544 for (emit_h.failed_decls.keys()) |key| {
2536 const decl = module.declPtr(key);2545 if (module.declFileScope(key).okToReportErrors()) {
2537 if (decl.getFileScope().okToReportErrors()) {
2538 total += 1;2546 total += 1;
2539 }2547 }
2540 }2548 }
...@@ -2618,7 +2626,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {...@@ -2618,7 +2626,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
2618 var it = module.failed_files.iterator();2626 var it = module.failed_files.iterator();
2619 while (it.next()) |entry| {2627 while (it.next()) |entry| {
2620 if (entry.value_ptr.*) |msg| {2628 if (entry.value_ptr.*) |msg| {
2621 try addModuleErrorMsg(&bundle, msg.*);2629 try addModuleErrorMsg(module, &bundle, msg.*);
2622 } else {2630 } else {
2623 // Must be ZIR errors. Note that this may include AST errors.2631 // Must be ZIR errors. Note that this may include AST errors.
2624 // addZirErrorMessages asserts that the tree is loaded.2632 // addZirErrorMessages asserts that the tree is loaded.
...@@ -2631,17 +2639,17 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {...@@ -2631,17 +2639,17 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
2631 var it = module.failed_embed_files.iterator();2639 var it = module.failed_embed_files.iterator();
2632 while (it.next()) |entry| {2640 while (it.next()) |entry| {
2633 const msg = entry.value_ptr.*;2641 const msg = entry.value_ptr.*;
2634 try addModuleErrorMsg(&bundle, msg.*);2642 try addModuleErrorMsg(module, &bundle, msg.*);
2635 }2643 }
2636 }2644 }
2637 {2645 {
2638 var it = module.failed_decls.iterator();2646 var it = module.failed_decls.iterator();
2639 while (it.next()) |entry| {2647 while (it.next()) |entry| {
2640 const decl = module.declPtr(entry.key_ptr.*);2648 const decl_index = entry.key_ptr.*;
2641 // Skip errors for Decls within files that had a parse failure.2649 // Skip errors for Decls within files that had a parse failure.
2642 // We'll try again once parsing succeeds.2650 // We'll try again once parsing succeeds.
2643 if (decl.getFileScope().okToReportErrors()) {2651 if (module.declFileScope(decl_index).okToReportErrors()) {
2644 try addModuleErrorMsg(&bundle, entry.value_ptr.*.*);2652 try addModuleErrorMsg(module, &bundle, entry.value_ptr.*.*);
2645 if (module.cimport_errors.get(entry.key_ptr.*)) |cimport_errors| for (cimport_errors) |c_error| {2653 if (module.cimport_errors.get(entry.key_ptr.*)) |cimport_errors| for (cimport_errors) |c_error| {
2646 try bundle.addRootErrorMessage(.{2654 try bundle.addRootErrorMessage(.{
2647 .msg = try bundle.addString(std.mem.span(c_error.msg)),2655 .msg = try bundle.addString(std.mem.span(c_error.msg)),
...@@ -2662,16 +2670,16 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {...@@ -2662,16 +2670,16 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
2662 if (module.emit_h) |emit_h| {2670 if (module.emit_h) |emit_h| {
2663 var it = emit_h.failed_decls.iterator();2671 var it = emit_h.failed_decls.iterator();
2664 while (it.next()) |entry| {2672 while (it.next()) |entry| {
2665 const decl = module.declPtr(entry.key_ptr.*);2673 const decl_index = entry.key_ptr.*;
2666 // Skip errors for Decls within files that had a parse failure.2674 // Skip errors for Decls within files that had a parse failure.
2667 // We'll try again once parsing succeeds.2675 // We'll try again once parsing succeeds.
2668 if (decl.getFileScope().okToReportErrors()) {2676 if (module.declFileScope(decl_index).okToReportErrors()) {
2669 try addModuleErrorMsg(&bundle, entry.value_ptr.*.*);2677 try addModuleErrorMsg(module, &bundle, entry.value_ptr.*.*);
2670 }2678 }
2671 }2679 }
2672 }2680 }
2673 for (module.failed_exports.values()) |value| {2681 for (module.failed_exports.values()) |value| {
2674 try addModuleErrorMsg(&bundle, value.*);2682 try addModuleErrorMsg(module, &bundle, value.*);
2675 }2683 }
2676 }2684 }
26772685
...@@ -2703,7 +2711,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {...@@ -2703,7 +2711,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
2703 const values = module.compile_log_decls.values();2711 const values = module.compile_log_decls.values();
2704 // First one will be the error; subsequent ones will be notes.2712 // First one will be the error; subsequent ones will be notes.
2705 const err_decl = module.declPtr(keys[0]);2713 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);
2707 const err_msg = Module.ErrorMsg{2715 const err_msg = Module.ErrorMsg{
2708 .src_loc = src_loc,2716 .src_loc = src_loc,
2709 .msg = "found compile log statement",2717 .msg = "found compile log statement",
...@@ -2714,12 +2722,12 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {...@@ -2714,12 +2722,12 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
2714 for (keys[1..], 0..) |key, i| {2722 for (keys[1..], 0..) |key, i| {
2715 const note_decl = module.declPtr(key);2723 const note_decl = module.declPtr(key);
2716 err_msg.notes[i] = .{2724 err_msg.notes[i] = .{
2717 .src_loc = note_decl.nodeOffsetSrcLoc(values[i + 1]),2725 .src_loc = note_decl.nodeOffsetSrcLoc(values[i + 1], module),
2718 .msg = "also here",2726 .msg = "also here",
2719 };2727 };
2720 }2728 }
27212729
2722 try addModuleErrorMsg(&bundle, err_msg);2730 try addModuleErrorMsg(module, &bundle, err_msg);
2723 }2731 }
2724 }2732 }
27252733
...@@ -2775,8 +2783,9 @@ pub const ErrorNoteHashContext = struct {...@@ -2775,8 +2783,9 @@ pub const ErrorNoteHashContext = struct {
2775 }2783 }
2776};2784};
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 {
2779 const gpa = eb.gpa;2787 const gpa = eb.gpa;
2788 const ip = &mod.intern_pool;
2780 const err_source = module_err_msg.src_loc.file_scope.getSource(gpa) catch |err| {2789 const err_source = module_err_msg.src_loc.file_scope.getSource(gpa) catch |err| {
2781 const file_path = try module_err_msg.src_loc.file_scope.fullPath(gpa);2790 const file_path = try module_err_msg.src_loc.file_scope.fullPath(gpa);
2782 defer gpa.free(file_path);2791 defer gpa.free(file_path);
...@@ -2802,7 +2811,7 @@ pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg)...@@ -2802,7 +2811,7 @@ pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg)
2802 .src_loc = .none,2811 .src_loc = .none,
2803 });2812 });
2804 break;2813 break;
2805 } else if (module_reference.decl == null) {2814 } else if (module_reference.decl == .none) {
2806 try ref_traces.append(gpa, .{2815 try ref_traces.append(gpa, .{
2807 .decl_name = 0,2816 .decl_name = 0,
2808 .src_loc = .none,2817 .src_loc = .none,
...@@ -2815,7 +2824,7 @@ pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg)...@@ -2815,7 +2824,7 @@ pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg)
2815 const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa);2824 const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa);
2816 defer gpa.free(rt_file_path);2825 defer gpa.free(rt_file_path);
2817 try ref_traces.append(gpa, .{2826 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).?),
2819 .src_loc = try eb.addSourceLocation(.{2828 .src_loc = try eb.addSourceLocation(.{
2820 .src_path = try eb.addString(rt_file_path),2829 .src_path = try eb.addString(rt_file_path),
2821 .span_start = span.start,2830 .span_start = span.start,
...@@ -3204,7 +3213,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3204,7 +3213,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
3204 // Tests are always emitted in test binaries. The decl_refs are created by3213 // Tests are always emitted in test binaries. The decl_refs are created by
3205 // Module.populateTestFunctions, but this will not queue body analysis, so do3214 // Module.populateTestFunctions, but this will not queue body analysis, so do
3206 // that now.3215 // 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);
3208 }3218 }
3209 },3219 },
3210 .update_embed_file => |embed_file| {3220 .update_embed_file => |embed_file| {
...@@ -3228,7 +3238,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3228,7 +3238,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
3228 try module.failed_decls.ensureUnusedCapacity(gpa, 1);3238 try module.failed_decls.ensureUnusedCapacity(gpa, 1);
3229 module.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(3239 module.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
3230 gpa,3240 gpa,
3231 decl.srcLoc(),3241 decl.srcLoc(module),
3232 "unable to update line number: {s}",3242 "unable to update line number: {s}",
3233 .{@errorName(err)},3243 .{@errorName(err)},
3234 ));3244 ));
...@@ -3841,7 +3851,7 @@ fn reportRetryableEmbedFileError(...@@ -3841,7 +3851,7 @@ fn reportRetryableEmbedFileError(
3841 const mod = comp.bin_file.options.module.?;3851 const mod = comp.bin_file.options.module.?;
3842 const gpa = mod.gpa;3852 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
3846 const err_msg = if (embed_file.pkg.root_src_directory.path) |dir_path|3856 const err_msg = if (embed_file.pkg.root_src_directory.path) |dir_path|
3847 try Module.ErrorMsg.create(3857 try Module.ErrorMsg.create(
...@@ -5417,6 +5427,7 @@ fn buildOutputFromZig(...@@ -5417,6 +5427,7 @@ fn buildOutputFromZig(
5417 .verbose_cc = comp.verbose_cc,5427 .verbose_cc = comp.verbose_cc,
5418 .verbose_link = comp.bin_file.options.verbose_link,5428 .verbose_link = comp.bin_file.options.verbose_link,
5419 .verbose_air = comp.verbose_air,5429 .verbose_air = comp.verbose_air,
5430 .verbose_intern_pool = comp.verbose_intern_pool,
5420 .verbose_llvm_ir = comp.verbose_llvm_ir,5431 .verbose_llvm_ir = comp.verbose_llvm_ir,
5421 .verbose_llvm_bc = comp.verbose_llvm_bc,5432 .verbose_llvm_bc = comp.verbose_llvm_bc,
5422 .verbose_cimport = comp.verbose_cimport,5433 .verbose_cimport = comp.verbose_cimport,
...@@ -5495,6 +5506,7 @@ pub fn build_crt_file(...@@ -5495,6 +5506,7 @@ pub fn build_crt_file(
5495 .verbose_cc = comp.verbose_cc,5506 .verbose_cc = comp.verbose_cc,
5496 .verbose_link = comp.bin_file.options.verbose_link,5507 .verbose_link = comp.bin_file.options.verbose_link,
5497 .verbose_air = comp.verbose_air,5508 .verbose_air = comp.verbose_air,
5509 .verbose_intern_pool = comp.verbose_intern_pool,
5498 .verbose_llvm_ir = comp.verbose_llvm_ir,5510 .verbose_llvm_ir = comp.verbose_llvm_ir,
5499 .verbose_llvm_bc = comp.verbose_llvm_bc,5511 .verbose_llvm_bc = comp.verbose_llvm_bc,
5500 .verbose_cimport = comp.verbose_cimport,5512 .verbose_cimport = comp.verbose_cimport,
src/InternPool.zig+5742-266
...@@ -1,316 +1,5792 @@...@@ -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.
1map: std.AutoArrayHashMapUnmanaged(void, void) = .{},8map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
2items: std.MultiArrayList(Item) = .{},9items: std.MultiArrayList(Item) = .{},
3extra: std.ArrayListUnmanaged(u32) = .{},10extra: 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");
6const std = @import("std");66const std = @import("std");
7const Allocator = std.mem.Allocator;67const Allocator = std.mem.Allocator;
8const assert = std.debug.assert;68const 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
10const KeyAdapter = struct {78const KeyAdapter = struct {
11 intern_pool: *const InternPool,79 intern_pool: *const InternPool,
1280
13 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {81 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
14 _ = b_void;82 _ = 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);
16 }84 }
1785
18 pub fn hash(ctx: @This(), a: Key) u32 {86 pub fn hash(ctx: @This(), a: Key) u32 {
19 _ = ctx;87 return a.hash32(ctx.intern_pool);
20 return a.hash();
21 }88 }
22};89};
2390
24pub const Key = union(enum) {91/// An index into `maps` which might be `none`.
25 int_type: struct {92pub const OptionalMapIndex = enum(u32) {
26 signedness: std.builtin.Signedness,93 none = std.math.maxInt(u32),
27 bits: u16,94 _,
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,
5695
57 pub fn hash(key: Key) u32 {96 pub fn unwrap(oi: OptionalMapIndex) ?MapIndex {
58 var hasher = std.hash.Wyhash.init(0);97 if (oi == .none) return null;
59 switch (key) {98 return @intToEnum(MapIndex, @enumToInt(oi));
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());
69 }99 }
100};
70101
71 pub fn eql(a: Key, b: Key) bool {102/// An index into `maps`.
72 const KeyTag = std.meta.Tag(Key);103pub const MapIndex = enum(u32) {
73 const a_tag: KeyTag = a;104 _,
74 const b_tag: KeyTag = b;105
75 if (a_tag != b_tag) return false;106 pub fn toOptional(i: MapIndex) OptionalMapIndex {
76 switch (a) {107 return @intToEnum(OptionalMapIndex, @enumToInt(i));
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 }
87 }108 }
88};109};
89110
90pub const Item = struct {111pub const RuntimeIndex = enum(u32) {
91 tag: Tag,112 zero = 0,
92 /// The doc comments on the respective Tag explain how to interpret this.113 comptime_field_ptr = std.math.maxInt(u32),
93 data: u32,114 _,
115
116 pub fn increment(ri: *RuntimeIndex) void {
117 ri.* = @intToEnum(RuntimeIndex, @enumToInt(ri.*) + 1);
118 }
94};119};
95120
96/// Represents an index into `map`. It represents the canonical index121/// An index into `string_bytes`.
97/// of a `Value` within this `InternPool`. The values are typed.122pub const String = enum(u32) {
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),
103 _,123 _,
104};124};
105125
106pub const Tag = enum(u8) {126/// An index into `string_bytes`.
107 /// An integer type.127pub const NullTerminatedString = enum(u32) {
108 /// data is number of bits128 /// This is distinct from `none` - it is a valid index that represents empty string.
109 type_int_signed,129 empty = 0,
110 /// An integer type.130 _,
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};
141131
142pub const Simple = enum(u32) {132 pub fn toString(self: NullTerminatedString) String {
143 f16,133 return @intToEnum(String, @enumToInt(self));
144 f32,134 }
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};
177135
178pub const Array = struct {136 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {
179 len: u32,137 return @intToEnum(OptionalNullTerminatedString, @enumToInt(self));
180 child: Index,138 }
181};
182139
183pub fn deinit(ip: *InternPool, gpa: Allocator) void {140 const Adapter = struct {
184 ip.map.deinit(gpa);141 strings: []const NullTerminatedString,
185 ip.items.deinit(gpa);
186 ip.extra.deinit(gpa);
187}
188142
189pub fn indexToKey(ip: InternPool, index: Index) Key {143 pub fn eql(ctx: @This(), a: NullTerminatedString, b_void: void, b_map_index: usize) bool {
190 const item = ip.items.get(@enumToInt(index));144 _ = b_void;
191 const data = item.data;145 return a == ctx.strings[b_map_index];
192 return switch (item.tag) {146 }
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) },
214147
215 else => @panic("TODO"),148 pub fn hash(ctx: @This(), a: NullTerminatedString) u32 {
149 _ = ctx;
150 return std.hash.uint32(@enumToInt(a));
151 }
216 };152 };
217}
218153
219pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {154 /// Compare based on integer value alone, ignoring the string contents.
220 const adapter: KeyAdapter = .{ .intern_pool = ip };155 pub fn indexLessThan(ctx: void, a: NullTerminatedString, b: NullTerminatedString) bool {
221 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);156 _ = ctx;
222 if (gop.found_existing) {157 return @enumToInt(a) < @enumToInt(b);
223 return @intToEnum(Index, gop.index);
224 }158 }
225 switch (key) {159
226 .int_type => |int_type| {160 pub fn toUnsigned(self: NullTerminatedString, ip: *const InternPool) ?u32 {
227 const tag: Tag = switch (int_type.signedness) {161 const s = ip.stringToSlice(self);
228 .signed => .type_int_signed,162 if (s.len > 1 and s[0] == '0') return null;
229 .unsigned => .type_int_unsigned,163 if (std.mem.indexOfScalar(u8, s, '_')) |_| return null;
230 };164 return std.fmt.parseUnsigned(u32, s, 10) catch null;
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"),
248 }165 }
249 return @intToEnum(Index, ip.items.len - 1);
250}
251166
252fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 {167 const FormatData = struct {
253 const fields = std.meta.fields(@TypeOf(extra));168 string: NullTerminatedString,
254 try ip.extra.ensureUnusedCapacity(gpa, fields.len);169 ip: *const InternPool,
255 return ip.addExtraAssumeCapacity(extra);170 };
256}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 {185 pub fn fmt(self: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(format) {
259 const fields = std.meta.fields(@TypeOf(extra));186 return .{ .data = .{ .string = self, .ip = ip } };
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 });
268 }187 }
269 return result;188};
270}
271189
272fn extraData(ip: InternPool, comptime T: type, index: usize) T {190/// An index into `string_bytes` which might be `none`.
273 const fields = std.meta.fields(T);191pub const OptionalNullTerminatedString = enum(u32) {
274 var i: usize = index;192 /// This is distinct from `none` - it is a valid index that represents empty string.
275 var result: T = undefined;193 empty = 0,
276 inline for (fields) |field| {194 none = std.math.maxInt(u32),
277 @field(result, field.name) = switch (field.type) {195 _,
278 u32 => ip.extra.items[i],196
279 Index => @intToEnum(Index, ip.extra.items[i]),197 pub fn unwrap(oi: OptionalNullTerminatedString) ?NullTerminatedString {
280 i32 => @bitCast(i32, ip.extra.items[i]),198 if (oi == .none) return null;
281 else => @compileError("bad field type"),199 return @intToEnum(NullTerminatedString, @enumToInt(oi));
282 };
283 i += 1;
284 }200 }
285 return result;201};
286}
287202
288test "basic usage" {203pub const Key = union(enum) {
289 const gpa = std.testing.allocator;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 = .{};229 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
292 defer ip.deinit(gpa);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 = .{258 /// A comptime function call with a memoized result.
295 .signedness = .signed,259 memoized_call: Key.MemoizedCall,
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 } });
303260
304 const another_i32_type = try ip.get(gpa, .{ .int_type = .{261 pub const TypeValue = extern struct {
305 .signedness = .signed,262 ty: Index,
306 .bits = 32,263 val: Index,
307 } });264 };
308 try std.testing.expect(another_i32_type == i32_type);
309265
310 const another_array_i32 = try ip.get(gpa, .{ .array_type = .{266 pub const IntType = std.builtin.Type.Int;
311 .len = 10,267
312 .child = i32_type,268 /// Extern for hashing via memory reinterpretation.
313 .sentinel = .none,269 pub const ErrorUnionType = extern struct {
314 } });270 error_set_type: Index,
315 try std.testing.expect(another_array_i32 == array_i32);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 };
316}5792}
src/Liveness.zig+27-29
...@@ -5,15 +5,17 @@...@@ -5,15 +5,17 @@
5//! Some instructions are special, such as:5//! Some instructions are special, such as:
6//! * Conditional Branches6//! * Conditional Branches
7//! * Switch Branches7//! * Switch Branches
8const Liveness = @This();
9const std = @import("std");8const std = @import("std");
10const trace = @import("tracy.zig").trace;
11const log = std.log.scoped(.liveness);9const log = std.log.scoped(.liveness);
12const assert = std.debug.assert;10const assert = std.debug.assert;
13const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
14const Air = @import("Air.zig");
15const Log2Int = std.math.Log2Int;12const 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
17pub const Verify = @import("Liveness/Verify.zig");19pub const Verify = @import("Liveness/Verify.zig");
1820
19/// This array is split into sets of 4 bits per AIR instruction.21/// This array is split into sets of 4 bits per AIR instruction.
...@@ -129,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type {...@@ -129,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type {
129 };131 };
130}132}
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 {
133 const tracy = trace(@src());135 const tracy = trace(@src());
134 defer tracy.end();136 defer tracy.end();
135137
...@@ -142,6 +144,7 @@ pub fn analyze(gpa: Allocator, air: Air) Allocator.Error!Liveness {...@@ -142,6 +144,7 @@ pub fn analyze(gpa: Allocator, air: Air) Allocator.Error!Liveness {
142 ),144 ),
143 .extra = .{},145 .extra = .{},
144 .special = .{},146 .special = .{},
147 .intern_pool = intern_pool,
145 };148 };
146 errdefer gpa.free(a.tomb_bits);149 errdefer gpa.free(a.tomb_bits);
147 errdefer a.special.deinit(gpa);150 errdefer a.special.deinit(gpa);
...@@ -222,6 +225,7 @@ pub fn categorizeOperand(...@@ -222,6 +225,7 @@ pub fn categorizeOperand(
222 air: Air,225 air: Air,
223 inst: Air.Inst.Index,226 inst: Air.Inst.Index,
224 operand: Air.Inst.Index,227 operand: Air.Inst.Index,
228 ip: *const InternPool,
225) OperandCategory {229) OperandCategory {
226 const air_tags = air.instructions.items(.tag);230 const air_tags = air.instructions.items(.tag);
227 const air_datas = air.instructions.items(.data);231 const air_datas = air.instructions.items(.data);
...@@ -317,9 +321,10 @@ pub fn categorizeOperand(...@@ -317,9 +321,10 @@ pub fn categorizeOperand(
317321
318 .arg,322 .arg,
319 .alloc,323 .alloc,
324 .inferred_alloc,
325 .inferred_alloc_comptime,
320 .ret_ptr,326 .ret_ptr,
321 .constant,327 .interned,
322 .const_ty,
323 .trap,328 .trap,
324 .breakpoint,329 .breakpoint,
325 .dbg_stmt,330 .dbg_stmt,
...@@ -530,7 +535,7 @@ pub fn categorizeOperand(...@@ -530,7 +535,7 @@ pub fn categorizeOperand(
530 .aggregate_init => {535 .aggregate_init => {
531 const ty_pl = air_datas[inst].ty_pl;536 const ty_pl = air_datas[inst].ty_pl;
532 const aggregate_ty = air.getRefType(ty_pl.ty);537 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));
534 const elements = @ptrCast([]const Air.Inst.Ref, air.extra[ty_pl.payload..][0..len]);539 const elements = @ptrCast([]const Air.Inst.Ref, air.extra[ty_pl.payload..][0..len]);
535540
536 if (elements.len <= bpi - 1) {541 if (elements.len <= bpi - 1) {
...@@ -621,7 +626,7 @@ pub fn categorizeOperand(...@@ -621,7 +626,7 @@ pub fn categorizeOperand(
621626
622 var operand_live: bool = true;627 var operand_live: bool = true;
623 for (air.extra[cond_extra.end..][0..2]) |cond_inst| {628 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)
625 operand_live = false;630 operand_live = false;
626631
627 switch (air_tags[cond_inst]) {632 switch (air_tags[cond_inst]) {
...@@ -818,6 +823,7 @@ pub const BigTomb = struct {...@@ -818,6 +823,7 @@ pub const BigTomb = struct {
818const Analysis = struct {823const Analysis = struct {
819 gpa: Allocator,824 gpa: Allocator,
820 air: Air,825 air: Air,
826 intern_pool: *const InternPool,
821 tomb_bits: []usize,827 tomb_bits: []usize,
822 special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),828 special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),
823 extra: std.ArrayListUnmanaged(u32),829 extra: std.ArrayListUnmanaged(u32),
...@@ -867,6 +873,7 @@ fn analyzeInst(...@@ -867,6 +873,7 @@ fn analyzeInst(
867 data: *LivenessPassData(pass),873 data: *LivenessPassData(pass),
868 inst: Air.Inst.Index,874 inst: Air.Inst.Index,
869) Allocator.Error!void {875) Allocator.Error!void {
876 const ip = a.intern_pool;
870 const inst_tags = a.air.instructions.items(.tag);877 const inst_tags = a.air.instructions.items(.tag);
871 const inst_datas = a.air.instructions.items(.data);878 const inst_datas = a.air.instructions.items(.data);
872879
...@@ -967,9 +974,7 @@ fn analyzeInst(...@@ -967,9 +974,7 @@ fn analyzeInst(
967 .work_group_id,974 .work_group_id,
968 => return analyzeOperands(a, pass, data, inst, .{ .none, .none, .none }),975 => return analyzeOperands(a, pass, data, inst, .{ .none, .none, .none }),
969976
970 .constant,977 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
971 .const_ty,
972 => unreachable,
973978
974 .trap,979 .trap,
975 .unreach,980 .unreach,
...@@ -1134,7 +1139,7 @@ fn analyzeInst(...@@ -1134,7 +1139,7 @@ fn analyzeInst(
1134 .aggregate_init => {1139 .aggregate_init => {
1135 const ty_pl = inst_datas[inst].ty_pl;1140 const ty_pl = inst_datas[inst].ty_pl;
1136 const aggregate_ty = a.air.getRefType(ty_pl.ty);1141 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));
1138 const elements = @ptrCast([]const Air.Inst.Ref, a.air.extra[ty_pl.payload..][0..len]);1143 const elements = @ptrCast([]const Air.Inst.Ref, a.air.extra[ty_pl.payload..][0..len]);
11391144
1140 if (elements.len <= bpi - 1) {1145 if (elements.len <= bpi - 1) {
...@@ -1253,19 +1258,17 @@ fn analyzeOperands(...@@ -1253,19 +1258,17 @@ fn analyzeOperands(
1253) Allocator.Error!void {1258) Allocator.Error!void {
1254 const gpa = a.gpa;1259 const gpa = a.gpa;
1255 const inst_tags = a.air.instructions.items(.tag);1260 const inst_tags = a.air.instructions.items(.tag);
1261 const ip = a.intern_pool;
12561262
1257 switch (pass) {1263 switch (pass) {
1258 .loop_analysis => {1264 .loop_analysis => {
1259 _ = data.live_set.remove(inst);1265 _ = data.live_set.remove(inst);
12601266
1261 for (operands) |op_ref| {1267 for (operands) |op_ref| {
1262 const operand = Air.refToIndex(op_ref) orelse continue;1268 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
12631269
1264 // Don't compute any liveness for constants1270 // Don't compute any liveness for constants
1265 switch (inst_tags[operand]) {1271 if (inst_tags[operand] == .interned) continue;
1266 .constant, .const_ty => continue,
1267 else => {},
1268 }
12691272
1270 _ = try data.live_set.put(gpa, operand, {});1273 _ = try data.live_set.put(gpa, operand, {});
1271 }1274 }
...@@ -1288,20 +1291,17 @@ fn analyzeOperands(...@@ -1288,20 +1291,17 @@ fn analyzeOperands(
1288 // If our result is unused and the instruction doesn't need to be lowered, backends will1291 // If our result is unused and the instruction doesn't need to be lowered, backends will
1289 // skip the lowering of this instruction, so we don't want to record uses of operands.1292 // skip the lowering of this instruction, so we don't want to record uses of operands.
1290 // That way, we can mark as many instructions as possible unused.1293 // 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)) {
1292 // Note that it's important we iterate over the operands backwards, so that if a dying1295 // Note that it's important we iterate over the operands backwards, so that if a dying
1293 // operand is used multiple times we mark its last use as its death.1296 // operand is used multiple times we mark its last use as its death.
1294 var i = operands.len;1297 var i = operands.len;
1295 while (i > 0) {1298 while (i > 0) {
1296 i -= 1;1299 i -= 1;
1297 const op_ref = operands[i];1300 const op_ref = operands[i];
1298 const operand = Air.refToIndex(op_ref) orelse continue;1301 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
12991302
1300 // Don't compute any liveness for constants1303 // Don't compute any liveness for constants
1301 switch (inst_tags[operand]) {1304 if (inst_tags[operand] == .interned) continue;
1302 .constant, .const_ty => continue,
1303 else => {},
1304 }
13051305
1306 const mask = @as(Bpi, 1) << @intCast(OperandInt, i);1306 const mask = @as(Bpi, 1) << @intCast(OperandInt, i);
13071307
...@@ -1407,7 +1407,7 @@ fn analyzeInstBlock(...@@ -1407,7 +1407,7 @@ fn analyzeInstBlock(
14071407
1408 // If the block is noreturn, block deaths not only aren't useful, they're impossible to1408 // If the block is noreturn, block deaths not only aren't useful, they're impossible to
1409 // find: there could be more stuff alive after the block than before it!1409 // 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)) {
1411 // The block kills the difference in the live sets1411 // The block kills the difference in the live sets
1412 const block_scope = data.block_scopes.get(inst).?;1412 const block_scope = data.block_scopes.get(inst).?;
1413 const num_deaths = data.live_set.count() - block_scope.live_set.count();1413 const num_deaths = data.live_set.count() - block_scope.live_set.count();
...@@ -1819,6 +1819,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -1819,6 +1819,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
18191819
1820 /// Must be called with operands in reverse order.1820 /// Must be called with operands in reverse order.
1821 fn feed(big: *Self, op_ref: Air.Inst.Ref) !void {1821 fn feed(big: *Self, op_ref: Air.Inst.Ref) !void {
1822 const ip = big.a.intern_pool;
1822 // Note that after this, `operands_remaining` becomes the index of the current operand1823 // Note that after this, `operands_remaining` becomes the index of the current operand
1823 big.operands_remaining -= 1;1824 big.operands_remaining -= 1;
18241825
...@@ -1831,15 +1832,12 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -1831,15 +1832,12 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
18311832
1832 // Don't compute any liveness for constants1833 // Don't compute any liveness for constants
1833 const inst_tags = big.a.air.instructions.items(.tag);1834 const inst_tags = big.a.air.instructions.items(.tag);
1834 switch (inst_tags[operand]) {1835 if (inst_tags[operand] == .interned) return
1835 .constant, .const_ty => return,
1836 else => {},
1837 }
18381836
1839 // If our result is unused and the instruction doesn't need to be lowered, backends will1837 // If our result is unused and the instruction doesn't need to be lowered, backends will
1840 // skip the lowering of this instruction, so we don't want to record uses of operands.1838 // skip the lowering of this instruction, so we don't want to record uses of operands.
1841 // That way, we can mark as many instructions as possible unused.1839 // 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
1844 const extra_byte = (big.operands_remaining - (bpi - 1)) / 31;1842 const extra_byte = (big.operands_remaining - (bpi - 1)) / 31;
1845 const extra_bit = @intCast(u5, big.operands_remaining - (bpi - 1) - extra_byte * 31);1843 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,...@@ -5,6 +5,7 @@ air: Air,
5liveness: Liveness,5liveness: Liveness,
6live: LiveMap = .{},6live: LiveMap = .{},
7blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, LiveMap) = .{},7blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, LiveMap) = .{},
8intern_pool: *const InternPool,
89
9pub const Error = error{ LivenessInvalid, OutOfMemory };10pub const Error = error{ LivenessInvalid, OutOfMemory };
1011
...@@ -27,10 +28,11 @@ pub fn verify(self: *Verify) Error!void {...@@ -27,10 +28,11 @@ pub fn verify(self: *Verify) Error!void {
27const LiveMap = std.AutoHashMapUnmanaged(Air.Inst.Index, void);28const LiveMap = std.AutoHashMapUnmanaged(Air.Inst.Index, void);
2829
29fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {30fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
31 const ip = self.intern_pool;
30 const tag = self.air.instructions.items(.tag);32 const tag = self.air.instructions.items(.tag);
31 const data = self.air.instructions.items(.data);33 const data = self.air.instructions.items(.data);
32 for (body) |inst| {34 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)) {
34 // This instruction will not be lowered and should be ignored.36 // This instruction will not be lowered and should be ignored.
35 continue;37 continue;
36 }38 }
...@@ -39,9 +41,10 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -39,9 +41,10 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
39 // no operands41 // no operands
40 .arg,42 .arg,
41 .alloc,43 .alloc,
44 .inferred_alloc,
45 .inferred_alloc_comptime,
42 .ret_ptr,46 .ret_ptr,
43 .constant,47 .interned,
44 .const_ty,
45 .breakpoint,48 .breakpoint,
46 .dbg_stmt,49 .dbg_stmt,
47 .dbg_inline_begin,50 .dbg_inline_begin,
...@@ -58,10 +61,10 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -58,10 +61,10 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
58 .work_item_id,61 .work_item_id,
59 .work_group_size,62 .work_group_size,
60 .work_group_id,63 .work_group_id,
61 => try self.verifyInst(inst, .{ .none, .none, .none }),64 => try self.verifyInstOperands(inst, .{ .none, .none, .none }),
6265
63 .trap, .unreach => {66 .trap, .unreach => {
64 try self.verifyInst(inst, .{ .none, .none, .none });67 try self.verifyInstOperands(inst, .{ .none, .none, .none });
65 // This instruction terminates the function, so everything should be dead68 // This instruction terminates the function, so everything should be dead
66 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});69 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});
67 },70 },
...@@ -110,7 +113,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -110,7 +113,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
110 .c_va_copy,113 .c_va_copy,
111 => {114 => {
112 const ty_op = data[inst].ty_op;115 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 });
114 },117 },
115 .is_null,118 .is_null,
116 .is_non_null,119 .is_non_null,
...@@ -146,13 +149,13 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -146,13 +149,13 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
146 .c_va_end,149 .c_va_end,
147 => {150 => {
148 const un_op = data[inst].un_op;151 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 });
150 },153 },
151 .ret,154 .ret,
152 .ret_load,155 .ret_load,
153 => {156 => {
154 const un_op = data[inst].un_op;157 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 });
156 // This instruction terminates the function, so everything should be dead159 // This instruction terminates the function, so everything should be dead
157 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});160 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});
158 },161 },
...@@ -161,36 +164,36 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -161,36 +164,36 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
161 .wasm_memory_grow,164 .wasm_memory_grow,
162 => {165 => {
163 const pl_op = data[inst].pl_op;166 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 });
165 },168 },
166 .prefetch => {169 .prefetch => {
167 const prefetch = data[inst].prefetch;170 const prefetch = data[inst].prefetch;
168 try self.verifyInst(inst, .{ prefetch.ptr, .none, .none });171 try self.verifyInstOperands(inst, .{ prefetch.ptr, .none, .none });
169 },172 },
170 .reduce,173 .reduce,
171 .reduce_optimized,174 .reduce_optimized,
172 => {175 => {
173 const reduce = data[inst].reduce;176 const reduce = data[inst].reduce;
174 try self.verifyInst(inst, .{ reduce.operand, .none, .none });177 try self.verifyInstOperands(inst, .{ reduce.operand, .none, .none });
175 },178 },
176 .union_init => {179 .union_init => {
177 const ty_pl = data[inst].ty_pl;180 const ty_pl = data[inst].ty_pl;
178 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;181 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 });
180 },183 },
181 .struct_field_ptr, .struct_field_val => {184 .struct_field_ptr, .struct_field_val => {
182 const ty_pl = data[inst].ty_pl;185 const ty_pl = data[inst].ty_pl;
183 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;186 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 });
185 },188 },
186 .field_parent_ptr => {189 .field_parent_ptr => {
187 const ty_pl = data[inst].ty_pl;190 const ty_pl = data[inst].ty_pl;
188 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;191 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 });
190 },193 },
191 .atomic_load => {194 .atomic_load => {
192 const atomic_load = data[inst].atomic_load;195 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 });
194 },197 },
195198
196 // binary199 // binary
...@@ -260,7 +263,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -260,7 +263,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
260 .memcpy,263 .memcpy,
261 => {264 => {
262 const bin_op = data[inst].bin_op;265 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 });
264 },267 },
265 .add_with_overflow,268 .add_with_overflow,
266 .sub_with_overflow,269 .sub_with_overflow,
...@@ -274,62 +277,62 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -274,62 +277,62 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
274 => {277 => {
275 const ty_pl = data[inst].ty_pl;278 const ty_pl = data[inst].ty_pl;
276 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;279 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 });
278 },281 },
279 .shuffle => {282 .shuffle => {
280 const ty_pl = data[inst].ty_pl;283 const ty_pl = data[inst].ty_pl;
281 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;284 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 });
283 },286 },
284 .cmp_vector,287 .cmp_vector,
285 .cmp_vector_optimized,288 .cmp_vector_optimized,
286 => {289 => {
287 const ty_pl = data[inst].ty_pl;290 const ty_pl = data[inst].ty_pl;
288 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;291 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 });
290 },293 },
291 .atomic_rmw => {294 .atomic_rmw => {
292 const pl_op = data[inst].pl_op;295 const pl_op = data[inst].pl_op;
293 const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data;296 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 });
295 },298 },
296299
297 // ternary300 // ternary
298 .select => {301 .select => {
299 const pl_op = data[inst].pl_op;302 const pl_op = data[inst].pl_op;
300 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;303 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 });
302 },305 },
303 .mul_add => {306 .mul_add => {
304 const pl_op = data[inst].pl_op;307 const pl_op = data[inst].pl_op;
305 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;308 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 });
307 },310 },
308 .vector_store_elem => {311 .vector_store_elem => {
309 const vector_store_elem = data[inst].vector_store_elem;312 const vector_store_elem = data[inst].vector_store_elem;
310 const extra = self.air.extraData(Air.Bin, vector_store_elem.payload).data;313 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 });
312 },315 },
313 .cmpxchg_strong,316 .cmpxchg_strong,
314 .cmpxchg_weak,317 .cmpxchg_weak,
315 => {318 => {
316 const ty_pl = data[inst].ty_pl;319 const ty_pl = data[inst].ty_pl;
317 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;320 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 });
319 },322 },
320323
321 // big tombs324 // big tombs
322 .aggregate_init => {325 .aggregate_init => {
323 const ty_pl = data[inst].ty_pl;326 const ty_pl = data[inst].ty_pl;
324 const aggregate_ty = self.air.getRefType(ty_pl.ty);327 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));
326 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);329 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
327330
328 var bt = self.liveness.iterateBigTomb(inst);331 var bt = self.liveness.iterateBigTomb(inst);
329 for (elements) |element| {332 for (elements) |element| {
330 try self.verifyOperand(inst, element, bt.feed());333 try self.verifyOperand(inst, element, bt.feed());
331 }334 }
332 try self.verifyInst(inst, .{ .none, .none, .none });335 try self.verifyInst(inst);
333 },336 },
334 .call, .call_always_tail, .call_never_tail, .call_never_inline => {337 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
335 const pl_op = data[inst].pl_op;338 const pl_op = data[inst].pl_op;
...@@ -344,7 +347,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -344,7 +347,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
344 for (args) |arg| {347 for (args) |arg| {
345 try self.verifyOperand(inst, arg, bt.feed());348 try self.verifyOperand(inst, arg, bt.feed());
346 }349 }
347 try self.verifyInst(inst, .{ .none, .none, .none });350 try self.verifyInst(inst);
348 },351 },
349 .assembly => {352 .assembly => {
350 const ty_pl = data[inst].ty_pl;353 const ty_pl = data[inst].ty_pl;
...@@ -370,7 +373,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -370,7 +373,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
370 for (inputs) |input| {373 for (inputs) |input| {
371 try self.verifyOperand(inst, input, bt.feed());374 try self.verifyOperand(inst, input, bt.feed());
372 }375 }
373 try self.verifyInst(inst, .{ .none, .none, .none });376 try self.verifyInst(inst);
374 },377 },
375378
376 // control flow379 // control flow
...@@ -394,7 +397,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -394,7 +397,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
394397
395 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);398 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);
398 },401 },
399 .try_ptr => {402 .try_ptr => {
400 const ty_pl = data[inst].ty_pl;403 const ty_pl = data[inst].ty_pl;
...@@ -416,7 +419,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -416,7 +419,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
416419
417 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);420 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);
420 },423 },
421 .br => {424 .br => {
422 const br = data[inst].br;425 const br = data[inst].br;
...@@ -428,7 +431,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -428,7 +431,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
428 } else {431 } else {
429 gop.value_ptr.* = try self.live.clone(self.gpa);432 gop.value_ptr.* = try self.live.clone(self.gpa);
430 }433 }
431 try self.verifyInst(inst, .{ .none, .none, .none });434 try self.verifyInst(inst);
432 },435 },
433 .block => {436 .block => {
434 const ty_pl = data[inst].ty_pl;437 const ty_pl = data[inst].ty_pl;
...@@ -450,7 +453,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -450,7 +453,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
450453
451 for (block_liveness.deaths) |death| try self.verifyDeath(inst, death);454 for (block_liveness.deaths) |death| try self.verifyDeath(inst, death);
452455
453 if (block_ty.isNoReturn()) {456 if (ip.isNoReturn(block_ty.toIntern())) {
454 assert(!self.blocks.contains(inst));457 assert(!self.blocks.contains(inst));
455 } else {458 } else {
456 var live = self.blocks.fetchRemove(inst).?.value;459 var live = self.blocks.fetchRemove(inst).?.value;
...@@ -459,7 +462,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -459,7 +462,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
459 try self.verifyMatchingLiveness(inst, live);462 try self.verifyMatchingLiveness(inst, live);
460 }463 }
461464
462 try self.verifyInst(inst, .{ .none, .none, .none });465 try self.verifyInstOperands(inst, .{ .none, .none, .none });
463 },466 },
464 .loop => {467 .loop => {
465 const ty_pl = data[inst].ty_pl;468 const ty_pl = data[inst].ty_pl;
...@@ -474,7 +477,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -474,7 +477,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
474 // The same stuff should be alive after the loop as before it477 // The same stuff should be alive after the loop as before it
475 try self.verifyMatchingLiveness(inst, live);478 try self.verifyMatchingLiveness(inst, live);
476479
477 try self.verifyInst(inst, .{ .none, .none, .none });480 try self.verifyInstOperands(inst, .{ .none, .none, .none });
478 },481 },
479 .cond_br => {482 .cond_br => {
480 const pl_op = data[inst].pl_op;483 const pl_op = data[inst].pl_op;
...@@ -497,7 +500,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -497,7 +500,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
497 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);500 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);
498 try self.verifyBody(else_body);501 try self.verifyBody(else_body);
499502
500 try self.verifyInst(inst, .{ .none, .none, .none });503 try self.verifyInst(inst);
501 },504 },
502 .switch_br => {505 .switch_br => {
503 const pl_op = data[inst].pl_op;506 const pl_op = data[inst].pl_op;
...@@ -541,7 +544,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -541,7 +544,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
541 try self.verifyBody(else_body);544 try self.verifyBody(else_body);
542 }545 }
543546
544 try self.verifyInst(inst, .{ .none, .none, .none });547 try self.verifyInst(inst);
545 },548 },
546 }549 }
547 }550 }
...@@ -552,20 +555,22 @@ fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Err...@@ -552,20 +555,22 @@ fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Err
552}555}
553556
554fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies: bool) Error!void {557fn 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;558 const operand = Air.refToIndexAllowNone(op_ref) orelse {
556 switch (self.air.instructions.items(.tag)[operand]) {559 assert(!dies);
557 .constant, .const_ty => {},560 return;
558 else => {561 };
559 if (dies) {562 if (self.air.instructions.items(.tag)[operand] == .interned) {
560 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });563 assert(!dies);
561 } else {564 return;
562 if (!self.live.contains(operand)) return invalid("%{}: dead operand %{} reused", .{ inst, operand });565 }
563 }566 if (dies) {
564 },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 });
565 }570 }
566}571}
567572
568fn verifyInst(573fn verifyInstOperands(
569 self: *Verify,574 self: *Verify,
570 inst: Air.Inst.Index,575 inst: Air.Inst.Index,
571 operands: [Liveness.bpi - 1]Air.Inst.Ref,576 operands: [Liveness.bpi - 1]Air.Inst.Ref,
...@@ -574,16 +579,15 @@ fn verifyInst(...@@ -574,16 +579,15 @@ fn verifyInst(
574 const dies = self.liveness.operandDies(inst, @intCast(Liveness.OperandInt, operand_index));579 const dies = self.liveness.operandDies(inst, @intCast(Liveness.OperandInt, operand_index));
575 try self.verifyOperand(inst, operand, dies);580 try self.verifyOperand(inst, operand, dies);
576 }581 }
577 const tag = self.air.instructions.items(.tag);582 try self.verifyInst(inst);
578 switch (tag[inst]) {583}
579 .constant, .const_ty => unreachable,584
580 else => {585fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {
581 if (self.liveness.isUnused(inst)) {586 if (self.air.instructions.items(.tag)[inst] == .interned) return;
582 assert(!self.live.contains(inst));587 if (self.liveness.isUnused(inst)) {
583 } else {588 assert(!self.live.contains(inst));
584 try self.live.putNoClobber(self.gpa, inst, {});589 } else {
585 }590 try self.live.putNoClobber(self.gpa, inst, {});
586 },
587 }591 }
588}592}
589593
...@@ -604,4 +608,5 @@ const log = std.log.scoped(.liveness_verify);...@@ -604,4 +608,5 @@ const log = std.log.scoped(.liveness_verify);
604608
605const Air = @import("../Air.zig");609const Air = @import("../Air.zig");
606const Liveness = @import("../Liveness.zig");610const Liveness = @import("../Liveness.zig");
611const InternPool = @import("../InternPool.zig");
607const Verify = @This();612const Verify = @This();
src/Module.zig+1440-1086
...@@ -32,6 +32,19 @@ const build_options = @import("build_options");...@@ -32,6 +32,19 @@ const build_options = @import("build_options");
32const Liveness = @import("Liveness.zig");32const Liveness = @import("Liveness.zig");
33const isUpDir = @import("introspect.zig").isUpDir;33const isUpDir = @import("introspect.zig").isUpDir;
34const clang = @import("clang.zig");34const 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
36/// General-purpose allocator. Used for both temporary and long-term storage.49/// General-purpose allocator. Used for both temporary and long-term storage.
37gpa: Allocator,50gpa: Allocator,
...@@ -72,28 +85,29 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{},...@@ -72,28 +85,29 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{},
72/// Keys are fully resolved file paths. This table owns the keys and values.85/// Keys are fully resolved file paths. This table owns the keys and values.
73embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},86embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},
7487
75/// This is a temporary addition to stage2 in order to match legacy behavior,88/// Stores all Type and Value objects; periodically garbage collected.
76/// however the end-game once the lang spec is settled will be to use a global89intern_pool: InternPool = .{},
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) = .{},
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) = .{},
86/// The set of all the generic function instantiations. This is used so that when a generic103/// The set of all the generic function instantiations. This is used so that when a generic
87/// function is called twice with the same comptime parameter arguments, both calls dispatch104/// function is called twice with the same comptime parameter arguments, both calls dispatch
88/// to the same function.105/// to the same function.
89monomorphed_funcs: MonomorphedFuncsSet = .{},106monomorphed_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 = .{},
93/// Contains the values from `@setAlignStack`. A sparse table is used here107/// Contains the values from `@setAlignStack`. A sparse table is used here
94/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while108/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
95/// functions are many.109/// functions are many.
96align_stack_fns: std.AutoHashMapUnmanaged(*const Fn, SetAlignStack) = .{},110align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{},
97111
98/// We optimize memory usage for a compilation with no compile errors by storing the112/// We optimize memory usage for a compilation with no compile errors by storing the
99/// error messages and mapping outside of `Decl`.113/// error messages and mapping outside of `Decl`.
...@@ -120,13 +134,8 @@ cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, []CImportError) = .{},...@@ -120,13 +134,8 @@ cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, []CImportError) = .{},
120/// contains Decls that need to be deleted if they end up having no references to them.134/// contains Decls that need to be deleted if they end up having no references to them.
121deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},135deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
122136
123/// Error tags and their values, tag names are duped with mod.gpa.137/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
124/// Corresponds with `error_name_list`.138global_error_set: GlobalErrorSet = .{},
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),
130139
131/// Incrementing integer used to compare against the corresponding Decl140/// Incrementing integer used to compare against the corresponding Decl
132/// field to determine whether a Decl's status applies to an ongoing update, or a141/// 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) = .{},...@@ -165,6 +174,11 @@ allocated_decls: std.SegmentedList(Decl, 0) = .{},
165/// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.174/// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.
166decls_free_list: ArrayListUnmanaged(Decl.Index) = .{},175decls_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
168global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},182global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},
169183
170reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {184reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
...@@ -172,6 +186,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {...@@ -172,6 +186,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
172 src: LazySrcLoc,186 src: LazySrcLoc,
173}) = .{},187}) = .{},
174188
189pub const GlobalErrorSet = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
190
175pub const CImportError = struct {191pub const CImportError = struct {
176 offset: u32,192 offset: u32,
177 line: u32,193 line: u32,
...@@ -187,108 +203,40 @@ pub const CImportError = struct {...@@ -187,108 +203,40 @@ pub const CImportError = struct {
187 }203 }
188};204};
189205
190pub const StringLiteralContext = struct {206pub const MonomorphedFuncKey = struct { func: Fn.Index, args_index: u32, args_len: u32 };
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),
211207
212 pub fn eql(self: @This(), a_slice: []const u8, b: StringLiteralContext.Key) bool {208pub const MonomorphedFuncAdaptedKey = struct { func: Fn.Index, args: []const InternPool.Index };
213 const b_slice = self.bytes.items[b.index..][0..b.len];
214 return mem.eql(u8, a_slice, b_slice);
215 }
216209
217 pub fn hash(self: @This(), adapted_key: []const u8) u64 {210pub const MonomorphedFuncsSet = std.HashMapUnmanaged(
218 _ = self;211 MonomorphedFuncKey,
219 return std.hash_map.hashString(adapted_key);212 InternPool.Index,
220 }
221};
222
223const MonomorphedFuncsSet = std.HashMapUnmanaged(
224 *Fn,
225 void,
226 MonomorphedFuncsContext,213 MonomorphedFuncsContext,
227 std.hash_map.default_max_load_percentage,214 std.hash_map.default_max_load_percentage,
228);215);
229216
230const MonomorphedFuncsContext = struct {217pub const MonomorphedFuncsContext = struct {
231 pub fn eql(ctx: @This(), a: *Fn, b: *Fn) bool {218 mod: *Module,
232 _ = ctx;219
233 return a == b;220 pub fn eql(_: @This(), a: MonomorphedFuncKey, b: MonomorphedFuncKey) bool {
221 return std.meta.eql(a, b);
234 }222 }
235223
236 /// Must match `Sema.GenericCallAdapter.hash`.224 pub fn hash(ctx: @This(), key: MonomorphedFuncKey) u64 {
237 pub fn hash(ctx: @This(), key: *Fn) u64 {225 const key_args = ctx.mod.monomorphed_func_keys.items[key.args_index..][0..key.args_len];
238 _ = ctx;226 return std.hash.Wyhash.hash(@enumToInt(key.func), std.mem.sliceAsBytes(key_args));
239 return key.hash;
240 }227 }
241};228};
242229
243pub const MemoizedCallSet = std.HashMapUnmanaged(230pub const MonomorphedFuncsAdaptedContext = struct {
244 MemoizedCall.Key,231 mod: *Module,
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 }
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);
275 }236 }
276237
277 /// Must match `Sema.GenericCallAdapter.hash`.238 pub fn hash(_: @This(), adapted_key: MonomorphedFuncAdaptedKey) u64 {
278 pub fn hash(ctx: @This(), key: Key) u64 {239 return std.hash.Wyhash.hash(@enumToInt(adapted_key.func), std.mem.sliceAsBytes(adapted_key.args));
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();
292 }240 }
293};241};
294242
...@@ -322,7 +270,7 @@ pub const GlobalEmitH = struct {...@@ -322,7 +270,7 @@ pub const GlobalEmitH = struct {
322pub const ErrorInt = u32;270pub const ErrorInt = u32;
323271
324pub const Export = struct {272pub const Export = struct {
325 options: std.builtin.ExportOptions,273 opts: Options,
326 src: LazySrcLoc,274 src: LazySrcLoc,
327 /// The Decl that performs the export. Note that this is *not* the Decl being exported.275 /// The Decl that performs the export. Note that this is *not* the Decl being exported.
328 owner_decl: Decl.Index,276 owner_decl: Decl.Index,
...@@ -340,10 +288,17 @@ pub const Export = struct {...@@ -340,10 +288,17 @@ pub const Export = struct {
340 complete,288 complete,
341 },289 },
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
343 pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc {298 pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc {
344 const src_decl = mod.declPtr(exp.src_decl);299 const src_decl = mod.declPtr(exp.src_decl);
345 return .{300 return .{
346 .file_scope = src_decl.getFileScope(),301 .file_scope = src_decl.getFileScope(mod),
347 .parent_decl_node = src_decl.src_node,302 .parent_decl_node = src_decl.src_node,
348 .lazy = exp.src,303 .lazy = exp.src,
349 };304 };
...@@ -351,61 +306,76 @@ pub const Export = struct {...@@ -351,61 +306,76 @@ pub const Export = struct {
351};306};
352307
353pub const CaptureScope = struct {308pub const CaptureScope = struct {
309 refs: u32,
354 parent: ?*CaptureScope,310 parent: ?*CaptureScope,
355311
356 /// Values from this decl's evaluation that will be closed over in312 /// 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.313 /// child decls. This map is backed by the gpa, and deinited when
358 /// During sema, this map is backed by the gpa. Once sema completes,314 /// the refcount reaches 0.
359 /// it is reallocated using the value_arena.315 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Capture) = .{},
360 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, TypedValue) = .{},
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 {
363 return self.captures.available == 0 and self.captures.size == std.math.maxInt(u32);323 return self.captures.available == 0 and self.captures.size == std.math.maxInt(u32);
364 }324 }
365325
366 pub fn fail(noalias self: *@This()) void {326 pub fn fail(noalias self: *CaptureScope, gpa: Allocator) void {
327 self.captures.deinit(gpa);
367 self.captures.available = 0;328 self.captures.available = 0;
368 self.captures.size = std.math.maxInt(u32);329 self.captures.size = std.math.maxInt(u32);
369 }330 }
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 }
370};345};
371346
372pub const WipCaptureScope = struct {347pub const WipCaptureScope = struct {
373 scope: *CaptureScope,348 scope: *CaptureScope,
374 finalized: bool,349 finalized: bool,
375 gpa: Allocator,350 gpa: Allocator,
376 perm_arena: Allocator,
377351
378 pub fn init(gpa: Allocator, perm_arena: Allocator, parent: ?*CaptureScope) !@This() {352 pub fn init(gpa: Allocator, parent: ?*CaptureScope) !WipCaptureScope {
379 const scope = try perm_arena.create(CaptureScope);353 const scope = try gpa.create(CaptureScope);
380 scope.* = .{ .parent = parent };354 if (parent) |p| p.incRef();
381 return @This(){355 scope.* = .{ .refs = 1, .parent = parent };
356 return .{
382 .scope = scope,357 .scope = scope,
383 .finalized = false,358 .finalized = false,
384 .gpa = gpa,359 .gpa = gpa,
385 .perm_arena = perm_arena,
386 };360 };
387 }361 }
388362
389 pub fn finalize(noalias self: *@This()) !void {363 pub fn finalize(noalias self: *WipCaptureScope) !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;
395 self.finalized = true;364 self.finalized = true;
396 }365 }
397366
398 pub fn reset(noalias self: *@This(), parent: ?*CaptureScope) !void {367 pub fn reset(noalias self: *WipCaptureScope, parent: ?*CaptureScope) !void {
399 if (!self.finalized) try self.finalize();368 self.scope.decRef(self.gpa);
400 self.scope = try self.perm_arena.create(CaptureScope);369 self.scope = try self.gpa.create(CaptureScope);
401 self.scope.* = .{ .parent = parent };370 if (parent) |p| p.incRef();
402 self.finalized = false;371 self.scope.* = .{ .refs = 1, .parent = parent };
403 }372 }
404373
405 pub fn deinit(noalias self: *@This()) void {374 pub fn deinit(noalias self: *WipCaptureScope) void {
406 if (!self.finalized) {375 if (self.finalized) {
407 self.scope.captures.deinit(self.gpa);376 self.scope.decRef(self.gpa);
408 self.scope.fail();377 } else {
378 self.scope.fail(self.gpa);
409 }379 }
410 self.* = undefined;380 self.* = undefined;
411 }381 }
...@@ -452,8 +422,7 @@ const ValueArena = struct {...@@ -452,8 +422,7 @@ const ValueArena = struct {
452};422};
453423
454pub const Decl = struct {424pub const Decl = struct {
455 /// Allocated with Module's allocator; outlives the ZIR code.425 name: InternPool.NullTerminatedString,
456 name: [*:0]const u8,
457 /// The most recent Type of the Decl after a successful semantic analysis.426 /// The most recent Type of the Decl after a successful semantic analysis.
458 /// Populated when `has_tv`.427 /// Populated when `has_tv`.
459 ty: Type,428 ty: Type,
...@@ -461,20 +430,16 @@ pub const Decl = struct {...@@ -461,20 +430,16 @@ pub const Decl = struct {
461 /// Populated when `has_tv`.430 /// Populated when `has_tv`.
462 val: Value,431 val: Value,
463 /// Populated when `has_tv`.432 /// Populated when `has_tv`.
464 /// Points to memory inside value_arena.433 @"linksection": InternPool.OptionalNullTerminatedString,
465 @"linksection": ?[*:0]const u8,
466 /// Populated when `has_tv`.434 /// Populated when `has_tv`.
467 @"align": u32,435 @"align": u32,
468 /// Populated when `has_tv`.436 /// Populated when `has_tv`.
469 @"addrspace": std.builtin.AddressSpace,437 @"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,
473 /// The direct parent namespace of the Decl.438 /// The direct parent namespace of the Decl.
474 /// Reference to externally owned memory.439 /// Reference to externally owned memory.
475 /// In the case of the Decl corresponding to a file, this is440 /// In the case of the Decl corresponding to a file, this is
476 /// the namespace of the struct, since there is no parent.441 /// the namespace of the struct, since there is no parent.
477 src_namespace: *Namespace,442 src_namespace: Namespace.Index,
478443
479 /// The scope which lexically contains this decl. A decl must depend444 /// The scope which lexically contains this decl. A decl must depend
480 /// on its lexical parent, in order to ensure that this pointer is valid.445 /// on its lexical parent, in order to ensure that this pointer is valid.
...@@ -624,55 +589,17 @@ pub const Decl = struct {...@@ -624,55 +589,17 @@ pub const Decl = struct {
624 function_body,589 function_body,
625 };590 };
626591
627 pub fn clearName(decl: *Decl, gpa: Allocator) void {
628 gpa.free(mem.sliceTo(decl.name, 0));
629 decl.name = undefined;
630 }
631
632 pub fn clearValues(decl: *Decl, mod: *Module) void {592 pub fn clearValues(decl: *Decl, mod: *Module) void {
633 const gpa = mod.gpa;593 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
634 if (decl.getExternFn()) |extern_fn| {
635 extern_fn.deinit(gpa);
636 gpa.destroy(extern_fn);
637 }
638 if (decl.getFunction()) |func| {
639 _ = mod.align_stack_fns.remove(func);594 _ = mod.align_stack_fns.remove(func);
640 if (func.comptime_args != null) {595 mod.destroyFunc(func);
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;
662 }596 }
663 }597 }
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
672 /// This name is relative to the containing namespace of the decl.599 /// This name is relative to the containing namespace of the decl.
673 /// The memory is owned by the containing File ZIR.600 /// The memory is owned by the containing File ZIR.
674 pub fn getName(decl: Decl) ?[:0]const u8 {601 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
675 const zir = decl.getFileScope().zir;602 const zir = decl.getFileScope(mod).zir;
676 return decl.getNameZir(zir);603 return decl.getNameZir(zir);
677 }604 }
678605
...@@ -683,8 +610,8 @@ pub const Decl = struct {...@@ -683,8 +610,8 @@ pub const Decl = struct {
683 return zir.nullTerminatedString(name_index);610 return zir.nullTerminatedString(name_index);
684 }611 }
685612
686 pub fn contentsHash(decl: Decl) std.zig.SrcHash {613 pub fn contentsHash(decl: Decl, mod: *Module) std.zig.SrcHash {
687 const zir = decl.getFileScope().zir;614 const zir = decl.getFileScope(mod).zir;
688 return decl.contentsHashZir(zir);615 return decl.contentsHashZir(zir);
689 }616 }
690617
...@@ -695,31 +622,31 @@ pub const Decl = struct {...@@ -695,31 +622,31 @@ pub const Decl = struct {
695 return contents_hash;622 return contents_hash;
696 }623 }
697624
698 pub fn zirBlockIndex(decl: *const Decl) Zir.Inst.Index {625 pub fn zirBlockIndex(decl: *const Decl, mod: *Module) Zir.Inst.Index {
699 assert(decl.zir_decl_index != 0);626 assert(decl.zir_decl_index != 0);
700 const zir = decl.getFileScope().zir;627 const zir = decl.getFileScope(mod).zir;
701 return zir.extra[decl.zir_decl_index + 6];628 return zir.extra[decl.zir_decl_index + 6];
702 }629 }
703630
704 pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref {631 pub fn zirAlignRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
705 if (!decl.has_align) return .none;632 if (!decl.has_align) return .none;
706 assert(decl.zir_decl_index != 0);633 assert(decl.zir_decl_index != 0);
707 const zir = decl.getFileScope().zir;634 const zir = decl.getFileScope(mod).zir;
708 return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 8]);635 return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 8]);
709 }636 }
710637
711 pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref {638 pub fn zirLinksectionRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
712 if (!decl.has_linksection_or_addrspace) return .none;639 if (!decl.has_linksection_or_addrspace) return .none;
713 assert(decl.zir_decl_index != 0);640 assert(decl.zir_decl_index != 0);
714 const zir = decl.getFileScope().zir;641 const zir = decl.getFileScope(mod).zir;
715 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align);642 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align);
716 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);643 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
717 }644 }
718645
719 pub fn zirAddrspaceRef(decl: Decl) Zir.Inst.Ref {646 pub fn zirAddrspaceRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
720 if (!decl.has_linksection_or_addrspace) return .none;647 if (!decl.has_linksection_or_addrspace) return .none;
721 assert(decl.zir_decl_index != 0);648 assert(decl.zir_decl_index != 0);
722 const zir = decl.getFileScope().zir;649 const zir = decl.getFileScope(mod).zir;
723 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align) + 1;650 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align) + 1;
724 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);651 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
725 }652 }
...@@ -744,154 +671,167 @@ pub const Decl = struct {...@@ -744,154 +671,167 @@ pub const Decl = struct {
744 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index));671 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index));
745 }672 }
746673
747 pub fn srcLoc(decl: Decl) SrcLoc {674 pub fn srcLoc(decl: Decl, mod: *Module) SrcLoc {
748 return decl.nodeOffsetSrcLoc(0);675 return decl.nodeOffsetSrcLoc(0, mod);
749 }676 }
750677
751 pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32) SrcLoc {678 pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32, mod: *Module) SrcLoc {
752 return .{679 return .{
753 .file_scope = decl.getFileScope(),680 .file_scope = decl.getFileScope(mod),
754 .parent_decl_node = decl.src_node,681 .parent_decl_node = decl.src_node,
755 .lazy = LazySrcLoc.nodeOffset(node_offset),682 .lazy = LazySrcLoc.nodeOffset(node_offset),
756 };683 };
757 }684 }
758685
759 pub fn srcToken(decl: Decl) Ast.TokenIndex {686 pub fn srcToken(decl: Decl, mod: *Module) Ast.TokenIndex {
760 const tree = &decl.getFileScope().tree;687 const tree = &decl.getFileScope(mod).tree;
761 return tree.firstToken(decl.src_node);688 return tree.firstToken(decl.src_node);
762 }689 }
763690
764 pub fn srcByteOffset(decl: Decl) u32 {691 pub fn srcByteOffset(decl: Decl, mod: *Module) u32 {
765 const tree = &decl.getFileScope().tree;692 const tree = &decl.getFileScope(mod).tree;
766 return tree.tokens.items(.start)[decl.srcToken()];693 return tree.tokens.items(.start)[decl.srcToken()];
767 }694 }
768695
769 pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {696 pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {
770 const unqualified_name = mem.sliceTo(decl.name, 0);
771 if (decl.name_fully_qualified) {697 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);
773 }701 }
774 return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer);
775 }702 }
776703
777 pub fn renderFullyQualifiedDebugName(decl: Decl, mod: *Module, writer: anytype) !void {704 pub fn renderFullyQualifiedDebugName(decl: Decl, mod: *Module, writer: anytype) !void {
778 const unqualified_name = mem.sliceTo(decl.name, 0);705 return mod.namespacePtr(decl.src_namespace).renderFullyQualifiedDebugName(mod, decl.name, writer);
779 return decl.src_namespace.renderFullyQualifiedDebugName(mod, unqualified_name, writer);
780 }706 }
781707
782 pub fn getFullyQualifiedName(decl: Decl, mod: *Module) ![:0]u8 {708 pub fn getFullyQualifiedName(decl: Decl, mod: *Module) !InternPool.NullTerminatedString {
783 var buffer = std.ArrayList(u8).init(mod.gpa);709 if (decl.name_fully_qualified) return decl.name;
784 defer buffer.deinit();710
785 try decl.renderFullyQualifiedName(mod, buffer.writer());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
787 // Sanitize the name for nvptx which is more restrictive.733 // 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.
788 if (mod.comp.bin_file.options.target.cpu.arch.isNvptx()) {736 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.*) {
790 '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',738 '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
791 else => {},739 else => {},
792 };740 };
793 }741 }
794742
795 return buffer.toOwnedSliceSentinel(0);743 return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start);
796 }744 }
797745
798 pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {746 pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {
799 if (!decl.has_tv) return error.AnalysisFail;747 if (!decl.has_tv) return error.AnalysisFail;
800 return TypedValue{748 return TypedValue{ .ty = decl.ty, .val = decl.val };
801 .ty = decl.ty,
802 .val = decl.val,
803 };
804 }749 }
805750
806 pub fn value(decl: *Decl) error{AnalysisFail}!Value {751 pub fn internValue(decl: *Decl, mod: *Module) Allocator.Error!InternPool.Index {
807 return (try decl.typedValue()).val;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;
808 }756 }
809757
810 pub fn isFunction(decl: Decl) !bool {758 pub fn isFunction(decl: Decl, mod: *const Module) !bool {
811 const tv = try decl.typedValue();759 const tv = try decl.typedValue();
812 return tv.ty.zigTypeTag() == .Fn;760 return tv.ty.zigTypeTag(mod) == .Fn;
813 }761 }
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,
816 /// otherwise null.764 /// otherwise null.
817 pub fn getStruct(decl: *Decl) ?*Struct {765 pub fn getOwnedStruct(decl: Decl, mod: *Module) ?*Struct {
818 if (!decl.owns_tv) return null;766 return mod.structPtrUnwrap(decl.getOwnedStructIndex(mod));
819 const ty = (decl.val.castTag(.ty) orelse return null).data;767 }
820 const struct_obj = (ty.castTag(.@"struct") orelse return null).data;768
821 return struct_obj;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());
822 }773 }
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,
825 /// otherwise null.776 /// otherwise null.
826 pub fn getUnion(decl: *Decl) ?*Union {777 pub fn getOwnedUnion(decl: Decl, mod: *Module) ?*Union {
827 if (!decl.owns_tv) return null;778 if (!decl.owns_tv) return null;
828 const ty = (decl.val.castTag(.ty) orelse return null).data;779 if (decl.val.ip_index == .none) return null;
829 const union_obj = (ty.cast(Type.Payload.Union) orelse return null).data;780 return mod.typeToUnion(decl.val.toType());
830 return union_obj;
831 }781 }
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,
834 /// otherwise null.784 /// otherwise null.
835 pub fn getFunction(decl: *const Decl) ?*Fn {785 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn {
836 if (!decl.owns_tv) return null;786 return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod));
837 const func = (decl.val.castTag(.function) orelse return null).data;
838 return func;
839 }787 }
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,
842 /// otherwise null.794 /// otherwise null.
843 pub fn getExternFn(decl: *const Decl) ?*ExternFn {795 pub fn getOwnedExternFunc(decl: Decl, mod: *Module) ?InternPool.Key.ExternFunc {
844 if (!decl.owns_tv) return null;796 return if (decl.owns_tv) decl.val.getExternFunc(mod) else null;
845 const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data;
846 return extern_fn;
847 }797 }
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,
850 /// otherwise null.800 /// otherwise null.
851 pub fn getVariable(decl: *const Decl) ?*Var {801 pub fn getOwnedVariable(decl: Decl, mod: *Module) ?InternPool.Key.Variable {
852 if (!decl.owns_tv) return null;802 return if (decl.owns_tv) decl.val.getVariable(mod) else null;
853 const variable = (decl.val.castTag(.variable) orelse return null).data;
854 return variable;
855 }803 }
856804
857 /// Gets the namespace that this Decl creates by being a struct, union,805 /// Gets the namespace that this Decl creates by being a struct, union,
858 /// enum, or opaque.806 /// enum, or opaque.
859 /// Only returns it if the Decl is the owner.807 /// Only returns it if the Decl is the owner.
860 pub fn getInnerNamespace(decl: *Decl) ?*Namespace {808 pub fn getOwnedInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
861 if (!decl.owns_tv) return null;809 if (!decl.owns_tv) return .none;
862 const ty = (decl.val.castTag(.ty) orelse return null).data;810 return switch (decl.val.ip_index) {
863 switch (ty.tag()) {811 .empty_struct_type => .none,
864 .@"struct" => {812 .none => .none,
865 const struct_obj = ty.castTag(.@"struct").?.data;813 else => switch (mod.intern_pool.indexToKey(decl.val.toIntern())) {
866 return &struct_obj.namespace;814 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
867 },815 .struct_type => |struct_type| struct_type.namespace,
868 .enum_full, .enum_nonexhaustive => {816 .union_type => |union_type| mod.unionPtr(union_type.index).namespace.toOptional(),
869 const enum_obj = ty.cast(Type.Payload.EnumFull).?.data;817 .enum_type => |enum_type| enum_type.namespace,
870 return &enum_obj.namespace;818 else => .none,
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;
882 },819 },
820 };
821 }
883822
884 else => return null,823 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
885 }824 pub fn getOwnedInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
825 return mod.namespacePtrUnwrap(decl.getOwnedInnerNamespaceIndex(mod));
886 }826 }
887827
888 pub fn dump(decl: *Decl) void {828 pub fn dump(decl: *Decl) void {
889 const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);829 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}", .{
891 decl.scope.sub_file_path,831 decl.scope.sub_file_path,
892 loc.line + 1,832 loc.line + 1,
893 loc.column + 1,833 loc.column + 1,
894 mem.sliceTo(decl.name, 0),834 @enumToInt(decl.name),
895 @tagName(decl.analysis),835 @tagName(decl.analysis),
896 });836 });
897 if (decl.has_tv) {837 if (decl.has_tv) {
...@@ -900,8 +840,8 @@ pub const Decl = struct {...@@ -900,8 +840,8 @@ pub const Decl = struct {
900 std.debug.print("\n", .{});840 std.debug.print("\n", .{});
901 }841 }
902842
903 pub fn getFileScope(decl: Decl) *File {843 pub fn getFileScope(decl: Decl, mod: *Module) *File {
904 return decl.src_namespace.file_scope;844 return mod.namespacePtr(decl.src_namespace).file_scope;
905 }845 }
906846
907 pub fn removeDependant(decl: *Decl, other: Decl.Index) void {847 pub fn removeDependant(decl: *Decl, other: Decl.Index) void {
...@@ -912,25 +852,29 @@ pub const Decl = struct {...@@ -912,25 +852,29 @@ pub const Decl = struct {
912 assert(decl.dependencies.swapRemove(other));852 assert(decl.dependencies.swapRemove(other));
913 }853 }
914854
915 pub fn isExtern(decl: Decl) bool {855 pub fn isExtern(decl: Decl, mod: *Module) bool {
916 assert(decl.has_tv);856 assert(decl.has_tv);
917 return switch (decl.val.tag()) {857 return switch (mod.intern_pool.indexToKey(decl.val.toIntern())) {
918 .extern_fn => true,858 .variable => |variable| variable.is_extern,
919 .variable => decl.val.castTag(.variable).?.data.init.tag() == .unreachable_value,859 .extern_func => true,
920 else => false,860 else => false,
921 };861 };
922 }862 }
923863
924 pub fn getAlignment(decl: Decl, target: Target) u32 {864 pub fn getAlignment(decl: Decl, mod: *Module) u32 {
925 assert(decl.has_tv);865 assert(decl.has_tv);
926 if (decl.@"align" != 0) {866 if (decl.@"align" != 0) {
927 // Explicit alignment.867 // Explicit alignment.
928 return decl.@"align";868 return decl.@"align";
929 } else {869 } else {
930 // Natural alignment.870 // Natural alignment.
931 return decl.ty.abiAlignment(target);871 return decl.ty.abiAlignment(mod);
932 }872 }
933 }873 }
874
875 pub fn intern(decl: *Decl, mod: *Module) Allocator.Error!void {
876 decl.val = (try decl.val.intern(decl.ty, mod)).toValue();
877 }
934};878};
935879
936/// This state is attached to every Decl when Module emit_h is non-null.880/// This state is attached to every Decl when Module emit_h is non-null.
...@@ -938,38 +882,6 @@ pub const EmitH = struct {...@@ -938,38 +882,6 @@ pub const EmitH = struct {
938 fwd_decl: ArrayListUnmanaged(u8) = .{},882 fwd_decl: ArrayListUnmanaged(u8) = .{},
939};883};
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
973pub const PropertyBoolean = enum { no, yes, unknown, wip };885pub const PropertyBoolean = enum { no, yes, unknown, wip };
974886
975/// Represents the data that a struct declaration provides.887/// Represents the data that a struct declaration provides.
...@@ -977,7 +889,7 @@ pub const Struct = struct {...@@ -977,7 +889,7 @@ pub const Struct = struct {
977 /// Set of field names in declaration order.889 /// Set of field names in declaration order.
978 fields: Fields,890 fields: Fields,
979 /// Represents the declarations inside this struct.891 /// Represents the declarations inside this struct.
980 namespace: Namespace,892 namespace: Namespace.Index,
981 /// The Decl that corresponds to the struct itself.893 /// The Decl that corresponds to the struct itself.
982 owner_decl: Decl.Index,894 owner_decl: Decl.Index,
983 /// Index of the struct_decl ZIR instruction.895 /// Index of the struct_decl ZIR instruction.
...@@ -989,7 +901,7 @@ pub const Struct = struct {...@@ -989,7 +901,7 @@ pub const Struct = struct {
989 /// If the layout is packed, this is the backing integer type of the packed struct.901 /// If the layout is packed, this is the backing integer type of the packed struct.
990 /// Whether zig chooses this type or the user specifies it, it is stored here.902 /// Whether zig chooses this type or the user specifies it, it is stored here.
991 /// This will be set to the noreturn type until status is `have_layout`.903 /// 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,
993 status: enum {905 status: enum {
994 none,906 none,
995 field_types_wip,907 field_types_wip,
...@@ -1011,15 +923,37 @@ pub const Struct = struct {...@@ -1011,15 +923,37 @@ pub const Struct = struct {
1011 is_tuple: bool,923 is_tuple: bool,
1012 assumed_runtime_bits: bool = false,924 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
1016 /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl.950 /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl.
1017 pub const Field = struct {951 pub const Field = struct {
1018 /// Uses `noreturn` to indicate `anytype`.952 /// Uses `noreturn` to indicate `anytype`.
1019 /// undefined until `status` is >= `have_field_types`.953 /// undefined until `status` is >= `have_field_types`.
1020 ty: Type,954 ty: Type,
1021 /// Uses `unreachable_value` to indicate no default.955 /// Uses `none` to indicate no default.
1022 default_val: Value,956 default_val: InternPool.Index,
1023 /// Zero means to use the ABI alignment of the type.957 /// Zero means to use the ABI alignment of the type.
1024 abi_align: u32,958 abi_align: u32,
1025 /// undefined until `status` is `have_layout`.959 /// undefined until `status` is `have_layout`.
...@@ -1030,7 +964,7 @@ pub const Struct = struct {...@@ -1030,7 +964,7 @@ pub const Struct = struct {
1030 /// Returns the field alignment. If the struct is packed, returns 0.964 /// Returns the field alignment. If the struct is packed, returns 0.
1031 pub fn alignment(965 pub fn alignment(
1032 field: Field,966 field: Field,
1033 target: Target,967 mod: *Module,
1034 layout: std.builtin.Type.ContainerLayout,968 layout: std.builtin.Type.ContainerLayout,
1035 ) u32 {969 ) u32 {
1036 if (field.abi_align != 0) {970 if (field.abi_align != 0) {
...@@ -1038,24 +972,26 @@ pub const Struct = struct {...@@ -1038,24 +972,26 @@ pub const Struct = struct {
1038 return field.abi_align;972 return field.abi_align;
1039 }973 }
1040974
975 const target = mod.getTarget();
976
1041 switch (layout) {977 switch (layout) {
1042 .Packed => return 0,978 .Packed => return 0,
1043 .Auto => {979 .Auto => {
1044 if (target.ofmt == .c) {980 if (target.ofmt == .c) {
1045 return alignmentExtern(field, target);981 return alignmentExtern(field, mod);
1046 } else {982 } else {
1047 return field.ty.abiAlignment(target);983 return field.ty.abiAlignment(mod);
1048 }984 }
1049 },985 },
1050 .Extern => return alignmentExtern(field, target),986 .Extern => return alignmentExtern(field, mod),
1051 }987 }
1052 }988 }
1053989
1054 pub fn alignmentExtern(field: Field, target: Target) u32 {990 pub fn alignmentExtern(field: Field, mod: *Module) u32 {
1055 // This logic is duplicated in Type.abiAlignmentAdvanced.991 // 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) {
1059 // The C ABI requires 128 bit integer fields of structs995 // The C ABI requires 128 bit integer fields of structs
1060 // to be 16-bytes aligned.996 // to be 16-bytes aligned.
1061 return @max(ty_abi_align, 16);997 return @max(ty_abi_align, 16);
...@@ -1069,39 +1005,12 @@ pub const Struct = struct {...@@ -1069,39 +1005,12 @@ pub const Struct = struct {
1069 /// runtime version of the struct.1005 /// runtime version of the struct.
1070 pub const omitted_field = std.math.maxInt(u32);1006 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 {
1073 return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);1009 return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
1074 }1010 }
10751011
1076 pub fn srcLoc(s: Struct, mod: *Module) SrcLoc {1012 pub fn srcLoc(s: Struct, mod: *Module) SrcLoc {
1077 const owner_decl = mod.declPtr(s.owner_decl);1013 return mod.declPtr(s.owner_decl).srcLoc(mod);
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 }
1105 }1014 }
11061015
1107 pub fn haveFieldTypes(s: Struct) bool {1016 pub fn haveFieldTypes(s: Struct) bool {
...@@ -1132,7 +1041,7 @@ pub const Struct = struct {...@@ -1132,7 +1041,7 @@ pub const Struct = struct {
1132 };1041 };
1133 }1042 }
11341043
1135 pub fn packedFieldBitOffset(s: Struct, target: Target, index: usize) u16 {1044 pub fn packedFieldBitOffset(s: Struct, mod: *Module, index: usize) u16 {
1136 assert(s.layout == .Packed);1045 assert(s.layout == .Packed);
1137 assert(s.haveLayout());1046 assert(s.haveLayout());
1138 var bit_sum: u64 = 0;1047 var bit_sum: u64 = 0;
...@@ -1140,12 +1049,13 @@ pub const Struct = struct {...@@ -1140,12 +1049,13 @@ pub const Struct = struct {
1140 if (i == index) {1049 if (i == index) {
1141 return @intCast(u16, bit_sum);1050 return @intCast(u16, bit_sum);
1142 }1051 }
1143 bit_sum += field.ty.bitSize(target);1052 bit_sum += field.ty.bitSize(mod);
1144 }1053 }
1145 unreachable; // index out of bounds1054 unreachable; // index out of bounds
1146 }1055 }
11471056
1148 pub const RuntimeFieldIterator = struct {1057 pub const RuntimeFieldIterator = struct {
1058 module: *Module,
1149 struct_obj: *const Struct,1059 struct_obj: *const Struct,
1150 index: u32 = 0,1060 index: u32 = 0,
11511061
...@@ -1155,6 +1065,7 @@ pub const Struct = struct {...@@ -1155,6 +1065,7 @@ pub const Struct = struct {
1155 };1065 };
11561066
1157 pub fn next(it: *RuntimeFieldIterator) ?FieldAndIndex {1067 pub fn next(it: *RuntimeFieldIterator) ?FieldAndIndex {
1068 const mod = it.module;
1158 while (true) {1069 while (true) {
1159 var i = it.index;1070 var i = it.index;
1160 it.index += 1;1071 it.index += 1;
...@@ -1167,120 +1078,19 @@ pub const Struct = struct {...@@ -1167,120 +1078,19 @@ pub const Struct = struct {
1167 }1078 }
1168 const field = it.struct_obj.fields.values()[i];1079 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)) {
1171 return FieldAndIndex{ .index = i, .field = field };1082 return FieldAndIndex{ .index = i, .field = field };
1172 }1083 }
1173 }1084 }
1174 }1085 }
1175 };1086 };
11761087
1177 pub fn runtimeFieldIterator(s: *const Struct) RuntimeFieldIterator {1088 pub fn runtimeFieldIterator(s: *const Struct, module: *Module) 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);
1257 return .{1089 return .{
1258 .file_scope = owner_decl.getFileScope(),1090 .struct_obj = s,
1259 .parent_decl_node = owner_decl.src_node,1091 .module = module,
1260 .lazy = LazySrcLoc.nodeOffset(0),
1261 };1092 };
1262 }1093 }
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 }
1284};1094};
12851095
1286pub const Union = struct {1096pub const Union = struct {
...@@ -1293,7 +1103,7 @@ pub const Union = struct {...@@ -1293,7 +1103,7 @@ pub const Union = struct {
1293 /// Set of field names in declaration order.1103 /// Set of field names in declaration order.
1294 fields: Fields,1104 fields: Fields,
1295 /// Represents the declarations inside this union.1105 /// Represents the declarations inside this union.
1296 namespace: Namespace,1106 namespace: Namespace.Index,
1297 /// The Decl that corresponds to the union itself.1107 /// The Decl that corresponds to the union itself.
1298 owner_decl: Decl.Index,1108 owner_decl: Decl.Index,
1299 /// Index of the union_decl ZIR instruction.1109 /// Index of the union_decl ZIR instruction.
...@@ -1314,6 +1124,28 @@ pub const Union = struct {...@@ -1314,6 +1124,28 @@ pub const Union = struct {
1314 requires_comptime: PropertyBoolean = .unknown,1124 requires_comptime: PropertyBoolean = .unknown,
1315 assumed_runtime_bits: bool = false,1125 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
1317 pub const Field = struct {1149 pub const Field = struct {
1318 /// undefined until `status` is `have_field_types` or `have_layout`.1150 /// undefined until `status` is `have_field_types` or `have_layout`.
1319 ty: Type,1151 ty: Type,
...@@ -1323,52 +1155,30 @@ pub const Union = struct {...@@ -1323,52 +1155,30 @@ pub const Union = struct {
1323 /// Returns the field alignment, assuming the union is not packed.1155 /// Returns the field alignment, assuming the union is not packed.
1324 /// Keep implementation in sync with `Sema.unionFieldAlignment`.1156 /// Keep implementation in sync with `Sema.unionFieldAlignment`.
1325 /// Prefer to call that function instead of this one during Sema.1157 /// 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 {
1327 if (field.abi_align == 0) {1159 if (field.abi_align == 0) {
1328 return field.ty.abiAlignment(target);1160 return field.ty.abiAlignment(mod);
1329 } else {1161 } else {
1330 return field.abi_align;1162 return field.abi_align;
1331 }1163 }
1332 }1164 }
1333 };1165 };
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 {
1338 return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);1170 return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
1339 }1171 }
13401172
1341 pub fn srcLoc(self: Union, mod: *Module) SrcLoc {1173 pub fn srcLoc(self: Union, mod: *Module) SrcLoc {
1342 const owner_decl = mod.declPtr(self.owner_decl);1174 const owner_decl = mod.declPtr(self.owner_decl);
1343 return .{1175 return .{
1344 .file_scope = owner_decl.getFileScope(),1176 .file_scope = owner_decl.getFileScope(mod),
1345 .parent_decl_node = owner_decl.src_node,1177 .parent_decl_node = owner_decl.src_node,
1346 .lazy = LazySrcLoc.nodeOffset(0),1178 .lazy = LazySrcLoc.nodeOffset(0),
1347 };1179 };
1348 }1180 }
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
1372 pub fn haveFieldTypes(u: Union) bool {1182 pub fn haveFieldTypes(u: Union) bool {
1373 return switch (u.status) {1183 return switch (u.status) {
1374 .none,1184 .none,
...@@ -1383,22 +1193,22 @@ pub const Union = struct {...@@ -1383,22 +1193,22 @@ pub const Union = struct {
1383 };1193 };
1384 }1194 }
13851195
1386 pub fn hasAllZeroBitFieldTypes(u: Union) bool {1196 pub fn hasAllZeroBitFieldTypes(u: Union, mod: *Module) bool {
1387 assert(u.haveFieldTypes());1197 assert(u.haveFieldTypes());
1388 for (u.fields.values()) |field| {1198 for (u.fields.values()) |field| {
1389 if (field.ty.hasRuntimeBits()) return false;1199 if (field.ty.hasRuntimeBits(mod)) return false;
1390 }1200 }
1391 return true;1201 return true;
1392 }1202 }
13931203
1394 pub fn mostAlignedField(u: Union, target: Target) u32 {1204 pub fn mostAlignedField(u: Union, mod: *Module) u32 {
1395 assert(u.haveFieldTypes());1205 assert(u.haveFieldTypes());
1396 var most_alignment: u32 = 0;1206 var most_alignment: u32 = 0;
1397 var most_index: usize = undefined;1207 var most_index: usize = undefined;
1398 for (u.fields.values(), 0..) |field, i| {1208 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);
1402 if (field_align > most_alignment) {1212 if (field_align > most_alignment) {
1403 most_alignment = field_align;1213 most_alignment = field_align;
1404 most_index = i;1214 most_index = i;
...@@ -1408,20 +1218,20 @@ pub const Union = struct {...@@ -1408,20 +1218,20 @@ pub const Union = struct {
1408 }1218 }
14091219
1410 /// Returns 0 if the union is represented with 0 bits at runtime.1220 /// 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 {
1412 var max_align: u32 = 0;1222 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);
1414 for (u.fields.values()) |field| {1224 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);
1418 max_align = @max(max_align, field_align);1228 max_align = @max(max_align, field_align);
1419 }1229 }
1420 return max_align;1230 return max_align;
1421 }1231 }
14221232
1423 pub fn abiSize(u: Union, target: Target, have_tag: bool) u64 {1233 pub fn abiSize(u: Union, mod: *Module, have_tag: bool) u64 {
1424 return u.getLayout(target, have_tag).abi_size;1234 return u.getLayout(mod, have_tag).abi_size;
1425 }1235 }
14261236
1427 pub const Layout = struct {1237 pub const Layout = struct {
...@@ -1451,7 +1261,7 @@ pub const Union = struct {...@@ -1451,7 +1261,7 @@ pub const Union = struct {
1451 };1261 };
1452 }1262 }
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 {
1455 assert(u.haveLayout());1265 assert(u.haveLayout());
1456 var most_aligned_field: u32 = undefined;1266 var most_aligned_field: u32 = undefined;
1457 var most_aligned_field_size: u64 = undefined;1267 var most_aligned_field_size: u64 = undefined;
...@@ -1460,16 +1270,16 @@ pub const Union = struct {...@@ -1460,16 +1270,16 @@ pub const Union = struct {
1460 var payload_align: u32 = 0;1270 var payload_align: u32 = 0;
1461 const fields = u.fields.values();1271 const fields = u.fields.values();
1462 for (fields, 0..) |field, i| {1272 for (fields, 0..) |field, i| {
1463 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;1273 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14641274
1465 const field_align = a: {1275 const field_align = a: {
1466 if (field.abi_align == 0) {1276 if (field.abi_align == 0) {
1467 break :a field.ty.abiAlignment(target);1277 break :a field.ty.abiAlignment(mod);
1468 } else {1278 } else {
1469 break :a field.abi_align;1279 break :a field.abi_align;
1470 }1280 }
1471 };1281 };
1472 const field_size = field.ty.abiSize(target);1282 const field_size = field.ty.abiSize(mod);
1473 if (field_size > payload_size) {1283 if (field_size > payload_size) {
1474 payload_size = field_size;1284 payload_size = field_size;
1475 biggest_field = @intCast(u32, i);1285 biggest_field = @intCast(u32, i);
...@@ -1481,7 +1291,7 @@ pub const Union = struct {...@@ -1481,7 +1291,7 @@ pub const Union = struct {
1481 }1291 }
1482 }1292 }
1483 payload_align = @max(payload_align, 1);1293 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)) {
1485 return .{1295 return .{
1486 .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align),1296 .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align),
1487 .abi_align = payload_align,1297 .abi_align = payload_align,
...@@ -1497,8 +1307,8 @@ pub const Union = struct {...@@ -1497,8 +1307,8 @@ pub const Union = struct {
1497 }1307 }
1498 // Put the tag before or after the payload depending on which one's1308 // Put the tag before or after the payload depending on which one's
1499 // alignment is greater.1309 // alignment is greater.
1500 const tag_size = u.tag_ty.abiSize(target);1310 const tag_size = u.tag_ty.abiSize(mod);
1501 const tag_align = @max(1, u.tag_ty.abiAlignment(target));1311 const tag_align = @max(1, u.tag_ty.abiAlignment(mod));
1502 var size: u64 = 0;1312 var size: u64 = 0;
1503 var padding: u32 = undefined;1313 var padding: u32 = undefined;
1504 if (tag_align >= payload_align) {1314 if (tag_align >= payload_align) {
...@@ -1533,26 +1343,6 @@ pub const Union = struct {...@@ -1533,26 +1343,6 @@ pub const Union = struct {
1533 }1343 }
1534};1344};
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
1556/// Some extern function struct memory is owned by the Decl's TypedValue.Managed1346/// Some extern function struct memory is owned by the Decl's TypedValue.Managed
1557/// arena allocator.1347/// arena allocator.
1558pub const ExternFn = struct {1348pub const ExternFn = struct {
...@@ -1630,12 +1420,27 @@ pub const Fn = struct {...@@ -1630,12 +1420,27 @@ pub const Fn = struct {
1630 is_noinline: bool,1420 is_noinline: bool,
1631 calls_or_awaits_errorable_fn: bool = false,1421 calls_or_awaits_errorable_fn: bool = false,
16321422
1633 /// Any inferred error sets that this function owns, both its own inferred error set and1423 pub const Index = enum(u32) {
1634 /// inferred error sets of any inline/comptime functions called. Not to be confused1424 _,
1635 /// with inferred error sets of generic instantiations of this function, which are1425
1636 /// *not* tracked here - they are tracked in the new `Fn` object created for the1426 pub fn toOptional(i: Index) OptionalIndex {
1637 /// instantiations.1427 return @intToEnum(OptionalIndex, @enumToInt(i));
1638 inferred_error_sets: InferredErrorSetList = .{},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
1640 pub const Analysis = enum {1445 pub const Analysis = enum {
1641 /// This function has not yet undergone analysis, because we have not1446 /// This function has not yet undergone analysis, because we have not
...@@ -1662,16 +1467,16 @@ pub const Fn = struct {...@@ -1662,16 +1467,16 @@ pub const Fn = struct {
1662 /// or comptime functions.1467 /// or comptime functions.
1663 pub const InferredErrorSet = struct {1468 pub const InferredErrorSet = struct {
1664 /// The function from which this error set originates.1469 /// The function from which this error set originates.
1665 func: *Fn,1470 func: Fn.Index,
16661471
1667 /// All currently known errors that this error set contains. This includes1472 /// All currently known errors that this error set contains. This includes
1668 /// direct additions via `return error.Foo;`, and possibly also errors that1473 /// direct additions via `return error.Foo;`, and possibly also errors that
1669 /// are returned from any dependent functions. When the inferred error set is1474 /// are returned from any dependent functions. When the inferred error set is
1670 /// fully resolved, this map contains all the errors that the function might return.1475 /// fully resolved, this map contains all the errors that the function might return.
1671 errors: ErrorSet.NameMap = .{},1476 errors: NameMap = .{},
16721477
1673 /// Other inferred error sets which this inferred error set should include.1478 /// 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
1676 /// Whether the function returned anyerror. This is true if either of1481 /// Whether the function returned anyerror. This is true if either of
1677 /// the dependent functions returns anyerror.1482 /// the dependent functions returns anyerror.
...@@ -1681,52 +1486,57 @@ pub const Fn = struct {...@@ -1681,52 +1486,57 @@ pub const Fn = struct {
1681 /// can skip resolving any dependents of this inferred error set.1486 /// can skip resolving any dependents of this inferred error set.
1682 is_resolved: bool = false,1487 is_resolved: bool = false,
16831488
1684 pub fn addErrorSet(self: *InferredErrorSet, gpa: Allocator, err_set_ty: Type) !void {1489 pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
1685 switch (err_set_ty.tag()) {1490
1686 .error_set => {1491 pub const Index = enum(u32) {
1687 const names = err_set_ty.castTag(.error_set).?.data.names.keys();1492 _,
1688 for (names) |name| {1493
1689 try self.errors.put(gpa, name, {});1494 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1690 }1495 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(i));
1691 },1496 }
1692 .error_set_single => {1497 };
1693 const name = err_set_ty.castTag(.error_set_single).?.data;1498
1694 try self.errors.put(gpa, name, {});1499 pub const OptionalIndex = enum(u32) {
1695 },1500 none = std.math.maxInt(u32),
1696 .error_set_inferred => {1501 _,
1697 const ies = err_set_ty.castTag(.error_set_inferred).?.data;1502
1698 try self.inferred_error_sets.put(gpa, ies, {});1503 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1699 },1504 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(oi orelse return .none));
1700 .error_set_merged => {1505 }
1701 const names = err_set_ty.castTag(.error_set_merged).?.data.keys();1506
1702 for (names) |name| {1507 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
1703 try self.errors.put(gpa, name, {});1508 if (oi == .none) return null;
1704 }1509 return @intToEnum(InferredErrorSet.Index, @enumToInt(oi));
1705 },1510 }
1706 .anyerror => {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 => {
1707 self.is_anyerror = true;1521 self.is_anyerror = true;
1708 },1522 },
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 },
1710 }1534 }
1711 }1535 }
1712 };1536 };
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
1728 pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {1538 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
1731 const tags = file.zir.instructions.items(.tag);1541 const tags = file.zir.instructions.items(.tag);
17321542
...@@ -1741,7 +1551,7 @@ pub const Fn = struct {...@@ -1741,7 +1551,7 @@ pub const Fn = struct {
1741 }1551 }
17421552
1743 pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 {1553 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
1746 const tags = file.zir.instructions.items(.tag);1556 const tags = file.zir.instructions.items(.tag);
1747 const data = file.zir.instructions.items(.data);1557 const data = file.zir.instructions.items(.data);
...@@ -1764,7 +1574,7 @@ pub const Fn = struct {...@@ -1764,7 +1574,7 @@ pub const Fn = struct {
17641574
1765 pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool {1575 pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool {
1766 const owner_decl = mod.declPtr(func.owner_decl);1576 const owner_decl = mod.declPtr(func.owner_decl);
1767 const zir = owner_decl.getFileScope().zir;1577 const zir = owner_decl.getFileScope(mod).zir;
1768 const zir_tags = zir.instructions.items(.tag);1578 const zir_tags = zir.instructions.items(.tag);
1769 switch (zir_tags[func.zir_body_inst]) {1579 switch (zir_tags[func.zir_body_inst]) {
1770 .func => return false,1580 .func => return false,
...@@ -1779,46 +1589,24 @@ pub const Fn = struct {...@@ -1779,46 +1589,24 @@ pub const Fn = struct {
1779 }1589 }
1780};1590};
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
1804pub const DeclAdapter = struct {1592pub const DeclAdapter = struct {
1805 mod: *Module,1593 mod: *Module,
18061594
1807 pub fn hash(self: @This(), s: []const u8) u32 {1595 pub fn hash(self: @This(), s: InternPool.NullTerminatedString) u32 {
1808 _ = self;1596 _ = self;
1809 return @truncate(u32, std.hash.Wyhash.hash(0, s));1597 return std.hash.uint32(@enumToInt(s));
1810 }1598 }
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 {
1813 _ = b_index;1601 _ = b_index;
1814 const b_decl = self.mod.declPtr(b_decl_index);1602 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;
1816 }1604 }
1817};1605};
18181606
1819/// The container that structs, enums, unions, and opaques have.1607/// The container that structs, enums, unions, and opaques have.
1820pub const Namespace = struct {1608pub const Namespace = struct {
1821 parent: ?*Namespace,1609 parent: OptionalIndex,
1822 file_scope: *File,1610 file_scope: *File,
1823 /// Will be a struct, enum, union, or opaque.1611 /// Will be a struct, enum, union, or opaque.
1824 ty: Type,1612 ty: Type,
...@@ -1836,21 +1624,41 @@ pub const Namespace = struct {...@@ -1836,21 +1624,41 @@ pub const Namespace = struct {
1836 /// Value is whether the usingnamespace decl is marked `pub`.1624 /// Value is whether the usingnamespace decl is marked `pub`.
1837 usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{},1625 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
1839 const DeclContext = struct {1649 const DeclContext = struct {
1840 module: *Module,1650 module: *Module,
18411651
1842 pub fn hash(ctx: @This(), decl_index: Decl.Index) u32 {1652 pub fn hash(ctx: @This(), decl_index: Decl.Index) u32 {
1843 const decl = ctx.module.declPtr(decl_index);1653 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));
1845 }1655 }
18461656
1847 pub fn eql(ctx: @This(), a_decl_index: Decl.Index, b_decl_index: Decl.Index, b_index: usize) bool {1657 pub fn eql(ctx: @This(), a_decl_index: Decl.Index, b_decl_index: Decl.Index, b_index: usize) bool {
1848 _ = b_index;1658 _ = b_index;
1849 const a_decl = ctx.module.declPtr(a_decl_index);1659 const a_decl = ctx.module.declPtr(a_decl_index);
1850 const b_decl = ctx.module.declPtr(b_decl_index);1660 const b_decl = ctx.module.declPtr(b_decl_index);
1851 const a_name = mem.sliceTo(a_decl.name, 0);1661 return a_decl.name == b_decl.name;
1852 const b_name = mem.sliceTo(b_decl.name, 0);
1853 return mem.eql(u8, a_name, b_name);
1854 }1662 }
1855 };1663 };
18561664
...@@ -1862,8 +1670,6 @@ pub const Namespace = struct {...@@ -1862,8 +1670,6 @@ pub const Namespace = struct {
1862 pub fn destroyDecls(ns: *Namespace, mod: *Module) void {1670 pub fn destroyDecls(ns: *Namespace, mod: *Module) void {
1863 const gpa = mod.gpa;1671 const gpa = mod.gpa;
18641672
1865 log.debug("destroyDecls {*}", .{ns});
1866
1867 var decls = ns.decls;1673 var decls = ns.decls;
1868 ns.decls = .{};1674 ns.decls = .{};
18691675
...@@ -1889,8 +1695,6 @@ pub const Namespace = struct {...@@ -1889,8 +1695,6 @@ pub const Namespace = struct {
1889 ) !void {1695 ) !void {
1890 const gpa = mod.gpa;1696 const gpa = mod.gpa;
18911697
1892 log.debug("deleteAllDecls {*}", .{ns});
1893
1894 var decls = ns.decls;1698 var decls = ns.decls;
1895 ns.decls = .{};1699 ns.decls = .{};
18961700
...@@ -1919,46 +1723,38 @@ pub const Namespace = struct {...@@ -1919,46 +1723,38 @@ pub const Namespace = struct {
1919 pub fn renderFullyQualifiedName(1723 pub fn renderFullyQualifiedName(
1920 ns: Namespace,1724 ns: Namespace,
1921 mod: *Module,1725 mod: *Module,
1922 name: []const u8,1726 name: InternPool.NullTerminatedString,
1923 writer: anytype,1727 writer: anytype,
1924 ) @TypeOf(writer).Error!void {1728 ) @TypeOf(writer).Error!void {
1925 if (ns.parent) |parent| {1729 if (ns.parent.unwrap()) |parent| {
1926 const decl_index = ns.getDeclIndex();1730 const decl = mod.declPtr(ns.getDeclIndex(mod));
1927 const decl = mod.declPtr(decl_index);1731 try mod.namespacePtr(parent).renderFullyQualifiedName(mod, decl.name, writer);
1928 try parent.renderFullyQualifiedName(mod, mem.sliceTo(decl.name, 0), writer);
1929 } else {1732 } else {
1930 try ns.file_scope.renderFullyQualifiedName(writer);1733 try ns.file_scope.renderFullyQualifiedName(writer);
1931 }1734 }
1932 if (name.len != 0) {1735 if (name != .empty) try writer.print(".{}", .{name.fmt(&mod.intern_pool)});
1933 try writer.writeAll(".");
1934 try writer.writeAll(name);
1935 }
1936 }1736 }
19371737
1938 /// This renders e.g. "std/fs.zig:Dir.OpenOptions"1738 /// This renders e.g. "std/fs.zig:Dir.OpenOptions"
1939 pub fn renderFullyQualifiedDebugName(1739 pub fn renderFullyQualifiedDebugName(
1940 ns: Namespace,1740 ns: Namespace,
1941 mod: *Module,1741 mod: *Module,
1942 name: []const u8,1742 name: InternPool.NullTerminatedString,
1943 writer: anytype,1743 writer: anytype,
1944 ) @TypeOf(writer).Error!void {1744 ) @TypeOf(writer).Error!void {
1945 var separator_char: u8 = '.';1745 const separator_char: u8 = if (ns.parent.unwrap()) |parent| sep: {
1946 if (ns.parent) |parent| {1746 const decl = mod.declPtr(ns.getDeclIndex(mod));
1947 const decl_index = ns.getDeclIndex();1747 try mod.namespacePtr(parent).renderFullyQualifiedDebugName(mod, decl.name, writer);
1948 const decl = mod.declPtr(decl_index);1748 break :sep '.';
1949 try parent.renderFullyQualifiedDebugName(mod, mem.sliceTo(decl.name, 0), writer);1749 } else sep: {
1950 } else {
1951 try ns.file_scope.renderFullyQualifiedDebugName(writer);1750 try ns.file_scope.renderFullyQualifiedDebugName(writer);
1952 separator_char = ':';1751 break :sep ':';
1953 }1752 };
1954 if (name.len != 0) {1753 if (name != .empty) try writer.print("{c}{}", .{ separator_char, name.fmt(&mod.intern_pool) });
1955 try writer.writeByte(separator_char);
1956 try writer.writeAll(name);
1957 }
1958 }1754 }
19591755
1960 pub fn getDeclIndex(ns: Namespace) Decl.Index {1756 pub fn getDeclIndex(ns: Namespace, mod: *Module) Decl.Index {
1961 return ns.ty.getOwnerDecl();1757 return ns.ty.getOwnerDecl(mod);
1962 }1758 }
1963};1759};
19641760
...@@ -2140,11 +1936,11 @@ pub const File = struct {...@@ -2140,11 +1936,11 @@ pub const File = struct {
2140 };1936 };
2141 }1937 }
21421938
2143 pub fn fullyQualifiedNameZ(file: File, gpa: Allocator) ![:0]u8 {1939 pub fn fullyQualifiedName(file: File, mod: *Module) !InternPool.NullTerminatedString {
2144 var buf = std.ArrayList(u8).init(gpa);1940 const ip = &mod.intern_pool;
2145 defer buf.deinit();1941 const start = ip.string_bytes.items.len;
2146 try file.renderFullyQualifiedName(buf.writer());1942 try file.renderFullyQualifiedName(ip.string_bytes.writer(mod.gpa));
2147 return buf.toOwnedSliceSentinel(0);1943 return ip.getOrPutTrailingString(mod.gpa, ip.string_bytes.items.len - start);
2148 }1944 }
21491945
2150 /// Returns the full path to this file relative to its package.1946 /// Returns the full path to this file relative to its package.
...@@ -2268,7 +2064,7 @@ pub const ErrorMsg = struct {...@@ -2268,7 +2064,7 @@ pub const ErrorMsg = struct {
2268 reference_trace: []Trace = &.{},2064 reference_trace: []Trace = &.{},
22692065
2270 pub const Trace = struct {2066 pub const Trace = struct {
2271 decl: ?[*:0]const u8,2067 decl: InternPool.OptionalNullTerminatedString,
2272 src_loc: SrcLoc,2068 src_loc: SrcLoc,
2273 hidden: u32 = 0,2069 hidden: u32 = 0,
2274 };2070 };
...@@ -2281,7 +2077,7 @@ pub const ErrorMsg = struct {...@@ -2281,7 +2077,7 @@ pub const ErrorMsg = struct {
2281 ) !*ErrorMsg {2077 ) !*ErrorMsg {
2282 const err_msg = try gpa.create(ErrorMsg);2078 const err_msg = try gpa.create(ErrorMsg);
2283 errdefer gpa.destroy(err_msg);2079 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);
2285 return err_msg;2081 return err_msg;
2286 }2082 }
22872083
...@@ -3287,7 +3083,7 @@ pub const LazySrcLoc = union(enum) {...@@ -3287,7 +3083,7 @@ pub const LazySrcLoc = union(enum) {
3287 }3083 }
32883084
3289 /// Upgrade to a `SrcLoc` based on the `Decl` provided.3085 /// 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 {
3291 return switch (lazy) {3087 return switch (lazy) {
3292 .unneeded,3088 .unneeded,
3293 .entire_file,3089 .entire_file,
...@@ -3295,7 +3091,7 @@ pub const LazySrcLoc = union(enum) {...@@ -3295,7 +3091,7 @@ pub const LazySrcLoc = union(enum) {
3295 .token_abs,3091 .token_abs,
3296 .node_abs,3092 .node_abs,
3297 => .{3093 => .{
3298 .file_scope = decl.getFileScope(),3094 .file_scope = decl.getFileScope(mod),
3299 .parent_decl_node = 0,3095 .parent_decl_node = 0,
3300 .lazy = lazy,3096 .lazy = lazy,
3301 },3097 },
...@@ -3361,7 +3157,7 @@ pub const LazySrcLoc = union(enum) {...@@ -3361,7 +3157,7 @@ pub const LazySrcLoc = union(enum) {
3361 .for_input,3157 .for_input,
3362 .for_capture_from_input,3158 .for_capture_from_input,
3363 => .{3159 => .{
3364 .file_scope = decl.getFileScope(),3160 .file_scope = decl.getFileScope(mod),
3365 .parent_decl_node = decl.src_node,3161 .parent_decl_node = decl.src_node,
3366 .lazy = lazy,3162 .lazy = lazy,
3367 },3163 },
...@@ -3391,6 +3187,12 @@ pub const CompileError = error{...@@ -3391,6 +3187,12 @@ pub const CompileError = error{
3391 ComptimeBreak,3187 ComptimeBreak,
3392};3188};
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
3394pub fn deinit(mod: *Module) void {3196pub fn deinit(mod: *Module) void {
3395 const gpa = mod.gpa;3197 const gpa = mod.gpa;
33963198
...@@ -3489,42 +3291,29 @@ pub fn deinit(mod: *Module) void {...@@ -3489,42 +3291,29 @@ pub fn deinit(mod: *Module) void {
3489 }3291 }
3490 mod.export_owners.deinit(gpa);3292 mod.export_owners.deinit(gpa);
34913293
3492 {3294 mod.global_error_set.deinit(gpa);
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 }
34993295
3500 mod.error_name_list.deinit(gpa);
3501 mod.test_functions.deinit(gpa);3296 mod.test_functions.deinit(gpa);
3502 mod.align_stack_fns.deinit(gpa);3297 mod.align_stack_fns.deinit(gpa);
3503 mod.monomorphed_funcs.deinit(gpa);3298 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
3514 mod.decls_free_list.deinit(gpa);3300 mod.decls_free_list.deinit(gpa);
3515 mod.allocated_decls.deinit(gpa);3301 mod.allocated_decls.deinit(gpa);
3516 mod.global_assembly.deinit(gpa);3302 mod.global_assembly.deinit(gpa);
3517 mod.reference_table.deinit(gpa);3303 mod.reference_table.deinit(gpa);
35183304
3519 mod.string_literal_table.deinit(gpa);3305 mod.namespaces_free_list.deinit(gpa);
3520 mod.string_literal_bytes.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();
3521}3311}
35223312
3523pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {3313pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3524 const gpa = mod.gpa;3314 const gpa = mod.gpa;
3525 {3315 {
3526 const decl = mod.declPtr(decl_index);3316 const decl = mod.declPtr(decl_index);
3527 log.debug("destroy {*} ({s})", .{ decl, decl.name });
3528 _ = mod.test_functions.swapRemove(decl_index);3317 _ = mod.test_functions.swapRemove(decl_index);
3529 if (decl.deletion_flag) {3318 if (decl.deletion_flag) {
3530 assert(mod.deletion_set.swapRemove(decl_index));3319 assert(mod.deletion_set.swapRemove(decl_index));
...@@ -3533,14 +3322,15 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -3533,14 +3322,15 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3533 gpa.free(kv.value);3322 gpa.free(kv.value);
3534 }3323 }
3535 if (decl.has_tv) {3324 if (decl.has_tv) {
3536 if (decl.getInnerNamespace()) |namespace| {3325 if (decl.getOwnedInnerNamespaceIndex(mod).unwrap()) |i| {
3537 namespace.destroyDecls(mod);3326 mod.namespacePtr(i).destroyDecls(mod);
3327 mod.destroyNamespace(i);
3538 }3328 }
3539 }3329 }
3330 if (decl.src_scope) |scope| scope.decRef(gpa);
3540 decl.clearValues(mod);3331 decl.clearValues(mod);
3541 decl.dependants.deinit(gpa);3332 decl.dependants.deinit(gpa);
3542 decl.dependencies.deinit(gpa);3333 decl.dependencies.deinit(gpa);
3543 decl.clearName(gpa);
3544 decl.* = undefined;3334 decl.* = undefined;
3545 }3335 }
3546 mod.decls_free_list.append(gpa, decl_index) catch {3336 mod.decls_free_list.append(gpa, decl_index) catch {
...@@ -3554,24 +3344,55 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -3554,24 +3344,55 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3554 }3344 }
3555}3345}
35563346
3557pub fn declPtr(mod: *Module, decl_index: Decl.Index) *Decl {3347pub fn declPtr(mod: *Module, index: Decl.Index) *Decl {
3558 return mod.allocated_decls.at(@enumToInt(decl_index));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);
3559}3383}
35603384
3561/// Returns true if and only if the Decl is the top level struct associated with a File.3385/// Returns true if and only if the Decl is the top level struct associated with a File.
3562pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {3386pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
3563 const decl = mod.declPtr(decl_index);3387 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)
3565 return false;3390 return false;
3566 return decl_index == decl.src_namespace.getDeclIndex();3391 return decl_index == namespace.getDeclIndex(mod);
3567}3392}
35683393
3569fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void {3394fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void {
3570 for (export_list.items) |exp| {3395 for (export_list.items) |exp| gpa.destroy(exp);
3571 gpa.free(exp.options.name);
3572 if (exp.options.section) |s| gpa.free(s);
3573 gpa.destroy(exp);
3574 }
3575 export_list.deinit(gpa);3396 export_list.deinit(gpa);
3576}3397}
35773398
...@@ -3990,9 +3811,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -3990,9 +3811,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3990 if (decl.zir_decl_index != 0) {3811 if (decl.zir_decl_index != 0) {
3991 const old_zir_decl_index = decl.zir_decl_index;3812 const old_zir_decl_index = decl.zir_decl_index;
3992 const new_zir_decl_index = extra_map.get(old_zir_decl_index) orelse {3813 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 });
3996 try file.deleted_decls.append(gpa, decl_index);3814 try file.deleted_decls.append(gpa, decl_index);
3997 continue;3815 continue;
3998 };3816 };
...@@ -4000,41 +3818,34 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -4000,41 +3818,34 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
4000 decl.zir_decl_index = new_zir_decl_index;3818 decl.zir_decl_index = new_zir_decl_index;
4001 const new_hash = decl.contentsHashZir(new_zir);3819 const new_hash = decl.contentsHashZir(new_zir);
4002 if (!std.zig.srcHashEql(old_hash, new_hash)) {3820 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 });
4006 try file.outdated_decls.append(gpa, decl_index);3821 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 });
4011 }3822 }
4012 }3823 }
40133824
4014 if (!decl.owns_tv) continue;3825 if (!decl.owns_tv) continue;
40153826
4016 if (decl.getStruct()) |struct_obj| {3827 if (decl.getOwnedStruct(mod)) |struct_obj| {
4017 struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {3828 struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {
4018 try file.deleted_decls.append(gpa, decl_index);3829 try file.deleted_decls.append(gpa, decl_index);
4019 continue;3830 continue;
4020 };3831 };
4021 }3832 }
40223833
4023 if (decl.getUnion()) |union_obj| {3834 if (decl.getOwnedUnion(mod)) |union_obj| {
4024 union_obj.zir_index = inst_map.get(union_obj.zir_index) orelse {3835 union_obj.zir_index = inst_map.get(union_obj.zir_index) orelse {
4025 try file.deleted_decls.append(gpa, decl_index);3836 try file.deleted_decls.append(gpa, decl_index);
4026 continue;3837 continue;
4027 };3838 };
4028 }3839 }
40293840
4030 if (decl.getFunction()) |func| {3841 if (decl.getOwnedFunction(mod)) |func| {
4031 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {3842 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
4032 try file.deleted_decls.append(gpa, decl_index);3843 try file.deleted_decls.append(gpa, decl_index);
4033 continue;3844 continue;
4034 };3845 };
4035 }3846 }
40363847
4037 if (decl.getInnerNamespace()) |namespace| {3848 if (decl.getOwnedInnerNamespace(mod)) |namespace| {
4038 for (namespace.decls.keys()) |sub_decl| {3849 for (namespace.decls.keys()) |sub_decl| {
4039 try decl_stack.append(gpa, sub_decl);3850 try decl_stack.append(gpa, sub_decl);
4040 }3851 }
...@@ -4207,14 +4018,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4207,14 +4018,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4207 .complete => return,4018 .complete => return,
42084019
4209 .outdated => blk: {4020 .outdated => blk: {
4210 log.debug("re-analyzing {*} ({s})", .{ decl, decl.name });
4211
4212 // The exports this Decl performs will be re-discovered, so we remove them here4021 // The exports this Decl performs will be re-discovered, so we remove them here
4213 // prior to re-analysis.4022 // prior to re-analysis.
4214 try mod.deleteDeclExports(decl_index);4023 try mod.deleteDeclExports(decl_index);
42154024
4216 // Similarly, `@setAlignStack` invocations will be re-discovered.4025 // Similarly, `@setAlignStack` invocations will be re-discovered.
4217 if (decl.getFunction()) |func| {4026 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
4218 _ = mod.align_stack_fns.remove(func);4027 _ = mod.align_stack_fns.remove(func);
4219 }4028 }
42204029
...@@ -4223,9 +4032,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4223,9 +4032,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4223 const dep = mod.declPtr(dep_index);4032 const dep = mod.declPtr(dep_index);
4224 dep.removeDependant(decl_index);4033 dep.removeDependant(decl_index);
4225 if (dep.dependants.count() == 0 and !dep.deletion_flag) {4034 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 });
4229 try mod.markDeclForDeletion(dep_index);4035 try mod.markDeclForDeletion(dep_index);
4230 }4036 }
4231 }4037 }
...@@ -4237,7 +4043,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4237,7 +4043,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4237 .unreferenced => false,4043 .unreferenced => false,
4238 };4044 };
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);
4241 decl_prog_node.activate();4047 decl_prog_node.activate();
4242 defer decl_prog_node.end();4048 defer decl_prog_node.end();
42434049
...@@ -4264,7 +4070,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4264,7 +4070,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4264 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);4070 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);
4265 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(4071 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
4266 mod.gpa,4072 mod.gpa,
4267 decl.srcLoc(),4073 decl.srcLoc(mod),
4268 "unable to analyze: {s}",4074 "unable to analyze: {s}",
4269 .{@errorName(e)},4075 .{@errorName(e)},
4270 ));4076 ));
...@@ -4277,7 +4083,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4277,7 +4083,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4277 // Update all dependents which have at least this level of dependency.4083 // Update all dependents which have at least this level of dependency.
4278 // If our type remained the same and we're a function, only update4084 // If our type remained the same and we're a function, only update
4279 // decls which depend on our body; otherwise, update all dependents.4085 // 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
4282 for (decl.dependants.keys(), decl.dependants.values()) |dep_index, dep_type| {4088 for (decl.dependants.keys(), decl.dependants.values()) |dep_index, dep_type| {
4283 if (@enumToInt(dep_type) < @enumToInt(update_level)) continue;4089 if (@enumToInt(dep_type) < @enumToInt(update_level)) continue;
...@@ -4304,10 +4110,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4304,10 +4110,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4304 }4110 }
4305}4111}
43064112
4307pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {4113pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {
4308 const tracy = trace(@src());4114 const tracy = trace(@src());
4309 defer tracy.end();4115 defer tracy.end();
43104116
4117 const func = mod.funcPtr(func_index);
4311 const decl_index = func.owner_decl;4118 const decl_index = func.owner_decl;
4312 const decl = mod.declPtr(decl_index);4119 const decl = mod.declPtr(decl_index);
43134120
...@@ -4339,7 +4146,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4339,7 +4146,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4339 defer tmp_arena.deinit();4146 defer tmp_arena.deinit();
4340 const sema_arena = tmp_arena.allocator();4147 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) {
4343 error.AnalysisFail => {4150 error.AnalysisFail => {
4344 if (func.state == .in_progress) {4151 if (func.state == .in_progress) {
4345 // If this decl caused the compile error, the analysis field would4152 // If this decl caused the compile error, the analysis field would
...@@ -4365,17 +4172,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4365,17 +4172,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43654172
4366 if (no_bin_file and !dump_air and !dump_llvm_ir) return;4173 if (no_bin_file and !dump_air and !dump_llvm_ir) return;
43674174
4368 log.debug("analyze liveness of {s}", .{decl.name});4175 var liveness = try Liveness.analyze(gpa, air, &mod.intern_pool);
4369 var liveness = try Liveness.analyze(gpa, air);
4370 defer liveness.deinit(gpa);4176 defer liveness.deinit(gpa);
43714177
4372 if (dump_air) {4178 if (dump_air) {
4373 const fqn = try decl.getFullyQualifiedName(mod);4179 const fqn = try decl.getFullyQualifiedName(mod);
4374 defer mod.gpa.free(fqn);4180 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(&mod.intern_pool)});
4375
4376 std.debug.print("# Begin Function AIR: {s}:\n", .{fqn});
4377 @import("print_air.zig").dump(mod, air, liveness);4181 @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)});
4379 }4183 }
43804184
4381 if (std.debug.runtime_safety) {4185 if (std.debug.runtime_safety) {
...@@ -4383,6 +4187,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4383,6 +4187,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4383 .gpa = gpa,4187 .gpa = gpa,
4384 .air = air,4188 .air = air,
4385 .liveness = liveness,4189 .liveness = liveness,
4190 .intern_pool = &mod.intern_pool,
4386 };4191 };
4387 defer verify.deinit();4192 defer verify.deinit();
43884193
...@@ -4394,7 +4199,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4394,7 +4199,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4394 decl_index,4199 decl_index,
4395 try Module.ErrorMsg.create(4200 try Module.ErrorMsg.create(
4396 gpa,4201 gpa,
4397 decl.srcLoc(),4202 decl.srcLoc(mod),
4398 "invalid liveness: {s}",4203 "invalid liveness: {s}",
4399 .{@errorName(err)},4204 .{@errorName(err)},
4400 ),4205 ),
...@@ -4407,7 +4212,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4407,7 +4212,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
44074212
4408 if (no_bin_file and !dump_llvm_ir) return;4213 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) {
4411 error.OutOfMemory => return error.OutOfMemory,4216 error.OutOfMemory => return error.OutOfMemory,
4412 error.AnalysisFail => {4217 error.AnalysisFail => {
4413 decl.analysis = .codegen_failure;4218 decl.analysis = .codegen_failure;
...@@ -4417,7 +4222,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4417,7 +4222,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4417 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);4222 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
4418 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(4223 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
4419 gpa,4224 gpa,
4420 decl.srcLoc(),4225 decl.srcLoc(mod),
4421 "unable to codegen: {s}",4226 "unable to codegen: {s}",
4422 .{@errorName(err)},4227 .{@errorName(err)},
4423 ));4228 ));
...@@ -4437,7 +4242,8 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {...@@ -4437,7 +4242,8 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4437/// analyzed, and for ensuring it can exist at runtime (see4242/// analyzed, and for ensuring it can exist at runtime (see
4438/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body4243/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
4439/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.4244/// 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);
4441 const decl_index = func.owner_decl;4247 const decl_index = func.owner_decl;
4442 const decl = mod.declPtr(decl_index);4248 const decl = mod.declPtr(decl_index);
44434249
...@@ -4475,7 +4281,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {...@@ -4475,7 +4281,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
44754281
4476 // Decl itself is safely analyzed, and body analysis is not yet queued4282 // 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 });
4479 if (mod.emit_h != null) {4285 if (mod.emit_h != null) {
4480 // TODO: we ideally only want to do this if the function's type changed4286 // TODO: we ideally only want to do this if the function's type changed
4481 // since the last update4287 // since the last update
...@@ -4527,42 +4333,54 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4527,42 +4333,54 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4527 if (file.root_decl != .none) return;4333 if (file.root_decl != .none) return;
45284334
4529 const gpa = mod.gpa;4335 const gpa = mod.gpa;
4530 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);4336
4531 errdefer new_decl_arena.deinit();4337 // Because these three things each reference each other, `undefined`
4532 const new_decl_arena_allocator = new_decl_arena.allocator();4338 // placeholders are used before being set after the struct type gains an
45334339 // InternPool index.
4534 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);4340 const new_namespace_index = try mod.createNamespace(.{
4535 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);4341 .parent = .none,
4536 const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);4342 .ty = undefined,
4537 const ty_ty = comptime Type.initTag(.type);4343 .file_scope = file,
4538 struct_obj.* = .{4344 });
4539 .owner_decl = undefined, // set below4345 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,
4540 .fields = .{},4354 .fields = .{},
4541 .zir_index = undefined, // set below4355 .zir_index = undefined, // set below
4542 .layout = .Auto,4356 .layout = .Auto,
4543 .status = .none,4357 .status = .none,
4544 .known_non_opv = undefined,4358 .known_non_opv = undefined,
4545 .is_tuple = undefined, // set below4359 .is_tuple = undefined, // set below
4546 .namespace = .{4360 .namespace = new_namespace_index,
4547 .parent = null,4361 });
4548 .ty = struct_ty,4362 errdefer mod.destroyStruct(struct_index);
4549 .file_scope = file,4363
4550 },4364 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
4551 };4365 .index = struct_index.toOptional(),
4552 const new_decl_index = try mod.allocateNewDecl(&struct_obj.namespace, 0, null);4366 .namespace = new_namespace_index.toOptional(),
4553 const new_decl = mod.declPtr(new_decl_index);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();
4554 file.root_decl = new_decl_index.toOptional();4372 file.root_decl = new_decl_index.toOptional();
4555 struct_obj.owner_decl = new_decl_index;4373
4556 new_decl.name = try file.fullyQualifiedNameZ(gpa);4374 new_decl.name = try file.fullyQualifiedName(mod);
4557 new_decl.src_line = 0;4375 new_decl.src_line = 0;
4558 new_decl.is_pub = true;4376 new_decl.is_pub = true;
4559 new_decl.is_exported = false;4377 new_decl.is_exported = false;
4560 new_decl.has_align = false;4378 new_decl.has_align = false;
4561 new_decl.has_linksection_or_addrspace = false;4379 new_decl.has_linksection_or_addrspace = false;
4562 new_decl.ty = ty_ty;4380 new_decl.ty = Type.type;
4563 new_decl.val = struct_val;4381 new_decl.val = struct_ty.toValue();
4564 new_decl.@"align" = 0;4382 new_decl.@"align" = 0;
4565 new_decl.@"linksection" = null;4383 new_decl.@"linksection" = .none;
4566 new_decl.has_tv = true;4384 new_decl.has_tv = true;
4567 new_decl.owns_tv = true;4385 new_decl.owns_tv = true;
4568 new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive.4386 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 {...@@ -4573,6 +4391,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4573 if (file.status == .success_zir) {4391 if (file.status == .success_zir) {
4574 assert(file.zir_loaded);4392 assert(file.zir_loaded);
4575 const main_struct_inst = Zir.main_struct_inst;4393 const main_struct_inst = Zir.main_struct_inst;
4394 const struct_obj = mod.structPtr(struct_index);
4576 struct_obj.zir_index = main_struct_inst;4395 struct_obj.zir_index = main_struct_inst;
4577 const extended = file.zir.instructions.items(.data)[main_struct_inst].extended;4396 const extended = file.zir.instructions.items(.data)[main_struct_inst].extended;
4578 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);4397 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
...@@ -4582,25 +4401,34 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4582,25 +4401,34 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4582 defer sema_arena.deinit();4401 defer sema_arena.deinit();
4583 const sema_arena_allocator = sema_arena.allocator();4402 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
4585 var sema: Sema = .{4407 var sema: Sema = .{
4586 .mod = mod,4408 .mod = mod,
4587 .gpa = gpa,4409 .gpa = gpa,
4588 .arena = sema_arena_allocator,4410 .arena = sema_arena_allocator,
4589 .perm_arena = new_decl_arena_allocator,
4590 .code = file.zir,4411 .code = file.zir,
4591 .owner_decl = new_decl,4412 .owner_decl = new_decl,
4592 .owner_decl_index = new_decl_index,4413 .owner_decl_index = new_decl_index,
4593 .func = null,4414 .func = null,
4415 .func_index = .none,
4594 .fn_ret_ty = Type.void,4416 .fn_ret_ty = Type.void,
4595 .owner_func = null,4417 .owner_func = null,
4418 .owner_func_index = .none,
4419 .comptime_mutable_decls = &comptime_mutable_decls,
4596 };4420 };
4597 defer sema.deinit();4421 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);
4600 defer wip_captures.deinit();4424 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)) |_| {
4603 try wip_captures.finalize();4427 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 }
4604 new_decl.analysis = .complete;4432 new_decl.analysis = .complete;
4605 } else |err| switch (err) {4433 } else |err| switch (err) {
4606 error.OutOfMemory => return error.OutOfMemory,4434 error.OutOfMemory => return error.OutOfMemory,
...@@ -4632,8 +4460,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4632,8 +4460,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4632 } else {4460 } else {
4633 new_decl.analysis = .file_failure;4461 new_decl.analysis = .file_failure;
4634 }4462 }
4635
4636 try new_decl.finalizeNewArena(&new_decl_arena);
4637}4463}
46384464
4639/// Returns `true` if the Decl type changed.4465/// Returns `true` if the Decl type changed.
...@@ -4645,68 +4471,52 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4645,68 +4471,52 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46454471
4646 const decl = mod.declPtr(decl_index);4472 const decl = mod.declPtr(decl_index);
46474473
4648 if (decl.getFileScope().status != .success_zir) {4474 if (decl.getFileScope(mod).status != .success_zir) {
4649 return error.AnalysisFail;4475 return error.AnalysisFail;
4650 }4476 }
46514477
4652 const gpa = mod.gpa;4478 const gpa = mod.gpa;
4653 const zir = decl.getFileScope().zir;4479 const zir = decl.getFileScope(mod).zir;
4654 const zir_datas = zir.instructions.items(.data);4480 const zir_datas = zir.instructions.items(.data);
46554481
4656 decl.analysis = .in_progress;4482 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
4677 var analysis_arena = std.heap.ArenaAllocator.init(gpa);4484 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
4678 defer analysis_arena.deinit();4485 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
4681 var sema: Sema = .{4490 var sema: Sema = .{
4682 .mod = mod,4491 .mod = mod,
4683 .gpa = gpa,4492 .gpa = gpa,
4684 .arena = analysis_arena_allocator,4493 .arena = analysis_arena.allocator(),
4685 .perm_arena = decl_arena_allocator,
4686 .code = zir,4494 .code = zir,
4687 .owner_decl = decl,4495 .owner_decl = decl,
4688 .owner_decl_index = decl_index,4496 .owner_decl_index = decl_index,
4689 .func = null,4497 .func = null,
4498 .func_index = .none,
4690 .fn_ret_ty = Type.void,4499 .fn_ret_ty = Type.void,
4691 .owner_func = null,4500 .owner_func = null,
4501 .owner_func_index = .none,
4502 .comptime_mutable_decls = &comptime_mutable_decls,
4692 };4503 };
4693 defer sema.deinit();4504 defer sema.deinit();
46944505
4695 if (mod.declIsRoot(decl_index)) {4506 if (mod.declIsRoot(decl_index)) {
4696 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
4697 const main_struct_inst = Zir.main_struct_inst;4507 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);
4699 // This might not have gotten set in `semaFile` if the first time had4510 // This might not have gotten set in `semaFile` if the first time had
4700 // a ZIR failure, so we set it here in case.4511 // a ZIR failure, so we set it here in case.
4701 struct_obj.zir_index = main_struct_inst;4512 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);
4703 decl.analysis = .complete;4514 decl.analysis = .complete;
4704 decl.generation = mod.generation;4515 decl.generation = mod.generation;
4705 return false;4516 return false;
4706 }4517 }
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);
4710 defer wip_captures.deinit();4520 defer wip_captures.deinit();
47114521
4712 var block_scope: Sema.Block = .{4522 var block_scope: Sema.Block = .{
...@@ -4724,12 +4534,16 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4724,12 +4534,16 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4724 block_scope.params.deinit(gpa);4534 block_scope.params.deinit(gpa);
4725 }4535 }
47264536
4727 const zir_block_index = decl.zirBlockIndex();4537 const zir_block_index = decl.zirBlockIndex(mod);
4728 const inst_data = zir_datas[zir_block_index].pl_node;4538 const inst_data = zir_datas[zir_block_index].pl_node;
4729 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);4539 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);
4730 const body = zir.extra[extra.end..][0..extra.data.body_len];4540 const body = zir.extra[extra.end..][0..extra.data.body_len];
4731 const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;4541 const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
4732 try wip_captures.finalize();4542 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 }
4733 const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 };4547 const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 };
4734 const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 };4548 const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 };
4735 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };4549 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
...@@ -4748,16 +4562,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4748,16 +4562,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4748 decl_tv.ty.fmt(mod),4562 decl_tv.ty.fmt(mod),
4749 });4563 });
4750 }4564 }
4751 var buffer: Value.ToTypeBuffer = undefined;4565 const ty = decl_tv.val.toType();
4752 const ty = try decl_tv.val.toType(&buffer).copy(decl_arena_allocator);4566 if (ty.getNamespace(mod) == null) {
4753 if (ty.getNamespace() == null) {
4754 return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});4567 return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});
4755 }4568 }
47564569
4757 decl.ty = Type.type;4570 decl.ty = InternPool.Index.type_type.toType();
4758 decl.val = try Value.Tag.ty.create(decl_arena_allocator, ty);4571 decl.val = ty.toValue();
4759 decl.@"align" = 0;4572 decl.@"align" = 0;
4760 decl.@"linksection" = null;4573 decl.@"linksection" = .none;
4761 decl.has_tv = true;4574 decl.has_tv = true;
4762 decl.owns_tv = false;4575 decl.owns_tv = false;
4763 decl.analysis = .complete;4576 decl.analysis = .complete;
...@@ -4766,8 +4579,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4766,8 +4579,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4766 return true;4579 return true;
4767 }4580 }
47684581
4769 if (decl_tv.val.castTag(.function)) |fn_payload| {4582 if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| {
4770 const func = fn_payload.data;4583 const func = mod.funcPtr(func_index);
4771 const owns_tv = func.owner_decl == decl_index;4584 const owns_tv = func.owner_decl == decl_index;
4772 if (owns_tv) {4585 if (owns_tv) {
4773 var prev_type_has_bits = false;4586 var prev_type_has_bits = false;
...@@ -4775,31 +4588,30 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4775,31 +4588,30 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4775 var type_changed = true;4588 var type_changed = true;
47764589
4777 if (decl.has_tv) {4590 if (decl.has_tv) {
4778 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits();4591 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4779 type_changed = !decl.ty.eql(decl_tv.ty, mod);4592 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4780 if (decl.getFunction()) |prev_func| {4593 if (decl.getOwnedFunction(mod)) |prev_func| {
4781 prev_is_inline = prev_func.state == .inline_only;4594 prev_is_inline = prev_func.state == .inline_only;
4782 }4595 }
4783 }4596 }
4784 decl.clearValues(mod);4597 decl.clearValues(mod);
47854598
4786 decl.ty = try decl_tv.ty.copy(decl_arena_allocator);4599 decl.ty = decl_tv.ty;
4787 decl.val = try decl_tv.val.copy(decl_arena_allocator);4600 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4788 // linksection, align, and addrspace were already set by Sema4601 // linksection, align, and addrspace were already set by Sema
4789 decl.has_tv = true;4602 decl.has_tv = true;
4790 decl.owns_tv = owns_tv;4603 decl.owns_tv = owns_tv;
4791 decl.analysis = .complete;4604 decl.analysis = .complete;
4792 decl.generation = mod.generation;4605 decl.generation = mod.generation;
47934606
4794 const is_inline = decl.ty.fnCallingConvention() == .Inline;4607 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
4795 if (decl.is_exported) {4608 if (decl.is_exported) {
4796 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };4609 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
4797 if (is_inline) {4610 if (is_inline) {
4798 return sema.fail(&block_scope, export_src, "export of inline function", .{});4611 return sema.fail(&block_scope, export_src, "export of inline function", .{});
4799 }4612 }
4800 // The scope needs to have the decl in it.4613 // The scope needs to have the decl in it.
4801 const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) };4614 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4802 try sema.analyzeExport(&block_scope, export_src, options, decl_index);
4803 }4615 }
4804 return type_changed or is_inline != prev_is_inline;4616 return type_changed or is_inline != prev_is_inline;
4805 }4617 }
...@@ -4813,64 +4625,57 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4813,64 +4625,57 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4813 decl.owns_tv = false;4625 decl.owns_tv = false;
4814 var queue_linker_work = false;4626 var queue_linker_work = false;
4815 var is_extern = false;4627 var is_extern = false;
4816 switch (decl_tv.val.tag()) {4628 switch (decl_tv.val.toIntern()) {
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
4836 .generic_poison => unreachable,4629 .generic_poison => unreachable,
4837 .unreachable_value => unreachable,4630 .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 => {4643 .func => {},
4842 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });4644
4843 queue_linker_work = true;4645 else => {
4646 queue_linker_work = true;
4647 },
4844 },4648 },
4845 }4649 }
48464650
4847 decl.ty = try decl_tv.ty.copy(decl_arena_allocator);4651 decl.ty = decl_tv.ty;
4848 decl.val = try decl_tv.val.copy(decl_arena_allocator);4652 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4849 decl.@"align" = blk: {4653 decl.@"align" = blk: {
4850 const align_ref = decl.zirAlignRef();4654 const align_ref = decl.zirAlignRef(mod);
4851 if (align_ref == .none) break :blk 0;4655 if (align_ref == .none) break :blk 0;
4852 break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);4656 break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);
4853 };4657 };
4854 decl.@"linksection" = blk: {4658 decl.@"linksection" = blk: {
4855 const linksection_ref = decl.zirLinksectionRef();4659 const linksection_ref = decl.zirLinksectionRef(mod);
4856 if (linksection_ref == .none) break :blk null;4660 if (linksection_ref == .none) break :blk .none;
4857 const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime-known");4661 const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime-known");
4858 if (mem.indexOfScalar(u8, bytes, 0) != null) {4662 if (mem.indexOfScalar(u8, bytes, 0) != null) {
4859 return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});4663 return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
4860 } else if (bytes.len == 0) {4664 } else if (bytes.len == 0) {
4861 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});4665 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
4862 }4666 }
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();
4864 };4669 };
4865 decl.@"addrspace" = blk: {4670 decl.@"addrspace" = blk: {
4866 const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) {4671 const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
4867 .function, .extern_fn => .function,
4868 .variable => .variable,4672 .variable => .variable,
4673 .extern_func, .func => .function,
4869 else => .constant,4674 else => .constant,
4870 };4675 };
48714676
4872 const target = sema.mod.getTarget();4677 const target = sema.mod.getTarget();
4873 break :blk switch (decl.zirAddrspaceRef()) {4678 break :blk switch (decl.zirAddrspaceRef(mod)) {
4874 .none => switch (addrspace_ctx) {4679 .none => switch (addrspace_ctx) {
4875 .function => target_util.defaultAddressSpace(target, .function),4680 .function => target_util.defaultAddressSpace(target, .function),
4876 .variable => target_util.defaultAddressSpace(target, .global_mutable),4681 .variable => target_util.defaultAddressSpace(target, .global_mutable),
...@@ -4888,7 +4693,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4888,7 +4693,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4888 (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty));4693 (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty));
48894694
4890 if (has_runtime_bits) {4695 if (has_runtime_bits) {
4891 log.debug("queue linker work for {*} ({s})", .{ decl, decl.name });
48924696
4893 // Needed for codegen_decl which will call updateDecl and then the4697 // Needed for codegen_decl which will call updateDecl and then the
4894 // codegen backend wants full access to the Decl Type.4698 // codegen backend wants full access to the Decl Type.
...@@ -4904,8 +4708,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4904,8 +4708,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4904 if (decl.is_exported) {4708 if (decl.is_exported) {
4905 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };4709 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
4906 // The scope needs to have the decl in it.4710 // The scope needs to have the decl in it.
4907 const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) };4711 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4908 try sema.analyzeExport(&block_scope, export_src, options, decl_index);
4909 }4712 }
49104713
4911 return type_changed;4714 return type_changed;
...@@ -4930,10 +4733,6 @@ pub fn declareDeclDependencyType(mod: *Module, depender_index: Decl.Index, depen...@@ -4930,10 +4733,6 @@ pub fn declareDeclDependencyType(mod: *Module, depender_index: Decl.Index, depen
4930 }4733 }
4931 }4734 }
49324735
4933 log.debug("{*} ({s}) depends on {*} ({s})", .{
4934 depender, depender.name, dependee, dependee.name,
4935 });
4936
4937 if (dependee.deletion_flag) {4736 if (dependee.deletion_flag) {
4938 dependee.deletion_flag = false;4737 dependee.deletion_flag = false;
4939 assert(mod.deletion_set.swapRemove(dependee_index));4738 assert(mod.deletion_set.swapRemove(dependee_index));
...@@ -5222,7 +5021,7 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {...@@ -5222,7 +5021,7 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
52225021
5223pub fn scanNamespace(5022pub fn scanNamespace(
5224 mod: *Module,5023 mod: *Module,
5225 namespace: *Namespace,5024 namespace_index: Namespace.Index,
5226 extra_start: usize,5025 extra_start: usize,
5227 decls_len: u32,5026 decls_len: u32,
5228 parent_decl: *Decl,5027 parent_decl: *Decl,
...@@ -5231,6 +5030,7 @@ pub fn scanNamespace(...@@ -5231,6 +5030,7 @@ pub fn scanNamespace(
5231 defer tracy.end();5030 defer tracy.end();
52325031
5233 const gpa = mod.gpa;5032 const gpa = mod.gpa;
5033 const namespace = mod.namespacePtr(namespace_index);
5234 const zir = namespace.file_scope.zir;5034 const zir = namespace.file_scope.zir;
52355035
5236 try mod.comp.work_queue.ensureUnusedCapacity(decls_len);5036 try mod.comp.work_queue.ensureUnusedCapacity(decls_len);
...@@ -5243,7 +5043,7 @@ pub fn scanNamespace(...@@ -5243,7 +5043,7 @@ pub fn scanNamespace(
5243 var decl_i: u32 = 0;5043 var decl_i: u32 = 0;
5244 var scan_decl_iter: ScanDeclIter = .{5044 var scan_decl_iter: ScanDeclIter = .{
5245 .module = mod,5045 .module = mod,
5246 .namespace = namespace,5046 .namespace_index = namespace_index,
5247 .parent_decl = parent_decl,5047 .parent_decl = parent_decl,
5248 };5048 };
5249 while (decl_i < decls_len) : (decl_i += 1) {5049 while (decl_i < decls_len) : (decl_i += 1) {
...@@ -5266,7 +5066,7 @@ pub fn scanNamespace(...@@ -5266,7 +5066,7 @@ pub fn scanNamespace(
52665066
5267const ScanDeclIter = struct {5067const ScanDeclIter = struct {
5268 module: *Module,5068 module: *Module,
5269 namespace: *Namespace,5069 namespace_index: Namespace.Index,
5270 parent_decl: *Decl,5070 parent_decl: *Decl,
5271 usingnamespace_index: usize = 0,5071 usingnamespace_index: usize = 0,
5272 comptime_index: usize = 0,5072 comptime_index: usize = 0,
...@@ -5278,9 +5078,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5278,9 +5078,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5278 defer tracy.end();5078 defer tracy.end();
52795079
5280 const mod = iter.module;5080 const mod = iter.module;
5281 const namespace = iter.namespace;5081 const namespace_index = iter.namespace_index;
5082 const namespace = mod.namespacePtr(namespace_index);
5282 const gpa = mod.gpa;5083 const gpa = mod.gpa;
5283 const zir = namespace.file_scope.zir;5084 const zir = namespace.file_scope.zir;
5085 const ip = &mod.intern_pool;
52845086
5285 // zig fmt: off5087 // zig fmt: off
5286 const is_pub = (flags & 0b0001) != 0;5088 const is_pub = (flags & 0b0001) != 0;
...@@ -5300,31 +5102,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5300,31 +5102,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5300 // Every Decl needs a name.5102 // Every Decl needs a name.
5301 var is_named_test = false;5103 var is_named_test = false;
5302 var kind: Decl.Kind = .named;5104 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) {
5304 0 => name: {5106 0 => name: {
5305 if (export_bit) {5107 if (export_bit) {
5306 const i = iter.usingnamespace_index;5108 const i = iter.usingnamespace_index;
5307 iter.usingnamespace_index += 1;5109 iter.usingnamespace_index += 1;
5308 kind = .@"usingnamespace";5110 kind = .@"usingnamespace";
5309 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});5111 break :name try ip.getOrPutStringFmt(gpa, "usingnamespace_{d}", .{i});
5310 } else {5112 } else {
5311 const i = iter.comptime_index;5113 const i = iter.comptime_index;
5312 iter.comptime_index += 1;5114 iter.comptime_index += 1;
5313 kind = .@"comptime";5115 kind = .@"comptime";
5314 break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});5116 break :name try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i});
5315 }5117 }
5316 },5118 },
5317 1 => name: {5119 1 => name: {
5318 const i = iter.unnamed_test_index;5120 const i = iter.unnamed_test_index;
5319 iter.unnamed_test_index += 1;5121 iter.unnamed_test_index += 1;
5320 kind = .@"test";5122 kind = .@"test";
5321 break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});5123 break :name try ip.getOrPutStringFmt(gpa, "test_{d}", .{i});
5322 },5124 },
5323 2 => name: {5125 2 => name: {
5324 is_named_test = true;5126 is_named_test = true;
5325 const test_name = zir.nullTerminatedString(decl_doccomment_index);5127 const test_name = zir.nullTerminatedString(decl_doccomment_index);
5326 kind = .@"test";5128 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});
5328 },5130 },
5329 else => name: {5131 else => name: {
5330 const raw_name = zir.nullTerminatedString(decl_name_index);5132 const raw_name = zir.nullTerminatedString(decl_name_index);
...@@ -5332,14 +5134,12 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5332,14 +5134,12 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5332 is_named_test = true;5134 is_named_test = true;
5333 const test_name = zir.nullTerminatedString(decl_name_index + 1);5135 const test_name = zir.nullTerminatedString(decl_name_index + 1);
5334 kind = .@"test";5136 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});
5336 } else {5138 } else {
5337 break :name try gpa.dupeZ(u8, raw_name);5139 break :name try ip.getOrPutString(gpa, raw_name);
5338 }5140 }
5339 },5141 },
5340 };5142 };
5341 var must_free_decl_name = true;
5342 defer if (must_free_decl_name) gpa.free(decl_name);
53435143
5344 const is_exported = export_bit and decl_name_index != 0;5144 const is_exported = export_bit and decl_name_index != 0;
5345 if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);5145 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...@@ -5347,21 +5147,19 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5347 // We create a Decl for it regardless of analysis status.5147 // We create a Decl for it regardless of analysis status.
5348 const gop = try namespace.decls.getOrPutContextAdapted(5148 const gop = try namespace.decls.getOrPutContextAdapted(
5349 gpa,5149 gpa,
5350 @as([]const u8, mem.sliceTo(decl_name, 0)),5150 decl_name,
5351 DeclAdapter{ .mod = mod },5151 DeclAdapter{ .mod = mod },
5352 Namespace.DeclContext{ .module = mod },5152 Namespace.DeclContext{ .module = mod },
5353 );5153 );
5354 const comp = mod.comp;5154 const comp = mod.comp;
5355 if (!gop.found_existing) {5155 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);
5357 const new_decl = mod.declPtr(new_decl_index);5157 const new_decl = mod.declPtr(new_decl_index);
5358 new_decl.kind = kind;5158 new_decl.kind = kind;
5359 new_decl.name = decl_name;5159 new_decl.name = decl_name;
5360 must_free_decl_name = false;
5361 if (kind == .@"usingnamespace") {5160 if (kind == .@"usingnamespace") {
5362 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);5161 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);
5363 }5162 }
5364 log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace });
5365 new_decl.src_line = line;5163 new_decl.src_line = line;
5366 gop.key_ptr.* = new_decl_index;5164 gop.key_ptr.* = new_decl_index;
5367 // Exported decls, comptime decls, usingnamespace decls, and5165 // Exported decls, comptime decls, usingnamespace decls, and
...@@ -5382,7 +5180,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5382,7 +5180,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5382 if (!comp.bin_file.options.is_test) break :blk false;5180 if (!comp.bin_file.options.is_test) break :blk false;
5383 if (decl_pkg != mod.main_pkg) break :blk false;5181 if (decl_pkg != mod.main_pkg) break :blk false;
5384 if (comp.test_filter) |test_filter| {5182 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) {
5386 break :blk false;5184 break :blk false;
5387 }5185 }
5388 }5186 }
...@@ -5405,16 +5203,13 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5405,16 +5203,13 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5405 const decl = mod.declPtr(decl_index);5203 const decl = mod.declPtr(decl_index);
5406 if (kind == .@"test") {5204 if (kind == .@"test") {
5407 const src_loc = SrcLoc{5205 const src_loc = SrcLoc{
5408 .file_scope = decl.getFileScope(),5206 .file_scope = decl.getFileScope(mod),
5409 .parent_decl_node = decl.src_node,5207 .parent_decl_node = decl.src_node,
5410 .lazy = .{ .token_offset = 1 },5208 .lazy = .{ .token_offset = 1 },
5411 };5209 };
5412 const msg = try ErrorMsg.create(5210 const msg = try ErrorMsg.create(gpa, src_loc, "duplicate test name: {}", .{
5413 gpa,5211 decl_name.fmt(&mod.intern_pool),
5414 src_loc,5212 });
5415 "duplicate test name: {s}",
5416 .{decl_name},
5417 );
5418 errdefer msg.destroy(gpa);5213 errdefer msg.destroy(gpa);
5419 try mod.failed_decls.putNoClobber(gpa, decl_index, msg);5214 try mod.failed_decls.putNoClobber(gpa, decl_index, msg);
5420 const other_src_loc = SrcLoc{5215 const other_src_loc = SrcLoc{
...@@ -5424,7 +5219,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5424,7 +5219,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5424 };5219 };
5425 try mod.errNoteNonLazy(other_src_loc, msg, "other test here", .{});5220 try mod.errNoteNonLazy(other_src_loc, msg, "other test here", .{});
5426 }5221 }
5427 log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl.name, namespace });
5428 // Update the AST node of the decl; even if its contents are unchanged, it may5222 // Update the AST node of the decl; even if its contents are unchanged, it may
5429 // have been re-ordered.5223 // have been re-ordered.
5430 decl.src_node = decl_node;5224 decl.src_node = decl_node;
...@@ -5436,7 +5230,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5436,7 +5230,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5436 decl.has_align = has_align;5230 decl.has_align = has_align;
5437 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;5231 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
5438 decl.zir_decl_index = @intCast(u32, decl_sub_index);5232 decl.zir_decl_index = @intCast(u32, decl_sub_index);
5439 if (decl.getFunction()) |_| {5233 if (decl.getOwnedFunctionIndex(mod) != .none) {
5440 switch (comp.bin_file.tag) {5234 switch (comp.bin_file.tag) {
5441 .coff, .elf, .macho, .plan9 => {5235 .coff, .elf, .macho, .plan9 => {
5442 // TODO Look into detecting when this would be unnecessary by storing enough state5236 // TODO Look into detecting when this would be unnecessary by storing enough state
...@@ -5458,7 +5252,6 @@ pub fn clearDecl(...@@ -5458,7 +5252,6 @@ pub fn clearDecl(
5458 defer tracy.end();5252 defer tracy.end();
54595253
5460 const decl = mod.declPtr(decl_index);5254 const decl = mod.declPtr(decl_index);
5461 log.debug("clearing {*} ({s})", .{ decl, decl.name });
54625255
5463 const gpa = mod.gpa;5256 const gpa = mod.gpa;
5464 try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count());5257 try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count());
...@@ -5473,9 +5266,6 @@ pub fn clearDecl(...@@ -5473,9 +5266,6 @@ pub fn clearDecl(
5473 const dep = mod.declPtr(dep_index);5266 const dep = mod.declPtr(dep_index);
5474 dep.removeDependant(decl_index);5267 dep.removeDependant(decl_index);
5475 if (dep.dependants.count() == 0 and !dep.deletion_flag) {5268 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 });
5479 // We don't recursively perform a deletion here, because during the update,5269 // We don't recursively perform a deletion here, because during the update,
5480 // another reference to it may turn up.5270 // another reference to it may turn up.
5481 dep.deletion_flag = true;5271 dep.deletion_flag = true;
...@@ -5510,10 +5300,10 @@ pub fn clearDecl(...@@ -5510,10 +5300,10 @@ pub fn clearDecl(
5510 try mod.deleteDeclExports(decl_index);5300 try mod.deleteDeclExports(decl_index);
55115301
5512 if (decl.has_tv) {5302 if (decl.has_tv) {
5513 if (decl.ty.isFnOrHasRuntimeBits()) {5303 if (decl.ty.isFnOrHasRuntimeBits(mod)) {
5514 mod.comp.bin_file.freeDecl(decl_index);5304 mod.comp.bin_file.freeDecl(decl_index);
5515 }5305 }
5516 if (decl.getInnerNamespace()) |namespace| {5306 if (decl.getOwnedInnerNamespace(mod)) |namespace| {
5517 try namespace.deleteAllDecls(mod, outdated_decls);5307 try namespace.deleteAllDecls(mod, outdated_decls);
5518 }5308 }
5519 }5309 }
...@@ -5530,10 +5320,9 @@ pub fn clearDecl(...@@ -5530,10 +5320,9 @@ pub fn clearDecl(
5530/// This function is exclusively called for anonymous decls.5320/// This function is exclusively called for anonymous decls.
5531pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {5321pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
5532 const decl = mod.declPtr(decl_index);5322 const decl = mod.declPtr(decl_index);
5533 log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name });
55345323
5535 assert(!mod.declIsRoot(decl_index));5324 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
5538 const dependants = decl.dependants.keys();5327 const dependants = decl.dependants.keys();
5539 for (dependants) |dep| {5328 for (dependants) |dep| {
...@@ -5558,10 +5347,9 @@ fn markDeclForDeletion(mod: *Module, decl_index: Decl.Index) !void {...@@ -5558,10 +5347,9 @@ fn markDeclForDeletion(mod: *Module, decl_index: Decl.Index) !void {
5558/// If other decls depend on this decl, they must be aborted first.5347/// If other decls depend on this decl, they must be aborted first.
5559pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {5348pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
5560 const decl = mod.declPtr(decl_index);5349 const decl = mod.declPtr(decl_index);
5561 log.debug("abortAnonDecl {*} ({s})", .{ decl, decl.name });
55625350
5563 assert(!mod.declIsRoot(decl_index));5351 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
5566 // An aborted decl must not have dependants -- they must have5354 // An aborted decl must not have dependants -- they must have
5567 // been aborted first and removed from this list.5355 // been aborted first and removed from this list.
...@@ -5575,6 +5363,17 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -5575,6 +5363,17 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
5575 mod.destroyDecl(decl_index);5363 mod.destroyDecl(decl_index);
5576}5364}
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
5578/// Delete all the Export objects that are caused by this Decl. Re-analysis of5377/// Delete all the Export objects that are caused by this Decl. Re-analysis of
5579/// this Decl will cause them to be re-created (or not).5378/// this Decl will cause them to be re-created (or not).
5580fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {5379fn 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...@@ -5600,51 +5399,53 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
5600 }5399 }
5601 }5400 }
5602 if (mod.comp.bin_file.cast(link.File.Elf)) |elf| {5401 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);
5604 }5403 }
5605 if (mod.comp.bin_file.cast(link.File.MachO)) |macho| {5404 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);
5607 }5406 }
5608 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {5407 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {
5609 wasm.deleteDeclExport(decl_index);5408 wasm.deleteDeclExport(decl_index);
5610 }5409 }
5611 if (mod.comp.bin_file.cast(link.File.Coff)) |coff| {5410 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);
5613 }5412 }
5614 if (mod.failed_exports.fetchSwapRemove(exp)) |failed_kv| {5413 if (mod.failed_exports.fetchSwapRemove(exp)) |failed_kv| {
5615 failed_kv.value.destroy(mod.gpa);5414 failed_kv.value.destroy(mod.gpa);
5616 }5415 }
5617 mod.gpa.free(exp.options.name);
5618 mod.gpa.destroy(exp);5416 mod.gpa.destroy(exp);
5619 }5417 }
5620 export_owners.deinit(mod.gpa);5418 export_owners.deinit(mod.gpa);
5621}5419}
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 {
5624 const tracy = trace(@src());5422 const tracy = trace(@src());
5625 defer tracy.end();5423 defer tracy.end();
56265424
5627 const gpa = mod.gpa;5425 const gpa = mod.gpa;
5426 const func = mod.funcPtr(func_index);
5628 const decl_index = func.owner_decl;5427 const decl_index = func.owner_decl;
5629 const decl = mod.declPtr(decl_index);5428 const decl = mod.declPtr(decl_index);
56305429
5631 // Use the Decl's arena for captured values.5430 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
5632 var decl_arena: std.heap.ArenaAllocator = undefined;5431 defer comptime_mutable_decls.deinit();
5633 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);5432
5634 defer decl.value_arena.?.release(&decl_arena);5433 const fn_ty = decl.ty;
56355434
5636 var sema: Sema = .{5435 var sema: Sema = .{
5637 .mod = mod,5436 .mod = mod,
5638 .gpa = gpa,5437 .gpa = gpa,
5639 .arena = arena,5438 .arena = arena,
5640 .perm_arena = decl_arena_allocator,5439 .code = decl.getFileScope(mod).zir,
5641 .code = decl.getFileScope().zir,
5642 .owner_decl = decl,5440 .owner_decl = decl,
5643 .owner_decl_index = decl_index,5441 .owner_decl_index = decl_index,
5644 .func = func,5442 .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(),
5646 .owner_func = func,5445 .owner_func = func,
5446 .owner_func_index = func_index.toOptional(),
5647 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),5447 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5448 .comptime_mutable_decls = &comptime_mutable_decls,
5648 };5449 };
5649 defer sema.deinit();5450 defer sema.deinit();
56505451
...@@ -5656,7 +5457,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5656,7 +5457,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5656 try sema.air_extra.ensureTotalCapacity(gpa, reserved_count);5457 try sema.air_extra.ensureTotalCapacity(gpa, reserved_count);
5657 sema.air_extra.items.len += reserved_count;5458 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);
5660 defer wip_captures.deinit();5461 defer wip_captures.deinit();
56615462
5662 var inner_block: Sema.Block = .{5463 var inner_block: Sema.Block = .{
...@@ -5680,9 +5481,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5680,9 +5481,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5680 // This could be a generic function instantiation, however, in which case we need to5481 // This could be a generic function instantiation, however, in which case we need to
5681 // map the comptime parameters to constant values and only emit arg AIR instructions5482 // map the comptime parameters to constant values and only emit arg AIR instructions
5682 // for the runtime ones.5483 // for the runtime ones.
5683 const fn_ty = decl.ty;5484 const runtime_params_len = @intCast(u32, mod.typeToFunc(fn_ty).?.param_types.len);
5684 const fn_ty_info = fn_ty.fnInfo();
5685 const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);
5686 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);5485 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
5687 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`5486 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
5688 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);5487 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 {...@@ -5697,9 +5496,9 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5697 const param_ty = if (func.comptime_args) |comptime_args| t: {5496 const param_ty = if (func.comptime_args) |comptime_args| t: {
5698 const arg_tv = comptime_args[total_param_index];5497 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())
5701 arg_tv.val5500 arg_tv.val
5702 else if (arg_tv.ty.onePossibleValue()) |opv|5501 else if (try arg_tv.ty.onePossibleValue(mod)) |opv|
5703 opv5502 opv
5704 else5503 else
5705 break :t arg_tv.ty;5504 break :t arg_tv.ty;
...@@ -5708,7 +5507,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5708,7 +5507,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5708 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);5507 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5709 total_param_index += 1;5508 total_param_index += 1;
5710 continue;5509 continue;
5711 } else fn_ty_info.param_types[runtime_param_index];5510 } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
57125511
5713 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {5512 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
5714 error.NeededSourceLocation => unreachable,5513 error.NeededSourceLocation => unreachable,
...@@ -5740,7 +5539,6 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5740,7 +5539,6 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5740 }5539 }
57415540
5742 func.state = .in_progress;5541 func.state = .in_progress;
5743 log.debug("set {s} to in_progress", .{decl.name});
57445542
5745 const last_arg_index = inner_block.instructions.items.len;5543 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 {...@@ -5765,7 +5563,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5765 // is unused so it just has to be a no-op.5563 // is unused so it just has to be a no-op.
5766 sema.air_instructions.set(ptr_inst.*, .{5564 sema.air_instructions.set(ptr_inst.*, .{
5767 .tag = .alloc,5565 .tag = .alloc,
5768 .data = .{ .ty = Type.initTag(.single_const_pointer_to_comptime_int) },5566 .data = .{ .ty = Type.single_const_pointer_to_comptime_int },
5769 });5567 });
5770 }5568 }
5771 }5569 }
...@@ -5773,7 +5571,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5773,7 +5571,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5773 // If we don't get an error return trace from a caller, create our own.5571 // If we don't get an error return trace from a caller, create our own.
5774 if (func.calls_or_awaits_errorable_fn and5572 if (func.calls_or_awaits_errorable_fn and
5775 mod.comp.bin_file.options.error_return_tracing and5573 mod.comp.bin_file.options.error_return_tracing and
5776 !sema.fn_ret_ty.isError())5574 !sema.fn_ret_ty.isError(mod))
5777 {5575 {
5778 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {5576 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
5779 // TODO make these unreachable instead of @panic5577 // TODO make these unreachable instead of @panic
...@@ -5786,6 +5584,10 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5786,6 +5584,10 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5786 }5584 }
57875585
5788 try wip_captures.finalize();5586 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
5790 // Copy the block into place and mark that as the main block.5592 // Copy the block into place and mark that as the main block.
5791 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +5593 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 {...@@ -5797,14 +5599,13 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5797 sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = main_block_index;5599 sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = main_block_index;
57985600
5799 func.state = .success;5601 func.state = .success;
5800 log.debug("set {s} to success", .{decl.name});
58015602
5802 // Finally we must resolve the return type and parameter types so that backends5603 // Finally we must resolve the return type and parameter types so that backends
5803 // have full access to type information.5604 // have full access to type information.
5804 // Crucially, this happens *after* we set the function state to success above,5605 // Crucially, this happens *after* we set the function state to success above,
5805 // so that dependencies on the function body will now be satisfied rather than5606 // so that dependencies on the function body will now be satisfied rather than
5806 // result in circular dependency errors.5607 // result in circular dependency errors.
5807 sema.resolveFnTypes(fn_ty_info) catch |err| switch (err) {5608 sema.resolveFnTypes(fn_ty) catch |err| switch (err) {
5808 error.NeededSourceLocation => unreachable,5609 error.NeededSourceLocation => unreachable,
5809 error.GenericPoison => unreachable,5610 error.GenericPoison => unreachable,
5810 error.ComptimeReturn => unreachable,5611 error.ComptimeReturn => unreachable,
...@@ -5820,9 +5621,8 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5820,9 +5621,8 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
58205621
5821 // Similarly, resolve any queued up types that were requested to be resolved for5622 // Similarly, resolve any queued up types that were requested to be resolved for
5822 // the backends.5623 // the backends.
5823 for (sema.types_to_resolve.items) |inst_ref| {5624 for (sema.types_to_resolve.keys()) |ty| {
5824 const ty = sema.getTmpAir().getRefType(inst_ref);5625 sema.resolveTypeFully(ty.toType()) catch |err| switch (err) {
5825 sema.resolveTypeFully(ty) catch |err| switch (err) {
5826 error.NeededSourceLocation => unreachable,5626 error.NeededSourceLocation => unreachable,
5827 error.GenericPoison => unreachable,5627 error.GenericPoison => unreachable,
5828 error.ComptimeReturn => unreachable,5628 error.ComptimeReturn => unreachable,
...@@ -5840,13 +5640,11 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5840,13 +5640,11 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5840 return Air{5640 return Air{
5841 .instructions = sema.air_instructions.toOwnedSlice(),5641 .instructions = sema.air_instructions.toOwnedSlice(),
5842 .extra = try sema.air_extra.toOwnedSlice(gpa),5642 .extra = try sema.air_extra.toOwnedSlice(gpa),
5843 .values = try sema.air_values.toOwnedSlice(gpa),
5844 };5643 };
5845}5644}
58465645
5847fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {5646fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5848 const decl = mod.declPtr(decl_index);5647 const decl = mod.declPtr(decl_index);
5849 log.debug("mark outdated {*} ({s})", .{ decl, decl.name });
5850 try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl_index });5648 try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl_index });
5851 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {5649 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
5852 kv.value.destroy(mod.gpa);5650 kv.value.destroy(mod.gpa);
...@@ -5854,11 +5652,8 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5854,11 +5652,8 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5854 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {5652 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
5855 for (kv.value) |err| err.deinit(mod.gpa);5653 for (kv.value) |err| err.deinit(mod.gpa);
5856 }5654 }
5857 if (decl.has_tv and decl.owns_tv) {5655 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
5858 if (decl.val.castTag(.function)) |payload| {5656 _ = mod.align_stack_fns.remove(func);
5859 const func = payload.data;
5860 _ = mod.align_stack_fns.remove(func);
5861 }
5862 }5657 }
5863 if (mod.emit_h) |emit_h| {5658 if (mod.emit_h) |emit_h| {
5864 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {5659 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
...@@ -5869,9 +5664,51 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5869,9 +5664,51 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5869 decl.analysis = .outdated;5664 decl.analysis = .outdated;
5870}5665}
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
5872pub fn allocateNewDecl(5709pub fn allocateNewDecl(
5873 mod: *Module,5710 mod: *Module,
5874 namespace: *Namespace,5711 namespace: Namespace.Index,
5875 src_node: Ast.Node.Index,5712 src_node: Ast.Node.Index,
5876 src_scope: ?*CaptureScope,5713 src_scope: ?*CaptureScope,
5877) !Decl.Index {5714) !Decl.Index {
...@@ -5896,6 +5733,7 @@ pub fn allocateNewDecl(...@@ -5896,6 +5733,7 @@ pub fn allocateNewDecl(
5896 };5733 };
5897 };5734 };
58985735
5736 if (src_scope) |scope| scope.incRef();
5899 decl_and_index.new_decl.* = .{5737 decl_and_index.new_decl.* = .{
5900 .name = undefined,5738 .name = undefined,
5901 .src_namespace = namespace,5739 .src_namespace = namespace,
...@@ -5906,7 +5744,7 @@ pub fn allocateNewDecl(...@@ -5906,7 +5744,7 @@ pub fn allocateNewDecl(
5906 .ty = undefined,5744 .ty = undefined,
5907 .val = undefined,5745 .val = undefined,
5908 .@"align" = undefined,5746 .@"align" = undefined,
5909 .@"linksection" = undefined,5747 .@"linksection" = .none,
5910 .@"addrspace" = .generic,5748 .@"addrspace" = .generic,
5911 .analysis = .unreferenced,5749 .analysis = .unreferenced,
5912 .deletion_flag = false,5750 .deletion_flag = false,
...@@ -5924,25 +5762,20 @@ pub fn allocateNewDecl(...@@ -5924,25 +5762,20 @@ pub fn allocateNewDecl(
5924 return decl_and_index.decl_index;5762 return decl_and_index.decl_index;
5925}5763}
59265764
5927/// Get error value for error tag `name`.5765pub fn getErrorValue(
5928pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).KV {5766 mod: *Module,
5767 name: InternPool.NullTerminatedString,
5768) Allocator.Error!ErrorInt {
5929 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);5769 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
5930 if (gop.found_existing) {5770 return @intCast(ErrorInt, gop.index);
5931 return std.StringHashMapUnmanaged(ErrorInt).KV{5771}
5932 .key = gop.key_ptr.*,
5933 .value = gop.value_ptr.*,
5934 };
5935 }
59365772
5937 errdefer assert(mod.global_error_set.remove(name));5773pub fn getErrorValueFromSlice(
5938 try mod.error_name_list.ensureUnusedCapacity(mod.gpa, 1);5774 mod: *Module,
5939 gop.key_ptr.* = try mod.gpa.dupe(u8, name);5775 name: []const u8,
5940 gop.value_ptr.* = @intCast(ErrorInt, mod.error_name_list.items.len);5776) Allocator.Error!ErrorInt {
5941 mod.error_name_list.appendAssumeCapacity(gop.key_ptr.*);5777 const interned_name = try mod.intern_pool.getOrPutString(mod.gpa, name);
5942 return std.StringHashMapUnmanaged(ErrorInt).KV{5778 return getErrorValue(mod, interned_name);
5943 .key = gop.key_ptr.*,
5944 .value = gop.value_ptr.*,
5945 };
5946}5779}
59475780
5948pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {5781pub 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...@@ -5953,29 +5786,28 @@ pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedV
5953pub fn createAnonymousDeclFromDecl(5786pub fn createAnonymousDeclFromDecl(
5954 mod: *Module,5787 mod: *Module,
5955 src_decl: *Decl,5788 src_decl: *Decl,
5956 namespace: *Namespace,5789 namespace: Namespace.Index,
5957 src_scope: ?*CaptureScope,5790 src_scope: ?*CaptureScope,
5958 tv: TypedValue,5791 tv: TypedValue,
5959) !Decl.Index {5792) !Decl.Index {
5960 const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope);5793 const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope);
5961 errdefer mod.destroyDecl(new_decl_index);5794 errdefer mod.destroyDecl(new_decl_index);
5962 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{5795 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{
5963 src_decl.name, @enumToInt(new_decl_index),5796 src_decl.name.fmt(&mod.intern_pool), @enumToInt(new_decl_index),
5964 });5797 });
5965 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name);5798 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name);
5966 return new_decl_index;5799 return new_decl_index;
5967}5800}
59685801
5969/// Takes ownership of `name` even if it returns an error.
5970pub fn initNewAnonDecl(5802pub fn initNewAnonDecl(
5971 mod: *Module,5803 mod: *Module,
5972 new_decl_index: Decl.Index,5804 new_decl_index: Decl.Index,
5973 src_line: u32,5805 src_line: u32,
5974 namespace: *Namespace,5806 namespace: Namespace.Index,
5975 typed_value: TypedValue,5807 typed_value: TypedValue,
5976 name: [:0]u8,5808 name: InternPool.NullTerminatedString,
5977) !void {5809) Allocator.Error!void {
5978 errdefer mod.gpa.free(name);5810 assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern()));
59795811
5980 const new_decl = mod.declPtr(new_decl_index);5812 const new_decl = mod.declPtr(new_decl_index);
59815813
...@@ -5984,34 +5816,12 @@ pub fn initNewAnonDecl(...@@ -5984,34 +5816,12 @@ pub fn initNewAnonDecl(
5984 new_decl.ty = typed_value.ty;5816 new_decl.ty = typed_value.ty;
5985 new_decl.val = typed_value.val;5817 new_decl.val = typed_value.val;
5986 new_decl.@"align" = 0;5818 new_decl.@"align" = 0;
5987 new_decl.@"linksection" = null;5819 new_decl.@"linksection" = .none;
5988 new_decl.has_tv = true;5820 new_decl.has_tv = true;
5989 new_decl.analysis = .complete;5821 new_decl.analysis = .complete;
5990 new_decl.generation = mod.generation;5822 new_decl.generation = mod.generation;
59915823
5992 try namespace.anon_decls.putNoClobber(mod.gpa, new_decl_index, {});5824 try mod.namespacePtr(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);
6015}5825}
60165826
6017pub fn errNoteNonLazy(5827pub fn errNoteNonLazy(
...@@ -6073,16 +5883,17 @@ pub const SwitchProngSrc = union(enum) {...@@ -6073,16 +5883,17 @@ pub const SwitchProngSrc = union(enum) {
6073 /// the LazySrcLoc in order to emit a compile error.5883 /// the LazySrcLoc in order to emit a compile error.
6074 pub fn resolve(5884 pub fn resolve(
6075 prong_src: SwitchProngSrc,5885 prong_src: SwitchProngSrc,
6076 gpa: Allocator,5886 mod: *Module,
6077 decl: *Decl,5887 decl: *Decl,
6078 switch_node_offset: i32,5888 switch_node_offset: i32,
6079 range_expand: RangeExpand,5889 range_expand: RangeExpand,
6080 ) LazySrcLoc {5890 ) LazySrcLoc {
6081 @setCold(true);5891 @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| {
6083 // In this case we emit a warning + a less precise source location.5894 // In this case we emit a warning + a less precise source location.
6084 log.warn("unable to load {s}: {s}", .{5895 log.warn("unable to load {s}: {s}", .{
6085 decl.getFileScope().sub_file_path, @errorName(err),5896 decl.getFileScope(mod).sub_file_path, @errorName(err),
6086 });5897 });
6087 return LazySrcLoc.nodeOffset(0);5898 return LazySrcLoc.nodeOffset(0);
6088 };5899 };
...@@ -6166,11 +5977,12 @@ pub const PeerTypeCandidateSrc = union(enum) {...@@ -6166,11 +5977,12 @@ pub const PeerTypeCandidateSrc = union(enum) {
61665977
6167 pub fn resolve(5978 pub fn resolve(
6168 self: PeerTypeCandidateSrc,5979 self: PeerTypeCandidateSrc,
6169 gpa: Allocator,5980 mod: *Module,
6170 decl: *Decl,5981 decl: *Decl,
6171 candidate_i: usize,5982 candidate_i: usize,
6172 ) ?LazySrcLoc {5983 ) ?LazySrcLoc {
6173 @setCold(true);5984 @setCold(true);
5985 const gpa = mod.gpa;
61745986
6175 switch (self) {5987 switch (self) {
6176 .none => {5988 .none => {
...@@ -6192,10 +6004,10 @@ pub const PeerTypeCandidateSrc = union(enum) {...@@ -6192,10 +6004,10 @@ pub const PeerTypeCandidateSrc = union(enum) {
6192 else => {},6004 else => {},
6193 }6005 }
61946006
6195 const tree = decl.getFileScope().getTree(gpa) catch |err| {6007 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
6196 // In this case we emit a warning + a less precise source location.6008 // In this case we emit a warning + a less precise source location.
6197 log.warn("unable to load {s}: {s}", .{6009 log.warn("unable to load {s}: {s}", .{
6198 decl.getFileScope().sub_file_path, @errorName(err),6010 decl.getFileScope(mod).sub_file_path, @errorName(err),
6199 });6011 });
6200 return LazySrcLoc.nodeOffset(0);6012 return LazySrcLoc.nodeOffset(0);
6201 };6013 };
...@@ -6254,15 +6066,16 @@ fn queryFieldSrc(...@@ -6254,15 +6066,16 @@ fn queryFieldSrc(
62546066
6255pub fn paramSrc(6067pub fn paramSrc(
6256 func_node_offset: i32,6068 func_node_offset: i32,
6257 gpa: Allocator,6069 mod: *Module,
6258 decl: *Decl,6070 decl: *Decl,
6259 param_i: usize,6071 param_i: usize,
6260) LazySrcLoc {6072) LazySrcLoc {
6261 @setCold(true);6073 @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| {
6263 // In this case we emit a warning + a less precise source location.6076 // In this case we emit a warning + a less precise source location.
6264 log.warn("unable to load {s}: {s}", .{6077 log.warn("unable to load {s}: {s}", .{
6265 decl.getFileScope().sub_file_path, @errorName(err),6078 decl.getFileScope(mod).sub_file_path, @errorName(err),
6266 });6079 });
6267 return LazySrcLoc.nodeOffset(0);6080 return LazySrcLoc.nodeOffset(0);
6268 };6081 };
...@@ -6284,19 +6097,20 @@ pub fn paramSrc(...@@ -6284,19 +6097,20 @@ pub fn paramSrc(
6284}6097}
62856098
6286pub fn argSrc(6099pub fn argSrc(
6100 mod: *Module,
6287 call_node_offset: i32,6101 call_node_offset: i32,
6288 gpa: Allocator,
6289 decl: *Decl,6102 decl: *Decl,
6290 start_arg_i: usize,6103 start_arg_i: usize,
6291 bound_arg_src: ?LazySrcLoc,6104 bound_arg_src: ?LazySrcLoc,
6292) LazySrcLoc {6105) LazySrcLoc {
6106 @setCold(true);
6107 const gpa = mod.gpa;
6293 if (start_arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;6108 if (start_arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;
6294 const arg_i = start_arg_i - @boolToInt(bound_arg_src != null);6109 const arg_i = start_arg_i - @boolToInt(bound_arg_src != null);
6295 @setCold(true);6110 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
6296 const tree = decl.getFileScope().getTree(gpa) catch |err| {
6297 // In this case we emit a warning + a less precise source location.6111 // In this case we emit a warning + a less precise source location.
6298 log.warn("unable to load {s}: {s}", .{6112 log.warn("unable to load {s}: {s}", .{
6299 decl.getFileScope().sub_file_path, @errorName(err),6113 decl.getFileScope(mod).sub_file_path, @errorName(err),
6300 });6114 });
6301 return LazySrcLoc.nodeOffset(0);6115 return LazySrcLoc.nodeOffset(0);
6302 };6116 };
...@@ -6310,7 +6124,7 @@ pub fn argSrc(...@@ -6310,7 +6124,7 @@ pub fn argSrc(
6310 const node_datas = tree.nodes.items(.data);6124 const node_datas = tree.nodes.items(.data);
6311 const call_args_node = tree.extra_data[node_datas[node].rhs - 1];6125 const call_args_node = tree.extra_data[node_datas[node].rhs - 1];
6312 const call_args_offset = decl.nodeIndexToRelative(call_args_node);6126 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);
6314 },6128 },
6315 else => unreachable,6129 else => unreachable,
6316 };6130 };
...@@ -6318,16 +6132,17 @@ pub fn argSrc(...@@ -6318,16 +6132,17 @@ pub fn argSrc(
6318}6132}
63196133
6320pub fn initSrc(6134pub fn initSrc(
6135 mod: *Module,
6321 init_node_offset: i32,6136 init_node_offset: i32,
6322 gpa: Allocator,
6323 decl: *Decl,6137 decl: *Decl,
6324 init_index: usize,6138 init_index: usize,
6325) LazySrcLoc {6139) LazySrcLoc {
6326 @setCold(true);6140 @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| {
6328 // In this case we emit a warning + a less precise source location.6143 // In this case we emit a warning + a less precise source location.
6329 log.warn("unable to load {s}: {s}", .{6144 log.warn("unable to load {s}: {s}", .{
6330 decl.getFileScope().sub_file_path, @errorName(err),6145 decl.getFileScope(mod).sub_file_path, @errorName(err),
6331 });6146 });
6332 return LazySrcLoc.nodeOffset(0);6147 return LazySrcLoc.nodeOffset(0);
6333 };6148 };
...@@ -6363,12 +6178,13 @@ pub fn initSrc(...@@ -6363,12 +6178,13 @@ pub fn initSrc(
6363 }6178 }
6364}6179}
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 {
6367 @setCold(true);6182 @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| {
6369 // In this case we emit a warning + a less precise source location.6185 // In this case we emit a warning + a less precise source location.
6370 log.warn("unable to load {s}: {s}", .{6186 log.warn("unable to load {s}: {s}", .{
6371 decl.getFileScope().sub_file_path, @errorName(err),6187 decl.getFileScope(mod).sub_file_path, @errorName(err),
6372 });6188 });
6373 return LazySrcLoc.nodeOffset(0);6189 return LazySrcLoc.nodeOffset(0);
6374 };6190 };
...@@ -6430,11 +6246,13 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {...@@ -6430,11 +6246,13 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
6430 // deletion set at this time.6246 // deletion set at this time.
6431 for (file.deleted_decls.items) |decl_index| {6247 for (file.deleted_decls.items) |decl_index| {
6432 const decl = mod.declPtr(decl_index);6248 const decl = mod.declPtr(decl_index);
6433 log.debug("deleted from source: {*} ({s})", .{ decl, decl.name });
64346249
6435 // Remove from the namespace it resides in, preserving declaration order.6250 // Remove from the namespace it resides in, preserving declaration order.
6436 assert(decl.zir_decl_index != 0);6251 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
6439 try mod.clearDecl(decl_index, &outdated_decls);6257 try mod.clearDecl(decl_index, &outdated_decls);
6440 mod.destroyDecl(decl_index);6258 mod.destroyDecl(decl_index);
...@@ -6454,7 +6272,7 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {...@@ -6454,7 +6272,7 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
6454pub fn processExports(mod: *Module) !void {6272pub fn processExports(mod: *Module) !void {
6455 const gpa = mod.gpa;6273 const gpa = mod.gpa;
6456 // Map symbol names to `Export` for name collision detection.6274 // 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) = .{};
6458 defer symbol_exports.deinit(gpa);6276 defer symbol_exports.deinit(gpa);
64596277
6460 var it = mod.decl_exports.iterator();6278 var it = mod.decl_exports.iterator();
...@@ -6462,13 +6280,13 @@ pub fn processExports(mod: *Module) !void {...@@ -6462,13 +6280,13 @@ pub fn processExports(mod: *Module) !void {
6462 const exported_decl = entry.key_ptr.*;6280 const exported_decl = entry.key_ptr.*;
6463 const exports = entry.value_ptr.items;6281 const exports = entry.value_ptr.items;
6464 for (exports) |new_export| {6282 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);
6466 if (gop.found_existing) {6284 if (gop.found_existing) {
6467 new_export.status = .failed_retryable;6285 new_export.status = .failed_retryable;
6468 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);6286 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
6469 const src_loc = new_export.getSrcLoc(mod);6287 const src_loc = new_export.getSrcLoc(mod);
6470 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {s}", .{6288 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {}", .{
6471 new_export.options.name,6289 new_export.opts.name.fmt(&mod.intern_pool),
6472 });6290 });
6473 errdefer msg.destroy(gpa);6291 errdefer msg.destroy(gpa);
6474 const other_export = gop.value_ptr.*;6292 const other_export = gop.value_ptr.*;
...@@ -6501,11 +6319,16 @@ pub fn populateTestFunctions(...@@ -6501,11 +6319,16 @@ pub fn populateTestFunctions(
6501 main_progress_node: *std.Progress.Node,6319 main_progress_node: *std.Progress.Node,
6502) !void {6320) !void {
6503 const gpa = mod.gpa;6321 const gpa = mod.gpa;
6322 const ip = &mod.intern_pool;
6504 const builtin_pkg = mod.main_pkg.table.get("builtin").?;6323 const builtin_pkg = mod.main_pkg.table.get("builtin").?;
6505 const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;6324 const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;
6506 const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?);6325 const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?);
6507 const builtin_namespace = root_decl.src_namespace;6326 const builtin_namespace = mod.namespacePtr(root_decl.src_namespace);
6508 const decl_index = builtin_namespace.decls.getKeyAdapted(@as([]const u8, "test_functions"), DeclAdapter{ .mod = mod }).?;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 ).?;
6509 {6332 {
6510 // We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions`6333 // We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions`
6511 // was not referenced by start code.6334 // was not referenced by start code.
...@@ -6518,90 +6341,117 @@ pub fn populateTestFunctions(...@@ -6518,90 +6341,117 @@ pub fn populateTestFunctions(
6518 try mod.ensureDeclAnalyzed(decl_index);6341 try mod.ensureDeclAnalyzed(decl_index);
6519 }6342 }
6520 const decl = mod.declPtr(decl_index);6343 const decl = mod.declPtr(decl_index);
6521 var buf: Type.SlicePtrFieldTypeBuffer = undefined;6344 const test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod);
6522 const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType();6345 const null_usize = try mod.intern(.{ .opt = .{
6346 .ty = try mod.intern(.{ .opt_type = .usize_type }),
6347 .val = .none,
6348 } });
65236349
6524 const array_decl_index = d: {6350 const array_decl_index = d: {
6525 // Add mod.test_functions to an array decl then make the test_functions6351 // Add mod.test_functions to an array decl then make the test_functions
6526 // decl reference it as a slice.6352 // decl reference it as a slice.
6527 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);6353 const test_fn_vals = try gpa.alloc(InternPool.Index, mod.test_functions.count());
6528 errdefer new_decl_arena.deinit();6354 defer gpa.free(test_fn_vals);
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);
65406355
6541 // Add a dependency on each test name and function pointer.6356 // 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| {
6545 const test_decl = mod.declPtr(test_decl_index);6362 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);
6547 const test_name_decl_index = n: {6366 const test_name_decl_index = n: {
6548 var name_decl_arena = std.heap.ArenaAllocator.init(gpa);6367 const test_name_decl_ty = try mod.arrayType(.{
6549 errdefer name_decl_arena.deinit();6368 .len = test_decl_name.len,
6550 const bytes = try name_decl_arena.allocator().dupe(u8, test_name_slice);6369 .child = .u8_type,
6551 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{6370 });
6552 .ty = try Type.Tag.array_u8.create(name_decl_arena.allocator(), bytes.len),6371 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{
6553 .val = try Value.Tag.bytes.create(name_decl_arena.allocator(), bytes),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(),
6554 });6377 });
6555 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);
6556 break :n test_name_decl_index;6378 break :n test_name_decl_index;
6557 };6379 };
6558 array_decl.dependencies.putAssumeCapacityNoClobber(test_decl_index, .normal);6380 array_decl_dependencies.appendAssumeCapacity(test_decl_index);
6559 array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, .normal);6381 array_decl_dependencies.appendAssumeCapacity(test_name_decl_index);
6560 try mod.linkerUpdateDecl(test_name_decl_index);6382 try mod.linkerUpdateDecl(test_name_decl_index);
65616383
6562 const field_vals = try arena.create([3]Value);6384 const test_fn_fields = .{
6563 field_vals.* = .{6385 // name
6564 try Value.Tag.slice.create(arena, .{6386 try mod.intern(.{ .ptr = .{
6565 .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl_index),6387 .ty = .slice_const_u8_type,
6566 .len = try Value.Tag.int_u64.create(arena, test_name_slice.len),6388 .addr = .{ .decl = test_name_decl_index },
6567 }), // name6389 .len = try mod.intern(.{ .int = .{
6568 try Value.Tag.decl_ref.create(arena, test_decl_index), // func6390 .ty = .usize_type,
6569 Value.initTag(.null_value), // async_frame_size6391 .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,
6570 };6406 };
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);
6572 }6427 }
65736428
6574 try array_decl.finalizeNewArena(&new_decl_arena);
6575 break :d array_decl_index;6429 break :d array_decl_index;
6576 };6430 };
6577 try mod.linkerUpdateDecl(array_decl_index);6431 try mod.linkerUpdateDecl(array_decl_index);
65786432
6579 {6433 {
6580 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);6434 const new_ty = try mod.ptrType(.{
6581 errdefer new_decl_arena.deinit();6435 .child = test_fn_ty.toIntern(),
6582 const arena = new_decl_arena.allocator();6436 .flags = .{
65836437 .is_const = true,
6584 {6438 .size = .Slice,
6585 // This copy accesses the old Decl Type/Value so it must be done before `clearValues`.6439 },
6586 const new_ty = try Type.Tag.const_slice.create(arena, try tmp_test_fn_ty.copy(arena));6440 });
6587 const new_var = try gpa.create(Var);6441 const new_val = decl.val;
6588 errdefer gpa.destroy(new_var);6442 const new_init = try mod.intern(.{ .ptr = .{
6589 new_var.* = decl.val.castTag(.variable).?.data.*;6443 .ty = new_ty.toIntern(),
6590 new_var.init = try Value.Tag.slice.create(arena, .{6444 .addr = .{ .decl = array_decl_index },
6591 .ptr = try Value.Tag.decl_ref.create(arena, array_decl_index),6445 .len = (try mod.intValue(Type.usize, mod.test_functions.count())).toIntern(),
6592 .len = try Value.Tag.int_u64.create(arena, mod.test_functions.count()),6446 } });
6593 });6447 ip.mutateVarInit(decl.val.toIntern(), new_init);
6594 const new_val = try Value.Tag.variable.create(arena, new_var);6448
65956449 // Since we are replacing the Decl's value we must perform cleanup on the
6596 // Since we are replacing the Decl's value we must perform cleanup on the6450 // previous value.
6597 // previous value.6451 decl.clearValues(mod);
6598 decl.clearValues(mod);6452 decl.ty = new_ty;
6599 decl.ty = new_ty;6453 decl.val = new_val;
6600 decl.val = new_val;6454 decl.has_tv = true;
6601 decl.has_tv = true;
6602 }
6603
6604 try decl.finalizeNewArena(&new_decl_arena);
6605 }6455 }
6606 try mod.linkerUpdateDecl(decl_index);6456 try mod.linkerUpdateDecl(decl_index);
6607}6457}
...@@ -6631,7 +6481,7 @@ pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -6631,7 +6481,7 @@ pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void {
6631 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);6481 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
6632 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(6482 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
6633 gpa,6483 gpa,
6634 decl.srcLoc(),6484 decl.srcLoc(mod),
6635 "unable to codegen: {s}",6485 "unable to codegen: {s}",
6636 .{@errorName(err)},6486 .{@errorName(err)},
6637 ));6487 ));
...@@ -6673,64 +6523,49 @@ fn reportRetryableFileError(...@@ -6673,64 +6523,49 @@ fn reportRetryableFileError(
6673 gop.value_ptr.* = err_msg;6523 gop.value_ptr.* = err_msg;
6674}6524}
66756525
6676pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void {6526pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
6677 switch (val.tag()) {6527 switch (mod.intern_pool.indexToKey(val.toIntern())) {
6678 .decl_ref_mut => return mod.markDeclIndexAlive(val.castTag(.decl_ref_mut).?.data.decl_index),6528 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
6679 .extern_fn => return mod.markDeclIndexAlive(val.castTag(.extern_fn).?.data.owner_decl),6529 .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
6680 .function => return mod.markDeclIndexAlive(val.castTag(.function).?.data.owner_decl),6530 .func => |func| try mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
6681 .variable => return mod.markDeclIndexAlive(val.castTag(.variable).?.data.owner_decl),6531 .error_union => |error_union| switch (error_union.val) {
6682 .decl_ref => return mod.markDeclIndexAlive(val.cast(Value.Payload.Decl).?.data),6532 .err_name => {},
66836533 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
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);
6707 },6534 },
6708 .aggregate => {6535 .ptr => |ptr| {
6709 for (val.castTag(.aggregate).?.data) |field_val| {6536 switch (ptr.addr) {
6710 mod.markReferencedDeclsAlive(field_val);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()),
6711 }6542 }
6543 if (ptr.len != .none) try mod.markReferencedDeclsAlive(ptr.len.toValue());
6712 },6544 },
6713 .@"union" => {6545 .opt => |opt| if (opt.val != .none) try mod.markReferencedDeclsAlive(opt.val.toValue()),
6714 const data = val.cast(Value.Payload.Union).?.data;6546 .aggregate => |aggregate| for (aggregate.storage.values()) |elem|
6715 mod.markReferencedDeclsAlive(data.tag);6547 try mod.markReferencedDeclsAlive(elem.toValue()),
6716 mod.markReferencedDeclsAlive(data.val);6548 .un => |un| {
6549 try mod.markReferencedDeclsAlive(un.tag.toValue());
6550 try mod.markReferencedDeclsAlive(un.val.toValue());
6717 },6551 },
6718
6719 else => {},6552 else => {},
6720 }6553 }
6721}6554}
67226555
6723pub fn markDeclAlive(mod: *Module, decl: *Decl) void {6556pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void {
6724 if (decl.alive) return;6557 if (decl.alive) return;
6725 decl.alive = true;6558 decl.alive = true;
67266559
6560 try decl.intern(mod);
6561
6727 // This is the first time we are marking this Decl alive. We must6562 // This is the first time we are marking this Decl alive. We must
6728 // therefore recurse into its value and mark any Decl it references6563 // therefore recurse into its value and mark any Decl it references
6729 // as also alive, so that any Decl referenced does not get garbage collected.6564 // as also alive, so that any Decl referenced does not get garbage collected.
6730 mod.markReferencedDeclsAlive(decl.val);6565 try mod.markReferencedDeclsAlive(decl.val);
6731}6566}
67326567
6733fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) void {6568fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
6734 return mod.markDeclAlive(mod.declPtr(decl_index));6569 return mod.markDeclAlive(mod.declPtr(decl_index));
6735}6570}
67366571
...@@ -6779,3 +6614,522 @@ pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {...@@ -6779,3 +6614,522 @@ pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
6779 .field_reordering => mod.comp.bin_file.options.use_llvm,6614 .field_reordering => mod.comp.bin_file.options.use_llvm,
6780 };6615 };
6781}6616}
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 @@...@@ -1,18 +1,18 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;
2const Order = std.math.Order;3const Order = std.math.Order;
34
4const RangeSet = @This();5const InternPool = @import("InternPool.zig");
5const Module = @import("Module.zig");6const Module = @import("Module.zig");
7const RangeSet = @This();
6const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;8const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
7const Type = @import("type.zig").Type;
8const Value = @import("value.zig").Value;
99
10ranges: std.ArrayList(Range),10ranges: std.ArrayList(Range),
11module: *Module,11module: *Module,
1212
13pub const Range = struct {13pub const Range = struct {
14 first: Value,14 first: InternPool.Index,
15 last: Value,15 last: InternPool.Index,
16 src: SwitchProngSrc,16 src: SwitchProngSrc,
17};17};
1818
...@@ -29,18 +29,27 @@ pub fn deinit(self: *RangeSet) void {...@@ -29,18 +29,27 @@ pub fn deinit(self: *RangeSet) void {
2929
30pub fn add(30pub fn add(
31 self: *RangeSet,31 self: *RangeSet,
32 first: Value,32 first: InternPool.Index,
33 last: Value,33 last: InternPool.Index,
34 ty: Type,
35 src: SwitchProngSrc,34 src: SwitchProngSrc,
36) !?SwitchProngSrc {35) !?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
37 for (self.ranges.items) |range| {42 for (self.ranges.items) |range| {
38 if (last.compareAll(.gte, range.first, ty, self.module) and43 assert(ty == ip.typeOf(range.first));
39 first.compareAll(.lte, range.last, ty, self.module))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))
40 {48 {
41 return range.src; // They overlap.49 return range.src; // They overlap.
42 }50 }
43 }51 }
52
44 try self.ranges.append(.{53 try self.ranges.append(.{
45 .first = first,54 .first = first,
46 .last = last,55 .last = last,
...@@ -49,45 +58,43 @@ pub fn add(...@@ -49,45 +58,43 @@ pub fn add(
49 return null;58 return null;
50}59}
5160
52const LessThanContext = struct { ty: Type, module: *Module };
53
54/// Assumes a and b do not overlap61/// Assumes a and b do not overlap
55fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {62fn lessThan(mod: *Module, a: Range, b: Range) bool {
56 return a.first.compareAll(.lt, b.first, ctx.ty, ctx.module);63 const ty = mod.intern_pool.typeOf(a.first).toType();
64 return a.first.toValue().compareScalar(.lt, b.first.toValue(), ty, mod);
57}65}
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
60 if (self.ranges.items.len == 0)72 if (self.ranges.items.len == 0)
61 return false;73 return false;
6274
63 std.mem.sort(Range, self.ranges.items, LessThanContext{75 std.mem.sort(Range, self.ranges.items, mod, lessThan);
64 .ty = ty,
65 .module = self.module,
66 }, lessThan);
6776
68 if (!self.ranges.items[0].first.eql(first, ty, self.module) or77 if (self.ranges.items[0].first != first or
69 !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, self.module))78 self.ranges.items[self.ranges.items.len - 1].last != last)
70 {79 {
71 return false;80 return false;
72 }81 }
7382
74 var space: Value.BigIntSpace = undefined;83 var space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
7584
76 var counter = try std.math.big.int.Managed.init(self.ranges.allocator);85 var counter = try std.math.big.int.Managed.init(self.ranges.allocator);
77 defer counter.deinit();86 defer counter.deinit();
7887
79 const target = self.module.getTarget();
80
81 // look for gaps88 // look for gaps
82 for (self.ranges.items[1..], 0..) |cur, i| {89 for (self.ranges.items[1..], 0..) |cur, i| {
83 // i starts counting from the second item.90 // i starts counting from the second item.
84 const prev = self.ranges.items[i];91 const prev = self.ranges.items[i];
8592
86 // prev.last + 1 == cur.first93 // prev.last + 1 == cur.first
87 try counter.copy(prev.last.toBigInt(&space, target));94 try counter.copy(prev.last.toValue().toBigInt(&space, mod));
88 try counter.addScalar(&counter, 1);95 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);
91 if (!cur_start_int.eq(counter.toConst())) {98 if (!cur_start_int.eq(counter.toConst())) {
92 return false;99 return false;
93 }100 }
src/Sema.zig+8816-8097
...@@ -11,13 +11,9 @@ gpa: Allocator,...@@ -11,13 +11,9 @@ gpa: Allocator,
11/// Points to the temporary arena allocator of the Sema.11/// Points to the temporary arena allocator of the Sema.
12/// This arena will be cleared when the sema is destroyed.12/// This arena will be cleared when the sema is destroyed.
13arena: Allocator,13arena: Allocator,
14/// Points to the arena allocator for the owner_decl.
15/// This arena will persist until the decl is invalidated.
16perm_arena: Allocator,
17code: Zir,14code: Zir,
18air_instructions: std.MultiArrayList(Air.Inst) = .{},15air_instructions: std.MultiArrayList(Air.Inst) = .{},
19air_extra: std.ArrayListUnmanaged(u32) = .{},16air_extra: std.ArrayListUnmanaged(u32) = .{},
20air_values: std.ArrayListUnmanaged(Value) = .{},
21/// Maps ZIR to AIR.17/// Maps ZIR to AIR.
22inst_map: InstMap = .{},18inst_map: InstMap = .{},
23/// When analyzing an inline function call, owner_decl is the Decl of the caller19/// When analyzing an inline function call, owner_decl is the Decl of the caller
...@@ -28,10 +24,12 @@ owner_decl_index: Decl.Index,...@@ -28,10 +24,12 @@ owner_decl_index: Decl.Index,
28/// For an inline or comptime function call, this will be the root parent function24/// For an inline or comptime function call, this will be the root parent function
29/// which contains the callsite. Corresponds to `owner_decl`.25/// which contains the callsite. Corresponds to `owner_decl`.
30owner_func: ?*Module.Fn,26owner_func: ?*Module.Fn,
27owner_func_index: Module.Fn.OptionalIndex,
31/// The function this ZIR code is the body of, according to the source code.28/// The function this ZIR code is the body of, according to the source code.
32/// This starts out the same as `owner_func` and then diverges in the case of29/// This starts out the same as `owner_func` and then diverges in the case of
33/// an inline or comptime function call.30/// an inline or comptime function call.
34func: ?*Module.Fn,31func: ?*Module.Fn,
32func_index: Module.Fn.OptionalIndex,
35/// Used to restore the error return trace when returning a non-error from a function.33/// Used to restore the error return trace when returning a non-error from a function.
36error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,34error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
37/// When semantic analysis needs to know the return type of the function whose body35/// 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,...@@ -65,12 +63,15 @@ comptime_args_fn_inst: Zir.Inst.Index = 0,
65/// to use this instead of allocating a fresh one. This avoids an unnecessary63/// to use this instead of allocating a fresh one. This avoids an unnecessary
66/// extra hash table lookup in the `monomorphed_funcs` set.64/// extra hash table lookup in the `monomorphed_funcs` set.
67/// Sema will set this to null when it takes ownership.65/// Sema will set this to null when it takes ownership.
68preallocated_new_func: ?*Module.Fn = null,66preallocated_new_func: Module.Fn.OptionalIndex = .none,
69/// The key is `constant` AIR instructions to types that must be fully resolved67/// The key is types that must be fully resolved prior to machine code
70/// after the current function body analysis is done.68/// generation pass. Types are added to this set when resolving them
71/// TODO: after upgrading to use InternPool change the key here to be an69/// immediately could cause a dependency loop, but they do need to be resolved
72/// InternPool value index.70/// before machine code generation passes process the AIR.
73types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{},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) = .{},
74/// These are lazily created runtime blocks from block_inline instructions.75/// These are lazily created runtime blocks from block_inline instructions.
75/// They are created when an break_inline passes through a runtime condition, because76/// They are created when an break_inline passes through a runtime condition, because
76/// Sema must convert comptime control flow to runtime control flow, which means77/// Sema must convert comptime control flow to runtime control flow, which means
...@@ -84,12 +85,22 @@ is_generic_instantiation: bool = false,...@@ -84,12 +85,22 @@ is_generic_instantiation: bool = false,
84/// function types will emit generic poison instead of a partial type.85/// function types will emit generic poison instead of a partial type.
85no_partial_func_ty: bool = false,86no_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
89const std = @import("std");100const std = @import("std");
90const math = std.math;101const math = std.math;
91const mem = std.mem;102const mem = std.mem;
92const Allocator = std.mem.Allocator;103const Allocator = mem.Allocator;
93const assert = std.debug.assert;104const assert = std.debug.assert;
94const log = std.log.scoped(.sema);105const log = std.log.scoped(.sema);
95106
...@@ -114,6 +125,7 @@ const Package = @import("Package.zig");...@@ -114,6 +125,7 @@ const Package = @import("Package.zig");
114const crash_report = @import("crash_report.zig");125const crash_report = @import("crash_report.zig");
115const build_options = @import("build_options");126const build_options = @import("build_options");
116const Compilation = @import("Compilation.zig");127const Compilation = @import("Compilation.zig");
128const InternPool = @import("InternPool.zig");
117129
118pub const default_branch_quota = 1000;130pub const default_branch_quota = 1000;
119pub const default_reference_trace_len = 2;131pub const default_reference_trace_len = 2;
...@@ -226,7 +238,7 @@ pub const Block = struct {...@@ -226,7 +238,7 @@ pub const Block = struct {
226 sema: *Sema,238 sema: *Sema,
227 /// The namespace to use for lookups from this source block239 /// The namespace to use for lookups from this source block
228 /// When analyzing fields, this is different from src_decl.src_namespace.240 /// When analyzing fields, this is different from src_decl.src_namespace.
229 namespace: *Namespace,241 namespace: Namespace.Index,
230 /// The AIR instructions generated for this block.242 /// The AIR instructions generated for this block.
231 instructions: std.ArrayListUnmanaged(Air.Inst.Index),243 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
232 // `param` instructions are collected here to be used by the `func` instruction.244 // `param` instructions are collected here to be used by the `func` instruction.
...@@ -285,6 +297,7 @@ pub const Block = struct {...@@ -285,6 +297,7 @@ pub const Block = struct {
285297
286 fn explain(cr: ComptimeReason, sema: *Sema, msg: ?*Module.ErrorMsg) !void {298 fn explain(cr: ComptimeReason, sema: *Sema, msg: ?*Module.ErrorMsg) !void {
287 const parent = msg orelse return;299 const parent = msg orelse return;
300 const mod = sema.mod;
288 const prefix = "expression is evaluated at comptime because ";301 const prefix = "expression is evaluated at comptime because ";
289 switch (cr) {302 switch (cr) {
290 .c_import => |ci| {303 .c_import => |ci| {
...@@ -292,21 +305,21 @@ pub const Block = struct {...@@ -292,21 +305,21 @@ pub const Block = struct {
292 },305 },
293 .comptime_ret_ty => |rt| {306 .comptime_ret_ty => |rt| {
294 const src_loc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| blk: {307 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);
296 src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 };309 src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 };
297 break :blk src_loc;310 break :blk src_loc;
298 } else blk: {311 } else blk: {
299 const src_decl = sema.mod.declPtr(rt.block.src_decl);312 const src_decl = mod.declPtr(rt.block.src_decl);
300 break :blk rt.func_src.toSrcLoc(src_decl);313 break :blk rt.func_src.toSrcLoc(src_decl, mod);
301 };314 };
302 if (rt.return_ty.tag() == .generic_poison) {315 if (rt.return_ty.isGenericPoison()) {
303 return sema.mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{});316 return mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{});
304 }317 }
305 try sema.mod.errNoteNonLazy(318 try mod.errNoteNonLazy(
306 src_loc,319 src_loc,
307 parent,320 parent,
308 prefix ++ "the function returns a comptime-only type '{}'",321 prefix ++ "the function returns a comptime-only type '{}'",
309 .{rt.return_ty.fmt(sema.mod)},322 .{rt.return_ty.fmt(mod)},
310 );323 );
311 try sema.explainWhyTypeIsComptime(parent, src_loc, rt.return_ty);324 try sema.explainWhyTypeIsComptime(parent, src_loc, rt.return_ty);
312 },325 },
...@@ -398,8 +411,8 @@ pub const Block = struct {...@@ -398,8 +411,8 @@ pub const Block = struct {
398 };411 };
399 }412 }
400413
401 pub fn getFileScope(block: *Block) *Module.File {414 pub fn getFileScope(block: *Block, mod: *Module) *Module.File {
402 return block.namespace.file_scope;415 return mod.namespacePtr(block.namespace).file_scope;
403 }416 }
404417
405 fn addTy(418 fn addTy(
...@@ -584,13 +597,18 @@ pub const Block = struct {...@@ -584,13 +597,18 @@ pub const Block = struct {
584 }597 }
585598
586 fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator) !Air.Inst.Ref {599 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;
587 return block.addInst(.{602 return block.addInst(.{
588 .tag = if (block.float_mode == .Optimized) .cmp_vector_optimized else .cmp_vector,603 .tag = if (block.float_mode == .Optimized) .cmp_vector_optimized else .cmp_vector,
589 .data = .{ .ty_pl = .{604 .data = .{ .ty_pl = .{
590 .ty = try block.sema.addType(605 .ty = try sema.addType(
591 try Type.vector(block.sema.arena, block.sema.typeOf(lhs).vectorLen(), Type.bool),606 try mod.vectorType(.{
607 .len = sema.typeOf(lhs).vectorLen(mod),
608 .child = .bool_type,
609 }),
592 ),610 ),
593 .payload = try block.sema.addExtra(Air.VectorCmp{611 .payload = try sema.addExtra(Air.VectorCmp{
594 .lhs = lhs,612 .lhs = lhs,
595 .rhs = rhs,613 .rhs = rhs,
596 .op = Air.VectorCmp.encodeOp(cmp_op),614 .op = Air.VectorCmp.encodeOp(cmp_op),
...@@ -684,29 +702,20 @@ pub const Block = struct {...@@ -684,29 +702,20 @@ pub const Block = struct {
684 pub fn startAnonDecl(block: *Block) !WipAnonDecl {702 pub fn startAnonDecl(block: *Block) !WipAnonDecl {
685 return WipAnonDecl{703 return WipAnonDecl{
686 .block = block,704 .block = block,
687 .new_decl_arena = std.heap.ArenaAllocator.init(block.sema.gpa),
688 .finished = false,705 .finished = false,
689 };706 };
690 }707 }
691708
692 pub const WipAnonDecl = struct {709 pub const WipAnonDecl = struct {
693 block: *Block,710 block: *Block,
694 new_decl_arena: std.heap.ArenaAllocator,
695 finished: bool,711 finished: bool,
696712
697 pub fn arena(wad: *WipAnonDecl) Allocator {
698 return wad.new_decl_arena.allocator();
699 }
700
701 pub fn deinit(wad: *WipAnonDecl) void {713 pub fn deinit(wad: *WipAnonDecl) void {
702 if (!wad.finished) {
703 wad.new_decl_arena.deinit();
704 }
705 wad.* = undefined;714 wad.* = undefined;
706 }715 }
707716
708 /// `alignment` value of 0 means to use ABI alignment.717 /// `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 {
710 const sema = wad.block.sema;719 const sema = wad.block.sema;
711 // Do this ahead of time because `createAnonymousDecl` depends on calling720 // Do this ahead of time because `createAnonymousDecl` depends on calling
712 // `type.hasRuntimeBits()`.721 // `type.hasRuntimeBits()`.
...@@ -716,10 +725,11 @@ pub const Block = struct {...@@ -716,10 +725,11 @@ pub const Block = struct {
716 .val = val,725 .val = val,
717 });726 });
718 const new_decl = sema.mod.declPtr(new_decl_index);727 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);
720 errdefer sema.mod.abortAnonDecl(new_decl_index);730 errdefer sema.mod.abortAnonDecl(new_decl_index);
721 try new_decl.finalizeNewArena(&wad.new_decl_arena);
722 wad.finished = true;731 wad.finished = true;
732 try sema.mod.finalizeAnonDecl(new_decl_index);
723 return new_decl_index;733 return new_decl_index;
724 }734 }
725 };735 };
...@@ -736,11 +746,27 @@ const LabeledBlock = struct {...@@ -736,11 +746,27 @@ const LabeledBlock = struct {
736 }746 }
737};747};
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
739pub fn deinit(sema: *Sema) void {766pub fn deinit(sema: *Sema) void {
740 const gpa = sema.gpa;767 const gpa = sema.gpa;
741 sema.air_instructions.deinit(gpa);768 sema.air_instructions.deinit(gpa);
742 sema.air_extra.deinit(gpa);769 sema.air_extra.deinit(gpa);
743 sema.air_values.deinit(gpa);
744 sema.inst_map.deinit(gpa);770 sema.inst_map.deinit(gpa);
745 sema.decl_val_table.deinit(gpa);771 sema.decl_val_table.deinit(gpa);
746 sema.types_to_resolve.deinit(gpa);772 sema.types_to_resolve.deinit(gpa);
...@@ -823,7 +849,7 @@ pub fn analyzeBodyBreak(...@@ -823,7 +849,7 @@ pub fn analyzeBodyBreak(
823 else => |e| return e,849 else => |e| return e,
824 };850 };
825 if (block.instructions.items.len != 0 and851 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])))
827 return null;853 return null;
828 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";854 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
829 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;855 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
...@@ -858,18 +884,20 @@ fn analyzeBodyInner(...@@ -858,18 +884,20 @@ fn analyzeBodyInner(
858884
859 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body);885 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.
861 const parent_capture_scope = block.wip_capture_scope;891 const parent_capture_scope = block.wip_capture_scope;
862892 parent_capture_scope.incRef();
863 var wip_captures = WipCaptureScope{893 var wip_captures: WipCaptureScope = .{
864 .finalized = true,
865 .scope = parent_capture_scope,894 .scope = parent_capture_scope,
866 .perm_arena = sema.perm_arena,
867 .gpa = sema.gpa,895 .gpa = sema.gpa,
896 .finalized = true, // don't finalize the parent scope
868 };897 };
869 defer if (wip_captures.scope != parent_capture_scope) {898 defer wip_captures.deinit();
870 wip_captures.deinit();
871 };
872899
900 const mod = sema.mod;
873 const map = &sema.inst_map;901 const map = &sema.inst_map;
874 const tags = sema.code.instructions.items(.tag);902 const tags = sema.code.instructions.items(.tag);
875 const datas = sema.code.instructions.items(.data);903 const datas = sema.code.instructions.items(.data);
...@@ -890,15 +918,15 @@ fn analyzeBodyInner(...@@ -890,15 +918,15 @@ fn analyzeBodyInner(
890 crash_info.setBodyIndex(i);918 crash_info.setBodyIndex(i);
891 const inst = body[i];919 const inst = body[i];
892 std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{920 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,
894 });922 });
895 const air_inst: Air.Inst.Ref = switch (tags[inst]) {923 const air_inst: Air.Inst.Ref = switch (tags[inst]) {
896 // zig fmt: off924 // zig fmt: off
897 .alloc => try sema.zirAlloc(block, inst),925 .alloc => try sema.zirAlloc(block, inst),
898 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),926 .alloc_inferred => try sema.zirAllocInferred(block, inst, true),
899 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),927 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, false),
900 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, Type.initTag(.inferred_alloc_const)),928 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, true),
901 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, Type.initTag(.inferred_alloc_mut)),929 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, false),
902 .alloc_mut => try sema.zirAllocMut(block, inst),930 .alloc_mut => try sema.zirAllocMut(block, inst),
903 .alloc_comptime_mut => try sema.zirAllocComptime(block, inst),931 .alloc_comptime_mut => try sema.zirAllocComptime(block, inst),
904 .make_ptr_const => try sema.zirMakePtrConst(block, inst),932 .make_ptr_const => try sema.zirMakePtrConst(block, inst),
...@@ -962,7 +990,7 @@ fn analyzeBodyInner(...@@ -962,7 +990,7 @@ fn analyzeBodyInner(
962 .int_big => try sema.zirIntBig(block, inst),990 .int_big => try sema.zirIntBig(block, inst),
963 .float => try sema.zirFloat(block, inst),991 .float => try sema.zirFloat(block, inst),
964 .float128 => try sema.zirFloat128(block, inst),992 .float128 => try sema.zirFloat128(block, inst),
965 .int_type => try sema.zirIntType(block, inst),993 .int_type => try sema.zirIntType(inst),
966 .is_non_err => try sema.zirIsNonErr(block, inst),994 .is_non_err => try sema.zirIsNonErr(block, inst),
967 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),995 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
968 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),996 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
...@@ -1420,6 +1448,11 @@ fn analyzeBodyInner(...@@ -1420,6 +1448,11 @@ fn analyzeBodyInner(
1420 const src = LazySrcLoc.nodeOffset(datas[inst].node);1448 const src = LazySrcLoc.nodeOffset(datas[inst].node);
1421 try sema.emitBackwardBranch(block, src);1449 try sema.emitBackwardBranch(block, src);
1422 if (wip_captures.scope.captures.count() != orig_captures) {1450 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.
1423 try wip_captures.reset(parent_capture_scope);1456 try wip_captures.reset(parent_capture_scope);
1424 block.wip_capture_scope = wip_captures.scope;1457 block.wip_capture_scope = wip_captures.scope;
1425 orig_captures = 0;1458 orig_captures = 0;
...@@ -1435,6 +1468,11 @@ fn analyzeBodyInner(...@@ -1435,6 +1468,11 @@ fn analyzeBodyInner(
1435 const src = LazySrcLoc.nodeOffset(datas[inst].node);1468 const src = LazySrcLoc.nodeOffset(datas[inst].node);
1436 try sema.emitBackwardBranch(block, src);1469 try sema.emitBackwardBranch(block, src);
1437 if (wip_captures.scope.captures.count() != orig_captures) {1470 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.
1438 try wip_captures.reset(parent_capture_scope);1476 try wip_captures.reset(parent_capture_scope);
1439 block.wip_capture_scope = wip_captures.scope;1477 block.wip_capture_scope = wip_captures.scope;
1440 orig_captures = 0;1478 orig_captures = 0;
...@@ -1621,18 +1659,18 @@ fn analyzeBodyInner(...@@ -1621,18 +1659,18 @@ fn analyzeBodyInner(
1621 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];1659 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
1622 const err_union = try sema.resolveInst(extra.data.operand);1660 const err_union = try sema.resolveInst(extra.data.operand);
1623 const err_union_ty = sema.typeOf(err_union);1661 const err_union_ty = sema.typeOf(err_union);
1624 if (err_union_ty.zigTypeTag() != .ErrorUnion) {1662 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) {
1625 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{1663 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{
1626 err_union_ty.fmt(sema.mod),1664 err_union_ty.fmt(mod),
1627 });1665 });
1628 }1666 }
1629 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);1667 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
1630 assert(is_non_err != .none);1668 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| {
1632 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);1670 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
1633 return err;1671 return err;
1634 };1672 };
1635 if (is_non_err_tv.val.toBool()) {1673 if (is_non_err_val.toBool()) {
1636 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);1674 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
1637 }1675 }
1638 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1676 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
...@@ -1654,11 +1692,11 @@ fn analyzeBodyInner(...@@ -1654,11 +1692,11 @@ fn analyzeBodyInner(
1654 const err_union = try sema.analyzeLoad(block, src, operand, operand_src);1692 const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
1655 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);1693 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
1656 assert(is_non_err != .none);1694 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| {
1658 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);1696 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
1659 return err;1697 return err;
1660 };1698 };
1661 if (is_non_err_tv.val.toBool()) {1699 if (is_non_err_val.toBool()) {
1662 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);1700 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1663 }1701 }
1664 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1702 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
...@@ -1684,7 +1722,7 @@ fn analyzeBodyInner(...@@ -1684,7 +1722,7 @@ fn analyzeBodyInner(
1684 const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;1722 const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
1685 const defer_body = sema.code.extra[extra.index..][0..extra.len];1723 const defer_body = sema.code.extra[extra.index..][0..extra.len];
1686 const err_code = try sema.resolveInst(inst_data.err_code);1724 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);
1688 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {1726 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {
1689 error.ComptimeBreak => sema.comptime_break_inst,1727 error.ComptimeBreak => sema.comptime_break_inst,
1690 else => |e| return e,1728 else => |e| return e,
...@@ -1693,8 +1731,12 @@ fn analyzeBodyInner(...@@ -1693,8 +1731,12 @@ fn analyzeBodyInner(
1693 break :blk Air.Inst.Ref.void_value;1731 break :blk Air.Inst.Ref.void_value;
1694 },1732 },
1695 };1733 };
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])));
1697 break always_noreturn;1738 break always_noreturn;
1739 }
1698 map.putAssumeCapacity(inst, air_inst);1740 map.putAssumeCapacity(inst, air_inst);
1699 i += 1;1741 i += 1;
1700 };1742 };
...@@ -1703,7 +1745,7 @@ fn analyzeBodyInner(...@@ -1703,7 +1745,7 @@ fn analyzeBodyInner(
1703 const noreturn_inst = block.instructions.popOrNull();1745 const noreturn_inst = block.instructions.popOrNull();
1704 while (dbg_block_begins > 0) {1746 while (dbg_block_begins > 0) {
1705 dbg_block_begins -= 1;1747 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
1708 _ = try block.addInst(.{1750 _ = try block.addInst(.{
1709 .tag = .dbg_block_end,1751 .tag = .dbg_block_end,
...@@ -1713,6 +1755,8 @@ fn analyzeBodyInner(...@@ -1713,6 +1755,8 @@ fn analyzeBodyInner(
1713 if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some);1755 if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some);
17141756
1715 if (!wip_captures.finalized) {1757 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
1716 try wip_captures.finalize();1760 try wip_captures.finalize();
1717 block.wip_capture_scope = parent_capture_scope;1761 block.wip_capture_scope = parent_capture_scope;
1718 }1762 }
...@@ -1720,20 +1764,23 @@ fn analyzeBodyInner(...@@ -1720,20 +1764,23 @@ fn analyzeBodyInner(
1720 return result;1764 return result;
1721}1765}
17221766
1723pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {1767pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1724 var i: usize = @enumToInt(zir_ref);1768 if (zir_ref == .none) {
17251769 return .none;
1726 // First section of indexes correspond to a set number of constant values.1770 } else {
1727 if (i < Zir.Inst.Ref.typed_value_map.len) {1771 return resolveInst(sema, zir_ref);
1728 // We intentionally map the same indexes to the same values between ZIR and AIR.
1729 return zir_ref;
1730 }1772 }
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.1775pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1734 const inst = sema.inst_map.get(@intCast(u32, i)).?;1776 assert(zir_ref != .none);
1735 const ty = sema.typeOf(inst);1777 const i = @enumToInt(zir_ref);
1736 if (ty.tag() == .generic_poison) return error.GenericPoison;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;
1737 return inst;1784 return inst;
1738}1785}
17391786
...@@ -1759,18 +1806,31 @@ pub fn resolveConstString(...@@ -1759,18 +1806,31 @@ pub fn resolveConstString(
1759 reason: []const u8,1806 reason: []const u8,
1760) ![]u8 {1807) ![]u8 {
1761 const air_inst = try sema.resolveInst(zir_ref);1808 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;
1763 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);1810 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
1764 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);1811 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
1765 return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);1812 return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);
1766}1813}
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
1768pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {1829pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {
1769 assert(zir_ref != .var_args_param);
1770 const air_inst = try sema.resolveInst(zir_ref);1830 const air_inst = try sema.resolveInst(zir_ref);
1771 assert(air_inst != .var_args_param);1831 assert(air_inst != .var_args_param_type);
1772 const ty = try sema.analyzeAsType(block, src, air_inst);1832 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;
1774 return ty;1834 return ty;
1775}1835}
17761836
...@@ -1780,45 +1840,48 @@ fn analyzeAsType(...@@ -1780,45 +1840,48 @@ fn analyzeAsType(
1780 src: LazySrcLoc,1840 src: LazySrcLoc,
1781 air_inst: Air.Inst.Ref,1841 air_inst: Air.Inst.Ref,
1782) !Type {1842) !Type {
1783 const wanted_type = Type.initTag(.type);1843 const wanted_type = Type.type;
1784 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);1844 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
1785 const val = try sema.resolveConstValue(block, src, coerced_inst, "types must be comptime-known");1845 const val = try sema.resolveConstValue(block, src, coerced_inst, "types must be comptime-known");
1786 var buffer: Value.ToTypeBuffer = undefined;1846 return val.toType();
1787 const ty = val.toType(&buffer);
1788 return ty.copy(sema.arena);
1789}1847}
17901848
1791pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {1849pub 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
1794 assert(!block.is_comptime);1855 assert(!block.is_comptime);
1795 var err_trace_block = block.makeSubBlock();1856 var err_trace_block = block.makeSubBlock();
1796 defer err_trace_block.instructions.deinit(sema.gpa);1857 defer err_trace_block.instructions.deinit(gpa);
17971858
1798 const src: LazySrcLoc = .unneeded;1859 const src: LazySrcLoc = .unneeded;
17991860
1800 // var addrs: [err_return_trace_addr_count]usize = undefined;1861 // var addrs: [err_return_trace_addr_count]usize = undefined;
1801 const err_return_trace_addr_count = 32;1862 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);1863 const addr_arr_ty = try Type.array(sema.arena, err_return_trace_addr_count, null, Type.usize, mod);
1803 const addrs_ptr = try err_trace_block.addTy(.alloc, try Type.Tag.single_mut_pointer.create(sema.arena, addr_arr_ty));1864 const addrs_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(addr_arr_ty));
18041865
1805 // var st: StackTrace = undefined;1866 // var st: StackTrace = undefined;
1806 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");1867 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
1807 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);1868 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
1810 // st.instruction_addresses = &addrs;1871 // 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);
1812 try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store);1874 try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store);
18131875
1814 // st.index = 0;1876 // 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);
1816 try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store);1879 try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store);
18171880
1818 // @errorReturnTrace() = &st;1881 // @errorReturnTrace() = &st;
1819 _ = try err_trace_block.addUnOp(.set_err_return_trace, st_ptr);1882 _ = 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);
1822}1885}
18231886
1824/// May return Value Tags: `variable`, `undef`.1887/// May return Value Tags: `variable`, `undef`.
...@@ -1832,7 +1895,7 @@ fn resolveValue(...@@ -1832,7 +1895,7 @@ fn resolveValue(
1832 reason: []const u8,1895 reason: []const u8,
1833) CompileError!Value {1896) CompileError!Value {
1834 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {1897 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
1835 if (val.tag() == .generic_poison) return error.GenericPoison;1898 if (val.isGenericPoison()) return error.GenericPoison;
1836 return val;1899 return val;
1837 }1900 }
1838 return sema.failWithNeededComptime(block, src, reason);1901 return sema.failWithNeededComptime(block, src, reason);
...@@ -1848,10 +1911,12 @@ fn resolveConstMaybeUndefVal(...@@ -1848,10 +1911,12 @@ fn resolveConstMaybeUndefVal(
1848 reason: []const u8,1911 reason: []const u8,
1849) CompileError!Value {1912) CompileError!Value {
1850 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {1913 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {
1851 switch (val.tag()) {1914 switch (val.toIntern()) {
1852 .variable => return sema.failWithNeededComptime(block, src, reason),
1853 .generic_poison => return error.GenericPoison,1915 .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 },
1855 }1920 }
1856 }1921 }
1857 return sema.failWithNeededComptime(block, src, reason);1922 return sema.failWithNeededComptime(block, src, reason);
...@@ -1867,16 +1932,31 @@ fn resolveConstValue(...@@ -1867,16 +1932,31 @@ fn resolveConstValue(
1867 reason: []const u8,1932 reason: []const u8,
1868) CompileError!Value {1933) CompileError!Value {
1869 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {1934 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
1870 switch (val.tag()) {1935 switch (val.toIntern()) {
1871 .undef => return sema.failWithUseOfUndef(block, src),
1872 .variable => return sema.failWithNeededComptime(block, src, reason),
1873 .generic_poison => return error.GenericPoison,1936 .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 },
1875 }1943 }
1876 }1944 }
1877 return sema.failWithNeededComptime(block, src, reason);1945 return sema.failWithNeededComptime(block, src, reason);
1878}1946}
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
1880/// Value Tag `variable` causes this function to return `null`.1960/// Value Tag `variable` causes this function to return `null`.
1881/// Value Tag `undef` causes this function to return a compile error.1961/// Value Tag `undef` causes this function to return a compile error.
1882fn resolveDefinedValue(1962fn resolveDefinedValue(
...@@ -1885,8 +1965,9 @@ fn resolveDefinedValue(...@@ -1885,8 +1965,9 @@ fn resolveDefinedValue(
1885 src: LazySrcLoc,1965 src: LazySrcLoc,
1886 air_ref: Air.Inst.Ref,1966 air_ref: Air.Inst.Ref,
1887) CompileError!?Value {1967) CompileError!?Value {
1968 const mod = sema.mod;
1888 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {1969 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
1889 if (val.isUndef()) {1970 if (val.isUndef(mod)) {
1890 if (block.is_typeof) return null;1971 if (block.is_typeof) return null;
1891 return sema.failWithUseOfUndef(block, src);1972 return sema.failWithUseOfUndef(block, src);
1892 }1973 }
...@@ -1903,34 +1984,53 @@ fn resolveMaybeUndefVal(...@@ -1903,34 +1984,53 @@ fn resolveMaybeUndefVal(
1903 inst: Air.Inst.Ref,1984 inst: Air.Inst.Ref,
1904) CompileError!?Value {1985) CompileError!?Value {
1905 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;1986 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
1906 switch (val.tag()) {1987 switch (val.ip_index) {
1907 .variable => return null,
1908 .generic_poison => return error.GenericPoison,1988 .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 },
1910 }1994 }
1911}1995}
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
1913/// Value Tag `variable` results in `null`.2008/// Value Tag `variable` results in `null`.
1914/// Value Tag `undef` results in the Value.2009/// Value Tag `undef` results in the Value.
1915/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.2010/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
1916/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.2011/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.
2012/// Lazy values are recursively resolved.
1917fn resolveMaybeUndefValIntable(2013fn resolveMaybeUndefValIntable(
1918 sema: *Sema,2014 sema: *Sema,
1919 inst: Air.Inst.Ref,2015 inst: Air.Inst.Ref,
1920) CompileError!?Value {2016) CompileError!?Value {
1921 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;2017 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
1922 var check = val;2018 var check = val;
1923 while (true) switch (check.tag()) {2019 while (true) switch (check.ip_index) {
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,
1928 .generic_poison => return error.GenericPoison,2020 .generic_poison => return error.GenericPoison,
1929 else => {2021 .none => break,
1930 try sema.resolveLazyValue(val);2022 else => switch (sema.mod.intern_pool.indexToKey(check.toIntern())) {
1931 return val;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,
1932 },2031 },
1933 };2032 };
2033 return try sema.resolveLazyValue(val);
1934}2034}
19352035
1936/// Returns all Value tags including `variable` and `undef`.2036/// Returns all Value tags including `variable` and `undef`.
...@@ -1949,35 +2049,33 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -1949,35 +2049,33 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
1949 inst: Air.Inst.Ref,2049 inst: Air.Inst.Ref,
1950 make_runtime: *bool,2050 make_runtime: *bool,
1951) CompileError!?Value {2051) CompileError!?Value {
2052 assert(inst != .none);
1952 // First section of indexes correspond to a set number of constant values.2053 // First section of indexes correspond to a set number of constant values.
1953 var i: usize = @enumToInt(inst);2054 const int = @enumToInt(inst);
1954 if (i < Air.Inst.Ref.typed_value_map.len) {2055 if (int < InternPool.static_len) {
1955 return Air.Inst.Ref.typed_value_map[i].val;2056 return @intToEnum(InternPool.Index, int).toValue();
1956 }2057 }
1957 i -= Air.Inst.Ref.typed_value_map.len;
19582058
2059 const i = int - InternPool.static_len;
1959 const air_tags = sema.air_instructions.items(.tag);2060 const air_tags = sema.air_instructions.items(.tag);
1960 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {2061 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
1961 if (air_tags[i] == .constant) {2062 if (air_tags[i] == .interned) {
1962 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;2063 const interned = sema.air_instructions.items(.data)[i].interned;
1963 const val = sema.air_values.items[ty_pl.payload];2064 const val = interned.toValue();
1964 if (val.tag() == .variable) return val;2065 if (val.getVariable(sema.mod) != null) return val;
1965 }2066 }
1966 return opv;2067 return opv;
1967 }2068 }
1968 switch (air_tags[i]) {2069 const air_datas = sema.air_instructions.items(.data);
1969 .constant => {2070 const val = switch (air_tags[i]) {
1970 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;2071 .inferred_alloc => unreachable,
1971 const val = sema.air_values.items[ty_pl.payload];2072 .inferred_alloc_comptime => unreachable,
1972 if (val.tag() == .runtime_value) make_runtime.* = true;2073 .interned => air_datas[i].interned.toValue(),
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 },
1979 else => return null,2074 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;
1981}2079}
19822080
1983fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: []const u8) CompileError {2081fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: []const u8) CompileError {
...@@ -2010,13 +2108,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, opt...@@ -2010,13 +2108,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, opt
2010}2108}
20112109
2012fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {2110fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
2111 const mod = sema.mod;
2013 const msg = msg: {2112 const msg = msg: {
2014 const msg = try sema.errMsg(block, src, "type '{}' does not support array initialization syntax", .{2113 const msg = try sema.errMsg(block, src, "type '{}' does not support array initialization syntax", .{
2015 ty.fmt(sema.mod),2114 ty.fmt(mod),
2016 });2115 });
2017 errdefer msg.destroy(sema.gpa);2116 errdefer msg.destroy(sema.gpa);
2018 if (ty.isSlice()) {2117 if (ty.isSlice(mod)) {
2019 try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2().fmt(sema.mod)});2118 try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(mod).fmt(mod)});
2020 }2119 }
2021 break :msg msg;2120 break :msg msg;
2022 };2121 };
...@@ -2042,7 +2141,8 @@ fn failWithErrorSetCodeMissing(...@@ -2042,7 +2141,8 @@ fn failWithErrorSetCodeMissing(
2042}2141}
20432142
2044fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: usize) CompileError {2143fn 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) {
2046 const msg = msg: {2146 const msg = msg: {
2047 const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{2147 const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{
2048 int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod),2148 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:...@@ -2059,16 +2159,17 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:
2059}2159}
20602160
2061fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError {2161fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError {
2162 const mod = sema.mod;
2062 const msg = msg: {2163 const msg = msg: {
2063 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});2164 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});
2064 errdefer msg.destroy(sema.gpa);2165 errdefer msg.destroy(sema.gpa);
20652166
2066 const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg;2167 const struct_ty = mod.typeToStruct(container_ty) orelse break :msg msg;
2067 const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{2168 const default_value_src = mod.fieldSrcLoc(struct_ty.owner_decl, .{
2068 .index = field_index,2169 .index = field_index,
2069 .range = .value,2170 .range = .value,
2070 });2171 });
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", .{});
2072 break :msg msg;2173 break :msg msg;
2073 };2174 };
2074 return sema.failWithOwnedErrorMsg(msg);2175 return sema.failWithOwnedErrorMsg(msg);
...@@ -2083,13 +2184,19 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError...@@ -2083,13 +2184,19 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError
2083 return sema.failWithOwnedErrorMsg(msg);2184 return sema.failWithOwnedErrorMsg(msg);
2084}2185}
20852186
2086fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, object_ty: Type, field_name: []const u8) CompileError {2187fn failWithInvalidFieldAccess(
2087 const inner_ty = if (object_ty.isSinglePointer()) object_ty.childType() else object_ty;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: {2197 if (inner_ty.zigTypeTag(mod) == .Optional) opt: {
2090 var buf: Type.Payload.ElemType = undefined;2198 const child_ty = inner_ty.optionalChild(mod);
2091 const child_ty = inner_ty.optionalChild(&buf);2199 if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :opt;
2092 if (!typeSupportsFieldAccess(child_ty, field_name)) break :opt;
2093 const msg = msg: {2200 const msg = msg: {
2094 const msg = try sema.errMsg(block, src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)});2201 const msg = try sema.errMsg(block, src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)});
2095 errdefer msg.destroy(sema.gpa);2202 errdefer msg.destroy(sema.gpa);
...@@ -2097,9 +2204,9 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec...@@ -2097,9 +2204,9 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec
2097 break :msg msg;2204 break :msg msg;
2098 };2205 };
2099 return sema.failWithOwnedErrorMsg(msg);2206 return sema.failWithOwnedErrorMsg(msg);
2100 } else if (inner_ty.zigTypeTag() == .ErrorUnion) err: {2207 } else if (inner_ty.zigTypeTag(mod) == .ErrorUnion) err: {
2101 const child_ty = inner_ty.errorUnionPayload();2208 const child_ty = inner_ty.errorUnionPayload(mod);
2102 if (!typeSupportsFieldAccess(child_ty, field_name)) break :err;2209 if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :err;
2103 const msg = msg: {2210 const msg = msg: {
2104 const msg = try sema.errMsg(block, src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)});2211 const msg = try sema.errMsg(block, src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)});
2105 errdefer msg.destroy(sema.gpa);2212 errdefer msg.destroy(sema.gpa);
...@@ -2111,15 +2218,16 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec...@@ -2111,15 +2218,16 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec
2111 return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)});2218 return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)});
2112}2219}
21132220
2114fn typeSupportsFieldAccess(ty: Type, field_name: []const u8) bool {2221fn typeSupportsFieldAccess(mod: *const Module, ty: Type, field_name: InternPool.NullTerminatedString) bool {
2115 switch (ty.zigTypeTag()) {2222 const ip = &mod.intern_pool;
2116 .Array => return mem.eql(u8, field_name, "len"),2223 switch (ty.zigTypeTag(mod)) {
2224 .Array => return ip.stringEqlSlice(field_name, "len"),
2117 .Pointer => {2225 .Pointer => {
2118 const ptr_info = ty.ptrInfo().data;2226 const ptr_info = ty.ptrInfo(mod);
2119 if (ptr_info.size == .Slice) {2227 if (ptr_info.size == .Slice) {
2120 return mem.eql(u8, field_name, "ptr") or mem.eql(u8, field_name, "len");2228 return ip.stringEqlSlice(field_name, "ptr") or ip.stringEqlSlice(field_name, "len");
2121 } else if (ptr_info.pointee_type.zigTypeTag() == .Array) {2229 } else if (ptr_info.pointee_type.zigTypeTag(mod) == .Array) {
2122 return mem.eql(u8, field_name, "len");2230 return ip.stringEqlSlice(field_name, "len");
2123 } else return false;2231 } else return false;
2124 },2232 },
2125 .Type, .Struct, .Union => return true,2233 .Type, .Struct, .Union => return true,
...@@ -2139,7 +2247,7 @@ fn errNote(...@@ -2139,7 +2247,7 @@ fn errNote(
2139) error{OutOfMemory}!void {2247) error{OutOfMemory}!void {
2140 const mod = sema.mod;2248 const mod = sema.mod;
2141 const src_decl = mod.declPtr(block.src_decl);2249 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);
2143}2251}
21442252
2145fn addFieldErrNote(2253fn addFieldErrNote(
...@@ -2152,19 +2260,19 @@ fn addFieldErrNote(...@@ -2152,19 +2260,19 @@ fn addFieldErrNote(
2152) !void {2260) !void {
2153 @setCold(true);2261 @setCold(true);
2154 const mod = sema.mod;2262 const mod = sema.mod;
2155 const decl_index = container_ty.getOwnerDecl();2263 const decl_index = container_ty.getOwnerDecl(mod);
2156 const decl = mod.declPtr(decl_index);2264 const decl = mod.declPtr(decl_index);
21572265
2158 const field_src = blk: {2266 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| {
2160 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});2268 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2161 break :blk decl.srcLoc();2269 break :blk decl.srcLoc(mod);
2162 };2270 };
21632271
2164 const container_node = decl.relativeToNodeIndex(0);2272 const container_node = decl.relativeToNodeIndex(0);
2165 const node_tags = tree.nodes.items(.tag);2273 const node_tags = tree.nodes.items(.tag);
2166 var buf: [2]std.zig.Ast.Node.Index = undefined;2274 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
2169 var it_index: usize = 0;2277 var it_index: usize = 0;
2170 for (container_decl.ast.members) |member_node| {2278 for (container_decl.ast.members) |member_node| {
...@@ -2174,7 +2282,7 @@ fn addFieldErrNote(...@@ -2174,7 +2282,7 @@ fn addFieldErrNote(
2174 .container_field,2282 .container_field,
2175 => {2283 => {
2176 if (it_index == field_index) {2284 if (it_index == field_index) {
2177 break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node));2285 break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node), mod);
2178 }2286 }
2179 it_index += 1;2287 it_index += 1;
2180 },2288 },
...@@ -2195,7 +2303,7 @@ fn errMsg(...@@ -2195,7 +2303,7 @@ fn errMsg(
2195) error{OutOfMemory}!*Module.ErrorMsg {2303) error{OutOfMemory}!*Module.ErrorMsg {
2196 const mod = sema.mod;2304 const mod = sema.mod;
2197 const src_decl = mod.declPtr(block.src_decl);2305 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);
2199}2307}
22002308
2201pub fn fail(2309pub fn fail(
...@@ -2212,19 +2320,19 @@ pub fn fail(...@@ -2212,19 +2320,19 @@ pub fn fail(
2212fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {2320fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2213 @setCold(true);2321 @setCold(true);
2214 const gpa = sema.gpa;2322 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) {
2217 if (err_msg.src_loc.lazy == .unneeded) return error.NeededSourceLocation;2326 if (err_msg.src_loc.lazy == .unneeded) return error.NeededSourceLocation;
2218 var wip_errors: std.zig.ErrorBundle.Wip = undefined;2327 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
2219 wip_errors.init(gpa) catch unreachable;2328 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;
2221 std.debug.print("compile error during Sema:\n", .{});2330 std.debug.print("compile error during Sema:\n", .{});
2222 var error_bundle = wip_errors.toOwnedBundle("") catch unreachable;2331 var error_bundle = wip_errors.toOwnedBundle("") catch unreachable;
2223 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });2332 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });
2224 crash_report.compilerPanic("unexpected compile error occurred", null, null);2333 crash_report.compilerPanic("unexpected compile error occurred", null, null);
2225 }2334 }
22262335
2227 const mod = sema.mod;
2228 ref: {2336 ref: {
2229 errdefer err_msg.destroy(gpa);2337 errdefer err_msg.destroy(gpa);
2230 if (err_msg.src_loc.lazy == .unneeded) {2338 if (err_msg.src_loc.lazy == .unneeded) {
...@@ -2234,9 +2342,9 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2234,9 +2342,9 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2234 try mod.failed_files.ensureUnusedCapacity(gpa, 1);2342 try mod.failed_files.ensureUnusedCapacity(gpa, 1);
22352343
2236 const max_references = blk: {2344 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;
2238 // Do not add multiple traces without explicit request.2346 // 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;
2240 break :blk default_reference_trace_len;2348 break :blk default_reference_trace_len;
2241 };2349 };
22422350
...@@ -2245,7 +2353,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2245,7 +2353,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2245 defer reference_stack.deinit();2353 defer reference_stack.deinit();
22462354
2247 // Avoid infinite loops.2355 // Avoid infinite loops.
2248 var seen = std.AutoHashMap(Module.Decl.Index, void).init(gpa);2356 var seen = std.AutoHashMap(Decl.Index, void).init(gpa);
2249 defer seen.deinit();2357 defer seen.deinit();
22502358
2251 var cur_reference_trace: u32 = 0;2359 var cur_reference_trace: u32 = 0;
...@@ -2254,13 +2362,16 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2254,13 +2362,16 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2254 if (gop.found_existing) break;2362 if (gop.found_existing) break;
2255 if (cur_reference_trace < max_references) {2363 if (cur_reference_trace < max_references) {
2256 const decl = sema.mod.declPtr(ref.referencer);2364 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 });
2258 }2369 }
2259 referenced_by = ref.referencer;2370 referenced_by = ref.referencer;
2260 }2371 }
2261 if (sema.mod.comp.reference_trace == null and cur_reference_trace > 0) {2372 if (sema.mod.comp.reference_trace == null and cur_reference_trace > 0) {
2262 try reference_stack.append(.{2373 try reference_stack.append(.{
2263 .decl = null,2374 .decl = .none,
2264 .src_loc = undefined,2375 .src_loc = undefined,
2265 .hidden = 0,2376 .hidden = 0,
2266 });2377 });
...@@ -2352,10 +2463,10 @@ fn analyzeAsInt(...@@ -2352,10 +2463,10 @@ fn analyzeAsInt(
2352 dest_ty: Type,2463 dest_ty: Type,
2353 reason: []const u8,2464 reason: []const u8,
2354) !u64 {2465) !u64 {
2466 const mod = sema.mod;
2355 const coerced = try sema.coerce(block, dest_ty, air_ref, src);2467 const coerced = try sema.coerce(block, dest_ty, air_ref, src);
2356 const val = try sema.resolveConstValue(block, src, coerced, reason);2468 const val = try sema.resolveConstValue(block, src, coerced, reason);
2357 const target = sema.mod.getTarget();2469 return (try val.getUnsignedIntAdvanced(mod, sema)).?;
2358 return (try val.getUnsignedIntAdvanced(target, sema)).?;
2359}2470}
23602471
2361// Returns a compile error if the value has tag `variable`. See `resolveInstValue` for2472// 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...@@ -2396,73 +2507,77 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
2396 const tracy = trace(@src());2507 const tracy = trace(@src());
2397 defer tracy.end();2508 defer tracy.end();
23982509
2510 const mod = sema.mod;
2399 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2511 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2400 const src = inst_data.src();2512 const src = inst_data.src();
2401 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;2513 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2402 const pointee_ty = try sema.resolveType(block, src, extra.lhs);2514 const pointee_ty = try sema.resolveType(block, src, extra.lhs);
2403 const ptr = try sema.resolveInst(extra.rhs);2515 const ptr = try sema.resolveInst(extra.rhs);
2404 const target = sema.mod.getTarget();2516 const target = mod.getTarget();
2405 const addr_space = target_util.defaultAddressSpace(target, .local);2517 const addr_space = target_util.defaultAddressSpace(target, .local);
24062518
2407 if (Air.refToIndex(ptr)) |ptr_inst| {2519 if (Air.refToIndex(ptr)) |ptr_inst| {
2408 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {2520 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
2409 const air_datas = sema.air_instructions.items(.data);2521 .inferred_alloc => {
2410 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];2522 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
2411 switch (ptr_val.tag()) {2523 const ia2 = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
2412 .inferred_alloc => {2524 // Add the stored instruction to the set we will use to resolve peer types
2413 const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data;2525 // for the inferred allocation.
2414 // Add the stored instruction to the set we will use to resolve peer types2526 // This instruction will not make it to codegen; it is only to participate
2415 // for the inferred allocation.2527 // in the `stored_inst_list` of the `inferred_alloc`.
2416 // This instruction will not make it to codegen; it is only to participate2528 var trash_block = block.makeSubBlock();
2417 // in the `stored_inst_list` of the `inferred_alloc`.2529 defer trash_block.instructions.deinit(sema.gpa);
2418 var trash_block = block.makeSubBlock();2530 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
2419 defer trash_block.instructions.deinit(sema.gpa);2531
2420 const operand = try trash_block.addBitCast(pointee_ty, .void_value);2532 const ptr_ty = try mod.ptrType(.{
24212533 .child = pointee_ty.toIntern(),
2422 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{2534 .flags = .{
2423 .pointee_type = pointee_ty,2535 .alignment = ia1.alignment,
2424 .@"align" = inferred_alloc.alignment,2536 .address_space = addr_space,
2425 .@"addrspace" = addr_space,2537 },
2426 });2538 });
2427 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);2539 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
24282540
2429 try inferred_alloc.prongs.append(sema.arena, .{2541 try ia2.prongs.append(sema.arena, .{
2430 .stored_inst = operand,2542 .stored_inst = operand,
2431 .placeholder = Air.refToIndex(bitcasted_ptr).?,2543 .placeholder = Air.refToIndex(bitcasted_ptr).?,
2432 });2544 });
24332545
2434 return bitcasted_ptr;2546 return bitcasted_ptr;
2435 },2547 },
2436 .inferred_alloc_comptime => {2548 .inferred_alloc_comptime => {
2437 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;2549 const alignment = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.alignment;
2438 // There will be only one coerce_result_ptr because we are running at comptime.2550 // There will be only one coerce_result_ptr because we are running at comptime.
2439 // The alloc will turn into a Decl.2551 // The alloc will turn into a Decl.
2440 var anon_decl = try block.startAnonDecl();2552 var anon_decl = try block.startAnonDecl();
2441 defer anon_decl.deinit();2553 defer anon_decl.deinit();
2442 iac.data.decl_index = try anon_decl.finish(2554 const decl_index = try anon_decl.finish(
2443 try pointee_ty.copy(anon_decl.arena()),2555 pointee_ty,
2444 Value.undef,2556 (try mod.intern(.{ .undef = pointee_ty.toIntern() })).toValue(),
2445 iac.data.alignment,2557 alignment.toByteUnits(0),
2446 );2558 );
2447 if (iac.data.alignment != 0) {2559 sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;
2448 try sema.resolveTypeLayout(pointee_ty);2560 if (alignment != .none) {
2449 }2561 try sema.resolveTypeLayout(pointee_ty);
2450 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{2562 }
2451 .pointee_type = pointee_ty,2563 const ptr_ty = try mod.ptrType(.{
2452 .@"align" = iac.data.alignment,2564 .child = pointee_ty.toIntern(),
2453 .@"addrspace" = addr_space,2565 .flags = .{
2454 });2566 .alignment = alignment,
2455 try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);2567 .address_space = addr_space,
2456 return sema.addConstant(2568 },
2457 ptr_ty,2569 });
2458 try Value.Tag.decl_ref_mut.create(sema.arena, .{2570 try sema.maybeQueueFuncBodyAnalysis(decl_index);
2459 .decl_index = iac.data.decl_index,2571 try sema.comptime_mutable_decls.append(decl_index);
2460 .runtime_index = block.runtime_index,2572 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
2461 }),2573 .ty = ptr_ty.toIntern(),
2462 );2574 .addr = .{ .mut_decl = .{
2463 },2575 .decl = decl_index,
2464 else => {},2576 .runtime_index = block.runtime_index,
2465 }2577 } },
2578 } })).toValue());
2579 },
2580 else => {},
2466 }2581 }
2467 }2582 }
24682583
...@@ -2487,6 +2602,7 @@ fn coerceResultPtr(...@@ -2487,6 +2602,7 @@ fn coerceResultPtr(
2487 dummy_operand: Air.Inst.Ref,2602 dummy_operand: Air.Inst.Ref,
2488 trash_block: *Block,2603 trash_block: *Block,
2489) CompileError!Air.Inst.Ref {2604) CompileError!Air.Inst.Ref {
2605 const mod = sema.mod;
2490 const target = sema.mod.getTarget();2606 const target = sema.mod.getTarget();
2491 const addr_space = target_util.defaultAddressSpace(target, .local);2607 const addr_space = target_util.defaultAddressSpace(target, .local);
2492 const pointee_ty = sema.typeOf(dummy_operand);2608 const pointee_ty = sema.typeOf(dummy_operand);
...@@ -2530,7 +2646,7 @@ fn coerceResultPtr(...@@ -2530,7 +2646,7 @@ fn coerceResultPtr(
2530 return sema.addConstant(ptr_ty, ptr_val);2646 return sema.addConstant(ptr_ty, ptr_val);
2531 }2647 }
2532 if (pointee_ty.eql(Type.null, sema.mod)) {2648 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);
2534 const null_inst = try sema.addConstant(opt_ty, Value.null);2650 const null_inst = try sema.addConstant(opt_ty, Value.null);
2535 _ = try block.addBinOp(.store, new_ptr, null_inst);2651 _ = try block.addBinOp(.store, new_ptr, null_inst);
2536 return Air.Inst.Ref.void_value;2652 return Air.Inst.Ref.void_value;
...@@ -2563,7 +2679,7 @@ fn coerceResultPtr(...@@ -2563,7 +2679,7 @@ fn coerceResultPtr(
2563 .@"addrspace" = addr_space,2679 .@"addrspace" = addr_space,
2564 });2680 });
2565 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {2681 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));
2567 } else {2683 } else {
2568 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);2684 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
2569 }2685 }
...@@ -2600,8 +2716,10 @@ pub fn analyzeStructDecl(...@@ -2600,8 +2716,10 @@ pub fn analyzeStructDecl(
2600 sema: *Sema,2716 sema: *Sema,
2601 new_decl: *Decl,2717 new_decl: *Decl,
2602 inst: Zir.Inst.Index,2718 inst: Zir.Inst.Index,
2603 struct_obj: *Module.Struct,2719 struct_index: Module.Struct.Index,
2604) SemaError!void {2720) SemaError!void {
2721 const mod = sema.mod;
2722 const struct_obj = mod.structPtr(struct_index);
2605 const extended = sema.code.instructions.items(.data)[inst].extended;2723 const extended = sema.code.instructions.items(.data)[inst].extended;
2606 assert(extended.opcode == .struct_decl);2724 assert(extended.opcode == .struct_decl);
2607 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);2725 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
...@@ -2630,7 +2748,7 @@ pub fn analyzeStructDecl(...@@ -2630,7 +2748,7 @@ pub fn analyzeStructDecl(
2630 }2748 }
2631 }2749 }
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);
2634}2752}
26352753
2636fn zirStructDecl(2754fn zirStructDecl(
...@@ -2639,28 +2757,35 @@ fn zirStructDecl(...@@ -2639,28 +2757,35 @@ fn zirStructDecl(
2639 extended: Zir.Inst.Extended.InstData,2757 extended: Zir.Inst.Extended.InstData,
2640 inst: Zir.Inst.Index,2758 inst: Zir.Inst.Index,
2641) CompileError!Air.Inst.Ref {2759) CompileError!Air.Inst.Ref {
2760 const mod = sema.mod;
2761 const gpa = sema.gpa;
2642 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);2762 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
2643 const src: LazySrcLoc = if (small.has_src_node) blk: {2763 const src: LazySrcLoc = if (small.has_src_node) blk: {
2644 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);2764 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);
2645 break :blk LazySrcLoc.nodeOffset(node_offset);2765 break :blk LazySrcLoc.nodeOffset(node_offset);
2646 } else sema.src;2766 } else sema.src;
26472767
2648 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);2768 // Because these three things each reference each other, `undefined`
2649 errdefer new_decl_arena.deinit();2769 // placeholders are used before being set after the struct type gains an
2650 const new_decl_arena_allocator = new_decl_arena.allocator();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);
2656 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{2772 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
2657 .ty = Type.type,2773 .ty = Type.noreturn,
2658 .val = struct_val,2774 .val = Value.@"unreachable",
2659 }, small.name_strategy, "struct", inst);2775 }, small.name_strategy, "struct", inst);
2660 const new_decl = mod.declPtr(new_decl_index);2776 const new_decl = mod.declPtr(new_decl_index);
2661 new_decl.owns_tv = true;2777 new_decl.owns_tv = true;
2662 errdefer mod.abortAnonDecl(new_decl_index);2778 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(.{
2664 .owner_decl = new_decl_index,2789 .owner_decl = new_decl_index,
2665 .fields = .{},2790 .fields = .{},
2666 .zir_index = inst,2791 .zir_index = inst,
...@@ -2668,18 +2793,25 @@ fn zirStructDecl(...@@ -2668,18 +2793,25 @@ fn zirStructDecl(
2668 .status = .none,2793 .status = .none,
2669 .known_non_opv = undefined,2794 .known_non_opv = undefined,
2670 .is_tuple = small.is_tuple,2795 .is_tuple = small.is_tuple,
2671 .namespace = .{2796 .namespace = new_namespace_index,
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,
2679 });2797 });
2680 try sema.analyzeStructDecl(new_decl, inst, struct_obj);2798 errdefer mod.destroyStruct(struct_index);
2681 try new_decl.finalizeNewArena(&new_decl_arena);2799
2682 return sema.analyzeDeclVal(block, src, new_decl_index);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;
2683}2815}
26842816
2685fn createAnonymousDeclTypeNamed(2817fn createAnonymousDeclTypeNamed(
...@@ -2692,6 +2824,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2692,6 +2824,7 @@ fn createAnonymousDeclTypeNamed(
2692 inst: ?Zir.Inst.Index,2824 inst: ?Zir.Inst.Index,
2693) !Decl.Index {2825) !Decl.Index {
2694 const mod = sema.mod;2826 const mod = sema.mod;
2827 const gpa = sema.gpa;
2695 const namespace = block.namespace;2828 const namespace = block.namespace;
2696 const src_scope = block.wip_capture_scope;2829 const src_scope = block.wip_capture_scope;
2697 const src_decl = mod.declPtr(block.src_decl);2830 const src_decl = mod.declPtr(block.src_decl);
...@@ -2707,16 +2840,15 @@ fn createAnonymousDeclTypeNamed(...@@ -2707,16 +2840,15 @@ fn createAnonymousDeclTypeNamed(
2707 // semantically analyzed.2840 // semantically analyzed.
2708 // This name is also used as the key in the parent namespace so it cannot be2841 // This name is also used as the key in the parent namespace so it cannot be
2709 // renamed.2842 // renamed.
2710 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{2843
2711 src_decl.name, anon_prefix, @enumToInt(new_decl_index),2844 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
2712 });2845 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @enumToInt(new_decl_index),
2713 errdefer sema.gpa.free(name);2846 }) catch unreachable;
2714 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2847 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2715 return new_decl_index;2848 return new_decl_index;
2716 },2849 },
2717 .parent => {2850 .parent => {
2718 const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));2851 const name = mod.declPtr(block.src_decl).name;
2719 errdefer sema.gpa.free(name);
2720 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2852 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2721 return new_decl_index;2853 return new_decl_index;
2722 },2854 },
...@@ -2724,10 +2856,11 @@ fn createAnonymousDeclTypeNamed(...@@ -2724,10 +2856,11 @@ fn createAnonymousDeclTypeNamed(
2724 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);2856 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);
2725 const zir_tags = sema.code.instructions.items(.tag);2857 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);
2728 defer buf.deinit();2860 defer buf.deinit();
2729 try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));2861
2730 try buf.appendSlice("(");2862 const writer = buf.writer();
2863 try writer.print("{}(", .{mod.declPtr(block.src_decl).name.fmt(&mod.intern_pool)});
27312864
2732 var arg_i: usize = 0;2865 var arg_i: usize = 0;
2733 for (fn_info.param_body) |zir_inst| switch (zir_tags[zir_inst]) {2866 for (fn_info.param_body) |zir_inst| switch (zir_tags[zir_inst]) {
...@@ -2741,8 +2874,8 @@ fn createAnonymousDeclTypeNamed(...@@ -2741,8 +2874,8 @@ fn createAnonymousDeclTypeNamed(
2741 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg, "") catch2874 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg, "") catch
2742 return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null);2875 return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null);
27432876
2744 if (arg_i != 0) try buf.appendSlice(",");2877 if (arg_i != 0) try writer.writeByte(',');
2745 try buf.writer().print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)});2878 try writer.print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)});
27462879
2747 arg_i += 1;2880 arg_i += 1;
2748 continue;2881 continue;
...@@ -2750,9 +2883,8 @@ fn createAnonymousDeclTypeNamed(...@@ -2750,9 +2883,8 @@ fn createAnonymousDeclTypeNamed(
2750 else => continue,2883 else => continue,
2751 };2884 };
27522885
2753 try buf.appendSlice(")");2886 try writer.writeByte(')');
2754 const name = try buf.toOwnedSliceSentinel(0);2887 const name = try mod.intern_pool.getOrPutString(gpa, buf.items);
2755 errdefer sema.gpa.free(name);
2756 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2888 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2757 return new_decl_index;2889 return new_decl_index;
2758 },2890 },
...@@ -2765,10 +2897,9 @@ fn createAnonymousDeclTypeNamed(...@@ -2765,10 +2897,9 @@ fn createAnonymousDeclTypeNamed(
2765 .dbg_var_ptr, .dbg_var_val => {2897 .dbg_var_ptr, .dbg_var_val => {
2766 if (zir_data[i].str_op.operand != ref) continue;2898 if (zir_data[i].str_op.operand != ref) continue;
27672899
2768 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}.{s}", .{2900 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}.{s}", .{
2769 src_decl.name, zir_data[i].str_op.getStr(sema.code),2901 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),
2770 });2902 });
2771 errdefer sema.gpa.free(name);
27722903
2773 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2904 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2774 return new_decl_index;2905 return new_decl_index;
...@@ -2825,53 +2956,28 @@ fn zirEnumDecl(...@@ -2825,53 +2956,28 @@ fn zirEnumDecl(
2825 break :blk decls_len;2956 break :blk decls_len;
2826 } else 0;2957 } else 0;
28272958
2828 var done = false;2959 // Because these three things each reference each other, `undefined`
28292960 // placeholders are used before being set after the enum type gains an
2830 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);2961 // InternPool index.
2831 errdefer if (!done) new_decl_arena.deinit();
2832 const new_decl_arena_allocator = new_decl_arena.allocator();
28332962
2834 const enum_obj = try new_decl_arena_allocator.create(Module.EnumFull);2963 var done = false;
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);
2842 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{2964 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
2843 .ty = Type.type,2965 .ty = Type.noreturn,
2844 .val = enum_val,2966 .val = Value.@"unreachable",
2845 }, small.name_strategy, "enum", inst);2967 }, small.name_strategy, "enum", inst);
2846 const new_decl = mod.declPtr(new_decl_index);2968 const new_decl = mod.declPtr(new_decl_index);
2847 new_decl.owns_tv = true;2969 new_decl.owns_tv = true;
2848 errdefer if (!done) mod.abortAnonDecl(new_decl_index);2970 errdefer if (!done) mod.abortAnonDecl(new_decl_index);
28492971
2850 enum_obj.* = .{2972 const new_namespace_index = try mod.createNamespace(.{
2851 .owner_decl = new_decl_index,2973 .parent = block.namespace.toOptional(),
2852 .tag_ty = Type.null,2974 .ty = undefined,
2853 .tag_ty_inferred = true,2975 .file_scope = block.getFileScope(mod),
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,
2864 });2976 });
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);2980 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);
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);
28752981
2876 const body = sema.code.extra[extra_index..][0..body_len];2982 const body = sema.code.extra[extra_index..][0..body_len];
2877 extra_index += body.len;2983 extra_index += body.len;
...@@ -2880,7 +2986,34 @@ fn zirEnumDecl(...@@ -2880,7 +2986,34 @@ fn zirEnumDecl(
2880 const body_end = extra_index;2986 const body_end = extra_index;
2881 extra_index += bit_bags_count;2987 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: {
2884 // We create a block for the field type instructions because they3017 // We create a block for the field type instructions because they
2885 // may need to reference Decls from inside the enum namespace.3018 // may need to reference Decls from inside the enum namespace.
2886 // Within the field type, default value, and alignment expressions, the "owner decl"3019 // Within the field type, default value, and alignment expressions, the "owner decl"
...@@ -2896,21 +3029,27 @@ fn zirEnumDecl(...@@ -2896,21 +3029,27 @@ fn zirEnumDecl(
2896 }3029 }
28973030
2898 const prev_owner_func = sema.owner_func;3031 const prev_owner_func = sema.owner_func;
3032 const prev_owner_func_index = sema.owner_func_index;
2899 sema.owner_func = null;3033 sema.owner_func = null;
3034 sema.owner_func_index = .none;
2900 defer sema.owner_func = prev_owner_func;3035 defer sema.owner_func = prev_owner_func;
3036 defer sema.owner_func_index = prev_owner_func_index;
29013037
2902 const prev_func = sema.func;3038 const prev_func = sema.func;
3039 const prev_func_index = sema.func_index;
2903 sema.func = null;3040 sema.func = null;
3041 sema.func_index = .none;
2904 defer sema.func = prev_func;3042 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);
2907 defer wip_captures.deinit();3046 defer wip_captures.deinit();
29083047
2909 var enum_block: Block = .{3048 var enum_block: Block = .{
2910 .parent = null,3049 .parent = null,
2911 .sema = sema,3050 .sema = sema,
2912 .src_decl = new_decl_index,3051 .src_decl = new_decl_index,
2913 .namespace = &enum_obj.namespace,3052 .namespace = new_namespace_index,
2914 .wip_capture_scope = wip_captures.scope,3053 .wip_capture_scope = wip_captures.scope,
2915 .instructions = .{},3054 .instructions = .{},
2916 .inlining = null,3055 .inlining = null,
...@@ -2926,43 +3065,29 @@ fn zirEnumDecl(...@@ -2926,43 +3065,29 @@ fn zirEnumDecl(
29263065
2927 if (tag_type_ref != .none) {3066 if (tag_type_ref != .none) {
2928 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);3067 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) {
2930 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)});3069 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)});
2931 }3070 }
2932 enum_obj.tag_ty = try ty.copy(decl_arena_allocator);3071 incomplete_enum.setTagType(&mod.intern_pool, ty.toIntern());
2933 enum_obj.tag_ty_inferred = false;3072 break :ty ty;
2934 } else if (fields_len == 0) {3073 } else if (fields_len == 0) {
2935 enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, 0);3074 break :ty try mod.intType(.unsigned, 0);
2936 enum_obj.tag_ty_inferred = true;
2937 } else {3075 } else {
2938 const bits = std.math.log2_int_ceil(usize, fields_len);3076 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);3077 break :ty try mod.intType(.unsigned, bits);
2940 enum_obj.tag_ty_inferred = true;
2941 }3078 }
2942 }3079 };
29433080
2944 if (small.nonexhaustive and enum_obj.tag_ty.zigTypeTag() != .ComptimeInt) {3081 if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
2945 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) {3082 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(mod)) {
2946 return sema.fail(block, src, "non-exhaustive enum specifies every value", .{});3083 return sema.fail(block, src, "non-exhaustive enum specifies every value", .{});
2947 }3084 }
2948 }3085 }
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
2961 var bit_bag_index: usize = body_end;3087 var bit_bag_index: usize = body_end;
2962 var cur_bit_bag: u32 = undefined;3088 var cur_bit_bag: u32 = undefined;
2963 var field_i: u32 = 0;3089 var field_i: u32 = 0;
2964 var last_tag_val: ?Value = null;3090 var last_tag_val: ?Value = null;
2965 var tag_val_buf: Value.Payload.U64 = undefined;
2966 while (field_i < fields_len) : (field_i += 1) {3091 while (field_i < fields_len) : (field_i += 1) {
2967 if (field_i % 32 == 0) {3092 if (field_i % 32 == 0) {
2968 cur_bit_bag = sema.code.extra[bit_bag_index];3093 cur_bit_bag = sema.code.extra[bit_bag_index];
...@@ -2977,15 +3102,12 @@ fn zirEnumDecl(...@@ -2977,15 +3102,12 @@ fn zirEnumDecl(
2977 // doc comment3102 // doc comment
2978 extra_index += 1;3103 extra_index += 1;
29793104
2980 // This string needs to outlive the ZIR code.3105 const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir);
2981 const field_name = try decl_arena_allocator.dupe(u8, field_name_zir);3106 if (try incomplete_enum.addFieldName(&mod.intern_pool, gpa, field_name)) |other_index| {
29823107 const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy;
2983 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);3108 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy;
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;
2987 const msg = msg: {3109 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});
2989 errdefer msg.destroy(gpa);3111 errdefer msg.destroy(gpa);
2990 try sema.errNote(block, other_field_src, msg, "other field here", .{});3112 try sema.errNote(block, other_field_src, msg, "other field here", .{});
2991 break :msg msg;3113 break :msg msg;
...@@ -2993,13 +3115,13 @@ fn zirEnumDecl(...@@ -2993,13 +3115,13 @@ fn zirEnumDecl(
2993 return sema.failWithOwnedErrorMsg(msg);3115 return sema.failWithOwnedErrorMsg(msg);
2994 }3116 }
29953117
2996 if (has_tag_value) {3118 const tag_overflow = if (has_tag_value) overflow: {
2997 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);3119 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2998 extra_index += 1;3120 extra_index += 1;
2999 const tag_inst = try sema.resolveInst(tag_val_ref);3121 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) {
3001 error.NeededSourceLocation => {3123 error.NeededSourceLocation => {
3002 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{3124 const value_src = mod.fieldSrcLoc(new_decl_index, .{
3003 .index = field_i,3125 .index = field_i,
3004 .range = .value,3126 .range = .value,
3005 }).lazy;3127 }).lazy;
...@@ -3008,63 +3130,56 @@ fn zirEnumDecl(...@@ -3008,63 +3130,56 @@ fn zirEnumDecl(
3008 },3130 },
3009 else => |e| return e,3131 else => |e| return e,
3010 };3132 };
3011 last_tag_val = tag_val;3133 if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true;
3012 const copied_tag_val = try tag_val.copy(decl_arena_allocator);3134 last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty);
3013 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{3135 if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, last_tag_val.?.toIntern())) |other_index| {
3014 .ty = enum_obj.tag_ty,3136 const value_src = mod.fieldSrcLoc(new_decl_index, .{
3015 .mod = mod,
3016 });
3017 if (gop_val.found_existing) {
3018 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3019 .index = field_i,3137 .index = field_i,
3020 .range = .value,3138 .range = .value,
3021 }).lazy;3139 }).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;
3023 const msg = msg: {3141 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)});
3025 errdefer msg.destroy(gpa);3143 errdefer msg.destroy(gpa);
3026 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});3144 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
3027 break :msg msg;3145 break :msg msg;
3028 };3146 };
3029 return sema.failWithOwnedErrorMsg(msg);3147 return sema.failWithOwnedErrorMsg(msg);
3030 }3148 }
3031 } else if (any_values) {3149 break :overflow false;
3032 const tag_val = if (last_tag_val) |val|3150 } else if (any_values) overflow: {
3033 try sema.intAdd(val, Value.one, enum_obj.tag_ty)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)
3034 else3154 else
3035 Value.zero;3155 try mod.intValue(int_tag_ty, 0);
3036 last_tag_val = tag_val;3156 if (overflow != null) break :overflow true;
3037 const copied_tag_val = try tag_val.copy(decl_arena_allocator);3157 if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, last_tag_val.?.toIntern())) |other_index| {
3038 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{3158 const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy;
3039 .ty = enum_obj.tag_ty,3159 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy;
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;
3045 const msg = msg: {3160 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)});
3047 errdefer msg.destroy(gpa);3162 errdefer msg.destroy(gpa);
3048 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});3163 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
3049 break :msg msg;3164 break :msg msg;
3050 };3165 };
3051 return sema.failWithOwnedErrorMsg(msg);3166 return sema.failWithOwnedErrorMsg(msg);
3052 }3167 }
3053 } else {3168 break :overflow false;
3054 tag_val_buf = .{3169 } else overflow: {
3055 .base = .{ .tag = .int_u64 },3170 last_tag_val = try mod.intValue(Type.comptime_int, field_i);
3056 .data = field_i,3171 if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true;
3057 };3172 last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty);
3058 last_tag_val = Value.initPayload(&tag_val_buf.base);3173 break :overflow false;
3059 }3174 };
30603175
3061 if (!(try sema.intFitsInType(last_tag_val.?, enum_obj.tag_ty, null))) {3176 if (tag_overflow) {
3062 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{3177 const value_src = mod.fieldSrcLoc(new_decl_index, .{
3063 .index = field_i,3178 .index = field_i,
3064 .range = if (has_tag_value) .value else .name,3179 .range = if (has_tag_value) .value else .name,
3065 }).lazy;3180 }).lazy;
3066 const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{3181 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),
3068 });3183 });
3069 return sema.failWithOwnedErrorMsg(msg);3184 return sema.failWithOwnedErrorMsg(msg);
3070 }3185 }
...@@ -3081,6 +3196,8 @@ fn zirUnionDecl(...@@ -3081,6 +3196,8 @@ fn zirUnionDecl(
3081 const tracy = trace(@src());3196 const tracy = trace(@src());
3082 defer tracy.end();3197 defer tracy.end();
30833198
3199 const mod = sema.mod;
3200 const gpa = sema.gpa;
3084 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);3201 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
3085 var extra_index: usize = extended.operand;3202 var extra_index: usize = extended.operand;
30863203
...@@ -3100,55 +3217,60 @@ fn zirUnionDecl(...@@ -3100,55 +3217,60 @@ fn zirUnionDecl(
3100 break :blk decls_len;3217 break :blk decls_len;
3101 } else 0;3218 } else 0;
31023219
3103 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);3220 // Because these three things each reference each other, `undefined`
3104 errdefer new_decl_arena.deinit();3221 // placeholders are used before being set after the union type gains an
3105 const new_decl_arena_allocator = new_decl_arena.allocator();3222 // InternPool index.
31063223
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;
3124 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{3224 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
3125 .ty = Type.type,3225 .ty = Type.noreturn,
3126 .val = union_val,3226 .val = Value.@"unreachable",
3127 }, small.name_strategy, "union", inst);3227 }, small.name_strategy, "union", inst);
3128 const new_decl = mod.declPtr(new_decl_index);3228 const new_decl = mod.declPtr(new_decl_index);
3129 new_decl.owns_tv = true;3229 new_decl.owns_tv = true;
3130 errdefer mod.abortAnonDecl(new_decl_index);3230 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(.{
3132 .owner_decl = new_decl_index,3241 .owner_decl = new_decl_index,
3133 .tag_ty = Type.initTag(.null),3242 .tag_ty = Type.null,
3134 .fields = .{},3243 .fields = .{},
3135 .zir_index = inst,3244 .zir_index = inst,
3136 .layout = small.layout,3245 .layout = small.layout,
3137 .status = .none,3246 .status = .none,
3138 .namespace = .{3247 .namespace = new_namespace_index,
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,
3146 });3248 });
31473249 errdefer mod.destroyUnion(union_index);
3148 _ = try mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl);3250
31493251 const union_ty = try mod.intern_pool.get(gpa, .{ .union_type = .{
3150 try new_decl.finalizeNewArena(&new_decl_arena);3252 .index = union_index,
3151 return sema.analyzeDeclVal(block, src, new_decl_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;
3152}3274}
31533275
3154fn zirOpaqueDecl(3276fn zirOpaqueDecl(
...@@ -3161,7 +3283,6 @@ fn zirOpaqueDecl(...@@ -3161,7 +3283,6 @@ fn zirOpaqueDecl(
3161 defer tracy.end();3283 defer tracy.end();
31623284
3163 const mod = sema.mod;3285 const mod = sema.mod;
3164 const gpa = sema.gpa;
3165 const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small);3286 const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small);
3166 var extra_index: usize = extended.operand;3287 var extra_index: usize = extended.operand;
31673288
...@@ -3177,42 +3298,42 @@ fn zirOpaqueDecl(...@@ -3177,42 +3298,42 @@ fn zirOpaqueDecl(
3177 break :blk decls_len;3298 break :blk decls_len;
3178 } else 0;3299 } else 0;
31793300
3180 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);3301 // Because these three things each reference each other, `undefined`
3181 errdefer new_decl_arena.deinit();3302 // placeholders are used in two places before being set after the opaque
3182 const new_decl_arena_allocator = new_decl_arena.allocator();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);
3192 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{3305 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
3193 .ty = Type.type,3306 .ty = Type.noreturn,
3194 .val = opaque_val,3307 .val = Value.@"unreachable",
3195 }, small.name_strategy, "opaque", inst);3308 }, small.name_strategy, "opaque", inst);
3196 const new_decl = mod.declPtr(new_decl_index);3309 const new_decl = mod.declPtr(new_decl_index);
3197 new_decl.owns_tv = true;3310 new_decl.owns_tv = true;
3198 errdefer mod.abortAnonDecl(new_decl_index);3311 errdefer mod.abortAnonDecl(new_decl_index);
31993312
3200 opaque_obj.* = .{3313 const new_namespace_index = try mod.createNamespace(.{
3201 .owner_decl = new_decl_index,3314 .parent = block.namespace.toOptional(),
3202 .namespace = .{3315 .ty = undefined,
3203 .parent = block.namespace,3316 .file_scope = block.getFileScope(mod),
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,
3210 });3317 });
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);3332 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);
3215 return sema.analyzeDeclVal(block, src, new_decl_index);3333
3334 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3335 try mod.finalizeAnonDecl(new_decl_index);
3336 return decl_val;
3216}3337}
32173338
3218fn zirErrorSetDecl(3339fn zirErrorSetDecl(
...@@ -3224,48 +3345,39 @@ fn zirErrorSetDecl(...@@ -3224,48 +3345,39 @@ fn zirErrorSetDecl(
3224 const tracy = trace(@src());3345 const tracy = trace(@src());
3225 defer tracy.end();3346 defer tracy.end();
32263347
3348 const mod = sema.mod;
3227 const gpa = sema.gpa;3349 const gpa = sema.gpa;
3228 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3350 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
3229 const src = inst_data.src();3351 const src = inst_data.src();
3230 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);3352 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
32313353
3232 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);3354 var names: Module.Fn.InferredErrorSet.NameMap = .{};
3233 errdefer new_decl_arena.deinit();3355 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);
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);
32503356
3251 var extra_index = @intCast(u32, extra.end);3357 var extra_index = @intCast(u32, extra.end);
3252 const extra_index_end = extra_index + (extra.data.fields_len * 2);3358 const extra_index_end = extra_index + (extra.data.fields_len * 2);
3253 while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string3359 while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string
3254 const str_index = sema.code.extra[extra_index];3360 const str_index = sema.code.extra[extra_index];
3255 const kv = try mod.getErrorValue(sema.code.nullTerminatedString(str_index));3361 const name = sema.code.nullTerminatedString(str_index);
3256 const result = names.getOrPutAssumeCapacity(kv.key);3362 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
3363 _ = try mod.getErrorValue(name_ip);
3364 const result = names.getOrPutAssumeCapacity(name_ip);
3257 assert(!result.found_existing); // verified in AstGen3365 assert(!result.found_existing); // verified in AstGen
3258 }3366 }
32593367
3260 // names must be sorted.3368 const error_set_ty = try mod.errorSetFromUnsortedNames(names.keys());
3261 Module.ErrorSet.sortNames(&names);
32623369
3263 error_set.* = .{3370 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
3264 .owner_decl = new_decl_index,3371 .ty = Type.type,
3265 .names = names,3372 .val = error_set_ty.toValue(),
3266 };3373 }, name_strategy, "error", inst);
3267 try new_decl.finalizeNewArena(&new_decl_arena);3374 const new_decl = mod.declPtr(new_decl_index);
3268 return sema.analyzeDeclVal(block, src, 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;
3269}3381}
32703382
3271fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {3383fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
...@@ -3319,7 +3431,8 @@ fn ensureResultUsed(...@@ -3319,7 +3431,8 @@ fn ensureResultUsed(
3319 ty: Type,3431 ty: Type,
3320 src: LazySrcLoc,3432 src: LazySrcLoc,
3321) CompileError!void {3433) CompileError!void {
3322 switch (ty.zigTypeTag()) {3434 const mod = sema.mod;
3435 switch (ty.zigTypeTag(mod)) {
3323 .Void, .NoReturn => return,3436 .Void, .NoReturn => return,
3324 .ErrorSet, .ErrorUnion => {3437 .ErrorSet, .ErrorUnion => {
3325 const msg = msg: {3438 const msg = msg: {
...@@ -3347,11 +3460,12 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3347,11 +3460,12 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3347 const tracy = trace(@src());3460 const tracy = trace(@src());
3348 defer tracy.end();3461 defer tracy.end();
33493462
3463 const mod = sema.mod;
3350 const inst_data = sema.code.instructions.items(.data)[inst].un_node;3464 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3351 const operand = try sema.resolveInst(inst_data.operand);3465 const operand = try sema.resolveInst(inst_data.operand);
3352 const src = inst_data.src();3466 const src = inst_data.src();
3353 const operand_ty = sema.typeOf(operand);3467 const operand_ty = sema.typeOf(operand);
3354 switch (operand_ty.zigTypeTag()) {3468 switch (operand_ty.zigTypeTag(mod)) {
3355 .ErrorSet, .ErrorUnion => {3469 .ErrorSet, .ErrorUnion => {
3356 const msg = msg: {3470 const msg = msg: {
3357 const msg = try sema.errMsg(block, src, "error is discarded", .{});3471 const msg = try sema.errMsg(block, src, "error is discarded", .{});
...@@ -3369,16 +3483,17 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index...@@ -3369,16 +3483,17 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index
3369 const tracy = trace(@src());3483 const tracy = trace(@src());
3370 defer tracy.end();3484 defer tracy.end();
33713485
3486 const mod = sema.mod;
3372 const inst_data = sema.code.instructions.items(.data)[inst].un_node;3487 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3373 const src = inst_data.src();3488 const src = inst_data.src();
3374 const operand = try sema.resolveInst(inst_data.operand);3489 const operand = try sema.resolveInst(inst_data.operand);
3375 const operand_ty = sema.typeOf(operand);3490 const operand_ty = sema.typeOf(operand);
3376 const err_union_ty = if (operand_ty.zigTypeTag() == .Pointer)3491 const err_union_ty = if (operand_ty.zigTypeTag(mod) == .Pointer)
3377 operand_ty.childType()3492 operand_ty.childType(mod)
3378 else3493 else
3379 operand_ty;3494 operand_ty;
3380 if (err_union_ty.zigTypeTag() != .ErrorUnion) return;3495 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) return;
3381 const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag();3496 const payload_ty = err_union_ty.errorUnionPayload(mod).zigTypeTag(mod);
3382 if (payload_ty != .Void and payload_ty != .NoReturn) {3497 if (payload_ty != .Void and payload_ty != .NoReturn) {
3383 const msg = msg: {3498 const msg = msg: {
3384 const msg = try sema.errMsg(block, src, "error union payload is ignored", .{});3499 const msg = try sema.errMsg(block, src, "error union payload is ignored", .{});
...@@ -3407,11 +3522,13 @@ fn indexablePtrLen(...@@ -3407,11 +3522,13 @@ fn indexablePtrLen(
3407 src: LazySrcLoc,3522 src: LazySrcLoc,
3408 object: Air.Inst.Ref,3523 object: Air.Inst.Ref,
3409) CompileError!Air.Inst.Ref {3524) CompileError!Air.Inst.Ref {
3525 const mod = sema.mod;
3410 const object_ty = sema.typeOf(object);3526 const object_ty = sema.typeOf(object);
3411 const is_pointer_to = object_ty.isSinglePointer();3527 const is_pointer_to = object_ty.isSinglePointer(mod);
3412 const indexable_ty = if (is_pointer_to) object_ty.childType() else object_ty;3528 const indexable_ty = if (is_pointer_to) object_ty.childType(mod) else object_ty;
3413 try checkIndexable(sema, block, src, indexable_ty);3529 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);
3415}3532}
34163533
3417fn indexablePtrLenOrNone(3534fn indexablePtrLenOrNone(
...@@ -3420,10 +3537,12 @@ fn indexablePtrLenOrNone(...@@ -3420,10 +3537,12 @@ fn indexablePtrLenOrNone(
3420 src: LazySrcLoc,3537 src: LazySrcLoc,
3421 operand: Air.Inst.Ref,3538 operand: Air.Inst.Ref,
3422) CompileError!Air.Inst.Ref {3539) CompileError!Air.Inst.Ref {
3540 const mod = sema.mod;
3423 const operand_ty = sema.typeOf(operand);3541 const operand_ty = sema.typeOf(operand);
3424 try checkMemOperand(sema, block, src, operand_ty);3542 try checkMemOperand(sema, block, src, operand_ty);
3425 if (operand_ty.ptrSize() == .Many) return .none;3543 if (operand_ty.ptrSize(mod) == .Many) return .none;
3426 return sema.fieldVal(block, src, operand, "len", src);3544 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len");
3545 return sema.fieldVal(block, src, operand, field_name, src);
3427}3546}
34283547
3429fn zirAllocExtended(3548fn zirAllocExtended(
...@@ -3431,6 +3550,7 @@ fn zirAllocExtended(...@@ -3431,6 +3550,7 @@ fn zirAllocExtended(
3431 block: *Block,3550 block: *Block,
3432 extended: Zir.Inst.Extended.InstData,3551 extended: Zir.Inst.Extended.InstData,
3433) CompileError!Air.Inst.Ref {3552) CompileError!Air.Inst.Ref {
3553 const gpa = sema.gpa;
3434 const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);3554 const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);
3435 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node };3555 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node };
3436 const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node };3556 const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node };
...@@ -3451,22 +3571,19 @@ fn zirAllocExtended(...@@ -3451,22 +3571,19 @@ fn zirAllocExtended(
3451 break :blk alignment;3571 break :blk alignment;
3452 } else 0;3572 } 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
3459 if (block.is_comptime or small.is_comptime) {3574 if (block.is_comptime or small.is_comptime) {
3460 if (small.has_type) {3575 if (small.has_type) {
3461 return sema.analyzeComptimeAlloc(block, var_ty, alignment);3576 return sema.analyzeComptimeAlloc(block, var_ty, alignment);
3462 } else {3577 } else {
3463 return sema.addConstant(3578 try sema.air_instructions.append(gpa, .{
3464 inferred_alloc_ty,3579 .tag = .inferred_alloc_comptime,
3465 try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{3580 .data = .{ .inferred_alloc_comptime = .{
3466 .decl_index = undefined,3581 .decl_index = undefined,
3467 .alignment = alignment,3582 .alignment = InternPool.Alignment.fromByteUnits(alignment),
3468 }),3583 .is_const = small.is_const,
3469 );3584 } },
3585 });
3586 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
3470 }3587 }
3471 }3588 }
34723589
...@@ -3484,17 +3601,15 @@ fn zirAllocExtended(...@@ -3484,17 +3601,15 @@ fn zirAllocExtended(
3484 return block.addTy(.alloc, ptr_type);3601 return block.addTy(.alloc, ptr_type);
3485 }3602 }
34863603
3487 // `Sema.addConstant` does not add the instruction to the block because it is3604 const result_index = try block.addInstAsIndex(.{
3488 // not needed in the case of constant values. However here, we plan to "downgrade"3605 .tag = .inferred_alloc,
3489 // to a normal instruction when we hit `resolve_inferred_alloc`. So we append3606 .data = .{ .inferred_alloc = .{
3490 // to the block even though it is currently a `.constant`.3607 .alignment = InternPool.Alignment.fromByteUnits(alignment),
3491 const result = try sema.addConstant(3608 .is_const = small.is_const,
3492 inferred_alloc_ty,3609 } },
3493 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = alignment }),3610 });
3494 );3611 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
3495 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);3612 return Air.indexToRef(result_index);
3496 try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {});
3497 return result;
3498}3613}
34993614
3500fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {3615fn 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...@@ -3508,11 +3623,12 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
3508}3623}
35093624
3510fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {3625fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
3626 const mod = sema.mod;
3511 const inst_data = sema.code.instructions.items(.data)[inst].un_node;3627 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3512 const alloc = try sema.resolveInst(inst_data.operand);3628 const alloc = try sema.resolveInst(inst_data.operand);
3513 const alloc_ty = sema.typeOf(alloc);3629 const alloc_ty = sema.typeOf(alloc);
35143630
3515 var ptr_info = alloc_ty.ptrInfo().data;3631 var ptr_info = alloc_ty.ptrInfo(mod);
3516 const elem_ty = ptr_info.pointee_type;3632 const elem_ty = ptr_info.pointee_type;
35173633
3518 // Detect if all stores to an `.alloc` were comptime-known.3634 // 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...@@ -3558,8 +3674,8 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3558 var anon_decl = try block.startAnonDecl();3674 var anon_decl = try block.startAnonDecl();
3559 defer anon_decl.deinit();3675 defer anon_decl.deinit();
3560 return sema.analyzeDeclRef(try anon_decl.finish(3676 return sema.analyzeDeclRef(try anon_decl.finish(
3561 try elem_ty.copy(anon_decl.arena()),3677 elem_ty,
3562 try store_val.copy(anon_decl.arena()),3678 store_val,
3563 ptr_info.@"align",3679 ptr_info.@"align",
3564 ));3680 ));
3565 }3681 }
...@@ -3568,15 +3684,16 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -3568,15 +3684,16 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3568}3684}
35693685
3570fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref {3686fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref {
3687 const mod = sema.mod;
3571 const alloc_ty = sema.typeOf(alloc);3688 const alloc_ty = sema.typeOf(alloc);
35723689
3573 var ptr_info = alloc_ty.ptrInfo().data;3690 var ptr_info = alloc_ty.ptrInfo(mod);
3574 ptr_info.mutable = false;3691 ptr_info.mutable = false;
3575 const const_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);3692 const const_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
35763693
3577 // Detect if a comptime value simply needs to have its type changed.3694 // Detect if a comptime value simply needs to have its type changed.
3578 if (try sema.resolveMaybeUndefVal(alloc)) |val| {3695 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));
3580 }3697 }
35813698
3582 return block.addBitCast(const_ptr_ty, alloc);3699 return block.addBitCast(const_ptr_ty, alloc);
...@@ -3585,18 +3702,22 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai...@@ -3585,18 +3702,22 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
3585fn zirAllocInferredComptime(3702fn zirAllocInferredComptime(
3586 sema: *Sema,3703 sema: *Sema,
3587 inst: Zir.Inst.Index,3704 inst: Zir.Inst.Index,
3588 inferred_alloc_ty: Type,3705 is_const: bool,
3589) CompileError!Air.Inst.Ref {3706) CompileError!Air.Inst.Ref {
3707 const gpa = sema.gpa;
3590 const src_node = sema.code.instructions.items(.data)[inst].node;3708 const src_node = sema.code.instructions.items(.data)[inst].node;
3591 const src = LazySrcLoc.nodeOffset(src_node);3709 const src = LazySrcLoc.nodeOffset(src_node);
3592 sema.src = src;3710 sema.src = src;
3593 return sema.addConstant(3711
3594 inferred_alloc_ty,3712 try sema.air_instructions.append(gpa, .{
3595 try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{3713 .tag = .inferred_alloc_comptime,
3714 .data = .{ .inferred_alloc_comptime = .{
3596 .decl_index = undefined,3715 .decl_index = undefined,
3597 .alignment = 0,3716 .alignment = .none,
3598 }),3717 .is_const = is_const,
3599 );3718 } },
3719 });
3720 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
3600}3721}
36013722
3602fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {3723fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -3642,104 +3763,103 @@ fn zirAllocInferred(...@@ -3642,104 +3763,103 @@ fn zirAllocInferred(
3642 sema: *Sema,3763 sema: *Sema,
3643 block: *Block,3764 block: *Block,
3644 inst: Zir.Inst.Index,3765 inst: Zir.Inst.Index,
3645 inferred_alloc_ty: Type,3766 is_const: bool,
3646) CompileError!Air.Inst.Ref {3767) CompileError!Air.Inst.Ref {
3647 const tracy = trace(@src());3768 const tracy = trace(@src());
3648 defer tracy.end();3769 defer tracy.end();
36493770
3771 const gpa = sema.gpa;
3650 const src_node = sema.code.instructions.items(.data)[inst].node;3772 const src_node = sema.code.instructions.items(.data)[inst].node;
3651 const src = LazySrcLoc.nodeOffset(src_node);3773 const src = LazySrcLoc.nodeOffset(src_node);
3652 sema.src = src;3774 sema.src = src;
36533775
3654 if (block.is_comptime) {3776 if (block.is_comptime) {
3655 return sema.addConstant(3777 try sema.air_instructions.append(gpa, .{
3656 inferred_alloc_ty,3778 .tag = .inferred_alloc_comptime,
3657 try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{3779 .data = .{ .inferred_alloc_comptime = .{
3658 .decl_index = undefined,3780 .decl_index = undefined,
3659 .alignment = 0,3781 .alignment = .none,
3660 }),3782 .is_const = is_const,
3661 );3783 } },
3784 });
3785 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
3662 }3786 }
36633787
3664 // `Sema.addConstant` does not add the instruction to the block because it is3788 const result_index = try block.addInstAsIndex(.{
3665 // not needed in the case of constant values. However here, we plan to "downgrade"3789 .tag = .inferred_alloc,
3666 // to a normal instruction when we hit `resolve_inferred_alloc`. So we append3790 .data = .{ .inferred_alloc = .{
3667 // to the block even though it is currently a `.constant`.3791 .alignment = .none,
3668 const result = try sema.addConstant(3792 .is_const = is_const,
3669 inferred_alloc_ty,3793 } },
3670 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = 0 }),3794 });
3671 );3795 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
3672 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);3796 return Air.indexToRef(result_index);
3673 try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {});
3674 return result;
3675}3797}
36763798
3677fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {3799fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
3678 const tracy = trace(@src());3800 const tracy = trace(@src());
3679 defer tracy.end();3801 defer tracy.end();
36803802
3803 const mod = sema.mod;
3681 const inst_data = sema.code.instructions.items(.data)[inst].un_node;3804 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3682 const src = inst_data.src();3805 const src = inst_data.src();
3683 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };3806 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
3684 const ptr = try sema.resolveInst(inst_data.operand);3807 const ptr = try sema.resolveInst(inst_data.operand);
3685 const ptr_inst = Air.refToIndex(ptr).?;3808 const ptr_inst = Air.refToIndex(ptr).?;
3686 assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);3809 const target = mod.getTarget();
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();
36953810
3696 switch (ptr_val.tag()) {3811 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
3697 .inferred_alloc_comptime => {3812 .inferred_alloc_comptime => {
3698 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;3813 const iac = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime;
3699 const decl_index = iac.data.decl_index;3814 const decl_index = iac.decl_index;
3700 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);3815 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
37013816
3702 const decl = sema.mod.declPtr(decl_index);3817 const decl = mod.declPtr(decl_index);
3703 const final_elem_ty = try decl.ty.copy(sema.arena);3818 if (iac.is_const) try decl.intern(mod);
3704 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{3819 const final_elem_ty = decl.ty;
3705 .pointee_type = final_elem_ty,3820 const final_ptr_ty = try mod.ptrType(.{
3706 .mutable = true,3821 .child = final_elem_ty.toIntern(),
3707 .@"align" = iac.data.alignment,3822 .flags = .{
3708 .@"addrspace" = target_util.defaultAddressSpace(target, .local),3823 .is_const = false,
3824 .alignment = iac.alignment,
3825 .address_space = target_util.defaultAddressSpace(target, .local),
3826 },
3709 });3827 });
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
3713 try sema.maybeQueueFuncBodyAnalysis(decl_index);3829 try sema.maybeQueueFuncBodyAnalysis(decl_index);
3714 if (var_is_mut) {3830 // Change it to an interned.
3715 sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{3831 sema.air_instructions.set(ptr_inst, .{
3716 .decl_index = decl_index,3832 .tag = .interned,
3717 .runtime_index = block.runtime_index,3833 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3718 });3834 .ty = final_ptr_ty.toIntern(),
3719 } else {3835 .addr = if (!iac.is_const) .{ .mut_decl = .{
3720 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl_index);3836 .decl = decl_index,
3721 }3837 .runtime_index = block.runtime_index,
3838 } } else .{ .decl = decl_index },
3839 } }) },
3840 });
3722 },3841 },
3723 .inferred_alloc => {3842 .inferred_alloc => {
3724 assert(sema.unresolved_inferred_allocs.remove(ptr_inst));3843 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
3725 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;3844 const ia2 = sema.unresolved_inferred_allocs.fetchRemove(ptr_inst).?.value;
3726 const peer_inst_list = inferred_alloc.data.prongs.items(.stored_inst);3845 const peer_inst_list = ia2.prongs.items(.stored_inst);
3727 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);3846 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, .{3848 const final_ptr_ty = try mod.ptrType(.{
3730 .pointee_type = final_elem_ty,3849 .child = final_elem_ty.toIntern(),
3731 .mutable = true,3850 .flags = .{
3732 .@"align" = inferred_alloc.data.alignment,3851 .alignment = ia1.alignment,
3733 .@"addrspace" = target_util.defaultAddressSpace(target, .local),3852 .address_space = target_util.defaultAddressSpace(target, .local),
3853 },
3734 });3854 });
37353855
3736 if (var_is_mut) {3856 if (!ia1.is_const) {
3737 try sema.validateVarType(block, ty_src, final_elem_ty, false);3857 try sema.validateVarType(block, ty_src, final_elem_ty, false);
3738 } else ct: {3858 } else ct: {
3739 // Detect if the value is comptime-known. In such case, the3859 // Detect if the value is comptime-known. In such case, the
3740 // last 3 AIR instructions of the block will look like this:3860 // last 3 AIR instructions of the block will look like this:
3741 //3861 //
3742 // %a = constant3862 // %a = inferred_alloc
3743 // %b = bitcast(%a)3863 // %b = bitcast(%a)
3744 // %c = store(%b, %d)3864 // %c = store(%b, %d)
3745 //3865 //
...@@ -3779,43 +3899,46 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3779,43 +3899,46 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3779 }3899 }
3780 };3900 };
37813901
3782 const const_inst = while (true) {3902 while (true) {
3783 if (search_index == 0) break :ct;3903 if (search_index == 0) break :ct;
3784 search_index -= 1;3904 search_index -= 1;
37853905
3786 const candidate = block.instructions.items[search_index];3906 const candidate = block.instructions.items[search_index];
3907 if (candidate == ptr_inst) break;
3787 switch (air_tags[candidate]) {3908 switch (air_tags[candidate]) {
3788 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,3909 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,
3789 .constant => break candidate,
3790 else => break :ct,3910 else => break :ct,
3791 }3911 }
3792 };3912 }
37933913
3794 const store_op = air_datas[store_inst].bin_op;3914 const store_op = air_datas[store_inst].bin_op;
3795 const store_val = (try sema.resolveMaybeUndefVal(store_op.rhs)) orelse break :ct;3915 const store_val = (try sema.resolveMaybeUndefVal(store_op.rhs)) orelse break :ct;
3796 if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct;3916 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
3799 const new_decl_index = d: {3919 const new_decl_index = d: {
3800 var anon_decl = try block.startAnonDecl();3920 var anon_decl = try block.startAnonDecl();
3801 defer anon_decl.deinit();3921 defer anon_decl.deinit();
3802 const new_decl_index = try anon_decl.finish(3922 const new_decl_index = try anon_decl.finish(
3803 try final_elem_ty.copy(anon_decl.arena()),3923 final_elem_ty,
3804 try store_val.copy(anon_decl.arena()),3924 store_val,
3805 inferred_alloc.data.alignment,3925 ia1.alignment.toByteUnits(0),
3806 );3926 );
3807 break :d new_decl_index;3927 break :d new_decl_index;
3808 };3928 };
3809 try sema.mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);3929 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
38103930
3811 // Even though we reuse the constant instruction, we still remove it from the3931 // Even though we reuse the constant instruction, we still remove it from the
3812 // block so that codegen does not see it.3932 // block so that codegen does not see it.
3813 block.instructions.shrinkRetainingCapacity(search_index);3933 block.instructions.shrinkRetainingCapacity(search_index);
3814 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);3934 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
3815 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);3935 sema.air_instructions.set(ptr_inst, .{
3816 // if bitcast ty ref needs to be made const, make_ptr_const3936 .tag = .interned,
3817 // ZIR handles it later, so we can just use the ty ref here.3937 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3818 air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;3938 .ty = final_ptr_ty.toIntern(),
3939 .addr = .{ .decl = new_decl_index },
3940 } }) },
3941 });
38193942
3820 // Unless the block is comptime, `alloc_inferred` always produces3943 // Unless the block is comptime, `alloc_inferred` always produces
3821 // a runtime constant. The final inferred type needs to be3944 // 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...@@ -3836,18 +3959,19 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3836 // Now we need to go back over all the coerce_result_ptr instructions, which3959 // Now we need to go back over all the coerce_result_ptr instructions, which
3837 // previously inserted a bitcast as a placeholder, and do the logic as if3960 // previously inserted a bitcast as a placeholder, and do the logic as if
3838 // the new result ptr type was available.3961 // the new result ptr type was available.
3839 const placeholders = inferred_alloc.data.prongs.items(.placeholder);3962 const placeholders = ia2.prongs.items(.placeholder);
3840 const gpa = sema.gpa;3963 const gpa = sema.gpa;
38413964
3842 var trash_block = block.makeSubBlock();3965 var trash_block = block.makeSubBlock();
3843 trash_block.is_comptime = false;3966 trash_block.is_comptime = false;
3844 defer trash_block.instructions.deinit(gpa);3967 defer trash_block.instructions.deinit(gpa);
38453968
3846 const mut_final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{3969 const mut_final_ptr_ty = try mod.ptrType(.{
3847 .pointee_type = final_elem_ty,3970 .child = final_elem_ty.toIntern(),
3848 .mutable = true,3971 .flags = .{
3849 .@"align" = inferred_alloc.data.alignment,3972 .alignment = ia1.alignment,
3850 .@"addrspace" = target_util.defaultAddressSpace(target, .local),3973 .address_space = target_util.defaultAddressSpace(target, .local),
3974 },
3851 });3975 });
3852 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);3976 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);
3853 const empty_trash_count = trash_block.instructions.items.len;3977 const empty_trash_count = trash_block.instructions.items.len;
...@@ -3855,7 +3979,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3855,7 +3979,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3855 for (peer_inst_list, placeholders) |peer_inst, placeholder_inst| {3979 for (peer_inst_list, placeholders) |peer_inst, placeholder_inst| {
3856 const sub_ptr_ty = sema.typeOf(Air.indexToRef(placeholder_inst));3980 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)) {
3859 // New result location type is the same as the old one; nothing3983 // New result location type is the same as the old one; nothing
3860 // to do here.3984 // to do here.
3861 continue;3985 continue;
...@@ -3920,27 +4044,28 @@ fn zirArrayBasePtr(...@@ -3920,27 +4044,28 @@ fn zirArrayBasePtr(
3920 block: *Block,4044 block: *Block,
3921 inst: Zir.Inst.Index,4045 inst: Zir.Inst.Index,
3922) CompileError!Air.Inst.Ref {4046) CompileError!Air.Inst.Ref {
4047 const mod = sema.mod;
3923 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4048 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3924 const src = inst_data.src();4049 const src = inst_data.src();
39254050
3926 const start_ptr = try sema.resolveInst(inst_data.operand);4051 const start_ptr = try sema.resolveInst(inst_data.operand);
3927 var base_ptr = start_ptr;4052 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)) {
3929 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),4054 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
3930 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),4055 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
3931 else => break,4056 else => break,
3932 };4057 };
39334058
3934 const elem_ty = sema.typeOf(base_ptr).childType();4059 const elem_ty = sema.typeOf(base_ptr).childType(mod);
3935 switch (elem_ty.zigTypeTag()) {4060 switch (elem_ty.zigTypeTag(mod)) {
3936 .Array, .Vector => return base_ptr,4061 .Array, .Vector => return base_ptr,
3937 .Struct => if (elem_ty.isTuple()) {4062 .Struct => if (elem_ty.isTuple(mod)) {
3938 // TODO validate element count4063 // TODO validate element count
3939 return base_ptr;4064 return base_ptr;
3940 },4065 },
3941 else => {},4066 else => {},
3942 }4067 }
3943 return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType());4068 return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType(mod));
3944}4069}
39454070
3946fn zirFieldBasePtr(4071fn zirFieldBasePtr(
...@@ -3948,27 +4073,30 @@ fn zirFieldBasePtr(...@@ -3948,27 +4073,30 @@ fn zirFieldBasePtr(
3948 block: *Block,4073 block: *Block,
3949 inst: Zir.Inst.Index,4074 inst: Zir.Inst.Index,
3950) CompileError!Air.Inst.Ref {4075) CompileError!Air.Inst.Ref {
4076 const mod = sema.mod;
3951 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4077 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3952 const src = inst_data.src();4078 const src = inst_data.src();
39534079
3954 const start_ptr = try sema.resolveInst(inst_data.operand);4080 const start_ptr = try sema.resolveInst(inst_data.operand);
3955 var base_ptr = start_ptr;4081 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)) {
3957 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),4083 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
3958 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),4084 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
3959 else => break,4085 else => break,
3960 };4086 };
39614087
3962 const elem_ty = sema.typeOf(base_ptr).childType();4088 const elem_ty = sema.typeOf(base_ptr).childType(mod);
3963 switch (elem_ty.zigTypeTag()) {4089 switch (elem_ty.zigTypeTag(mod)) {
3964 .Struct, .Union => return base_ptr,4090 .Struct, .Union => return base_ptr,
3965 else => {},4091 else => {},
3966 }4092 }
3967 return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType());4093 return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType(mod));
3968}4094}
39694095
3970fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4096fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4097 const mod = sema.mod;
3971 const gpa = sema.gpa;4098 const gpa = sema.gpa;
4099 const ip = &mod.intern_pool;
3972 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4100 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
3973 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);4101 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
3974 const args = sema.code.refSlice(extra.end, extra.data.operands_len);4102 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....@@ -3991,7 +4119,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
3991 const object_ty = sema.typeOf(object);4119 const object_ty = sema.typeOf(object);
3992 // Each arg could be an indexable, or a range, in which case the length4120 // Each arg could be an indexable, or a range, in which case the length
3993 // is passed directly as an integer.4121 // is passed directly as an integer.
3994 const is_int = switch (object_ty.zigTypeTag()) {4122 const is_int = switch (object_ty.zigTypeTag(mod)) {
3995 .Int, .ComptimeInt => true,4123 .Int, .ComptimeInt => true,
3996 else => false,4124 else => false,
3997 };4125 };
...@@ -4000,7 +4128,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4000,7 +4128,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4000 .input_index = i,4128 .input_index = i,
4001 } };4129 } };
4002 const arg_len_uncoerced = if (is_int) object else l: {4130 const arg_len_uncoerced = if (is_int) object else l: {
4003 if (!object_ty.isIndexable()) {4131 if (!object_ty.isIndexable(mod)) {
4004 // Instead of using checkIndexable we customize this error.4132 // Instead of using checkIndexable we customize this error.
4005 const msg = msg: {4133 const msg = msg: {
4006 const msg = try sema.errMsg(block, arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)});4134 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....@@ -4010,9 +4138,9 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4010 };4138 };
4011 return sema.failWithOwnedErrorMsg(msg);4139 return sema.failWithOwnedErrorMsg(msg);
4012 }4140 }
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);
4016 };4144 };
4017 const arg_len = try sema.coerce(block, Type.usize, arg_len_uncoerced, arg_src);4145 const arg_len = try sema.coerce(block, Type.usize, arg_len_uncoerced, arg_src);
4018 if (len == .none) {4146 if (len == .none) {
...@@ -4061,7 +4189,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4061,7 +4189,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4061 const object_ty = sema.typeOf(object);4189 const object_ty = sema.typeOf(object);
4062 // Each arg could be an indexable, or a range, in which case the length4190 // Each arg could be an indexable, or a range, in which case the length
4063 // is passed directly as an integer.4191 // is passed directly as an integer.
4064 switch (object_ty.zigTypeTag()) {4192 switch (object_ty.zigTypeTag(mod)) {
4065 .Int, .ComptimeInt => continue,4193 .Int, .ComptimeInt => continue,
4066 else => {},4194 else => {},
4067 }4195 }
...@@ -4096,15 +4224,16 @@ fn validateArrayInitTy(...@@ -4096,15 +4224,16 @@ fn validateArrayInitTy(
4096 block: *Block,4224 block: *Block,
4097 inst: Zir.Inst.Index,4225 inst: Zir.Inst.Index,
4098) CompileError!void {4226) CompileError!void {
4227 const mod = sema.mod;
4099 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4228 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
4100 const src = inst_data.src();4229 const src = inst_data.src();
4101 const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node };4230 const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node };
4102 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;4231 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
4103 const ty = try sema.resolveType(block, ty_src, extra.ty);4232 const ty = try sema.resolveType(block, ty_src, extra.ty);
41044233
4105 switch (ty.zigTypeTag()) {4234 switch (ty.zigTypeTag(mod)) {
4106 .Array => {4235 .Array => {
4107 const array_len = ty.arrayLen();4236 const array_len = ty.arrayLen(mod);
4108 if (extra.init_count != array_len) {4237 if (extra.init_count != array_len) {
4109 return sema.fail(block, src, "expected {d} array elements; found {d}", .{4238 return sema.fail(block, src, "expected {d} array elements; found {d}", .{
4110 array_len, extra.init_count,4239 array_len, extra.init_count,
...@@ -4113,7 +4242,7 @@ fn validateArrayInitTy(...@@ -4113,7 +4242,7 @@ fn validateArrayInitTy(
4113 return;4242 return;
4114 },4243 },
4115 .Vector => {4244 .Vector => {
4116 const array_len = ty.arrayLen();4245 const array_len = ty.arrayLen(mod);
4117 if (extra.init_count != array_len) {4246 if (extra.init_count != array_len) {
4118 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{4247 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{
4119 array_len, extra.init_count,4248 array_len, extra.init_count,
...@@ -4121,9 +4250,9 @@ fn validateArrayInitTy(...@@ -4121,9 +4250,9 @@ fn validateArrayInitTy(
4121 }4250 }
4122 return;4251 return;
4123 },4252 },
4124 .Struct => if (ty.isTuple()) {4253 .Struct => if (ty.isTuple(mod)) {
4125 _ = try sema.resolveTypeFields(ty);4254 _ = try sema.resolveTypeFields(ty);
4126 const array_len = ty.arrayLen();4255 const array_len = ty.arrayLen(mod);
4127 if (extra.init_count > array_len) {4256 if (extra.init_count > array_len) {
4128 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{4257 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
4129 array_len, extra.init_count,4258 array_len, extra.init_count,
...@@ -4141,11 +4270,12 @@ fn validateStructInitTy(...@@ -4141,11 +4270,12 @@ fn validateStructInitTy(
4141 block: *Block,4270 block: *Block,
4142 inst: Zir.Inst.Index,4271 inst: Zir.Inst.Index,
4143) CompileError!void {4272) CompileError!void {
4273 const mod = sema.mod;
4144 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4274 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4145 const src = inst_data.src();4275 const src = inst_data.src();
4146 const ty = try sema.resolveType(block, src, inst_data.operand);4276 const ty = try sema.resolveType(block, src, inst_data.operand);
41474277
4148 switch (ty.zigTypeTag()) {4278 switch (ty.zigTypeTag(mod)) {
4149 .Struct, .Union => return,4279 .Struct, .Union => return,
4150 else => {},4280 else => {},
4151 }4281 }
...@@ -4160,6 +4290,7 @@ fn zirValidateStructInit(...@@ -4160,6 +4290,7 @@ fn zirValidateStructInit(
4160 const tracy = trace(@src());4290 const tracy = trace(@src());
4161 defer tracy.end();4291 defer tracy.end();
41624292
4293 const mod = sema.mod;
4163 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;4294 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;
4164 const init_src = validate_inst.src();4295 const init_src = validate_inst.src();
4165 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);4296 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);
...@@ -4167,8 +4298,8 @@ fn zirValidateStructInit(...@@ -4167,8 +4298,8 @@ fn zirValidateStructInit(
4167 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;4298 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
4168 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;4299 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
4169 const object_ptr = try sema.resolveInst(field_ptr_extra.lhs);4300 const object_ptr = try sema.resolveInst(field_ptr_extra.lhs);
4170 const agg_ty = sema.typeOf(object_ptr).childType();4301 const agg_ty = sema.typeOf(object_ptr).childType(mod);
4171 switch (agg_ty.zigTypeTag()) {4302 switch (agg_ty.zigTypeTag(mod)) {
4172 .Struct => return sema.validateStructInit(4303 .Struct => return sema.validateStructInit(
4173 block,4304 block,
4174 agg_ty,4305 agg_ty,
...@@ -4194,6 +4325,9 @@ fn validateUnionInit(...@@ -4194,6 +4325,9 @@ fn validateUnionInit(
4194 instrs: []const Zir.Inst.Index,4325 instrs: []const Zir.Inst.Index,
4195 union_ptr: Air.Inst.Ref,4326 union_ptr: Air.Inst.Ref,
4196) CompileError!void {4327) CompileError!void {
4328 const mod = sema.mod;
4329 const gpa = sema.gpa;
4330
4197 if (instrs.len != 1) {4331 if (instrs.len != 1) {
4198 const msg = msg: {4332 const msg = msg: {
4199 const msg = try sema.errMsg(4333 const msg = try sema.errMsg(
...@@ -4202,7 +4336,7 @@ fn validateUnionInit(...@@ -4202,7 +4336,7 @@ fn validateUnionInit(
4202 "cannot initialize multiple union fields at once; unions can only have one active field",4336 "cannot initialize multiple union fields at once; unions can only have one active field",
4203 .{},4337 .{},
4204 );4338 );
4205 errdefer msg.destroy(sema.gpa);4339 errdefer msg.destroy(gpa);
42064340
4207 for (instrs[1..]) |inst| {4341 for (instrs[1..]) |inst| {
4208 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4342 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
...@@ -4226,7 +4360,7 @@ fn validateUnionInit(...@@ -4226,7 +4360,7 @@ fn validateUnionInit(
4226 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;4360 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
4227 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node };4361 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node };
4228 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;4362 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));
4230 // Validate the field access but ignore the index since we want the tag enum field index.4364 // Validate the field access but ignore the index since we want the tag enum field index.
4231 _ = try sema.unionFieldIndex(block, union_ty, field_name, field_src);4365 _ = try sema.unionFieldIndex(block, union_ty, field_name, field_src);
4232 const air_tags = sema.air_instructions.items(.tag);4366 const air_tags = sema.air_instructions.items(.tag);
...@@ -4291,21 +4425,25 @@ fn validateUnionInit(...@@ -4291,21 +4425,25 @@ fn validateUnionInit(
4291 break;4425 break;
4292 }4426 }
42934427
4294 const tag_ty = union_ty.unionTagTypeHypothetical();4428 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
4295 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);4429 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);
4296 const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);4430 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
42974431
4298 if (init_val) |val| {4432 if (init_val) |val| {
4299 // Our task is to delete all the `field_ptr` and `store` instructions, and insert4433 // Our task is to delete all the `field_ptr` and `store` instructions, and insert
4300 // instead a single `store` to the result ptr with a comptime union value.4434 // instead a single `store` to the result ptr with a comptime union value.
4301 block.instructions.shrinkRetainingCapacity(first_block_index);4435 block.instructions.shrinkRetainingCapacity(first_block_index);
43024436
4303 var union_val = try Value.Tag.@"union".create(sema.arena, .{4437 var union_val = try mod.intern(.{ .un = .{
4304 .tag = tag_val,4438 .ty = union_ty.toIntern(),
4305 .val = val,4439 .tag = tag_val.toIntern(),
4306 });4440 .val = val.toIntern(),
4307 if (make_runtime) union_val = try Value.Tag.runtime_value.create(sema.arena, union_val);4441 } });
4308 const union_init = try sema.addConstant(union_ty, union_val);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());
4309 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);4447 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
4310 return;4448 return;
4311 } else if (try sema.typeRequiresComptime(union_ty)) {4449 } else if (try sema.typeRequiresComptime(union_ty)) {
...@@ -4323,10 +4461,12 @@ fn validateStructInit(...@@ -4323,10 +4461,12 @@ fn validateStructInit(
4323 init_src: LazySrcLoc,4461 init_src: LazySrcLoc,
4324 instrs: []const Zir.Inst.Index,4462 instrs: []const Zir.Inst.Index,
4325) CompileError!void {4463) CompileError!void {
4464 const mod = sema.mod;
4326 const gpa = sema.gpa;4465 const gpa = sema.gpa;
4466 const ip = &mod.intern_pool;
43274467
4328 // Maps field index to field_ptr index of where it was already initialized.4468 // 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));
4330 defer gpa.free(found_fields);4470 defer gpa.free(found_fields);
4331 @memset(found_fields, 0);4471 @memset(found_fields, 0);
43324472
...@@ -4337,8 +4477,11 @@ fn validateStructInit(...@@ -4337,8 +4477,11 @@ fn validateStructInit(
4337 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node };4477 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node };
4338 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;4478 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
4339 struct_ptr_zir_ref = field_ptr_extra.lhs;4479 struct_ptr_zir_ref = field_ptr_extra.lhs;
4340 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);4480 const field_name = try ip.getOrPutString(
4341 const field_index = if (struct_ty.isTuple())4481 gpa,
4482 sema.code.nullTerminatedString(field_ptr_extra.field_name_start),
4483 );
4484 const field_index = if (struct_ty.isTuple(mod))
4342 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src)4485 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src)
4343 else4486 else
4344 try sema.structFieldIndex(block, struct_ty, field_name, field_src);4487 try sema.structFieldIndex(block, struct_ty, field_name, field_src);
...@@ -4371,9 +4514,9 @@ fn validateStructInit(...@@ -4371,9 +4514,9 @@ fn validateStructInit(
4371 for (found_fields, 0..) |field_ptr, i| {4514 for (found_fields, 0..) |field_ptr, i| {
4372 if (field_ptr != 0) continue;4515 if (field_ptr != 0) continue;
43734516
4374 const default_val = struct_ty.structFieldDefaultValue(i);4517 const default_val = struct_ty.structFieldDefaultValue(i, mod);
4375 if (default_val.tag() == .unreachable_value) {4518 if (default_val.toIntern() == .unreachable_value) {
4376 if (struct_ty.isTuple()) {4519 if (struct_ty.isTuple(mod)) {
4377 const template = "missing tuple field with index {d}";4520 const template = "missing tuple field with index {d}";
4378 if (root_msg) |msg| {4521 if (root_msg) |msg| {
4379 try sema.errNote(block, init_src, msg, template, .{i});4522 try sema.errNote(block, init_src, msg, template, .{i});
...@@ -4382,9 +4525,9 @@ fn validateStructInit(...@@ -4382,9 +4525,9 @@ fn validateStructInit(
4382 }4525 }
4383 continue;4526 continue;
4384 }4527 }
4385 const field_name = struct_ty.structFieldName(i);4528 const field_name = struct_ty.structFieldName(i, mod);
4386 const template = "missing struct field: {s}";4529 const template = "missing struct field: {}";
4387 const args = .{field_name};4530 const args = .{field_name.fmt(ip)};
4388 if (root_msg) |msg| {4531 if (root_msg) |msg| {
4389 try sema.errNote(block, init_src, msg, template, args);4532 try sema.errNote(block, init_src, msg, template, args);
4390 } else {4533 } else {
...@@ -4394,25 +4537,23 @@ fn validateStructInit(...@@ -4394,25 +4537,23 @@ fn validateStructInit(
4394 }4537 }
43954538
4396 const field_src = init_src; // TODO better source location4539 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))
4398 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)4541 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
4399 else4542 else
4400 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);4543 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);
4402 const init = try sema.addConstant(field_ty, default_val);4545 const init = try sema.addConstant(field_ty, default_val);
4403 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);4546 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
4404 }4547 }
44054548
4406 if (root_msg) |msg| {4549 if (root_msg) |msg| {
4407 if (struct_ty.castTag(.@"struct")) |struct_obj| {4550 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4408 const mod = sema.mod;4551 const fqn = try struct_obj.getFullyQualifiedName(mod);
4409 const fqn = try struct_obj.data.getFullyQualifiedName(mod);
4410 defer gpa.free(fqn);
4411 try mod.errNoteNonLazy(4552 try mod.errNoteNonLazy(
4412 struct_obj.data.srcLoc(mod),4553 struct_obj.srcLoc(mod),
4413 msg,4554 msg,
4414 "struct '{s}' declared here",4555 "struct '{}' declared here",
4415 .{fqn},4556 .{fqn.fmt(ip)},
4416 );4557 );
4417 }4558 }
4418 root_msg = null;4559 root_msg = null;
...@@ -4432,14 +4573,14 @@ fn validateStructInit(...@@ -4432,14 +4573,14 @@ fn validateStructInit(
44324573
4433 // We collect the comptime field values in case the struct initialization4574 // We collect the comptime field values in case the struct initialization
4434 // ends up being comptime-known.4575 // 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
4437 field: for (found_fields, 0..) |field_ptr, i| {4578 field: for (found_fields, 0..) |field_ptr, i| {
4438 if (field_ptr != 0) {4579 if (field_ptr != 0) {
4439 // Determine whether the value stored to this pointer is comptime-known.4580 // 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);
4441 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {4582 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {
4442 field_values[i] = opv;4583 field_values[i] = opv.toIntern();
4443 continue;4584 continue;
4444 }4585 }
44454586
...@@ -4504,7 +4645,7 @@ fn validateStructInit(...@@ -4504,7 +4645,7 @@ fn validateStructInit(
4504 first_block_index = @min(first_block_index, block_index);4645 first_block_index = @min(first_block_index, block_index);
4505 }4646 }
4506 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {4647 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4507 field_values[i] = val;4648 field_values[i] = val.toIntern();
4508 } else if (require_comptime) {4649 } else if (require_comptime) {
4509 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;4650 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
4510 return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");4651 return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");
...@@ -4517,9 +4658,9 @@ fn validateStructInit(...@@ -4517,9 +4658,9 @@ fn validateStructInit(
4517 continue :field;4658 continue :field;
4518 }4659 }
45194660
4520 const default_val = struct_ty.structFieldDefaultValue(i);4661 const default_val = struct_ty.structFieldDefaultValue(i, mod);
4521 if (default_val.tag() == .unreachable_value) {4662 if (default_val.toIntern() == .unreachable_value) {
4522 if (struct_ty.isTuple()) {4663 if (struct_ty.isTuple(mod)) {
4523 const template = "missing tuple field with index {d}";4664 const template = "missing tuple field with index {d}";
4524 if (root_msg) |msg| {4665 if (root_msg) |msg| {
4525 try sema.errNote(block, init_src, msg, template, .{i});4666 try sema.errNote(block, init_src, msg, template, .{i});
...@@ -4528,9 +4669,9 @@ fn validateStructInit(...@@ -4528,9 +4669,9 @@ fn validateStructInit(
4528 }4669 }
4529 continue;4670 continue;
4530 }4671 }
4531 const field_name = struct_ty.structFieldName(i);4672 const field_name = struct_ty.structFieldName(i, mod);
4532 const template = "missing struct field: {s}";4673 const template = "missing struct field: {}";
4533 const args = .{field_name};4674 const args = .{field_name.fmt(ip)};
4534 if (root_msg) |msg| {4675 if (root_msg) |msg| {
4535 try sema.errNote(block, init_src, msg, template, args);4676 try sema.errNote(block, init_src, msg, template, args);
4536 } else {4677 } else {
...@@ -4538,18 +4679,17 @@ fn validateStructInit(...@@ -4538,18 +4679,17 @@ fn validateStructInit(
4538 }4679 }
4539 continue;4680 continue;
4540 }4681 }
4541 field_values[i] = default_val;4682 field_values[i] = default_val.toIntern();
4542 }4683 }
45434684
4544 if (root_msg) |msg| {4685 if (root_msg) |msg| {
4545 if (struct_ty.castTag(.@"struct")) |struct_obj| {4686 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4546 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);4687 const fqn = try struct_obj.getFullyQualifiedName(mod);
4547 defer gpa.free(fqn);4688 try mod.errNoteNonLazy(
4548 try sema.mod.errNoteNonLazy(4689 struct_obj.srcLoc(mod),
4549 struct_obj.data.srcLoc(sema.mod),
4550 msg,4690 msg,
4551 "struct '{s}' declared here",4691 "struct '{}' declared here",
4552 .{fqn},4692 .{fqn.fmt(ip)},
4553 );4693 );
4554 }4694 }
4555 root_msg = null;4695 root_msg = null;
...@@ -4561,9 +4701,15 @@ fn validateStructInit(...@@ -4561,9 +4701,15 @@ fn validateStructInit(
4561 // instead a single `store` to the struct_ptr with a comptime struct value.4701 // instead a single `store` to the struct_ptr with a comptime struct value.
45624702
4563 block.instructions.shrinkRetainingCapacity(first_block_index);4703 block.instructions.shrinkRetainingCapacity(first_block_index);
4564 var struct_val = try Value.Tag.aggregate.create(sema.arena, field_values);4704 var struct_val = try mod.intern(.{ .aggregate = .{
4565 if (make_runtime) struct_val = try Value.Tag.runtime_value.create(sema.arena, struct_val);4705 .ty = struct_ty.toIntern(),
4566 const struct_init = try sema.addConstant(struct_ty, struct_val);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());
4567 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);4713 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
4568 return;4714 return;
4569 }4715 }
...@@ -4574,12 +4720,12 @@ fn validateStructInit(...@@ -4574,12 +4720,12 @@ fn validateStructInit(
4574 if (field_ptr != 0) continue;4720 if (field_ptr != 0) continue;
45754721
4576 const field_src = init_src; // TODO better source location4722 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))
4578 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)4724 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
4579 else4725 else
4580 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);4726 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();4727 const field_ty = sema.typeOf(default_field_ptr).childType(mod);
4582 const init = try sema.addConstant(field_ty, field_values[i]);4728 const init = try sema.addConstant(field_ty, field_values[i].toValue());
4583 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);4729 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
4584 }4730 }
4585}4731}
...@@ -4589,6 +4735,7 @@ fn zirValidateArrayInit(...@@ -4589,6 +4735,7 @@ fn zirValidateArrayInit(
4589 block: *Block,4735 block: *Block,
4590 inst: Zir.Inst.Index,4736 inst: Zir.Inst.Index,
4591) CompileError!void {4737) CompileError!void {
4738 const mod = sema.mod;
4592 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;4739 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;
4593 const init_src = validate_inst.src();4740 const init_src = validate_inst.src();
4594 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);4741 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);
...@@ -4596,18 +4743,18 @@ fn zirValidateArrayInit(...@@ -4596,18 +4743,18 @@ fn zirValidateArrayInit(
4596 const first_elem_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;4743 const first_elem_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
4597 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;4744 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;
4598 const array_ptr = try sema.resolveInst(elem_ptr_extra.ptr);4745 const array_ptr = try sema.resolveInst(elem_ptr_extra.ptr);
4599 const array_ty = sema.typeOf(array_ptr).childType();4746 const array_ty = sema.typeOf(array_ptr).childType(mod);
4600 const array_len = array_ty.arrayLen();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)) {
4603 .Struct => {4750 .Struct => {
4604 var root_msg: ?*Module.ErrorMsg = null;4751 var root_msg: ?*Module.ErrorMsg = null;
4605 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);4752 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
46064753
4607 var i = instrs.len;4754 var i = instrs.len;
4608 while (i < array_len) : (i += 1) {4755 while (i < array_len) : (i += 1) {
4609 const default_val = array_ty.structFieldDefaultValue(i);4756 const default_val = array_ty.structFieldDefaultValue(i, mod);
4610 if (default_val.tag() == .unreachable_value) {4757 if (default_val.toIntern() == .unreachable_value) {
4611 const template = "missing tuple field with index {d}";4758 const template = "missing tuple field with index {d}";
4612 if (root_msg) |msg| {4759 if (root_msg) |msg| {
4613 try sema.errNote(block, init_src, msg, template, .{i});4760 try sema.errNote(block, init_src, msg, template, .{i});
...@@ -4642,39 +4789,41 @@ fn zirValidateArrayInit(...@@ -4642,39 +4789,41 @@ fn zirValidateArrayInit(
4642 // at comptime so we have almost nothing to do here. However, in case of a4789 // at comptime so we have almost nothing to do here. However, in case of a
4643 // sentinel-terminated array, the sentinel will not have been populated by4790 // sentinel-terminated array, the sentinel will not have been populated by
4644 // any ZIR instructions at comptime; we need to do that here.4791 // 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| {
4646 const array_len_ref = try sema.addIntUnsigned(Type.usize, array_len);4793 const array_len_ref = try sema.addIntUnsigned(Type.usize, array_len);
4647 const sentinel_ptr = try sema.elemPtrArray(block, init_src, init_src, array_ptr, init_src, array_len_ref, true, true);4794 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);
4649 try sema.storePtr2(block, init_src, sentinel_ptr, init_src, sentinel, init_src, .store);4796 try sema.storePtr2(block, init_src, sentinel_ptr, init_src, sentinel, init_src, .store);
4650 }4797 }
4651 return;4798 return;
4652 }4799 }
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
4654 var array_is_comptime = true;4808 var array_is_comptime = true;
4655 var first_block_index = block.instructions.items.len;4809 var first_block_index = block.instructions.items.len;
4656 var make_runtime = false;4810 var make_runtime = false;
46574811
4658 // Collect the comptime element values in case the array literal ends up4812 // Collect the comptime element values in case the array literal ends up
4659 // being comptime-known.4813 // being comptime-known.
4660 const array_len_s = try sema.usizeCast(block, init_src, array_ty.arrayLenIncludingSentinel());4814 const element_vals = try sema.arena.alloc(
4661 const element_vals = try sema.arena.alloc(Value, array_len_s);4815 InternPool.Index,
4662 const opt_opv = try sema.typeHasOnePossibleValue(array_ty);4816 try sema.usizeCast(block, init_src, array_len),
4817 );
4663 const air_tags = sema.air_instructions.items(.tag);4818 const air_tags = sema.air_instructions.items(.tag);
4664 const air_datas = sema.air_instructions.items(.data);4819 const air_datas = sema.air_instructions.items(.data);
46654820
4666 outer: for (instrs, 0..) |elem_ptr, i| {4821 outer: for (instrs, 0..) |elem_ptr, i| {
4667 // Determine whether the value stored to this pointer is comptime-known.4822 // Determine whether the value stored to this pointer is comptime-known.
46684823
4669 if (array_ty.isTuple()) {4824 if (array_ty.isTuple(mod)) {
4670 if (array_ty.structFieldValueComptime(i)) |opv| {4825 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
4671 element_vals[i] = opv;4826 element_vals[i] = opv.toIntern();
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;
4678 continue;4827 continue;
4679 }4828 }
4680 }4829 }
...@@ -4735,7 +4884,7 @@ fn zirValidateArrayInit(...@@ -4735,7 +4884,7 @@ fn zirValidateArrayInit(
4735 first_block_index = @min(first_block_index, block_index);4884 first_block_index = @min(first_block_index, block_index);
4736 }4885 }
4737 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {4886 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4738 element_vals[i] = val;4887 element_vals[i] = val.toIntern();
4739 } else {4888 } else {
4740 array_is_comptime = false;4889 array_is_comptime = false;
4741 }4890 }
...@@ -4747,50 +4896,55 @@ fn zirValidateArrayInit(...@@ -4747,50 +4896,55 @@ fn zirValidateArrayInit(
47474896
4748 if (array_is_comptime) {4897 if (array_is_comptime) {
4749 if (try sema.resolveDefinedValue(block, init_src, array_ptr)) |ptr_val| {4898 if (try sema.resolveDefinedValue(block, init_src, array_ptr)) |ptr_val| {
4750 if (ptr_val.tag() == .comptime_field_ptr) {4899 switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {
4751 // This store was validated by the individual elem ptrs.4900 .ptr => |ptr| switch (ptr.addr) {
4752 return;4901 .comptime_field => return, // This store was validated by the individual elem ptrs.
4902 else => {},
4903 },
4904 else => {},
4753 }4905 }
4754 }4906 }
47554907
4756 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert4908 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert
4757 // instead a single `store` to the array_ptr with a comptime struct value.4909 // 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
4763 block.instructions.shrinkRetainingCapacity(first_block_index);4910 block.instructions.shrinkRetainingCapacity(first_block_index);
47644911
4765 var array_val = try Value.Tag.aggregate.create(sema.arena, element_vals);4912 var array_val = try mod.intern(.{ .aggregate = .{
4766 if (make_runtime) array_val = try Value.Tag.runtime_value.create(sema.arena, array_val);4913 .ty = array_ty.toIntern(),
4767 const array_init = try sema.addConstant(array_ty, array_val);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());
4768 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);4921 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
4769 }4922 }
4770}4923}
47714924
4772fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {4925fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
4926 const mod = sema.mod;
4773 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4927 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4774 const src = inst_data.src();4928 const src = inst_data.src();
4775 const operand = try sema.resolveInst(inst_data.operand);4929 const operand = try sema.resolveInst(inst_data.operand);
4776 const operand_ty = sema.typeOf(operand);4930 const operand_ty = sema.typeOf(operand);
47774931
4778 if (operand_ty.zigTypeTag() != .Pointer) {4932 if (operand_ty.zigTypeTag(mod) != .Pointer) {
4779 return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(sema.mod)});4933 return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(mod)});
4780 } else switch (operand_ty.ptrSize()) {4934 } else switch (operand_ty.ptrSize(mod)) {
4781 .One, .C => {},4935 .One, .C => {},
4782 .Many => return sema.fail(block, src, "index syntax required for unknown-length pointer 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)}),
4783 .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}),4937 .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(mod)}),
4784 }4938 }
47854939
4786 if ((try sema.typeHasOnePossibleValue(operand_ty.childType())) != null) {4940 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(mod))) != null) {
4787 // No need to validate the actual pointer value, we don't need it!4941 // No need to validate the actual pointer value, we don't need it!
4788 return;4942 return;
4789 }4943 }
47904944
4791 const elem_ty = operand_ty.elemType2();4945 const elem_ty = operand_ty.elemType2(mod);
4792 if (try sema.resolveMaybeUndefVal(operand)) |val| {4946 if (try sema.resolveMaybeUndefVal(operand)) |val| {
4793 if (val.isUndef()) {4947 if (val.isUndef(mod)) {
4794 return sema.fail(block, src, "cannot dereference undefined value", .{});4948 return sema.fail(block, src, "cannot dereference undefined value", .{});
4795 }4949 }
4796 } else if (!(try sema.validateRunTimeType(elem_ty, false))) {4950 } else if (!(try sema.validateRunTimeType(elem_ty, false))) {
...@@ -4799,12 +4953,12 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -4799,12 +4953,12 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
4799 block,4953 block,
4800 src,4954 src,
4801 "values of type '{}' must be comptime-known, but operand value is runtime-known",4955 "values of type '{}' must be comptime-known, but operand value is runtime-known",
4802 .{elem_ty.fmt(sema.mod)},4956 .{elem_ty.fmt(mod)},
4803 );4957 );
4804 errdefer msg.destroy(sema.gpa);4958 errdefer msg.destroy(sema.gpa);
48054959
4806 const src_decl = sema.mod.declPtr(block.src_decl);4960 const src_decl = mod.declPtr(block.src_decl);
4807 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl), elem_ty);4961 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl, mod), elem_ty);
4808 break :msg msg;4962 break :msg msg;
4809 };4963 };
4810 return sema.failWithOwnedErrorMsg(msg);4964 return sema.failWithOwnedErrorMsg(msg);
...@@ -4816,23 +4970,24 @@ fn failWithBadMemberAccess(...@@ -4816,23 +4970,24 @@ fn failWithBadMemberAccess(
4816 block: *Block,4970 block: *Block,
4817 agg_ty: Type,4971 agg_ty: Type,
4818 field_src: LazySrcLoc,4972 field_src: LazySrcLoc,
4819 field_name: []const u8,4973 field_name: InternPool.NullTerminatedString,
4820) CompileError {4974) CompileError {
4821 const kw_name = switch (agg_ty.zigTypeTag()) {4975 const mod = sema.mod;
4976 const kw_name = switch (agg_ty.zigTypeTag(mod)) {
4822 .Union => "union",4977 .Union => "union",
4823 .Struct => "struct",4978 .Struct => "struct",
4824 .Opaque => "opaque",4979 .Opaque => "opaque",
4825 .Enum => "enum",4980 .Enum => "enum",
4826 else => unreachable,4981 else => unreachable,
4827 };4982 };
4828 if (agg_ty.getOwnerDeclOrNull()) |some| if (sema.mod.declIsRoot(some)) {4983 if (agg_ty.getOwnerDeclOrNull(mod)) |some| if (mod.declIsRoot(some)) {
4829 return sema.fail(block, field_src, "root struct of file '{}' has no member named '{s}'", .{4984 return sema.fail(block, field_src, "root struct of file '{}' has no member named '{}'", .{
4830 agg_ty.fmt(sema.mod), field_name,4985 agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool),
4831 });4986 });
4832 };4987 };
4833 const msg = msg: {4988 const msg = msg: {
4834 const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{4989 const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{}'", .{
4835 kw_name, agg_ty.fmt(sema.mod), field_name,4990 kw_name, agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool),
4836 });4991 });
4837 errdefer msg.destroy(sema.gpa);4992 errdefer msg.destroy(sema.gpa);
4838 try sema.addDeclaredHereNote(msg, agg_ty);4993 try sema.addDeclaredHereNote(msg, agg_ty);
...@@ -4846,22 +5001,22 @@ fn failWithBadStructFieldAccess(...@@ -4846,22 +5001,22 @@ fn failWithBadStructFieldAccess(
4846 block: *Block,5001 block: *Block,
4847 struct_obj: *Module.Struct,5002 struct_obj: *Module.Struct,
4848 field_src: LazySrcLoc,5003 field_src: LazySrcLoc,
4849 field_name: []const u8,5004 field_name: InternPool.NullTerminatedString,
4850) CompileError {5005) CompileError {
5006 const mod = sema.mod;
4851 const gpa = sema.gpa;5007 const gpa = sema.gpa;
48525008
4853 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);5009 const fqn = try struct_obj.getFullyQualifiedName(mod);
4854 defer gpa.free(fqn);
48555010
4856 const msg = msg: {5011 const msg = msg: {
4857 const msg = try sema.errMsg(5012 const msg = try sema.errMsg(
4858 block,5013 block,
4859 field_src,5014 field_src,
4860 "no field named '{s}' in struct '{s}'",5015 "no field named '{}' in struct '{}'",
4861 .{ field_name, fqn },5016 .{ field_name.fmt(&mod.intern_pool), fqn.fmt(&mod.intern_pool) },
4862 );5017 );
4863 errdefer msg.destroy(gpa);5018 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", .{});
4865 break :msg msg;5020 break :msg msg;
4866 };5021 };
4867 return sema.failWithOwnedErrorMsg(msg);5022 return sema.failWithOwnedErrorMsg(msg);
...@@ -4872,30 +5027,31 @@ fn failWithBadUnionFieldAccess(...@@ -4872,30 +5027,31 @@ fn failWithBadUnionFieldAccess(
4872 block: *Block,5027 block: *Block,
4873 union_obj: *Module.Union,5028 union_obj: *Module.Union,
4874 field_src: LazySrcLoc,5029 field_src: LazySrcLoc,
4875 field_name: []const u8,5030 field_name: InternPool.NullTerminatedString,
4876) CompileError {5031) CompileError {
5032 const mod = sema.mod;
4877 const gpa = sema.gpa;5033 const gpa = sema.gpa;
48785034
4879 const fqn = try union_obj.getFullyQualifiedName(sema.mod);5035 const fqn = try union_obj.getFullyQualifiedName(mod);
4880 defer gpa.free(fqn);
48815036
4882 const msg = msg: {5037 const msg = msg: {
4883 const msg = try sema.errMsg(5038 const msg = try sema.errMsg(
4884 block,5039 block,
4885 field_src,5040 field_src,
4886 "no field named '{s}' in union '{s}'",5041 "no field named '{}' in union '{}'",
4887 .{ field_name, fqn },5042 .{ field_name.fmt(&mod.intern_pool), fqn.fmt(&mod.intern_pool) },
4888 );5043 );
4889 errdefer msg.destroy(gpa);5044 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", .{});
4891 break :msg msg;5046 break :msg msg;
4892 };5047 };
4893 return sema.failWithOwnedErrorMsg(msg);5048 return sema.failWithOwnedErrorMsg(msg);
4894}5049}
48955050
4896fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void {5051fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void {
4897 const src_loc = decl_ty.declSrcLocOrNull(sema.mod) orelse return;5052 const mod = sema.mod;
4898 const category = switch (decl_ty.zigTypeTag()) {5053 const src_loc = decl_ty.declSrcLocOrNull(mod) orelse return;
5054 const category = switch (decl_ty.zigTypeTag(mod)) {
4899 .Union => "union",5055 .Union => "union",
4900 .Struct => "struct",5056 .Struct => "struct",
4901 .Enum => "enum",5057 .Enum => "enum",
...@@ -4903,7 +5059,7 @@ fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !vo...@@ -4903,7 +5059,7 @@ fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !vo
4903 .ErrorSet => "error set",5059 .ErrorSet => "error set",
4904 else => unreachable,5060 else => unreachable,
4905 };5061 };
4906 try sema.mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category});5062 try mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category});
4907}5063}
49085064
4909fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {5065fn 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...@@ -4919,17 +5075,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
4919 const src: LazySrcLoc = sema.src;5075 const src: LazySrcLoc = sema.src;
4920 blk: {5076 blk: {
4921 const ptr_inst = Air.refToIndex(ptr) orelse break :blk;5077 const ptr_inst = Air.refToIndex(ptr) orelse break :blk;
4922 if (sema.air_instructions.items(.tag)[ptr_inst] != .constant) break :blk;5078 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
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()) {
4926 .inferred_alloc_comptime => {5079 .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;
4928 return sema.storeToInferredAllocComptime(block, src, operand, iac);5081 return sema.storeToInferredAllocComptime(block, src, operand, iac);
4929 },5082 },
4930 .inferred_alloc => {5083 .inferred_alloc => {
4931 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;5084 const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
4932 return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);5085 return sema.storeToInferredAlloc(block, ptr, operand, ia);
4933 },5086 },
4934 else => break :blk,5087 else => break :blk,
4935 }5088 }
...@@ -4947,18 +5100,16 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi...@@ -4947,18 +5100,16 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
4947 const ptr = try sema.resolveInst(bin_inst.lhs);5100 const ptr = try sema.resolveInst(bin_inst.lhs);
4948 const operand = try sema.resolveInst(bin_inst.rhs);5101 const operand = try sema.resolveInst(bin_inst.rhs);
4949 const ptr_inst = Air.refToIndex(ptr).?;5102 const ptr_inst = Air.refToIndex(ptr).?;
4950 assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
4951 const air_datas = sema.air_instructions.items(.data);5103 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]) {
4955 .inferred_alloc_comptime => {5106 .inferred_alloc_comptime => {
4956 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;5107 const iac = &air_datas[ptr_inst].inferred_alloc_comptime;
4957 return sema.storeToInferredAllocComptime(block, src, operand, iac);5108 return sema.storeToInferredAllocComptime(block, src, operand, iac);
4958 },5109 },
4959 .inferred_alloc => {5110 .inferred_alloc => {
4960 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;5111 const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
4961 return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);5112 return sema.storeToInferredAlloc(block, ptr, operand, ia);
4962 },5113 },
4963 else => unreachable,5114 else => unreachable,
4964 }5115 }
...@@ -4969,14 +5120,14 @@ fn storeToInferredAlloc(...@@ -4969,14 +5120,14 @@ fn storeToInferredAlloc(
4969 block: *Block,5120 block: *Block,
4970 ptr: Air.Inst.Ref,5121 ptr: Air.Inst.Ref,
4971 operand: Air.Inst.Ref,5122 operand: Air.Inst.Ref,
4972 inferred_alloc: *Value.Payload.InferredAlloc,5123 inferred_alloc: *InferredAlloc,
4973) CompileError!void {5124) CompileError!void {
4974 // Create a store instruction as a placeholder. This will be replaced by a5125 // Create a store instruction as a placeholder. This will be replaced by a
4975 // proper store sequence once we know the stored type.5126 // proper store sequence once we know the stored type.
4976 const dummy_store = try block.addBinOp(.store, ptr, operand);5127 const dummy_store = try block.addBinOp(.store, ptr, operand);
4977 // Add the stored instruction to the set we will use to resolve peer types5128 // Add the stored instruction to the set we will use to resolve peer types
4978 // for the inferred allocation.5129 // for the inferred allocation.
4979 try inferred_alloc.data.prongs.append(sema.arena, .{5130 try inferred_alloc.prongs.append(sema.arena, .{
4980 .stored_inst = operand,5131 .stored_inst = operand,
4981 .placeholder = Air.refToIndex(dummy_store).?,5132 .placeholder = Air.refToIndex(dummy_store).?,
4982 });5133 });
...@@ -4987,20 +5138,21 @@ fn storeToInferredAllocComptime(...@@ -4987,20 +5138,21 @@ fn storeToInferredAllocComptime(
4987 block: *Block,5138 block: *Block,
4988 src: LazySrcLoc,5139 src: LazySrcLoc,
4989 operand: Air.Inst.Ref,5140 operand: Air.Inst.Ref,
4990 iac: *Value.Payload.InferredAllocComptime,5141 iac: *Air.Inst.Data.InferredAllocComptime,
4991) CompileError!void {5142) CompileError!void {
4992 const operand_ty = sema.typeOf(operand);5143 const operand_ty = sema.typeOf(operand);
4993 // There will be only one store_to_inferred_ptr because we are running at comptime.5144 // There will be only one store_to_inferred_ptr because we are running at comptime.
4994 // The alloc will turn into a Decl.5145 // The alloc will turn into a Decl.
4995 if (try sema.resolveMaybeUndefValAllowVariables(operand)) |operand_val| store: {5146 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;
4997 var anon_decl = try block.startAnonDecl();5148 var anon_decl = try block.startAnonDecl();
4998 defer anon_decl.deinit();5149 defer anon_decl.deinit();
4999 iac.data.decl_index = try anon_decl.finish(5150 iac.decl_index = try anon_decl.finish(
5000 try operand_ty.copy(anon_decl.arena()),5151 operand_ty,
5001 try operand_val.copy(anon_decl.arena()),5152 operand_val,
5002 iac.data.alignment,5153 iac.alignment.toByteUnits(0),
5003 );5154 );
5155 try sema.comptime_mutable_decls.append(iac.decl_index);
5004 return;5156 return;
5005 }5157 }
50065158
...@@ -5028,6 +5180,7 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v...@@ -5028,6 +5180,7 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
5028 const tracy = trace(@src());5180 const tracy = trace(@src());
5029 defer tracy.end();5181 defer tracy.end();
50305182
5183 const mod = sema.mod;
5031 const zir_tags = sema.code.instructions.items(.tag);5184 const zir_tags = sema.code.instructions.items(.tag);
5032 const zir_datas = sema.code.instructions.items(.data);5185 const zir_datas = sema.code.instructions.items(.data);
5033 const inst_data = zir_datas[inst].pl_node;5186 const inst_data = zir_datas[inst].pl_node;
...@@ -5046,9 +5199,9 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v...@@ -5046,9 +5199,9 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
5046 // %b = store(%a, %c)5199 // %b = store(%a, %c)
5047 // Where %c is an error union or error set. In such case we need to add5200 // Where %c is an error union or error set. In such case we need to add
5048 // to the current function's inferred error set, if any.5201 // to the current function's inferred error set, if any.
5049 if (is_ret and (sema.typeOf(operand).zigTypeTag() == .ErrorUnion or5202 if (is_ret and (sema.typeOf(operand).zigTypeTag(mod) == .ErrorUnion or
5050 sema.typeOf(operand).zigTypeTag() == .ErrorSet) and5203 sema.typeOf(operand).zigTypeTag(mod) == .ErrorSet) and
5051 sema.fn_ret_ty.zigTypeTag() == .ErrorUnion)5204 sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion)
5052 {5205 {
5053 try sema.addToInferredErrorSet(operand);5206 try sema.addToInferredErrorSet(operand);
5054 }5207 }
...@@ -5072,47 +5225,30 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -5072,47 +5225,30 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
5072 return sema.addStrLit(block, bytes);5225 return sema.addStrLit(block, bytes);
5073}5226}
50745227
5075fn addStrLit(sema: *Sema, block: *Block, zir_bytes: []const u8) CompileError!Air.Inst.Ref {5228fn addStrLit(sema: *Sema, block: *Block, 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.
5079 const mod = sema.mod;5229 const mod = sema.mod;
5080 const gpa = sema.gpa;5230 const gpa = sema.gpa;
5081 const string_bytes = &mod.string_literal_bytes;5231 // TODO: write something like getCoercedInts to avoid needing to dupe
5082 const StringLiteralAdapter = Module.StringLiteralAdapter;5232 const duped_bytes = try sema.arena.dupe(u8, bytes);
5083 const StringLiteralContext = Module.StringLiteralContext;5233 const ty = try mod.arrayType(.{
5084 try string_bytes.ensureUnusedCapacity(gpa, zir_bytes.len);5234 .len = bytes.len,
5085 const gop = try mod.string_literal_table.getOrPutContextAdapted(gpa, zir_bytes, StringLiteralAdapter{5235 .child = .u8_type,
5086 .bytes = string_bytes,5236 .sentinel = .zero_u8,
5087 }, StringLiteralContext{
5088 .bytes = string_bytes,
5089 });5237 });
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);
5090 if (!gop.found_existing) {5243 if (!gop.found_existing) {
5091 gop.key_ptr.* = .{5244 const new_decl_index = try mod.createAnonymousDecl(block, .{
5092 .index = @intCast(u32, string_bytes.items.len),5245 .ty = ty,
5093 .len = @intCast(u32, zir_bytes.len),5246 .val = val.toValue(),
5094 };5247 });
5095 string_bytes.appendSliceAssumeCapacity(zir_bytes);5248 gop.value_ptr.* = new_decl_index;
5096 gop.value_ptr.* = .none;5249 try mod.finalizeAnonDecl(new_decl_index);
5097 }5250 }
5098 const decl_index = gop.value_ptr.unwrap() orelse di: {5251 return sema.analyzeDeclRef(gop.value_ptr.*);
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);
5116}5252}
51175253
5118fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5254fn 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...@@ -5121,7 +5257,7 @@ fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
5121 defer tracy.end();5257 defer tracy.end();
51225258
5123 const int = sema.code.instructions.items(.data)[inst].int;5259 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);
5125}5261}
51265262
5127fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5263fn 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....@@ -5129,38 +5265,43 @@ fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
5129 const tracy = trace(@src());5265 const tracy = trace(@src());
5130 defer tracy.end();5266 defer tracy.end();
51315267
5132 const arena = sema.arena;5268 const mod = sema.mod;
5133 const int = sema.code.instructions.items(.data)[inst].str;5269 const int = sema.code.instructions.items(.data)[inst].str;
5134 const byte_count = int.len * @sizeOf(std.math.big.Limb);5270 const byte_count = int.len * @sizeOf(std.math.big.Limb);
5135 const limb_bytes = sema.code.string_bytes[int.start..][0..byte_count];5271 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);
5137 @memcpy(mem.sliceAsBytes(limbs), limb_bytes);5277 @memcpy(mem.sliceAsBytes(limbs), limb_bytes);
51385278
5139 return sema.addConstant(5279 return sema.addConstant(
5140 Type.initTag(.comptime_int),5280 Type.comptime_int,
5141 try Value.Tag.int_big_positive.create(arena, limbs),5281 try mod.intValue_big(Type.comptime_int, .{
5282 .limbs = limbs,
5283 .positive = true,
5284 }),
5142 );5285 );
5143}5286}
51445287
5145fn zirFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5288fn zirFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5146 _ = block;5289 _ = block;
5147 const arena = sema.arena;
5148 const number = sema.code.instructions.items(.data)[inst].float;5290 const number = sema.code.instructions.items(.data)[inst].float;
5149 return sema.addConstant(5291 return sema.addConstant(
5150 Type.initTag(.comptime_float),5292 Type.comptime_float,
5151 try Value.Tag.float_64.create(arena, number),5293 try sema.mod.floatValue(Type.comptime_float, number),
5152 );5294 );
5153}5295}
51545296
5155fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5297fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5156 _ = block;5298 _ = block;
5157 const arena = sema.arena;
5158 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;5299 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5159 const extra = sema.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;5300 const extra = sema.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;
5160 const number = extra.get();5301 const number = extra.get();
5161 return sema.addConstant(5302 return sema.addConstant(
5162 Type.initTag(.comptime_float),5303 Type.comptime_float,
5163 try Value.Tag.float_128.create(arena, number),5304 try sema.mod.floatValue(Type.comptime_float, number),
5164 );5305 );
5165}5306}
51665307
...@@ -5179,7 +5320,9 @@ fn zirCompileLog(...@@ -5179,7 +5320,9 @@ fn zirCompileLog(
5179 sema: *Sema,5320 sema: *Sema,
5180 extended: Zir.Inst.Extended.InstData,5321 extended: Zir.Inst.Extended.InstData,
5181) CompileError!Air.Inst.Ref {5322) 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);
5183 defer sema.mod.compile_log_text = managed.moveToUnmanaged();5326 defer sema.mod.compile_log_text = managed.moveToUnmanaged();
5184 const writer = managed.writer();5327 const writer = managed.writer();
51855328
...@@ -5192,19 +5335,18 @@ fn zirCompileLog(...@@ -5192,19 +5335,18 @@ fn zirCompileLog(
51925335
5193 const arg = try sema.resolveInst(arg_ref);5336 const arg = try sema.resolveInst(arg_ref);
5194 const arg_ty = sema.typeOf(arg);5337 const arg_ty = sema.typeOf(arg);
5195 if (try sema.resolveMaybeUndefVal(arg)) |val| {5338 if (try sema.resolveMaybeUndefLazyVal(arg)) |val| {
5196 try sema.resolveLazyValue(val);
5197 try writer.print("@as({}, {})", .{5339 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),
5199 });5341 });
5200 } else {5342 } else {
5201 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(sema.mod)});5343 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(mod)});
5202 }5344 }
5203 }5345 }
5204 try writer.print("\n", .{});5346 try writer.print("\n", .{});
52055347
5206 const decl_index = if (sema.func) |some| some.owner_decl else sema.owner_decl_index;5348 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);
5208 if (!gop.found_existing) {5350 if (!gop.found_existing) {
5209 gop.value_ptr.* = src_node;5351 gop.value_ptr.* = src_node;
5210 }5352 }
...@@ -5235,6 +5377,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError...@@ -5235,6 +5377,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
5235 const tracy = trace(@src());5377 const tracy = trace(@src());
5236 defer tracy.end();5378 defer tracy.end();
52375379
5380 const mod = sema.mod;
5238 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;5381 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5239 const src = inst_data.src();5382 const src = inst_data.src();
5240 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);5383 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...@@ -5284,7 +5427,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
5284 try sema.analyzeBody(&loop_block, body);5427 try sema.analyzeBody(&loop_block, body);
52855428
5286 const loop_block_len = loop_block.instructions.items.len;5429 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)) {
5288 // If the loop ended with a noreturn terminator, then there is no way for it to loop,5431 // If the loop ended with a noreturn terminator, then there is no way for it to loop,
5289 // so we can just use the block instead.5432 // so we can just use the block instead.
5290 try child_block.instructions.appendSlice(gpa, loop_block.instructions.items);5433 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...@@ -5311,7 +5454,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
53115454
5312 // we check this here to avoid undefined symbols5455 // we check this here to avoid undefined symbols
5313 if (!@import("build_options").have_llvm)5456 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
5316 var c_import_buf = std.ArrayList(u8).init(sema.gpa);5459 var c_import_buf = std.ArrayList(u8).init(sema.gpa);
5317 defer c_import_buf.deinit();5460 defer c_import_buf.deinit();
...@@ -5354,7 +5497,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -5354,7 +5497,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5354 if (!mod.comp.bin_file.options.link_libc)5497 if (!mod.comp.bin_file.options.link_libc)
5355 try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});5498 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);
5358 if (!gop.found_existing) {5501 if (!gop.found_existing) {
5359 var errs = try std.ArrayListUnmanaged(Module.CImportError).initCapacity(sema.gpa, c_import_res.errors.len);5502 var errs = try std.ArrayListUnmanaged(Module.CImportError).initCapacity(sema.gpa, c_import_res.errors.len);
5360 errdefer {5503 errdefer {
...@@ -5537,7 +5680,7 @@ fn analyzeBlockBody(...@@ -5537,7 +5680,7 @@ fn analyzeBlockBody(
55375680
5538 // Blocks must terminate with noreturn instruction.5681 // Blocks must terminate with noreturn instruction.
5539 assert(child_block.instructions.items.len != 0);5682 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
5542 if (merges.results.items.len == 0) {5685 if (merges.results.items.len == 0) {
5543 // No need for a block instruction. We can put the new instructions5686 // No need for a block instruction. We can put the new instructions
...@@ -5578,7 +5721,7 @@ fn analyzeBlockBody(...@@ -5578,7 +5721,7 @@ fn analyzeBlockBody(
5578 try sema.errNote(child_block, runtime_src, msg, "runtime control flow here", .{});5721 try sema.errNote(child_block, runtime_src, msg, "runtime control flow here", .{});
55795722
5580 const child_src_decl = mod.declPtr(child_block.src_decl);5723 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
5583 break :msg msg;5726 break :msg msg;
5584 };5727 };
...@@ -5649,15 +5792,16 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -5649,15 +5792,16 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
5649 const tracy = trace(@src());5792 const tracy = trace(@src());
5650 defer tracy.end();5793 defer tracy.end();
56515794
5795 const mod = sema.mod;
5652 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;5796 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5653 const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;5797 const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
5654 const src = inst_data.src();5798 const src = inst_data.src();
5655 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };5799 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
5656 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };5800 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));
5658 const decl_index = if (extra.namespace != .none) index_blk: {5802 const decl_index = if (extra.namespace != .none) index_blk: {
5659 const container_ty = try sema.resolveType(block, operand_src, extra.namespace);5803 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
5662 const maybe_index = try sema.lookupInNamespace(block, operand_src, container_namespace, decl_name, false);5806 const maybe_index = try sema.lookupInNamespace(block, operand_src, container_namespace, decl_name, false);
5663 break :index_blk maybe_index orelse5807 break :index_blk maybe_index orelse
...@@ -5671,10 +5815,10 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -5671,10 +5815,10 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
5671 else => |e| return e,5815 else => |e| return e,
5672 };5816 };
5673 {5817 {
5674 try sema.mod.ensureDeclAnalyzed(decl_index);5818 try mod.ensureDeclAnalyzed(decl_index);
5675 const exported_decl = sema.mod.declPtr(decl_index);5819 const exported_decl = mod.declPtr(decl_index);
5676 if (exported_decl.val.castTag(.function)) |some| {5820 if (exported_decl.val.getFunction(mod)) |function| {
5677 return sema.analyzeExport(block, src, options, some.data.owner_decl);5821 return sema.analyzeExport(block, src, options, function.owner_decl);
5678 }5822 }
5679 }5823 }
5680 try sema.analyzeExport(block, src, options, decl_index);5824 try sema.analyzeExport(block, src, options, decl_index);
...@@ -5697,17 +5841,14 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -5697,17 +5841,14 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
5697 },5841 },
5698 else => |e| return e,5842 else => |e| return e,
5699 };5843 };
5700 const decl_index = switch (operand.val.tag()) {5844 const decl_index = if (operand.val.getFunction(sema.mod)) |function| function.owner_decl else blk: {
5701 .function => operand.val.castTag(.function).?.data.owner_decl,5845 var anon_decl = try block.startAnonDecl();
5702 else => blk: {5846 defer anon_decl.deinit();
5703 var anon_decl = try block.startAnonDecl();5847 break :blk try anon_decl.finish(
5704 defer anon_decl.deinit();5848 operand.ty,
5705 break :blk try anon_decl.finish(5849 operand.val,
5706 try operand.ty.copy(anon_decl.arena()),5850 0,
5707 try operand.val.copy(anon_decl.arena()),5851 );
5708 0,
5709 );
5710 },
5711 };5852 };
5712 try sema.analyzeExport(block, src, options, decl_index);5853 try sema.analyzeExport(block, src, options, decl_index);
5713}5854}
...@@ -5716,13 +5857,13 @@ pub fn analyzeExport(...@@ -5716,13 +5857,13 @@ pub fn analyzeExport(
5716 sema: *Sema,5857 sema: *Sema,
5717 block: *Block,5858 block: *Block,
5718 src: LazySrcLoc,5859 src: LazySrcLoc,
5719 borrowed_options: std.builtin.ExportOptions,5860 options: Module.Export.Options,
5720 exported_decl_index: Decl.Index,5861 exported_decl_index: Decl.Index,
5721) !void {5862) !void {
5722 const Export = Module.Export;5863 const Export = Module.Export;
5723 const mod = sema.mod;5864 const mod = sema.mod;
57245865
5725 if (borrowed_options.linkage == .Internal) {5866 if (options.linkage == .Internal) {
5726 return;5867 return;
5727 }5868 }
57285869
...@@ -5731,11 +5872,11 @@ pub fn analyzeExport(...@@ -5731,11 +5872,11 @@ pub fn analyzeExport(
57315872
5732 if (!try sema.validateExternType(exported_decl.ty, .other)) {5873 if (!try sema.validateExternType(exported_decl.ty, .other)) {
5733 const msg = msg: {5874 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)});
5735 errdefer msg.destroy(sema.gpa);5876 errdefer msg.destroy(sema.gpa);
57365877
5737 const src_decl = sema.mod.declPtr(block.src_decl);5878 const src_decl = mod.declPtr(block.src_decl);
5738 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);5879 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), exported_decl.ty, .other);
57395880
5740 try sema.addDeclaredHereNote(msg, exported_decl.ty);5881 try sema.addDeclaredHereNote(msg, exported_decl.ty);
5741 break :msg msg;5882 break :msg msg;
...@@ -5744,15 +5885,15 @@ pub fn analyzeExport(...@@ -5744,15 +5885,15 @@ pub fn analyzeExport(
5744 }5885 }
57455886
5746 // TODO: some backends might support re-exporting extern decls5887 // TODO: some backends might support re-exporting extern decls
5747 if (exported_decl.isExtern()) {5888 if (exported_decl.isExtern(mod)) {
5748 return sema.fail(block, src, "export target cannot be extern", .{});5889 return sema.fail(block, src, "export target cannot be extern", .{});
5749 }5890 }
57505891
5751 // This decl is alive no matter what, since it's being exported5892 // This decl is alive no matter what, since it's being exported
5752 mod.markDeclAlive(exported_decl);5893 try mod.markDeclAlive(exported_decl);
5753 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);5894 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
57545895
5755 const gpa = mod.gpa;5896 const gpa = sema.gpa;
57565897
5757 try mod.decl_exports.ensureUnusedCapacity(gpa, 1);5898 try mod.decl_exports.ensureUnusedCapacity(gpa, 1);
5758 try mod.export_owners.ensureUnusedCapacity(gpa, 1);5899 try mod.export_owners.ensureUnusedCapacity(gpa, 1);
...@@ -5760,19 +5901,8 @@ pub fn analyzeExport(...@@ -5760,19 +5901,8 @@ pub fn analyzeExport(
5760 const new_export = try gpa.create(Export);5901 const new_export = try gpa.create(Export);
5761 errdefer gpa.destroy(new_export);5902 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
5769 new_export.* = .{5904 new_export.* = .{
5770 .options = .{5905 .opts = options,
5771 .name = symbol_name,
5772 .linkage = borrowed_options.linkage,
5773 .section = section,
5774 .visibility = borrowed_options.visibility,
5775 },
5776 .src = src,5906 .src = src,
5777 .owner_decl = sema.owner_decl_index,5907 .owner_decl = sema.owner_decl_index,
5778 .src_decl = block.src_decl,5908 .src_decl = block.src_decl,
...@@ -5798,6 +5928,7 @@ pub fn analyzeExport(...@@ -5798,6 +5928,7 @@ pub fn analyzeExport(
5798}5928}
57995929
5800fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {5930fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
5931 const mod = sema.mod;
5801 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;5932 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
5802 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };5933 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
5803 const src = LazySrcLoc.nodeOffset(extra.node);5934 const src = LazySrcLoc.nodeOffset(extra.node);
...@@ -5807,11 +5938,12 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5807,11 +5938,12 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5807 alignment,5938 alignment,
5808 });5939 });
5809 }5940 }
5810 const func = sema.func orelse5941 const func_index = sema.func_index.unwrap() orelse
5811 return sema.fail(block, src, "@setAlignStack outside function body", .{});5942 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);5945 const fn_owner_decl = mod.declPtr(func.owner_decl);
5814 switch (fn_owner_decl.ty.fnCallingConvention()) {5946 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
5815 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),5947 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
5816 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),5948 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
5817 else => if (block.inlining != null) {5949 else => if (block.inlining != null) {
...@@ -5819,7 +5951,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5819,7 +5951,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5819 },5951 },
5820 }5952 }
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);
5823 if (gop.found_existing) {5955 if (gop.found_existing) {
5824 const msg = msg: {5956 const msg = msg: {
5825 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});5957 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
...@@ -5971,10 +6103,11 @@ fn addDbgVar(...@@ -5971,10 +6103,11 @@ fn addDbgVar(
5971 air_tag: Air.Inst.Tag,6103 air_tag: Air.Inst.Tag,
5972 name: []const u8,6104 name: []const u8,
5973) CompileError!void {6105) CompileError!void {
6106 const mod = sema.mod;
5974 const operand_ty = sema.typeOf(operand);6107 const operand_ty = sema.typeOf(operand);
5975 switch (air_tag) {6108 switch (air_tag) {
5976 .dbg_var_ptr => {6109 .dbg_var_ptr => {
5977 if (!(try sema.typeHasRuntimeBits(operand_ty.childType()))) return;6110 if (!(try sema.typeHasRuntimeBits(operand_ty.childType(mod)))) return;
5978 },6111 },
5979 .dbg_var_val => {6112 .dbg_var_val => {
5980 if (!(try sema.typeHasRuntimeBits(operand_ty))) return;6113 if (!(try sema.typeHasRuntimeBits(operand_ty))) return;
...@@ -6003,29 +6136,32 @@ fn addDbgVar(...@@ -6003,29 +6136,32 @@ fn addDbgVar(
6003}6136}
60046137
6005fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6138fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6139 const mod = sema.mod;
6006 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;6140 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
6007 const src = inst_data.src();6141 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));
6009 const decl_index = try sema.lookupIdentifier(block, src, decl_name);6143 const decl_index = try sema.lookupIdentifier(block, src, decl_name);
6010 try sema.addReferencedBy(block, src, decl_index);6144 try sema.addReferencedBy(block, src, decl_index);
6011 return sema.analyzeDeclRef(decl_index);6145 return sema.analyzeDeclRef(decl_index);
6012}6146}
60136147
6014fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6148fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6149 const mod = sema.mod;
6015 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;6150 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
6016 const src = inst_data.src();6151 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));
6018 const decl = try sema.lookupIdentifier(block, src, decl_name);6153 const decl = try sema.lookupIdentifier(block, src, decl_name);
6019 return sema.analyzeDeclVal(block, src, decl);6154 return sema.analyzeDeclVal(block, src, decl);
6020}6155}
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;
6023 var namespace = block.namespace;6159 var namespace = block.namespace;
6024 while (true) {6160 while (true) {
6025 if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl_index| {6161 if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl_index| {
6026 return decl_index;6162 return decl_index;
6027 }6163 }
6028 namespace = namespace.parent orelse break;6164 namespace = mod.namespacePtr(namespace).parent.unwrap() orelse break;
6029 }6165 }
6030 unreachable; // AstGen detects use of undeclared identifier errors.6166 unreachable; // AstGen detects use of undeclared identifier errors.
6031}6167}
...@@ -6036,21 +6172,22 @@ fn lookupInNamespace(...@@ -6036,21 +6172,22 @@ fn lookupInNamespace(
6036 sema: *Sema,6172 sema: *Sema,
6037 block: *Block,6173 block: *Block,
6038 src: LazySrcLoc,6174 src: LazySrcLoc,
6039 namespace: *Namespace,6175 namespace_index: Namespace.Index,
6040 ident_name: []const u8,6176 ident_name: InternPool.NullTerminatedString,
6041 observe_usingnamespace: bool,6177 observe_usingnamespace: bool,
6042) CompileError!?Decl.Index {6178) CompileError!?Decl.Index {
6043 const mod = sema.mod;6179 const mod = sema.mod;
60446180
6045 const namespace_decl_index = namespace.getDeclIndex();6181 const namespace = mod.namespacePtr(namespace_index);
6046 const namespace_decl = sema.mod.declPtr(namespace_decl_index);6182 const namespace_decl_index = namespace.getDeclIndex(mod);
6183 const namespace_decl = mod.declPtr(namespace_decl_index);
6047 if (namespace_decl.analysis == .file_failure) {6184 if (namespace_decl.analysis == .file_failure) {
6048 try mod.declareDeclDependency(sema.owner_decl_index, namespace_decl_index);6185 try mod.declareDeclDependency(sema.owner_decl_index, namespace_decl_index);
6049 return error.AnalysisFail;6186 return error.AnalysisFail;
6050 }6187 }
60516188
6052 if (observe_usingnamespace and namespace.usingnamespace_set.count() != 0) {6189 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
6055 const gpa = sema.gpa;6192 const gpa = sema.gpa;
6056 var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{};6193 var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{};
...@@ -6069,7 +6206,7 @@ fn lookupInNamespace(...@@ -6069,7 +6206,7 @@ fn lookupInNamespace(
6069 // Skip decls which are not marked pub, which are in a different6206 // Skip decls which are not marked pub, which are in a different
6070 // file than the `a.b`/`@hasDecl` syntax.6207 // file than the `a.b`/`@hasDecl` syntax.
6071 const decl = mod.declPtr(decl_index);6208 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])) {
6073 try candidates.append(gpa, decl_index);6210 try candidates.append(gpa, decl_index);
6074 }6211 }
6075 }6212 }
...@@ -6080,15 +6217,15 @@ fn lookupInNamespace(...@@ -6080,15 +6217,15 @@ fn lookupInNamespace(
6080 if (sub_usingnamespace_decl_index == sema.owner_decl_index) continue;6217 if (sub_usingnamespace_decl_index == sema.owner_decl_index) continue;
6081 const sub_usingnamespace_decl = mod.declPtr(sub_usingnamespace_decl_index);6218 const sub_usingnamespace_decl = mod.declPtr(sub_usingnamespace_decl_index);
6082 const sub_is_pub = entry.value_ptr.*;6219 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)) {
6084 // Skip usingnamespace decls which are not marked pub, which are in6221 // Skip usingnamespace decls which are not marked pub, which are in
6085 // a different file than the `a.b`/`@hasDecl` syntax.6222 // a different file than the `a.b`/`@hasDecl` syntax.
6086 continue;6223 continue;
6087 }6224 }
6088 try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index);6225 try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index);
6089 const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data;6226 const ns_ty = sub_usingnamespace_decl.val.toType();
6090 const sub_ns = ns_ty.getNamespace().?;6227 const sub_ns = ns_ty.getNamespace(mod).?;
6091 try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope());6228 try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope(mod));
6092 }6229 }
6093 }6230 }
60946231
...@@ -6116,7 +6253,7 @@ fn lookupInNamespace(...@@ -6116,7 +6253,7 @@ fn lookupInNamespace(
6116 errdefer msg.destroy(gpa);6253 errdefer msg.destroy(gpa);
6117 for (candidates.items) |candidate_index| {6254 for (candidates.items) |candidate_index| {
6118 const candidate = mod.declPtr(candidate_index);6255 const candidate = mod.declPtr(candidate_index);
6119 const src_loc = candidate.srcLoc();6256 const src_loc = candidate.srcLoc(mod);
6120 try mod.errNoteNonLazy(src_loc, msg, "declared here", .{});6257 try mod.errNoteNonLazy(src_loc, msg, "declared here", .{});
6121 }6258 }
6122 break :msg msg;6259 break :msg msg;
...@@ -6129,9 +6266,6 @@ fn lookupInNamespace(...@@ -6129,9 +6266,6 @@ fn lookupInNamespace(
6129 return decl_index;6266 return decl_index;
6130 }6267 }
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 });
6135 // TODO This dependency is too strong. Really, it should only be a dependency6269 // TODO This dependency is too strong. Really, it should only be a dependency
6136 // on the non-existence of `ident_name` in the namespace. We can lessen the number of6270 // on the non-existence of `ident_name` in the namespace. We can lessen the number of
6137 // outdated declarations by making this dependency more sophisticated.6271 // outdated declarations by making this dependency more sophisticated.
...@@ -6140,22 +6274,28 @@ fn lookupInNamespace(...@@ -6140,22 +6274,28 @@ fn lookupInNamespace(
6140}6274}
61416275
6142fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {6276fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
6277 const mod = sema.mod;
6143 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;6278 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;
6144 if (func_val.isUndef()) return null;6279 if (func_val.isUndef(mod)) return null;
6145 const owner_decl_index = switch (func_val.tag()) {6280 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
6146 .extern_fn => func_val.castTag(.extern_fn).?.data.owner_decl,6281 .extern_func => |extern_func| extern_func.decl,
6147 .function => func_val.castTag(.function).?.data.owner_decl,6282 .func => |func| mod.funcPtr(func.index).owner_decl,
6148 .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,6283 .ptr => |ptr| switch (ptr.addr) {
6284 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,
6285 else => return null,
6286 },
6149 else => return null,6287 else => return null,
6150 };6288 };
6151 return sema.mod.declPtr(owner_decl_index);6289 return mod.declPtr(owner_decl_index);
6152}6290}
61536291
6154pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {6292pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
6293 const mod = sema.mod;
6294 const gpa = sema.gpa;
6155 const src = sema.src;6295 const src = sema.src;
61566296
6157 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return .none;6297 if (!mod.backendSupportsFeature(.error_return_trace)) return .none;
6158 if (!sema.mod.comp.bin_file.options.error_return_tracing) return .none;6298 if (!mod.comp.bin_file.options.error_return_tracing) return .none;
61596299
6160 if (block.is_comptime)6300 if (block.is_comptime)
6161 return .none;6301 return .none;
...@@ -6168,7 +6308,8 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref...@@ -6168,7 +6308,8 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
6168 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,6308 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
6169 else => |e| return e,6309 else => |e| return e,
6170 };6310 };
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) {
6172 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,6313 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
6173 else => |e| return e,6314 else => |e| return e,
6174 };6315 };
...@@ -6191,6 +6332,8 @@ fn popErrorReturnTrace(...@@ -6191,6 +6332,8 @@ fn popErrorReturnTrace(
6191 operand: Air.Inst.Ref,6332 operand: Air.Inst.Ref,
6192 saved_error_trace_index: Air.Inst.Ref,6333 saved_error_trace_index: Air.Inst.Ref,
6193) CompileError!void {6334) CompileError!void {
6335 const mod = sema.mod;
6336 const gpa = sema.gpa;
6194 var is_non_error: ?bool = null;6337 var is_non_error: ?bool = null;
6195 var is_non_error_inst: Air.Inst.Ref = undefined;6338 var is_non_error_inst: Air.Inst.Ref = undefined;
6196 if (operand != .none) {6339 if (operand != .none) {
...@@ -6205,15 +6348,16 @@ fn popErrorReturnTrace(...@@ -6205,15 +6348,16 @@ fn popErrorReturnTrace(
62056348
6206 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");6349 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
6207 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);6350 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);
6209 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);6352 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);
6211 try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store);6355 try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store);
6212 } else if (is_non_error == null) {6356 } else if (is_non_error == null) {
6213 // The result might be an error. If it is, we leave the error trace alone. If it isn't, we need6357 // The result might be an error. If it is, we leave the error trace alone. If it isn't, we need
6214 // to pop any error trace that may have been propagated from our arguments.6358 // 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);
6217 const cond_block_inst = try block.addInstAsIndex(.{6361 const cond_block_inst = try block.addInstAsIndex(.{
6218 .tag = .block,6362 .tag = .block,
6219 .data = .{6363 .data = .{
...@@ -6225,28 +6369,29 @@ fn popErrorReturnTrace(...@@ -6225,28 +6369,29 @@ fn popErrorReturnTrace(
6225 });6369 });
62266370
6227 var then_block = block.makeSubBlock();6371 var then_block = block.makeSubBlock();
6228 defer then_block.instructions.deinit(sema.gpa);6372 defer then_block.instructions.deinit(gpa);
62296373
6230 // If non-error, then pop the error return trace by restoring the index.6374 // If non-error, then pop the error return trace by restoring the index.
6231 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");6375 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
6232 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);6376 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);
6234 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);6378 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);
6236 try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store);6381 try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store);
6237 _ = try then_block.addBr(cond_block_inst, Air.Inst.Ref.void_value);6382 _ = try then_block.addBr(cond_block_inst, Air.Inst.Ref.void_value);
62386383
6239 // Otherwise, do nothing6384 // Otherwise, do nothing
6240 var else_block = block.makeSubBlock();6385 var else_block = block.makeSubBlock();
6241 defer else_block.instructions.deinit(sema.gpa);6386 defer else_block.instructions.deinit(gpa);
6242 _ = try else_block.addBr(cond_block_inst, Air.Inst.Ref.void_value);6387 _ = 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 +
6245 then_block.instructions.items.len + else_block.instructions.items.len +6390 then_block.instructions.items.len + else_block.instructions.items.len +
6246 @typeInfo(Air.Block).Struct.fields.len + 1); // +1 for the sole .cond_br instruction in the .block6391 @typeInfo(Air.Block).Struct.fields.len + 1); // +1 for the sole .cond_br instruction in the .block
62476392
6248 const cond_br_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);6393 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 = .{
6250 .operand = is_non_error_inst,6395 .operand = is_non_error_inst,
6251 .payload = sema.addExtraAssumeCapacity(Air.CondBr{6396 .payload = sema.addExtraAssumeCapacity(Air.CondBr{
6252 .then_body_len = @intCast(u32, then_block.instructions.items.len),6397 .then_body_len = @intCast(u32, then_block.instructions.items.len),
...@@ -6270,6 +6415,7 @@ fn zirCall(...@@ -6270,6 +6415,7 @@ fn zirCall(
6270 const tracy = trace(@src());6415 const tracy = trace(@src());
6271 defer tracy.end();6416 defer tracy.end();
62726417
6418 const mod = sema.mod;
6273 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6419 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6274 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };6420 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
6275 const call_src = inst_data.src();6421 const call_src = inst_data.src();
...@@ -6288,7 +6434,7 @@ fn zirCall(...@@ -6288,7 +6434,7 @@ fn zirCall(
6288 .direct => .{ .direct = try sema.resolveInst(extra.data.callee) },6434 .direct => .{ .direct = try sema.resolveInst(extra.data.callee) },
6289 .field => blk: {6435 .field => blk: {
6290 const object_ptr = try sema.resolveInst(extra.data.obj_ptr);6436 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));
6292 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };6438 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
6293 break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src);6439 break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src);
6294 },6440 },
...@@ -6320,8 +6466,7 @@ fn zirCall(...@@ -6320,8 +6466,7 @@ fn zirCall(
6320 var input_is_error = false;6466 var input_is_error = false;
6321 const block_index = @intCast(Air.Inst.Index, block.instructions.items.len);6467 const block_index = @intCast(Air.Inst.Index, block.instructions.items.len);
63226468
6323 const func_ty_info = func_ty.fnInfo();6469 const fn_params_len = mod.typeToFunc(func_ty).?.param_types.len;
6324 const fn_params_len = func_ty_info.param_types.len;
6325 const parent_comptime = block.is_comptime;6470 const parent_comptime = block.is_comptime;
6326 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.6471 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
6327 var extra_index: usize = 0;6472 var extra_index: usize = 0;
...@@ -6330,32 +6475,33 @@ fn zirCall(...@@ -6330,32 +6475,33 @@ fn zirCall(
6330 extra_index += 1;6475 extra_index += 1;
6331 arg_index += 1;6476 arg_index += 1;
6332 }) {6477 }) {
6478 const func_ty_info = mod.typeToFunc(func_ty).?;
6333 const arg_end = sema.code.extra[extra.end + extra_index];6479 const arg_end = sema.code.extra[extra.end + extra_index];
6334 defer arg_start = arg_end;6480 defer arg_start = arg_end;
63356481
6336 // Generate args to comptime params in comptime block.6482 // Generate args to comptime params in comptime block.
6337 defer block.is_comptime = parent_comptime;6483 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))) {
6339 block.is_comptime = true;6485 block.is_comptime = true;
6340 // TODO set comptime_reason6486 // TODO set comptime_reason
6341 }6487 }
63426488
6343 sema.inst_map.putAssumeCapacity(inst, inst: {6489 sema.inst_map.putAssumeCapacity(inst, inst: {
6344 if (arg_index >= fn_params_len)6490 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)
6348 break :inst Air.Inst.Ref.generic_poison_type;6494 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());
6351 });6497 });
63526498
6353 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);6499 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
6354 const resolved_ty = sema.typeOf(resolved);6500 const resolved_ty = sema.typeOf(resolved);
6355 if (resolved_ty.zigTypeTag() == .NoReturn) {6501 if (resolved_ty.zigTypeTag(mod) == .NoReturn) {
6356 return resolved;6502 return resolved;
6357 }6503 }
6358 if (resolved_ty.isError()) {6504 if (resolved_ty.isError(mod)) {
6359 input_is_error = true;6505 input_is_error = true;
6360 }6506 }
6361 resolved_args[arg_index] = resolved;6507 resolved_args[arg_index] = resolved;
...@@ -6367,7 +6513,7 @@ fn zirCall(...@@ -6367,7 +6513,7 @@ fn zirCall(
6367 // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction.6513 // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction.
6368 const call_dbg_node = inst - 1;6514 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 and6516 if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_tracing and
6371 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))6517 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))
6372 {6518 {
6373 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {6519 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {
...@@ -6375,15 +6521,16 @@ fn zirCall(...@@ -6375,15 +6521,16 @@ fn zirCall(
6375 };6521 };
63766522
6377 const return_ty = sema.typeOf(call_inst);6523 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))
6379 return call_inst; // call to "fn(...) noreturn", don't pop6525 return call_inst; // call to "fn(...) noreturn", don't pop
63806526
6381 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only6527 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
6382 // need to clean-up our own trace if we were passed to a non-error-handling expression.6528 // 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))) {
6384 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");6530 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
6385 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);6531 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
6388 // Insert a save instruction before the arg resolution + call instructions we just generated6535 // Insert a save instruction before the arg resolution + call instructions we just generated
6389 const save_inst = try block.insertInst(block_index, .{6536 const save_inst = try block.insertInst(block_index, .{
...@@ -6417,24 +6564,24 @@ fn checkCallArgumentCount(...@@ -6417,24 +6564,24 @@ fn checkCallArgumentCount(
6417 total_args: usize,6564 total_args: usize,
6418 member_fn: bool,6565 member_fn: bool,
6419) !Type {6566) !Type {
6567 const mod = sema.mod;
6420 const func_ty = func_ty: {6568 const func_ty = func_ty: {
6421 switch (callee_ty.zigTypeTag()) {6569 switch (callee_ty.zigTypeTag(mod)) {
6422 .Fn => break :func_ty callee_ty,6570 .Fn => break :func_ty callee_ty,
6423 .Pointer => {6571 .Pointer => {
6424 const ptr_info = callee_ty.ptrInfo().data;6572 const ptr_info = callee_ty.ptrInfo(mod);
6425 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {6573 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Fn) {
6426 break :func_ty ptr_info.pointee_type;6574 break :func_ty ptr_info.pointee_type;
6427 }6575 }
6428 },6576 },
6429 .Optional => {6577 .Optional => {
6430 var buf: Type.Payload.ElemType = undefined;6578 const opt_child = callee_ty.optionalChild(mod);
6431 const opt_child = callee_ty.optionalChild(&buf);6579 if (opt_child.zigTypeTag(mod) == .Fn or (opt_child.isSinglePointer(mod) and
6432 if (opt_child.zigTypeTag() == .Fn or (opt_child.isSinglePointer() and6580 opt_child.childType(mod).zigTypeTag(mod) == .Fn))
6433 opt_child.childType().zigTypeTag() == .Fn))
6434 {6581 {
6435 const msg = msg: {6582 const msg = msg: {
6436 const msg = try sema.errMsg(block, func_src, "cannot call optional type '{}'", .{6583 const msg = try sema.errMsg(block, func_src, "cannot call optional type '{}'", .{
6437 callee_ty.fmt(sema.mod),6584 callee_ty.fmt(mod),
6438 });6585 });
6439 errdefer msg.destroy(sema.gpa);6586 errdefer msg.destroy(sema.gpa);
6440 try sema.errNote(block, func_src, msg, "consider using '.?', 'orelse' or 'if'", .{});6587 try sema.errNote(block, func_src, msg, "consider using '.?', 'orelse' or 'if'", .{});
...@@ -6445,10 +6592,10 @@ fn checkCallArgumentCount(...@@ -6445,10 +6592,10 @@ fn checkCallArgumentCount(
6445 },6592 },
6446 else => {},6593 else => {},
6447 }6594 }
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)});
6449 };6596 };
64506597
6451 const func_ty_info = func_ty.fnInfo();6598 const func_ty_info = mod.typeToFunc(func_ty).?;
6452 const fn_params_len = func_ty_info.param_types.len;6599 const fn_params_len = func_ty_info.param_types.len;
6453 const args_len = total_args - @boolToInt(member_fn);6600 const args_len = total_args - @boolToInt(member_fn);
6454 if (func_ty_info.is_var_args) {6601 if (func_ty_info.is_var_args) {
...@@ -6475,7 +6622,7 @@ fn checkCallArgumentCount(...@@ -6475,7 +6622,7 @@ fn checkCallArgumentCount(
6475 );6622 );
6476 errdefer msg.destroy(sema.gpa);6623 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", .{});
6479 break :msg msg;6626 break :msg msg;
6480 };6627 };
6481 return sema.failWithOwnedErrorMsg(msg);6628 return sema.failWithOwnedErrorMsg(msg);
...@@ -6488,22 +6635,23 @@ fn callBuiltin(...@@ -6488,22 +6635,23 @@ fn callBuiltin(
6488 modifier: std.builtin.CallModifier,6635 modifier: std.builtin.CallModifier,
6489 args: []const Air.Inst.Ref,6636 args: []const Air.Inst.Ref,
6490) !void {6637) !void {
6638 const mod = sema.mod;
6491 const callee_ty = sema.typeOf(builtin_fn);6639 const callee_ty = sema.typeOf(builtin_fn);
6492 const func_ty = func_ty: {6640 const func_ty = func_ty: {
6493 switch (callee_ty.zigTypeTag()) {6641 switch (callee_ty.zigTypeTag(mod)) {
6494 .Fn => break :func_ty callee_ty,6642 .Fn => break :func_ty callee_ty,
6495 .Pointer => {6643 .Pointer => {
6496 const ptr_info = callee_ty.ptrInfo().data;6644 const ptr_info = callee_ty.ptrInfo(mod);
6497 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {6645 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Fn) {
6498 break :func_ty ptr_info.pointee_type;6646 break :func_ty ptr_info.pointee_type;
6499 }6647 }
6500 },6648 },
6501 else => {},6649 else => {},
6502 }6650 }
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)});
6504 };6652 };
65056653
6506 const func_ty_info = func_ty.fnInfo();6654 const func_ty_info = mod.typeToFunc(func_ty).?;
6507 const fn_params_len = func_ty_info.param_types.len;6655 const fn_params_len = func_ty_info.param_types.len;
6508 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {6656 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {
6509 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });6657 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });
...@@ -6511,76 +6659,6 @@ fn callBuiltin(...@@ -6511,76 +6659,6 @@ fn callBuiltin(
6511 _ = try sema.analyzeCall(block, builtin_fn, func_ty, sema.src, sema.src, modifier, false, args, null, null);6659 _ = try sema.analyzeCall(block, builtin_fn, func_ty, sema.src, sema.src, modifier, false, args, null, null);
6512}6660}
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
6584fn analyzeCall(6662fn analyzeCall(
6585 sema: *Sema,6663 sema: *Sema,
6586 block: *Block,6664 block: *Block,
...@@ -6597,7 +6675,7 @@ fn analyzeCall(...@@ -6597,7 +6675,7 @@ fn analyzeCall(
6597 const mod = sema.mod;6675 const mod = sema.mod;
65986676
6599 const callee_ty = sema.typeOf(func);6677 const callee_ty = sema.typeOf(func);
6600 const func_ty_info = func_ty.fnInfo();6678 const func_ty_info = mod.typeToFunc(func_ty).?;
6601 const fn_params_len = func_ty_info.param_types.len;6679 const fn_params_len = func_ty_info.param_types.len;
6602 const cc = func_ty_info.cc;6680 const cc = func_ty_info.cc;
6603 if (cc == .Naked) {6681 if (cc == .Naked) {
...@@ -6611,7 +6689,7 @@ fn analyzeCall(...@@ -6611,7 +6689,7 @@ fn analyzeCall(
6611 );6689 );
6612 errdefer msg.destroy(sema.gpa);6690 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", .{});
6615 break :msg msg;6693 break :msg msg;
6616 };6694 };
6617 return sema.failWithOwnedErrorMsg(msg);6695 return sema.failWithOwnedErrorMsg(msg);
...@@ -6645,7 +6723,7 @@ fn analyzeCall(...@@ -6645,7 +6723,7 @@ fn analyzeCall(
6645 var comptime_reason_buf: Block.ComptimeReason = undefined;6723 var comptime_reason_buf: Block.ComptimeReason = undefined;
6646 var comptime_reason: ?*const Block.ComptimeReason = null;6724 var comptime_reason: ?*const Block.ComptimeReason = null;
6647 if (!is_comptime_call) {6725 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| {
6649 is_comptime_call = ct;6727 is_comptime_call = ct;
6650 if (ct) {6728 if (ct) {
6651 // stage1 can't handle doing this directly6729 // stage1 can't handle doing this directly
...@@ -6653,7 +6731,7 @@ fn analyzeCall(...@@ -6653,7 +6731,7 @@ fn analyzeCall(
6653 .block = block,6731 .block = block,
6654 .func = func,6732 .func = func,
6655 .func_src = func_src,6733 .func_src = func_src,
6656 .return_ty = func_ty_info.return_type,6734 .return_ty = func_ty_info.return_type.toType(),
6657 } };6735 } };
6658 comptime_reason = &comptime_reason_buf;6736 comptime_reason = &comptime_reason_buf;
6659 }6737 }
...@@ -6671,7 +6749,7 @@ fn analyzeCall(...@@ -6671,7 +6749,7 @@ fn analyzeCall(
6671 func,6749 func,
6672 func_src,6750 func_src,
6673 call_src,6751 call_src,
6674 func_ty_info,6752 func_ty,
6675 ensure_result_used,6753 ensure_result_used,
6676 uncasted_args,6754 uncasted_args,
6677 call_tag,6755 call_tag,
...@@ -6691,7 +6769,7 @@ fn analyzeCall(...@@ -6691,7 +6769,7 @@ fn analyzeCall(
6691 .block = block,6769 .block = block,
6692 .func = func,6770 .func = func,
6693 .func_src = func_src,6771 .func_src = func_src,
6694 .return_ty = func_ty_info.return_type,6772 .return_ty = func_ty_info.return_type.toType(),
6695 } };6773 } };
6696 comptime_reason = &comptime_reason_buf;6774 comptime_reason = &comptime_reason_buf;
6697 },6775 },
...@@ -6708,18 +6786,21 @@ fn analyzeCall(...@@ -6708,18 +6786,21 @@ fn analyzeCall(
6708 if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);6786 if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);
6709 return err;6787 return err;
6710 };6788 };
6711 const module_fn = switch (func_val.tag()) {6789 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
6712 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,6790 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
6713 .function => func_val.castTag(.function).?.data,
6714 .extern_fn => return sema.fail(block, call_src, "{s} call of extern function", .{
6715 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),6791 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6716 }),6792 }),
6717 else => {6793 .func => |function| function.index,
6718 assert(callee_ty.isPtrAtRuntime());6794 .ptr => |ptr| switch (ptr.addr) {
6719 return sema.fail(block, call_src, "{s} call of function pointer", .{6795 .decl => |decl| mod.declPtr(decl).val.getFunctionIndex(mod).unwrap().?,
6720 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),6796 else => {
6721 });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 },
6722 },6802 },
6803 else => unreachable,
6723 };6804 };
6724 if (func_ty_info.is_var_args) {6805 if (func_ty_info.is_var_args) {
6725 return sema.fail(block, call_src, "{s} call of variadic function", .{6806 return sema.fail(block, call_src, "{s} call of variadic function", .{
...@@ -6752,8 +6833,9 @@ fn analyzeCall(...@@ -6752,8 +6833,9 @@ fn analyzeCall(
6752 // In order to save a bit of stack space, directly modify Sema rather6833 // In order to save a bit of stack space, directly modify Sema rather
6753 // than create a child one.6834 // than create a child one.
6754 const parent_zir = sema.code;6835 const parent_zir = sema.code;
6836 const module_fn = mod.funcPtr(module_fn_index);
6755 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);6837 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;
6757 defer sema.code = parent_zir;6839 defer sema.code = parent_zir;
67586840
6759 try mod.declareDeclDependencyType(sema.owner_decl_index, module_fn.owner_decl, .function_body);6841 try mod.declareDeclDependencyType(sema.owner_decl_index, module_fn.owner_decl, .function_body);
...@@ -6767,14 +6849,17 @@ fn analyzeCall(...@@ -6767,14 +6849,17 @@ fn analyzeCall(
6767 }6849 }
67686850
6769 const parent_func = sema.func;6851 const parent_func = sema.func;
6852 const parent_func_index = sema.func_index;
6770 sema.func = module_fn;6853 sema.func = module_fn;
6854 sema.func_index = module_fn_index.toOptional();
6771 defer sema.func = parent_func;6855 defer sema.func = parent_func;
6856 defer sema.func_index = parent_func_index;
67726857
6773 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;6858 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
6774 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;6859 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;
6775 defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index;6860 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);
6778 defer wip_captures.deinit();6863 defer wip_captures.deinit();
67796864
6780 var child_block: Block = .{6865 var child_block: Block = .{
...@@ -6797,28 +6882,18 @@ fn analyzeCall(...@@ -6797,28 +6882,18 @@ fn analyzeCall(
6797 defer child_block.instructions.deinit(gpa);6882 defer child_block.instructions.deinit(gpa);
6798 defer merges.deinit(gpa);6883 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
6813 try sema.emitBackwardBranch(block, call_src);6885 try sema.emitBackwardBranch(block, call_src);
68146886
6815 // Whether this call should be memoized, set to false if the call can mutate6887 // Whether this call should be memoized, set to false if the call can mutate comptime state.
6816 // comptime state.
6817 var should_memoize = true;6888 var should_memoize = true;
68186889
6819 var new_fn_info = fn_owner_decl.ty.fnInfo();6890 // If it's a comptime function call, we need to memoize it as long as no external
6820 new_fn_info.param_types = try sema.arena.alloc(Type, new_fn_info.param_types.len);6891 // comptime memory is mutated.
6821 new_fn_info.comptime_params = (try sema.arena.alloc(bool, new_fn_info.param_types.len)).ptr;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
6823 // This will have return instructions analyzed as break instructions to6898 // This will have return instructions analyzed as break instructions to
6824 // the block_inst above. Here we are performing "comptime/inline semantic analysis"6899 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
...@@ -6837,31 +6912,31 @@ fn analyzeCall(...@@ -6837,31 +6912,31 @@ fn analyzeCall(
6837 &child_block,6912 &child_block,
6838 .unneeded,6913 .unneeded,
6839 inst,6914 inst,
6840 new_fn_info,6915 &new_fn_info,
6841 &arg_i,6916 &arg_i,
6842 uncasted_args,6917 uncasted_args,
6843 is_comptime_call,6918 is_comptime_call,
6844 &should_memoize,6919 &should_memoize,
6845 memoized_call_key,6920 memoized_arg_values,
6846 func_ty_info.param_types,6921 mod.typeToFunc(func_ty).?.param_types,
6847 func,6922 func,
6848 &has_comptime_args,6923 &has_comptime_args,
6849 ) catch |err| switch (err) {6924 ) catch |err| switch (err) {
6850 error.NeededSourceLocation => {6925 error.NeededSourceLocation => {
6851 _ = sema.inst_map.remove(inst);6926 _ = sema.inst_map.remove(inst);
6852 const decl = sema.mod.declPtr(block.src_decl);6927 const decl = mod.declPtr(block.src_decl);
6853 try sema.analyzeInlineCallArg(6928 try sema.analyzeInlineCallArg(
6854 block,6929 block,
6855 &child_block,6930 &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),
6857 inst,6932 inst,
6858 new_fn_info,6933 &new_fn_info,
6859 &arg_i,6934 &arg_i,
6860 uncasted_args,6935 uncasted_args,
6861 is_comptime_call,6936 is_comptime_call,
6862 &should_memoize,6937 &should_memoize,
6863 memoized_call_key,6938 memoized_arg_values,
6864 func_ty_info.param_types,6939 mod.typeToFunc(func_ty).?.param_types,
6865 func,6940 func,
6866 &has_comptime_args,6941 &has_comptime_args,
6867 );6942 );
...@@ -6897,21 +6972,15 @@ fn analyzeCall(...@@ -6897,21 +6972,15 @@ fn analyzeCall(
6897 // Create a fresh inferred error set type for inline/comptime calls.6972 // Create a fresh inferred error set type for inline/comptime calls.
6898 const fn_ret_ty = blk: {6973 const fn_ret_ty = blk: {
6899 if (module_fn.hasInferredErrorSet(mod)) {6974 if (module_fn.hasInferredErrorSet(mod)) {
6900 const node = try sema.gpa.create(Module.Fn.InferredErrorSetListNode);6975 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
6901 node.data = .{ .func = module_fn };6976 .func = module_fn_index,
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,
6910 });6977 });
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);
6911 }6980 }
6912 break :blk bare_return_type;6981 break :blk bare_return_type;
6913 };6982 };
6914 new_fn_info.return_type = fn_ret_ty;6983 new_fn_info.return_type = fn_ret_ty.toIntern();
6915 const parent_fn_ret_ty = sema.fn_ret_ty;6984 const parent_fn_ret_ty = sema.fn_ret_ty;
6916 sema.fn_ret_ty = fn_ret_ty;6985 sema.fn_ret_ty = fn_ret_ty;
6917 defer sema.fn_ret_ty = parent_fn_ret_ty;6986 defer sema.fn_ret_ty = parent_fn_ret_ty;
...@@ -6920,23 +6989,22 @@ fn analyzeCall(...@@ -6920,23 +6989,22 @@ fn analyzeCall(
6920 // bug generating invalid LLVM IR.6989 // bug generating invalid LLVM IR.
6921 const res2: Air.Inst.Ref = res2: {6990 const res2: Air.Inst.Ref = res2: {
6922 if (should_memoize and is_comptime_call) {6991 if (should_memoize and is_comptime_call) {
6923 if (mod.memoized_calls.getContext(memoized_call_key, .{ .module = mod })) |result| {6992 if (mod.intern_pool.getIfExists(.{ .memoized_call = .{
6924 const ty_inst = try sema.addType(fn_ret_ty);6993 .func = module_fn_index,
6925 try sema.air_values.append(gpa, result.val);6994 .arg_values = memoized_arg_values,
6926 sema.air_instructions.set(block_inst, .{6995 .result = .none,
6927 .tag = .constant,6996 } })) |memoized_call_index| {
6928 .data = .{ .ty_pl = .{6997 const memoized_call = mod.intern_pool.indexToKey(memoized_call_index).memoized_call;
6929 .ty = ty_inst,6998 break :res2 try sema.addConstant(
6930 .payload = @intCast(u32, sema.air_values.items.len - 1),6999 mod.intern_pool.typeOf(memoized_call.result).toType(),
6931 } },7000 memoized_call.result.toValue(),
6932 });7001 );
6933 break :res2 Air.indexToRef(block_inst);
6934 }7002 }
6935 }7003 }
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);
6938 if (!is_comptime_call and !block.is_typeof) {7006 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
6941 const zir_tags = sema.code.instructions.items(.tag);7009 const zir_tags = sema.code.instructions.items(.tag);
6942 for (fn_info.param_body) |param| switch (zir_tags[param]) {7010 for (fn_info.param_body) |param| switch (zir_tags[param]) {
...@@ -6968,7 +7036,7 @@ fn analyzeCall(...@@ -6968,7 +7036,7 @@ fn analyzeCall(
6968 error.ComptimeReturn => break :result inlining.comptime_result,7036 error.ComptimeReturn => break :result inlining.comptime_result,
6969 error.AnalysisFail => {7037 error.AnalysisFail => {
6970 const err_msg = sema.err orelse return err;7038 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;
6972 try sema.errNote(block, call_src, err_msg, "called from here", .{});7040 try sema.errNote(block, call_src, err_msg, "called from here", .{});
6973 err_msg.clearTrace(sema.gpa);7041 err_msg.clearTrace(sema.gpa);
6974 return err;7042 return err;
...@@ -6978,11 +7046,11 @@ fn analyzeCall(...@@ -6978,11 +7046,11 @@ fn analyzeCall(
6978 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);7046 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);
6979 };7047 };
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) {
6982 try sema.emitDbgInline(7050 try sema.emitDbgInline(
6983 block,7051 block,
6984 module_fn,7052 module_fn_index,
6985 parent_func.?,7053 parent_func_index.unwrap().?,
6986 mod.declPtr(parent_func.?.owner_decl).ty,7054 mod.declPtr(parent_func.?.owner_decl).ty,
6987 .dbg_inline_end,7055 .dbg_inline_end,
6988 );7056 );
...@@ -6993,23 +7061,11 @@ fn analyzeCall(...@@ -6993,23 +7061,11 @@ fn analyzeCall(
69937061
6994 // TODO: check whether any external comptime memory was mutated by the7062 // TODO: check whether any external comptime memory was mutated by the
6995 // comptime function call. If so, then do not memoize the call here.7063 // comptime function call. If so, then do not memoize the call here.
6996 // TODO: re-evaluate whether memoized_calls needs its own arena. I think7064 _ = try mod.intern(.{ .memoized_call = .{
6997 // it should be fine to use the Decl arena for the function.7065 .func = module_fn_index,
6998 {7066 .arg_values = memoized_arg_values,
6999 var arena_allocator = std.heap.ArenaAllocator.init(gpa);7067 .result = try result_val.intern(fn_ret_ty, mod),
7000 errdefer arena_allocator.deinit();7068 } });
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 }
7013 }7069 }
70147070
7015 break :res2 result;7071 break :res2 result;
...@@ -7028,7 +7084,7 @@ fn analyzeCall(...@@ -7028,7 +7084,7 @@ fn analyzeCall(
7028 .func_inst = func,7084 .func_inst = func,
7029 .param_i = @intCast(u32, i),7085 .param_i = @intCast(u32, i),
7030 } };7086 } };
7031 const param_ty = func_ty.fnParamType(i);7087 const param_ty = mod.typeToFunc(func_ty).?.param_types[i].toType();
7032 args[i] = sema.analyzeCallArg(7088 args[i] = sema.analyzeCallArg(
7033 block,7089 block,
7034 .unneeded,7090 .unneeded,
...@@ -7037,10 +7093,10 @@ fn analyzeCall(...@@ -7037,10 +7093,10 @@ fn analyzeCall(
7037 opts,7093 opts,
7038 ) catch |err| switch (err) {7094 ) catch |err| switch (err) {
7039 error.NeededSourceLocation => {7095 error.NeededSourceLocation => {
7040 const decl = sema.mod.declPtr(block.src_decl);7096 const decl = mod.declPtr(block.src_decl);
7041 _ = try sema.analyzeCallArg(7097 _ = try sema.analyzeCallArg(
7042 block,7098 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),
7044 param_ty,7100 param_ty,
7045 uncasted_arg,7101 uncasted_arg,
7046 opts,7102 opts,
...@@ -7052,11 +7108,11 @@ fn analyzeCall(...@@ -7052,11 +7108,11 @@ fn analyzeCall(
7052 } else {7108 } else {
7053 args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) {7109 args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) {
7054 error.NeededSourceLocation => {7110 error.NeededSourceLocation => {
7055 const decl = sema.mod.declPtr(block.src_decl);7111 const decl = mod.declPtr(block.src_decl);
7056 _ = try sema.coerceVarArgParam(7112 _ = try sema.coerceVarArgParam(
7057 block,7113 block,
7058 uncasted_arg,7114 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),
7060 );7116 );
7061 unreachable;7117 unreachable;
7062 },7118 },
...@@ -7067,14 +7123,14 @@ fn analyzeCall(...@@ -7067,14 +7123,14 @@ fn analyzeCall(
70677123
7068 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7124 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
70697125
7070 try sema.queueFullTypeResolution(func_ty_info.return_type);7126 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7071 if (sema.owner_func != null and func_ty_info.return_type.isError()) {7127 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {
7072 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7128 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7073 }7129 }
70747130
7075 if (try sema.resolveMaybeUndefVal(func)) |func_val| {7131 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7076 if (func_val.castTag(.function)) |func_obj| {7132 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {
7077 try sema.mod.ensureFuncBodyAnalysisQueued(func_obj.data);7133 try mod.ensureFuncBodyAnalysisQueued(func_index);
7078 }7134 }
7079 }7135 }
70807136
...@@ -7096,23 +7152,24 @@ fn analyzeCall(...@@ -7096,23 +7152,24 @@ fn analyzeCall(
7096 try sema.ensureResultUsed(block, sema.typeOf(func_inst), call_src);7152 try sema.ensureResultUsed(block, sema.typeOf(func_inst), call_src);
7097 }7153 }
7098 return sema.handleTailCall(block, call_src, func_ty, func_inst);7154 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: {
7100 // Function pointers and extern functions aren't guaranteed to7157 // Function pointers and extern functions aren't guaranteed to
7101 // actually be noreturn so we add a safety check for them.7158 // actually be noreturn so we add a safety check for them.
7102 check: {7159 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7103 var func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;7160 switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7104 switch (func_val.tag()) {7161 .func => break :skip_safety,
7105 .function, .decl_ref => {7162 .ptr => |ptr| switch (ptr.addr) {
7106 _ = try block.addNoOp(.unreach);7163 .decl => |decl| if (!mod.declPtr(decl).isExtern(mod)) break :skip_safety,
7107 return Air.Inst.Ref.unreachable_value;7164 else => {},
7108 },7165 },
7109 else => break :check,7166 else => {},
7110 }7167 }
7111 }7168 }
7112
7113 try sema.safetyPanic(block, .noreturn_returned);7169 try sema.safetyPanic(block, .noreturn_returned);
7114 return Air.Inst.Ref.unreachable_value;7170 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) {
7116 _ = try block.addNoOp(.unreach);7173 _ = try block.addNoOp(.unreach);
7117 return Air.Inst.Ref.unreachable_value;7174 return Air.Inst.Ref.unreachable_value;
7118 }7175 }
...@@ -7126,17 +7183,18 @@ fn analyzeCall(...@@ -7126,17 +7183,18 @@ fn analyzeCall(
7126}7183}
71277184
7128fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref {7185fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref {
7129 const target = sema.mod.getTarget();7186 const mod = sema.mod;
7130 const backend = sema.mod.comp.getZigBackend();7187 const target = mod.getTarget();
7188 const backend = mod.comp.getZigBackend();
7131 if (!target_util.supportsTailCall(target, backend)) {7189 if (!target_util.supportsTailCall(target, backend)) {
7132 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", .{7190 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", .{
7133 @tagName(backend), @tagName(target.cpu.arch),7191 @tagName(backend), @tagName(target.cpu.arch),
7134 });7192 });
7135 }7193 }
7136 const func_decl = sema.mod.declPtr(sema.owner_func.?.owner_decl);7194 const func_decl = mod.declPtr(sema.owner_func.?.owner_decl);
7137 if (!func_ty.eql(func_decl.ty, sema.mod)) {7195 if (!func_ty.eql(func_decl.ty, mod)) {
7138 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{7196 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),
7140 });7198 });
7141 }7199 }
7142 _ = try block.addUnOp(.ret, result);7200 _ = try block.addUnOp(.ret, result);
...@@ -7149,16 +7207,17 @@ fn analyzeInlineCallArg(...@@ -7149,16 +7207,17 @@ fn analyzeInlineCallArg(
7149 param_block: *Block,7207 param_block: *Block,
7150 arg_src: LazySrcLoc,7208 arg_src: LazySrcLoc,
7151 inst: Zir.Inst.Index,7209 inst: Zir.Inst.Index,
7152 new_fn_info: Type.Payload.Function.Data,7210 new_fn_info: *InternPool.Key.FuncType,
7153 arg_i: *usize,7211 arg_i: *usize,
7154 uncasted_args: []const Air.Inst.Ref,7212 uncasted_args: []const Air.Inst.Ref,
7155 is_comptime_call: bool,7213 is_comptime_call: bool,
7156 should_memoize: *bool,7214 should_memoize: *bool,
7157 memoized_call_key: Module.MemoizedCall.Key,7215 memoized_arg_values: []InternPool.Index,
7158 raw_param_types: []const Type,7216 raw_param_types: []const InternPool.Index,
7159 func_inst: Air.Inst.Ref,7217 func_inst: Air.Inst.Ref,
7160 has_comptime_args: *bool,7218 has_comptime_args: *bool,
7161) !void {7219) !void {
7220 const mod = sema.mod;
7162 const zir_tags = sema.code.instructions.items(.tag);7221 const zir_tags = sema.code.instructions.items(.tag);
7163 switch (zir_tags[inst]) {7222 switch (zir_tags[inst]) {
7164 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,7223 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
...@@ -7174,13 +7233,14 @@ fn analyzeInlineCallArg(...@@ -7174,13 +7233,14 @@ fn analyzeInlineCallArg(
7174 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];7233 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
7175 const param_ty = param_ty: {7234 const param_ty = param_ty: {
7176 const raw_param_ty = raw_param_types[arg_i.*];7235 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;
7178 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);7237 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();
7180 };7240 };
7181 new_fn_info.param_types[arg_i.*] = param_ty;7241 new_fn_info.param_types[arg_i.*] = param_ty;
7182 const uncasted_arg = uncasted_args[arg_i.*];7242 const uncasted_arg = uncasted_args[arg_i.*];
7183 if (try sema.typeRequiresComptime(param_ty)) {7243 if (try sema.typeRequiresComptime(param_ty.toType())) {
7184 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {7244 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
7185 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);7245 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
7186 return err;7246 return err;
...@@ -7188,7 +7248,7 @@ fn analyzeInlineCallArg(...@@ -7188,7 +7248,7 @@ fn analyzeInlineCallArg(
7188 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {7248 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {
7189 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");7249 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
7190 }7250 }
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 = .{
7192 .func_inst = func_inst,7252 .func_inst = func_inst,
7193 .param_i = @intCast(u32, arg_i.*),7253 .param_i = @intCast(u32, arg_i.*),
7194 } }) catch |err| switch (err) {7254 } }) catch |err| switch (err) {
...@@ -7202,24 +7262,20 @@ fn analyzeInlineCallArg(...@@ -7202,24 +7262,20 @@ fn analyzeInlineCallArg(
7202 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);7262 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
7203 return err;7263 return err;
7204 };7264 };
7205 switch (arg_val.tag()) {7265 switch (arg_val.toIntern()) {
7206 .generic_poison, .generic_poison_type => {7266 .generic_poison, .generic_poison_type => {
7207 // This function is currently evaluated as part of an as-of-yet unresolvable7267 // This function is currently evaluated as part of an as-of-yet unresolvable
7208 // parameter or return type.7268 // parameter or return type.
7209 return error.GenericPoison;7269 return error.GenericPoison;
7210 },7270 },
7211 else => {7271 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 },
7217 }7272 }
7218 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();7273 // Needed so that lazy values do not trigger
7219 memoized_call_key.args[arg_i.*] = .{7274 // assertion due to type not being resolved
7220 .ty = param_ty,7275 // when the hash function is called.
7221 .val = arg_val,7276 const resolved_arg_val = try sema.resolveLazyValue(arg_val);
7222 };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);
7223 } else {7279 } else {
7224 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);7280 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
7225 }7281 }
...@@ -7233,7 +7289,7 @@ fn analyzeInlineCallArg(...@@ -7233,7 +7289,7 @@ fn analyzeInlineCallArg(
7233 .param_anytype, .param_anytype_comptime => {7289 .param_anytype, .param_anytype_comptime => {
7234 // No coercion needed.7290 // No coercion needed.
7235 const uncasted_arg = uncasted_args[arg_i.*];7291 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
7238 if (is_comptime_call) {7294 if (is_comptime_call) {
7239 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);7295 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
...@@ -7241,24 +7297,20 @@ fn analyzeInlineCallArg(...@@ -7241,24 +7297,20 @@ fn analyzeInlineCallArg(
7241 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);7297 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
7242 return err;7298 return err;
7243 };7299 };
7244 switch (arg_val.tag()) {7300 switch (arg_val.toIntern()) {
7245 .generic_poison, .generic_poison_type => {7301 .generic_poison, .generic_poison_type => {
7246 // This function is currently evaluated as part of an as-of-yet unresolvable7302 // This function is currently evaluated as part of an as-of-yet unresolvable
7247 // parameter or return type.7303 // parameter or return type.
7248 return error.GenericPoison;7304 return error.GenericPoison;
7249 },7305 },
7250 else => {7306 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 },
7256 }7307 }
7257 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();7308 // Needed so that lazy values do not trigger
7258 memoized_call_key.args[arg_i.*] = .{7309 // assertion due to type not being resolved
7259 .ty = sema.typeOf(uncasted_arg),7310 // when the hash function is called.
7260 .val = arg_val,7311 const resolved_arg_val = try sema.resolveLazyValue(arg_val);
7261 };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);
7262 } else {7314 } else {
7263 if (zir_tags[inst] == .param_anytype_comptime) {7315 if (zir_tags[inst] == .param_anytype_comptime) {
7264 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");7316 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
...@@ -7298,14 +7350,15 @@ fn analyzeGenericCallArg(...@@ -7298,14 +7350,15 @@ fn analyzeGenericCallArg(
7298 uncasted_arg: Air.Inst.Ref,7350 uncasted_arg: Air.Inst.Ref,
7299 comptime_arg: TypedValue,7351 comptime_arg: TypedValue,
7300 runtime_args: []Air.Inst.Ref,7352 runtime_args: []Air.Inst.Ref,
7301 new_fn_info: Type.Payload.Function.Data,7353 new_fn_info: InternPool.Key.FuncType,
7302 runtime_i: *u32,7354 runtime_i: *u32,
7303) !void {7355) !void {
7304 const is_runtime = comptime_arg.val.tag() == .generic_poison and7356 const mod = sema.mod;
7305 comptime_arg.ty.hasRuntimeBits() and7357 const is_runtime = comptime_arg.val.isGenericPoison() and
7358 comptime_arg.ty.hasRuntimeBits(mod) and
7306 !(try sema.typeRequiresComptime(comptime_arg.ty));7359 !(try sema.typeRequiresComptime(comptime_arg.ty));
7307 if (is_runtime) {7360 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();
7309 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);7362 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
7310 try sema.queueFullTypeResolution(param_ty);7363 try sema.queueFullTypeResolution(param_ty);
7311 runtime_args[runtime_i.*] = casted_arg;7364 runtime_args[runtime_i.*] = casted_arg;
...@@ -7315,10 +7368,16 @@ fn analyzeGenericCallArg(...@@ -7315,10 +7368,16 @@ fn analyzeGenericCallArg(
7315 }7368 }
7316}7369}
73177370
7318fn analyzeGenericCallArgVal(sema: *Sema, block: *Block, arg_src: LazySrcLoc, uncasted_arg: Air.Inst.Ref) !Value {7371fn analyzeGenericCallArgVal(
7319 const arg_val = try sema.resolveValue(block, arg_src, uncasted_arg, "parameter is comptime");7372 sema: *Sema,
7320 try sema.resolveLazyValue(arg_val);7373 block: *Block,
7321 return arg_val;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));
7322}7381}
73237382
7324fn instantiateGenericCall(7383fn instantiateGenericCall(
...@@ -7327,7 +7386,7 @@ fn instantiateGenericCall(...@@ -7327,7 +7386,7 @@ fn instantiateGenericCall(
7327 func: Air.Inst.Ref,7386 func: Air.Inst.Ref,
7328 func_src: LazySrcLoc,7387 func_src: LazySrcLoc,
7329 call_src: LazySrcLoc,7388 call_src: LazySrcLoc,
7330 func_ty_info: Type.Payload.Function.Data,7389 generic_func_ty: Type,
7331 ensure_result_used: bool,7390 ensure_result_used: bool,
7332 uncasted_args: []const Air.Inst.Ref,7391 uncasted_args: []const Air.Inst.Ref,
7333 call_tag: Air.Inst.Tag,7392 call_tag: Air.Inst.Tag,
...@@ -7338,46 +7397,41 @@ fn instantiateGenericCall(...@@ -7338,46 +7397,41 @@ fn instantiateGenericCall(
7338 const gpa = sema.gpa;7397 const gpa = sema.gpa;
73397398
7340 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");7399 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()) {7400 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7342 .function => func_val.castTag(.function).?.data,7401 .func => |function| function.index,
7343 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,7402 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?,
7344 else => unreachable,7403 else => unreachable,
7345 };7404 };
7405 const module_fn = mod.funcPtr(module_fn_index);
7346 // Check the Module's generic function map with an adapted context, so that we7406 // Check the Module's generic function map with an adapted context, so that we
7347 // can match against `uncasted_args` rather than doing the work below to create a7407 // can match against `uncasted_args` rather than doing the work below to create a
7348 // generic Scope only to junk it if it matches an existing instantiation.7408 // generic Scope only to junk it if it matches an existing instantiation.
7349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);7409 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);
7351 const fn_zir = namespace.file_scope.zir;7412 const fn_zir = namespace.file_scope.zir;
7352 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);7413 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
7353 const zir_tags = fn_zir.instructions.items(.tag);7414 const zir_tags = fn_zir.instructions.items(.tag);
73547415
7355 // This hash must match `Module.MonomorphedFuncsContext.hash`.7416 const monomorphed_args = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(generic_func_ty).?.param_types.len);
7356 // For parameters explicitly marked comptime and simple parameter type expressions,7417 const callee_index = callee: {
7357 // we know whether a parameter is elided from a monomorphed function, and can7418 var arg_i: usize = 0;
7358 // use it in the hash here. However, for parameter type expressions that are not7419 var monomorphed_arg_i: u32 = 0;
7359 // explicitly marked comptime and rely on previous parameter comptime values, we7420 var known_unique = false;
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;
7368 for (fn_info.param_body) |inst| {7421 for (fn_info.param_body) |inst| {
7422 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7369 var is_comptime = false;7423 var is_comptime = false;
7370 var is_anytype = false;7424 var is_anytype = false;
7371 switch (zir_tags[inst]) {7425 switch (zir_tags[inst]) {
7372 .param => {7426 .param => {
7373 is_comptime = func_ty_info.paramIsComptime(i);7427 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7374 },7428 },
7375 .param_comptime => {7429 .param_comptime => {
7376 is_comptime = true;7430 is_comptime = true;
7377 },7431 },
7378 .param_anytype => {7432 .param_anytype => {
7379 is_anytype = true;7433 is_anytype = true;
7380 is_comptime = func_ty_info.paramIsComptime(i);7434 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7381 },7435 },
7382 .param_anytype_comptime => {7436 .param_anytype_comptime => {
7383 is_anytype = true;7437 is_anytype = true;
...@@ -7386,87 +7440,90 @@ fn instantiateGenericCall(...@@ -7386,87 +7440,90 @@ fn instantiateGenericCall(
7386 else => continue,7440 else => continue,
7387 }7441 }
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;
7390 if (is_comptime or is_anytype) {7468 if (is_comptime or is_anytype) {
7391 // Tuple default values are a part of the type and need to be7469 // Tuple default values are a part of the type and need to be
7392 // resolved to hash the type.7470 // resolved to hash the type.
7393 try sema.resolveTupleLazyValues(block, call_src, arg_ty);7471 try sema.resolveTupleLazyValues(block, call_src, arg_ty.toType());
7394 }7472 }
73957473
7396 if (is_comptime) {7474 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) {
7398 error.NeededSourceLocation => {7476 error.NeededSourceLocation => {
7399 const decl = sema.mod.declPtr(block.src_decl);7477 const decl = mod.declPtr(block.src_decl);
7400 const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src);7478 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7401 _ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[i]);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 );
7402 unreachable;7489 unreachable;
7403 },7490 },
7404 else => |e| return e,7491 else => |e| return e,
7405 };7492 };
7406 arg_val.hashUncoerced(arg_ty, &hasher, mod);7493 monomorphed_args[monomorphed_arg_i] = casted_arg.toIntern();
7407 if (is_anytype) {7494 monomorphed_arg_i += 1;
7408 arg_ty.hashWithHasher(&hasher, mod);7495 } else if (is_anytype or is_generic) {
7409 generic_args[i] = .{7496 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty });
7410 .ty = arg_ty,7497 monomorphed_arg_i += 1;
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 };
7434 }7498 }
7435
7436 i += 1;
7437 }7499 }
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 = .{7511 const new_module_func_index = try mod.createFunc(undefined);
7443 .generic_fn = module_fn,7512 const new_module_func = mod.funcPtr(new_module_func_index);
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);
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;
7456 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();7514 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
7457 new_module_func.comptime_args = null;7515 new_module_func.comptime_args = null;
7458 gop.key_ptr.* = new_module_func;
74597516
7460 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);7517 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
74617518
7462 // Create a Decl for the new function.7519 // Create a Decl for the new function.
7463 const src_decl_index = namespace.getDeclIndex();7520 const src_decl_index = namespace.getDeclIndex(mod);
7464 const src_decl = mod.declPtr(src_decl_index);7521 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);
7466 const new_decl = mod.declPtr(new_decl_index);7523 const new_decl = mod.declPtr(new_decl_index);
7467 // TODO better names for generic function instantiations7524 // TODO better names for generic function instantiations
7468 const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{7525 const decl_name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}__anon_{d}", .{
7469 fn_owner_decl.name, @enumToInt(new_decl_index),7526 fn_owner_decl.name.fmt(&mod.intern_pool), @enumToInt(new_decl_index),
7470 });7527 });
7471 new_decl.name = decl_name;7528 new_decl.name = decl_name;
7472 new_decl.src_line = fn_owner_decl.src_line;7529 new_decl.src_line = fn_owner_decl.src_line;
...@@ -7488,25 +7545,21 @@ fn instantiateGenericCall(...@@ -7488,25 +7545,21 @@ fn instantiateGenericCall(
7488 assert(new_decl.dependencies.keys().len == 0);7545 assert(new_decl.dependencies.keys().len == 0);
7489 try mod.declareDeclDependencyType(new_decl_index, module_fn.owner_decl, .function_body);7546 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
7494 const new_func = sema.resolveGenericInstantiationType(7548 const new_func = sema.resolveGenericInstantiationType(
7495 block,7549 block,
7496 new_decl_arena_allocator,
7497 fn_zir,7550 fn_zir,
7498 new_decl,7551 new_decl,
7499 new_decl_index,7552 new_decl_index,
7500 uncasted_args,7553 uncasted_args,
7501 module_fn,7554 monomorphed_arg_i,
7502 new_module_func,7555 module_fn_index,
7503 namespace,7556 new_module_func_index,
7504 func_ty_info,7557 namespace_index,
7558 generic_func_ty,
7505 call_src,7559 call_src,
7506 bound_arg_src,7560 bound_arg_src,
7507 ) catch |err| switch (err) {7561 ) catch |err| switch (err) {
7508 error.GenericPoison, error.ComptimeReturn => {7562 error.GenericPoison, error.ComptimeReturn => {
7509 new_decl_arena.deinit();
7510 // Resolving the new function type below will possibly declare more decl dependencies7563 // Resolving the new function type below will possibly declare more decl dependencies
7511 // and so we remove them all here in case of error.7564 // and so we remove them all here in case of error.
7512 for (new_decl.dependencies.keys()) |dep_index| {7565 for (new_decl.dependencies.keys()) |dep_index| {
...@@ -7515,16 +7568,10 @@ fn instantiateGenericCall(...@@ -7515,16 +7568,10 @@ fn instantiateGenericCall(
7515 }7568 }
7516 assert(namespace.anon_decls.orderedRemove(new_decl_index));7569 assert(namespace.anon_decls.orderedRemove(new_decl_index));
7517 mod.destroyDecl(new_decl_index);7570 mod.destroyDecl(new_decl_index);
7518 assert(mod.monomorphed_funcs.remove(new_module_func));7571 mod.destroyFunc(new_module_func_index);
7519 gpa.destroy(new_module_func);
7520 return err;7572 return err;
7521 },7573 },
7522 else => {7574 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 }
7528 // TODO look up the compile error that happened here and attach a note to it7575 // TODO look up the compile error that happened here and attach a note to it
7529 // pointing here, at the generic instantiation callsite.7576 // pointing here, at the generic instantiation callsite.
7530 if (sema.owner_func) |owner_func| {7577 if (sema.owner_func) |owner_func| {
...@@ -7535,12 +7582,10 @@ fn instantiateGenericCall(...@@ -7535,12 +7582,10 @@ fn instantiateGenericCall(
7535 return err;7582 return err;
7536 },7583 },
7537 };7584 };
7538 errdefer new_decl_arena.deinit();
75397585
7540 try new_decl.finalizeNewArena(&new_decl_arena);
7541 break :callee new_func;7586 break :callee new_func;
7542 } else gop.key_ptr.*;7587 };
75437588 const callee = mod.funcPtr(callee_index);
7544 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);7589 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
75457590
7546 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);7591 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);
...@@ -7548,8 +7593,7 @@ fn instantiateGenericCall(...@@ -7548,8 +7593,7 @@ fn instantiateGenericCall(
7548 // Make a runtime call to the new function, making sure to omit the comptime args.7593 // Make a runtime call to the new function, making sure to omit the comptime args.
7549 const comptime_args = callee.comptime_args.?;7594 const comptime_args = callee.comptime_args.?;
7550 const func_ty = mod.declPtr(callee.owner_decl).ty;7595 const func_ty = mod.declPtr(callee.owner_decl).ty;
7551 const new_fn_info = func_ty.fnInfo();7596 const runtime_args_len = @intCast(u32, mod.typeToFunc(func_ty).?.param_types.len);
7552 const runtime_args_len = @intCast(u32, new_fn_info.param_types.len);
7553 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);7597 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
7554 {7598 {
7555 var runtime_i: u32 = 0;7599 var runtime_i: u32 = 0;
...@@ -7565,18 +7609,18 @@ fn instantiateGenericCall(...@@ -7565,18 +7609,18 @@ fn instantiateGenericCall(
7565 uncasted_args[total_i],7609 uncasted_args[total_i],
7566 comptime_args[total_i],7610 comptime_args[total_i],
7567 runtime_args,7611 runtime_args,
7568 new_fn_info,7612 mod.typeToFunc(func_ty).?,
7569 &runtime_i,7613 &runtime_i,
7570 ) catch |err| switch (err) {7614 ) catch |err| switch (err) {
7571 error.NeededSourceLocation => {7615 error.NeededSourceLocation => {
7572 const decl = sema.mod.declPtr(block.src_decl);7616 const decl = mod.declPtr(block.src_decl);
7573 _ = try sema.analyzeGenericCallArg(7617 _ = try sema.analyzeGenericCallArg(
7574 block,7618 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),
7576 uncasted_args[total_i],7620 uncasted_args[total_i],
7577 comptime_args[total_i],7621 comptime_args[total_i],
7578 runtime_args,7622 runtime_args,
7579 new_fn_info,7623 mod.typeToFunc(func_ty).?,
7580 &runtime_i,7624 &runtime_i,
7581 );7625 );
7582 unreachable;7626 unreachable;
...@@ -7586,16 +7630,16 @@ fn instantiateGenericCall(...@@ -7586,16 +7630,16 @@ fn instantiateGenericCall(
7586 total_i += 1;7630 total_i += 1;
7587 }7631 }
75887632
7589 try sema.queueFullTypeResolution(new_fn_info.return_type);7633 try sema.queueFullTypeResolution(mod.typeToFunc(func_ty).?.return_type.toType());
7590 }7634 }
75917635
7592 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7636 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)) {
7595 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7639 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7596 }7640 }
75977641
7598 try sema.mod.ensureFuncBodyAnalysisQueued(callee);7642 try mod.ensureFuncBodyAnalysisQueued(callee_index);
75997643
7600 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +7644 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
7601 runtime_args_len);7645 runtime_args_len);
...@@ -7616,7 +7660,7 @@ fn instantiateGenericCall(...@@ -7616,7 +7660,7 @@ fn instantiateGenericCall(
7616 if (call_tag == .call_always_tail) {7660 if (call_tag == .call_always_tail) {
7617 return sema.handleTailCall(block, call_src, func_ty, result);7661 return sema.handleTailCall(block, call_src, func_ty, result);
7618 }7662 }
7619 if (new_fn_info.return_type.isNoReturn()) {7663 if (func_ty.fnReturnType(mod).isNoReturn(mod)) {
7620 _ = try block.addNoOp(.unreach);7664 _ = try block.addNoOp(.unreach);
7621 return Air.Inst.Ref.unreachable_value;7665 return Air.Inst.Ref.unreachable_value;
7622 }7666 }
...@@ -7626,22 +7670,23 @@ fn instantiateGenericCall(...@@ -7626,22 +7670,23 @@ fn instantiateGenericCall(
7626fn resolveGenericInstantiationType(7670fn resolveGenericInstantiationType(
7627 sema: *Sema,7671 sema: *Sema,
7628 block: *Block,7672 block: *Block,
7629 new_decl_arena_allocator: Allocator,
7630 fn_zir: Zir,7673 fn_zir: Zir,
7631 new_decl: *Decl,7674 new_decl: *Decl,
7632 new_decl_index: Decl.Index,7675 new_decl_index: Decl.Index,
7633 uncasted_args: []const Air.Inst.Ref,7676 uncasted_args: []const Air.Inst.Ref,
7634 module_fn: *Module.Fn,7677 monomorphed_args_len: u32,
7635 new_module_func: *Module.Fn,7678 module_fn_index: Module.Fn.Index,
7636 namespace: *Namespace,7679 new_module_func: Module.Fn.Index,
7637 func_ty_info: Type.Payload.Function.Data,7680 namespace: Namespace.Index,
7681 generic_func_ty: Type,
7638 call_src: LazySrcLoc,7682 call_src: LazySrcLoc,
7639 bound_arg_src: ?LazySrcLoc,7683 bound_arg_src: ?LazySrcLoc,
7640) !*Module.Fn {7684) !Module.Fn.Index {
7641 const mod = sema.mod;7685 const mod = sema.mod;
7642 const gpa = sema.gpa;7686 const gpa = sema.gpa;
76437687
7644 const zir_tags = fn_zir.instructions.items(.tag);7688 const zir_tags = fn_zir.instructions.items(.tag);
7689 const module_fn = mod.funcPtr(module_fn_index);
7645 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);7690 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
76467691
7647 // Re-run the block that creates the function, with the comptime parameters7692 // Re-run the block that creates the function, with the comptime parameters
...@@ -7652,23 +7697,26 @@ fn resolveGenericInstantiationType(...@@ -7652,23 +7697,26 @@ fn resolveGenericInstantiationType(
7652 .mod = mod,7697 .mod = mod,
7653 .gpa = gpa,7698 .gpa = gpa,
7654 .arena = sema.arena,7699 .arena = sema.arena,
7655 .perm_arena = new_decl_arena_allocator,
7656 .code = fn_zir,7700 .code = fn_zir,
7657 .owner_decl = new_decl,7701 .owner_decl = new_decl,
7658 .owner_decl_index = new_decl_index,7702 .owner_decl_index = new_decl_index,
7659 .func = null,7703 .func = null,
7704 .func_index = .none,
7660 .fn_ret_ty = Type.void,7705 .fn_ret_ty = Type.void,
7661 .owner_func = null,7706 .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),
7663 .comptime_args_fn_inst = module_fn.zir_body_inst,7710 .comptime_args_fn_inst = module_fn.zir_body_inst,
7664 .preallocated_new_func = new_module_func,7711 .preallocated_new_func = new_module_func.toOptional(),
7665 .is_generic_instantiation = true,7712 .is_generic_instantiation = true,
7666 .branch_quota = sema.branch_quota,7713 .branch_quota = sema.branch_quota,
7667 .branch_count = sema.branch_count,7714 .branch_count = sema.branch_count,
7715 .comptime_mutable_decls = sema.comptime_mutable_decls,
7668 };7716 };
7669 defer child_sema.deinit();7717 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);
7672 defer wip_captures.deinit();7720 defer wip_captures.deinit();
76737721
7674 var child_block: Block = .{7722 var child_block: Block = .{
...@@ -7690,18 +7738,19 @@ fn resolveGenericInstantiationType(...@@ -7690,18 +7738,19 @@ fn resolveGenericInstantiationType(
76907738
7691 var arg_i: usize = 0;7739 var arg_i: usize = 0;
7692 for (fn_info.param_body) |inst| {7740 for (fn_info.param_body) |inst| {
7741 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7693 var is_comptime = false;7742 var is_comptime = false;
7694 var is_anytype = false;7743 var is_anytype = false;
7695 switch (zir_tags[inst]) {7744 switch (zir_tags[inst]) {
7696 .param => {7745 .param => {
7697 is_comptime = func_ty_info.paramIsComptime(arg_i);7746 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7698 },7747 },
7699 .param_comptime => {7748 .param_comptime => {
7700 is_comptime = true;7749 is_comptime = true;
7701 },7750 },
7702 .param_anytype => {7751 .param_anytype => {
7703 is_anytype = true;7752 is_anytype = true;
7704 is_comptime = func_ty_info.paramIsComptime(arg_i);7753 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7705 },7754 },
7706 .param_anytype_comptime => {7755 .param_anytype_comptime => {
7707 is_anytype = true;7756 is_anytype = true;
...@@ -7719,8 +7768,8 @@ fn resolveGenericInstantiationType(...@@ -7719,8 +7768,8 @@ fn resolveGenericInstantiationType(
7719 if (try sema.typeRequiresComptime(arg_ty)) {7768 if (try sema.typeRequiresComptime(arg_ty)) {
7720 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {7769 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
7721 error.NeededSourceLocation => {7770 error.NeededSourceLocation => {
7722 const decl = sema.mod.declPtr(block.src_decl);7771 const decl = mod.declPtr(block.src_decl);
7723 const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src);7772 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7724 _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");7773 _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
7725 unreachable;7774 unreachable;
7726 },7775 },
...@@ -7752,50 +7801,61 @@ fn resolveGenericInstantiationType(...@@ -7752,50 +7801,61 @@ fn resolveGenericInstantiationType(
77527801
7753 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);7802 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
7754 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;7803 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;7804 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
7756 errdefer new_func.deinit(gpa);
7757 assert(new_func == new_module_func);7805 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
7759 arg_i = 0;7812 arg_i = 0;
7760 for (fn_info.param_body) |inst| {7813 for (fn_info.param_body) |inst| {
7814 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7761 var is_comptime = false;7815 var is_comptime = false;
7816 var is_anytype = false;
7762 switch (zir_tags[inst]) {7817 switch (zir_tags[inst]) {
7763 .param => {7818 .param => {
7764 is_comptime = func_ty_info.paramIsComptime(arg_i);7819 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7765 },7820 },
7766 .param_comptime => {7821 .param_comptime => {
7767 is_comptime = true;7822 is_comptime = true;
7768 },7823 },
7769 .param_anytype => {7824 .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));
7771 },7827 },
7772 .param_anytype_comptime => {7828 .param_anytype_comptime => {
7829 is_anytype = true;
7773 is_comptime = true;7830 is_comptime = true;
7774 },7831 },
7775 else => continue,7832 else => continue,
7776 }7833 }
77777834
7778 // We populate the Type here regardless because it is needed by7835 const param_ty = generic_func_ty_info.param_types[arg_i];
7779 // `GenericCallAdapter.eql` as well as function body analysis.7836 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7780 // Whether it is anytype is communicated by `isAnytypeParam`.7837
7781 const arg = child_sema.inst_map.get(inst).?;7838 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)) {7841 if (is_generic) if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{
7785 is_comptime = true;7842 .func = module_fn_index,
7786 }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
7788 if (is_comptime) {7848 if (is_comptime) {
7789 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;7849 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;
7790 child_sema.comptime_args[arg_i] = .{7850 monomorphed_args[monomorphed_arg_i] = arg_val.toIntern();
7791 .ty = copied_arg_ty,7851 monomorphed_arg_i += 1;
7792 .val = try arg_val.copy(new_decl_arena_allocator),7852 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = arg_val };
7793 };
7794 } else {7853 } else {
7795 child_sema.comptime_args[arg_i] = .{7854 if (is_anytype or is_generic) {
7796 .ty = copied_arg_ty,7855 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty.toIntern() });
7797 .val = Value.initTag(.generic_poison),7856 monomorphed_arg_i += 1;
7798 };7857 }
7858 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = Value.generic_poison };
7799 }7859 }
78007860
7801 arg_i += 1;7861 arg_i += 1;
...@@ -7804,11 +7864,11 @@ fn resolveGenericInstantiationType(...@@ -7804,11 +7864,11 @@ fn resolveGenericInstantiationType(
7804 try wip_captures.finalize();7864 try wip_captures.finalize();
78057865
7806 // Populate the Decl ty/val with the function and its type.7866 // 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);
7808 // If the call evaluated to a return type that requires comptime, never mind7868 // If the call evaluated to a return type that requires comptime, never mind
7809 // our generic instantiation. Instead we need to perform a comptime call.7869 // our generic instantiation. Instead we need to perform a comptime call.
7810 const new_fn_info = new_decl.ty.fnInfo();7870 const new_fn_info = mod.typeToFunc(new_decl.ty).?;
7811 if (try sema.typeRequiresComptime(new_fn_info.return_type)) {7871 if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) {
7812 return error.ComptimeReturn;7872 return error.ComptimeReturn;
7813 }7873 }
7814 // Similarly, if the call evaluated to a generic type we need to instead7874 // Similarly, if the call evaluated to a generic type we need to instead
...@@ -7817,15 +7877,20 @@ fn resolveGenericInstantiationType(...@@ -7817,15 +7877,20 @@ fn resolveGenericInstantiationType(
7817 return error.GenericPoison;7877 return error.GenericPoison;
7818 }7878 }
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();
7821 new_decl.@"align" = 0;7884 new_decl.@"align" = 0;
7822 new_decl.has_tv = true;7885 new_decl.has_tv = true;
7823 new_decl.owns_tv = true;7886 new_decl.owns_tv = true;
7824 new_decl.analysis = .complete;7887 new_decl.analysis = .complete;
78257888
7826 log.debug("generic function '{s}' instantiated with type {}", .{7889 mod.monomorphed_funcs.putAssumeCapacityNoClobberContext(.{
7827 new_decl.name, new_decl.ty.fmtDebug(),7890 .func = module_fn_index,
7828 });7891 .args_index = monomorphed_args_index,
7892 .args_len = monomorphed_arg_i,
7893 }, new_decl.val.toIntern(), .{ .mod = mod });
78297894
7830 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field7895 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field
7831 // will be populated, ensuring it will have `analyzeBody` called with the ZIR7896 // will be populated, ensuring it will have `analyzeBody` called with the ZIR
...@@ -7835,46 +7900,46 @@ fn resolveGenericInstantiationType(...@@ -7835,46 +7900,46 @@ fn resolveGenericInstantiationType(
7835}7900}
78367901
7837fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {7902fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
7838 if (!ty.isSimpleTupleOrAnonStruct()) return;7903 const mod = sema.mod;
7839 const tuple = ty.tupleFields();7904 const tuple = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
7840 for (tuple.values, 0..) |field_val, i| {7905 .anon_struct_type => |tuple| tuple,
7841 try sema.resolveTupleLazyValues(block, src, tuple.types[i]);7906 else => return,
7842 if (field_val.tag() == .unreachable_value) continue;7907 };
7843 try sema.resolveLazyValue(field_val);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());
7844 }7913 }
7845}7914}
78467915
7847fn emitDbgInline(7916fn emitDbgInline(
7848 sema: *Sema,7917 sema: *Sema,
7849 block: *Block,7918 block: *Block,
7850 old_func: *Module.Fn,7919 old_func: Module.Fn.Index,
7851 new_func: *Module.Fn,7920 new_func: Module.Fn.Index,
7852 new_func_ty: Type,7921 new_func_ty: Type,
7853 tag: Air.Inst.Tag,7922 tag: Air.Inst.Tag,
7854) CompileError!void {7923) 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
7857 // Recursive inline call; no dbg_inline needed.7927 // Recursive inline call; no dbg_inline needed.
7858 if (old_func == new_func) return;7928 if (old_func == new_func) return;
78597929
7860 try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
7861 _ = try block.addInst(.{7930 _ = try block.addInst(.{
7862 .tag = tag,7931 .tag = tag,
7863 .data = .{ .ty_pl = .{7932 .data = .{ .ty_fn = .{
7864 .ty = try sema.addType(new_func_ty),7933 .ty = try sema.addType(new_func_ty),
7865 .payload = @intCast(u32, sema.air_values.items.len - 1),7934 .func = new_func,
7866 } },7935 } },
7867 });7936 });
7868}7937}
78697938
7870fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7939fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7871 _ = block;7940 const mod = sema.mod;
7872 const tracy = trace(@src());
7873 defer tracy.end();
7874
7875 const int_type = sema.code.instructions.items(.data)[inst].int_type;7941 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);7942 const ty = try mod.intType(int_type.signedness, int_type.bit_count);
7877
7878 return sema.addType(ty);7943 return sema.addType(ty);
7879}7944}
78807945
...@@ -7882,43 +7947,46 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -7882,43 +7947,46 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
7882 const tracy = trace(@src());7947 const tracy = trace(@src());
7883 defer tracy.end();7948 defer tracy.end();
78847949
7950 const mod = sema.mod;
7885 const inst_data = sema.code.instructions.items(.data)[inst].un_node;7951 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
7886 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };7952 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };
7887 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);7953 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);
7888 if (child_type.zigTypeTag() == .Opaque) {7954 if (child_type.zigTypeTag(mod) == .Opaque) {
7889 return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(sema.mod)});7955 return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(mod)});
7890 } else if (child_type.zigTypeTag() == .Null) {7956 } else if (child_type.zigTypeTag(mod) == .Null) {
7891 return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(sema.mod)});7957 return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(mod)});
7892 }7958 }
7893 const opt_type = try Type.optional(sema.arena, child_type);7959 const opt_type = try Type.optional(sema.arena, child_type, mod);
78947960
7895 return sema.addType(opt_type);7961 return sema.addType(opt_type);
7896}7962}
78977963
7898fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7964fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7965 const mod = sema.mod;
7899 const bin = sema.code.instructions.items(.data)[inst].bin;7966 const bin = sema.code.instructions.items(.data)[inst].bin;
7900 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);7967 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
7901 assert(indexable_ty.isIndexable()); // validated by a previous instruction7968 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
7902 if (indexable_ty.zigTypeTag() == .Struct) {7969 if (indexable_ty.zigTypeTag(mod) == .Struct) {
7903 const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs));7970 const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs), mod);
7904 return sema.addType(elem_type);7971 return sema.addType(elem_type);
7905 } else {7972 } else {
7906 const elem_type = indexable_ty.elemType2();7973 const elem_type = indexable_ty.elemType2(mod);
7907 return sema.addType(elem_type);7974 return sema.addType(elem_type);
7908 }7975 }
7909}7976}
79107977
7911fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7978fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7979 const mod = sema.mod;
7912 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;7980 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
7913 const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };7981 const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
7914 const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };7982 const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
7915 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;7983 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"));
7917 const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs);7985 const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs);
7918 try sema.checkVectorElemType(block, elem_type_src, elem_type);7986 try sema.checkVectorElemType(block, elem_type_src, elem_type);
7919 const vector_type = try Type.Tag.vector.create(sema.arena, .{7987 const vector_type = try mod.vectorType(.{
7920 .len = @intCast(u32, len),7988 .len = len,
7921 .elem_type = elem_type,7989 .child = elem_type.toIntern(),
7922 });7990 });
7923 return sema.addType(vector_type);7991 return sema.addType(vector_type);
7924}7992}
...@@ -7960,9 +8028,10 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -7960,9 +8028,10 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
7960}8028}
79618029
7962fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src: LazySrcLoc) !void {8030fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src: LazySrcLoc) !void {
7963 if (elem_type.zigTypeTag() == .Opaque) {8031 const mod = sema.mod;
7964 return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(sema.mod)});8032 if (elem_type.zigTypeTag(mod) == .Opaque) {
7965 } else if (elem_type.zigTypeTag() == .NoReturn) {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) {
7966 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});8035 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});
7967 }8036 }
7968}8037}
...@@ -7975,9 +8044,10 @@ fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -7975,9 +8044,10 @@ fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
7975 if (true) {8044 if (true) {
7976 return sema.failWithUseOfAsync(block, inst_data.src());8045 return sema.failWithUseOfAsync(block, inst_data.src());
7977 }8046 }
8047 const mod = sema.mod;
7978 const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node };8048 const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node };
7979 const return_type = try sema.resolveType(block, operand_src, inst_data.operand);8049 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
7982 return sema.addType(anyframe_type);8052 return sema.addType(anyframe_type);
7983}8053}
...@@ -7986,6 +8056,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -7986,6 +8056,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
7986 const tracy = trace(@src());8056 const tracy = trace(@src());
7987 defer tracy.end();8057 defer tracy.end();
79888058
8059 const mod = sema.mod;
7989 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8060 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
7990 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;8061 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
7991 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };8062 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...@@ -7993,50 +8064,48 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
7993 const error_set = try sema.resolveType(block, lhs_src, extra.lhs);8064 const error_set = try sema.resolveType(block, lhs_src, extra.lhs);
7994 const payload = try sema.resolveType(block, rhs_src, extra.rhs);8065 const payload = try sema.resolveType(block, rhs_src, extra.rhs);
79958066
7996 if (error_set.zigTypeTag() != .ErrorSet) {8067 if (error_set.zigTypeTag(mod) != .ErrorSet) {
7997 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{8068 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{
7998 error_set.fmt(sema.mod),8069 error_set.fmt(mod),
7999 });8070 });
8000 }8071 }
8001 try sema.validateErrorUnionPayloadType(block, payload, rhs_src);8072 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);
8003 return sema.addType(err_union_ty);8074 return sema.addType(err_union_ty);
8004}8075}
80058076
8006fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, payload_src: LazySrcLoc) !void {8077fn 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) {
8008 return sema.fail(block, payload_src, "error union with payload of opaque type '{}' not allowed", .{8080 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),
8010 });8082 });
8011 } else if (payload_ty.zigTypeTag() == .ErrorSet) {8083 } else if (payload_ty.zigTypeTag(mod) == .ErrorSet) {
8012 return sema.fail(block, payload_src, "error union with payload of error set type '{}' not allowed", .{8084 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),
8014 });8086 });
8015 }8087 }
8016}8088}
80178089
8018fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8090fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8019 _ = block;8091 _ = block;
8020 const tracy = trace(@src());8092 const mod = sema.mod;
8021 defer tracy.end();
8022
8023 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;8093 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
80248094 const name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
8025 // Create an anonymous error set type with only this error value, and return the value.8095 _ = try mod.getErrorValue(name);
8026 const kv = try sema.mod.getErrorValue(inst_data.get(sema.code));8096 // Create an error set type with only this error value, and return the value.
8027 const result_type = try Type.Tag.error_set_single.create(sema.arena, kv.key);8097 const error_set_type = try mod.singleErrorSetType(name);
8028 return sema.addConstant(8098 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
8029 result_type,8099 .ty = error_set_type.toIntern(),
8030 try Value.Tag.@"error".create(sema.arena, .{8100 .name = name,
8031 .name = kv.key,8101 } })).toValue());
8032 }),
8033 );
8034}8102}
80358103
8036fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {8104fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
8037 const tracy = trace(@src());8105 const tracy = trace(@src());
8038 defer tracy.end();8106 defer tracy.end();
80398107
8108 const mod = sema.mod;
8040 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;8109 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8041 const src = LazySrcLoc.nodeOffset(extra.node);8110 const src = LazySrcLoc.nodeOffset(extra.node);
8042 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };8111 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...@@ -8044,34 +8113,26 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
8044 const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src);8113 const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src);
80458114
8046 if (try sema.resolveMaybeUndefVal(operand)) |val| {8115 if (try sema.resolveMaybeUndefVal(operand)) |val| {
8047 if (val.isUndef()) {8116 if (val.isUndef(mod)) {
8048 return sema.addConstUndef(Type.err_int);8117 return sema.addConstUndef(Type.err_int);
8049 }8118 }
8050 switch (val.tag()) {8119 const err_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
8051 .@"error" => {8120 return sema.addConstant(Type.err_int, try mod.intValue(
8052 const payload = try sema.arena.create(Value.Payload.U64);8121 Type.err_int,
8053 payload.* = .{8122 try mod.getErrorValue(err_name),
8054 .base = .{ .tag = .int_u64 },8123 ));
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 }
8066 }8124 }
80678125
8068 const op_ty = sema.typeOf(uncasted_operand);8126 const op_ty = sema.typeOf(uncasted_operand);
8069 try sema.resolveInferredErrorSetTy(block, src, op_ty);8127 try sema.resolveInferredErrorSetTy(block, src, op_ty);
8070 if (!op_ty.isAnyError()) {8128 if (!op_ty.isAnyError(mod)) {
8071 const names = op_ty.errorSetNames();8129 const names = op_ty.errorSetNames(mod);
8072 switch (names.len) {8130 switch (names.len) {
8073 0 => return sema.addConstant(Type.err_int, Value.zero),8131 0 => return sema.addConstant(Type.err_int, try mod.intValue(Type.err_int, 0)),
8074 1 => return sema.addIntUnsigned(Type.err_int, sema.mod.global_error_set.get(names[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 },
8075 else => {},8136 else => {},
8076 }8137 }
8077 }8138 }
...@@ -8084,28 +8145,26 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -8084,28 +8145,26 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
8084 const tracy = trace(@src());8145 const tracy = trace(@src());
8085 defer tracy.end();8146 defer tracy.end();
80868147
8148 const mod = sema.mod;
8087 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;8149 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8088 const src = LazySrcLoc.nodeOffset(extra.node);8150 const src = LazySrcLoc.nodeOffset(extra.node);
8089 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };8151 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
8090 const uncasted_operand = try sema.resolveInst(extra.operand);8152 const uncasted_operand = try sema.resolveInst(extra.operand);
8091 const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);8153 const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);
8092 const target = sema.mod.getTarget();
80938154
8094 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {8155 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
8095 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(target));8156 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));
8096 if (int > sema.mod.global_error_set.count() or int == 0)8157 if (int > mod.global_error_set.count() or int == 0)
8097 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});8158 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
8098 const payload = try sema.arena.create(Value.Payload.Error);8159 return sema.addConstant(Type.anyerror, (try mod.intern(.{ .err = .{
8099 payload.* = .{8160 .ty = .anyerror_type,
8100 .base = .{ .tag = .@"error" },8161 .name = mod.global_error_set.keys()[int],
8101 .data = .{ .name = sema.mod.error_name_list.items[int] },8162 } })).toValue());
8102 };
8103 return sema.addConstant(Type.anyerror, Value.initPayload(&payload.base));
8104 }8163 }
8105 try sema.requireRuntimeBlock(block, src, operand_src);8164 try sema.requireRuntimeBlock(block, src, operand_src);
8106 if (block.wantSafety()) {8165 if (block.wantSafety()) {
8107 const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand);8166 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));
8109 const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);8168 const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);
8110 const ok = try block.addBinOp(.bit_and, is_lt_len, is_non_zero);8169 const ok = try block.addBinOp(.bit_and, is_lt_len, is_non_zero);
8111 try sema.addSafetyCheck(block, ok, .invalid_error_code);8170 try sema.addSafetyCheck(block, ok, .invalid_error_code);
...@@ -8123,6 +8182,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8123,6 +8182,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8123 const tracy = trace(@src());8182 const tracy = trace(@src());
8124 defer tracy.end();8183 defer tracy.end();
81258184
8185 const mod = sema.mod;
8126 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8186 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8127 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;8187 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
8128 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };8188 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...@@ -8130,7 +8190,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8130 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };8190 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
8131 const lhs = try sema.resolveInst(extra.lhs);8191 const lhs = try sema.resolveInst(extra.lhs);
8132 const rhs = try sema.resolveInst(extra.rhs);8192 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) {
8134 const msg = msg: {8194 const msg = msg: {
8135 const msg = try sema.errMsg(block, lhs_src, "expected error set type, found 'bool'", .{});8195 const msg = try sema.errMsg(block, lhs_src, "expected error set type, found 'bool'", .{});
8136 errdefer msg.destroy(sema.gpa);8196 errdefer msg.destroy(sema.gpa);
...@@ -8141,32 +8201,32 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8141,32 +8201,32 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8141 }8201 }
8142 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);8202 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);
8143 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);8203 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);
8144 if (lhs_ty.zigTypeTag() != .ErrorSet)8204 if (lhs_ty.zigTypeTag(mod) != .ErrorSet)
8145 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(sema.mod)});8205 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(mod)});
8146 if (rhs_ty.zigTypeTag() != .ErrorSet)8206 if (rhs_ty.zigTypeTag(mod) != .ErrorSet)
8147 return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(sema.mod)});8207 return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(mod)});
81488208
8149 // Anything merged with anyerror is anyerror.8209 // 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) {
8151 return Air.Inst.Ref.anyerror_type;8211 return Air.Inst.Ref.anyerror_type;
8152 }8212 }
81538213
8154 if (lhs_ty.castTag(.error_set_inferred)) |payload| {8214 if (mod.typeToInferredErrorSetIndex(lhs_ty).unwrap()) |ies_index| {
8155 try sema.resolveInferredErrorSet(block, src, payload.data);8215 try sema.resolveInferredErrorSet(block, src, ies_index);
8156 // isAnyError might have changed from a false negative to a true positive after resolution.8216 // 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)) {
8158 return Air.Inst.Ref.anyerror_type;8218 return Air.Inst.Ref.anyerror_type;
8159 }8219 }
8160 }8220 }
8161 if (rhs_ty.castTag(.error_set_inferred)) |payload| {8221 if (mod.typeToInferredErrorSetIndex(rhs_ty).unwrap()) |ies_index| {
8162 try sema.resolveInferredErrorSet(block, src, payload.data);8222 try sema.resolveInferredErrorSet(block, src, ies_index);
8163 // isAnyError might have changed from a false negative to a true positive after resolution.8223 // 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)) {
8165 return Air.Inst.Ref.anyerror_type;8225 return Air.Inst.Ref.anyerror_type;
8166 }8226 }
8167 }8227 }
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);
8170 return sema.addType(err_set_ty);8230 return sema.addType(err_set_ty);
8171}8231}
81728232
...@@ -8175,27 +8235,27 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8175,27 +8235,27 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8175 const tracy = trace(@src());8235 const tracy = trace(@src());
8176 defer tracy.end();8236 defer tracy.end();
81778237
8238 const mod = sema.mod;
8178 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;8239 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));8240 const name = inst_data.get(sema.code);
8180 return sema.addConstant(8241 return sema.addConstant(.{ .ip_index = .enum_literal_type }, (try mod.intern(.{
8181 Type.initTag(.enum_literal),8242 .enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name),
8182 try Value.Tag.enum_literal.create(sema.arena, duped_name),8243 })).toValue());
8183 );
8184}8244}
81858245
8186fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8246fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8187 const arena = sema.arena;8247 const mod = sema.mod;
8188 const inst_data = sema.code.instructions.items(.data)[inst].un_node;8248 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
8189 const src = inst_data.src();8249 const src = inst_data.src();
8190 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };8250 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
8191 const operand = try sema.resolveInst(inst_data.operand);8251 const operand = try sema.resolveInst(inst_data.operand);
8192 const operand_ty = sema.typeOf(operand);8252 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)) {
8195 .Enum => operand,8255 .Enum => operand,
8196 .Union => blk: {8256 .Union => blk: {
8197 const union_ty = try sema.resolveTypeFields(operand_ty);8257 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 {
8199 return sema.fail(8259 return sema.fail(
8200 block,8260 block,
8201 operand_src,8261 operand_src,
...@@ -8207,22 +8267,20 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8207,22 +8267,20 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8207 },8267 },
8208 else => {8268 else => {
8209 return sema.fail(block, operand_src, "expected enum or tagged union, found '{}'", .{8269 return sema.fail(block, operand_src, "expected enum or tagged union, found '{}'", .{
8210 operand_ty.fmt(sema.mod),8270 operand_ty.fmt(mod),
8211 });8271 });
8212 },8272 },
8213 };8273 };
8214 const enum_tag_ty = sema.typeOf(enum_tag);8274 const enum_tag_ty = sema.typeOf(enum_tag);
82158275
8216 var int_tag_type_buffer: Type.Payload.Bits = undefined;8276 const int_tag_ty = enum_tag_ty.intTagType(mod);
8217 const int_tag_ty = try enum_tag_ty.intTagType(&int_tag_type_buffer).copy(arena);
82188277
8219 if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| {8278 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));
8221 }8280 }
82228281
8223 if (try sema.resolveMaybeUndefVal(enum_tag)) |enum_tag_val| {8282 if (try sema.resolveMaybeUndefVal(enum_tag)) |enum_tag_val| {
8224 var buffer: Value.Payload.U64 = undefined;8283 const val = try enum_tag_val.enumToInt(enum_tag_ty, mod);
8225 const val = enum_tag_val.enumToInt(enum_tag_ty, &buffer);
8226 return sema.addConstant(int_tag_ty, try val.copy(sema.arena));8284 return sema.addConstant(int_tag_ty, try val.copy(sema.arena));
8227 }8285 }
82288286
...@@ -8231,6 +8289,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8231,6 +8289,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8231}8289}
82328290
8233fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8291fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8292 const mod = sema.mod;
8234 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8293 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8235 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;8294 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
8236 const src = inst_data.src();8295 const src = inst_data.src();
...@@ -8239,24 +8298,23 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8239,24 +8298,23 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8239 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);8298 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
8240 const operand = try sema.resolveInst(extra.rhs);8299 const operand = try sema.resolveInst(extra.rhs);
82418300
8242 if (dest_ty.zigTypeTag() != .Enum) {8301 if (dest_ty.zigTypeTag(mod) != .Enum) {
8243 return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(sema.mod)});8302 return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(mod)});
8244 }8303 }
8245 _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand));8304 _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand));
82468305
8247 if (try sema.resolveMaybeUndefVal(operand)) |int_val| {8306 if (try sema.resolveMaybeUndefVal(operand)) |int_val| {
8248 if (dest_ty.isNonexhaustiveEnum()) {8307 if (dest_ty.isNonexhaustiveEnum(mod)) {
8249 var buffer: Type.Payload.Bits = undefined;8308 const int_tag_ty = dest_ty.intTagType(mod);
8250 const int_tag_ty = dest_ty.intTagType(&buffer);
8251 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {8309 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));
8253 }8311 }
8254 const msg = msg: {8312 const msg = msg: {
8255 const msg = try sema.errMsg(8313 const msg = try sema.errMsg(
8256 block,8314 block,
8257 src,8315 src,
8258 "int value '{}' out of range of non-exhaustive enum '{}'",8316 "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) },
8260 );8318 );
8261 errdefer msg.destroy(sema.gpa);8319 errdefer msg.destroy(sema.gpa);
8262 try sema.addDeclaredHereNote(msg, dest_ty);8320 try sema.addDeclaredHereNote(msg, dest_ty);
...@@ -8264,7 +8322,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8264,7 +8322,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8264 };8322 };
8265 return sema.failWithOwnedErrorMsg(msg);8323 return sema.failWithOwnedErrorMsg(msg);
8266 }8324 }
8267 if (int_val.isUndef()) {8325 if (int_val.isUndef(mod)) {
8268 return sema.failWithUseOfUndef(block, operand_src);8326 return sema.failWithUseOfUndef(block, operand_src);
8269 }8327 }
8270 if (!(try sema.enumHasInt(dest_ty, int_val))) {8328 if (!(try sema.enumHasInt(dest_ty, int_val))) {
...@@ -8273,7 +8331,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8273,7 +8331,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8273 block,8331 block,
8274 src,8332 src,
8275 "enum '{}' has no tag with value '{}'",8333 "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) },
8277 );8335 );
8278 errdefer msg.destroy(sema.gpa);8336 errdefer msg.destroy(sema.gpa);
8279 try sema.addDeclaredHereNote(msg, dest_ty);8337 try sema.addDeclaredHereNote(msg, dest_ty);
...@@ -8281,7 +8339,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8281,7 +8339,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8281 };8339 };
8282 return sema.failWithOwnedErrorMsg(msg);8340 return sema.failWithOwnedErrorMsg(msg);
8283 }8341 }
8284 return sema.addConstant(dest_ty, int_val);8342 return sema.addConstant(dest_ty, try mod.getCoerced(int_val, dest_ty));
8285 }8343 }
82868344
8287 if (try sema.typeHasOnePossibleValue(dest_ty)) |opv| {8345 if (try sema.typeHasOnePossibleValue(dest_ty)) |opv| {
...@@ -8295,8 +8353,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8295,8 +8353,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82958353
8296 try sema.requireRuntimeBlock(block, src, operand_src);8354 try sema.requireRuntimeBlock(block, src, operand_src);
8297 const result = try block.addTyOp(.intcast, dest_ty, operand);8355 const result = try block.addTyOp(.intcast, dest_ty, operand);
8298 if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and8356 if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum(mod) and
8299 sema.mod.backendSupportsFeature(.is_named_enum_value))8357 mod.backendSupportsFeature(.is_named_enum_value))
8300 {8358 {
8301 const ok = try block.addUnOp(.is_named_enum_value, result);8359 const ok = try block.addUnOp(.is_named_enum_value, result);
8302 try sema.addSafetyCheck(block, ok, .invalid_enum_value);8360 try sema.addSafetyCheck(block, ok, .invalid_enum_value);
...@@ -8329,49 +8387,44 @@ fn analyzeOptionalPayloadPtr(...@@ -8329,49 +8387,44 @@ fn analyzeOptionalPayloadPtr(
8329 safety_check: bool,8387 safety_check: bool,
8330 initializing: bool,8388 initializing: bool,
8331) CompileError!Air.Inst.Ref {8389) CompileError!Air.Inst.Ref {
8390 const mod = sema.mod;
8332 const optional_ptr_ty = sema.typeOf(optional_ptr);8391 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();8394 const opt_type = optional_ptr_ty.childType(mod);
8336 if (opt_type.zigTypeTag() != .Optional) {8395 if (opt_type.zigTypeTag(mod) != .Optional) {
8337 return sema.fail(block, src, "expected optional type, found '{}'", .{opt_type.fmt(sema.mod)});8396 return sema.fail(block, src, "expected optional type, found '{}'", .{opt_type.fmt(mod)});
8338 }8397 }
83398398
8340 const child_type = try opt_type.optionalChildAlloc(sema.arena);8399 const child_type = opt_type.optionalChild(mod);
8341 const child_pointer = try Type.ptr(sema.arena, sema.mod, .{8400 const child_pointer = try Type.ptr(sema.arena, mod, .{
8342 .pointee_type = child_type,8401 .pointee_type = child_type,
8343 .mutable = !optional_ptr_ty.isConstPtr(),8402 .mutable = !optional_ptr_ty.isConstPtr(mod),
8344 .@"addrspace" = optional_ptr_ty.ptrAddressSpace(),8403 .@"addrspace" = optional_ptr_ty.ptrAddressSpace(mod),
8345 });8404 });
83468405
8347 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {8406 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {
8348 if (initializing) {8407 if (initializing) {
8349 if (!ptr_val.isComptimeMutablePtr()) {8408 if (!ptr_val.isComptimeMutablePtr(mod)) {
8350 // If the pointer resulting from this function was stored at comptime,8409 // If the pointer resulting from this function was stored at comptime,
8351 // the optional non-null bit would be set that way. But in this case,8410 // the optional non-null bit would be set that way. But in this case,
8352 // we need to emit a runtime instruction to do it.8411 // we need to emit a runtime instruction to do it.
8353 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);8412 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);
8354 }8413 }
8355 return sema.addConstant(8414 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8356 child_pointer,8415 .ty = child_pointer.toIntern(),
8357 try Value.Tag.opt_payload_ptr.create(sema.arena, .{8416 .addr = .{ .opt_payload = ptr_val.toIntern() },
8358 .container_ptr = ptr_val,8417 } })).toValue());
8359 .container_ty = optional_ptr_ty.childType(),
8360 }),
8361 );
8362 }8418 }
8363 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {8419 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
8364 if (val.isNull()) {8420 if (val.isNull(mod)) {
8365 return sema.fail(block, src, "unable to unwrap null", .{});8421 return sema.fail(block, src, "unable to unwrap null", .{});
8366 }8422 }
8367 // The same Value represents the pointer to the optional and the payload.8423 // The same Value represents the pointer to the optional and the payload.
8368 return sema.addConstant(8424 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8369 child_pointer,8425 .ty = child_pointer.toIntern(),
8370 try Value.Tag.opt_payload_ptr.create(sema.arena, .{8426 .addr = .{ .opt_payload = ptr_val.toIntern() },
8371 .container_ptr = ptr_val,8427 } })).toValue());
8372 .container_ty = optional_ptr_ty.childType(),
8373 }),
8374 );
8375 }8428 }
8376 }8429 }
83778430
...@@ -8397,21 +8450,22 @@ fn zirOptionalPayload(...@@ -8397,21 +8450,22 @@ fn zirOptionalPayload(
8397 const tracy = trace(@src());8450 const tracy = trace(@src());
8398 defer tracy.end();8451 defer tracy.end();
83998452
8453 const mod = sema.mod;
8400 const inst_data = sema.code.instructions.items(.data)[inst].un_node;8454 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
8401 const src = inst_data.src();8455 const src = inst_data.src();
8402 const operand = try sema.resolveInst(inst_data.operand);8456 const operand = try sema.resolveInst(inst_data.operand);
8403 const operand_ty = sema.typeOf(operand);8457 const operand_ty = sema.typeOf(operand);
8404 const result_ty = switch (operand_ty.zigTypeTag()) {8458 const result_ty = switch (operand_ty.zigTypeTag(mod)) {
8405 .Optional => try operand_ty.optionalChildAlloc(sema.arena),8459 .Optional => operand_ty.optionalChild(mod),
8406 .Pointer => t: {8460 .Pointer => t: {
8407 if (operand_ty.ptrSize() != .C) {8461 if (operand_ty.ptrSize(mod) != .C) {
8408 return sema.failWithExpectedOptionalType(block, src, operand_ty);8462 return sema.failWithExpectedOptionalType(block, src, operand_ty);
8409 }8463 }
8410 // TODO https://github.com/ziglang/zig/issues/65978464 // TODO https://github.com/ziglang/zig/issues/6597
8411 if (true) break :t operand_ty;8465 if (true) break :t operand_ty;
8412 const ptr_info = operand_ty.ptrInfo().data;8466 const ptr_info = operand_ty.ptrInfo(mod);
8413 break :t try Type.ptr(sema.arena, sema.mod, .{8467 break :t try Type.ptr(sema.arena, mod, .{
8414 .pointee_type = try ptr_info.pointee_type.copy(sema.arena),8468 .pointee_type = ptr_info.pointee_type,
8415 .@"align" = ptr_info.@"align",8469 .@"align" = ptr_info.@"align",
8416 .@"addrspace" = ptr_info.@"addrspace",8470 .@"addrspace" = ptr_info.@"addrspace",
8417 .mutable = ptr_info.mutable,8471 .mutable = ptr_info.mutable,
...@@ -8424,13 +8478,10 @@ fn zirOptionalPayload(...@@ -8424,13 +8478,10 @@ fn zirOptionalPayload(
8424 };8478 };
84258479
8426 if (try sema.resolveDefinedValue(block, src, operand)) |val| {8480 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8427 if (val.isNull()) {8481 return if (val.optionalValue(mod)) |payload|
8428 return sema.fail(block, src, "unable to unwrap null", .{});8482 sema.addConstant(result_ty, payload)
8429 }8483 else
8430 if (val.castTag(.opt_payload)) |payload| {8484 sema.fail(block, src, "unable to unwrap null", .{});
8431 return sema.addConstant(result_ty, payload.data);
8432 }
8433 return sema.addConstant(result_ty, val);
8434 }8485 }
84358486
8436 try sema.requireRuntimeBlock(block, src, null);8487 try sema.requireRuntimeBlock(block, src, null);
...@@ -8450,14 +8501,15 @@ fn zirErrUnionPayload(...@@ -8450,14 +8501,15 @@ fn zirErrUnionPayload(
8450 const tracy = trace(@src());8501 const tracy = trace(@src());
8451 defer tracy.end();8502 defer tracy.end();
84528503
8504 const mod = sema.mod;
8453 const inst_data = sema.code.instructions.items(.data)[inst].un_node;8505 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
8454 const src = inst_data.src();8506 const src = inst_data.src();
8455 const operand = try sema.resolveInst(inst_data.operand);8507 const operand = try sema.resolveInst(inst_data.operand);
8456 const operand_src = src;8508 const operand_src = src;
8457 const err_union_ty = sema.typeOf(operand);8509 const err_union_ty = sema.typeOf(operand);
8458 if (err_union_ty.zigTypeTag() != .ErrorUnion) {8510 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) {
8459 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{8511 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{
8460 err_union_ty.fmt(sema.mod),8512 err_union_ty.fmt(mod),
8461 });8513 });
8462 }8514 }
8463 return sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);8515 return sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
...@@ -8468,24 +8520,27 @@ fn analyzeErrUnionPayload(...@@ -8468,24 +8520,27 @@ fn analyzeErrUnionPayload(
8468 block: *Block,8520 block: *Block,
8469 src: LazySrcLoc,8521 src: LazySrcLoc,
8470 err_union_ty: Type,8522 err_union_ty: Type,
8471 operand: Zir.Inst.Ref,8523 operand: Air.Inst.Ref,
8472 operand_src: LazySrcLoc,8524 operand_src: LazySrcLoc,
8473 safety_check: bool,8525 safety_check: bool,
8474) CompileError!Air.Inst.Ref {8526) 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);
8476 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {8529 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
8477 if (val.getError()) |name| {8530 if (val.getErrorName(mod).unwrap()) |name| {
8478 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});8531 return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)});
8479 }8532 }
8480 const data = val.castTag(.eu_payload).?.data;8533 return sema.addConstant(
8481 return sema.addConstant(payload_ty, data);8534 payload_ty,
8535 mod.intern_pool.indexToKey(val.toIntern()).error_union.val.payload.toValue(),
8536 );
8482 }8537 }
84838538
8484 try sema.requireRuntimeBlock(block, src, null);8539 try sema.requireRuntimeBlock(block, src, null);
84858540
8486 // If the error set has no fields then no safety check is needed.8541 // If the error set has no fields then no safety check is needed.
8487 if (safety_check and block.wantSafety() and8542 if (safety_check and block.wantSafety() and
8488 !err_union_ty.errorUnionSet().errorSetIsEmpty())8543 !err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod))
8489 {8544 {
8490 try sema.panicUnwrapError(block, operand, .unwrap_errunion_err, .is_non_err);8545 try sema.panicUnwrapError(block, operand, .unwrap_errunion_err, .is_non_err);
8491 }8546 }
...@@ -8517,52 +8572,46 @@ fn analyzeErrUnionPayloadPtr(...@@ -8517,52 +8572,46 @@ fn analyzeErrUnionPayloadPtr(
8517 safety_check: bool,8572 safety_check: bool,
8518 initializing: bool,8573 initializing: bool,
8519) CompileError!Air.Inst.Ref {8574) CompileError!Air.Inst.Ref {
8575 const mod = sema.mod;
8520 const operand_ty = sema.typeOf(operand);8576 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) {
8524 return sema.fail(block, src, "expected error union type, found '{}'", .{8580 return sema.fail(block, src, "expected error union type, found '{}'", .{
8525 operand_ty.elemType().fmt(sema.mod),8581 operand_ty.childType(mod).fmt(mod),
8526 });8582 });
8527 }8583 }
85288584
8529 const err_union_ty = operand_ty.elemType();8585 const err_union_ty = operand_ty.childType(mod);
8530 const payload_ty = err_union_ty.errorUnionPayload();8586 const payload_ty = err_union_ty.errorUnionPayload(mod);
8531 const operand_pointer_ty = try Type.ptr(sema.arena, sema.mod, .{8587 const operand_pointer_ty = try Type.ptr(sema.arena, mod, .{
8532 .pointee_type = payload_ty,8588 .pointee_type = payload_ty,
8533 .mutable = !operand_ty.isConstPtr(),8589 .mutable = !operand_ty.isConstPtr(mod),
8534 .@"addrspace" = operand_ty.ptrAddressSpace(),8590 .@"addrspace" = operand_ty.ptrAddressSpace(mod),
8535 });8591 });
85368592
8537 if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| {8593 if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| {
8538 if (initializing) {8594 if (initializing) {
8539 if (!ptr_val.isComptimeMutablePtr()) {8595 if (!ptr_val.isComptimeMutablePtr(mod)) {
8540 // If the pointer resulting from this function was stored at comptime,8596 // If the pointer resulting from this function was stored at comptime,
8541 // the error union error code would be set that way. But in this case,8597 // the error union error code would be set that way. But in this case,
8542 // we need to emit a runtime instruction to do it.8598 // we need to emit a runtime instruction to do it.
8543 try sema.requireRuntimeBlock(block, src, null);8599 try sema.requireRuntimeBlock(block, src, null);
8544 _ = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);8600 _ = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);
8545 }8601 }
8546 return sema.addConstant(8602 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8547 operand_pointer_ty,8603 .ty = operand_pointer_ty.toIntern(),
8548 try Value.Tag.eu_payload_ptr.create(sema.arena, .{8604 .addr = .{ .eu_payload = ptr_val.toIntern() },
8549 .container_ptr = ptr_val,8605 } })).toValue());
8550 .container_ty = operand_ty.elemType(),
8551 }),
8552 );
8553 }8606 }
8554 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {8607 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
8555 if (val.getError()) |name| {8608 if (val.getErrorName(mod).unwrap()) |name| {
8556 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});8609 return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)});
8557 }8610 }
85588611 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8559 return sema.addConstant(8612 .ty = operand_pointer_ty.toIntern(),
8560 operand_pointer_ty,8613 .addr = .{ .eu_payload = ptr_val.toIntern() },
8561 try Value.Tag.eu_payload_ptr.create(sema.arena, .{8614 } })).toValue());
8562 .container_ptr = ptr_val,
8563 .container_ty = operand_ty.elemType(),
8564 }),
8565 );
8566 }8615 }
8567 }8616 }
85688617
...@@ -8570,7 +8619,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -8570,7 +8619,7 @@ fn analyzeErrUnionPayloadPtr(
85708619
8571 // If the error set has no fields then no safety check is needed.8620 // If the error set has no fields then no safety check is needed.
8572 if (safety_check and block.wantSafety() and8621 if (safety_check and block.wantSafety() and
8573 !err_union_ty.errorUnionSet().errorSetIsEmpty())8622 !err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod))
8574 {8623 {
8575 try sema.panicUnwrapError(block, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);8624 try sema.panicUnwrapError(block, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
8576 }8625 }
...@@ -8594,18 +8643,21 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -8594,18 +8643,21 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
8594}8643}
85958644
8596fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {8645fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {
8646 const mod = sema.mod;
8597 const operand_ty = sema.typeOf(operand);8647 const operand_ty = sema.typeOf(operand);
8598 if (operand_ty.zigTypeTag() != .ErrorUnion) {8648 if (operand_ty.zigTypeTag(mod) != .ErrorUnion) {
8599 return sema.fail(block, src, "expected error union type, found '{}'", .{8649 return sema.fail(block, src, "expected error union type, found '{}'", .{
8600 operand_ty.fmt(sema.mod),8650 operand_ty.fmt(mod),
8601 });8651 });
8602 }8652 }
86038653
8604 const result_ty = operand_ty.errorUnionSet();8654 const result_ty = operand_ty.errorUnionSet(mod);
86058655
8606 if (try sema.resolveDefinedValue(block, src, operand)) |val| {8656 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8607 assert(val.getError() != null);8657 return sema.addConstant(result_ty, (try mod.intern(.{ .err = .{
8608 return sema.addConstant(result_ty, val);8658 .ty = result_ty.toIntern(),
8659 .name = mod.intern_pool.indexToKey(val.toIntern()).error_union.val.err_name,
8660 } })).toValue());
8609 }8661 }
86108662
8611 try sema.requireRuntimeBlock(block, src, null);8663 try sema.requireRuntimeBlock(block, src, null);
...@@ -8617,23 +8669,24 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -8617,23 +8669,24 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
8617 const tracy = trace(@src());8669 const tracy = trace(@src());
8618 defer tracy.end();8670 defer tracy.end();
86198671
8672 const mod = sema.mod;
8620 const inst_data = sema.code.instructions.items(.data)[inst].un_node;8673 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
8621 const src = inst_data.src();8674 const src = inst_data.src();
8622 const operand = try sema.resolveInst(inst_data.operand);8675 const operand = try sema.resolveInst(inst_data.operand);
8623 const operand_ty = sema.typeOf(operand);8676 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) {
8627 return sema.fail(block, src, "expected error union type, found '{}'", .{8680 return sema.fail(block, src, "expected error union type, found '{}'", .{
8628 operand_ty.elemType().fmt(sema.mod),8681 operand_ty.childType(mod).fmt(mod),
8629 });8682 });
8630 }8683 }
86318684
8632 const result_ty = operand_ty.elemType().errorUnionSet();8685 const result_ty = operand_ty.childType(mod).errorUnionSet(mod);
86338686
8634 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {8687 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
8635 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {8688 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
8636 assert(val.getError() != null);8689 assert(val.getErrorName(mod) != .none);
8637 return sema.addConstant(result_ty, val);8690 return sema.addConstant(result_ty, val);
8638 }8691 }
8639 }8692 }
...@@ -8667,7 +8720,7 @@ fn zirFunc(...@@ -8667,7 +8720,7 @@ fn zirFunc(
8667 break :blk ret_ty;8720 break :blk ret_ty;
8668 } else |err| switch (err) {8721 } else |err| switch (err) {
8669 error.GenericPoison => {8722 error.GenericPoison => {
8670 break :blk Type.initTag(.generic_poison);8723 break :blk Type.generic_poison;
8671 },8724 },
8672 else => |e| return e,8725 else => |e| return e,
8673 }8726 }
...@@ -8677,8 +8730,7 @@ fn zirFunc(...@@ -8677,8 +8730,7 @@ fn zirFunc(
8677 extra_index += ret_ty_body.len;8730 extra_index += ret_ty_body.len;
86788731
8679 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type, "return type must be comptime-known");8732 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;8733 break :blk ret_ty_val.toType();
8681 break :blk try ret_ty_val.toType(&buffer).copy(sema.arena);
8682 },8734 },
8683 };8735 };
86848736
...@@ -8745,10 +8797,10 @@ fn resolveGenericBody(...@@ -8745,10 +8797,10 @@ fn resolveGenericBody(
8745 };8797 };
8746 switch (err) {8798 switch (err) {
8747 error.GenericPoison => {8799 error.GenericPoison => {
8748 if (dest_ty.tag() == .type) {8800 if (dest_ty.toIntern() == .type_type) {
8749 return Value.initTag(.generic_poison_type);8801 return Value.generic_poison_type;
8750 } else {8802 } else {
8751 return Value.initTag(.generic_poison);8803 return Value.generic_poison;
8752 }8804 }
8753 },8805 },
8754 else => |e| return e,8806 else => |e| return e,
...@@ -8822,7 +8874,7 @@ fn handleExternLibName(...@@ -8822,7 +8874,7 @@ fn handleExternLibName(
8822const FuncLinkSection = union(enum) {8874const FuncLinkSection = union(enum) {
8823 generic,8875 generic,
8824 default,8876 default,
8825 explicit: []const u8,8877 explicit: InternPool.NullTerminatedString,
8826};8878};
88278879
8828fn funcCommon(8880fn funcCommon(
...@@ -8849,11 +8901,13 @@ fn funcCommon(...@@ -8849,11 +8901,13 @@ fn funcCommon(
8849 noalias_bits: u32,8901 noalias_bits: u32,
8850 is_noinline: bool,8902 is_noinline: bool,
8851) CompileError!Air.Inst.Ref {8903) CompileError!Air.Inst.Ref {
8904 const mod = sema.mod;
8905 const gpa = sema.gpa;
8852 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };8906 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
8853 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };8907 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
8854 const func_src = LazySrcLoc.nodeOffset(src_node_offset);8908 const func_src = LazySrcLoc.nodeOffset(src_node_offset);
88558909
8856 var is_generic = bare_return_type.tag() == .generic_poison or8910 var is_generic = bare_return_type.isGenericPoison() or
8857 alignment == null or8911 alignment == null or
8858 address_space == null or8912 address_space == null or
8859 section == .generic or8913 section == .generic or
...@@ -8869,70 +8923,42 @@ fn funcCommon(...@@ -8869,70 +8923,42 @@ fn funcCommon(
8869 }8923 }
88708924
8871 var destroy_fn_on_error = false;8925 var destroy_fn_on_error = false;
8872 const new_func: *Module.Fn = new_func: {8926 const new_func_index = new_func: {
8873 if (!has_body) break :new_func undefined;8927 if (!has_body) break :new_func undefined;
8874 if (sema.comptime_args_fn_inst == func_inst) {8928 if (sema.comptime_args_fn_inst == func_inst) {
8875 const new_func = sema.preallocated_new_func.?;8929 const new_func_index = sema.preallocated_new_func.unwrap().?;
8876 sema.preallocated_new_func = null; // take ownership8930 sema.preallocated_new_func = .none; // take ownership
8877 break :new_func new_func;8931 break :new_func new_func_index;
8878 }8932 }
8879 destroy_fn_on_error = true;8933 destroy_fn_on_error = true;
8880 const new_func = try sema.gpa.create(Module.Fn);8934 var new_func: Module.Fn = undefined;
8881 // Set this here so that the inferred return type can be printed correctly if it appears in an error.8935 // Set this here so that the inferred return type can be printed correctly if it appears in an error.
8882 new_func.owner_decl = sema.owner_decl_index;8936 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;
8884 };8939 };
8885 errdefer if (destroy_fn_on_error) sema.gpa.destroy(new_func);8940 errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
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.
88908941
8891 const target = sema.mod.getTarget();8942 const target = mod.getTarget();
8892 const fn_ty: Type = fn_ty: {8943 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
8918 // In the case of generic calling convention, or generic alignment, we use8944 // In the case of generic calling convention, or generic alignment, we use
8919 // default values which are only meaningful for the generic function, *not*8945 // default values which are only meaningful for the generic function, *not*
8920 // the instantiation, which can depend on comptime parameters.8946 // the instantiation, which can depend on comptime parameters.
8921 // Related proposal: https://github.com/ziglang/zig/issues/118348947 // Related proposal: https://github.com/ziglang/zig/issues/11834
8922 const cc_resolved = cc orelse .Unspecified;8948 const cc_resolved = cc orelse .Unspecified;
8923 const param_types = try sema.arena.alloc(Type, block.params.items.len);8949 const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len);
8924 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);8950 var comptime_bits: u32 = 0;
8925 for (block.params.items, 0..) |param, i| {8951 for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| {
8926 const is_noalias = blk: {8952 const is_noalias = blk: {
8927 const index = std.math.cast(u5, i) orelse break :blk false;8953 const index = std.math.cast(u5, i) orelse break :blk false;
8928 break :blk @truncate(u1, noalias_bits >> index) != 0;8954 break :blk @truncate(u1, noalias_bits >> index) != 0;
8929 };8955 };
8930 param_types[i] = param.ty;8956 dest_param_ty.* = param.ty.toIntern();
8931 sema.analyzeParameter(8957 sema.analyzeParameter(
8932 block,8958 block,
8933 .unneeded,8959 .unneeded,
8934 param,8960 param,
8935 comptime_params,8961 &comptime_bits,
8936 i,8962 i,
8937 &is_generic,8963 &is_generic,
8938 cc_resolved,8964 cc_resolved,
...@@ -8940,12 +8966,12 @@ fn funcCommon(...@@ -8940,12 +8966,12 @@ fn funcCommon(
8940 is_noalias,8966 is_noalias,
8941 ) catch |err| switch (err) {8967 ) catch |err| switch (err) {
8942 error.NeededSourceLocation => {8968 error.NeededSourceLocation => {
8943 const decl = sema.mod.declPtr(block.src_decl);8969 const decl = mod.declPtr(block.src_decl);
8944 try sema.analyzeParameter(8970 try sema.analyzeParameter(
8945 block,8971 block,
8946 Module.paramSrc(src_node_offset, sema.gpa, decl, i),8972 Module.paramSrc(src_node_offset, mod, decl, i),
8947 param,8973 param,
8948 comptime_params,8974 &comptime_bits,
8949 i,8975 i,
8950 &is_generic,8976 &is_generic,
8951 cc_resolved,8977 cc_resolved,
...@@ -8961,7 +8987,7 @@ fn funcCommon(...@@ -8961,7 +8987,7 @@ fn funcCommon(
8961 var ret_ty_requires_comptime = false;8987 var ret_ty_requires_comptime = false;
8962 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {8988 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
8963 ret_ty_requires_comptime = ret_comptime;8989 ret_ty_requires_comptime = ret_comptime;
8964 break :rp bare_return_type.tag() == .generic_poison;8990 break :rp bare_return_type.isGenericPoison();
8965 } else |err| switch (err) {8991 } else |err| switch (err) {
8966 error.GenericPoison => rp: {8992 error.GenericPoison => rp: {
8967 is_generic = true;8993 is_generic = true;
...@@ -8970,43 +8996,41 @@ fn funcCommon(...@@ -8970,43 +8996,41 @@ fn funcCommon(
8970 else => |e| return e,8996 else => |e| return e,
8971 };8997 };
89728998
8973 const return_type = if (!inferred_error_set or ret_poison)8999 const return_type: Type = if (!inferred_error_set or ret_poison)
8974 bare_return_type9000 bare_return_type
8975 else blk: {9001 else blk: {
8976 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);9002 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
8977 const node = try sema.gpa.create(Module.Fn.InferredErrorSetListNode);9003 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
8978 node.data = .{ .func = new_func };9004 .func = new_func_index,
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,
8985 });9005 });
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);
8986 };9008 };
89879009
8988 if (!return_type.isValidReturnType()) {9010 if (!return_type.isValidReturnType(mod)) {
8989 const opaque_str = if (return_type.zigTypeTag() == .Opaque) "opaque " else "";9011 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
8990 const msg = msg: {9012 const msg = msg: {
8991 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{9013 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),
8993 });9015 });
8994 errdefer msg.destroy(sema.gpa);9016 errdefer msg.destroy(gpa);
89959017
8996 try sema.addDeclaredHereNote(msg, return_type);9018 try sema.addDeclaredHereNote(msg, return_type);
8997 break :msg msg;9019 break :msg msg;
8998 };9020 };
8999 return sema.failWithOwnedErrorMsg(msg);9021 return sema.failWithOwnedErrorMsg(msg);
9000 }9022 }
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 {
9002 const msg = msg: {9026 const msg = msg: {
9003 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{9027 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),
9005 });9029 });
9006 errdefer msg.destroy(sema.gpa);9030 errdefer msg.destroy(gpa);
90079031
9008 const src_decl = sema.mod.declPtr(block.src_decl);9032 const src_decl = mod.declPtr(block.src_decl);
9009 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);9033 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty);
90109034
9011 try sema.addDeclaredHereNote(msg, return_type);9035 try sema.addDeclaredHereNote(msg, return_type);
9012 break :msg msg;9036 break :msg msg;
...@@ -9024,9 +9048,9 @@ fn funcCommon(...@@ -9024,9 +9048,9 @@ fn funcCommon(
9024 block,9048 block,
9025 ret_ty_src,9049 ret_ty_src,
9026 "function with comptime-only return type '{}' requires all parameters to be comptime",9050 "function with comptime-only return type '{}' requires all parameters to be comptime",
9027 .{return_type.fmt(sema.mod)},9051 .{return_type.fmt(mod)},
9028 );9052 );
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
9031 const tags = sema.code.instructions.items(.tag);9055 const tags = sema.code.instructions.items(.tag);
9032 const data = sema.code.instructions.items(.data);9056 const data = sema.code.instructions.items(.data);
...@@ -9049,7 +9073,7 @@ fn funcCommon(...@@ -9049,7 +9073,7 @@ fn funcCommon(
9049 return sema.failWithOwnedErrorMsg(msg);9073 return sema.failWithOwnedErrorMsg(msg);
9050 }9074 }
90519075
9052 const arch = sema.mod.getTarget().cpu.arch;9076 const arch = mod.getTarget().cpu.arch;
9053 if (switch (cc_resolved) {9077 if (switch (cc_resolved) {
9054 .Unspecified, .C, .Naked, .Async, .Inline => null,9078 .Unspecified, .C, .Naked, .Async, .Inline => null,
9055 .Interrupt => switch (arch) {9079 .Interrupt => switch (arch) {
...@@ -9092,8 +9116,7 @@ fn funcCommon(...@@ -9092,8 +9116,7 @@ fn funcCommon(
9092 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});9116 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
9093 }9117 }
9094 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;9118 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
9095 for (comptime_params) |ct| is_generic = is_generic or ct;9119 is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
9096 is_generic = is_generic or ret_ty_requires_comptime;
90979120
9098 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {9121 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
9099 // Make sure that StackTrace's fields are resolved so that the backend can9122 // Make sure that StackTrace's fields are resolved so that the backend can
...@@ -9102,68 +9125,58 @@ fn funcCommon(...@@ -9102,68 +9125,58 @@ fn funcCommon(
9102 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);9125 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
9103 }9126 }
91049127
9105 break :fn_ty try Type.Tag.function.create(sema.arena, .{9128 break :fn_ty try mod.funcType(.{
9106 .param_types = param_types,9129 .param_types = param_types,
9107 .comptime_params = comptime_params.ptr,9130 .noalias_bits = noalias_bits,
9108 .return_type = return_type,9131 .comptime_bits = comptime_bits,
9132 .return_type = return_type.toIntern(),
9109 .cc = cc_resolved,9133 .cc = cc_resolved,
9110 .cc_is_generic = cc == null,9134 .cc_is_generic = cc == null,
9111 .alignment = alignment orelse 0,9135 .alignment = if (alignment) |a| InternPool.Alignment.fromByteUnits(a) else .none,
9112 .align_is_generic = alignment == null,9136 .align_is_generic = alignment == null,
9113 .section_is_generic = section == .generic,9137 .section_is_generic = section == .generic,
9114 .addrspace_is_generic = address_space == null,9138 .addrspace_is_generic = address_space == null,
9115 .is_var_args = var_args,9139 .is_var_args = var_args,
9116 .is_generic = is_generic,9140 .is_generic = is_generic,
9117 .is_noinline = is_noinline,9141 .is_noinline = is_noinline,
9118 .noalias_bits = noalias_bits,
9119 });9142 });
9120 };9143 };
91219144
9122 sema.owner_decl.@"linksection" = switch (section) {9145 sema.owner_decl.@"linksection" = switch (section) {
9123 .generic => undefined,9146 .generic => .none,
9124 .default => null,9147 .default => .none,
9125 .explicit => |section_name| try sema.perm_arena.dupeZ(u8, section_name),9148 .explicit => |section_name| section_name.toOptional(),
9126 };9149 };
9127 sema.owner_decl.@"align" = alignment orelse 0;9150 sema.owner_decl.@"align" = alignment orelse 0;
9128 sema.owner_decl.@"addrspace" = address_space orelse .generic;9151 sema.owner_decl.@"addrspace" = address_space orelse .generic;
91299152
9130 if (is_extern) {9153 if (is_extern) {
9131 const new_extern_fn = try sema.gpa.create(Module.ExternFn);9154 return sema.addConstant(fn_ty, (try mod.intern(.{ .extern_func = .{
9132 errdefer sema.gpa.destroy(new_extern_fn);9155 .ty = fn_ty.toIntern(),
91339156 .decl = sema.owner_decl_index,
9134 new_extern_fn.* = Module.ExternFn{9157 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9135 .owner_decl = sema.owner_decl_index,9158 gpa,
9136 .lib_name = null,9159 try sema.handleExternLibName(block, .{
9137 };9160 .node_offset_lib_name = src_node_offset,
91389161 }, lib_name),
9139 if (opt_lib_name) |lib_name| {9162 )).toOptional() else .none,
9140 new_extern_fn.lib_name = try sema.handleExternLibName(block, .{9163 } })).toValue());
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));
9151 }9164 }
91529165
9153 if (!has_body) {9166 if (!has_body) {
9154 return sema.addType(fn_ty);9167 return sema.addType(fn_ty);
9155 }9168 }
91569169
9157 const is_inline = fn_ty.fnCallingConvention() == .Inline;9170 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;
9158 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;9171 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
91599172
9160 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {9173 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
9161 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;9174 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
9162 } else null;9175 } else null;
91639176
9177 const new_func = mod.funcPtr(new_func_index);
9164 const hash = new_func.hash;9178 const hash = new_func.hash;
9165 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;9179 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);
9167 new_func.* = .{9180 new_func.* = .{
9168 .state = anal_state,9181 .state = anal_state,
9169 .zir_body_inst = func_inst,9182 .zir_body_inst = func_inst,
...@@ -9178,15 +9191,10 @@ fn funcCommon(...@@ -9178,15 +9191,10 @@ fn funcCommon(
9178 .branch_quota = default_branch_quota,9191 .branch_quota = default_branch_quota,
9179 .is_noinline = is_noinline,9192 .is_noinline = is_noinline,
9180 };9193 };
9181 if (maybe_inferred_error_set_node) |node| {9194 return sema.addConstant(fn_ty, (try mod.intern(.{ .func = .{
9182 new_func.inferred_error_sets.prepend(node);9195 .ty = fn_ty.toIntern(),
9183 }9196 .index = new_func_index,
9184 maybe_inferred_error_set_node = null;9197 } })).toValue());
9185 fn_payload.* = .{
9186 .base = .{ .tag = .function },
9187 .data = new_func,
9188 };
9189 return sema.addConstant(fn_ty, Value.initPayload(&fn_payload.base));
9190}9198}
91919199
9192fn analyzeParameter(9200fn analyzeParameter(
...@@ -9194,29 +9202,32 @@ fn analyzeParameter(...@@ -9194,29 +9202,32 @@ fn analyzeParameter(
9194 block: *Block,9202 block: *Block,
9195 param_src: LazySrcLoc,9203 param_src: LazySrcLoc,
9196 param: Block.Param,9204 param: Block.Param,
9197 comptime_params: []bool,9205 comptime_bits: *u32,
9198 i: usize,9206 i: usize,
9199 is_generic: *bool,9207 is_generic: *bool,
9200 cc: std.builtin.CallingConvention,9208 cc: std.builtin.CallingConvention,
9201 has_body: bool,9209 has_body: bool,
9202 is_noalias: bool,9210 is_noalias: bool,
9203) !void {9211) !void {
9212 const mod = sema.mod;
9204 const requires_comptime = try sema.typeRequiresComptime(param.ty);9213 const requires_comptime = try sema.typeRequiresComptime(param.ty);
9205 comptime_params[i] = param.is_comptime or requires_comptime;9214 if (param.is_comptime or requires_comptime) {
9206 const this_generic = param.ty.tag() == .generic_poison;9215 comptime_bits.* |= @as(u32, 1) << @intCast(u5, i); // TODO: handle cast error
9216 }
9217 const this_generic = param.ty.isGenericPoison();
9207 is_generic.* = is_generic.* or this_generic;9218 is_generic.* = is_generic.* or this_generic;
9208 const target = sema.mod.getTarget();9219 const target = mod.getTarget();
9209 if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) {9220 if (param.is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
9210 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9221 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9211 }9222 }
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)) {
9213 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9224 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9214 }9225 }
9215 if (!param.ty.isValidParamType()) {9226 if (!param.ty.isValidParamType(mod)) {
9216 const opaque_str = if (param.ty.zigTypeTag() == .Opaque) "opaque " else "";9227 const opaque_str = if (param.ty.zigTypeTag(mod) == .Opaque) "opaque " else "";
9217 const msg = msg: {9228 const msg = msg: {
9218 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{9229 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),
9220 });9231 });
9221 errdefer msg.destroy(sema.gpa);9232 errdefer msg.destroy(sema.gpa);
92229233
...@@ -9225,15 +9236,15 @@ fn analyzeParameter(...@@ -9225,15 +9236,15 @@ fn analyzeParameter(
9225 };9236 };
9226 return sema.failWithOwnedErrorMsg(msg);9237 return sema.failWithOwnedErrorMsg(msg);
9227 }9238 }
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)) {
9229 const msg = msg: {9240 const msg = msg: {
9230 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{9241 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),
9232 });9243 });
9233 errdefer msg.destroy(sema.gpa);9244 errdefer msg.destroy(sema.gpa);
92349245
9235 const src_decl = sema.mod.declPtr(block.src_decl);9246 const src_decl = mod.declPtr(block.src_decl);
9236 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);9247 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param.ty, .param_ty);
92379248
9238 try sema.addDeclaredHereNote(msg, param.ty);9249 try sema.addDeclaredHereNote(msg, param.ty);
9239 break :msg msg;9250 break :msg msg;
...@@ -9243,12 +9254,12 @@ fn analyzeParameter(...@@ -9243,12 +9254,12 @@ fn analyzeParameter(
9243 if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) {9254 if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) {
9244 const msg = msg: {9255 const msg = msg: {
9245 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{9256 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),
9247 });9258 });
9248 errdefer msg.destroy(sema.gpa);9259 errdefer msg.destroy(sema.gpa);
92499260
9250 const src_decl = sema.mod.declPtr(block.src_decl);9261 const src_decl = mod.declPtr(block.src_decl);
9251 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl), param.ty);9262 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param.ty);
92529263
9253 try sema.addDeclaredHereNote(msg, param.ty);9264 try sema.addDeclaredHereNote(msg, param.ty);
9254 break :msg msg;9265 break :msg msg;
...@@ -9256,7 +9267,7 @@ fn analyzeParameter(...@@ -9256,7 +9267,7 @@ fn analyzeParameter(
9256 return sema.failWithOwnedErrorMsg(msg);9267 return sema.failWithOwnedErrorMsg(msg);
9257 }9268 }
9258 if (!sema.is_generic_instantiation and !this_generic and is_noalias and9269 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)))
9260 {9271 {
9261 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});9272 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9262 }9273 }
...@@ -9283,7 +9294,7 @@ fn zirParam(...@@ -9283,7 +9294,7 @@ fn zirParam(
9283 const prev_preallocated_new_func = sema.preallocated_new_func;9294 const prev_preallocated_new_func = sema.preallocated_new_func;
9284 const prev_no_partial_func_type = sema.no_partial_func_ty;9295 const prev_no_partial_func_type = sema.no_partial_func_ty;
9285 block.params = .{};9296 block.params = .{};
9286 sema.preallocated_new_func = null;9297 sema.preallocated_new_func = .none;
9287 sema.no_partial_func_ty = true;9298 sema.no_partial_func_ty = true;
9288 defer {9299 defer {
9289 block.params.deinit(sema.gpa);9300 block.params.deinit(sema.gpa);
...@@ -9309,7 +9320,7 @@ fn zirParam(...@@ -9309,7 +9320,7 @@ fn zirParam(
9309 // We result the param instruction with a poison value and9320 // We result the param instruction with a poison value and
9310 // insert an anytype parameter.9321 // insert an anytype parameter.
9311 try block.params.append(sema.gpa, .{9322 try block.params.append(sema.gpa, .{
9312 .ty = Type.initTag(.generic_poison),9323 .ty = Type.generic_poison,
9313 .is_comptime = comptime_syntax,9324 .is_comptime = comptime_syntax,
9314 .name = param_name,9325 .name = param_name,
9315 });9326 });
...@@ -9330,7 +9341,7 @@ fn zirParam(...@@ -9330,7 +9341,7 @@ fn zirParam(
9330 // We result the param instruction with a poison value and9341 // We result the param instruction with a poison value and
9331 // insert an anytype parameter.9342 // insert an anytype parameter.
9332 try block.params.append(sema.gpa, .{9343 try block.params.append(sema.gpa, .{
9333 .ty = Type.initTag(.generic_poison),9344 .ty = Type.generic_poison,
9334 .is_comptime = comptime_syntax,9345 .is_comptime = comptime_syntax,
9335 .name = param_name,9346 .name = param_name,
9336 });9347 });
...@@ -9340,7 +9351,7 @@ fn zirParam(...@@ -9340,7 +9351,7 @@ fn zirParam(
9340 else => |e| return e,9351 else => |e| return e,
9341 } or comptime_syntax;9352 } or comptime_syntax;
9342 if (sema.inst_map.get(inst)) |arg| {9353 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) {
9344 // We have a comptime value for this parameter so it should be elided from the9355 // We have a comptime value for this parameter so it should be elided from the
9345 // function type of the function instruction in this block.9356 // function type of the function instruction in this block.
9346 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {9357 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
...@@ -9363,7 +9374,7 @@ fn zirParam(...@@ -9363,7 +9374,7 @@ fn zirParam(
9363 assert(sema.inst_map.remove(inst));9374 assert(sema.inst_map.remove(inst));
9364 }9375 }
93659376
9366 if (sema.preallocated_new_func != null) {9377 if (sema.preallocated_new_func != .none) {
9367 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {9378 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
9368 // In this case we are instantiating a generic function call with a non-comptime9379 // In this case we are instantiating a generic function call with a non-comptime
9369 // non-anytype parameter that ended up being a one-possible-type.9380 // non-anytype parameter that ended up being a one-possible-type.
...@@ -9383,7 +9394,7 @@ fn zirParam(...@@ -9383,7 +9394,7 @@ fn zirParam(
9383 if (is_comptime) {9394 if (is_comptime) {
9384 // If this is a comptime parameter we can add a constant generic_poison9395 // If this is a comptime parameter we can add a constant generic_poison
9385 // since this is also a generic parameter.9396 // 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);
9387 sema.inst_map.putAssumeCapacityNoClobber(inst, result);9398 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9388 } else {9399 } else {
9389 // Otherwise we need a dummy runtime instruction.9400 // Otherwise we need a dummy runtime instruction.
...@@ -9428,7 +9439,7 @@ fn zirParamAnytype(...@@ -9428,7 +9439,7 @@ fn zirParamAnytype(
9428 // We are evaluating a generic function without any comptime args provided.9439 // We are evaluating a generic function without any comptime args provided.
94299440
9430 try block.params.append(sema.gpa, .{9441 try block.params.append(sema.gpa, .{
9431 .ty = Type.initTag(.generic_poison),9442 .ty = Type.generic_poison,
9432 .is_comptime = comptime_syntax,9443 .is_comptime = comptime_syntax,
9433 .name = param_name,9444 .name = param_name,
9434 });9445 });
...@@ -9472,13 +9483,14 @@ fn analyzeAs(...@@ -9472,13 +9483,14 @@ fn analyzeAs(
9472 zir_operand: Zir.Inst.Ref,9483 zir_operand: Zir.Inst.Ref,
9473 no_cast_to_comptime_int: bool,9484 no_cast_to_comptime_int: bool,
9474) CompileError!Air.Inst.Ref {9485) CompileError!Air.Inst.Ref {
9486 const mod = sema.mod;
9475 const operand = try sema.resolveInst(zir_operand);9487 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;
9477 const dest_ty = sema.resolveType(block, src, zir_dest_type) catch |err| switch (err) {9489 const dest_ty = sema.resolveType(block, src, zir_dest_type) catch |err| switch (err) {
9478 error.GenericPoison => return operand,9490 error.GenericPoison => return operand,
9479 else => |e| return e,9491 else => |e| return e,
9480 };9492 };
9481 if (dest_ty.zigTypeTag() == .NoReturn) {9493 if (dest_ty.zigTypeTag(mod) == .NoReturn) {
9482 return sema.fail(block, src, "cannot cast to noreturn", .{});9494 return sema.fail(block, src, "cannot cast to noreturn", .{});
9483 }9495 }
9484 const is_ret = if (Zir.refToIndex(zir_dest_type)) |ptr_index|9496 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...@@ -9495,15 +9507,19 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
9495 const tracy = trace(@src());9507 const tracy = trace(@src());
9496 defer tracy.end();9508 defer tracy.end();
94979509
9510 const mod = sema.mod;
9498 const inst_data = sema.code.instructions.items(.data)[inst].un_node;9511 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
9499 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };9512 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9500 const ptr = try sema.resolveInst(inst_data.operand);9513 const ptr = try sema.resolveInst(inst_data.operand);
9501 const ptr_ty = sema.typeOf(ptr);9514 const ptr_ty = sema.typeOf(ptr);
9502 if (!ptr_ty.isPtrAtRuntime()) {9515 if (!ptr_ty.isPtrAtRuntime(mod)) {
9503 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)});9516 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(mod)});
9504 }9517 }
9505 if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| {9518 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 );
9507 }9523 }
9508 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);9524 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
9509 return block.addUnOp(.ptrtoint, ptr);9525 return block.addUnOp(.ptrtoint, ptr);
...@@ -9513,11 +9529,12 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -9513,11 +9529,12 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
9513 const tracy = trace(@src());9529 const tracy = trace(@src());
9514 defer tracy.end();9530 defer tracy.end();
95159531
9532 const mod = sema.mod;
9516 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;9533 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
9517 const src = inst_data.src();9534 const src = inst_data.src();
9518 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };9535 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
9519 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;9536 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));
9521 const object = try sema.resolveInst(extra.lhs);9538 const object = try sema.resolveInst(extra.lhs);
9522 return sema.fieldVal(block, src, object, field_name, field_name_src);9539 return sema.fieldVal(block, src, object, field_name, field_name_src);
9523}9540}
...@@ -9526,11 +9543,12 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index, initializing: b...@@ -9526,11 +9543,12 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index, initializing: b
9526 const tracy = trace(@src());9543 const tracy = trace(@src());
9527 defer tracy.end();9544 defer tracy.end();
95289545
9546 const mod = sema.mod;
9529 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;9547 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
9530 const src = inst_data.src();9548 const src = inst_data.src();
9531 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };9549 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
9532 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;9550 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));
9534 const object_ptr = try sema.resolveInst(extra.lhs);9552 const object_ptr = try sema.resolveInst(extra.lhs);
9535 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, initializing);9553 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, initializing);
9536}9554}
...@@ -9544,7 +9562,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -9544,7 +9562,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
9544 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };9562 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
9545 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;9563 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
9546 const object = try sema.resolveInst(extra.lhs);9564 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");
9548 return sema.fieldVal(block, src, object, field_name, field_name_src);9566 return sema.fieldVal(block, src, object, field_name, field_name_src);
9549}9567}
95509568
...@@ -9557,7 +9575,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -9557,7 +9575,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
9557 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };9575 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
9558 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;9576 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
9559 const object_ptr = try sema.resolveInst(extra.lhs);9577 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");
9561 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false);9579 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false);
9562}9580}
95639581
...@@ -9586,31 +9604,31 @@ fn intCast(...@@ -9586,31 +9604,31 @@ fn intCast(
9586 operand_src: LazySrcLoc,9604 operand_src: LazySrcLoc,
9587 runtime_safety: bool,9605 runtime_safety: bool,
9588) CompileError!Air.Inst.Ref {9606) CompileError!Air.Inst.Ref {
9607 const mod = sema.mod;
9589 const operand_ty = sema.typeOf(operand);9608 const operand_ty = sema.typeOf(operand);
9590 const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, dest_ty_src);9609 const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, dest_ty_src);
9591 const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src);9610 const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src);
95929611
9593 if (try sema.isComptimeKnown(operand)) {9612 if (try sema.isComptimeKnown(operand)) {
9594 return sema.coerce(block, dest_ty, operand, operand_src);9613 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) {
9596 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{});9615 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{});
9597 }9616 }
95989617
9599 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src);9618 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
9602 if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| {9621 if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| {
9603 // requirement: intCast(u0, input) iff input == 09622 // requirement: intCast(u0, input) iff input == 0
9604 if (runtime_safety and block.wantSafety()) {9623 if (runtime_safety and block.wantSafety()) {
9605 try sema.requireRuntimeBlock(block, src, operand_src);9624 try sema.requireRuntimeBlock(block, src, operand_src);
9606 const target = sema.mod.getTarget();9625 const wanted_info = dest_scalar_ty.intInfo(mod);
9607 const wanted_info = dest_scalar_ty.intInfo(target);
9608 const wanted_bits = wanted_info.bits;9626 const wanted_bits = wanted_info.bits;
96099627
9610 if (wanted_bits == 0) {9628 if (wanted_bits == 0) {
9611 const ok = if (is_vector) ok: {9629 const ok = if (is_vector) ok: {
9612 const zeros = try Value.Tag.repeated.create(sema.arena, Value.zero);9630 const zeros = try sema.splat(operand_ty, try mod.intValue(operand_scalar_ty, 0));
9613 const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);9631 const zero_inst = try sema.addConstant(operand_ty, zeros);
9614 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);9632 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
9615 const all_in_range = try block.addInst(.{9633 const all_in_range = try block.addInst(.{
9616 .tag = .reduce,9634 .tag = .reduce,
...@@ -9618,7 +9636,7 @@ fn intCast(...@@ -9618,7 +9636,7 @@ fn intCast(
9618 });9636 });
9619 break :ok all_in_range;9637 break :ok all_in_range;
9620 } else ok: {9638 } 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));
9622 const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);9640 const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
9623 break :ok is_in_range;9641 break :ok is_in_range;
9624 };9642 };
...@@ -9631,9 +9649,8 @@ fn intCast(...@@ -9631,9 +9649,8 @@ fn intCast(
96319649
9632 try sema.requireRuntimeBlock(block, src, operand_src);9650 try sema.requireRuntimeBlock(block, src, operand_src);
9633 if (runtime_safety and block.wantSafety()) {9651 if (runtime_safety and block.wantSafety()) {
9634 const target = sema.mod.getTarget();9652 const actual_info = operand_scalar_ty.intInfo(mod);
9635 const actual_info = operand_scalar_ty.intInfo(target);9653 const wanted_info = dest_scalar_ty.intInfo(mod);
9636 const wanted_info = dest_scalar_ty.intInfo(target);
9637 const actual_bits = actual_info.bits;9654 const actual_bits = actual_info.bits;
9638 const wanted_bits = wanted_info.bits;9655 const wanted_bits = wanted_info.bits;
9639 const actual_value_bits = actual_bits - @boolToInt(actual_info.signedness == .signed);9656 const actual_value_bits = actual_bits - @boolToInt(actual_info.signedness == .signed);
...@@ -9642,26 +9659,24 @@ fn intCast(...@@ -9642,26 +9659,24 @@ fn intCast(
9642 // range shrinkage9659 // range shrinkage
9643 // requirement: int value fits into target type9660 // requirement: int value fits into target type
9644 if (wanted_value_bits < actual_value_bits) {9661 if (wanted_value_bits < actual_value_bits) {
9645 const dest_max_val_scalar = try dest_scalar_ty.maxInt(sema.arena, target);9662 const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_scalar_ty);
9646 const dest_max_val = if (is_vector)9663 const dest_max_val = try sema.splat(operand_ty, dest_max_val_scalar);
9647 try Value.Tag.repeated.create(sema.arena, dest_max_val_scalar)
9648 else
9649 dest_max_val_scalar;
9650 const dest_max = try sema.addConstant(operand_ty, dest_max_val);9664 const dest_max = try sema.addConstant(operand_ty, dest_max_val);
9651 const diff = try block.addBinOp(.subwrap, dest_max, operand);9665 const diff = try block.addBinOp(.subwrap, dest_max, operand);
96529666
9653 if (actual_info.signedness == .signed) {9667 if (actual_info.signedness == .signed) {
9654 // Reinterpret the sign-bit as part of the value. This will make9668 // Reinterpret the sign-bit as part of the value. This will make
9655 // negative differences (`operand` > `dest_max`) appear too big.9669 // 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);
9657 const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff);9671 const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff);
96589672
9659 // If the destination type is signed, then we need to double its9673 // If the destination type is signed, then we need to double its
9660 // range to account for negative values.9674 // range to account for negative values.
9661 const dest_range_val = if (wanted_info.signedness == .signed) range_val: {9675 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);9676 const one = try mod.intValue(unsigned_operand_ty, 1);
9663 break :range_val try sema.intAdd(range_minus_one, Value.one, unsigned_operand_ty);9677 const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, mod);
9664 } else dest_max_val;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);
9665 const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);9680 const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);
96669681
9667 const ok = if (is_vector) ok: {9682 const ok = if (is_vector) ok: {
...@@ -9701,7 +9716,8 @@ fn intCast(...@@ -9701,7 +9716,8 @@ fn intCast(
9701 // no shrinkage, yes sign loss9716 // no shrinkage, yes sign loss
9702 // requirement: signed to unsigned >= 09717 // requirement: signed to unsigned >= 0
9703 const ok = if (is_vector) ok: {9718 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);
9705 const zero_inst = try sema.addConstant(operand_ty, zero_val);9721 const zero_inst = try sema.addConstant(operand_ty, zero_val);
9706 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);9722 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
9707 const all_in_range = try block.addInst(.{9723 const all_in_range = try block.addInst(.{
...@@ -9713,7 +9729,7 @@ fn intCast(...@@ -9713,7 +9729,7 @@ fn intCast(
9713 });9729 });
9714 break :ok all_in_range;9730 break :ok all_in_range;
9715 } else ok: {9731 } 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));
9717 const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst);9733 const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst);
9718 break :ok is_in_range;9734 break :ok is_in_range;
9719 };9735 };
...@@ -9727,6 +9743,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9727,6 +9743,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9727 const tracy = trace(@src());9743 const tracy = trace(@src());
9728 defer tracy.end();9744 defer tracy.end();
97299745
9746 const mod = sema.mod;
9730 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;9747 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
9731 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };9748 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9732 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };9749 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...@@ -9735,7 +9752,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9735 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);9752 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
9736 const operand = try sema.resolveInst(extra.rhs);9753 const operand = try sema.resolveInst(extra.rhs);
9737 const operand_ty = sema.typeOf(operand);9754 const operand_ty = sema.typeOf(operand);
9738 switch (dest_ty.zigTypeTag()) {9755 switch (dest_ty.zigTypeTag(mod)) {
9739 .AnyFrame,9756 .AnyFrame,
9740 .ComptimeFloat,9757 .ComptimeFloat,
9741 .ComptimeInt,9758 .ComptimeInt,
...@@ -9751,14 +9768,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9751,14 +9768,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9751 .Type,9768 .Type,
9752 .Undefined,9769 .Undefined,
9753 .Void,9770 .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
9756 .Enum => {9773 .Enum => {
9757 const msg = msg: {9774 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)});
9759 errdefer msg.destroy(sema.gpa);9776 errdefer msg.destroy(sema.gpa);
9760 switch (operand_ty.zigTypeTag()) {9777 switch (operand_ty.zigTypeTag(mod)) {
9761 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(sema.mod)}),9778 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(mod)}),
9762 else => {},9779 else => {},
9763 }9780 }
97649781
...@@ -9769,11 +9786,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9769,11 +9786,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97699786
9770 .Pointer => {9787 .Pointer => {
9771 const msg = msg: {9788 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)});
9773 errdefer msg.destroy(sema.gpa);9790 errdefer msg.destroy(sema.gpa);
9774 switch (operand_ty.zigTypeTag()) {9791 switch (operand_ty.zigTypeTag(mod)) {
9775 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(sema.mod)}),9792 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(mod)}),
9776 .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(sema.mod)}),9793 .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(mod)}),
9777 else => {},9794 else => {},
9778 }9795 }
97799796
...@@ -9781,14 +9798,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9781,14 +9798,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9781 };9798 };
9782 return sema.failWithOwnedErrorMsg(msg);9799 return sema.failWithOwnedErrorMsg(msg);
9783 },9800 },
9784 .Struct, .Union => if (dest_ty.containerLayout() == .Auto) {9801 .Struct, .Union => if (dest_ty.containerLayout(mod) == .Auto) {
9785 const container = switch (dest_ty.zigTypeTag()) {9802 const container = switch (dest_ty.zigTypeTag(mod)) {
9786 .Struct => "struct",9803 .Struct => "struct",
9787 .Union => "union",9804 .Union => "union",
9788 else => unreachable,9805 else => unreachable,
9789 };9806 };
9790 return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}'; {s} does not have a guaranteed in-memory layout", .{9807 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,
9792 });9809 });
9793 },9810 },
97949811
...@@ -9799,7 +9816,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9799,7 +9816,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9799 .Vector,9816 .Vector,
9800 => {},9817 => {},
9801 }9818 }
9802 switch (operand_ty.zigTypeTag()) {9819 switch (operand_ty.zigTypeTag(mod)) {
9803 .AnyFrame,9820 .AnyFrame,
9804 .ComptimeFloat,9821 .ComptimeFloat,
9805 .ComptimeInt,9822 .ComptimeInt,
...@@ -9815,14 +9832,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9815,14 +9832,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9815 .Type,9832 .Type,
9816 .Undefined,9833 .Undefined,
9817 .Void,9834 .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
9820 .Enum => {9837 .Enum => {
9821 const msg = msg: {9838 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)});
9823 errdefer msg.destroy(sema.gpa);9840 errdefer msg.destroy(sema.gpa);
9824 switch (dest_ty.zigTypeTag()) {9841 switch (dest_ty.zigTypeTag(mod)) {
9825 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}),9842 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(mod)}),
9826 else => {},9843 else => {},
9827 }9844 }
98289845
...@@ -9832,11 +9849,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9832,11 +9849,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9832 },9849 },
9833 .Pointer => {9850 .Pointer => {
9834 const msg = msg: {9851 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)});
9836 errdefer msg.destroy(sema.gpa);9853 errdefer msg.destroy(sema.gpa);
9837 switch (dest_ty.zigTypeTag()) {9854 switch (dest_ty.zigTypeTag(mod)) {
9838 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}),9855 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(mod)}),
9839 .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(sema.mod)}),9856 .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(mod)}),
9840 else => {},9857 else => {},
9841 }9858 }
98429859
...@@ -9844,14 +9861,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9844,14 +9861,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9844 };9861 };
9845 return sema.failWithOwnedErrorMsg(msg);9862 return sema.failWithOwnedErrorMsg(msg);
9846 },9863 },
9847 .Struct, .Union => if (operand_ty.containerLayout() == .Auto) {9864 .Struct, .Union => if (operand_ty.containerLayout(mod) == .Auto) {
9848 const container = switch (operand_ty.zigTypeTag()) {9865 const container = switch (operand_ty.zigTypeTag(mod)) {
9849 .Struct => "struct",9866 .Struct => "struct",
9850 .Union => "union",9867 .Union => "union",
9851 else => unreachable,9868 else => unreachable,
9852 };9869 };
9853 return sema.fail(block, operand_src, "cannot @bitCast from '{}'; {s} does not have a guaranteed in-memory layout", .{9870 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,
9855 });9872 });
9856 },9873 },
98579874
...@@ -9869,6 +9886,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -9869,6 +9886,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
9869 const tracy = trace(@src());9886 const tracy = trace(@src());
9870 defer tracy.end();9887 defer tracy.end();
98719888
9889 const mod = sema.mod;
9872 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;9890 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
9873 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };9891 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9874 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };9892 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...@@ -9877,31 +9895,31 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
9877 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);9895 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
9878 const operand = try sema.resolveInst(extra.rhs);9896 const operand = try sema.resolveInst(extra.rhs);
98799897
9880 const target = sema.mod.getTarget();9898 const target = mod.getTarget();
9881 const dest_is_comptime_float = switch (dest_ty.zigTypeTag()) {9899 const dest_is_comptime_float = switch (dest_ty.zigTypeTag(mod)) {
9882 .ComptimeFloat => true,9900 .ComptimeFloat => true,
9883 .Float => false,9901 .Float => false,
9884 else => return sema.fail(9902 else => return sema.fail(
9885 block,9903 block,
9886 dest_ty_src,9904 dest_ty_src,
9887 "expected float type, found '{}'",9905 "expected float type, found '{}'",
9888 .{dest_ty.fmt(sema.mod)},9906 .{dest_ty.fmt(mod)},
9889 ),9907 ),
9890 };9908 };
98919909
9892 const operand_ty = sema.typeOf(operand);9910 const operand_ty = sema.typeOf(operand);
9893 switch (operand_ty.zigTypeTag()) {9911 switch (operand_ty.zigTypeTag(mod)) {
9894 .ComptimeFloat, .Float, .ComptimeInt => {},9912 .ComptimeFloat, .Float, .ComptimeInt => {},
9895 else => return sema.fail(9913 else => return sema.fail(
9896 block,9914 block,
9897 operand_src,9915 operand_src,
9898 "expected float type, found '{}'",9916 "expected float type, found '{}'",
9899 .{operand_ty.fmt(sema.mod)},9917 .{operand_ty.fmt(mod)},
9900 ),9918 ),
9901 }9919 }
99029920
9903 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {9921 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));
9905 }9923 }
9906 if (dest_is_comptime_float) {9924 if (dest_is_comptime_float) {
9907 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_float'", .{});9925 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...@@ -9944,20 +9962,21 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9944 const tracy = trace(@src());9962 const tracy = trace(@src());
9945 defer tracy.end();9963 defer tracy.end();
99469964
9965 const mod = sema.mod;
9947 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;9966 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
9948 const src = inst_data.src();9967 const src = inst_data.src();
9949 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;9968 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
9950 const array_ptr = try sema.resolveInst(extra.lhs);9969 const array_ptr = try sema.resolveInst(extra.lhs);
9951 const elem_index = try sema.resolveInst(extra.rhs);9970 const elem_index = try sema.resolveInst(extra.rhs);
9952 const indexable_ty = sema.typeOf(array_ptr);9971 const indexable_ty = sema.typeOf(array_ptr);
9953 if (indexable_ty.zigTypeTag() != .Pointer) {9972 if (indexable_ty.zigTypeTag(mod) != .Pointer) {
9954 const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node };9973 const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node };
9955 const msg = msg: {9974 const msg = msg: {
9956 const msg = try sema.errMsg(block, capture_src, "pointer capture of non pointer type '{}'", .{9975 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),
9958 });9977 });
9959 errdefer msg.destroy(sema.gpa);9978 errdefer msg.destroy(sema.gpa);
9960 if (indexable_ty.zigTypeTag() == .Array) {9979 if (indexable_ty.zigTypeTag(mod) == .Array) {
9961 try sema.errNote(block, src, msg, "consider using '&' here", .{});9980 try sema.errNote(block, src, msg, "consider using '&' here", .{});
9962 }9981 }
9963 break :msg msg;9982 break :msg msg;
...@@ -10054,7 +10073,7 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10054,7 +10073,7 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10054 const array_ptr = try sema.resolveInst(extra.lhs);10073 const array_ptr = try sema.resolveInst(extra.lhs);
10055 const start = try sema.resolveInst(extra.start);10074 const start = try sema.resolveInst(extra.start);
10056 const len = try sema.resolveInst(extra.len);10075 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);
10058 const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node };10077 const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node };
10059 const start_src: LazySrcLoc = .{ .node_offset_slice_start = extra.start_src_node_offset };10078 const start_src: LazySrcLoc = .{ .node_offset_slice_start = extra.start_src_node_offset };
10060 const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };10079 const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
...@@ -10076,6 +10095,8 @@ fn zirSwitchCapture(...@@ -10076,6 +10095,8 @@ fn zirSwitchCapture(
10076 const tracy = trace(@src());10095 const tracy = trace(@src());
10077 defer tracy.end();10096 defer tracy.end();
1007810097
10098 const mod = sema.mod;
10099 const gpa = sema.gpa;
10079 const zir_datas = sema.code.instructions.items(.data);10100 const zir_datas = sema.code.instructions.items(.data);
10080 const capture_info = zir_datas[inst].switch_capture;10101 const capture_info = zir_datas[inst].switch_capture;
10081 const switch_info = zir_datas[capture_info.switch_inst].pl_node;10102 const switch_info = zir_datas[capture_info.switch_inst].pl_node;
...@@ -10087,47 +10108,49 @@ fn zirSwitchCapture(...@@ -10087,47 +10108,49 @@ fn zirSwitchCapture(
10087 const operand_is_ref = cond_tag == .switch_cond_ref;10108 const operand_is_ref = cond_tag == .switch_cond_ref;
10088 const operand_ptr = try sema.resolveInst(cond_info.operand);10109 const operand_ptr = try sema.resolveInst(cond_info.operand);
10089 const operand_ptr_ty = sema.typeOf(operand_ptr);10110 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
10092 if (block.inline_case_capture != .none) {10113 if (block.inline_case_capture != .none) {
10093 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable;10114 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable;
10094 if (operand_ty.zigTypeTag() == .Union) {10115 const resolved_item_val = try sema.resolveLazyValue(item_val);
10095 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, sema.mod).?);10116 if (operand_ty.zigTypeTag(mod) == .Union) {
10096 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;10117 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(resolved_item_val, mod).?);
10118 const union_obj = mod.typeToUnion(operand_ty).?;
10097 const field_ty = union_obj.fields.values()[field_index].ty;10119 const field_ty = union_obj.fields.values()[field_index].ty;
10098 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_val| {10120 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_val| {
10099 if (is_ref) {10121 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, .{
10101 .pointee_type = field_ty,10123 .pointee_type = field_ty,
10102 .mutable = operand_ptr_ty.ptrIsMutable(),10124 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10103 .@"volatile" = operand_ptr_ty.isVolatilePtr(),10125 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10104 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(),10126 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
10105 });10127 });
10106 return sema.addConstant(10128 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
10107 ptr_field_ty,10129 .ty = ptr_field_ty.toIntern(),
10108 try Value.Tag.field_ptr.create(sema.arena, .{10130 .addr = .{ .field = .{
10109 .container_ptr = union_val,10131 .base = union_val.toIntern(),
10110 .container_ty = operand_ty,10132 .index = field_index,
10111 .field_index = field_index,10133 } },
10112 }),10134 } })).toValue());
10113 );
10114 }10135 }
10115 const tag_and_val = union_val.castTag(.@"union").?.data;10136 return sema.addConstant(
10116 return sema.addConstant(field_ty, tag_and_val.val);10137 field_ty,
10138 mod.intern_pool.indexToKey(union_val.toIntern()).un.val.toValue(),
10139 );
10117 }10140 }
10118 if (is_ref) {10141 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, .{
10120 .pointee_type = field_ty,10143 .pointee_type = field_ty,
10121 .mutable = operand_ptr_ty.ptrIsMutable(),10144 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10122 .@"volatile" = operand_ptr_ty.isVolatilePtr(),10145 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10123 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(),10146 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
10124 });10147 });
10125 return block.addStructFieldPtr(operand_ptr, field_index, ptr_field_ty);10148 return block.addStructFieldPtr(operand_ptr, field_index, ptr_field_ty);
10126 } else {10149 } else {
10127 return block.addStructFieldVal(operand_ptr, field_index, field_ty);10150 return block.addStructFieldVal(operand_ptr, field_index, field_ty);
10128 }10151 }
10129 } else if (is_ref) {10152 } 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);
10131 } else {10154 } else {
10132 return block.inline_case_capture;10155 return block.inline_case_capture;
10133 }10156 }
...@@ -10144,7 +10167,7 @@ fn zirSwitchCapture(...@@ -10144,7 +10167,7 @@ fn zirSwitchCapture(
10144 return operand_ptr;10167 return operand_ptr;
10145 }10168 }
1014610169
10147 switch (operand_ty.zigTypeTag()) {10170 switch (operand_ty.zigTypeTag(mod)) {
10148 .ErrorSet => if (block.switch_else_err_ty) |some| {10171 .ErrorSet => if (block.switch_else_err_ty) |some| {
10149 return sema.bitCast(block, some, operand, operand_src, null);10172 return sema.bitCast(block, some, operand, operand_src, null);
10150 } else {10173 } else {
...@@ -10162,14 +10185,14 @@ fn zirSwitchCapture(...@@ -10162,14 +10185,14 @@ fn zirSwitchCapture(
10162 switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item,10185 switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item,
10163 };10186 };
1016410187
10165 switch (operand_ty.zigTypeTag()) {10188 switch (operand_ty.zigTypeTag(mod)) {
10166 .Union => {10189 .Union => {
10167 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;10190 const union_obj = mod.typeToUnion(operand_ty).?;
10168 const first_item = try sema.resolveInst(items[0]);10191 const first_item = try sema.resolveInst(items[0]);
10169 // Previous switch validation ensured this will succeed10192 // Previous switch validation ensured this will succeed
10170 const first_item_val = sema.resolveConstValue(block, .unneeded, first_item, "") catch unreachable;10193 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).?);
10173 const first_field = union_obj.fields.values()[first_field_index];10196 const first_field = union_obj.fields.values()[first_field_index];
1017410197
10175 for (items[1..], 0..) |item, i| {10198 for (items[1..], 0..) |item, i| {
...@@ -10177,22 +10200,22 @@ fn zirSwitchCapture(...@@ -10177,22 +10200,22 @@ fn zirSwitchCapture(
10177 // Previous switch validation ensured this will succeed10200 // Previous switch validation ensured this will succeed
10178 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;10201 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).?;
10181 const field = union_obj.fields.values()[field_index];10204 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)) {
10183 const msg = msg: {10206 const msg = msg: {
10184 const raw_capture_src = Module.SwitchProngSrc{ .multi_capture = capture_info.prong_index };10207 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
10187 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});10210 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
10190 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 0 } };10213 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);
10192 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 1 + @intCast(u32, i) } };10215 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);10216 const item_src = raw_item_src.resolve(mod, 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)});10217 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(mod)});
10195 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(sema.mod)});10218 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});
10196 break :msg msg;10219 break :msg msg;
10197 };10220 };
10198 return sema.failWithOwnedErrorMsg(msg);10221 return sema.failWithOwnedErrorMsg(msg);
...@@ -10200,21 +10223,20 @@ fn zirSwitchCapture(...@@ -10200,21 +10223,20 @@ fn zirSwitchCapture(
10200 }10223 }
1020110224
10202 if (is_ref) {10225 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, .{
10204 .pointee_type = first_field.ty,10227 .pointee_type = first_field.ty,
10205 .@"addrspace" = .generic,10228 .@"addrspace" = .generic,
10206 .mutable = operand_ptr_ty.ptrIsMutable(),10229 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10207 });10230 });
1020810231
10209 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {10232 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {
10210 return sema.addConstant(10233 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
10211 field_ty_ptr,10234 .ty = field_ty_ptr.toIntern(),
10212 try Value.Tag.field_ptr.create(sema.arena, .{10235 .addr = .{ .field = .{
10213 .container_ptr = op_ptr_val,10236 .base = op_ptr_val.toIntern(),
10214 .container_ty = operand_ty,10237 .index = first_field_index,
10215 .field_index = first_field_index,10238 } },
10216 }),10239 } })).toValue());
10217 );
10218 }10240 }
10219 try sema.requireRuntimeBlock(block, operand_src, null);10241 try sema.requireRuntimeBlock(block, operand_src, null);
10220 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);10242 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);
...@@ -10223,7 +10245,7 @@ fn zirSwitchCapture(...@@ -10223,7 +10245,7 @@ fn zirSwitchCapture(
10223 if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| {10245 if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| {
10224 return sema.addConstant(10246 return sema.addConstant(
10225 first_field.ty,10247 first_field.ty,
10226 operand_val.castTag(.@"union").?.data.val,10248 mod.intern_pool.indexToKey(operand_val.toIntern()).un.val.toValue(),
10227 );10249 );
10228 }10250 }
10229 try sema.requireRuntimeBlock(block, operand_src, null);10251 try sema.requireRuntimeBlock(block, operand_src, null);
...@@ -10231,28 +10253,23 @@ fn zirSwitchCapture(...@@ -10231,28 +10253,23 @@ fn zirSwitchCapture(
10231 },10253 },
10232 .ErrorSet => {10254 .ErrorSet => {
10233 if (is_multi) {10255 if (is_multi) {
10234 var names: Module.ErrorSet.NameMap = .{};10256 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10235 try names.ensureUnusedCapacity(sema.arena, items.len);10257 try names.ensureUnusedCapacity(sema.arena, items.len);
10236 for (items) |item| {10258 for (items) |item| {
10237 const item_ref = try sema.resolveInst(item);10259 const item_ref = try sema.resolveInst(item);
10238 // Previous switch validation ensured this will succeed10260 // Previous switch validation ensured this will succeed
10239 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;10261 const item_val = sema.resolveConstLazyValue(block, .unneeded, item_ref, "") catch unreachable;
10240 names.putAssumeCapacityNoClobber(10262 names.putAssumeCapacityNoClobber(item_val.getErrorName(mod).unwrap().?, {});
10241 item_val.getError().?,
10242 {},
10243 );
10244 }10263 }
10245 // names must be sorted10264 const else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
10246 Module.ErrorSet.sortNames(&names);
10247 const else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
1024810265
10249 return sema.bitCast(block, else_error_ty, operand, operand_src, null);10266 return sema.bitCast(block, else_error_ty, operand, operand_src, null);
10250 } else {10267 } else {
10251 const item_ref = try sema.resolveInst(items[0]);10268 const item_ref = try sema.resolveInst(items[0]);
10252 // Previous switch validation ensured this will succeed10269 // 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().?);
10256 return sema.bitCast(block, item_ty, operand, operand_src, null);10273 return sema.bitCast(block, item_ty, operand, operand_src, null);
10257 }10274 }
10258 },10275 },
...@@ -10269,6 +10286,7 @@ fn zirSwitchCapture(...@@ -10269,6 +10286,7 @@ fn zirSwitchCapture(
10269}10286}
1027010287
10271fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10288fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10289 const mod = sema.mod;
10272 const zir_datas = sema.code.instructions.items(.data);10290 const zir_datas = sema.code.instructions.items(.data);
10273 const inst_data = zir_datas[inst].un_tok;10291 const inst_data = zir_datas[inst].un_tok;
10274 const src = inst_data.src();10292 const src = inst_data.src();
...@@ -10278,12 +10296,12 @@ fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile...@@ -10278,12 +10296,12 @@ fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile
10278 const cond_data = zir_datas[Zir.refToIndex(inst_data.operand).?].un_node;10296 const cond_data = zir_datas[Zir.refToIndex(inst_data.operand).?].un_node;
10279 const operand_ptr = try sema.resolveInst(cond_data.operand);10297 const operand_ptr = try sema.resolveInst(cond_data.operand);
10280 const operand_ptr_ty = sema.typeOf(operand_ptr);10298 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) {
10284 const msg = msg: {10302 const msg = msg: {
10285 const msg = try sema.errMsg(block, src, "cannot capture tag of non-union type '{}'", .{10303 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),
10287 });10305 });
10288 errdefer msg.destroy(sema.gpa);10306 errdefer msg.destroy(sema.gpa);
10289 try sema.addDeclaredHereNote(msg, operand_ty);10307 try sema.addDeclaredHereNote(msg, operand_ty);
...@@ -10301,6 +10319,7 @@ fn zirSwitchCond(...@@ -10301,6 +10319,7 @@ fn zirSwitchCond(
10301 inst: Zir.Inst.Index,10319 inst: Zir.Inst.Index,
10302 is_ref: bool,10320 is_ref: bool,
10303) CompileError!Air.Inst.Ref {10321) CompileError!Air.Inst.Ref {
10322 const mod = sema.mod;
10304 const inst_data = sema.code.instructions.items(.data)[inst].un_node;10323 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
10305 const src = inst_data.src();10324 const src = inst_data.src();
10306 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node };10325 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node };
...@@ -10311,7 +10330,7 @@ fn zirSwitchCond(...@@ -10311,7 +10330,7 @@ fn zirSwitchCond(
10311 operand_ptr;10330 operand_ptr;
10312 const operand_ty = sema.typeOf(operand);10331 const operand_ty = sema.typeOf(operand);
1031310332
10314 switch (operand_ty.zigTypeTag()) {10333 switch (operand_ty.zigTypeTag(mod)) {
10315 .Type,10334 .Type,
10316 .Void,10335 .Void,
10317 .Bool,10336 .Bool,
...@@ -10325,8 +10344,8 @@ fn zirSwitchCond(...@@ -10325,8 +10344,8 @@ fn zirSwitchCond(
10325 .ErrorSet,10344 .ErrorSet,
10326 .Enum,10345 .Enum,
10327 => {10346 => {
10328 if (operand_ty.isSlice()) {10347 if (operand_ty.isSlice(mod)) {
10329 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(sema.mod)});10348 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(mod)});
10330 }10349 }
10331 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {10350 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {
10332 return sema.addConstant(operand_ty, opv);10351 return sema.addConstant(operand_ty, opv);
...@@ -10336,12 +10355,12 @@ fn zirSwitchCond(...@@ -10336,12 +10355,12 @@ fn zirSwitchCond(
1033610355
10337 .Union => {10356 .Union => {
10338 const union_ty = try sema.resolveTypeFields(operand_ty);10357 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 {
10340 const msg = msg: {10359 const msg = msg: {
10341 const msg = try sema.errMsg(block, src, "switch on union with no attached enum", .{});10360 const msg = try sema.errMsg(block, src, "switch on union with no attached enum", .{});
10342 errdefer msg.destroy(sema.gpa);10361 errdefer msg.destroy(sema.gpa);
10343 if (union_ty.declSrcLocOrNull(sema.mod)) |union_src| {10362 if (union_ty.declSrcLocOrNull(mod)) |union_src| {
10344 try sema.mod.errNoteNonLazy(union_src, msg, "consider 'union(enum)' here", .{});10363 try mod.errNoteNonLazy(union_src, msg, "consider 'union(enum)' here", .{});
10345 }10364 }
10346 break :msg msg;10365 break :msg msg;
10347 };10366 };
...@@ -10361,17 +10380,19 @@ fn zirSwitchCond(...@@ -10361,17 +10380,19 @@ fn zirSwitchCond(
10361 .Vector,10380 .Vector,
10362 .Frame,10381 .Frame,
10363 .AnyFrame,10382 .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)}),
10365 }10384 }
10366}10385}
1036710386
10368const SwitchErrorSet = std.StringHashMap(Module.SwitchProngSrc);10387const SwitchErrorSet = std.AutoHashMap(InternPool.NullTerminatedString, Module.SwitchProngSrc);
1036910388
10370fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10389fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10371 const tracy = trace(@src());10390 const tracy = trace(@src());
10372 defer tracy.end();10391 defer tracy.end();
1037310392
10393 const mod = sema.mod;
10374 const gpa = sema.gpa;10394 const gpa = sema.gpa;
10395 const ip = &mod.intern_pool;
10375 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;10396 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
10376 const src = inst_data.src();10397 const src = inst_data.src();
10377 const src_node_offset = inst_data.src_node;10398 const src_node_offset = inst_data.src_node;
...@@ -10413,14 +10434,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10413,14 +10434,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10413 const cond_index = Zir.refToIndex(extra.data.operand).?;10434 const cond_index = Zir.refToIndex(extra.data.operand).?;
10414 const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;10435 const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;
10415 const target_ty = sema.typeOf(raw_operand);10436 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;
10417 };10438 };
10418 const union_originally = maybe_union_ty.zigTypeTag() == .Union;10439 const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union;
1041910440
10420 // Duplicate checking variables later also used for `inline else`.10441 // Duplicate checking variables later also used for `inline else`.
10421 var seen_enum_fields: []?Module.SwitchProngSrc = &.{};10442 var seen_enum_fields: []?Module.SwitchProngSrc = &.{};
10422 var seen_errors = SwitchErrorSet.init(gpa);10443 var seen_errors = SwitchErrorSet.init(gpa);
10423 var range_set = RangeSet.init(gpa, sema.mod);10444 var range_set = RangeSet.init(gpa, mod);
10424 var true_count: u8 = 0;10445 var true_count: u8 = 0;
10425 var false_count: u8 = 0;10446 var false_count: u8 = 0;
1042610447
...@@ -10433,12 +10454,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10433,12 +10454,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10433 var empty_enum = false;10454 var empty_enum = false;
1043410455
10435 const operand_ty = sema.typeOf(operand);10456 const operand_ty = sema.typeOf(operand);
10436 const err_set = operand_ty.zigTypeTag() == .ErrorSet;10457 const err_set = operand_ty.zigTypeTag(mod) == .ErrorSet;
1043710458
10438 var else_error_ty: ?Type = null;10459 var else_error_ty: ?Type = null;
1043910460
10440 // Validate usage of '_' prongs.10461 // 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)) {
10442 const msg = msg: {10463 const msg = msg: {
10443 const msg = try sema.errMsg(10464 const msg = try sema.errMsg(
10444 block,10465 block,
...@@ -10459,14 +10480,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10459,14 +10480,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10459 return sema.failWithOwnedErrorMsg(msg);10480 return sema.failWithOwnedErrorMsg(msg);
10460 }10481 }
1046110482
10462 const target = sema.mod.getTarget();
10463
10464 // Validate for duplicate items, missing else prong, and invalid range.10483 // Validate for duplicate items, missing else prong, and invalid range.
10465 switch (operand_ty.zigTypeTag()) {10484 switch (operand_ty.zigTypeTag(mod)) {
10466 .Union => unreachable, // handled in zirSwitchCond10485 .Union => unreachable, // handled in zirSwitchCond
10467 .Enum => {10486 .Enum => {
10468 seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount());10487 seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount(mod));
10469 empty_enum = seen_enum_fields.len == 0 and !operand_ty.isNonexhaustiveEnum();10488 empty_enum = seen_enum_fields.len == 0 and !operand_ty.isNonexhaustiveEnum(mod);
10470 @memset(seen_enum_fields, null);10489 @memset(seen_enum_fields, null);
10471 // `range_set` is used for non-exhaustive enum values that do not correspond to any tags.10490 // `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...@@ -10521,7 +10540,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10521 } else true;10540 } else true;
1052210541
10523 if (special_prong == .@"else") {10542 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(
10525 block,10544 block,
10526 special_prong_src,10545 special_prong_src,
10527 "unreachable else prong; all cases already handled",10546 "unreachable else prong; all cases already handled",
...@@ -10539,25 +10558,25 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10539,25 +10558,25 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10539 for (seen_enum_fields, 0..) |seen_src, i| {10558 for (seen_enum_fields, 0..) |seen_src, i| {
10540 if (seen_src != null) continue;10559 if (seen_src != null) continue;
1054110560
10542 const field_name = operand_ty.enumFieldName(i);10561 const field_name = operand_ty.enumFieldName(i, mod);
10543 try sema.addFieldErrNote(10562 try sema.addFieldErrNote(
10544 operand_ty,10563 operand_ty,
10545 i,10564 i,
10546 msg,10565 msg,
10547 "unhandled enumeration value: '{s}'",10566 "unhandled enumeration value: '{}'",
10548 .{field_name},10567 .{field_name.fmt(&mod.intern_pool)},
10549 );10568 );
10550 }10569 }
10551 try sema.mod.errNoteNonLazy(10570 try mod.errNoteNonLazy(
10552 operand_ty.declSrcLoc(sema.mod),10571 operand_ty.declSrcLoc(mod),
10553 msg,10572 msg,
10554 "enum '{}' declared here",10573 "enum '{}' declared here",
10555 .{operand_ty.fmt(sema.mod)},10574 .{operand_ty.fmt(mod)},
10556 );10575 );
10557 break :msg msg;10576 break :msg msg;
10558 };10577 };
10559 return sema.failWithOwnedErrorMsg(msg);10578 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) {
10561 return sema.fail(10580 return sema.fail(
10562 block,10581 block,
10563 src,10582 src,
...@@ -10614,7 +10633,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10614,7 +10633,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1061410633
10615 try sema.resolveInferredErrorSetTy(block, src, operand_ty);10634 try sema.resolveInferredErrorSetTy(block, src, operand_ty);
1061610635
10617 if (operand_ty.isAnyError()) {10636 if (operand_ty.isAnyError(mod)) {
10618 if (special_prong != .@"else") {10637 if (special_prong != .@"else") {
10619 return sema.fail(10638 return sema.fail(
10620 block,10639 block,
...@@ -10628,7 +10647,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10628,7 +10647,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10628 var maybe_msg: ?*Module.ErrorMsg = null;10647 var maybe_msg: ?*Module.ErrorMsg = null;
10629 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);10648 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| {
10632 if (!seen_errors.contains(error_name) and special_prong != .@"else") {10651 if (!seen_errors.contains(error_name) and special_prong != .@"else") {
10633 const msg = maybe_msg orelse blk: {10652 const msg = maybe_msg orelse blk: {
10634 maybe_msg = try sema.errMsg(10653 maybe_msg = try sema.errMsg(
...@@ -10644,8 +10663,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10644,8 +10663,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10644 block,10663 block,
10645 src,10664 src,
10646 msg,10665 msg,
10647 "unhandled error value: 'error.{s}'",10666 "unhandled error value: 'error.{}'",
10648 .{error_name},10667 .{error_name.fmt(ip)},
10649 );10668 );
10650 }10669 }
10651 }10670 }
...@@ -10656,7 +10675,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10656,7 +10675,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10656 return sema.failWithOwnedErrorMsg(msg);10675 return sema.failWithOwnedErrorMsg(msg);
10657 }10676 }
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) {
10660 // In order to enable common patterns for generic code allow simple else bodies10679 // In order to enable common patterns for generic code allow simple else bodies
10661 // else => unreachable,10680 // else => unreachable,
10662 // else => return,10681 // else => return,
...@@ -10693,18 +10712,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10693,18 +10712,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10693 );10712 );
10694 }10713 }
1069510714
10696 const error_names = operand_ty.errorSetNames();10715 const error_names = operand_ty.errorSetNames(mod);
10697 var names: Module.ErrorSet.NameMap = .{};10716 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10698 try names.ensureUnusedCapacity(sema.arena, error_names.len);10717 try names.ensureUnusedCapacity(sema.arena, error_names.len);
10699 for (error_names) |error_name| {10718 for (error_names) |error_name| {
10700 if (seen_errors.contains(error_name)) continue;10719 if (seen_errors.contains(error_name)) continue;
1070110720
10702 names.putAssumeCapacityNoClobber(error_name, {});10721 names.putAssumeCapacityNoClobber(error_name, {});
10703 }10722 }
1070410723 // No need to keep the hash map metadata correct; here we
10705 // names must be sorted10724 // extract the (sorted) keys only.
10706 Module.ErrorSet.sortNames(&names);10725 else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
10707 else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
10708 }10726 }
10709 },10727 },
10710 .Int, .ComptimeInt => {10728 .Int, .ComptimeInt => {
...@@ -10722,7 +10740,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10722,7 +10740,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10722 block,10740 block,
10723 &range_set,10741 &range_set,
10724 item_ref,10742 item_ref,
10725 operand_ty,
10726 src_node_offset,10743 src_node_offset,
10727 .{ .scalar = scalar_i },10744 .{ .scalar = scalar_i },
10728 );10745 );
...@@ -10745,7 +10762,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10745,7 +10762,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10745 block,10762 block,
10746 &range_set,10763 &range_set,
10747 item_ref,10764 item_ref,
10748 operand_ty,
10749 src_node_offset,10765 src_node_offset,
10750 .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },10766 .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
10751 );10767 );
...@@ -10763,7 +10779,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10763,7 +10779,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10763 &range_set,10779 &range_set,
10764 item_first,10780 item_first,
10765 item_last,10781 item_last,
10766 operand_ty,
10767 src_node_offset,10782 src_node_offset,
10768 .{ .range = .{ .prong = multi_i, .item = range_i } },10783 .{ .range = .{ .prong = multi_i, .item = range_i } },
10769 );10784 );
...@@ -10774,13 +10789,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10774,13 +10789,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10774 }10789 }
1077510790
10776 check_range: {10791 check_range: {
10777 if (operand_ty.zigTypeTag() == .Int) {10792 if (operand_ty.zigTypeTag(mod) == .Int) {
10778 var arena = std.heap.ArenaAllocator.init(gpa);10793 const min_int = try operand_ty.minInt(mod, operand_ty);
10779 defer arena.deinit();10794 const max_int = try operand_ty.maxInt(mod, operand_ty);
1078010795 if (try range_set.spans(min_int.toIntern(), max_int.toIntern())) {
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)) {
10784 if (special_prong == .@"else") {10796 if (special_prong == .@"else") {
10785 return sema.fail(10797 return sema.fail(
10786 block,10798 block,
...@@ -10878,15 +10890,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10878,15 +10890,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10878 block,10890 block,
10879 src,10891 src,
10880 "else prong required when switching on type '{}'",10892 "else prong required when switching on type '{}'",
10881 .{operand_ty.fmt(sema.mod)},10893 .{operand_ty.fmt(mod)},
10882 );10894 );
10883 }10895 }
1088410896
10885 var seen_values = ValueSrcMap.initContext(gpa, .{10897 var seen_values = ValueSrcMap{};
10886 .ty = operand_ty,10898 defer seen_values.deinit(gpa);
10887 .mod = sema.mod,
10888 });
10889 defer seen_values.deinit();
1089010899
10891 var extra_index: usize = special.end;10900 var extra_index: usize = special.end;
10892 {10901 {
...@@ -10948,7 +10957,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10948,7 +10957,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10948 .ComptimeFloat,10957 .ComptimeFloat,
10949 .Float,10958 .Float,
10950 => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{10959 => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{
10951 operand_ty.fmt(sema.mod),10960 operand_ty.fmt(mod),
10952 }),10961 }),
10953 }10962 }
1095410963
...@@ -10991,6 +11000,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10991,6 +11000,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10991 defer merges.deinit(gpa);11000 defer merges.deinit(gpa);
1099211001
10993 if (try sema.resolveDefinedValue(&child_block, src, operand)) |operand_val| {11002 if (try sema.resolveDefinedValue(&child_block, src, operand)) |operand_val| {
11003 const resolved_operand_val = try sema.resolveLazyValue(operand_val);
10994 var extra_index: usize = special.end;11004 var extra_index: usize = special.end;
10995 {11005 {
10996 var scalar_i: usize = 0;11006 var scalar_i: usize = 0;
...@@ -11005,8 +11015,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11005,8 +11015,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1100511015
11006 const item = try sema.resolveInst(item_ref);11016 const item = try sema.resolveInst(item_ref);
11007 // Validation above ensured these will succeed.11017 // Validation above ensured these will succeed.
11008 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;11018 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;
11009 if (operand_val.eql(item_val, operand_ty, sema.mod)) {11019 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {
11010 if (is_inline) child_block.inline_case_capture = operand;11020 if (is_inline) child_block.inline_case_capture = operand;
1101111021
11012 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11022 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...@@ -11031,8 +11041,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11031 for (items) |item_ref| {11041 for (items) |item_ref| {
11032 const item = try sema.resolveInst(item_ref);11042 const item = try sema.resolveInst(item_ref);
11033 // Validation above ensured these will succeed.11043 // Validation above ensured these will succeed.
11034 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;11044 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;
11035 if (operand_val.eql(item_val, operand_ty, sema.mod)) {11045 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {
11036 if (is_inline) child_block.inline_case_capture = operand;11046 if (is_inline) child_block.inline_case_capture = operand;
1103711047
11038 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11048 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...@@ -11050,8 +11060,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11050 // Validation above ensured these will succeed.11060 // Validation above ensured these will succeed.
11051 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;11061 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;
11052 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable;11062 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)) and11063 if ((try sema.compareAll(resolved_operand_val, .gte, first_tv.val, operand_ty)) and
11054 (try sema.compareAll(operand_val, .lte, last_tv.val, operand_ty)))11064 (try sema.compareAll(resolved_operand_val, .lte, last_tv.val, operand_ty)))
11055 {11065 {
11056 if (is_inline) child_block.inline_case_capture = operand;11066 if (is_inline) child_block.inline_case_capture = operand;
11057 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11067 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...@@ -11080,8 +11090,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11080 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {11090 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {
11081 return Air.Inst.Ref.unreachable_value;11091 return Air.Inst.Ref.unreachable_value;
11082 }11092 }
11083 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and11093 if (mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag(mod) == .Enum and
11084 (!operand_ty.isNonexhaustiveEnum() or union_originally))11094 (!operand_ty.isNonexhaustiveEnum(mod) or union_originally))
11085 {11095 {
11086 try sema.zirDbgStmt(block, cond_dbg_node_index);11096 try sema.zirDbgStmt(block, cond_dbg_node_index);
11087 const ok = try block.addUnOp(.is_named_enum_value, operand);11097 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...@@ -11121,7 +11131,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11121 const body = sema.code.extra[extra_index..][0..body_len];11131 const body = sema.code.extra[extra_index..][0..body_len];
11122 extra_index += body_len;11132 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);
11125 defer wip_captures.deinit();11135 defer wip_captures.deinit();
1112611136
11127 case_block.instructions.shrinkRetainingCapacity(0);11137 case_block.instructions.shrinkRetainingCapacity(0);
...@@ -11133,9 +11143,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11133,9 +11143,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11133 // `item` is already guaranteed to be constant known.11143 // `item` is already guaranteed to be constant known.
1113411144
11135 const analyze_body = if (union_originally) blk: {11145 const analyze_body = if (union_originally) blk: {
11136 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;11146 const item_val = sema.resolveConstLazyValue(block, .unneeded, item, "") catch unreachable;
11137 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);11147 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11138 break :blk field_ty.zigTypeTag() != .NoReturn;11148 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
11139 } else true;11149 } else true;
1114011150
11141 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {11151 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...@@ -11197,9 +11207,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11197 const item_last_ref = try sema.resolveInst(last_ref);11207 const item_last_ref = try sema.resolveInst(last_ref);
11198 const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable;11208 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)) : ({
11201 // Previous validation has resolved any possible lazy values.11211 // 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 };
11203 }) {11216 }) {
11204 cases_len += 1;11217 cases_len += 1;
1120511218
...@@ -11212,8 +11225,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11212,8 +11225,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11212 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {11225 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {
11213 error.NeededSourceLocation => {11226 error.NeededSourceLocation => {
11214 const case_src = Module.SwitchProngSrc{ .range = .{ .prong = multi_i, .item = range_i } };11227 const case_src = Module.SwitchProngSrc{ .range = .{ .prong = multi_i, .item = range_i } };
11215 const decl = sema.mod.declPtr(case_block.src_decl);11228 const decl = mod.declPtr(case_block.src_decl);
11216 try sema.emitBackwardBranch(block, case_src.resolve(sema.gpa, decl, src_node_offset, .none));11229 try sema.emitBackwardBranch(block, case_src.resolve(mod, decl, src_node_offset, .none));
11217 unreachable;11230 unreachable;
11218 },11231 },
11219 else => return err,11232 else => return err,
...@@ -11241,15 +11254,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11241,15 +11254,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1124111254
11242 const analyze_body = if (union_originally) blk: {11255 const analyze_body = if (union_originally) blk: {
11243 const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable;11256 const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable;
11244 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);11257 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11245 break :blk field_ty.zigTypeTag() != .NoReturn;11258 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
11246 } else true;11259 } else true;
1124711260
11248 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {11261 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {
11249 error.NeededSourceLocation => {11262 error.NeededSourceLocation => {
11250 const case_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } };11263 const case_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } };
11251 const decl = sema.mod.declPtr(case_block.src_decl);11264 const decl = mod.declPtr(case_block.src_decl);
11252 try sema.emitBackwardBranch(block, case_src.resolve(sema.gpa, decl, src_node_offset, .none));11265 try sema.emitBackwardBranch(block, case_src.resolve(mod, decl, src_node_offset, .none));
11253 unreachable;11266 unreachable;
11254 },11267 },
11255 else => return err,11268 else => return err,
...@@ -11285,8 +11298,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11285,8 +11298,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11285 for (items) |item_ref| {11298 for (items) |item_ref| {
11286 const item = try sema.resolveInst(item_ref);11299 const item = try sema.resolveInst(item_ref);
11287 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;11300 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
11288 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);11301 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11289 if (field_ty.zigTypeTag() != .NoReturn) break true;11302 if (field_ty.zigTypeTag(mod) != .NoReturn) break true;
11290 } else false11303 } else false
11291 else11304 else
11292 true;11305 true;
...@@ -11366,7 +11379,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11366,7 +11379,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11366 var cond_body = try case_block.instructions.toOwnedSlice(gpa);11379 var cond_body = try case_block.instructions.toOwnedSlice(gpa);
11367 defer gpa.free(cond_body);11380 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);
11370 defer wip_captures.deinit();11383 defer wip_captures.deinit();
1137111384
11372 case_block.instructions.shrinkRetainingCapacity(0);11385 case_block.instructions.shrinkRetainingCapacity(0);
...@@ -11409,18 +11422,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11409,18 +11422,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11409 var final_else_body: []const Air.Inst.Index = &.{};11422 var final_else_body: []const Air.Inst.Index = &.{};
11410 if (special.body.len != 0 or !is_first or case_block.wantSafety()) {11423 if (special.body.len != 0 or !is_first or case_block.wantSafety()) {
11411 var emit_bb = false;11424 var emit_bb = false;
11412 if (special.is_inline) switch (operand_ty.zigTypeTag()) {11425 if (special.is_inline) switch (operand_ty.zigTypeTag(mod)) {
11413 .Enum => {11426 .Enum => {
11414 if (operand_ty.isNonexhaustiveEnum() and !union_originally) {11427 if (operand_ty.isNonexhaustiveEnum(mod) and !union_originally) {
11415 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{11428 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),
11417 });11430 });
11418 }11431 }
11419 for (seen_enum_fields, 0..) |f, i| {11432 for (seen_enum_fields, 0..) |f, i| {
11420 if (f != null) continue;11433 if (f != null) continue;
11421 cases_len += 1;11434 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));
11424 const item_ref = try sema.addConstant(operand_ty, item_val);11437 const item_ref = try sema.addConstant(operand_ty, item_val);
11425 case_block.inline_case_capture = item_ref;11438 case_block.inline_case_capture = item_ref;
1142611439
...@@ -11428,8 +11441,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11428,8 +11441,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11428 case_block.wip_capture_scope = child_block.wip_capture_scope;11441 case_block.wip_capture_scope = child_block.wip_capture_scope;
1142911442
11430 const analyze_body = if (union_originally) blk: {11443 const analyze_body = if (union_originally) blk: {
11431 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);11444 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11432 break :blk field_ty.zigTypeTag() != .NoReturn;11445 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
11433 } else true;11446 } else true;
1143411447
11435 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11448 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...@@ -11449,17 +11462,21 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11449 }11462 }
11450 },11463 },
11451 .ErrorSet => {11464 .ErrorSet => {
11452 if (operand_ty.isAnyError()) {11465 if (operand_ty.isAnyError(mod)) {
11453 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{11466 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),
11455 });11468 });
11456 }11469 }
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];
11458 if (seen_errors.contains(error_name)) continue;11472 if (seen_errors.contains(error_name)) continue;
11459 cases_len += 1;11473 cases_len += 1;
1146011474
11461 const item_val = try Value.Tag.@"error".create(sema.arena, .{ .name = error_name });11475 const item_val = try mod.intern(.{ .err = .{
11462 const item_ref = try sema.addConstant(operand_ty, item_val);11476 .ty = operand_ty.toIntern(),
11477 .name = error_name,
11478 } });
11479 const item_ref = try sema.addConstant(operand_ty, item_val.toValue());
11463 case_block.inline_case_capture = item_ref;11480 case_block.inline_case_capture = item_ref;
1146411481
11465 case_block.instructions.shrinkRetainingCapacity(0);11482 case_block.instructions.shrinkRetainingCapacity(0);
...@@ -11482,7 +11499,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11482,7 +11499,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11482 while (try it.next()) |cur| {11499 while (try it.next()) |cur| {
11483 cases_len += 1;11500 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());
11486 case_block.inline_case_capture = item_ref;11503 case_block.inline_case_capture = item_ref;
1148711504
11488 case_block.instructions.shrinkRetainingCapacity(0);11505 case_block.instructions.shrinkRetainingCapacity(0);
...@@ -11539,19 +11556,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11539,19 +11556,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11539 }11556 }
11540 },11557 },
11541 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{11558 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),
11543 }),11560 }),
11544 };11561 };
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);
11547 defer wip_captures.deinit();11564 defer wip_captures.deinit();
1154811565
11549 case_block.instructions.shrinkRetainingCapacity(0);11566 case_block.instructions.shrinkRetainingCapacity(0);
11550 case_block.wip_capture_scope = wip_captures.scope;11567 case_block.wip_capture_scope = wip_captures.scope;
11551 case_block.inline_case_capture = .none;11568 case_block.inline_case_capture = .none;
1155211569
11553 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and11570 if (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))11571 operand_ty.zigTypeTag(mod) == .Enum and (!operand_ty.isNonexhaustiveEnum(mod) or union_originally))
11555 {11572 {
11556 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);11573 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
11557 const ok = try case_block.addUnOp(.is_named_enum_value, operand);11574 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...@@ -11561,9 +11578,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11561 const analyze_body = if (union_originally and !special.is_inline)11578 const analyze_body = if (union_originally and !special.is_inline)
11562 for (seen_enum_fields, 0..) |seen_field, index| {11579 for (seen_enum_fields, 0..) |seen_field, index| {
11563 if (seen_field != null) continue;11580 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).?;
11565 const field_ty = union_obj.fields.values()[index].ty;11582 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;
11567 } else false11584 } else false
11568 else11585 else
11569 true;11586 true;
...@@ -11620,47 +11637,70 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11620,47 +11637,70 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11620}11637}
1162111638
11622const RangeSetUnhandledIterator = struct {11639const RangeSetUnhandledIterator = struct {
11623 sema: *Sema,11640 mod: *Module,
11624 ty: Type,11641 cur: ?InternPool.Index,
11625 cur: Value,11642 max: InternPool.Index,
11626 max: Value,11643 range_i: usize,
11627 ranges: []const RangeSet.Range,11644 ranges: []const RangeSet.Range,
11628 range_i: usize = 0,11645 limbs: []math.big.Limb,
11629 first: bool = true,
1163011646
11631 fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {11647 const preallocated_limbs = math.big.int.calcTwosCompLimbCount(128);
11632 const target = sema.mod.getTarget();
11633 const min = try ty.minInt(sema.arena, target);
11634 const max = try ty.maxInt(sema.arena, target);
1163511648
11636 return RangeSetUnhandledIterator{11649 fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {
11637 .sema = sema,11650 const mod = sema.mod;
11638 .ty = ty,11651 const int_type = mod.intern_pool.indexToKey(ty.toIntern()).int_type;
11639 .cur = min,11652 const needed_limbs = math.big.int.calcTwosCompLimbCount(int_type.bits);
11640 .max = max,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,
11641 .ranges = range_set.ranges.items,11658 .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 &.{},
11642 };11663 };
11643 }11664 }
1164411665
11645 fn next(it: *RangeSetUnhandledIterator) !?Value {11666 fn addOne(it: *const RangeSetUnhandledIterator, val: InternPool.Index) !?InternPool.Index {
11646 while (it.range_i < it.ranges.len) : (it.range_i += 1) {11667 if (val == it.max) return null;
11647 if (!it.first) {11668 const int = it.mod.intern_pool.indexToKey(val).int;
11648 it.cur = try it.sema.intAdd(it.cur, Value.one, it.ty);11669
11649 }11670 switch (int.storage) {
11650 it.first = false;11671 inline .u64, .i64 => |val_int| {
11651 if (it.cur.compareAll(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) {11672 const next_int = @addWithOverflow(val_int, 1);
11652 return it.cur;11673 if (next_int[1] == 0)
11653 }11674 return (try it.mod.intValue(int.ty.toType(), next_int[0])).toIntern();
11654 it.cur = it.ranges[it.range_i].last;11675 },
11655 }11676 .big_int => {},
11656 if (!it.first) {11677 .lazy_align, .lazy_size => unreachable,
11657 it.cur = try it.sema.intAdd(it.cur, Value.one, it.ty);
11658 }11678 }
11659 it.first = false;11679
11660 if (it.cur.compareAll(.lte, it.max, it.ty, it.sema.mod)) {11680 var val_space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
11661 return it.cur;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 };
11662 }11701 }
11663 return null;11702 it.cur = try it.addOne(cur);
11703 return cur;
11664 }11704 }
11665};11705};
1166611706
...@@ -11671,18 +11711,17 @@ fn resolveSwitchItemVal(...@@ -11671,18 +11711,17 @@ fn resolveSwitchItemVal(
11671 switch_node_offset: i32,11711 switch_node_offset: i32,
11672 switch_prong_src: Module.SwitchProngSrc,11712 switch_prong_src: Module.SwitchProngSrc,
11673 range_expand: Module.SwitchProngSrc.RangeExpand,11713 range_expand: Module.SwitchProngSrc.RangeExpand,
11674) CompileError!TypedValue {11714) CompileError!InternPool.Index {
11715 const mod = sema.mod;
11675 const item = try sema.resolveInst(item_ref);11716 const item = try sema.resolveInst(item_ref);
11676 const item_ty = sema.typeOf(item);
11677 // Constructing a LazySrcLoc is costly because we only have the switch AST node.11717 // Constructing a LazySrcLoc is costly because we only have the switch AST node.
11678 // Only if we know for sure we need to report a compile error do we resolve the11718 // Only if we know for sure we need to report a compile error do we resolve the
11679 // full source locations.11719 // full source locations.
11680 if (sema.resolveConstValue(block, .unneeded, item, "")) |val| {11720 if (sema.resolveConstLazyValue(block, .unneeded, item, "")) |val| {
11681 try sema.resolveLazyValue(val);11721 return val.toIntern();
11682 return TypedValue{ .ty = item_ty, .val = val };
11683 } else |err| switch (err) {11722 } else |err| switch (err) {
11684 error.NeededSourceLocation => {11723 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);
11686 _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");11725 _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");
11687 unreachable;11726 unreachable;
11688 },11727 },
...@@ -11696,17 +11735,17 @@ fn validateSwitchRange(...@@ -11696,17 +11735,17 @@ fn validateSwitchRange(
11696 range_set: *RangeSet,11735 range_set: *RangeSet,
11697 first_ref: Zir.Inst.Ref,11736 first_ref: Zir.Inst.Ref,
11698 last_ref: Zir.Inst.Ref,11737 last_ref: Zir.Inst.Ref,
11699 operand_ty: Type,
11700 src_node_offset: i32,11738 src_node_offset: i32,
11701 switch_prong_src: Module.SwitchProngSrc,11739 switch_prong_src: Module.SwitchProngSrc,
11702) CompileError!void {11740) CompileError!void {
11703 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;11741 const mod = sema.mod;
11704 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;11742 const first = try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first);
11705 if (first_val.compareAll(.gt, last_val, operand_ty, sema.mod)) {11743 const last = try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last);
11706 const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first);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);
11707 return sema.fail(block, src, "range start value is greater than the end value", .{});11746 return sema.fail(block, src, "range start value is greater than the end value", .{});
11708 }11747 }
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);
11710 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);11749 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
11711}11750}
1171211751
...@@ -11715,12 +11754,11 @@ fn validateSwitchItem(...@@ -11715,12 +11754,11 @@ fn validateSwitchItem(
11715 block: *Block,11754 block: *Block,
11716 range_set: *RangeSet,11755 range_set: *RangeSet,
11717 item_ref: Zir.Inst.Ref,11756 item_ref: Zir.Inst.Ref,
11718 operand_ty: Type,
11719 src_node_offset: i32,11757 src_node_offset: i32,
11720 switch_prong_src: Module.SwitchProngSrc,11758 switch_prong_src: Module.SwitchProngSrc,
11721) CompileError!void {11759) CompileError!void {
11722 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;11760 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11723 const maybe_prev_src = try range_set.add(item_val, item_val, operand_ty, switch_prong_src);11761 const maybe_prev_src = try range_set.add(item, item, switch_prong_src);
11724 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);11762 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
11725}11763}
1172611764
...@@ -11733,9 +11771,11 @@ fn validateSwitchItemEnum(...@@ -11733,9 +11771,11 @@ fn validateSwitchItemEnum(
11733 src_node_offset: i32,11771 src_node_offset: i32,
11734 switch_prong_src: Module.SwitchProngSrc,11772 switch_prong_src: Module.SwitchProngSrc,
11735) CompileError!void {11773) CompileError!void {
11736 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);11774 const ip = &sema.mod.intern_pool;
11737 const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {11775 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11738 const maybe_prev_src = try range_set.add(item_tv.val, item_tv.val, item_tv.ty, switch_prong_src);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);
11739 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);11779 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
11740 };11780 };
11741 const maybe_prev_src = seen_fields[field_index];11781 const maybe_prev_src = seen_fields[field_index];
...@@ -11751,9 +11791,10 @@ fn validateSwitchItemError(...@@ -11751,9 +11791,10 @@ fn validateSwitchItemError(
11751 src_node_offset: i32,11791 src_node_offset: i32,
11752 switch_prong_src: Module.SwitchProngSrc,11792 switch_prong_src: Module.SwitchProngSrc,
11753) CompileError!void {11793) 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);
11755 // TODO: Do i need to typecheck here?11796 // 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;
11757 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|11798 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|
11758 prev.value11799 prev.value
11759 else11800 else
...@@ -11769,10 +11810,10 @@ fn validateSwitchDupe(...@@ -11769,10 +11810,10 @@ fn validateSwitchDupe(
11769 src_node_offset: i32,11810 src_node_offset: i32,
11770) CompileError!void {11811) CompileError!void {
11771 const prev_prong_src = maybe_prev_src orelse return;11812 const prev_prong_src = maybe_prev_src orelse return;
11772 const gpa = sema.gpa;11813 const mod = sema.mod;
11773 const block_src_decl = sema.mod.declPtr(block.src_decl);11814 const block_src_decl = mod.declPtr(block.src_decl);
11774 const src = switch_prong_src.resolve(gpa, block_src_decl, src_node_offset, .none);11815 const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none);
11775 const prev_src = prev_prong_src.resolve(gpa, block_src_decl, src_node_offset, .none);11816 const prev_src = prev_prong_src.resolve(mod, block_src_decl, src_node_offset, .none);
11776 const msg = msg: {11817 const msg = msg: {
11777 const msg = try sema.errMsg(11818 const msg = try sema.errMsg(
11778 block,11819 block,
...@@ -11802,20 +11843,21 @@ fn validateSwitchItemBool(...@@ -11802,20 +11843,21 @@ fn validateSwitchItemBool(
11802 src_node_offset: i32,11843 src_node_offset: i32,
11803 switch_prong_src: Module.SwitchProngSrc,11844 switch_prong_src: Module.SwitchProngSrc,
11804) CompileError!void {11845) CompileError!void {
11805 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;11846 const mod = sema.mod;
11806 if (item_val.toBool()) {11847 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11848 if (item.toValue().toBool()) {
11807 true_count.* += 1;11849 true_count.* += 1;
11808 } else {11850 } else {
11809 false_count.* += 1;11851 false_count.* += 1;
11810 }11852 }
11811 if (true_count.* + false_count.* > 2) {11853 if (true_count.* + false_count.* > 2) {
11812 const block_src_decl = sema.mod.declPtr(block.src_decl);11854 const block_src_decl = mod.declPtr(block.src_decl);
11813 const src = switch_prong_src.resolve(sema.gpa, block_src_decl, src_node_offset, .none);11855 const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none);
11814 return sema.fail(block, src, "duplicate switch value", .{});11856 return sema.fail(block, src, "duplicate switch value", .{});
11815 }11857 }
11816}11858}
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
11820fn validateSwitchItemSparse(11862fn validateSwitchItemSparse(
11821 sema: *Sema,11863 sema: *Sema,
...@@ -11825,8 +11867,8 @@ fn validateSwitchItemSparse(...@@ -11825,8 +11867,8 @@ fn validateSwitchItemSparse(
11825 src_node_offset: i32,11867 src_node_offset: i32,
11826 switch_prong_src: Module.SwitchProngSrc,11868 switch_prong_src: Module.SwitchProngSrc,
11827) CompileError!void {11869) CompileError!void {
11828 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;11870 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11829 const kv = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;11871 const kv = (try seen_values.fetchPut(sema.gpa, item, switch_prong_src)) orelse return;
11830 return sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset);11872 return sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset);
11831}11873}
1183211874
...@@ -11864,7 +11906,8 @@ fn validateSwitchNoRange(...@@ -11864,7 +11906,8 @@ fn validateSwitchNoRange(
11864}11906}
1186511907
11866fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, operand: Air.Inst.Ref) !bool {11908fn 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
11869 const tags = sema.code.instructions.items(.tag);11912 const tags = sema.code.instructions.items(.tag);
11870 for (body) |inst| {11913 for (body) |inst| {
...@@ -11900,7 +11943,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op...@@ -11900,7 +11943,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
11900 .as_node => try sema.zirAsNode(block, inst),11943 .as_node => try sema.zirAsNode(block, inst),
11901 .field_val => try sema.zirFieldVal(block, inst),11944 .field_val => try sema.zirFieldVal(block, inst),
11902 .@"unreachable" => {11945 .@"unreachable" => {
11903 if (!sema.mod.comp.formatted_panics) {11946 if (!mod.comp.formatted_panics) {
11904 try sema.safetyPanic(block, .unwrap_error);11947 try sema.safetyPanic(block, .unwrap_error);
11905 return true;11948 return true;
11906 }11949 }
...@@ -11923,7 +11966,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op...@@ -11923,7 +11966,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
11923 },11966 },
11924 else => unreachable,11967 else => unreachable,
11925 };11968 };
11926 if (sema.typeOf(air_inst).isNoReturn())11969 if (sema.typeOf(air_inst).isNoReturn(mod))
11927 return true;11970 return true;
11928 sema.inst_map.putAssumeCapacity(inst, air_inst);11971 sema.inst_map.putAssumeCapacity(inst, air_inst);
11929 }11972 }
...@@ -11931,19 +11974,20 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op...@@ -11931,19 +11974,20 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
11931}11974}
1193211975
11933fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, cond: Zir.Inst.Ref, cond_src: LazySrcLoc) !void {11976fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, cond: Zir.Inst.Ref, cond_src: LazySrcLoc) !void {
11977 const mod = sema.mod;
11934 const index = Zir.refToIndex(cond) orelse return;11978 const index = Zir.refToIndex(cond) orelse return;
11935 if (sema.code.instructions.items(.tag)[index] != .is_non_err) return;11979 if (sema.code.instructions.items(.tag)[index] != .is_non_err) return;
1193611980
11937 const err_inst_data = sema.code.instructions.items(.data)[index].un_node;11981 const err_inst_data = sema.code.instructions.items(.data)[index].un_node;
11938 const err_operand = try sema.resolveInst(err_inst_data.operand);11982 const err_operand = try sema.resolveInst(err_inst_data.operand);
11939 const operand_ty = sema.typeOf(err_operand);11983 const operand_ty = sema.typeOf(err_operand);
11940 if (operand_ty.zigTypeTag() == .ErrorSet) {11984 if (operand_ty.zigTypeTag(mod) == .ErrorSet) {
11941 try sema.maybeErrorUnwrapComptime(block, body, err_operand);11985 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
11942 return;11986 return;
11943 }11987 }
11944 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {11988 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {
11945 if (!operand_ty.isError()) return;11989 if (!operand_ty.isError(mod)) return;
11946 if (val.getError() == null) return;11990 if (val.getErrorName(mod) == .none) return;
11947 try sema.maybeErrorUnwrapComptime(block, body, err_operand);11991 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
11948 }11992 }
11949}11993}
...@@ -11965,45 +12009,60 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I...@@ -11965,45 +12009,60 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
11965 const src = inst_data.src();12009 const src = inst_data.src();
1196612010
11967 if (try sema.resolveDefinedValue(block, src, operand)) |val| {12011 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
11968 if (val.getError()) |name| {12012 if (val.getErrorName(sema.mod).unwrap()) |name| {
11969 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});12013 return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&sema.mod.intern_pool)});
11970 }12014 }
11971 }12015 }
11972}12016}
1197312017
11974fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {12018fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12019 const mod = sema.mod;
11975 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;12020 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11976 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;12021 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
11977 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };12022 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
11978 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };12023 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
11979 const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs);12024 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");
11981 const ty = try sema.resolveTypeFields(unresolved_ty);12026 const ty = try sema.resolveTypeFields(unresolved_ty);
12027 const ip = &mod.intern_pool;
1198212028
11983 const has_field = hf: {12029 const has_field = hf: {
11984 if (ty.isSlice()) {12030 switch (ip.indexToKey(ty.toIntern())) {
11985 if (mem.eql(u8, field_name, "ptr")) break :hf true;12031 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
11986 if (mem.eql(u8, field_name, "len")) break :hf true;12032 .Slice => {
11987 break :hf false;12033 if (ip.stringEqlSlice(field_name, "ptr")) break :hf true;
11988 }12034 if (ip.stringEqlSlice(field_name, "len")) break :hf true;
11989 if (ty.castTag(.anon_struct)) |pl| {12035 break :hf false;
11990 break :hf for (pl.data.names) |name| {12036 },
11991 if (mem.eql(u8, name, field_name)) break true;12037 else => {},
11992 } else false;12038 },
11993 }12039 .anon_struct_type => |anon_struct| {
11994 if (ty.isTuple()) {12040 if (anon_struct.names.len != 0) {
11995 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;12041 break :hf mem.indexOfScalar(InternPool.NullTerminatedString, anon_struct.names, field_name) != null;
11996 break :hf field_index < ty.structFieldCount();12042 } else {
11997 }12043 const field_index = field_name.toUnsigned(ip) orelse break :hf false;
11998 break :hf switch (ty.zigTypeTag()) {12044 break :hf field_index < ty.structFieldCount(mod);
11999 .Struct => ty.structFields().contains(field_name),12045 }
12000 .Union => ty.unionFields().contains(field_name),12046 },
12001 .Enum => ty.enumFields().contains(field_name),12047 .struct_type => |struct_type| {
12002 .Array => mem.eql(u8, field_name, "len"),12048 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :hf false;
12003 else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{12049 assert(struct_obj.haveFieldTypes());
12004 ty.fmt(sema.mod),12050 break :hf struct_obj.fields.contains(field_name);
12005 }),12051 },
12006 };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 });
12007 };12066 };
12008 if (has_field) {12067 if (has_field) {
12009 return Air.Inst.Ref.bool_true;12068 return Air.Inst.Ref.bool_true;
...@@ -12013,20 +12072,22 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12013,20 +12072,22 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12013}12072}
1201412073
12015fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {12074fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12075 const mod = sema.mod;
12016 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;12076 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12017 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;12077 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
12018 const src = inst_data.src();12078 const src = inst_data.src();
12019 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };12079 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
12020 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };12080 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
12021 const container_type = try sema.resolveType(block, lhs_src, extra.lhs);12081 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
12024 try sema.checkNamespaceType(block, lhs_src, container_type);12084 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;
12027 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| {12088 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| {
12028 const decl = sema.mod.declPtr(decl_index);12089 const decl = mod.declPtr(decl_index);
12029 if (decl.is_pub or decl.getFileScope() == block.getFileScope()) {12090 if (decl.is_pub or decl.getFileScope(mod) == block.getFileScope(mod)) {
12030 return Air.Inst.Ref.bool_true;12091 return Air.Inst.Ref.bool_true;
12031 }12092 }
12032 }12093 }
...@@ -12042,12 +12103,12 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -12042,12 +12103,12 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
12042 const operand_src = inst_data.src();12103 const operand_src = inst_data.src();
12043 const operand = inst_data.get(sema.code);12104 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) {
12046 error.ImportOutsidePkgPath => {12107 error.ImportOutsidePkgPath => {
12047 return sema.fail(block, operand_src, "import of file outside package path: '{s}'", .{operand});12108 return sema.fail(block, operand_src, "import of file outside package path: '{s}'", .{operand});
12048 },12109 },
12049 error.PackageNotFound => {12110 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.*);
12051 defer sema.gpa.free(name);12112 defer sema.gpa.free(name);
12052 return sema.fail(block, operand_src, "no package named '{s}' available within package '{s}'", .{ operand, name });12113 return sema.fail(block, operand_src, "no package named '{s}' available within package '{s}'", .{ operand, name });
12053 },12114 },
...@@ -12073,7 +12134,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -12073,7 +12134,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
12073 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };12134 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
12074 const name = try sema.resolveConstString(block, operand_src, inst_data.operand, "file path name must be comptime-known");12135 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) {
12077 error.ImportOutsidePkgPath => {12138 error.ImportOutsidePkgPath => {
12078 return sema.fail(block, operand_src, "embed of file outside package path: '{s}'", .{name});12139 return sema.fail(block, operand_src, "embed of file outside package path: '{s}'", .{name});
12079 },12140 },
...@@ -12087,17 +12148,23 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -12087,17 +12148,23 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
12087 var anon_decl = try block.startAnonDecl();12148 var anon_decl = try block.startAnonDecl();
12088 defer anon_decl.deinit();12149 defer anon_decl.deinit();
1208912150
12090 const bytes_including_null = embed_file.bytes[0 .. embed_file.bytes.len + 1];12151 // TODO instead of using `.bytes`, create a new value tag for pointing at
12091
12092 // TODO instead of using `Value.Tag.bytes`, create a new value tag for pointing at
12093 // a `*Module.EmbedFile`. The purpose of this would be:12152 // a `*Module.EmbedFile`. The purpose of this would be:
12094 // - If only the length is read and the bytes are not inspected by comptime code,12153 // - If only the length is read and the bytes are not inspected by comptime code,
12095 // there can be an optimization where the codegen backend does a copy_file_range12154 // there can be an optimization where the codegen backend does a copy_file_range
12096 // into the final binary, and never loads the data into memory.12155 // into the final binary, and never loads the data into memory.
12097 // - When a Decl is destroyed, it can free the `*Module.EmbedFile`.12156 // - 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 });
12098 embed_file.owner_decl = try anon_decl.finish(12162 embed_file.owner_decl = try anon_decl.finish(
12099 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), embed_file.bytes.len),12163 ty,
12100 try Value.Tag.bytes.create(anon_decl.arena(), bytes_including_null),12164 (try mod.intern(.{ .aggregate = .{
12165 .ty = ty.toIntern(),
12166 .storage = .{ .bytes = embed_file.bytes },
12167 } })).toValue(),
12101 0, // default alignment12168 0, // default alignment
12102 );12169 );
1210312170
...@@ -12105,16 +12172,15 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -12105,16 +12172,15 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
12105}12172}
1210612173
12107fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {12174fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12175 const mod = sema.mod;
12108 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;12176 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
12109 const err_name = inst_data.get(sema.code);12177 const name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
1211012178 _ = try mod.getErrorValue(name);
12111 // Return the error code from the function.12179 const error_set_type = try mod.singleErrorSetType(name);
12112 const kv = try sema.mod.getErrorValue(err_name);12180 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
12113 const result_inst = try sema.addConstant(12181 .ty = error_set_type.toIntern(),
12114 try Type.Tag.error_set_single.create(sema.arena, kv.key),12182 .name = name,
12115 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),12183 } })).toValue());
12116 );
12117 return result_inst;
12118}12184}
1211912185
12120fn zirShl(12186fn zirShl(
...@@ -12126,6 +12192,7 @@ fn zirShl(...@@ -12126,6 +12192,7 @@ fn zirShl(
12126 const tracy = trace(@src());12192 const tracy = trace(@src());
12127 defer tracy.end();12193 defer tracy.end();
1212812194
12195 const mod = sema.mod;
12129 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;12196 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12130 const src = inst_data.src();12197 const src = inst_data.src();
12131 sema.src = src;12198 sema.src = src;
...@@ -12136,11 +12203,10 @@ fn zirShl(...@@ -12136,11 +12203,10 @@ fn zirShl(
12136 const rhs = try sema.resolveInst(extra.rhs);12203 const rhs = try sema.resolveInst(extra.rhs);
12137 const lhs_ty = sema.typeOf(lhs);12204 const lhs_ty = sema.typeOf(lhs);
12138 const rhs_ty = sema.typeOf(rhs);12205 const rhs_ty = sema.typeOf(rhs);
12139 const target = sema.mod.getTarget();
12140 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);12206 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1214112207
12142 const scalar_ty = lhs_ty.scalarType();12208 const scalar_ty = lhs_ty.scalarType(mod);
12143 const scalar_rhs_ty = rhs_ty.scalarType();12209 const scalar_rhs_ty = rhs_ty.scalarType(mod);
1214412210
12145 // TODO coerce rhs if air_tag is not shl_sat12211 // TODO coerce rhs if air_tag is not shl_sat
12146 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty);12212 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty);
...@@ -12149,62 +12215,56 @@ fn zirShl(...@@ -12149,62 +12215,56 @@ fn zirShl(
12149 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);12215 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);
1215012216
12151 if (maybe_rhs_val) |rhs_val| {12217 if (maybe_rhs_val) |rhs_val| {
12152 if (rhs_val.isUndef()) {12218 if (rhs_val.isUndef(mod)) {
12153 return sema.addConstUndef(sema.typeOf(lhs));12219 return sema.addConstUndef(sema.typeOf(lhs));
12154 }12220 }
12155 // If rhs is 0, return lhs without doing any calculations.12221 // If rhs is 0, return lhs without doing any calculations.
12156 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {12222 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
12157 return lhs;12223 return lhs;
12158 }12224 }
12159 if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) {12225 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt and air_tag != .shl_sat) {
12160 var bits_payload = Value.Payload.U64{12226 const bit_value = try mod.intValue(Type.comptime_int, scalar_ty.intInfo(mod).bits);
12161 .base = .{ .tag = .int_u64 },12227 if (rhs_ty.zigTypeTag(mod) == .Vector) {
12162 .data = scalar_ty.intInfo(target).bits,
12163 };
12164 const bit_value = Value.initPayload(&bits_payload.base);
12165 if (rhs_ty.zigTypeTag() == .Vector) {
12166 var i: usize = 0;12228 var i: usize = 0;
12167 while (i < rhs_ty.vectorLen()) : (i += 1) {12229 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12168 var elem_value_buf: Value.ElemValueBuffer = undefined;12230 const rhs_elem = try rhs_val.elemValue(mod, i);
12169 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);12231 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {
12170 if (rhs_elem.compareHetero(.gte, bit_value, target)) {
12171 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{12232 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),
12173 i,12234 i,
12174 scalar_ty.fmt(sema.mod),12235 scalar_ty.fmt(mod),
12175 });12236 });
12176 }12237 }
12177 }12238 }
12178 } else if (rhs_val.compareHetero(.gte, bit_value, target)) {12239 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {
12179 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{12240 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
12180 rhs_val.fmtValue(scalar_ty, sema.mod),12241 rhs_val.fmtValue(scalar_ty, mod),
12181 scalar_ty.fmt(sema.mod),12242 scalar_ty.fmt(mod),
12182 });12243 });
12183 }12244 }
12184 }12245 }
12185 if (rhs_ty.zigTypeTag() == .Vector) {12246 if (rhs_ty.zigTypeTag(mod) == .Vector) {
12186 var i: usize = 0;12247 var i: usize = 0;
12187 while (i < rhs_ty.vectorLen()) : (i += 1) {12248 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12188 var elem_value_buf: Value.ElemValueBuffer = undefined;12249 const rhs_elem = try rhs_val.elemValue(mod, i);
12189 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);12250 if (rhs_elem.compareHetero(.lt, try mod.intValue(scalar_rhs_ty, 0), mod)) {
12190 if (rhs_elem.compareHetero(.lt, Value.zero, target)) {
12191 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{12251 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),
12193 i,12253 i,
12194 });12254 });
12195 }12255 }
12196 }12256 }
12197 } else if (rhs_val.compareHetero(.lt, Value.zero, target)) {12257 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
12198 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{12258 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),
12200 });12260 });
12201 }12261 }
12202 }12262 }
1220312263
12204 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {12264 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);
12206 const rhs_val = maybe_rhs_val orelse {12266 const rhs_val = maybe_rhs_val orelse {
12207 if (scalar_ty.zigTypeTag() == .ComptimeInt) {12267 if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) {
12208 return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{});12268 return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{});
12209 }12269 }
12210 break :rs rhs_src;12270 break :rs rhs_src;
...@@ -12212,25 +12272,25 @@ fn zirShl(...@@ -12212,25 +12272,25 @@ fn zirShl(
1221212272
12213 const val = switch (air_tag) {12273 const val = switch (air_tag) {
12214 .shl_exact => val: {12274 .shl_exact => val: {
12215 const shifted = try lhs_val.shlWithOverflow(rhs_val, lhs_ty, sema.arena, sema.mod);12275 const shifted = try lhs_val.shlWithOverflow(rhs_val, lhs_ty, sema.arena, mod);
12216 if (scalar_ty.zigTypeTag() == .ComptimeInt) {12276 if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) {
12217 break :val shifted.wrapped_result;12277 break :val shifted.wrapped_result;
12218 }12278 }
12219 if (shifted.overflow_bit.compareAllWithZero(.eq, sema.mod)) {12279 if (shifted.overflow_bit.compareAllWithZero(.eq, mod)) {
12220 break :val shifted.wrapped_result;12280 break :val shifted.wrapped_result;
12221 }12281 }
12222 return sema.fail(block, src, "operation caused overflow", .{});12282 return sema.fail(block, src, "operation caused overflow", .{});
12223 },12283 },
1222412284
12225 .shl_sat => if (scalar_ty.zigTypeTag() == .ComptimeInt)12285 .shl_sat => if (scalar_ty.zigTypeTag(mod) == .ComptimeInt)
12226 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod)12286 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, mod)
12227 else12287 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)12290 .shl => if (scalar_ty.zigTypeTag(mod) == .ComptimeInt)
12231 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod)12291 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, mod)
12232 else12292 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
12235 else => unreachable,12295 else => unreachable,
12236 };12296 };
...@@ -12241,11 +12301,11 @@ fn zirShl(...@@ -12241,11 +12301,11 @@ fn zirShl(
12241 const new_rhs = if (air_tag == .shl_sat) rhs: {12301 const new_rhs = if (air_tag == .shl_sat) rhs: {
12242 // Limit the RHS type for saturating shl to be an integer as small as the LHS.12302 // Limit the RHS type for saturating shl to be an integer as small as the LHS.
12243 if (rhs_is_comptime_int or12303 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)
12245 {12305 {
12246 const max_int = try sema.addConstant(12306 const max_int = try sema.addConstant(
12247 lhs_ty,12307 lhs_ty,
12248 try lhs_ty.maxInt(sema.arena, target),12308 try lhs_ty.maxInt(mod, lhs_ty),
12249 );12309 );
12250 const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src });12310 const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src });
12251 break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false);12311 break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false);
...@@ -12256,12 +12316,11 @@ fn zirShl(...@@ -12256,12 +12316,11 @@ fn zirShl(
1225612316
12257 try sema.requireRuntimeBlock(block, src, runtime_src);12317 try sema.requireRuntimeBlock(block, src, runtime_src);
12258 if (block.wantSafety()) {12318 if (block.wantSafety()) {
12259 const bit_count = scalar_ty.intInfo(target).bits;12319 const bit_count = scalar_ty.intInfo(mod).bits;
12260 if (!std.math.isPowerOfTwo(bit_count)) {12320 if (!std.math.isPowerOfTwo(bit_count)) {
12261 const bit_count_val = try Value.Tag.int_u64.create(sema.arena, bit_count);12321 const bit_count_val = try mod.intValue(scalar_rhs_ty, bit_count);
1226212322 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
12263 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {12323 const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
12264 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
12265 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);12324 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
12266 break :ok try block.addInst(.{12325 break :ok try block.addInst(.{
12267 .tag = .reduce,12326 .tag = .reduce,
...@@ -12290,7 +12349,7 @@ fn zirShl(...@@ -12290,7 +12349,7 @@ fn zirShl(
12290 } },12349 } },
12291 });12350 });
12292 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);12351 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)
12294 try block.addInst(.{12353 try block.addInst(.{
12295 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,12354 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
12296 .data = .{ .reduce = .{12355 .data = .{ .reduce = .{
...@@ -12300,7 +12359,7 @@ fn zirShl(...@@ -12300,7 +12359,7 @@ fn zirShl(
12300 })12359 })
12301 else12360 else
12302 ov_bit;12361 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));
12304 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);12363 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
1230512364
12306 try sema.addSafetyCheck(block, no_ov, .shl_overflow);12365 try sema.addSafetyCheck(block, no_ov, .shl_overflow);
...@@ -12319,6 +12378,7 @@ fn zirShr(...@@ -12319,6 +12378,7 @@ fn zirShr(
12319 const tracy = trace(@src());12378 const tracy = trace(@src());
12320 defer tracy.end();12379 defer tracy.end();
1232112380
12381 const mod = sema.mod;
12322 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;12382 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12323 const src = inst_data.src();12383 const src = inst_data.src();
12324 sema.src = src;12384 sema.src = src;
...@@ -12330,94 +12390,87 @@ fn zirShr(...@@ -12330,94 +12390,87 @@ fn zirShr(
12330 const lhs_ty = sema.typeOf(lhs);12390 const lhs_ty = sema.typeOf(lhs);
12331 const rhs_ty = sema.typeOf(rhs);12391 const rhs_ty = sema.typeOf(rhs);
12332 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);12392 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
12333 const target = sema.mod.getTarget();12393 const scalar_ty = lhs_ty.scalarType(mod);
12334 const scalar_ty = lhs_ty.scalarType();
1233512394
12336 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs);12395 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs);
12337 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);12396 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);
1233812397
12339 const runtime_src = if (maybe_rhs_val) |rhs_val| rs: {12398 const runtime_src = if (maybe_rhs_val) |rhs_val| rs: {
12340 if (rhs_val.isUndef()) {12399 if (rhs_val.isUndef(mod)) {
12341 return sema.addConstUndef(lhs_ty);12400 return sema.addConstUndef(lhs_ty);
12342 }12401 }
12343 // If rhs is 0, return lhs without doing any calculations.12402 // If rhs is 0, return lhs without doing any calculations.
12344 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {12403 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
12345 return lhs;12404 return lhs;
12346 }12405 }
12347 if (scalar_ty.zigTypeTag() != .ComptimeInt) {12406 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt) {
12348 var bits_payload = Value.Payload.U64{12407 const bit_value = try mod.intValue(Type.comptime_int, scalar_ty.intInfo(mod).bits);
12349 .base = .{ .tag = .int_u64 },12408 if (rhs_ty.zigTypeTag(mod) == .Vector) {
12350 .data = scalar_ty.intInfo(target).bits,
12351 };
12352 const bit_value = Value.initPayload(&bits_payload.base);
12353 if (rhs_ty.zigTypeTag() == .Vector) {
12354 var i: usize = 0;12409 var i: usize = 0;
12355 while (i < rhs_ty.vectorLen()) : (i += 1) {12410 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12356 var elem_value_buf: Value.ElemValueBuffer = undefined;12411 const rhs_elem = try rhs_val.elemValue(mod, i);
12357 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);12412 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {
12358 if (rhs_elem.compareHetero(.gte, bit_value, target)) {
12359 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{12413 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),
12361 i,12415 i,
12362 scalar_ty.fmt(sema.mod),12416 scalar_ty.fmt(mod),
12363 });12417 });
12364 }12418 }
12365 }12419 }
12366 } else if (rhs_val.compareHetero(.gte, bit_value, target)) {12420 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {
12367 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{12421 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
12368 rhs_val.fmtValue(scalar_ty, sema.mod),12422 rhs_val.fmtValue(scalar_ty, mod),
12369 scalar_ty.fmt(sema.mod),12423 scalar_ty.fmt(mod),
12370 });12424 });
12371 }12425 }
12372 }12426 }
12373 if (rhs_ty.zigTypeTag() == .Vector) {12427 if (rhs_ty.zigTypeTag(mod) == .Vector) {
12374 var i: usize = 0;12428 var i: usize = 0;
12375 while (i < rhs_ty.vectorLen()) : (i += 1) {12429 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12376 var elem_value_buf: Value.ElemValueBuffer = undefined;12430 const rhs_elem = try rhs_val.elemValue(mod, i);
12377 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);12431 if (rhs_elem.compareHetero(.lt, try mod.intValue(rhs_ty.childType(mod), 0), mod)) {
12378 if (rhs_elem.compareHetero(.lt, Value.zero, target)) {
12379 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{12432 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),
12381 i,12434 i,
12382 });12435 });
12383 }12436 }
12384 }12437 }
12385 } else if (rhs_val.compareHetero(.lt, Value.zero, target)) {12438 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
12386 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{12439 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),
12388 });12441 });
12389 }12442 }
12390 if (maybe_lhs_val) |lhs_val| {12443 if (maybe_lhs_val) |lhs_val| {
12391 if (lhs_val.isUndef()) {12444 if (lhs_val.isUndef(mod)) {
12392 return sema.addConstUndef(lhs_ty);12445 return sema.addConstUndef(lhs_ty);
12393 }12446 }
12394 if (air_tag == .shr_exact) {12447 if (air_tag == .shr_exact) {
12395 // Detect if any ones would be shifted out.12448 // 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);
12397 if (!(try truncated.compareAllWithZeroAdvanced(.eq, sema))) {12450 if (!(try truncated.compareAllWithZeroAdvanced(.eq, sema))) {
12398 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});12451 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});
12399 }12452 }
12400 }12453 }
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);
12402 return sema.addConstant(lhs_ty, val);12455 return sema.addConstant(lhs_ty, val);
12403 } else {12456 } else {
12404 break :rs lhs_src;12457 break :rs lhs_src;
12405 }12458 }
12406 } else rhs_src;12459 } 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) {
12409 return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{});12462 return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{});
12410 }12463 }
1241112464
12412 try sema.requireRuntimeBlock(block, src, runtime_src);12465 try sema.requireRuntimeBlock(block, src, runtime_src);
12413 const result = try block.addBinOp(air_tag, lhs, rhs);12466 const result = try block.addBinOp(air_tag, lhs, rhs);
12414 if (block.wantSafety()) {12467 if (block.wantSafety()) {
12415 const bit_count = scalar_ty.intInfo(target).bits;12468 const bit_count = scalar_ty.intInfo(mod).bits;
12416 if (!std.math.isPowerOfTwo(bit_count)) {12469 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: {12472 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
12420 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));12473 const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
12421 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);12474 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
12422 break :ok try block.addInst(.{12475 break :ok try block.addInst(.{
12423 .tag = .reduce,12476 .tag = .reduce,
...@@ -12436,7 +12489,7 @@ fn zirShr(...@@ -12436,7 +12489,7 @@ fn zirShr(
12436 if (air_tag == .shr_exact) {12489 if (air_tag == .shr_exact) {
12437 const back = try block.addBinOp(.shl, result, rhs);12490 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: {
12440 const eql = try block.addCmpVector(lhs, back, .eq);12493 const eql = try block.addCmpVector(lhs, back, .eq);
12441 break :ok try block.addInst(.{12494 break :ok try block.addInst(.{
12442 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,12495 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
...@@ -12461,6 +12514,7 @@ fn zirBitwise(...@@ -12461,6 +12514,7 @@ fn zirBitwise(
12461 const tracy = trace(@src());12514 const tracy = trace(@src());
12462 defer tracy.end();12515 defer tracy.end();
1246312516
12517 const mod = sema.mod;
12464 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;12518 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12465 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };12519 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
12466 sema.src = src;12520 sema.src = src;
...@@ -12475,8 +12529,8 @@ fn zirBitwise(...@@ -12475,8 +12529,8 @@ fn zirBitwise(
1247512529
12476 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };12530 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
12477 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });12531 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
12478 const scalar_type = resolved_type.scalarType();12532 const scalar_type = resolved_type.scalarType(mod);
12479 const scalar_tag = scalar_type.zigTypeTag();12533 const scalar_tag = scalar_type.zigTypeTag(mod);
1248012534
12481 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);12535 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
12482 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);12536 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
...@@ -12484,7 +12538,7 @@ fn zirBitwise(...@@ -12484,7 +12538,7 @@ fn zirBitwise(
12484 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;12538 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1248512539
12486 if (!is_int) {12540 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)) });
12488 }12542 }
1248912543
12490 const runtime_src = runtime: {12544 const runtime_src = runtime: {
...@@ -12493,9 +12547,9 @@ fn zirBitwise(...@@ -12493,9 +12547,9 @@ fn zirBitwise(
12493 if (try sema.resolveMaybeUndefValIntable(casted_lhs)) |lhs_val| {12547 if (try sema.resolveMaybeUndefValIntable(casted_lhs)) |lhs_val| {
12494 if (try sema.resolveMaybeUndefValIntable(casted_rhs)) |rhs_val| {12548 if (try sema.resolveMaybeUndefValIntable(casted_rhs)) |rhs_val| {
12495 const result_val = switch (air_tag) {12549 const result_val = switch (air_tag) {
12496 .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena, sema.mod),12550 .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena, mod),
12497 .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena, sema.mod),12551 .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena, mod),
12498 .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena, sema.mod),12552 .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena, mod),
12499 else => unreachable,12553 else => unreachable,
12500 };12554 };
12501 return sema.addConstant(resolved_type, result_val);12555 return sema.addConstant(resolved_type, result_val);
...@@ -12515,37 +12569,37 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -12515,37 +12569,37 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
12515 const tracy = trace(@src());12569 const tracy = trace(@src());
12516 defer tracy.end();12570 defer tracy.end();
1251712571
12572 const mod = sema.mod;
12518 const inst_data = sema.code.instructions.items(.data)[inst].un_node;12573 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
12519 const src = inst_data.src();12574 const src = inst_data.src();
12520 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };12575 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };
1252112576
12522 const operand = try sema.resolveInst(inst_data.operand);12577 const operand = try sema.resolveInst(inst_data.operand);
12523 const operand_type = sema.typeOf(operand);12578 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) {
12527 return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{12582 return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{
12528 operand_type.fmt(sema.mod),12583 operand_type.fmt(mod),
12529 });12584 });
12530 }12585 }
1253112586
12532 if (try sema.resolveMaybeUndefVal(operand)) |val| {12587 if (try sema.resolveMaybeUndefVal(operand)) |val| {
12533 if (val.isUndef()) {12588 if (val.isUndef(mod)) {
12534 return sema.addConstUndef(operand_type);12589 return sema.addConstUndef(operand_type);
12535 } else if (operand_type.zigTypeTag() == .Vector) {12590 } else if (operand_type.zigTypeTag(mod) == .Vector) {
12536 const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen());12591 const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen(mod));
12537 var elem_val_buf: Value.ElemValueBuffer = undefined;12592 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
12538 const elems = try sema.arena.alloc(Value, vec_len);
12539 for (elems, 0..) |*elem, i| {12593 for (elems, 0..) |*elem, i| {
12540 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_val_buf);12594 const elem_val = try val.elemValue(mod, i);
12541 elem.* = try elem_val.bitwiseNot(scalar_type, sema.arena, sema.mod);12595 elem.* = try (try elem_val.bitwiseNot(scalar_type, sema.arena, mod)).intern(scalar_type, mod);
12542 }12596 }
12543 return sema.addConstant(12597 return sema.addConstant(operand_type, (try mod.intern(.{ .aggregate = .{
12544 operand_type,12598 .ty = operand_type.toIntern(),
12545 try Value.Tag.aggregate.create(sema.arena, elems),12599 .storage = .{ .elems = elems },
12546 );12600 } })).toValue());
12547 } else {12601 } 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);
12549 return sema.addConstant(operand_type, result_val);12603 return sema.addConstant(operand_type, result_val);
12550 }12604 }
12551 }12605 }
...@@ -12561,18 +12615,19 @@ fn analyzeTupleCat(...@@ -12561,18 +12615,19 @@ fn analyzeTupleCat(
12561 lhs: Air.Inst.Ref,12615 lhs: Air.Inst.Ref,
12562 rhs: Air.Inst.Ref,12616 rhs: Air.Inst.Ref,
12563) CompileError!Air.Inst.Ref {12617) CompileError!Air.Inst.Ref {
12618 const mod = sema.mod;
12564 const lhs_ty = sema.typeOf(lhs);12619 const lhs_ty = sema.typeOf(lhs);
12565 const rhs_ty = sema.typeOf(rhs);12620 const rhs_ty = sema.typeOf(rhs);
12566 const src = LazySrcLoc.nodeOffset(src_node);12621 const src = LazySrcLoc.nodeOffset(src_node);
12567 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };12622 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
12568 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };12623 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1256912624
12570 const lhs_len = lhs_ty.structFieldCount();12625 const lhs_len = lhs_ty.structFieldCount(mod);
12571 const rhs_len = rhs_ty.structFieldCount();12626 const rhs_len = rhs_ty.structFieldCount(mod);
12572 const dest_fields = lhs_len + rhs_len;12627 const dest_fields = lhs_len + rhs_len;
1257312628
12574 if (dest_fields == 0) {12629 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);
12576 }12631 }
12577 if (lhs_len == 0) {12632 if (lhs_len == 0) {
12578 return rhs;12633 return rhs;
...@@ -12582,42 +12637,48 @@ fn analyzeTupleCat(...@@ -12582,42 +12637,48 @@ fn analyzeTupleCat(
12582 }12637 }
12583 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);12638 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);
1258412639
12585 const types = try sema.arena.alloc(Type, final_len);12640 const types = try sema.arena.alloc(InternPool.Index, final_len);
12586 const values = try sema.arena.alloc(Value, final_len);12641 const values = try sema.arena.alloc(InternPool.Index, final_len);
1258712642
12588 const opt_runtime_src = rs: {12643 const opt_runtime_src = rs: {
12589 var runtime_src: ?LazySrcLoc = null;12644 var runtime_src: ?LazySrcLoc = null;
12590 var i: u32 = 0;12645 var i: u32 = 0;
12591 while (i < lhs_len) : (i += 1) {12646 while (i < lhs_len) : (i += 1) {
12592 types[i] = lhs_ty.structFieldType(i);12647 types[i] = lhs_ty.structFieldType(i, mod).toIntern();
12593 const default_val = lhs_ty.structFieldDefaultValue(i);12648 const default_val = lhs_ty.structFieldDefaultValue(i, mod);
12594 values[i] = default_val;12649 values[i] = default_val.toIntern();
12595 const operand_src = lhs_src; // TODO better source location12650 const operand_src = lhs_src; // TODO better source location
12596 if (default_val.tag() == .unreachable_value) {12651 if (default_val.toIntern() == .unreachable_value) {
12597 runtime_src = operand_src;12652 runtime_src = operand_src;
12653 values[i] = .none;
12598 }12654 }
12599 }12655 }
12600 i = 0;12656 i = 0;
12601 while (i < rhs_len) : (i += 1) {12657 while (i < rhs_len) : (i += 1) {
12602 types[i + lhs_len] = rhs_ty.structFieldType(i);12658 types[i + lhs_len] = rhs_ty.structFieldType(i, mod).toIntern();
12603 const default_val = rhs_ty.structFieldDefaultValue(i);12659 const default_val = rhs_ty.structFieldDefaultValue(i, mod);
12604 values[i + lhs_len] = default_val;12660 values[i + lhs_len] = default_val.toIntern();
12605 const operand_src = rhs_src; // TODO better source location12661 const operand_src = rhs_src; // TODO better source location
12606 if (default_val.tag() == .unreachable_value) {12662 if (default_val.toIntern() == .unreachable_value) {
12607 runtime_src = operand_src;12663 runtime_src = operand_src;
12664 values[i + lhs_len] = .none;
12608 }12665 }
12609 }12666 }
12610 break :rs runtime_src;12667 break :rs runtime_src;
12611 };12668 };
1261212669
12613 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{12670 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
12614 .types = types,12671 .types = types,
12615 .values = values,12672 .values = values,
12616 });12673 .names = &.{},
12674 } });
1261712675
12618 const runtime_src = opt_runtime_src orelse {12676 const runtime_src = opt_runtime_src orelse {
12619 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);12677 const tuple_val = try mod.intern(.{ .aggregate = .{
12620 return sema.addConstant(tuple_ty, tuple_val);12678 .ty = tuple_ty,
12679 .storage = .{ .elems = values },
12680 } });
12681 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
12621 };12682 };
1262212683
12623 try sema.requireRuntimeBlock(block, src, runtime_src);12684 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -12635,13 +12696,14 @@ fn analyzeTupleCat(...@@ -12635,13 +12696,14 @@ fn analyzeTupleCat(
12635 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);12696 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);
12636 }12697 }
1263712698
12638 return block.addAggregateInit(tuple_ty, element_refs);12699 return block.addAggregateInit(tuple_ty.toType(), element_refs);
12639}12700}
1264012701
12641fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {12702fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12642 const tracy = trace(@src());12703 const tracy = trace(@src());
12643 defer tracy.end();12704 defer tracy.end();
1264412705
12706 const mod = sema.mod;
12645 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;12707 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12646 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;12708 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
12647 const lhs = try sema.resolveInst(extra.lhs);12709 const lhs = try sema.resolveInst(extra.lhs);
...@@ -12650,8 +12712,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12650,8 +12712,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12650 const rhs_ty = sema.typeOf(rhs);12712 const rhs_ty = sema.typeOf(rhs);
12651 const src = inst_data.src();12713 const src = inst_data.src();
1265212714
12653 const lhs_is_tuple = lhs_ty.isTuple();12715 const lhs_is_tuple = lhs_ty.isTuple(mod);
12654 const rhs_is_tuple = rhs_ty.isTuple();12716 const rhs_is_tuple = rhs_ty.isTuple(mod);
12655 if (lhs_is_tuple and rhs_is_tuple) {12717 if (lhs_is_tuple and rhs_is_tuple) {
12656 return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs);12718 return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs);
12657 }12719 }
...@@ -12661,11 +12723,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12661,11 +12723,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1266112723
12662 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {12724 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {
12663 if (lhs_is_tuple) break :lhs_info @as(Type.ArrayInfo, undefined);12725 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)});
12665 };12727 };
12666 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {12728 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {
12667 assert(!rhs_is_tuple);12729 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)});
12669 };12731 };
1267012732
12671 const resolved_elem_ty = t: {12733 const resolved_elem_ty = t: {
...@@ -12727,73 +12789,71 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12727,73 +12789,71 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12727 ),12789 ),
12728 };12790 };
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);
12731 const ptr_addrspace = p: {12793 const ptr_addrspace = p: {
12732 if (lhs_ty.zigTypeTag() == .Pointer) break :p lhs_ty.ptrAddressSpace();12794 if (lhs_ty.zigTypeTag(mod) == .Pointer) break :p lhs_ty.ptrAddressSpace(mod);
12733 if (rhs_ty.zigTypeTag() == .Pointer) break :p rhs_ty.ptrAddressSpace();12795 if (rhs_ty.zigTypeTag(mod) == .Pointer) break :p rhs_ty.ptrAddressSpace(mod);
12734 break :p null;12796 break :p null;
12735 };12797 };
1273612798
12737 const runtime_src = if (switch (lhs_ty.zigTypeTag()) {12799 const runtime_src = if (switch (lhs_ty.zigTypeTag(mod)) {
12738 .Array, .Struct => try sema.resolveMaybeUndefVal(lhs),12800 .Array, .Struct => try sema.resolveMaybeUndefVal(lhs),
12739 .Pointer => try sema.resolveDefinedValue(block, lhs_src, lhs),12801 .Pointer => try sema.resolveDefinedValue(block, lhs_src, lhs),
12740 else => unreachable,12802 else => unreachable,
12741 }) |lhs_val| rs: {12803 }) |lhs_val| rs: {
12742 if (switch (rhs_ty.zigTypeTag()) {12804 if (switch (rhs_ty.zigTypeTag(mod)) {
12743 .Array, .Struct => try sema.resolveMaybeUndefVal(rhs),12805 .Array, .Struct => try sema.resolveMaybeUndefVal(rhs),
12744 .Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs),12806 .Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs),
12745 else => unreachable,12807 else => unreachable,
12746 }) |rhs_val| {12808 }) |rhs_val| {
12747 const lhs_sub_val = if (lhs_ty.isSinglePointer())12809 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
12748 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?12810 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
12749 else12811 else
12750 lhs_val;12812 lhs_val;
1275112813
12752 const rhs_sub_val = if (rhs_ty.isSinglePointer())12814 const rhs_sub_val = if (rhs_ty.isSinglePointer(mod))
12753 (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).?12815 (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).?
12754 else12816 else
12755 rhs_val;12817 rhs_val;
1275612818
12757 const final_len_including_sent = result_len + @boolToInt(res_sent_val != null);12819 const element_vals = try sema.arena.alloc(InternPool.Index, result_len);
12758 const element_vals = try sema.arena.alloc(Value, final_len_including_sent);
12759 var elem_i: usize = 0;12820 var elem_i: usize = 0;
12760 while (elem_i < lhs_len) : (elem_i += 1) {12821 while (elem_i < lhs_len) : (elem_i += 1) {
12761 const lhs_elem_i = elem_i;12822 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;12823 const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i, mod) 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);12824 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";
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;12825 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;
12765 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);12826 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
12766 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);12827 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
12767 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, "");12828 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);
12769 }12830 }
12770 while (elem_i < result_len) : (elem_i += 1) {12831 while (elem_i < result_len) : (elem_i += 1) {
12771 const rhs_elem_i = elem_i - lhs_len;12832 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;12833 const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i, mod) 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);12834 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";
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;12835 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;
12775 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);12836 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
12776 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);12837 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
12777 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, "");12838 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);
12779 }12840 }
12780 if (res_sent_val) |sent_val| {12841 return sema.addConstantMaybeRef(block, result_ty, (try mod.intern(.{ .aggregate = .{
12781 element_vals[result_len] = sent_val;12842 .ty = result_ty.toIntern(),
12782 }12843 .storage = .{ .elems = element_vals },
12783 const val = try Value.Tag.aggregate.create(sema.arena, element_vals);12844 } })).toValue(), ptr_addrspace != null);
12784 return sema.addConstantMaybeRef(block, result_ty, val, ptr_addrspace != null);
12785 } else break :rs rhs_src;12845 } else break :rs rhs_src;
12786 } else lhs_src;12846 } else lhs_src;
1278712847
12788 try sema.requireRuntimeBlock(block, src, runtime_src);12848 try sema.requireRuntimeBlock(block, src, runtime_src);
1278912849
12790 if (ptr_addrspace) |ptr_as| {12850 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, .{
12792 .pointee_type = result_ty,12852 .pointee_type = result_ty,
12793 .@"addrspace" = ptr_as,12853 .@"addrspace" = ptr_as,
12794 });12854 });
12795 const alloc = try block.addTy(.alloc, alloc_ty);12855 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, .{
12797 .pointee_type = resolved_elem_ty,12857 .pointee_type = resolved_elem_ty,
12798 .@"addrspace" = ptr_as,12858 .@"addrspace" = ptr_as,
12799 });12859 });
...@@ -12815,7 +12875,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12815,7 +12875,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12815 if (res_sent_val) |sent_val| {12875 if (res_sent_val) |sent_val| {
12816 const elem_index = try sema.addIntUnsigned(Type.usize, result_len);12876 const elem_index = try sema.addIntUnsigned(Type.usize, result_len);
12817 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);12877 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));
12819 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);12879 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
12820 }12880 }
1282112881
...@@ -12841,11 +12901,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12841,11 +12901,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12841}12901}
1284212902
12843fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, peer_ty: Type) !?Type.ArrayInfo {12903fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, peer_ty: Type) !?Type.ArrayInfo {
12904 const mod = sema.mod;
12844 const operand_ty = sema.typeOf(operand);12905 const operand_ty = sema.typeOf(operand);
12845 switch (operand_ty.zigTypeTag()) {12906 switch (operand_ty.zigTypeTag(mod)) {
12846 .Array => return operand_ty.arrayInfo(),12907 .Array => return operand_ty.arrayInfo(mod),
12847 .Pointer => {12908 .Pointer => {
12848 const ptr_info = operand_ty.ptrInfo().data;12909 const ptr_info = operand_ty.ptrInfo(mod);
12849 switch (ptr_info.size) {12910 switch (ptr_info.size) {
12850 // TODO: in the Many case here this should only work if the type12911 // TODO: in the Many case here this should only work if the type
12851 // has a sentinel, and this code should compute the length based12912 // 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...@@ -12855,24 +12916,24 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
12855 return Type.ArrayInfo{12916 return Type.ArrayInfo{
12856 .elem_type = ptr_info.pointee_type,12917 .elem_type = ptr_info.pointee_type,
12857 .sentinel = ptr_info.sentinel,12918 .sentinel = ptr_info.sentinel,
12858 .len = val.sliceLen(sema.mod),12919 .len = val.sliceLen(mod),
12859 };12920 };
12860 },12921 },
12861 .One => {12922 .One => {
12862 if (ptr_info.pointee_type.zigTypeTag() == .Array) {12923 if (ptr_info.pointee_type.zigTypeTag(mod) == .Array) {
12863 return ptr_info.pointee_type.arrayInfo();12924 return ptr_info.pointee_type.arrayInfo(mod);
12864 }12925 }
12865 },12926 },
12866 .C => {},12927 .C => {},
12867 }12928 }
12868 },12929 },
12869 .Struct => {12930 .Struct => {
12870 if (operand_ty.isTuple() and peer_ty.isIndexable()) {12931 if (operand_ty.isTuple(mod) and peer_ty.isIndexable(mod)) {
12871 assert(!peer_ty.isTuple());12932 assert(!peer_ty.isTuple(mod));
12872 return .{12933 return .{
12873 .elem_type = peer_ty.elemType2(),12934 .elem_type = peer_ty.elemType2(mod),
12874 .sentinel = null,12935 .sentinel = null,
12875 .len = operand_ty.arrayLen(),12936 .len = operand_ty.arrayLen(mod),
12876 };12937 };
12877 }12938 }
12878 },12939 },
...@@ -12886,52 +12947,54 @@ fn analyzeTupleMul(...@@ -12886,52 +12947,54 @@ fn analyzeTupleMul(
12886 block: *Block,12947 block: *Block,
12887 src_node: i32,12948 src_node: i32,
12888 operand: Air.Inst.Ref,12949 operand: Air.Inst.Ref,
12889 factor: u64,12950 factor: usize,
12890) CompileError!Air.Inst.Ref {12951) CompileError!Air.Inst.Ref {
12952 const mod = sema.mod;
12891 const operand_ty = sema.typeOf(operand);12953 const operand_ty = sema.typeOf(operand);
12892 const src = LazySrcLoc.nodeOffset(src_node);12954 const src = LazySrcLoc.nodeOffset(src_node);
12893 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };12955 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
12894 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };12956 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1289512957
12896 const tuple_len = operand_ty.structFieldCount();12958 const tuple_len = operand_ty.structFieldCount(mod);
12897 const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch12959 const final_len = std.math.mul(usize, tuple_len, factor) catch
12898 return sema.fail(block, rhs_src, "operation results in overflow", .{});12960 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1289912961
12900 if (final_len_u64 == 0) {12962 if (final_len == 0) {
12901 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));12963 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);
12902 }12964 }
12903 const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);12965 const types = try sema.arena.alloc(InternPool.Index, final_len);
1290412966 const values = try sema.arena.alloc(InternPool.Index, final_len);
12905 const types = try sema.arena.alloc(Type, final_len);
12906 const values = try sema.arena.alloc(Value, final_len);
1290712967
12908 const opt_runtime_src = rs: {12968 const opt_runtime_src = rs: {
12909 var runtime_src: ?LazySrcLoc = null;12969 var runtime_src: ?LazySrcLoc = null;
12910 var i: u32 = 0;12970 for (0..tuple_len) |i| {
12911 while (i < tuple_len) : (i += 1) {12971 types[i] = operand_ty.structFieldType(i, mod).toIntern();
12912 types[i] = operand_ty.structFieldType(i);12972 values[i] = operand_ty.structFieldDefaultValue(i, mod).toIntern();
12913 values[i] = operand_ty.structFieldDefaultValue(i);
12914 const operand_src = lhs_src; // TODO better source location12973 const operand_src = lhs_src; // TODO better source location
12915 if (values[i].tag() == .unreachable_value) {12974 if (values[i] == .unreachable_value) {
12916 runtime_src = operand_src;12975 runtime_src = operand_src;
12976 values[i] = .none; // TODO don't treat unreachable_value as special
12917 }12977 }
12918 }12978 }
12919 i = 0;12979 for (0..factor) |i| {
12920 while (i < factor) : (i += 1) {12980 mem.copyForwards(InternPool.Index, types[tuple_len * i ..], types[0..tuple_len]);
12921 mem.copyForwards(Type, types[tuple_len * i ..], types[0..tuple_len]);12981 mem.copyForwards(InternPool.Index, values[tuple_len * i ..], values[0..tuple_len]);
12922 mem.copyForwards(Value, values[tuple_len * i ..], values[0..tuple_len]);
12923 }12982 }
12924 break :rs runtime_src;12983 break :rs runtime_src;
12925 };12984 };
1292612985
12927 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{12986 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
12928 .types = types,12987 .types = types,
12929 .values = values,12988 .values = values,
12930 });12989 .names = &.{},
12990 } });
1293112991
12932 const runtime_src = opt_runtime_src orelse {12992 const runtime_src = opt_runtime_src orelse {
12933 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);12993 const tuple_val = try mod.intern(.{ .aggregate = .{
12934 return sema.addConstant(tuple_ty, tuple_val);12994 .ty = tuple_ty,
12995 .storage = .{ .elems = values },
12996 } });
12997 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
12935 };12998 };
1293612999
12937 try sema.requireRuntimeBlock(block, src, runtime_src);13000 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -12947,13 +13010,14 @@ fn analyzeTupleMul(...@@ -12947,13 +13010,14 @@ fn analyzeTupleMul(
12947 @memcpy(element_refs[tuple_len * i ..][0..tuple_len], element_refs[0..tuple_len]);13010 @memcpy(element_refs[tuple_len * i ..][0..tuple_len], element_refs[0..tuple_len]);
12948 }13011 }
1294913012
12950 return block.addAggregateInit(tuple_ty, element_refs);13013 return block.addAggregateInit(tuple_ty.toType(), element_refs);
12951}13014}
1295213015
12953fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13016fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12954 const tracy = trace(@src());13017 const tracy = trace(@src());
12955 defer tracy.end();13018 defer tracy.end();
1295613019
13020 const mod = sema.mod;
12957 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;13021 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12958 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;13022 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
12959 const lhs = try sema.resolveInst(extra.lhs);13023 const lhs = try sema.resolveInst(extra.lhs);
...@@ -12963,18 +13027,19 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12963,18 +13027,19 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12963 const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };13027 const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };
12964 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };13028 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
1296513029
12966 if (lhs_ty.isTuple()) {13030 if (lhs_ty.isTuple(mod)) {
12967 // In `**` rhs must be comptime-known, but lhs can be runtime-known13031 // In `**` rhs must be comptime-known, but lhs can be runtime-known
12968 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");13032 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);
12970 }13035 }
1297113036
12972 // Analyze the lhs first, to catch the case that someone tried to do exponentiation13037 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
12973 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {13038 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {
12974 const msg = msg: {13039 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)});
12976 errdefer msg.destroy(sema.gpa);13041 errdefer msg.destroy(sema.gpa);
12977 switch (lhs_ty.zigTypeTag()) {13042 switch (lhs_ty.zigTypeTag(mod)) {
12978 .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => {13043 .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => {
12979 try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{});13044 try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{});
12980 },13045 },
...@@ -12992,15 +13057,13 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12992,15 +13057,13 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12992 return sema.fail(block, rhs_src, "operation results in overflow", .{});13057 return sema.fail(block, rhs_src, "operation results in overflow", .{});
12993 const result_len = try sema.usizeCast(block, src, result_len_u64);13058 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;
12998 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);13063 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);
1299913064
13000 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {13065 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
13001 const final_len_including_sent = result_len + @boolToInt(lhs_info.sentinel != null);13066 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
13002
13003 const lhs_sub_val = if (lhs_ty.isSinglePointer())
13004 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?13067 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
13005 else13068 else
13006 lhs_val;13069 lhs_val;
...@@ -13008,38 +13071,41 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13008,38 +13071,41 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13008 const val = v: {13071 const val = v: {
13009 // Optimization for the common pattern of a single element repeated N times, such13072 // Optimization for the common pattern of a single element repeated N times, such
13010 // as zero-filling a byte array.13073 // as zero-filling a byte array.
13011 if (lhs_len == 1) {13074 if (lhs_len == 1 and lhs_info.sentinel == null) {
13012 const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, 0);13075 const elem_val = try lhs_sub_val.elemValue(mod, 0);
13013 break :v try Value.Tag.repeated.create(sema.arena, elem_val);13076 break :v try mod.intern(.{ .aggregate = .{
13077 .ty = result_ty.toIntern(),
13078 .storage = .{ .repeated_elem = elem_val.toIntern() },
13079 } });
13014 }13080 }
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);
13017 var elem_i: usize = 0;13083 var elem_i: usize = 0;
13018 while (elem_i < result_len) {13084 while (elem_i < result_len) {
13019 var lhs_i: usize = 0;13085 var lhs_i: usize = 0;
13020 while (lhs_i < lhs_len) : (lhs_i += 1) {13086 while (lhs_i < lhs_len) : (lhs_i += 1) {
13021 const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_i);13087 const elem_val = try lhs_sub_val.elemValue(mod, lhs_i);
13022 element_vals[elem_i] = elem_val;13088 element_vals[elem_i] = elem_val.toIntern();
13023 elem_i += 1;13089 elem_i += 1;
13024 }13090 }
13025 }13091 }
13026 if (lhs_info.sentinel) |sent_val| {13092 break :v try mod.intern(.{ .aggregate = .{
13027 element_vals[result_len] = sent_val;13093 .ty = result_ty.toIntern(),
13028 }13094 .storage = .{ .elems = element_vals },
13029 break :v try Value.Tag.aggregate.create(sema.arena, element_vals);13095 } });
13030 };13096 };
13031 return sema.addConstantMaybeRef(block, result_ty, val, ptr_addrspace != null);13097 return sema.addConstantMaybeRef(block, result_ty, val.toValue(), ptr_addrspace != null);
13032 }13098 }
1303313099
13034 try sema.requireRuntimeBlock(block, src, lhs_src);13100 try sema.requireRuntimeBlock(block, src, lhs_src);
1303513101
13036 if (ptr_addrspace) |ptr_as| {13102 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, .{
13038 .pointee_type = result_ty,13104 .pointee_type = result_ty,
13039 .@"addrspace" = ptr_as,13105 .@"addrspace" = ptr_as,
13040 });13106 });
13041 const alloc = try block.addTy(.alloc, alloc_ty);13107 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, .{
13043 .pointee_type = lhs_info.elem_type,13109 .pointee_type = lhs_info.elem_type,
13044 .@"addrspace" = ptr_as,13110 .@"addrspace" = ptr_as,
13045 });13111 });
...@@ -13082,6 +13148,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13082,6 +13148,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13082}13148}
1308313149
13084fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13150fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13151 const mod = sema.mod;
13085 const inst_data = sema.code.instructions.items(.data)[inst].un_node;13152 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
13086 const src = inst_data.src();13153 const src = inst_data.src();
13087 const lhs_src = src;13154 const lhs_src = src;
...@@ -13089,34 +13156,31 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13089,34 +13156,31 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1308913156
13090 const rhs = try sema.resolveInst(inst_data.operand);13157 const rhs = try sema.resolveInst(inst_data.operand);
13091 const rhs_ty = sema.typeOf(rhs);13158 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)) {
13095 .Int, .ComptimeInt, .Float, .ComptimeFloat => false,13162 .Int, .ComptimeInt, .Float, .ComptimeFloat => false,
13096 else => true,13163 else => true,
13097 }) {13164 }) {
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)});
13099 }13166 }
1310013167
13101 if (rhs_scalar_ty.isAnyFloat()) {13168 if (rhs_scalar_ty.isAnyFloat()) {
13102 // We handle float negation here to ensure negative zero is represented in the bits.13169 // We handle float negation here to ensure negative zero is represented in the bits.
13103 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {13170 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
13104 if (rhs_val.isUndef()) return sema.addConstUndef(rhs_ty);13171 if (rhs_val.isUndef(mod)) return sema.addConstUndef(rhs_ty);
13105 return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, sema.mod));13172 return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, mod));
13106 }13173 }
13107 try sema.requireRuntimeBlock(block, src, null);13174 try sema.requireRuntimeBlock(block, src, null);
13108 return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);13175 return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);
13109 }13176 }
1311013177
13111 const lhs = if (rhs_ty.zigTypeTag() == .Vector)13178 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
13112 try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
13113 else
13114 try sema.resolveInst(.zero);
13115
13116 return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);13179 return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
13117}13180}
1311813181
13119fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13182fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13183 const mod = sema.mod;
13120 const inst_data = sema.code.instructions.items(.data)[inst].un_node;13184 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
13121 const src = inst_data.src();13185 const src = inst_data.src();
13122 const lhs_src = src;13186 const lhs_src = src;
...@@ -13124,18 +13188,14 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -13124,18 +13188,14 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1312413188
13125 const rhs = try sema.resolveInst(inst_data.operand);13189 const rhs = try sema.resolveInst(inst_data.operand);
13126 const rhs_ty = sema.typeOf(rhs);13190 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)) {
13130 .Int, .ComptimeInt, .Float, .ComptimeFloat => {},13194 .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)}),
13132 }13196 }
1313313197
13134 const lhs = if (rhs_ty.zigTypeTag() == .Vector)13198 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
13135 try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
13136 else
13137 try sema.resolveInst(.zero);
13138
13139 return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);13199 return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
13140}13200}
1314113201
...@@ -13161,6 +13221,7 @@ fn zirArithmetic(...@@ -13161,6 +13221,7 @@ fn zirArithmetic(
13161}13221}
1316213222
13163fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13223fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13224 const mod = sema.mod;
13164 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;13225 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13165 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };13226 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
13166 sema.src = src;13227 sema.src = src;
...@@ -13171,8 +13232,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13171,8 +13232,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13171 const rhs = try sema.resolveInst(extra.rhs);13232 const rhs = try sema.resolveInst(extra.rhs);
13172 const lhs_ty = sema.typeOf(lhs);13233 const lhs_ty = sema.typeOf(lhs);
13173 const rhs_ty = sema.typeOf(rhs);13234 const rhs_ty = sema.typeOf(rhs);
13174 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13235 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13175 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13236 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
13176 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13237 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13177 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);13238 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...@@ -13181,25 +13242,22 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13181 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13242 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13182 });13243 });
1318313244
13184 const is_vector = resolved_type.zigTypeTag() == .Vector;
13185
13186 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13245 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13187 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13246 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1318813247
13189 const lhs_scalar_ty = lhs_ty.scalarType();13248 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13190 const rhs_scalar_ty = rhs_ty.scalarType();13249 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13191 const scalar_tag = resolved_type.scalarType().zigTypeTag();13250 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1319213251
13193 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;13252 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1319413253
13195 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div);13254 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div);
1319613255
13197 const mod = sema.mod;
13198 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);13256 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
13199 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);13257 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1320013258
13201 if ((lhs_ty.zigTypeTag() == .ComptimeFloat and rhs_ty.zigTypeTag() == .ComptimeInt) or13259 if ((lhs_ty.zigTypeTag(mod) == .ComptimeFloat and rhs_ty.zigTypeTag(mod) == .ComptimeInt) or
13202 (lhs_ty.zigTypeTag() == .ComptimeInt and rhs_ty.zigTypeTag() == .ComptimeFloat))13260 (lhs_ty.zigTypeTag(mod) == .ComptimeInt and rhs_ty.zigTypeTag(mod) == .ComptimeFloat))
13203 {13261 {
13204 // If it makes a difference whether we coerce to ints or floats before doing the division, error.13262 // If it makes a difference whether we coerce to ints or floats before doing the division, error.
13205 // If lhs % rhs is 0, it doesn't matter.13263 // 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...@@ -13207,9 +13265,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13207 const rhs_val = maybe_rhs_val orelse unreachable;13265 const rhs_val = maybe_rhs_val orelse unreachable;
13208 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;13266 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;
13209 if (!rem.compareAllWithZero(.eq, mod)) {13267 if (!rem.compareAllWithZero(.eq, mod)) {
13210 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{13268 return sema.fail(
13211 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),13269 block,
13212 });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 );
13213 }13274 }
13214 }13275 }
1321513276
...@@ -13243,17 +13304,20 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13243,17 +13304,20 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13243 switch (scalar_tag) {13304 switch (scalar_tag) {
13244 .Int, .ComptimeInt, .ComptimeFloat => {13305 .Int, .ComptimeInt, .ComptimeFloat => {
13245 if (maybe_lhs_val) |lhs_val| {13306 if (maybe_lhs_val) |lhs_val| {
13246 if (!lhs_val.isUndef()) {13307 if (!lhs_val.isUndef(mod)) {
13247 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {13308 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13248 const zero_val = if (is_vector) b: {13309 const scalar_zero = switch (scalar_tag) {
13249 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13310 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13250 } else Value.zero;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);
13251 return sema.addConstant(resolved_type, zero_val);13315 return sema.addConstant(resolved_type, zero_val);
13252 }13316 }
13253 }13317 }
13254 }13318 }
13255 if (maybe_rhs_val) |rhs_val| {13319 if (maybe_rhs_val) |rhs_val| {
13256 if (rhs_val.isUndef()) {13320 if (rhs_val.isUndef(mod)) {
13257 return sema.failWithUseOfUndef(block, rhs_src);13321 return sema.failWithUseOfUndef(block, rhs_src);
13258 }13322 }
13259 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {13323 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -13267,10 +13331,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13267,10 +13331,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1326713331
13268 const runtime_src = rs: {13332 const runtime_src = rs: {
13269 if (maybe_lhs_val) |lhs_val| {13333 if (maybe_lhs_val) |lhs_val| {
13270 if (lhs_val.isUndef()) {13334 if (lhs_val.isUndef(mod)) {
13271 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {13335 if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
13272 if (maybe_rhs_val) |rhs_val| {13336 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)) {
13274 return sema.addConstUndef(resolved_type);13338 return sema.addConstUndef(resolved_type);
13275 }13339 }
13276 }13340 }
...@@ -13281,10 +13345,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13281,10 +13345,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1328113345
13282 if (maybe_rhs_val) |rhs_val| {13346 if (maybe_rhs_val) |rhs_val| {
13283 if (is_int) {13347 if (is_int) {
13284 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);13348 var overflow_idx: ?usize = null;
13285 var vector_index: usize = undefined;13349 const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
13286 if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) {13350 if (overflow_idx) |vec_idx| {
13287 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index);13351 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx);
13288 }13352 }
13289 return sema.addConstant(resolved_type, res);13353 return sema.addConstant(resolved_type, res);
13290 } else {13354 } else {
...@@ -13309,8 +13373,13 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13309,8 +13373,13 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13309 }13373 }
1331013374
13311 const air_tag = if (is_int) blk: {13375 const air_tag = if (is_int) blk: {
13312 if (lhs_ty.isSignedInt() or rhs_ty.isSignedInt()) {13376 if (lhs_ty.isSignedInt(mod) or rhs_ty.isSignedInt(mod)) {
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()) });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 );
13314 }13383 }
13315 break :blk Air.Inst.Tag.div_trunc;13384 break :blk Air.Inst.Tag.div_trunc;
13316 } else switch (block.float_mode) {13385 } else switch (block.float_mode) {
...@@ -13321,6 +13390,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13321,6 +13390,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13321}13390}
1332213391
13323fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13392fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13393 const mod = sema.mod;
13324 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;13394 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13325 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };13395 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
13326 sema.src = src;13396 sema.src = src;
...@@ -13331,8 +13401,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13331,8 +13401,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13331 const rhs = try sema.resolveInst(extra.rhs);13401 const rhs = try sema.resolveInst(extra.rhs);
13332 const lhs_ty = sema.typeOf(lhs);13402 const lhs_ty = sema.typeOf(lhs);
13333 const rhs_ty = sema.typeOf(rhs);13403 const rhs_ty = sema.typeOf(rhs);
13334 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13404 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13335 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13405 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
13336 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13406 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13337 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);13407 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1333813408
...@@ -13341,19 +13411,16 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13341,19 +13411,16 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13341 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13411 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13342 });13412 });
1334313413
13344 const is_vector = resolved_type.zigTypeTag() == .Vector;
13345
13346 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13414 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13347 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13415 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1334813416
13349 const lhs_scalar_ty = lhs_ty.scalarType();13417 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13350 const scalar_tag = resolved_type.scalarType().zigTypeTag();13418 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1335113419
13352 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;13420 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1335313421
13354 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact);13422 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact);
1335513423
13356 const mod = sema.mod;
13357 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);13424 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
13358 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);13425 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...@@ -13375,19 +13442,22 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13375 // If the lhs is undefined, compile error because there is a possible13442 // If the lhs is undefined, compile error because there is a possible
13376 // value for which the division would result in a remainder.13443 // value for which the division would result in a remainder.
13377 if (maybe_lhs_val) |lhs_val| {13444 if (maybe_lhs_val) |lhs_val| {
13378 if (lhs_val.isUndef()) {13445 if (lhs_val.isUndef(mod)) {
13379 return sema.failWithUseOfUndef(block, rhs_src);13446 return sema.failWithUseOfUndef(block, rhs_src);
13380 } else {13447 } else {
13381 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {13448 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13382 const zero_val = if (is_vector) b: {13449 const scalar_zero = switch (scalar_tag) {
13383 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13450 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13384 } else Value.zero;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);
13385 return sema.addConstant(resolved_type, zero_val);13455 return sema.addConstant(resolved_type, zero_val);
13386 }13456 }
13387 }13457 }
13388 }13458 }
13389 if (maybe_rhs_val) |rhs_val| {13459 if (maybe_rhs_val) |rhs_val| {
13390 if (rhs_val.isUndef()) {13460 if (rhs_val.isUndef(mod)) {
13391 return sema.failWithUseOfUndef(block, rhs_src);13461 return sema.failWithUseOfUndef(block, rhs_src);
13392 }13462 }
13393 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {13463 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -13402,10 +13472,10 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13402,10 +13472,10 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13402 if (!(modulus_val.compareAllWithZero(.eq, mod))) {13472 if (!(modulus_val.compareAllWithZero(.eq, mod))) {
13403 return sema.fail(block, src, "exact division produced remainder", .{});13473 return sema.fail(block, src, "exact division produced remainder", .{});
13404 }13474 }
13405 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);13475 var overflow_idx: ?usize = null;
13406 var vector_index: usize = undefined;13476 const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
13407 if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) {13477 if (overflow_idx) |vec_idx| {
13408 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index);13478 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx);
13409 }13479 }
13410 return sema.addConstant(resolved_type, res);13480 return sema.addConstant(resolved_type, res);
13411 } else {13481 } else {
...@@ -13437,7 +13507,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13437,7 +13507,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13437 const ok = if (!is_int) ok: {13507 const ok = if (!is_int) ok: {
13438 const floored = try block.addUnOp(.floor, result);13508 const floored = try block.addUnOp(.floor, result);
1343913509
13440 if (resolved_type.zigTypeTag() == .Vector) {13510 if (resolved_type.zigTypeTag(mod) == .Vector) {
13441 const eql = try block.addCmpVector(result, floored, .eq);13511 const eql = try block.addCmpVector(result, floored, .eq);
13442 break :ok try block.addInst(.{13512 break :ok try block.addInst(.{
13443 .tag = switch (block.float_mode) {13513 .tag = switch (block.float_mode) {
...@@ -13459,8 +13529,13 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13459,8 +13529,13 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13459 } else ok: {13529 } else ok: {
13460 const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);13530 const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);
1346113531
13462 if (resolved_type.zigTypeTag() == .Vector) {13532 const scalar_zero = switch (scalar_tag) {
13463 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);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);
13464 const zero = try sema.addConstant(resolved_type, zero_val);13539 const zero = try sema.addConstant(resolved_type, zero_val);
13465 const eql = try block.addCmpVector(remainder, zero, .eq);13540 const eql = try block.addCmpVector(remainder, zero, .eq);
13466 break :ok try block.addInst(.{13541 break :ok try block.addInst(.{
...@@ -13471,7 +13546,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13471,7 +13546,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13471 } },13546 } },
13472 });13547 });
13473 } else {13548 } else {
13474 const zero = try sema.addConstant(resolved_type, Value.zero);13549 const zero = try sema.addConstant(resolved_type, scalar_zero);
13475 const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);13550 const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
13476 break :ok is_in_range;13551 break :ok is_in_range;
13477 }13552 }
...@@ -13484,6 +13559,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13484,6 +13559,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13484}13559}
1348513560
13486fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13561fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13562 const mod = sema.mod;
13487 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;13563 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13488 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };13564 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
13489 sema.src = src;13565 sema.src = src;
...@@ -13494,8 +13570,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13494,8 +13570,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13494 const rhs = try sema.resolveInst(extra.rhs);13570 const rhs = try sema.resolveInst(extra.rhs);
13495 const lhs_ty = sema.typeOf(lhs);13571 const lhs_ty = sema.typeOf(lhs);
13496 const rhs_ty = sema.typeOf(rhs);13572 const rhs_ty = sema.typeOf(rhs);
13497 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13573 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13498 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13574 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
13499 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13575 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13500 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);13576 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1350113577
...@@ -13504,20 +13580,17 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13504,20 +13580,17 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13504 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13580 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13505 });13581 });
1350613582
13507 const is_vector = resolved_type.zigTypeTag() == .Vector;
13508
13509 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13583 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13510 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13584 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1351113585
13512 const lhs_scalar_ty = lhs_ty.scalarType();13586 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13513 const rhs_scalar_ty = rhs_ty.scalarType();13587 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13514 const scalar_tag = resolved_type.scalarType().zigTypeTag();13588 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1351513589
13516 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;13590 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1351713591
13518 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor);13592 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor);
1351913593
13520 const mod = sema.mod;
13521 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);13594 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
13522 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);13595 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...@@ -13542,17 +13615,20 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13542 // value (zero) for which the division would be illegal behavior.13615 // value (zero) for which the division would be illegal behavior.
13543 // If the lhs is undefined, result is undefined.13616 // If the lhs is undefined, result is undefined.
13544 if (maybe_lhs_val) |lhs_val| {13617 if (maybe_lhs_val) |lhs_val| {
13545 if (!lhs_val.isUndef()) {13618 if (!lhs_val.isUndef(mod)) {
13546 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {13619 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13547 const zero_val = if (is_vector) b: {13620 const scalar_zero = switch (scalar_tag) {
13548 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13621 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13549 } else Value.zero;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);
13550 return sema.addConstant(resolved_type, zero_val);13626 return sema.addConstant(resolved_type, zero_val);
13551 }13627 }
13552 }13628 }
13553 }13629 }
13554 if (maybe_rhs_val) |rhs_val| {13630 if (maybe_rhs_val) |rhs_val| {
13555 if (rhs_val.isUndef()) {13631 if (rhs_val.isUndef(mod)) {
13556 return sema.failWithUseOfUndef(block, rhs_src);13632 return sema.failWithUseOfUndef(block, rhs_src);
13557 }13633 }
13558 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {13634 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -13561,10 +13637,10 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13561,10 +13637,10 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13561 // TODO: if the RHS is one, return the LHS directly13637 // TODO: if the RHS is one, return the LHS directly
13562 }13638 }
13563 if (maybe_lhs_val) |lhs_val| {13639 if (maybe_lhs_val) |lhs_val| {
13564 if (lhs_val.isUndef()) {13640 if (lhs_val.isUndef(mod)) {
13565 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {13641 if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
13566 if (maybe_rhs_val) |rhs_val| {13642 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)) {
13568 return sema.addConstUndef(resolved_type);13644 return sema.addConstUndef(resolved_type);
13569 }13645 }
13570 }13646 }
...@@ -13600,6 +13676,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13600,6 +13676,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13600}13676}
1360113677
13602fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13678fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13679 const mod = sema.mod;
13603 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;13680 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13604 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };13681 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
13605 sema.src = src;13682 sema.src = src;
...@@ -13610,8 +13687,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13610,8 +13687,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13610 const rhs = try sema.resolveInst(extra.rhs);13687 const rhs = try sema.resolveInst(extra.rhs);
13611 const lhs_ty = sema.typeOf(lhs);13688 const lhs_ty = sema.typeOf(lhs);
13612 const rhs_ty = sema.typeOf(rhs);13689 const rhs_ty = sema.typeOf(rhs);
13613 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13690 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13614 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13691 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
13615 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13692 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13616 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);13693 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1361713694
...@@ -13620,20 +13697,17 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13620,20 +13697,17 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13620 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13697 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13621 });13698 });
1362213699
13623 const is_vector = resolved_type.zigTypeTag() == .Vector;
13624
13625 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13700 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13626 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13701 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1362713702
13628 const lhs_scalar_ty = lhs_ty.scalarType();13703 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13629 const rhs_scalar_ty = rhs_ty.scalarType();13704 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13630 const scalar_tag = resolved_type.scalarType().zigTypeTag();13705 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1363113706
13632 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;13707 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1363313708
13634 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc);13709 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc);
1363513710
13636 const mod = sema.mod;
13637 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);13711 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
13638 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);13712 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...@@ -13658,17 +13732,20 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13658 // value (zero) for which the division would be illegal behavior.13732 // value (zero) for which the division would be illegal behavior.
13659 // If the lhs is undefined, result is undefined.13733 // If the lhs is undefined, result is undefined.
13660 if (maybe_lhs_val) |lhs_val| {13734 if (maybe_lhs_val) |lhs_val| {
13661 if (!lhs_val.isUndef()) {13735 if (!lhs_val.isUndef(mod)) {
13662 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {13736 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13663 const zero_val = if (is_vector) b: {13737 const scalar_zero = switch (scalar_tag) {
13664 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13738 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13665 } else Value.zero;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);
13666 return sema.addConstant(resolved_type, zero_val);13743 return sema.addConstant(resolved_type, zero_val);
13667 }13744 }
13668 }13745 }
13669 }13746 }
13670 if (maybe_rhs_val) |rhs_val| {13747 if (maybe_rhs_val) |rhs_val| {
13671 if (rhs_val.isUndef()) {13748 if (rhs_val.isUndef(mod)) {
13672 return sema.failWithUseOfUndef(block, rhs_src);13749 return sema.failWithUseOfUndef(block, rhs_src);
13673 }13750 }
13674 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {13751 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -13676,10 +13753,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13676,10 +13753,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13676 }13753 }
13677 }13754 }
13678 if (maybe_lhs_val) |lhs_val| {13755 if (maybe_lhs_val) |lhs_val| {
13679 if (lhs_val.isUndef()) {13756 if (lhs_val.isUndef(mod)) {
13680 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {13757 if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
13681 if (maybe_rhs_val) |rhs_val| {13758 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)) {
13683 return sema.addConstUndef(resolved_type);13760 return sema.addConstUndef(resolved_type);
13684 }13761 }
13685 }13762 }
...@@ -13690,10 +13767,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13690,10 +13767,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1369013767
13691 if (maybe_rhs_val) |rhs_val| {13768 if (maybe_rhs_val) |rhs_val| {
13692 if (is_int) {13769 if (is_int) {
13693 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);13770 var overflow_idx: ?usize = null;
13694 var vector_index: usize = undefined;13771 const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
13695 if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) {13772 if (overflow_idx) |vec_idx| {
13696 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index);13773 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx);
13697 }13774 }
13698 return sema.addConstant(resolved_type, res);13775 return sema.addConstant(resolved_type, res);
13699 } else {13776 } else {
...@@ -13727,39 +13804,34 @@ fn addDivIntOverflowSafety(...@@ -13727,39 +13804,34 @@ fn addDivIntOverflowSafety(
13727 casted_rhs: Air.Inst.Ref,13804 casted_rhs: Air.Inst.Ref,
13728 is_int: bool,13805 is_int: bool,
13729) CompileError!void {13806) CompileError!void {
13807 const mod = sema.mod;
13730 if (!is_int) return;13808 if (!is_int) return;
1373113809
13732 // If the LHS is unsigned, it cannot cause overflow.13810 // If the LHS is unsigned, it cannot cause overflow.
13733 if (!lhs_scalar_ty.isSignedInt()) return;13811 if (!lhs_scalar_ty.isSignedInt(mod)) return;
13734
13735 const mod = sema.mod;
13736 const target = mod.getTarget();
1373713812
13738 // If the LHS is widened to a larger integer type, no overflow is possible.13813 // 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) {
13740 return;13815 return;
13741 }13816 }
1374213817
13743 const min_int = try resolved_type.minInt(sema.arena, target);13818 const min_int = try resolved_type.minInt(mod, resolved_type);
13744 const neg_one_scalar = try Value.Tag.int_i64.create(sema.arena, -1);13819 const neg_one_scalar = try mod.intValue(lhs_scalar_ty, -1);
13745 const neg_one = if (resolved_type.zigTypeTag() == .Vector)13820 const neg_one = try sema.splat(resolved_type, neg_one_scalar);
13746 try Value.Tag.repeated.create(sema.arena, neg_one_scalar)
13747 else
13748 neg_one_scalar;
1374913821
13750 // If the LHS is comptime-known to be not equal to the min int,13822 // If the LHS is comptime-known to be not equal to the min int,
13751 // no overflow is possible.13823 // no overflow is possible.
13752 if (maybe_lhs_val) |lhs_val| {13824 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;
13754 }13826 }
1375513827
13756 // If the RHS is comptime-known to not be equal to -1, no overflow is possible.13828 // If the RHS is comptime-known to not be equal to -1, no overflow is possible.
13757 if (maybe_rhs_val) |rhs_val| {13829 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;
13759 }13831 }
1376013832
13761 var ok: Air.Inst.Ref = .none;13833 var ok: Air.Inst.Ref = .none;
13762 if (resolved_type.zigTypeTag() == .Vector) {13834 if (resolved_type.zigTypeTag(mod) == .Vector) {
13763 if (maybe_lhs_val == null) {13835 if (maybe_lhs_val == null) {
13764 const min_int_ref = try sema.addConstant(resolved_type, min_int);13836 const min_int_ref = try sema.addConstant(resolved_type, min_int);
13765 ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq);13837 ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq);
...@@ -13815,8 +13887,13 @@ fn addDivByZeroSafety(...@@ -13815,8 +13887,13 @@ fn addDivByZeroSafety(
13815 // emitted above.13887 // emitted above.
13816 if (maybe_rhs_val != null) return;13888 if (maybe_rhs_val != null) return;
1381713889
13818 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {13890 const mod = sema.mod;
13819 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);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);
13820 const zero = try sema.addConstant(resolved_type, zero_val);13897 const zero = try sema.addConstant(resolved_type, zero_val);
13821 const ok = try block.addCmpVector(casted_rhs, zero, .neq);13898 const ok = try block.addCmpVector(casted_rhs, zero, .neq);
13822 break :ok try block.addInst(.{13899 break :ok try block.addInst(.{
...@@ -13827,7 +13904,7 @@ fn addDivByZeroSafety(...@@ -13827,7 +13904,7 @@ fn addDivByZeroSafety(
13827 } },13904 } },
13828 });13905 });
13829 } else ok: {13906 } else ok: {
13830 const zero = try sema.addConstant(resolved_type, Value.zero);13907 const zero = try sema.addConstant(resolved_type, scalar_zero);
13831 break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);13908 break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);
13832 };13909 };
13833 try sema.addSafetyCheck(block, ok, .divide_by_zero);13910 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...@@ -13842,6 +13919,7 @@ fn airTag(block: *Block, is_int: bool, normal: Air.Inst.Tag, optimized: Air.Inst
13842}13919}
1384313920
13844fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13921fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13922 const mod = sema.mod;
13845 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;13923 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13846 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };13924 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
13847 sema.src = src;13925 sema.src = src;
...@@ -13852,8 +13930,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13852,8 +13930,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13852 const rhs = try sema.resolveInst(extra.rhs);13930 const rhs = try sema.resolveInst(extra.rhs);
13853 const lhs_ty = sema.typeOf(lhs);13931 const lhs_ty = sema.typeOf(lhs);
13854 const rhs_ty = sema.typeOf(rhs);13932 const rhs_ty = sema.typeOf(rhs);
13855 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13933 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13856 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13934 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
13857 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13935 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13858 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);13936 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1385913937
...@@ -13862,20 +13940,19 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13862,20 +13940,19 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13862 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },13940 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13863 });13941 });
1386413942
13865 const is_vector = resolved_type.zigTypeTag() == .Vector;13943 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
1386613944
13867 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);13945 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
13868 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);13946 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1386913947
13870 const lhs_scalar_ty = lhs_ty.scalarType();13948 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13871 const rhs_scalar_ty = rhs_ty.scalarType();13949 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13872 const scalar_tag = resolved_type.scalarType().zigTypeTag();13950 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1387313951
13874 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;13952 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1387513953
13876 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem);13954 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem);
1387713955
13878 const mod = sema.mod;
13879 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);13956 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
13880 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);13957 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....@@ -13895,20 +13972,26 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13895 // then emit a compile error saying you have to pick one.13972 // then emit a compile error saying you have to pick one.
13896 if (is_int) {13973 if (is_int) {
13897 if (maybe_lhs_val) |lhs_val| {13974 if (maybe_lhs_val) |lhs_val| {
13898 if (lhs_val.isUndef()) {13975 if (lhs_val.isUndef(mod)) {
13899 return sema.failWithUseOfUndef(block, lhs_src);13976 return sema.failWithUseOfUndef(block, lhs_src);
13900 }13977 }
13901 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {13978 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13902 const zero_val = if (is_vector) b: {13979 const scalar_zero = switch (scalar_tag) {
13903 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13980 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13904 } else Value.zero;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;
13905 return sema.addConstant(resolved_type, zero_val);13988 return sema.addConstant(resolved_type, zero_val);
13906 }13989 }
13907 } else if (lhs_scalar_ty.isSignedInt()) {13990 } else if (lhs_scalar_ty.isSignedInt(mod)) {
13908 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);13991 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
13909 }13992 }
13910 if (maybe_rhs_val) |rhs_val| {13993 if (maybe_rhs_val) |rhs_val| {
13911 if (rhs_val.isUndef()) {13994 if (rhs_val.isUndef(mod)) {
13912 return sema.failWithUseOfUndef(block, rhs_src);13995 return sema.failWithUseOfUndef(block, rhs_src);
13913 }13996 }
13914 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {13997 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -13929,7 +14012,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13929,7 +14012,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13929 return sema.addConstant(resolved_type, rem_result);14012 return sema.addConstant(resolved_type, rem_result);
13930 }14013 }
13931 break :rs lhs_src;14014 break :rs lhs_src;
13932 } else if (rhs_scalar_ty.isSignedInt()) {14015 } else if (rhs_scalar_ty.isSignedInt(mod)) {
13933 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);14016 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
13934 } else {14017 } else {
13935 break :rs rhs_src;14018 break :rs rhs_src;
...@@ -13937,7 +14020,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13937,7 +14020,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13937 }14020 }
13938 // float operands14021 // float operands
13939 if (maybe_rhs_val) |rhs_val| {14022 if (maybe_rhs_val) |rhs_val| {
13940 if (rhs_val.isUndef()) {14023 if (rhs_val.isUndef(mod)) {
13941 return sema.failWithUseOfUndef(block, rhs_src);14024 return sema.failWithUseOfUndef(block, rhs_src);
13942 }14025 }
13943 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {14026 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -13947,7 +14030,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13947,7 +14030,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13947 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);14030 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
13948 }14031 }
13949 if (maybe_lhs_val) |lhs_val| {14032 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))) {
13951 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);14034 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
13952 }14035 }
13953 return sema.addConstant(14036 return sema.addConstant(
...@@ -13978,32 +14061,31 @@ fn intRem(...@@ -13978,32 +14061,31 @@ fn intRem(
13978 lhs: Value,14061 lhs: Value,
13979 rhs: Value,14062 rhs: Value,
13980) CompileError!Value {14063) CompileError!Value {
13981 if (ty.zigTypeTag() == .Vector) {14064 const mod = sema.mod;
13982 const result_data = try sema.arena.alloc(Value, ty.vectorLen());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);
13983 for (result_data, 0..) |*scalar, i| {14068 for (result_data, 0..) |*scalar, i| {
13984 var lhs_buf: Value.ElemValueBuffer = undefined;14069 const lhs_elem = try lhs.elemValue(mod, i);
13985 var rhs_buf: Value.ElemValueBuffer = undefined;14070 const rhs_elem = try rhs.elemValue(mod, i);
13986 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);14071 scalar.* = try (try sema.intRemScalar(lhs_elem, rhs_elem, scalar_ty)).intern(scalar_ty, mod);
13987 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
13988 scalar.* = try sema.intRemScalar(lhs_elem, rhs_elem);
13989 }14072 }
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();
13991 }14077 }
13992 return sema.intRemScalar(lhs, rhs);14078 return sema.intRemScalar(lhs, rhs, ty);
13993}14079}
1399414080
13995fn intRemScalar(14081fn intRemScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) CompileError!Value {
13996 sema: *Sema,14082 const mod = sema.mod;
13997 lhs: Value,
13998 rhs: Value,
13999) CompileError!Value {
14000 const target = sema.mod.getTarget();
14001 // TODO is this a performance issue? maybe we should try the operation without14083 // TODO is this a performance issue? maybe we should try the operation without
14002 // resorting to BigInt first.14084 // resorting to BigInt first.
14003 var lhs_space: Value.BigIntSpace = undefined;14085 var lhs_space: Value.BigIntSpace = undefined;
14004 var rhs_space: Value.BigIntSpace = undefined;14086 var rhs_space: Value.BigIntSpace = undefined;
14005 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);14087 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
14006 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);14088 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
14007 const limbs_q = try sema.arena.alloc(14089 const limbs_q = try sema.arena.alloc(
14008 math.big.Limb,14090 math.big.Limb,
14009 lhs_bigint.limbs.len,14091 lhs_bigint.limbs.len,
...@@ -14021,10 +14103,11 @@ fn intRemScalar(...@@ -14021,10 +14103,11 @@ fn intRemScalar(
14021 var result_q = math.big.int.Mutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };14103 var result_q = math.big.int.Mutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
14022 var result_r = math.big.int.Mutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };14104 var result_r = math.big.int.Mutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
14023 result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);14105 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());
14025}14107}
1402614108
14027fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {14109fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
14110 const mod = sema.mod;
14028 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;14111 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
14029 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };14112 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
14030 sema.src = src;14113 sema.src = src;
...@@ -14035,8 +14118,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -14035,8 +14118,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14035 const rhs = try sema.resolveInst(extra.rhs);14118 const rhs = try sema.resolveInst(extra.rhs);
14036 const lhs_ty = sema.typeOf(lhs);14119 const lhs_ty = sema.typeOf(lhs);
14037 const rhs_ty = sema.typeOf(rhs);14120 const rhs_ty = sema.typeOf(rhs);
14038 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();14121 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
14039 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();14122 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
14040 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14123 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14041 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);14124 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...@@ -14048,13 +14131,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14048 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14131 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14049 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14132 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
14053 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;14136 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1405414137
14055 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod);14138 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod);
1405614139
14057 const mod = sema.mod;
14058 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);14140 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
14059 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);14141 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...@@ -14072,12 +14154,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14072 // If the lhs is undefined, result is undefined.14154 // If the lhs is undefined, result is undefined.
14073 if (is_int) {14155 if (is_int) {
14074 if (maybe_lhs_val) |lhs_val| {14156 if (maybe_lhs_val) |lhs_val| {
14075 if (lhs_val.isUndef()) {14157 if (lhs_val.isUndef(mod)) {
14076 return sema.failWithUseOfUndef(block, lhs_src);14158 return sema.failWithUseOfUndef(block, lhs_src);
14077 }14159 }
14078 }14160 }
14079 if (maybe_rhs_val) |rhs_val| {14161 if (maybe_rhs_val) |rhs_val| {
14080 if (rhs_val.isUndef()) {14162 if (rhs_val.isUndef(mod)) {
14081 return sema.failWithUseOfUndef(block, rhs_src);14163 return sema.failWithUseOfUndef(block, rhs_src);
14082 }14164 }
14083 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {14165 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -14096,7 +14178,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -14096,7 +14178,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14096 }14178 }
14097 // float operands14179 // float operands
14098 if (maybe_rhs_val) |rhs_val| {14180 if (maybe_rhs_val) |rhs_val| {
14099 if (rhs_val.isUndef()) {14181 if (rhs_val.isUndef(mod)) {
14100 return sema.failWithUseOfUndef(block, rhs_src);14182 return sema.failWithUseOfUndef(block, rhs_src);
14101 }14183 }
14102 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {14184 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -14104,7 +14186,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -14104,7 +14186,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14104 }14186 }
14105 }14187 }
14106 if (maybe_lhs_val) |lhs_val| {14188 if (maybe_lhs_val) |lhs_val| {
14107 if (lhs_val.isUndef()) {14189 if (lhs_val.isUndef(mod)) {
14108 return sema.addConstUndef(resolved_type);14190 return sema.addConstUndef(resolved_type);
14109 }14191 }
14110 if (maybe_rhs_val) |rhs_val| {14192 if (maybe_rhs_val) |rhs_val| {
...@@ -14127,6 +14209,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -14127,6 +14209,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14127}14209}
1412814210
14129fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {14211fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
14212 const mod = sema.mod;
14130 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;14213 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
14131 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };14214 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
14132 sema.src = src;14215 sema.src = src;
...@@ -14137,8 +14220,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -14137,8 +14220,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14137 const rhs = try sema.resolveInst(extra.rhs);14220 const rhs = try sema.resolveInst(extra.rhs);
14138 const lhs_ty = sema.typeOf(lhs);14221 const lhs_ty = sema.typeOf(lhs);
14139 const rhs_ty = sema.typeOf(rhs);14222 const rhs_ty = sema.typeOf(rhs);
14140 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();14223 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
14141 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();14224 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
14142 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14225 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14143 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);14226 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...@@ -14150,13 +14233,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14150 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14233 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14151 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14234 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
14155 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;14238 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1415614239
14157 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem);14240 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem);
1415814241
14159 const mod = sema.mod;
14160 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);14242 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
14161 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);14243 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...@@ -14174,12 +14256,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14174 // If the lhs is undefined, result is undefined.14256 // If the lhs is undefined, result is undefined.
14175 if (is_int) {14257 if (is_int) {
14176 if (maybe_lhs_val) |lhs_val| {14258 if (maybe_lhs_val) |lhs_val| {
14177 if (lhs_val.isUndef()) {14259 if (lhs_val.isUndef(mod)) {
14178 return sema.failWithUseOfUndef(block, lhs_src);14260 return sema.failWithUseOfUndef(block, lhs_src);
14179 }14261 }
14180 }14262 }
14181 if (maybe_rhs_val) |rhs_val| {14263 if (maybe_rhs_val) |rhs_val| {
14182 if (rhs_val.isUndef()) {14264 if (rhs_val.isUndef(mod)) {
14183 return sema.failWithUseOfUndef(block, rhs_src);14265 return sema.failWithUseOfUndef(block, rhs_src);
14184 }14266 }
14185 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {14267 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -14198,7 +14280,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -14198,7 +14280,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14198 }14280 }
14199 // float operands14281 // float operands
14200 if (maybe_rhs_val) |rhs_val| {14282 if (maybe_rhs_val) |rhs_val| {
14201 if (rhs_val.isUndef()) {14283 if (rhs_val.isUndef(mod)) {
14202 return sema.failWithUseOfUndef(block, rhs_src);14284 return sema.failWithUseOfUndef(block, rhs_src);
14203 }14285 }
14204 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {14286 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
...@@ -14206,7 +14288,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -14206,7 +14288,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14206 }14288 }
14207 }14289 }
14208 if (maybe_lhs_val) |lhs_val| {14290 if (maybe_lhs_val) |lhs_val| {
14209 if (lhs_val.isUndef()) {14291 if (lhs_val.isUndef(mod)) {
14210 return sema.addConstUndef(resolved_type);14292 return sema.addConstUndef(resolved_type);
14211 }14293 }
14212 if (maybe_rhs_val) |rhs_val| {14294 if (maybe_rhs_val) |rhs_val| {
...@@ -14268,7 +14350,7 @@ fn zirOverflowArithmetic(...@@ -14268,7 +14350,7 @@ fn zirOverflowArithmetic(
14268 const lhs = try sema.coerce(block, dest_ty, uncasted_lhs, lhs_src);14350 const lhs = try sema.coerce(block, dest_ty, uncasted_lhs, lhs_src);
14269 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);14351 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) {
14272 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)});14354 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)});
14273 }14355 }
1427414356
...@@ -14276,30 +14358,32 @@ fn zirOverflowArithmetic(...@@ -14276,30 +14358,32 @@ fn zirOverflowArithmetic(
14276 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);14358 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);
1427714359
14278 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);14360 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
14280 var result: struct {14363 var result: struct {
14281 inst: Air.Inst.Ref = .none,14364 inst: Air.Inst.Ref = .none,
14282 wrapped: Value = Value.initTag(.unreachable_value),14365 wrapped: Value = Value.@"unreachable",
14283 overflow_bit: Value,14366 overflow_bit: Value,
14284 } = result: {14367 } = result: {
14368 const zero_bit = try mod.intValue(Type.u1, 0);
14285 switch (zir_tag) {14369 switch (zir_tag) {
14286 .add_with_overflow => {14370 .add_with_overflow => {
14287 // If either of the arguments is zero, `false` is returned and the other is stored14371 // If either of the arguments is zero, `false` is returned and the other is stored
14288 // to the result, even if it is undefined..14372 // to the result, even if it is undefined..
14289 // Otherwise, if either of the argument is undefined, undefined is returned.14373 // Otherwise, if either of the argument is undefined, undefined is returned.
14290 if (maybe_lhs_val) |lhs_val| {14374 if (maybe_lhs_val) |lhs_val| {
14291 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14375 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14292 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };14376 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
14293 }14377 }
14294 }14378 }
14295 if (maybe_rhs_val) |rhs_val| {14379 if (maybe_rhs_val) |rhs_val| {
14296 if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14380 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14297 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };14381 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
14298 }14382 }
14299 }14383 }
14300 if (maybe_lhs_val) |lhs_val| {14384 if (maybe_lhs_val) |lhs_val| {
14301 if (maybe_rhs_val) |rhs_val| {14385 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)) {
14303 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };14387 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
14304 }14388 }
1430514389
...@@ -14312,12 +14396,12 @@ fn zirOverflowArithmetic(...@@ -14312,12 +14396,12 @@ fn zirOverflowArithmetic(
14312 // If the rhs is zero, then the result is lhs and no overflow occured.14396 // If the rhs is zero, then the result is lhs and no overflow occured.
14313 // Otherwise, if either result is undefined, both results are undefined.14397 // Otherwise, if either result is undefined, both results are undefined.
14314 if (maybe_rhs_val) |rhs_val| {14398 if (maybe_rhs_val) |rhs_val| {
14315 if (rhs_val.isUndef()) {14399 if (rhs_val.isUndef(mod)) {
14316 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };14400 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
14317 } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14401 } 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 };
14319 } else if (maybe_lhs_val) |lhs_val| {14403 } else if (maybe_lhs_val) |lhs_val| {
14320 if (lhs_val.isUndef()) {14404 if (lhs_val.isUndef(mod)) {
14321 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };14405 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
14322 }14406 }
1432314407
...@@ -14330,29 +14414,30 @@ fn zirOverflowArithmetic(...@@ -14330,29 +14414,30 @@ fn zirOverflowArithmetic(
14330 // If either of the arguments is zero, the result is zero and no overflow occured.14414 // If either of the arguments is zero, the result is zero and no overflow occured.
14331 // If either of the arguments is one, the result is the other and no overflow occured.14415 // If either of the arguments is one, the result is the other and no overflow occured.
14332 // Otherwise, if either of the arguments is undefined, both results are undefined.14416 // Otherwise, if either of the arguments is undefined, both results are undefined.
14417 const scalar_one = try mod.intValue(dest_ty.scalarType(mod), 1);
14333 if (maybe_lhs_val) |lhs_val| {14418 if (maybe_lhs_val) |lhs_val| {
14334 if (!lhs_val.isUndef()) {14419 if (!lhs_val.isUndef(mod)) {
14335 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14420 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14336 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };14421 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
14337 } else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {14422 } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14338 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };14423 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
14339 }14424 }
14340 }14425 }
14341 }14426 }
1434214427
14343 if (maybe_rhs_val) |rhs_val| {14428 if (maybe_rhs_val) |rhs_val| {
14344 if (!rhs_val.isUndef()) {14429 if (!rhs_val.isUndef(mod)) {
14345 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14430 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14346 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };14431 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
14347 } else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {14432 } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14348 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };14433 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
14349 }14434 }
14350 }14435 }
14351 }14436 }
1435214437
14353 if (maybe_lhs_val) |lhs_val| {14438 if (maybe_lhs_val) |lhs_val| {
14354 if (maybe_rhs_val) |rhs_val| {14439 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)) {
14356 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };14441 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
14357 }14442 }
1435814443
...@@ -14366,22 +14451,22 @@ fn zirOverflowArithmetic(...@@ -14366,22 +14451,22 @@ fn zirOverflowArithmetic(
14366 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.14451 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
14367 // Oterhwise if either of the arguments is undefined, both results are undefined.14452 // Oterhwise if either of the arguments is undefined, both results are undefined.
14368 if (maybe_lhs_val) |lhs_val| {14453 if (maybe_lhs_val) |lhs_val| {
14369 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14454 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14370 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };14455 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
14371 }14456 }
14372 }14457 }
14373 if (maybe_rhs_val) |rhs_val| {14458 if (maybe_rhs_val) |rhs_val| {
14374 if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {14459 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14375 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };14460 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
14376 }14461 }
14377 }14462 }
14378 if (maybe_lhs_val) |lhs_val| {14463 if (maybe_lhs_val) |lhs_val| {
14379 if (maybe_rhs_val) |rhs_val| {14464 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)) {
14381 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };14466 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
14382 }14467 }
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);
14385 break :result .{ .overflow_bit = result.overflow_bit, .wrapped = result.wrapped_result };14470 break :result .{ .overflow_bit = result.overflow_bit, .wrapped = result.wrapped_result };
14386 }14471 }
14387 }14472 }
...@@ -14420,40 +14505,46 @@ fn zirOverflowArithmetic(...@@ -14420,40 +14505,46 @@ fn zirOverflowArithmetic(
14420 }14505 }
1442114506
14422 if (result.inst == .none) {14507 if (result.inst == .none) {
14423 const values = try sema.arena.alloc(Value, 2);14508 return sema.addConstant(tuple_ty, (try mod.intern(.{ .aggregate = .{
14424 values[0] = result.wrapped;14509 .ty = tuple_ty.toIntern(),
14425 values[1] = result.overflow_bit;14510 .storage = .{ .elems = &.{
14426 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);14511 result.wrapped.toIntern(),
14427 return sema.addConstant(tuple_ty, tuple_val);14512 result.overflow_bit.toIntern(),
14513 } },
14514 } })).toValue());
14428 }14515 }
1442914516
14430 const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2);14517 const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2);
14431 element_refs[0] = result.inst;14518 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);
14433 return block.addAggregateInit(tuple_ty, element_refs);14520 return block.addAggregateInit(tuple_ty, element_refs);
14434}14521}
1443514522
14436fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value {14523fn splat(sema: *Sema, ty: Type, val: Value) !Value {
14437 if (ty.zigTypeTag() != .Vector) return val;14524 const mod = sema.mod;
14438 return Value.Tag.repeated.create(sema.arena, val);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();
14439}14531}
1444014532
14441fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {14533fn 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;14534 const mod = sema.mod;
1444314535 const ov_ty = if (ty.zigTypeTag(mod) == .Vector) try mod.vectorType(.{
14444 const types = try sema.arena.alloc(Type, 2);14536 .len = ty.vectorLen(mod),
14445 const values = try sema.arena.alloc(Value, 2);14537 .child = .u1_type,
14446 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{14538 }) else Type.u1;
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);
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();
14457}14548}
1445814549
14459fn analyzeArithmetic(14550fn analyzeArithmetic(
...@@ -14468,13 +14559,14 @@ fn analyzeArithmetic(...@@ -14468,13 +14559,14 @@ fn analyzeArithmetic(
14468 rhs_src: LazySrcLoc,14559 rhs_src: LazySrcLoc,
14469 want_safety: bool,14560 want_safety: bool,
14470) CompileError!Air.Inst.Ref {14561) CompileError!Air.Inst.Ref {
14562 const mod = sema.mod;
14471 const lhs_ty = sema.typeOf(lhs);14563 const lhs_ty = sema.typeOf(lhs);
14472 const rhs_ty = sema.typeOf(rhs);14564 const rhs_ty = sema.typeOf(rhs);
14473 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();14565 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
14474 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();14566 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
14475 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14567 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)) {
14478 .One, .Slice => {},14570 .One, .Slice => {},
14479 .Many, .C => {14571 .Many, .C => {
14480 const air_tag: Air.Inst.Tag = switch (zir_tag) {14572 const air_tag: Air.Inst.Tag = switch (zir_tag) {
...@@ -14491,18 +14583,16 @@ fn analyzeArithmetic(...@@ -14491,18 +14583,16 @@ fn analyzeArithmetic(
14491 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },14583 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
14492 });14584 });
1449314585
14494 const is_vector = resolved_type.zigTypeTag() == .Vector;
14495
14496 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14586 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14497 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14587 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
14501 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;14592 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1450214593
14503 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, zir_tag);14594 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, zir_tag);
1450414595
14505 const mod = sema.mod;
14506 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);14596 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
14507 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);14597 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
14508 const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: {14598 const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: {
...@@ -14516,12 +14606,12 @@ fn analyzeArithmetic(...@@ -14516,12 +14606,12 @@ fn analyzeArithmetic(
14516 // overflow (max_int), causing illegal behavior.14606 // overflow (max_int), causing illegal behavior.
14517 // For floats: either operand being undef makes the result undef.14607 // For floats: either operand being undef makes the result undef.
14518 if (maybe_lhs_val) |lhs_val| {14608 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))) {
14520 return casted_rhs;14610 return casted_rhs;
14521 }14611 }
14522 }14612 }
14523 if (maybe_rhs_val) |rhs_val| {14613 if (maybe_rhs_val) |rhs_val| {
14524 if (rhs_val.isUndef()) {14614 if (rhs_val.isUndef(mod)) {
14525 if (is_int) {14615 if (is_int) {
14526 return sema.failWithUseOfUndef(block, rhs_src);14616 return sema.failWithUseOfUndef(block, rhs_src);
14527 } else {14617 } else {
...@@ -14534,7 +14624,7 @@ fn analyzeArithmetic(...@@ -14534,7 +14624,7 @@ fn analyzeArithmetic(
14534 }14624 }
14535 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .add_optimized else .add;14625 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .add_optimized else .add;
14536 if (maybe_lhs_val) |lhs_val| {14626 if (maybe_lhs_val) |lhs_val| {
14537 if (lhs_val.isUndef()) {14627 if (lhs_val.isUndef(mod)) {
14538 if (is_int) {14628 if (is_int) {
14539 return sema.failWithUseOfUndef(block, lhs_src);14629 return sema.failWithUseOfUndef(block, lhs_src);
14540 } else {14630 } else {
...@@ -14543,16 +14633,16 @@ fn analyzeArithmetic(...@@ -14543,16 +14633,16 @@ fn analyzeArithmetic(
14543 }14633 }
14544 if (maybe_rhs_val) |rhs_val| {14634 if (maybe_rhs_val) |rhs_val| {
14545 if (is_int) {14635 if (is_int) {
14546 const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type);14636 var overflow_idx: ?usize = null;
14547 var vector_index: usize = undefined;14637 const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type, &overflow_idx);
14548 if (!(try sema.intFitsInType(sum, resolved_type, &vector_index))) {14638 if (overflow_idx) |vec_idx| {
14549 return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vector_index);14639 return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vec_idx);
14550 }14640 }
14551 return sema.addConstant(resolved_type, sum);14641 return sema.addConstant(resolved_type, sum);
14552 } else {14642 } else {
14553 return sema.addConstant(14643 return sema.addConstant(
14554 resolved_type,14644 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),
14556 );14646 );
14557 }14647 }
14558 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };14648 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
...@@ -14563,13 +14653,13 @@ fn analyzeArithmetic(...@@ -14563,13 +14653,13 @@ fn analyzeArithmetic(
14563 // If either of the operands are zero, the other operand is returned.14653 // If either of the operands are zero, the other operand is returned.
14564 // If either of the operands are undefined, the result is undefined.14654 // If either of the operands are undefined, the result is undefined.
14565 if (maybe_lhs_val) |lhs_val| {14655 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))) {
14567 return casted_rhs;14657 return casted_rhs;
14568 }14658 }
14569 }14659 }
14570 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .addwrap_optimized else .addwrap;14660 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .addwrap_optimized else .addwrap;
14571 if (maybe_rhs_val) |rhs_val| {14661 if (maybe_rhs_val) |rhs_val| {
14572 if (rhs_val.isUndef()) {14662 if (rhs_val.isUndef(mod)) {
14573 return sema.addConstUndef(resolved_type);14663 return sema.addConstUndef(resolved_type);
14574 }14664 }
14575 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14665 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
...@@ -14588,12 +14678,12 @@ fn analyzeArithmetic(...@@ -14588,12 +14678,12 @@ fn analyzeArithmetic(
14588 // If either of the operands are zero, then the other operand is returned.14678 // If either of the operands are zero, then the other operand is returned.
14589 // If either of the operands are undefined, the result is undefined.14679 // If either of the operands are undefined, the result is undefined.
14590 if (maybe_lhs_val) |lhs_val| {14680 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))) {
14592 return casted_rhs;14682 return casted_rhs;
14593 }14683 }
14594 }14684 }
14595 if (maybe_rhs_val) |rhs_val| {14685 if (maybe_rhs_val) |rhs_val| {
14596 if (rhs_val.isUndef()) {14686 if (rhs_val.isUndef(mod)) {
14597 return sema.addConstUndef(resolved_type);14687 return sema.addConstUndef(resolved_type);
14598 }14688 }
14599 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14689 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
...@@ -14601,7 +14691,7 @@ fn analyzeArithmetic(...@@ -14601,7 +14691,7 @@ fn analyzeArithmetic(
14601 }14691 }
14602 if (maybe_lhs_val) |lhs_val| {14692 if (maybe_lhs_val) |lhs_val| {
14603 const val = if (scalar_tag == .ComptimeInt)14693 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)
14605 else14695 else
14606 try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, mod);14696 try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, mod);
1460714697
...@@ -14618,7 +14708,7 @@ fn analyzeArithmetic(...@@ -14618,7 +14708,7 @@ fn analyzeArithmetic(
14618 // overflow, causing illegal behavior.14708 // overflow, causing illegal behavior.
14619 // For floats: either operand being undef makes the result undef.14709 // For floats: either operand being undef makes the result undef.
14620 if (maybe_rhs_val) |rhs_val| {14710 if (maybe_rhs_val) |rhs_val| {
14621 if (rhs_val.isUndef()) {14711 if (rhs_val.isUndef(mod)) {
14622 if (is_int) {14712 if (is_int) {
14623 return sema.failWithUseOfUndef(block, rhs_src);14713 return sema.failWithUseOfUndef(block, rhs_src);
14624 } else {14714 } else {
...@@ -14631,7 +14721,7 @@ fn analyzeArithmetic(...@@ -14631,7 +14721,7 @@ fn analyzeArithmetic(
14631 }14721 }
14632 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .sub_optimized else .sub;14722 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .sub_optimized else .sub;
14633 if (maybe_lhs_val) |lhs_val| {14723 if (maybe_lhs_val) |lhs_val| {
14634 if (lhs_val.isUndef()) {14724 if (lhs_val.isUndef(mod)) {
14635 if (is_int) {14725 if (is_int) {
14636 return sema.failWithUseOfUndef(block, lhs_src);14726 return sema.failWithUseOfUndef(block, lhs_src);
14637 } else {14727 } else {
...@@ -14640,16 +14730,16 @@ fn analyzeArithmetic(...@@ -14640,16 +14730,16 @@ fn analyzeArithmetic(
14640 }14730 }
14641 if (maybe_rhs_val) |rhs_val| {14731 if (maybe_rhs_val) |rhs_val| {
14642 if (is_int) {14732 if (is_int) {
14643 const diff = try sema.intSub(lhs_val, rhs_val, resolved_type);14733 var overflow_idx: ?usize = null;
14644 var vector_index: usize = undefined;14734 const diff = try sema.intSub(lhs_val, rhs_val, resolved_type, &overflow_idx);
14645 if (!(try sema.intFitsInType(diff, resolved_type, &vector_index))) {14735 if (overflow_idx) |vec_idx| {
14646 return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vector_index);14736 return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vec_idx);
14647 }14737 }
14648 return sema.addConstant(resolved_type, diff);14738 return sema.addConstant(resolved_type, diff);
14649 } else {14739 } else {
14650 return sema.addConstant(14740 return sema.addConstant(
14651 resolved_type,14741 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),
14653 );14743 );
14654 }14744 }
14655 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };14745 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
...@@ -14660,7 +14750,7 @@ fn analyzeArithmetic(...@@ -14660,7 +14750,7 @@ fn analyzeArithmetic(
14660 // If the RHS is zero, then the other operand is returned, even if it is undefined.14750 // If the RHS is zero, then the other operand is returned, even if it is undefined.
14661 // If either of the operands are undefined, the result is undefined.14751 // If either of the operands are undefined, the result is undefined.
14662 if (maybe_rhs_val) |rhs_val| {14752 if (maybe_rhs_val) |rhs_val| {
14663 if (rhs_val.isUndef()) {14753 if (rhs_val.isUndef(mod)) {
14664 return sema.addConstUndef(resolved_type);14754 return sema.addConstUndef(resolved_type);
14665 }14755 }
14666 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14756 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
...@@ -14669,7 +14759,7 @@ fn analyzeArithmetic(...@@ -14669,7 +14759,7 @@ fn analyzeArithmetic(
14669 }14759 }
14670 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .subwrap_optimized else .subwrap;14760 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .subwrap_optimized else .subwrap;
14671 if (maybe_lhs_val) |lhs_val| {14761 if (maybe_lhs_val) |lhs_val| {
14672 if (lhs_val.isUndef()) {14762 if (lhs_val.isUndef(mod)) {
14673 return sema.addConstUndef(resolved_type);14763 return sema.addConstUndef(resolved_type);
14674 }14764 }
14675 if (maybe_rhs_val) |rhs_val| {14765 if (maybe_rhs_val) |rhs_val| {
...@@ -14685,7 +14775,7 @@ fn analyzeArithmetic(...@@ -14685,7 +14775,7 @@ fn analyzeArithmetic(
14685 // If the RHS is zero, result is LHS.14775 // If the RHS is zero, result is LHS.
14686 // If either of the operands are undefined, result is undefined.14776 // If either of the operands are undefined, result is undefined.
14687 if (maybe_rhs_val) |rhs_val| {14777 if (maybe_rhs_val) |rhs_val| {
14688 if (rhs_val.isUndef()) {14778 if (rhs_val.isUndef(mod)) {
14689 return sema.addConstUndef(resolved_type);14779 return sema.addConstUndef(resolved_type);
14690 }14780 }
14691 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14781 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
...@@ -14693,12 +14783,12 @@ fn analyzeArithmetic(...@@ -14693,12 +14783,12 @@ fn analyzeArithmetic(
14693 }14783 }
14694 }14784 }
14695 if (maybe_lhs_val) |lhs_val| {14785 if (maybe_lhs_val) |lhs_val| {
14696 if (lhs_val.isUndef()) {14786 if (lhs_val.isUndef(mod)) {
14697 return sema.addConstUndef(resolved_type);14787 return sema.addConstUndef(resolved_type);
14698 }14788 }
14699 if (maybe_rhs_val) |rhs_val| {14789 if (maybe_rhs_val) |rhs_val| {
14700 const val = if (scalar_tag == .ComptimeInt)14790 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)
14702 else14792 else
14703 try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod);14793 try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod);
1470414794
...@@ -14718,62 +14808,74 @@ fn analyzeArithmetic(...@@ -14718,62 +14808,74 @@ fn analyzeArithmetic(
14718 // If either of the operands are inf, and the other operand is zero,14808 // If either of the operands are inf, and the other operand is zero,
14719 // the result is nan.14809 // the result is nan.
14720 // If either of the operands are nan, the result is nan.14810 // 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 };
14721 if (maybe_lhs_val) |lhs_val| {14821 if (maybe_lhs_val) |lhs_val| {
14722 if (!lhs_val.isUndef()) {14822 if (!lhs_val.isUndef(mod)) {
14723 if (lhs_val.isNan()) {14823 if (lhs_val.isNan(mod)) {
14724 return sema.addConstant(resolved_type, lhs_val);14824 return sema.addConstant(resolved_type, lhs_val);
14725 }14825 }
14726 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) lz: {14826 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) lz: {
14727 if (maybe_rhs_val) |rhs_val| {14827 if (maybe_rhs_val) |rhs_val| {
14728 if (rhs_val.isNan()) {14828 if (rhs_val.isNan(mod)) {
14729 return sema.addConstant(resolved_type, rhs_val);14829 return sema.addConstant(resolved_type, rhs_val);
14730 }14830 }
14731 if (rhs_val.isInf()) {14831 if (rhs_val.isInf(mod)) {
14732 return sema.addConstant(resolved_type, try Value.Tag.float_32.create(sema.arena, std.math.nan_f32));14832 return sema.addConstant(
14833 resolved_type,
14834 try mod.floatValue(resolved_type, std.math.nan_f128),
14835 );
14733 }14836 }
14734 } else if (resolved_type.isAnyFloat()) {14837 } else if (resolved_type.isAnyFloat()) {
14735 break :lz;14838 break :lz;
14736 }14839 }
14737 const zero_val = if (is_vector) b: {14840 const zero_val = try sema.splat(resolved_type, scalar_zero);
14738 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14739 } else Value.zero;
14740 return sema.addConstant(resolved_type, zero_val);14841 return sema.addConstant(resolved_type, zero_val);
14741 }14842 }
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)) {
14743 return casted_rhs;14844 return casted_rhs;
14744 }14845 }
14745 }14846 }
14746 }14847 }
14747 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mul_optimized else .mul;14848 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mul_optimized else .mul;
14748 if (maybe_rhs_val) |rhs_val| {14849 if (maybe_rhs_val) |rhs_val| {
14749 if (rhs_val.isUndef()) {14850 if (rhs_val.isUndef(mod)) {
14750 if (is_int) {14851 if (is_int) {
14751 return sema.failWithUseOfUndef(block, rhs_src);14852 return sema.failWithUseOfUndef(block, rhs_src);
14752 } else {14853 } else {
14753 return sema.addConstUndef(resolved_type);14854 return sema.addConstUndef(resolved_type);
14754 }14855 }
14755 }14856 }
14756 if (rhs_val.isNan()) {14857 if (rhs_val.isNan(mod)) {
14757 return sema.addConstant(resolved_type, rhs_val);14858 return sema.addConstant(resolved_type, rhs_val);
14758 }14859 }
14759 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) rz: {14860 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) rz: {
14760 if (maybe_lhs_val) |lhs_val| {14861 if (maybe_lhs_val) |lhs_val| {
14761 if (lhs_val.isInf()) {14862 if (lhs_val.isInf(mod)) {
14762 return sema.addConstant(resolved_type, try Value.Tag.float_32.create(sema.arena, std.math.nan_f32));14863 return sema.addConstant(
14864 resolved_type,
14865 try mod.floatValue(resolved_type, std.math.nan_f128),
14866 );
14763 }14867 }
14764 } else if (resolved_type.isAnyFloat()) {14868 } else if (resolved_type.isAnyFloat()) {
14765 break :rz;14869 break :rz;
14766 }14870 }
14767 const zero_val = if (is_vector) b: {14871 const zero_val = try sema.splat(resolved_type, scalar_zero);
14768 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14769 } else Value.zero;
14770 return sema.addConstant(resolved_type, zero_val);14872 return sema.addConstant(resolved_type, zero_val);
14771 }14873 }
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)) {
14773 return casted_lhs;14875 return casted_lhs;
14774 }14876 }
14775 if (maybe_lhs_val) |lhs_val| {14877 if (maybe_lhs_val) |lhs_val| {
14776 if (lhs_val.isUndef()) {14878 if (lhs_val.isUndef(mod)) {
14777 if (is_int) {14879 if (is_int) {
14778 return sema.failWithUseOfUndef(block, lhs_src);14880 return sema.failWithUseOfUndef(block, lhs_src);
14779 } else {14881 } else {
...@@ -14781,16 +14883,16 @@ fn analyzeArithmetic(...@@ -14781,16 +14883,16 @@ fn analyzeArithmetic(
14781 }14883 }
14782 }14884 }
14783 if (is_int) {14885 if (is_int) {
14784 const product = try lhs_val.intMul(rhs_val, resolved_type, sema.arena, sema.mod);14886 var overflow_idx: ?usize = null;
14785 var vector_index: usize = undefined;14887 const product = try lhs_val.intMul(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
14786 if (!(try sema.intFitsInType(product, resolved_type, &vector_index))) {14888 if (overflow_idx) |vec_idx| {
14787 return sema.failWithIntegerOverflow(block, src, resolved_type, product, vector_index);14889 return sema.failWithIntegerOverflow(block, src, resolved_type, product, vec_idx);
14788 }14890 }
14789 return sema.addConstant(resolved_type, product);14891 return sema.addConstant(resolved_type, product);
14790 } else {14892 } else {
14791 return sema.addConstant(14893 return sema.addConstant(
14792 resolved_type,14894 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),
14794 );14896 );
14795 }14897 }
14796 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };14898 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
...@@ -14801,40 +14903,46 @@ fn analyzeArithmetic(...@@ -14801,40 +14903,46 @@ fn analyzeArithmetic(
14801 // If either of the operands are zero, result is zero.14903 // If either of the operands are zero, result is zero.
14802 // If either of the operands are one, result is the other operand.14904 // If either of the operands are one, result is the other operand.
14803 // If either of the operands are undefined, result is undefined.14905 // 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 };
14804 if (maybe_lhs_val) |lhs_val| {14916 if (maybe_lhs_val) |lhs_val| {
14805 if (!lhs_val.isUndef()) {14917 if (!lhs_val.isUndef(mod)) {
14806 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14918 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14807 const zero_val = if (is_vector) b: {14919 const zero_val = try sema.splat(resolved_type, scalar_zero);
14808 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14809 } else Value.zero;
14810 return sema.addConstant(resolved_type, zero_val);14920 return sema.addConstant(resolved_type, zero_val);
14811 }14921 }
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)) {
14813 return casted_rhs;14923 return casted_rhs;
14814 }14924 }
14815 }14925 }
14816 }14926 }
14817 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mulwrap_optimized else .mulwrap;14927 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mulwrap_optimized else .mulwrap;
14818 if (maybe_rhs_val) |rhs_val| {14928 if (maybe_rhs_val) |rhs_val| {
14819 if (rhs_val.isUndef()) {14929 if (rhs_val.isUndef(mod)) {
14820 return sema.addConstUndef(resolved_type);14930 return sema.addConstUndef(resolved_type);
14821 }14931 }
14822 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14932 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14823 const zero_val = if (is_vector) b: {14933 const zero_val = try sema.splat(resolved_type, scalar_zero);
14824 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14825 } else Value.zero;
14826 return sema.addConstant(resolved_type, zero_val);14934 return sema.addConstant(resolved_type, zero_val);
14827 }14935 }
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)) {
14829 return casted_lhs;14937 return casted_lhs;
14830 }14938 }
14831 if (maybe_lhs_val) |lhs_val| {14939 if (maybe_lhs_val) |lhs_val| {
14832 if (lhs_val.isUndef()) {14940 if (lhs_val.isUndef(mod)) {
14833 return sema.addConstUndef(resolved_type);14941 return sema.addConstUndef(resolved_type);
14834 }14942 }
14835 return sema.addConstant(14943 return sema.addConstant(
14836 resolved_type,14944 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),
14838 );14946 );
14839 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };14947 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
14840 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };14948 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
...@@ -14844,41 +14952,47 @@ fn analyzeArithmetic(...@@ -14844,41 +14952,47 @@ fn analyzeArithmetic(
14844 // If either of the operands are zero, result is zero.14952 // If either of the operands are zero, result is zero.
14845 // If either of the operands are one, result is the other operand.14953 // If either of the operands are one, result is the other operand.
14846 // If either of the operands are undefined, result is undefined.14954 // 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 };
14847 if (maybe_lhs_val) |lhs_val| {14965 if (maybe_lhs_val) |lhs_val| {
14848 if (!lhs_val.isUndef()) {14966 if (!lhs_val.isUndef(mod)) {
14849 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14967 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14850 const zero_val = if (is_vector) b: {14968 const zero_val = try sema.splat(resolved_type, scalar_zero);
14851 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14852 } else Value.zero;
14853 return sema.addConstant(resolved_type, zero_val);14969 return sema.addConstant(resolved_type, zero_val);
14854 }14970 }
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)) {
14856 return casted_rhs;14972 return casted_rhs;
14857 }14973 }
14858 }14974 }
14859 }14975 }
14860 if (maybe_rhs_val) |rhs_val| {14976 if (maybe_rhs_val) |rhs_val| {
14861 if (rhs_val.isUndef()) {14977 if (rhs_val.isUndef(mod)) {
14862 return sema.addConstUndef(resolved_type);14978 return sema.addConstUndef(resolved_type);
14863 }14979 }
14864 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14980 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14865 const zero_val = if (is_vector) b: {14981 const zero_val = try sema.splat(resolved_type, scalar_zero);
14866 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14867 } else Value.zero;
14868 return sema.addConstant(resolved_type, zero_val);14982 return sema.addConstant(resolved_type, zero_val);
14869 }14983 }
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)) {
14871 return casted_lhs;14985 return casted_lhs;
14872 }14986 }
14873 if (maybe_lhs_val) |lhs_val| {14987 if (maybe_lhs_val) |lhs_val| {
14874 if (lhs_val.isUndef()) {14988 if (lhs_val.isUndef(mod)) {
14875 return sema.addConstUndef(resolved_type);14989 return sema.addConstUndef(resolved_type);
14876 }14990 }
1487714991
14878 const val = if (scalar_tag == .ComptimeInt)14992 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)
14880 else14994 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
14883 return sema.addConstant(resolved_type, val);14997 return sema.addConstant(resolved_type, val);
14884 } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat };14998 } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat };
...@@ -14910,7 +15024,7 @@ fn analyzeArithmetic(...@@ -14910,7 +15024,7 @@ fn analyzeArithmetic(
14910 } },15024 } },
14911 });15025 });
14912 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);15026 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)
14914 try block.addInst(.{15028 try block.addInst(.{
14915 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,15029 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
14916 .data = .{ .reduce = .{15030 .data = .{ .reduce = .{
...@@ -14920,7 +15034,7 @@ fn analyzeArithmetic(...@@ -14920,7 +15034,7 @@ fn analyzeArithmetic(
14920 })15034 })
14921 else15035 else
14922 ov_bit;15036 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));
14924 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);15038 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
1492515039
14926 try sema.addSafetyCheck(block, no_ov, .integer_overflow);15040 try sema.addSafetyCheck(block, no_ov, .integer_overflow);
...@@ -14944,15 +15058,12 @@ fn analyzePtrArithmetic(...@@ -14944,15 +15058,12 @@ fn analyzePtrArithmetic(
14944 // TODO if the operand is comptime-known to be negative, or is a negative int,15058 // TODO if the operand is comptime-known to be negative, or is a negative int,
14945 // coerce to isize instead of usize.15059 // coerce to isize instead of usize.
14946 const offset = try sema.coerce(block, Type.usize, uncasted_offset, offset_src);15060 const offset = try sema.coerce(block, Type.usize, uncasted_offset, offset_src);
14947 const target = sema.mod.getTarget();15061 const mod = sema.mod;
14948 const opt_ptr_val = try sema.resolveMaybeUndefVal(ptr);15062 const opt_ptr_val = try sema.resolveMaybeUndefVal(ptr);
14949 const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset);15063 const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset);
14950 const ptr_ty = sema.typeOf(ptr);15064 const ptr_ty = sema.typeOf(ptr);
14951 const ptr_info = ptr_ty.ptrInfo().data;15065 const ptr_info = ptr_ty.ptrInfo(mod);
14952 const elem_ty = if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Array)15066 assert(ptr_info.size == .Many or ptr_info.size == .C);
14953 ptr_info.pointee_type.childType()
14954 else
14955 ptr_info.pointee_type;
1495615067
14957 const new_ptr_ty = t: {15068 const new_ptr_ty = t: {
14958 // Calculate the new pointer alignment.15069 // Calculate the new pointer alignment.
...@@ -14963,9 +15074,9 @@ fn analyzePtrArithmetic(...@@ -14963,9 +15074,9 @@ fn analyzePtrArithmetic(
14963 }15074 }
14964 // If the addend is not a comptime-known value we can still count on15075 // If the addend is not a comptime-known value we can still count on
14965 // it being a multiple of the type size.15076 // 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);
14967 const addend = if (opt_off_val) |off_val| a: {15078 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));
14969 break :a elem_size * off_int;15080 break :a elem_size * off_int;
14970 } else elem_size;15081 } else elem_size;
1497115082
...@@ -14974,7 +15085,7 @@ fn analyzePtrArithmetic(...@@ -14974,7 +15085,7 @@ fn analyzePtrArithmetic(
14974 // non zero).15085 // non zero).
14975 const new_align = @as(u32, 1) << @intCast(u5, @ctz(addend | ptr_info.@"align"));15086 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, .{
14978 .pointee_type = ptr_info.pointee_type,15089 .pointee_type = ptr_info.pointee_type,
14979 .sentinel = ptr_info.sentinel,15090 .sentinel = ptr_info.sentinel,
14980 .@"align" = new_align,15091 .@"align" = new_align,
...@@ -14989,24 +15100,24 @@ fn analyzePtrArithmetic(...@@ -14989,24 +15100,24 @@ fn analyzePtrArithmetic(
14989 const runtime_src = rs: {15100 const runtime_src = rs: {
14990 if (opt_ptr_val) |ptr_val| {15101 if (opt_ptr_val) |ptr_val| {
14991 if (opt_off_val) |offset_val| {15102 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));
14995 if (offset_int == 0) return ptr;15106 if (offset_int == 0) return ptr;
14996 if (try ptr_val.getUnsignedIntAdvanced(target, sema)) |addr| {15107 if (try ptr_val.getUnsignedIntAdvanced(mod, sema)) |addr| {
14997 const elem_size = elem_ty.abiSize(target);15108 const elem_size = ptr_info.pointee_type.abiSize(mod);
14998 const new_addr = switch (air_tag) {15109 const new_addr = switch (air_tag) {
14999 .ptr_add => addr + elem_size * offset_int,15110 .ptr_add => addr + elem_size * offset_int,
15000 .ptr_sub => addr - elem_size * offset_int,15111 .ptr_sub => addr - elem_size * offset_int,
15001 else => unreachable,15112 else => unreachable,
15002 };15113 };
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);
15004 return sema.addConstant(new_ptr_ty, new_ptr_val);15115 return sema.addConstant(new_ptr_ty, new_ptr_val);
15005 }15116 }
15006 if (air_tag == .ptr_sub) {15117 if (air_tag == .ptr_sub) {
15007 return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});15118 return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});
15008 }15119 }
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);
15010 return sema.addConstant(new_ptr_ty, new_ptr_val);15121 return sema.addConstant(new_ptr_ty, new_ptr_val);
15011 } else break :rs offset_src;15122 } else break :rs offset_src;
15012 } else break :rs ptr_src;15123 } else break :rs ptr_src;
...@@ -15052,7 +15163,7 @@ fn zirAsm(...@@ -15052,7 +15163,7 @@ fn zirAsm(
15052 const inputs_len = @truncate(u5, extended.small >> 5);15163 const inputs_len = @truncate(u5, extended.small >> 5);
15053 const clobbers_len = @truncate(u5, extended.small >> 10);15164 const clobbers_len = @truncate(u5, extended.small >> 10);
15054 const is_volatile = @truncate(u1, extended.small >> 15) != 0;15165 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
15057 const asm_source: []const u8 = if (tmpl_is_expr) blk: {15168 const asm_source: []const u8 = if (tmpl_is_expr) blk: {
15058 const tmpl = @intToEnum(Zir.Inst.Ref, extra.data.asm_source);15169 const tmpl = @intToEnum(Zir.Inst.Ref, extra.data.asm_source);
...@@ -15116,6 +15227,7 @@ fn zirAsm(...@@ -15116,6 +15227,7 @@ fn zirAsm(
1511615227
15117 const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len);15228 const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len);
15118 const inputs = try sema.arena.alloc(ConstraintName, inputs_len);15229 const inputs = try sema.arena.alloc(ConstraintName, inputs_len);
15230 const mod = sema.mod;
1511915231
15120 for (args, 0..) |*arg, arg_i| {15232 for (args, 0..) |*arg, arg_i| {
15121 const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);15233 const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);
...@@ -15123,9 +15235,9 @@ fn zirAsm(...@@ -15123,9 +15235,9 @@ fn zirAsm(
1512315235
15124 const uncasted_arg = try sema.resolveInst(input.data.operand);15236 const uncasted_arg = try sema.resolveInst(input.data.operand);
15125 const uncasted_arg_ty = sema.typeOf(uncasted_arg);15237 const uncasted_arg_ty = sema.typeOf(uncasted_arg);
15126 switch (uncasted_arg_ty.zigTypeTag()) {15238 switch (uncasted_arg_ty.zigTypeTag(mod)) {
15127 .ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src),15239 .ComptimeInt => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
15128 .ComptimeFloat => arg.* = try sema.coerce(block, Type.initTag(.f64), uncasted_arg, src),15240 .ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
15129 else => {15241 else => {
15130 arg.* = uncasted_arg;15242 arg.* = uncasted_arg;
15131 try sema.queueFullTypeResolution(uncasted_arg_ty);15243 try sema.queueFullTypeResolution(uncasted_arg_ty);
...@@ -15205,6 +15317,7 @@ fn zirCmpEq(...@@ -15205,6 +15317,7 @@ fn zirCmpEq(
15205 const tracy = trace(@src());15317 const tracy = trace(@src());
15206 defer tracy.end();15318 defer tracy.end();
1520715319
15320 const mod = sema.mod;
15208 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;15321 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
15209 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;15322 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
15210 const src: LazySrcLoc = inst_data.src();15323 const src: LazySrcLoc = inst_data.src();
...@@ -15215,8 +15328,8 @@ fn zirCmpEq(...@@ -15215,8 +15328,8 @@ fn zirCmpEq(
1521515328
15216 const lhs_ty = sema.typeOf(lhs);15329 const lhs_ty = sema.typeOf(lhs);
15217 const rhs_ty = sema.typeOf(rhs);15330 const rhs_ty = sema.typeOf(rhs);
15218 const lhs_ty_tag = lhs_ty.zigTypeTag();15331 const lhs_ty_tag = lhs_ty.zigTypeTag(mod);
15219 const rhs_ty_tag = rhs_ty.zigTypeTag();15332 const rhs_ty_tag = rhs_ty.zigTypeTag(mod);
15220 if (lhs_ty_tag == .Null and rhs_ty_tag == .Null) {15333 if (lhs_ty_tag == .Null and rhs_ty_tag == .Null) {
15221 // null == null, null != null15334 // null == null, null != null
15222 if (op == .eq) {15335 if (op == .eq) {
...@@ -15227,16 +15340,16 @@ fn zirCmpEq(...@@ -15227,16 +15340,16 @@ fn zirCmpEq(
15227 }15340 }
1522815341
15229 // comparing null with optionals15342 // 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))) {
15231 return sema.analyzeIsNull(block, src, rhs, op == .neq);15344 return sema.analyzeIsNull(block, src, rhs, op == .neq);
15232 }15345 }
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))) {
15234 return sema.analyzeIsNull(block, src, lhs, op == .neq);15347 return sema.analyzeIsNull(block, src, lhs, op == .neq);
15235 }15348 }
1523615349
15237 if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) {15350 if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) {
15238 const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty;15351 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)});
15240 }15353 }
1524115354
15242 if (lhs_ty_tag == .Union and (rhs_ty_tag == .EnumLiteral or rhs_ty_tag == .Enum)) {15355 if (lhs_ty_tag == .Union and (rhs_ty_tag == .EnumLiteral or rhs_ty_tag == .Enum)) {
...@@ -15250,15 +15363,12 @@ fn zirCmpEq(...@@ -15250,15 +15363,12 @@ fn zirCmpEq(
15250 const runtime_src: LazySrcLoc = src: {15363 const runtime_src: LazySrcLoc = src: {
15251 if (try sema.resolveMaybeUndefVal(lhs)) |lval| {15364 if (try sema.resolveMaybeUndefVal(lhs)) |lval| {
15252 if (try sema.resolveMaybeUndefVal(rhs)) |rval| {15365 if (try sema.resolveMaybeUndefVal(rhs)) |rval| {
15253 if (lval.isUndef() or rval.isUndef()) {15366 if (lval.isUndef(mod) or rval.isUndef(mod)) {
15254 return sema.addConstUndef(Type.bool);15367 return sema.addConstUndef(Type.bool);
15255 }15368 }
15256 // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,15369 const lkey = mod.intern_pool.indexToKey(lval.toIntern());
15257 // or calling to Module.getErrorValue to get the values and then compare them is15370 const rkey = mod.intern_pool.indexToKey(rval.toIntern());
15258 // faster.15371 if ((lkey.err.name == rkey.err.name) == (op == .eq)) {
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)) {
15262 return Air.Inst.Ref.bool_true;15372 return Air.Inst.Ref.bool_true;
15263 } else {15373 } else {
15264 return Air.Inst.Ref.bool_false;15374 return Air.Inst.Ref.bool_false;
...@@ -15276,7 +15386,7 @@ fn zirCmpEq(...@@ -15276,7 +15386,7 @@ fn zirCmpEq(
15276 if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) {15386 if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) {
15277 const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs);15387 const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs);
15278 const rhs_as_type = try sema.analyzeAsType(block, rhs_src, rhs);15388 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)) {
15280 return Air.Inst.Ref.bool_true;15390 return Air.Inst.Ref.bool_true;
15281 } else {15391 } else {
15282 return Air.Inst.Ref.bool_false;15392 return Air.Inst.Ref.bool_false;
...@@ -15295,12 +15405,13 @@ fn analyzeCmpUnionTag(...@@ -15295,12 +15405,13 @@ fn analyzeCmpUnionTag(
15295 tag_src: LazySrcLoc,15405 tag_src: LazySrcLoc,
15296 op: std.math.CompareOperator,15406 op: std.math.CompareOperator,
15297) CompileError!Air.Inst.Ref {15407) CompileError!Air.Inst.Ref {
15408 const mod = sema.mod;
15298 const union_ty = try sema.resolveTypeFields(sema.typeOf(un));15409 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 {
15300 const msg = msg: {15411 const msg = msg: {
15301 const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});15412 const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
15302 errdefer msg.destroy(sema.gpa);15413 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)});
15304 break :msg msg;15415 break :msg msg;
15305 };15416 };
15306 return sema.failWithOwnedErrorMsg(msg);15417 return sema.failWithOwnedErrorMsg(msg);
...@@ -15311,9 +15422,9 @@ fn analyzeCmpUnionTag(...@@ -15311,9 +15422,9 @@ fn analyzeCmpUnionTag(
15311 const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src);15422 const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src);
1531215423
15313 if (try sema.resolveMaybeUndefVal(coerced_tag)) |enum_val| {15424 if (try sema.resolveMaybeUndefVal(coerced_tag)) |enum_val| {
15314 if (enum_val.isUndef()) return sema.addConstUndef(Type.bool);15425 if (enum_val.isUndef(mod)) return sema.addConstUndef(Type.bool);
15315 const field_ty = union_ty.unionFieldType(enum_val, sema.mod);15426 const field_ty = union_ty.unionFieldType(enum_val, mod);
15316 if (field_ty.zigTypeTag() == .NoReturn) {15427 if (field_ty.zigTypeTag(mod) == .NoReturn) {
15317 return Air.Inst.Ref.bool_false;15428 return Air.Inst.Ref.bool_false;
15318 }15429 }
15319 }15430 }
...@@ -15352,34 +15463,35 @@ fn analyzeCmp(...@@ -15352,34 +15463,35 @@ fn analyzeCmp(
15352 rhs_src: LazySrcLoc,15463 rhs_src: LazySrcLoc,
15353 is_equality_cmp: bool,15464 is_equality_cmp: bool,
15354) CompileError!Air.Inst.Ref {15465) CompileError!Air.Inst.Ref {
15466 const mod = sema.mod;
15355 const lhs_ty = sema.typeOf(lhs);15467 const lhs_ty = sema.typeOf(lhs);
15356 const rhs_ty = sema.typeOf(rhs);15468 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) {
15358 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);15470 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
15359 }15471 }
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) {
15362 return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src);15474 return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src);
15363 }15475 }
15364 if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {15476 if (lhs_ty.isNumeric(mod) and rhs_ty.isNumeric(mod)) {
15365 // This operation allows any combination of integer and float types, regardless of the15477 // This operation allows any combination of integer and float types, regardless of the
15366 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for15478 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
15367 // numeric types.15479 // numeric types.
15368 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);15480 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
15369 }15481 }
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) {
15371 const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs);15483 const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs);
15372 return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src);15484 return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src);
15373 }15485 }
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) {
15375 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);15487 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);
15376 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);15488 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
15377 }15489 }
15378 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };15490 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
15379 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });15491 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)) {
15381 return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{15493 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),
15383 });15495 });
15384 }15496 }
15385 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);15497 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
...@@ -15408,15 +15520,19 @@ fn cmpSelf(...@@ -15408,15 +15520,19 @@ fn cmpSelf(
15408 lhs_src: LazySrcLoc,15520 lhs_src: LazySrcLoc,
15409 rhs_src: LazySrcLoc,15521 rhs_src: LazySrcLoc,
15410) CompileError!Air.Inst.Ref {15522) CompileError!Air.Inst.Ref {
15523 const mod = sema.mod;
15411 const resolved_type = sema.typeOf(casted_lhs);15524 const resolved_type = sema.typeOf(casted_lhs);
15412 const runtime_src: LazySrcLoc = src: {15525 const runtime_src: LazySrcLoc = src: {
15413 if (try sema.resolveMaybeUndefVal(casted_lhs)) |lhs_val| {15526 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);
15415 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {15528 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) {15531 if (resolved_type.zigTypeTag(mod) == .Vector) {
15419 const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.bool);15532 const result_ty = try mod.vectorType(.{
15533 .len = resolved_type.vectorLen(mod),
15534 .child = .bool_type,
15535 });
15420 const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_type);15536 const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_type);
15421 return sema.addConstant(result_ty, cmp_val);15537 return sema.addConstant(result_ty, cmp_val);
15422 }15538 }
...@@ -15427,7 +15543,7 @@ fn cmpSelf(...@@ -15427,7 +15543,7 @@ fn cmpSelf(
15427 return Air.Inst.Ref.bool_false;15543 return Air.Inst.Ref.bool_false;
15428 }15544 }
15429 } else {15545 } else {
15430 if (resolved_type.zigTypeTag() == .Bool) {15546 if (resolved_type.zigTypeTag(mod) == .Bool) {
15431 // We can lower bool eq/neq more efficiently.15547 // We can lower bool eq/neq more efficiently.
15432 return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(), rhs_src);15548 return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(), rhs_src);
15433 }15549 }
...@@ -15436,9 +15552,9 @@ fn cmpSelf(...@@ -15436,9 +15552,9 @@ fn cmpSelf(
15436 } else {15552 } else {
15437 // For bools, we still check the other operand, because we can lower15553 // For bools, we still check the other operand, because we can lower
15438 // bool eq/neq more efficiently.15554 // bool eq/neq more efficiently.
15439 if (resolved_type.zigTypeTag() == .Bool) {15555 if (resolved_type.zigTypeTag(mod) == .Bool) {
15440 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {15556 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);
15442 return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src);15558 return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src);
15443 }15559 }
15444 }15560 }
...@@ -15446,7 +15562,7 @@ fn cmpSelf(...@@ -15446,7 +15562,7 @@ fn cmpSelf(
15446 }15562 }
15447 };15563 };
15448 try sema.requireRuntimeBlock(block, src, runtime_src);15564 try sema.requireRuntimeBlock(block, src, runtime_src);
15449 if (resolved_type.zigTypeTag() == .Vector) {15565 if (resolved_type.zigTypeTag(mod) == .Vector) {
15450 return block.addCmpVector(casted_lhs, casted_rhs, op);15566 return block.addCmpVector(casted_lhs, casted_rhs, op);
15451 }15567 }
15452 const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized);15568 const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized);
...@@ -15475,16 +15591,17 @@ fn runtimeBoolCmp(...@@ -15475,16 +15591,17 @@ fn runtimeBoolCmp(
15475}15591}
1547615592
15477fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {15593fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15594 const mod = sema.mod;
15478 const inst_data = sema.code.instructions.items(.data)[inst].un_node;15595 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
15479 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };15596 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
15480 const ty = try sema.resolveType(block, operand_src, inst_data.operand);15597 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
15481 switch (ty.zigTypeTag()) {15598 switch (ty.zigTypeTag(mod)) {
15482 .Fn,15599 .Fn,
15483 .NoReturn,15600 .NoReturn,
15484 .Undefined,15601 .Undefined,
15485 .Null,15602 .Null,
15486 .Opaque,15603 .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
15489 .Type,15606 .Type,
15490 .EnumLiteral,15607 .EnumLiteral,
...@@ -15509,25 +15626,25 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15509,25 +15626,25 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15509 .AnyFrame,15626 .AnyFrame,
15510 => {},15627 => {},
15511 }15628 }
15512 const target = sema.mod.getTarget();15629 const val = try ty.lazyAbiSize(mod);
15513 const val = try ty.lazyAbiSize(target, sema.arena);15630 if (val.isLazySize(mod)) {
15514 if (val.tag() == .lazy_size) {
15515 try sema.queueFullTypeResolution(ty);15631 try sema.queueFullTypeResolution(ty);
15516 }15632 }
15517 return sema.addConstant(Type.comptime_int, val);15633 return sema.addConstant(Type.comptime_int, val);
15518}15634}
1551915635
15520fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {15636fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15637 const mod = sema.mod;
15521 const inst_data = sema.code.instructions.items(.data)[inst].un_node;15638 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
15522 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };15639 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
15523 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);15640 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
15524 switch (operand_ty.zigTypeTag()) {15641 switch (operand_ty.zigTypeTag(mod)) {
15525 .Fn,15642 .Fn,
15526 .NoReturn,15643 .NoReturn,
15527 .Undefined,15644 .Undefined,
15528 .Null,15645 .Null,
15529 .Opaque,15646 .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
15532 .Type,15649 .Type,
15533 .EnumLiteral,15650 .EnumLiteral,
...@@ -15552,8 +15669,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -15552,8 +15669,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
15552 .AnyFrame,15669 .AnyFrame,
15553 => {},15670 => {},
15554 }15671 }
15555 const target = sema.mod.getTarget();15672 const bit_size = try operand_ty.bitSizeAdvanced(mod, sema);
15556 const bit_size = try operand_ty.bitSizeAdvanced(target, sema);
15557 return sema.addIntUnsigned(Type.comptime_int, bit_size);15673 return sema.addIntUnsigned(Type.comptime_int, bit_size);
15558}15674}
1555915675
...@@ -15562,17 +15678,13 @@ fn zirThis(...@@ -15562,17 +15678,13 @@ fn zirThis(
15562 block: *Block,15678 block: *Block,
15563 extended: Zir.Inst.Extended.InstData,15679 extended: Zir.Inst.Extended.InstData,
15564) CompileError!Air.Inst.Ref {15680) 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);
15566 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));15683 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
15567 return sema.analyzeDeclVal(block, src, this_decl_index);15684 return sema.analyzeDeclVal(block, src, this_decl_index);
15568}15685}
1556915686
15570fn zirClosureCapture(15687fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
15571 sema: *Sema,
15572 block: *Block,
15573 inst: Zir.Inst.Index,
15574) CompileError!void {
15575 // TODO: Compile error when closed over values are modified
15576 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;15688 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
15577 // Closures are not necessarily constant values. For example, the15689 // Closures are not necessarily constant values. For example, the
15578 // code might do something like this:15690 // code might do something like this:
...@@ -15580,26 +15692,24 @@ fn zirClosureCapture(...@@ -15580,26 +15692,24 @@ fn zirClosureCapture(
15580 // ...in which case the closure_capture instruction has access to a runtime15692 // ...in which case the closure_capture instruction has access to a runtime
15581 // value only. In such case we preserve the type and use a dummy runtime value.15693 // value only. In such case we preserve the type and use a dummy runtime value.
15582 const operand = try sema.resolveInst(inst_data.operand);15694 const operand = try sema.resolveInst(inst_data.operand);
15583 const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse15695 const ty = sema.typeOf(operand);
15584 Value.initTag(.unreachable_value);15696 const capture: CaptureScope.Capture = blk: {
1558515697 if (try sema.resolveMaybeUndefValAllowVariables(operand)) |val| {
15586 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{15698 const ip_index = try val.intern(ty, sema.mod);
15587 .ty = try sema.typeOf(operand).copy(sema.perm_arena),15699 break :blk .{ .comptime_val = ip_index };
15588 .val = try val.copy(sema.perm_arena),15700 }
15589 });15701 break :blk .{ .runtime_val = ty.toIntern() };
15702 };
15703 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, capture);
15590}15704}
1559115705
15592fn zirClosureGet(15706fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15593 sema: *Sema,15707 const mod = sema.mod;
15594 block: *Block,
15595 inst: Zir.Inst.Index,
15596) CompileError!Air.Inst.Ref {
15597 // TODO CLOSURE: Test this with inline functions
15598 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;15708 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.?;
15600 // Note: The target closure must be in this scope list.15710 // Note: The target closure must be in this scope list.
15601 // If it's not here, the zir is invalid, or the list is broken.15711 // If it's not here, the zir is invalid, or the list is broken.
15602 const tv = while (true) {15712 const capture = while (true) {
15603 // Note: We don't need to add a dependency here, because15713 // Note: We don't need to add a dependency here, because
15604 // decls always depend on their lexical parents.15714 // decls always depend on their lexical parents.
1560515715
...@@ -15612,17 +15722,17 @@ fn zirClosureGet(...@@ -15612,17 +15722,17 @@ fn zirClosureGet(
15612 }15722 }
15613 return error.AnalysisFail;15723 return error.AnalysisFail;
15614 }15724 }
15615 if (scope.captures.getPtr(inst_data.inst)) |tv| {15725 if (scope.captures.get(inst_data.inst)) |capture| {
15616 break tv;15726 break capture;
15617 }15727 }
15618 scope = scope.parent.?;15728 scope = scope.parent.?;
15619 };15729 };
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) {
15622 const msg = msg: {15732 const msg = msg: {
15623 const name = name: {15733 const name = name: {
15624 const file = sema.owner_decl.getFileScope();15734 const file = sema.owner_decl.getFileScope(mod);
15625 const tree = file.getTree(sema.mod.gpa) catch |err| {15735 const tree = file.getTree(sema.gpa) catch |err| {
15626 // In this case we emit a warning + a less precise source location.15736 // In this case we emit a warning + a less precise source location.
15627 log.warn("unable to load {s}: {s}", .{15737 log.warn("unable to load {s}: {s}", .{
15628 file.sub_file_path, @errorName(err),15738 file.sub_file_path, @errorName(err),
...@@ -15646,11 +15756,11 @@ fn zirClosureGet(...@@ -15646,11 +15756,11 @@ fn zirClosureGet(
15646 return sema.failWithOwnedErrorMsg(msg);15756 return sema.failWithOwnedErrorMsg(msg);
15647 }15757 }
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) {
15650 const msg = msg: {15760 const msg = msg: {
15651 const name = name: {15761 const name = name: {
15652 const file = sema.owner_decl.getFileScope();15762 const file = sema.owner_decl.getFileScope(mod);
15653 const tree = file.getTree(sema.mod.gpa) catch |err| {15763 const tree = file.getTree(sema.gpa) catch |err| {
15654 // In this case we emit a warning + a less precise source location.15764 // In this case we emit a warning + a less precise source location.
15655 log.warn("unable to load {s}: {s}", .{15765 log.warn("unable to load {s}: {s}", .{
15656 file.sub_file_path, @errorName(err),15766 file.sub_file_path, @errorName(err),
...@@ -15676,13 +15786,17 @@ fn zirClosureGet(...@@ -15676,13 +15786,17 @@ fn zirClosureGet(
15676 return sema.failWithOwnedErrorMsg(msg);15786 return sema.failWithOwnedErrorMsg(msg);
15677 }15787 }
1567815788
15679 if (tv.val.tag() == .unreachable_value) {15789 switch (capture) {
15680 assert(block.is_typeof);15790 .runtime_val => |ty_ip_index| {
15681 // We need a dummy runtime instruction with the correct type.15791 assert(block.is_typeof);
15682 return block.addTy(.alloc, tv.ty);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 },
15683 }15799 }
15684
15685 return sema.addConstant(tv.ty, tv.val);
15686}15800}
1568715801
15688fn zirRetAddr(15802fn zirRetAddr(
...@@ -15717,345 +15831,422 @@ fn zirBuiltinSrc(...@@ -15717,345 +15831,422 @@ fn zirBuiltinSrc(
15717 const tracy = trace(@src());15831 const tracy = trace(@src());
15718 defer tracy.end();15832 defer tracy.end();
1571915833
15834 const mod = sema.mod;
15720 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;15835 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;
15721 const src = LazySrcLoc.nodeOffset(extra.node);15836 const src = LazySrcLoc.nodeOffset(extra.node);
15722 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});15837 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
15725 const func_name_val = blk: {15840 const func_name_val = blk: {
15726 var anon_decl = try block.startAnonDecl();15841 var anon_decl = try block.startAnonDecl();
15727 defer anon_decl.deinit();15842 defer anon_decl.deinit();
15728 const name = std.mem.span(fn_owner_decl.name);15843 // TODO: write something like getCoercedInts to avoid needing to dupe
15729 const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);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 });
15730 const new_decl = try anon_decl.finish(15850 const new_decl = try anon_decl.finish(
15731 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len - 1),15851 new_decl_ty,
15732 try Value.Tag.bytes.create(anon_decl.arena(), bytes),15852 (try mod.intern(.{ .aggregate = .{
15853 .ty = new_decl_ty.toIntern(),
15854 .storage = .{ .bytes = name },
15855 } })).toValue(),
15733 0, // default alignment15856 0, // default alignment
15734 );15857 );
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 } });
15736 };15863 };
1573715864
15738 const file_name_val = blk: {15865 const file_name_val = blk: {
15739 var anon_decl = try block.startAnonDecl();15866 var anon_decl = try block.startAnonDecl();
15740 defer anon_decl.deinit();15867 defer anon_decl.deinit();
15741 // The compiler must not call realpath anywhere.15868 // 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 });
15743 const new_decl = try anon_decl.finish(15875 const new_decl = try anon_decl.finish(
15744 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), name.len),15876 new_decl_ty,
15745 try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),15877 (try mod.intern(.{ .aggregate = .{
15878 .ty = new_decl_ty.toIntern(),
15879 .storage = .{ .bytes = name },
15880 } })).toValue(),
15746 0, // default alignment15881 0, // default alignment
15747 );15882 );
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 } });
15749 };15888 };
1575015889
15751 const field_values = try sema.arena.alloc(Value, 4);15890 const src_loc_ty = try sema.getBuiltinType("SourceLocation");
15752 // file: [:0]const u8,15891 const fields = .{
15753 field_values[0] = file_name_val;15892 // file: [:0]const u8,
15754 // fn_name: [:0]const u8,15893 file_name_val,
15755 field_values[1] = func_name_val;15894 // fn_name: [:0]const u8,
15756 // line: u3215895 func_name_val,
15757 field_values[2] = try Value.Tag.runtime_value.create(sema.arena, try Value.Tag.int_u64.create(sema.arena, extra.line + 1));15896 // line: u32,
15758 // column: u32,15897 try mod.intern(.{ .runtime_value = .{
15759 field_values[3] = try Value.Tag.int_u64.create(sema.arena, extra.column + 1);15898 .ty = .u32_type,
1576015899 .val = (try mod.intValue(Type.u32, extra.line + 1)).toIntern(),
15761 return sema.addConstant(15900 } }),
15762 try sema.getBuiltinType("SourceLocation"),15901 // column: u32,
15763 try Value.Tag.aggregate.create(sema.arena, field_values),15902 (try mod.intValue(Type.u32, extra.column + 1)).toIntern(),
15764 );15903 };
15904 return sema.addConstant(src_loc_ty, (try mod.intern(.{ .aggregate = .{
15905 .ty = src_loc_ty.toIntern(),
15906 .storage = .{ .elems = &fields },
15907 } })).toValue());
15765}15908}
1576615909
15767fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {15910fn 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;
15768 const inst_data = sema.code.instructions.items(.data)[inst].un_node;15914 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
15769 const src = inst_data.src();15915 const src = inst_data.src();
15770 const ty = try sema.resolveType(block, src, inst_data.operand);15916 const ty = try sema.resolveType(block, src, inst_data.operand);
15771 const type_info_ty = try sema.getBuiltinType("Type");15917 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()) {15920 switch (ty.zigTypeTag(mod)) {
15775 .Type => return sema.addConstant(15921 .Type,
15776 type_info_ty,15922 .Void,
15777 try Value.Tag.@"union".create(sema.arena, .{15923 .Bool,
15778 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Type)),15924 .NoReturn,
15779 .val = Value.void,15925 .ComptimeFloat,
15780 }),15926 .ComptimeInt,
15781 ),15927 .Undefined,
15782 .Void => return sema.addConstant(15928 .Null,
15783 type_info_ty,15929 .EnumLiteral,
15784 try Value.Tag.@"union".create(sema.arena, .{15930 => |type_info_tag| return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
15785 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Void)),15931 .ty = type_info_ty.toIntern(),
15786 .val = Value.void,15932 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(type_info_tag))).toIntern(),
15787 }),15933 .val = .void_value,
15788 ),15934 } })).toValue()),
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 ),
15838 .Fn => {15935 .Fn => {
15839 // TODO: look into memoizing this result.15936 // TODO: look into memoizing this result.
15840 const info = ty.fnInfo();
15841
15842 var params_anon_decl = try block.startAnonDecl();15937 var params_anon_decl = try block.startAnonDecl();
15843 defer params_anon_decl.deinit();15938 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);
15846 for (param_vals, 0..) |*param_val, i| {15963 for (param_vals, 0..) |*param_val, i| {
15964 const info = mod.typeToFunc(ty).?;
15847 const param_ty = info.param_types[i];15965 const param_ty = info.param_types[i];
15848 const is_generic = param_ty.tag() == .generic_poison;15966 const is_generic = param_ty == .generic_poison_type;
15849 const param_ty_val = if (is_generic)15967 const param_ty_val = try ip.get(gpa, .{ .opt = .{
15850 Value.null15968 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
15851 else15969 .val = if (is_generic) .none else param_ty,
15852 try Value.Tag.opt_payload.create(15970 } });
15853 params_anon_decl.arena(),
15854 try Value.Tag.ty.create(params_anon_decl.arena(), try param_ty.copy(params_anon_decl.arena())),
15855 );
1585615971
15857 const is_noalias = blk: {15972 const is_noalias = blk: {
15858 const index = std.math.cast(u5, i) orelse break :blk false;15973 const index = std.math.cast(u5, i) orelse break :blk false;
15859 break :blk @truncate(u1, info.noalias_bits >> index) != 0;15974 break :blk @truncate(u1, info.noalias_bits >> index) != 0;
15860 };15975 };
1586115976
15862 const param_fields = try params_anon_decl.arena().create([3]Value);15977 const param_fields = .{
15863 param_fields.* = .{
15864 // is_generic: bool,15978 // is_generic: bool,
15865 Value.makeBool(is_generic),15979 Value.makeBool(is_generic).toIntern(),
15866 // is_noalias: bool,15980 // is_noalias: bool,
15867 Value.makeBool(is_noalias),15981 Value.makeBool(is_noalias).toIntern(),
15868 // type: ?type,15982 // type: ?type,
15869 param_ty_val,15983 param_ty_val,
15870 };15984 };
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 } });
15872 }15989 }
1587315990
15874 const args_val = v: {15991 const args_val = v: {
15875 const fn_info_decl_index = (try sema.namespaceLookup(15992 const new_decl_ty = try mod.arrayType(.{
15876 block,15993 .len = param_vals.len,
15877 src,15994 .child = param_info_ty.toIntern(),
15878 type_info_ty.getNamespace().?,15995 });
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);
15897 const new_decl = try params_anon_decl.finish(15996 const new_decl = try params_anon_decl.finish(
15898 try Type.Tag.array.create(params_anon_decl.arena(), .{15997 new_decl_ty,
15899 .len = param_vals.len,15998 (try mod.intern(.{ .aggregate = .{
15900 .elem_type = try param_ty.copy(params_anon_decl.arena()),15999 .ty = new_decl_ty.toIntern(),
15901 }),16000 .storage = .{ .elems = param_vals },
15902 try Value.Tag.aggregate.create(16001 } })).toValue(),
15903 params_anon_decl.arena(),
15904 param_vals,
15905 ),
15906 0, // default alignment16002 0, // default alignment
15907 );16003 );
15908 break :v try Value.Tag.slice.create(sema.arena, .{16004 break :v try mod.intern(.{ .ptr = .{
15909 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),16005 .ty = (try mod.ptrType(.{
15910 .len = try Value.Tag.int_u64.create(sema.arena, param_vals.len),16006 .child = param_info_ty.toIntern(),
15911 });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 } });
15912 };16015 };
1591316016
15914 const ret_ty_opt = if (info.return_type.tag() != .generic_poison)16017 const info = mod.typeToFunc(ty).?;
15915 try Value.Tag.opt_payload.create(16018 const ret_ty_opt = try mod.intern(.{ .opt = .{
15916 sema.arena,16019 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
15917 try Value.Tag.ty.create(sema.arena, info.return_type),16020 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
15918 )16021 } });
15919 else16022
15920 Value.null;16023 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1592116024
15922 const field_values = try sema.arena.create([6]Value);16025 const field_values = .{
15923 field_values.* = .{
15924 // calling_convention: CallingConvention,16026 // 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(),
15926 // alignment: comptime_int,16028 // 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(),
15928 // is_generic: bool,16030 // is_generic: bool,
15929 Value.makeBool(info.is_generic),16031 Value.makeBool(info.is_generic).toIntern(),
15930 // is_var_args: bool,16032 // is_var_args: bool,
15931 Value.makeBool(info.is_var_args),16033 Value.makeBool(info.is_var_args).toIntern(),
15932 // return_type: ?type,16034 // return_type: ?type,
15933 ret_ty_opt,16035 ret_ty_opt,
15934 // args: []const Fn.Param,16036 // args: []const Fn.Param,
15935 args_val,16037 args_val,
15936 };16038 };
1593716039 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
15938 return sema.addConstant(16040 .ty = type_info_ty.toIntern(),
15939 type_info_ty,16041 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn))).toIntern(),
15940 try Value.Tag.@"union".create(sema.arena, .{16042 .val = try mod.intern(.{ .aggregate = .{
15941 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Fn)),16043 .ty = fn_info_ty.toIntern(),
15942 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16044 .storage = .{ .elems = &field_values },
15943 }),16045 } }),
15944 );16046 } })).toValue());
15945 },16047 },
15946 .Int => {16048 .Int => {
15947 const info = ty.intInfo(target);16049 const int_info_decl_index = (try sema.namespaceLookup(
15948 const field_values = try sema.arena.alloc(Value, 2);16050 block,
15949 // signedness: Signedness,16051 src,
15950 field_values[0] = try Value.Tag.enum_field_index.create(16052 type_info_ty.getNamespaceIndex(mod).unwrap().?,
15951 sema.arena,16053 try ip.getOrPutString(gpa, "Int"),
15952 @enumToInt(info.signedness),16054 )).?;
15953 );16055 try mod.declareDeclDependency(sema.owner_decl_index, int_info_decl_index);
15954 // bits: comptime_int,16056 try sema.ensureDeclAnalyzed(int_info_decl_index);
15955 field_values[1] = try Value.Tag.int_u64.create(sema.arena, info.bits);16057 const int_info_decl = mod.declPtr(int_info_decl_index);
1595616058 const int_info_ty = int_info_decl.val.toType();
15957 return sema.addConstant(16059
15958 type_info_ty,16060 const signedness_ty = try sema.getBuiltinType("Signedness");
15959 try Value.Tag.@"union".create(sema.arena, .{16061 const info = ty.intInfo(mod);
15960 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Int)),16062 const field_values = .{
15961 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16063 // signedness: Signedness,
15962 }),16064 try (try mod.enumValueFieldIndex(signedness_ty, @enumToInt(info.signedness))).intern(signedness_ty, mod),
15963 );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());
15964 },16076 },
15965 .Float => {16077 .Float => {
15966 const field_values = try sema.arena.alloc(Value, 1);16078 const float_info_decl_index = (try sema.namespaceLookup(
15967 // bits: comptime_int,16079 block,
15968 field_values[0] = try Value.Tag.int_u64.create(sema.arena, ty.bitSize(target));16080 src,
1596916081 type_info_ty.getNamespaceIndex(mod).unwrap().?,
15970 return sema.addConstant(16082 try ip.getOrPutString(gpa, "Float"),
15971 type_info_ty,16083 )).?;
15972 try Value.Tag.@"union".create(sema.arena, .{16084 try mod.declareDeclDependency(sema.owner_decl_index, float_info_decl_index);
15973 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Float)),16085 try sema.ensureDeclAnalyzed(float_info_decl_index);
15974 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16086 const float_info_decl = mod.declPtr(float_info_decl_index);
15975 }),16087 const float_info_ty = float_info_decl.val.toType();
15976 );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());
15977 },16101 },
15978 .Pointer => {16102 .Pointer => {
15979 const info = ty.ptrInfo().data;16103 const info = ty.ptrInfo(mod);
15980 const alignment = if (info.@"align" != 0)16104 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")
15982 else16106 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);16109 const addrspace_ty = try sema.getBuiltinType("AddressSpace");
15986 field_values.* = .{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 = .{
15987 // size: Size,16136 // 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),
15989 // is_const: bool,16138 // is_const: bool,
15990 Value.makeBool(!info.mutable),16139 Value.makeBool(!info.mutable).toIntern(),
15991 // is_volatile: bool,16140 // is_volatile: bool,
15992 Value.makeBool(info.@"volatile"),16141 Value.makeBool(info.@"volatile").toIntern(),
15993 // alignment: comptime_int,16142 // alignment: comptime_int,
15994 alignment,16143 alignment.toIntern(),
15995 // address_space: AddressSpace16144 // 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),
15997 // child: type,16146 // child: type,
15998 try Value.Tag.ty.create(sema.arena, info.pointee_type),16147 info.pointee_type.toIntern(),
15999 // is_allowzero: bool,16148 // is_allowzero: bool,
16000 Value.makeBool(info.@"allowzero"),16149 Value.makeBool(info.@"allowzero").toIntern(),
16001 // sentinel: ?*const anyopaque,16150 // sentinel: ?*const anyopaque,
16002 try sema.optRefValue(block, info.pointee_type, info.sentinel),16151 (try sema.optRefValue(block, info.pointee_type, info.sentinel)).toIntern(),
16003 };16152 };
1600416153 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16005 return sema.addConstant(16154 .ty = type_info_ty.toIntern(),
16006 type_info_ty,16155 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Pointer))).toIntern(),
16007 try Value.Tag.@"union".create(sema.arena, .{16156 .val = try mod.intern(.{ .aggregate = .{
16008 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Pointer)),16157 .ty = pointer_ty.toIntern(),
16009 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16158 .storage = .{ .elems = &field_values },
16010 }),16159 } }),
16011 );16160 } })).toValue());
16012 },16161 },
16013 .Array => {16162 .Array => {
16014 const info = ty.arrayInfo();16163 const array_field_ty = t: {
16015 const field_values = try sema.arena.alloc(Value, 3);16164 const array_field_ty_decl_index = (try sema.namespaceLookup(
16016 // len: comptime_int,16165 block,
16017 field_values[0] = try Value.Tag.int_u64.create(sema.arena, info.len);16166 src,
16018 // child: type,16167 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16019 field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);16168 try ip.getOrPutString(gpa, "Array"),
16020 // sentinel: ?*const anyopaque,16169 )).?;
16021 field_values[2] = try sema.optRefValue(block, info.elem_type, info.sentinel);16170 try mod.declareDeclDependency(sema.owner_decl_index, array_field_ty_decl_index);
1602216171 try sema.ensureDeclAnalyzed(array_field_ty_decl_index);
16023 return sema.addConstant(16172 const array_field_ty_decl = mod.declPtr(array_field_ty_decl_index);
16024 type_info_ty,16173 break :t array_field_ty_decl.val.toType();
16025 try Value.Tag.@"union".create(sema.arena, .{16174 };
16026 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Array)),16175
16027 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16176 const info = ty.arrayInfo(mod);
16028 }),16177 const field_values = .{
16029 );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());
16030 },16193 },
16031 .Vector => {16194 .Vector => {
16032 const info = ty.arrayInfo();16195 const vector_field_ty = t: {
16033 const field_values = try sema.arena.alloc(Value, 2);16196 const vector_field_ty_decl_index = (try sema.namespaceLookup(
16034 // len: comptime_int,16197 block,
16035 field_values[0] = try Value.Tag.int_u64.create(sema.arena, info.len);16198 src,
16036 // child: type,16199 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16037 field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);16200 try ip.getOrPutString(gpa, "Vector"),
1603816201 )).?;
16039 return sema.addConstant(16202 try mod.declareDeclDependency(sema.owner_decl_index, vector_field_ty_decl_index);
16040 type_info_ty,16203 try sema.ensureDeclAnalyzed(vector_field_ty_decl_index);
16041 try Value.Tag.@"union".create(sema.arena, .{16204 const vector_field_ty_decl = mod.declPtr(vector_field_ty_decl_index);
16042 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Vector)),16205 break :t vector_field_ty_decl.val.toType();
16043 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16206 };
16044 }),16207
16045 );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());
16046 },16223 },
16047 .Optional => {16224 .Optional => {
16048 const field_values = try sema.arena.alloc(Value, 1);16225 const optional_field_ty = t: {
16049 // child: type,16226 const optional_field_ty_decl_index = (try sema.namespaceLookup(
16050 field_values[0] = try Value.Tag.ty.create(sema.arena, try ty.optionalChildAlloc(sema.arena));16227 block,
1605116228 src,
16052 return sema.addConstant(16229 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16053 type_info_ty,16230 try ip.getOrPutString(gpa, "Optional"),
16054 try Value.Tag.@"union".create(sema.arena, .{16231 )).?;
16055 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Optional)),16232 try mod.declareDeclDependency(sema.owner_decl_index, optional_field_ty_decl_index);
16056 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16233 try sema.ensureDeclAnalyzed(optional_field_ty_decl_index);
16057 }),16234 const optional_field_ty_decl = mod.declPtr(optional_field_ty_decl_index);
16058 );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());
16059 },16250 },
16060 .ErrorSet => {16251 .ErrorSet => {
16061 var fields_anon_decl = try block.startAnonDecl();16252 var fields_anon_decl = try block.startAnonDecl();
...@@ -16066,17 +16257,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16066,17 +16257,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16066 const set_field_ty_decl_index = (try sema.namespaceLookup(16257 const set_field_ty_decl_index = (try sema.namespaceLookup(
16067 block,16258 block,
16068 src,16259 src,
16069 type_info_ty.getNamespace().?,16260 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16070 "Error",16261 try ip.getOrPutString(gpa, "Error"),
16071 )).?;16262 )).?;
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);
16073 try sema.ensureDeclAnalyzed(set_field_ty_decl_index);16264 try sema.ensureDeclAnalyzed(set_field_ty_decl_index);
16074 const set_field_ty_decl = sema.mod.declPtr(set_field_ty_decl_index);16265 const set_field_ty_decl = mod.declPtr(set_field_ty_decl_index);
16075 var buffer: Value.ToTypeBuffer = undefined;16266 break :t set_field_ty_decl.val.toType();
16076 break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16077 };16267 };
1607816268
16079 try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena));16269 try sema.queueFullTypeResolution(error_field_ty);
1608016270
16081 // If the error set is inferred it must be resolved at this point16271 // If the error set is inferred it must be resolved at this point
16082 try sema.resolveInferredErrorSetTy(block, src, ty);16272 try sema.resolveInferredErrorSetTy(block, src, ty);
...@@ -16084,90 +16274,119 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16084,90 +16274,119 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16084 // Build our list of Error values16274 // Build our list of Error values
16085 // Optional value is only null if anyerror16275 // Optional value is only null if anyerror
16086 // Value can be zero-length slice otherwise16276 // Value can be zero-length slice otherwise
16087 const error_field_vals: ?[]Value = if (ty.isAnyError()) null else blk: {16277 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
16088 const names = ty.errorSetNames();16278 const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);
16089 const vals = try fields_anon_decl.arena().alloc(Value, names.len);
16090 for (vals, 0..) |*field_val, i| {16279 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]));
16092 const name_val = v: {16282 const name_val = v: {
16093 var anon_decl = try block.startAnonDecl();16283 var anon_decl = try block.startAnonDecl();
16094 defer anon_decl.deinit();16284 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 });
16096 const new_decl = try anon_decl.finish(16289 const new_decl = try anon_decl.finish(
16097 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),16290 new_decl_ty,
16098 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16291 (try mod.intern(.{ .aggregate = .{
16292 .ty = new_decl_ty.toIntern(),
16293 .storage = .{ .bytes = name },
16294 } })).toValue(),
16099 0, // default alignment16295 0, // default alignment
16100 );16296 );
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 } });
16102 };16302 };
1610316303
16104 const error_field_fields = try fields_anon_decl.arena().create([1]Value);16304 const error_field_fields = .{
16105 error_field_fields.* = .{
16106 // name: []const u8,16305 // name: []const u8,
16107 name_val,16306 name_val,
16108 };16307 };
1610916308 field_val.* = try mod.intern(.{ .aggregate = .{
16110 field_val.* = try Value.Tag.aggregate.create(16309 .ty = error_field_ty.toIntern(),
16111 fields_anon_decl.arena(),16310 .storage = .{ .elems = &error_field_fields },
16112 error_field_fields,16311 } });
16113 );
16114 }16312 }
1611516313
16116 break :blk vals;16314 break :blk vals;
16117 };16315 };
1611816316
16119 // Build our ?[]const Error value16317 // 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 });
16121 const new_decl = try fields_anon_decl.finish(16332 const new_decl = try fields_anon_decl.finish(
16122 try Type.Tag.array.create(fields_anon_decl.arena(), .{16333 array_errors_ty,
16123 .len = vals.len,16334 (try mod.intern(.{ .aggregate = .{
16124 .elem_type = error_field_ty,16335 .ty = array_errors_ty.toIntern(),
16125 }),16336 .storage = .{ .elems = vals },
16126 try Value.Tag.aggregate.create(16337 } })).toValue(),
16127 fields_anon_decl.arena(),
16128 vals,
16129 ),
16130 0, // default alignment16338 0, // default alignment
16131 );16339 );
1613216340 break :v try mod.intern(.{ .ptr = .{
16133 const new_decl_val = try Value.Tag.decl_ref.create(sema.arena, new_decl);16341 .ty = slice_errors_ty.toIntern(),
16134 const slice_val = try Value.Tag.slice.create(sema.arena, .{16342 .addr = .{ .decl = new_decl },
16135 .ptr = new_decl_val,16343 .len = (try mod.intValue(Type.usize, vals.len)).toIntern(),
16136 .len = try Value.Tag.int_u64.create(sema.arena, vals.len),16344 } });
16137 });16345 } else .none;
16138 break :v try Value.Tag.opt_payload.create(sema.arena, slice_val);16346 const errors_val = try mod.intern(.{ .opt = .{
16139 } else Value.null;16347 .ty = opt_slice_errors_ty.toIntern(),
16348 .val = errors_payload_val,
16349 } });
1614016350
16141 // Construct Type{ .ErrorSet = errors_val }16351 // Construct Type{ .ErrorSet = errors_val }
16142 return sema.addConstant(16352 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16143 type_info_ty,16353 .ty = type_info_ty.toIntern(),
16144 try Value.Tag.@"union".create(sema.arena, .{16354 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet))).toIntern(),
16145 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ErrorSet)),16355 .val = errors_val,
16146 .val = errors_val,16356 } })).toValue());
16147 }),
16148 );
16149 },16357 },
16150 .ErrorUnion => {16358 .ErrorUnion => {
16151 const field_values = try sema.arena.alloc(Value, 2);16359 const error_union_field_ty = t: {
16152 // error_set: type,16360 const error_union_field_ty_decl_index = (try sema.namespaceLookup(
16153 field_values[0] = try Value.Tag.ty.create(sema.arena, ty.errorUnionSet());16361 block,
16154 // payload: type,16362 src,
16155 field_values[1] = try Value.Tag.ty.create(sema.arena, ty.errorUnionPayload());16363 type_info_ty.getNamespaceIndex(mod).unwrap().?,
1615616364 try ip.getOrPutString(gpa, "ErrorUnion"),
16157 return sema.addConstant(16365 )).?;
16158 type_info_ty,16366 try mod.declareDeclDependency(sema.owner_decl_index, error_union_field_ty_decl_index);
16159 try Value.Tag.@"union".create(sema.arena, .{16367 try sema.ensureDeclAnalyzed(error_union_field_ty_decl_index);
16160 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ErrorUnion)),16368 const error_union_field_ty_decl = mod.declPtr(error_union_field_ty_decl_index);
16161 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16369 break :t error_union_field_ty_decl.val.toType();
16162 }),16370 };
16163 );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());
16164 },16386 },
16165 .Enum => {16387 .Enum => {
16166 // TODO: look into memoizing this result.16388 // TODO: look into memoizing this result.
16167 var int_tag_type_buffer: Type.Payload.Bits = undefined;16389 const is_exhaustive = Value.makeBool(ip.indexToKey(ty.toIntern()).enum_type.tag_mode != .nonexhaustive);
16168 const int_tag_ty = try ty.intTagType(&int_tag_type_buffer).copy(sema.arena);
16169
16170 const is_exhaustive = Value.makeBool(!ty.isNonexhaustiveEnum());
1617116390
16172 var fields_anon_decl = try block.startAnonDecl();16391 var fields_anon_decl = try block.startAnonDecl();
16173 defer fields_anon_decl.deinit();16392 defer fields_anon_decl.deinit();
...@@ -16176,88 +16395,121 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16176,88 +16395,121 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16176 const enum_field_ty_decl_index = (try sema.namespaceLookup(16395 const enum_field_ty_decl_index = (try sema.namespaceLookup(
16177 block,16396 block,
16178 src,16397 src,
16179 type_info_ty.getNamespace().?,16398 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16180 "EnumField",16399 try ip.getOrPutString(gpa, "EnumField"),
16181 )).?;16400 )).?;
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);
16183 try sema.ensureDeclAnalyzed(enum_field_ty_decl_index);16402 try sema.ensureDeclAnalyzed(enum_field_ty_decl_index);
16184 const enum_field_ty_decl = sema.mod.declPtr(enum_field_ty_decl_index);16403 const enum_field_ty_decl = mod.declPtr(enum_field_ty_decl_index);
16185 var buffer: Value.ToTypeBuffer = undefined;16404 break :t enum_field_ty_decl.val.toType();
16186 break :t try enum_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16187 };16405 };
1618816406
16189 const enum_fields = ty.enumFields();16407 const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.indexToKey(ty.toIntern()).enum_type.names.len);
16190 const enum_field_vals = try fields_anon_decl.arena().alloc(Value, enum_fields.count());
16191
16192 for (enum_field_vals, 0..) |*field_val, i| {16408 for (enum_field_vals, 0..) |*field_val, i| {
16193 var tag_val_payload: Value.Payload.U32 = .{16409 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
16194 .base = .{ .tag = .enum_field_index },16410 const value_val = if (enum_type.values.len > 0)
16195 .data = @intCast(u32, i),16411 try mod.intern_pool.getCoerced(gpa, enum_type.values[i], .comptime_int_type)
16196 };16412 else
16197 const tag_val = Value.initPayload(&tag_val_payload.base);16413 try mod.intern(.{ .int = .{
1619816414 .ty = .comptime_int_type,
16199 var buffer: Value.Payload.U64 = undefined;16415 .storage = .{ .u64 = @intCast(u64, i) },
16200 const int_val = try tag_val.enumToInt(ty, &buffer).copy(fields_anon_decl.arena());16416 } });
1620116417 // TODO: write something like getCoercedInts to avoid needing to dupe
16202 const name = enum_fields.keys()[i];16418 const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names[i]));
16203 const name_val = v: {16419 const name_val = v: {
16204 var anon_decl = try block.startAnonDecl();16420 var anon_decl = try block.startAnonDecl();
16205 defer anon_decl.deinit();16421 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 });
16207 const new_decl = try anon_decl.finish(16426 const new_decl = try anon_decl.finish(
16208 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),16427 new_decl_ty,
16209 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16428 (try mod.intern(.{ .aggregate = .{
16429 .ty = new_decl_ty.toIntern(),
16430 .storage = .{ .bytes = name },
16431 } })).toValue(),
16210 0, // default alignment16432 0, // default alignment
16211 );16433 );
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 } });
16213 };16439 };
1621416440
16215 const enum_field_fields = try fields_anon_decl.arena().create([2]Value);16441 const enum_field_fields = .{
16216 enum_field_fields.* = .{
16217 // name: []const u8,16442 // name: []const u8,
16218 name_val,16443 name_val,
16219 // value: comptime_int,16444 // value: comptime_int,
16220 int_val,16445 value_val,
16221 };16446 };
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 } });
16223 }16451 }
1622416452
16225 const fields_val = v: {16453 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 });
16226 const new_decl = try fields_anon_decl.finish(16459 const new_decl = try fields_anon_decl.finish(
16227 try Type.Tag.array.create(fields_anon_decl.arena(), .{16460 fields_array_ty,
16228 .len = enum_field_vals.len,16461 (try mod.intern(.{ .aggregate = .{
16229 .elem_type = enum_field_ty,16462 .ty = fields_array_ty.toIntern(),
16230 }),16463 .storage = .{ .elems = enum_field_vals },
16231 try Value.Tag.aggregate.create(16464 } })).toValue(),
16232 fields_anon_decl.arena(),
16233 enum_field_vals,
16234 ),
16235 0, // default alignment16465 0, // default alignment
16236 );16466 );
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 } });
16238 };16478 };
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);16495 const field_values = .{
16243 field_values.* = .{
16244 // tag_type: type,16496 // tag_type: type,
16245 try Value.Tag.ty.create(sema.arena, int_tag_ty),16497 ip.indexToKey(ty.toIntern()).enum_type.tag_ty,
16246 // fields: []const EnumField,16498 // fields: []const EnumField,
16247 fields_val,16499 fields_val,
16248 // decls: []const Declaration,16500 // decls: []const Declaration,
16249 decls_val,16501 decls_val,
16250 // is_exhaustive: bool,16502 // is_exhaustive: bool,
16251 is_exhaustive,16503 is_exhaustive.toIntern(),
16252 };16504 };
1625316505 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16254 return sema.addConstant(16506 .ty = type_info_ty.toIntern(),
16255 type_info_ty,16507 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum))).toIntern(),
16256 try Value.Tag.@"union".create(sema.arena, .{16508 .val = try mod.intern(.{ .aggregate = .{
16257 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Enum)),16509 .ty = type_enum_ty.toIntern(),
16258 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16510 .storage = .{ .elems = &field_values },
16259 }),16511 } }),
16260 );16512 } })).toValue());
16261 },16513 },
16262 .Union => {16514 .Union => {
16263 // TODO: look into memoizing this result.16515 // TODO: look into memoizing this result.
...@@ -16265,91 +16517,135 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16265,91 +16517,135 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16265 var fields_anon_decl = try block.startAnonDecl();16517 var fields_anon_decl = try block.startAnonDecl();
16266 defer fields_anon_decl.deinit();16518 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
16268 const union_field_ty = t: {16533 const union_field_ty = t: {
16269 const union_field_ty_decl_index = (try sema.namespaceLookup(16534 const union_field_ty_decl_index = (try sema.namespaceLookup(
16270 block,16535 block,
16271 src,16536 src,
16272 type_info_ty.getNamespace().?,16537 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16273 "UnionField",16538 try ip.getOrPutString(gpa, "UnionField"),
16274 )).?;16539 )).?;
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);
16276 try sema.ensureDeclAnalyzed(union_field_ty_decl_index);16541 try sema.ensureDeclAnalyzed(union_field_ty_decl_index);
16277 const union_field_ty_decl = sema.mod.declPtr(union_field_ty_decl_index);16542 const union_field_ty_decl = mod.declPtr(union_field_ty_decl_index);
16278 var buffer: Value.ToTypeBuffer = undefined;16543 break :t union_field_ty_decl.val.toType();
16279 break :t try union_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16280 };16544 };
1628116545
16282 const union_ty = try sema.resolveTypeFields(ty);16546 const union_ty = try sema.resolveTypeFields(ty);
16283 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout16547 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();16550 const union_fields = union_ty.unionFields(mod);
16287 const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count());16551 const union_field_vals = try gpa.alloc(InternPool.Index, union_fields.count());
16552 defer gpa.free(union_field_vals);
1628816553
16289 for (union_field_vals, 0..) |*field_val, i| {16554 for (union_field_vals, 0..) |*field_val, i| {
16290 const field = union_fields.values()[i];16555 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]));
16292 const name_val = v: {16558 const name_val = v: {
16293 var anon_decl = try block.startAnonDecl();16559 var anon_decl = try block.startAnonDecl();
16294 defer anon_decl.deinit();16560 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 });
16296 const new_decl = try anon_decl.finish(16565 const new_decl = try anon_decl.finish(
16297 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),16566 new_decl_ty,
16298 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16567 (try mod.intern(.{ .aggregate = .{
16568 .ty = new_decl_ty.toIntern(),
16569 .storage = .{ .bytes = name },
16570 } })).toValue(),
16299 0, // default alignment16571 0, // default alignment
16300 );16572 );
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 } });
16302 };16578 };
1630316579
16304 const union_field_fields = try fields_anon_decl.arena().create([3]Value);
16305 const alignment = switch (layout) {16580 const alignment = switch (layout) {
16306 .Auto, .Extern => try sema.unionFieldAlignment(field),16581 .Auto, .Extern => try sema.unionFieldAlignment(field),
16307 .Packed => 0,16582 .Packed => 0,
16308 };16583 };
1630916584
16310 union_field_fields.* = .{16585 const union_field_fields = .{
16311 // name: []const u8,16586 // name: []const u8,
16312 name_val,16587 name_val,
16313 // type: type,16588 // type: type,
16314 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),16589 field.ty.toIntern(),
16315 // alignment: comptime_int,16590 // alignment: comptime_int,
16316 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),16591 (try mod.intValue(Type.comptime_int, alignment)).toIntern(),
16317 };16592 };
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 } });
16319 }16597 }
1632016598
16321 const fields_val = v: {16599 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 });
16322 const new_decl = try fields_anon_decl.finish(16605 const new_decl = try fields_anon_decl.finish(
16323 try Type.Tag.array.create(fields_anon_decl.arena(), .{16606 array_fields_ty,
16324 .len = union_field_vals.len,16607 (try mod.intern(.{ .aggregate = .{
16325 .elem_type = union_field_ty,16608 .ty = array_fields_ty.toIntern(),
16326 }),16609 .storage = .{ .elems = union_field_vals },
16327 try Value.Tag.aggregate.create(16610 } })).toValue(),
16328 fields_anon_decl.arena(),
16329 try fields_anon_decl.arena().dupe(Value, union_field_vals),
16330 ),
16331 0, // default alignment16611 0, // default alignment
16332 );16612 );
16333 break :v try Value.Tag.slice.create(sema.arena, .{16613 break :v try mod.intern(.{ .ptr = .{
16334 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),16614 .ty = (try mod.ptrType(.{
16335 .len = try Value.Tag.int_u64.create(sema.arena, union_field_vals.len),16615 .child = union_field_ty.toIntern(),
16336 });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 } });
16337 };16624 };
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: {16628 const enum_tag_ty_val = try mod.intern(.{ .opt = .{
16342 const ty_val = try Value.Tag.ty.create(sema.arena, tag_ty);16629 .ty = (try mod.optionalType(.type_type)).toIntern(),
16343 break :v try Value.Tag.opt_payload.create(sema.arena, ty_val);16630 .val = if (union_ty.unionTagType(mod)) |tag_ty| tag_ty.toIntern() else .none,
16344 } else Value.null;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);16646 const field_values = .{
16347 field_values.* = .{
16348 // layout: ContainerLayout,16647 // layout: ContainerLayout,
16349 try Value.Tag.enum_field_index.create(16648 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).toIntern(),
16350 sema.arena,
16351 @enumToInt(layout),
16352 ),
1635316649
16354 // tag_type: ?type,16650 // tag_type: ?type,
16355 enum_tag_ty_val,16651 enum_tag_ty_val,
...@@ -16358,14 +16654,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16358,14 +16654,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16358 // decls: []const Declaration,16654 // decls: []const Declaration,
16359 decls_val,16655 decls_val,
16360 };16656 };
1636116657 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16362 return sema.addConstant(16658 .ty = type_info_ty.toIntern(),
16363 type_info_ty,16659 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union))).toIntern(),
16364 try Value.Tag.@"union".create(sema.arena, .{16660 .val = try mod.intern(.{ .aggregate = .{
16365 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Union)),16661 .ty = type_union_ty.toIntern(),
16366 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16662 .storage = .{ .elems = &field_values },
16367 }),16663 } }),
16368 );16664 } })).toValue());
16369 },16665 },
16370 .Struct => {16666 .Struct => {
16371 // TODO: look into memoizing this result.16667 // TODO: look into memoizing this result.
...@@ -16373,154 +16669,212 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16373,154 +16669,212 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16373 var fields_anon_decl = try block.startAnonDecl();16669 var fields_anon_decl = try block.startAnonDecl();
16374 defer fields_anon_decl.deinit();16670 defer fields_anon_decl.deinit();
1637516671
16376 const struct_field_ty = t: {16672 const type_struct_ty = t: {
16377 const struct_field_ty_decl_index = (try sema.namespaceLookup(16673 const type_struct_ty_decl_index = (try sema.namespaceLookup(
16378 block,16674 block,
16379 src,16675 src,
16380 type_info_ty.getNamespace().?,16676 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16381 "StructField",16677 try ip.getOrPutString(gpa, "Struct"),
16382 )).?;16678 )).?;
16383 try sema.mod.declareDeclDependency(sema.owner_decl_index, struct_field_ty_decl_index);16679 try mod.declareDeclDependency(sema.owner_decl_index, type_struct_ty_decl_index);
16384 try sema.ensureDeclAnalyzed(struct_field_ty_decl_index);16680 try sema.ensureDeclAnalyzed(type_struct_ty_decl_index);
16385 const struct_field_ty_decl = sema.mod.declPtr(struct_field_ty_decl_index);16681 const type_struct_ty_decl = mod.declPtr(type_struct_ty_decl_index);
16386 var buffer: Value.ToTypeBuffer = undefined;16682 break :t type_struct_ty_decl.val.toType();
16387 break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16388 };16683 };
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);16685 const struct_field_ty = t: {
16419 const field_val = tuple.values[i];16686 const struct_field_ty_decl_index = (try sema.namespaceLookup(
16420 const is_comptime = field_val.tag() != .unreachable_value;16687 block,
16421 const opt_default_val = if (is_comptime) field_val else null;16688 src,
16422 const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val);16689 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16423 struct_field_fields.* = .{16690 try ip.getOrPutString(gpa, "StructField"),
16424 // name: []const u8,16691 )).?;
16425 name_val,16692 try mod.declareDeclDependency(sema.owner_decl_index, struct_field_ty_decl_index);
16426 // type: type,16693 try sema.ensureDeclAnalyzed(struct_field_ty_decl_index);
16427 try Value.Tag.ty.create(fields_anon_decl.arena(), field_ty),16694 const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index);
16428 // default_value: ?*const anyopaque,16695 break :t struct_field_ty_decl.val.toType();
16429 try default_val_ptr.copy(fields_anon_decl.arena()),16696 };
16430 // is_comptime: bool,16697
16431 Value.makeBool(is_comptime),16698 const struct_ty = try sema.resolveTypeFields(ty);
16432 // alignment: comptime_int,16699 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16433 try field_ty.lazyAbiAlignment(target, fields_anon_decl.arena()),16700 const layout = struct_ty.containerLayout(mod);
16434 };16701
16435 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);16702 var struct_field_vals: []InternPool.Index = &.{};
16436 }16703 defer gpa.free(struct_field_vals);
16437 break :fv struct_field_vals;16704 fv: {
16438 }16705 const struct_type = switch (ip.indexToKey(struct_ty.toIntern())) {
16439 const struct_fields = struct_ty.structFields();16706 .anon_struct_type => |tuple| {
16440 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());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| {16740 const is_comptime = field_val != .none;
16443 const field = struct_fields.values()[i];16741 const opt_default_val = if (is_comptime) field_val.toValue() else null;
16444 const name = struct_fields.keys()[i];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));
16445 const name_val = v: {16775 const name_val = v: {
16446 var anon_decl = try block.startAnonDecl();16776 var anon_decl = try block.startAnonDecl();
16447 defer anon_decl.deinit();16777 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 });
16449 const new_decl = try anon_decl.finish(16782 const new_decl = try anon_decl.finish(
16450 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),16783 new_decl_ty,
16451 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16784 (try mod.intern(.{ .aggregate = .{
16785 .ty = new_decl_ty.toIntern(),
16786 .storage = .{ .bytes = name },
16787 } })).toValue(),
16452 0, // default alignment16788 0, // default alignment
16453 );16789 );
16454 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{16790 break :v try mod.intern(.{ .ptr = .{
16455 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),16791 .ty = .slice_const_u8_type,
16456 .len = try Value.Tag.int_u64.create(fields_anon_decl.arena(), bytes.len),16792 .addr = .{ .decl = new_decl },
16457 });16793 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16794 } });
16458 };16795 };
1645916796
16460 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);16797 const opt_default_val = if (field.default_val == .none)
16461 const opt_default_val = if (field.default_val.tag() == .unreachable_value)
16462 null16798 null
16463 else16799 else
16464 field.default_val;16800 field.default_val.toValue();
16465 const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val);16801 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 = .{
16469 // name: []const u8,16805 // name: []const u8,
16470 name_val,16806 name_val,
16471 // type: type,16807 // type: type,
16472 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),16808 field.ty.toIntern(),
16473 // default_value: ?*const anyopaque,16809 // default_value: ?*const anyopaque,
16474 try default_val_ptr.copy(fields_anon_decl.arena()),16810 default_val_ptr.toIntern(),
16475 // is_comptime: bool,16811 // is_comptime: bool,
16476 Value.makeBool(field.is_comptime),16812 Value.makeBool(field.is_comptime).toIntern(),
16477 // alignment: comptime_int,16813 // alignment: comptime_int,
16478 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),16814 (try mod.intValue(Type.comptime_int, alignment)).toIntern(),
16479 };16815 };
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 } });
16481 }16820 }
16482 break :fv struct_field_vals;16821 }
16483 };
1648416822
16485 const fields_val = v: {16823 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 });
16486 const new_decl = try fields_anon_decl.finish(16829 const new_decl = try fields_anon_decl.finish(
16487 try Type.Tag.array.create(fields_anon_decl.arena(), .{16830 array_fields_ty,
16488 .len = struct_field_vals.len,16831 (try mod.intern(.{ .aggregate = .{
16489 .elem_type = struct_field_ty,16832 .ty = array_fields_ty.toIntern(),
16490 }),16833 .storage = .{ .elems = struct_field_vals },
16491 try Value.Tag.aggregate.create(16834 } })).toValue(),
16492 fields_anon_decl.arena(),
16493 try fields_anon_decl.arena().dupe(Value, struct_field_vals),
16494 ),
16495 0, // default alignment16835 0, // default alignment
16496 );16836 );
16497 break :v try Value.Tag.slice.create(sema.arena, .{16837 break :v try mod.intern(.{ .ptr = .{
16498 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),16838 .ty = (try mod.ptrType(.{
16499 .len = try Value.Tag.int_u64.create(sema.arena, struct_field_vals.len),16839 .child = struct_field_ty.toIntern(),
16500 });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 } });
16501 };16848 };
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: {16852 const backing_integer_val = try mod.intern(.{ .opt = .{
16506 if (layout == .Packed) {16853 .ty = (try mod.optionalType(.type_type)).toIntern(),
16507 const struct_obj = struct_ty.castTag(.@"struct").?.data;16854 .val = if (layout == .Packed) val: {
16855 const struct_obj = mod.typeToStruct(struct_ty).?;
16508 assert(struct_obj.haveLayout());16856 assert(struct_obj.haveLayout());
16509 assert(struct_obj.backing_int_ty.isInt());16857 assert(struct_obj.backing_int_ty.isInt(mod));
16510 const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty);16858 break :val struct_obj.backing_int_ty.toIntern();
16511 break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val);16859 } else .none,
16512 } else {16860 } });
16513 break :blk Value.initTag(.null_value);16861
16514 }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();
16515 };16873 };
1651616874
16517 const field_values = try sema.arena.create([5]Value);16875 const field_values = [_]InternPool.Index{
16518 field_values.* = .{
16519 // layout: ContainerLayout,16876 // layout: ContainerLayout,
16520 try Value.Tag.enum_field_index.create(16877 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).toIntern(),
16521 sema.arena,
16522 @enumToInt(layout),
16523 ),
16524 // backing_integer: ?type,16878 // backing_integer: ?type,
16525 backing_integer_val,16879 backing_integer_val,
16526 // fields: []const StructField,16880 // fields: []const StructField,
...@@ -16528,36 +16882,48 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16528,36 +16882,48 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16528 // decls: []const Declaration,16882 // decls: []const Declaration,
16529 decls_val,16883 decls_val,
16530 // is_tuple: bool,16884 // is_tuple: bool,
16531 Value.makeBool(struct_ty.isTuple()),16885 Value.makeBool(struct_ty.isTuple(mod)).toIntern(),
16532 };16886 };
1653316887 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16534 return sema.addConstant(16888 .ty = type_info_ty.toIntern(),
16535 type_info_ty,16889 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct))).toIntern(),
16536 try Value.Tag.@"union".create(sema.arena, .{16890 .val = try mod.intern(.{ .aggregate = .{
16537 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Struct)),16891 .ty = type_struct_ty.toIntern(),
16538 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16892 .storage = .{ .elems = &field_values },
16539 }),16893 } }),
16540 );16894 } })).toValue());
16541 },16895 },
16542 .Opaque => {16896 .Opaque => {
16543 // TODO: look into memoizing this result.16897 // 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
16545 const opaque_ty = try sema.resolveTypeFields(ty);16912 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);16915 const field_values = .{
16549 field_values.* = .{
16550 // decls: []const Declaration,16916 // decls: []const Declaration,
16551 decls_val,16917 decls_val,
16552 };16918 };
1655316919 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16554 return sema.addConstant(16920 .ty = type_info_ty.toIntern(),
16555 type_info_ty,16921 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque))).toIntern(),
16556 try Value.Tag.@"union".create(sema.arena, .{16922 .val = try mod.intern(.{ .aggregate = .{
16557 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Opaque)),16923 .ty = type_opaque_ty.toIntern(),
16558 .val = try Value.Tag.aggregate.create(sema.arena, field_values),16924 .storage = .{ .elems = &field_values },
16559 }),16925 } }),
16560 );16926 } })).toValue());
16561 },16927 },
16562 .Frame => return sema.failWithUseOfAsync(block, src),16928 .Frame => return sema.failWithUseOfAsync(block, src),
16563 .AnyFrame => return sema.failWithUseOfAsync(block, src),16929 .AnyFrame => return sema.failWithUseOfAsync(block, src),
...@@ -16569,8 +16935,11 @@ fn typeInfoDecls(...@@ -16569,8 +16935,11 @@ fn typeInfoDecls(
16569 block: *Block,16935 block: *Block,
16570 src: LazySrcLoc,16936 src: LazySrcLoc,
16571 type_info_ty: Type,16937 type_info_ty: Type,
16572 opt_namespace: ?*Module.Namespace,16938 opt_namespace: Module.Namespace.OptionalIndex,
16573) CompileError!Value {16939) CompileError!InternPool.Index {
16940 const mod = sema.mod;
16941 const gpa = sema.gpa;
16942
16574 var decls_anon_decl = try block.startAnonDecl();16943 var decls_anon_decl = try block.startAnonDecl();
16575 defer decls_anon_decl.deinit();16944 defer decls_anon_decl.deinit();
1657616945
...@@ -16578,89 +16947,110 @@ fn typeInfoDecls(...@@ -16578,89 +16947,110 @@ fn typeInfoDecls(
16578 const declaration_ty_decl_index = (try sema.namespaceLookup(16947 const declaration_ty_decl_index = (try sema.namespaceLookup(
16579 block,16948 block,
16580 src,16949 src,
16581 type_info_ty.getNamespace().?,16950 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16582 "Declaration",16951 try mod.intern_pool.getOrPutString(gpa, "Declaration"),
16583 )).?;16952 )).?;
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);
16585 try sema.ensureDeclAnalyzed(declaration_ty_decl_index);16954 try sema.ensureDeclAnalyzed(declaration_ty_decl_index);
16586 const declaration_ty_decl = sema.mod.declPtr(declaration_ty_decl_index);16955 const declaration_ty_decl = mod.declPtr(declaration_ty_decl_index);
16587 var buffer: Value.ToTypeBuffer = undefined;16956 break :t declaration_ty_decl.val.toType();
16588 break :t try declaration_ty_decl.val.toType(&buffer).copy(decls_anon_decl.arena());
16589 };16957 };
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);
16593 defer decl_vals.deinit();16961 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);
16596 defer seen_namespaces.deinit();16964 defer seen_namespaces.deinit();
1659716965
16598 if (opt_namespace) |some| {16966 if (opt_namespace.unwrap()) |namespace_index| {
16599 try sema.typeInfoNamespaceDecls(block, decls_anon_decl.arena(), some, &decl_vals, &seen_namespaces);16967 const namespace = mod.namespacePtr(namespace_index);
16968 try sema.typeInfoNamespaceDecls(block, namespace, declaration_ty, &decl_vals, &seen_namespaces);
16600 }16969 }
1660116970
16971 const array_decl_ty = try mod.arrayType(.{
16972 .len = decl_vals.items.len,
16973 .child = declaration_ty.toIntern(),
16974 .sentinel = .none,
16975 });
16602 const new_decl = try decls_anon_decl.finish(16976 const new_decl = try decls_anon_decl.finish(
16603 try Type.Tag.array.create(decls_anon_decl.arena(), .{16977 array_decl_ty,
16604 .len = decl_vals.items.len,16978 (try mod.intern(.{ .aggregate = .{
16605 .elem_type = declaration_ty,16979 .ty = array_decl_ty.toIntern(),
16606 }),16980 .storage = .{ .elems = decl_vals.items },
16607 try Value.Tag.aggregate.create(16981 } })).toValue(),
16608 decls_anon_decl.arena(),
16609 try decls_anon_decl.arena().dupe(Value, decl_vals.items),
16610 ),
16611 0, // default alignment16982 0, // default alignment
16612 );16983 );
16613 return try Value.Tag.slice.create(sema.arena, .{16984 return try mod.intern(.{ .ptr = .{
16614 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),16985 .ty = (try mod.ptrType(.{
16615 .len = try Value.Tag.int_u64.create(sema.arena, decl_vals.items.len),16986 .child = declaration_ty.toIntern(),
16616 });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 } });
16617}16995}
1661816996
16619fn typeInfoNamespaceDecls(16997fn typeInfoNamespaceDecls(
16620 sema: *Sema,16998 sema: *Sema,
16621 block: *Block,16999 block: *Block,
16622 decls_anon_decl: Allocator,
16623 namespace: *Namespace,17000 namespace: *Namespace,
16624 decl_vals: *std.ArrayList(Value),17001 declaration_ty: Type,
17002 decl_vals: *std.ArrayList(InternPool.Index),
16625 seen_namespaces: *std.AutoHashMap(*Namespace, void),17003 seen_namespaces: *std.AutoHashMap(*Namespace, void),
16626) !void {17004) !void {
17005 const mod = sema.mod;
17006 const ip = &mod.intern_pool;
16627 const gop = try seen_namespaces.getOrPut(namespace);17007 const gop = try seen_namespaces.getOrPut(namespace);
16628 if (gop.found_existing) return;17008 if (gop.found_existing) return;
16629 const decls = namespace.decls.keys();17009 const decls = namespace.decls.keys();
16630 for (decls) |decl_index| {17010 for (decls) |decl_index| {
16631 const decl = sema.mod.declPtr(decl_index);17011 const decl = mod.declPtr(decl_index);
16632 if (decl.kind == .@"usingnamespace") {17012 if (decl.kind == .@"usingnamespace") {
16633 if (decl.analysis == .in_progress) continue;17013 if (decl.analysis == .in_progress) continue;
16634 try sema.mod.ensureDeclAnalyzed(decl_index);17014 try mod.ensureDeclAnalyzed(decl_index);
16635 var buf: Value.ToTypeBuffer = undefined;17015 const new_ns = decl.val.toType().getNamespace(mod).?;
16636 const new_ns = decl.val.toType(&buf).getNamespace().?;17016 try sema.typeInfoNamespaceDecls(block, new_ns, declaration_ty, decl_vals, seen_namespaces);
16637 try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces);
16638 continue;17017 continue;
16639 }17018 }
16640 if (decl.kind != .named) continue;17019 if (decl.kind != .named) continue;
16641 const name_val = v: {17020 const name_val = v: {
16642 var anon_decl = try block.startAnonDecl();17021 var anon_decl = try block.startAnonDecl();
16643 defer anon_decl.deinit();17022 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 });
16645 const new_decl = try anon_decl.finish(17029 const new_decl = try anon_decl.finish(
16646 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),17030 new_decl_ty,
16647 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),17031 (try mod.intern(.{ .aggregate = .{
17032 .ty = new_decl_ty.toIntern(),
17033 .storage = .{ .bytes = name },
17034 } })).toValue(),
16648 0, // default alignment17035 0, // default alignment
16649 );17036 );
16650 break :v try Value.Tag.slice.create(decls_anon_decl, .{17037 break :v try mod.intern(.{ .ptr = .{
16651 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),17038 .ty = .slice_const_u8_type,
16652 .len = try Value.Tag.int_u64.create(decls_anon_decl, bytes.len),17039 .addr = .{ .decl = new_decl },
16653 });17040 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
17041 } });
16654 };17042 };
1665517043
16656 const fields = try decls_anon_decl.create([2]Value);17044 const fields = .{
16657 fields.* = .{
16658 //name: []const u8,17045 //name: []const u8,
16659 name_val,17046 name_val,
16660 //is_pub: bool,17047 //is_pub: bool,
16661 Value.makeBool(decl.is_pub),17048 Value.makeBool(decl.is_pub).toIntern(),
16662 };17049 };
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 } }));
16664 }17054 }
16665}17055}
1666617056
...@@ -16695,7 +17085,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -16695,7 +17085,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1669517085
16696 const operand = try sema.resolveBody(&child_block, body, inst);17086 const operand = try sema.resolveBody(&child_block, body, inst);
16697 const operand_ty = sema.typeOf(operand);17087 const operand_ty = sema.typeOf(operand);
16698 if (operand_ty.tag() == .generic_poison) return error.GenericPoison;17088 if (operand_ty.isGenericPoison()) return error.GenericPoison;
16699 return sema.addType(operand_ty);17089 return sema.addType(operand_ty);
16700}17090}
1670117091
...@@ -16709,10 +17099,11 @@ fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -16709,10 +17099,11 @@ fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
16709}17099}
1671017100
16711fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) CompileError!Type {17101fn 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)) {
16713 .ComptimeInt => return Type.comptime_int,17104 .ComptimeInt => return Type.comptime_int,
16714 .Int => {17105 .Int => {
16715 const bits = operand.bitSize(sema.mod.getTarget());17106 const bits = operand.bitSize(mod);
16716 const count = if (bits == 0)17107 const count = if (bits == 0)
16717 017108 0
16718 else blk: {17109 else blk: {
...@@ -16723,14 +17114,14 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi...@@ -16723,14 +17114,14 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
16723 }17114 }
16724 break :blk count;17115 break :blk count;
16725 };17116 };
16726 return Module.makeIntType(sema.arena, .unsigned, count);17117 return mod.intType(.unsigned, count);
16727 },17118 },
16728 .Vector => {17119 .Vector => {
16729 const elem_ty = operand.elemType2();17120 const elem_ty = operand.elemType2(mod);
16730 const log2_elem_ty = try sema.log2IntType(block, elem_ty, src);17121 const log2_elem_ty = try sema.log2IntType(block, elem_ty, src);
16731 return Type.Tag.vector.create(sema.arena, .{17122 return mod.vectorType(.{
16732 .len = operand.vectorLen(),17123 .len = operand.vectorLen(mod),
16733 .elem_type = log2_elem_ty,17124 .child = log2_elem_ty.toIntern(),
16734 });17125 });
16735 },17126 },
16736 else => {},17127 else => {},
...@@ -16739,7 +17130,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi...@@ -16739,7 +17130,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
16739 block,17130 block,
16740 src,17131 src,
16741 "bit shifting operation expected integer type, found '{}'",17132 "bit shifting operation expected integer type, found '{}'",
16742 .{operand.fmt(sema.mod)},17133 .{operand.fmt(mod)},
16743 );17134 );
16744}17135}
1674517136
...@@ -16790,6 +17181,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -16790,6 +17181,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
16790 const tracy = trace(@src());17181 const tracy = trace(@src());
16791 defer tracy.end();17182 defer tracy.end();
1679217183
17184 const mod = sema.mod;
16793 const inst_data = sema.code.instructions.items(.data)[inst].un_node;17185 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
16794 const src = inst_data.src();17186 const src = inst_data.src();
16795 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };17187 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...@@ -16797,7 +17189,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1679717189
16798 const operand = try sema.coerce(block, Type.bool, uncasted_operand, operand_src);17190 const operand = try sema.coerce(block, Type.bool, uncasted_operand, operand_src);
16799 if (try sema.resolveMaybeUndefVal(operand)) |val| {17191 if (try sema.resolveMaybeUndefVal(operand)) |val| {
16800 return if (val.isUndef())17192 return if (val.isUndef(mod))
16801 sema.addConstUndef(Type.bool)17193 sema.addConstUndef(Type.bool)
16802 else if (val.toBool())17194 else if (val.toBool())
16803 Air.Inst.Ref.bool_false17195 Air.Inst.Ref.bool_false
...@@ -16817,6 +17209,7 @@ fn zirBoolBr(...@@ -16817,6 +17209,7 @@ fn zirBoolBr(
16817 const tracy = trace(@src());17209 const tracy = trace(@src());
16818 defer tracy.end();17210 defer tracy.end();
1681917211
17212 const mod = sema.mod;
16820 const datas = sema.code.instructions.items(.data);17213 const datas = sema.code.instructions.items(.data);
16821 const inst_data = datas[inst].bool_br;17214 const inst_data = datas[inst].bool_br;
16822 const lhs = try sema.resolveInst(inst_data.lhs);17215 const lhs = try sema.resolveInst(inst_data.lhs);
...@@ -16865,12 +17258,12 @@ fn zirBoolBr(...@@ -16865,12 +17258,12 @@ fn zirBoolBr(
16865 _ = try lhs_block.addBr(block_inst, lhs_result);17258 _ = try lhs_block.addBr(block_inst, lhs_result);
1686617259
16867 const rhs_result = try sema.resolveBody(rhs_block, body, inst);17260 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)) {
16869 _ = try rhs_block.addBr(block_inst, rhs_result);17262 _ = try rhs_block.addBr(block_inst, rhs_result);
16870 }17263 }
1687117264
16872 const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst);17265 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)) {
16874 if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| {17267 if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| {
16875 if (is_bool_or and rhs_val.toBool()) {17268 if (is_bool_or and rhs_val.toBool()) {
16876 return Air.Inst.Ref.bool_true;17269 return Air.Inst.Ref.bool_true;
...@@ -16920,9 +17313,10 @@ fn finishCondBr(...@@ -16920,9 +17313,10 @@ fn finishCondBr(
16920}17313}
1692117314
16922fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {17315fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
16923 switch (ty.zigTypeTag()) {17316 const mod = sema.mod;
17317 switch (ty.zigTypeTag(mod)) {
16924 .Optional, .Null, .Undefined => return,17318 .Optional, .Null, .Undefined => return,
16925 .Pointer => if (ty.isPtrLikeOptional()) return,17319 .Pointer => if (ty.isPtrLikeOptional(mod)) return,
16926 else => {},17320 else => {},
16927 }17321 }
16928 return sema.failWithExpectedOptionalType(block, src, ty);17322 return sema.failWithExpectedOptionalType(block, src, ty);
...@@ -16951,10 +17345,11 @@ fn zirIsNonNullPtr(...@@ -16951,10 +17345,11 @@ fn zirIsNonNullPtr(
16951 const tracy = trace(@src());17345 const tracy = trace(@src());
16952 defer tracy.end();17346 defer tracy.end();
1695317347
17348 const mod = sema.mod;
16954 const inst_data = sema.code.instructions.items(.data)[inst].un_node;17349 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
16955 const src = inst_data.src();17350 const src = inst_data.src();
16956 const ptr = try sema.resolveInst(inst_data.operand);17351 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));
16958 if ((try sema.resolveMaybeUndefVal(ptr)) == null) {17353 if ((try sema.resolveMaybeUndefVal(ptr)) == null) {
16959 return block.addUnOp(.is_non_null_ptr, ptr);17354 return block.addUnOp(.is_non_null_ptr, ptr);
16960 }17355 }
...@@ -16963,10 +17358,11 @@ fn zirIsNonNullPtr(...@@ -16963,10 +17358,11 @@ fn zirIsNonNullPtr(
16963}17358}
1696417359
16965fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {17360fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
16966 switch (ty.zigTypeTag()) {17361 const mod = sema.mod;
17362 switch (ty.zigTypeTag(mod)) {
16967 .ErrorSet, .ErrorUnion, .Undefined => return,17363 .ErrorSet, .ErrorUnion, .Undefined => return,
16968 else => return sema.fail(block, src, "expected error union type, found '{}'", .{17364 else => return sema.fail(block, src, "expected error union type, found '{}'", .{
16969 ty.fmt(sema.mod),17365 ty.fmt(mod),
16970 }),17366 }),
16971 }17367 }
16972}17368}
...@@ -16986,10 +17382,11 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -16986,10 +17382,11 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
16986 const tracy = trace(@src());17382 const tracy = trace(@src());
16987 defer tracy.end();17383 defer tracy.end();
1698817384
17385 const mod = sema.mod;
16989 const inst_data = sema.code.instructions.items(.data)[inst].un_node;17386 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
16990 const src = inst_data.src();17387 const src = inst_data.src();
16991 const ptr = try sema.resolveInst(inst_data.operand);17388 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));
16993 const loaded = try sema.analyzeLoad(block, src, ptr, src);17390 const loaded = try sema.analyzeLoad(block, src, ptr, src);
16994 return sema.analyzeIsNonErr(block, src, loaded);17391 return sema.analyzeIsNonErr(block, src, loaded);
16995}17392}
...@@ -17012,6 +17409,7 @@ fn zirCondbr(...@@ -17012,6 +17409,7 @@ fn zirCondbr(
17012 const tracy = trace(@src());17409 const tracy = trace(@src());
17013 defer tracy.end();17410 defer tracy.end();
1701417411
17412 const mod = sema.mod;
17015 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;17413 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
17016 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };17414 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };
17017 const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);17415 const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
...@@ -17052,8 +17450,8 @@ fn zirCondbr(...@@ -17052,8 +17450,8 @@ fn zirCondbr(
17052 const err_inst_data = sema.code.instructions.items(.data)[index].un_node;17450 const err_inst_data = sema.code.instructions.items(.data)[index].un_node;
17053 const err_operand = try sema.resolveInst(err_inst_data.operand);17451 const err_operand = try sema.resolveInst(err_inst_data.operand);
17054 const operand_ty = sema.typeOf(err_operand);17452 const operand_ty = sema.typeOf(err_operand);
17055 assert(operand_ty.zigTypeTag() == .ErrorUnion);17453 assert(operand_ty.zigTypeTag(mod) == .ErrorUnion);
17056 const result_ty = operand_ty.errorUnionSet();17454 const result_ty = operand_ty.errorUnionSet(mod);
17057 break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand);17455 break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand);
17058 };17456 };
1705917457
...@@ -17079,7 +17477,7 @@ fn zirCondbr(...@@ -17079,7 +17477,7 @@ fn zirCondbr(
17079 return always_noreturn;17477 return always_noreturn;
17080}17478}
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 {
17083 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;17481 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
17084 const src = inst_data.src();17482 const src = inst_data.src();
17085 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };17483 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!...@@ -17087,9 +17485,10 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
17087 const body = sema.code.extra[extra.end..][0..extra.data.body_len];17485 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
17088 const err_union = try sema.resolveInst(extra.data.operand);17486 const err_union = try sema.resolveInst(extra.data.operand);
17089 const err_union_ty = sema.typeOf(err_union);17487 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) {
17091 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{17490 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),
17093 });17492 });
17094 }17493 }
17095 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);17494 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!...@@ -17124,7 +17523,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
17124 return try_inst;17523 return try_inst;
17125}17524}
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 {
17128 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;17527 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
17129 const src = inst_data.src();17528 const src = inst_data.src();
17130 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };17529 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...@@ -17133,9 +17532,10 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
17133 const operand = try sema.resolveInst(extra.data.operand);17532 const operand = try sema.resolveInst(extra.data.operand);
17134 const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src);17533 const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src);
17135 const err_union_ty = sema.typeOf(err_union);17534 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) {
17137 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{17537 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),
17139 });17539 });
17140 }17540 }
17141 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);17541 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...@@ -17156,9 +17556,9 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
17156 _ = try sema.analyzeBodyInner(&sub_block, body);17556 _ = try sema.analyzeBodyInner(&sub_block, body);
1715717557
17158 const operand_ty = sema.typeOf(operand);17558 const operand_ty = sema.typeOf(operand);
17159 const ptr_info = operand_ty.ptrInfo().data;17559 const ptr_info = operand_ty.ptrInfo(mod);
17160 const res_ty = try Type.ptr(sema.arena, sema.mod, .{17560 const res_ty = try Type.ptr(sema.arena, mod, .{
17161 .pointee_type = err_union_ty.errorUnionPayload(),17561 .pointee_type = err_union_ty.errorUnionPayload(mod),
17162 .@"addrspace" = ptr_info.@"addrspace",17562 .@"addrspace" = ptr_info.@"addrspace",
17163 .mutable = ptr_info.mutable,17563 .mutable = ptr_info.mutable,
17164 .@"allowzero" = ptr_info.@"allowzero",17564 .@"allowzero" = ptr_info.@"allowzero",
...@@ -17254,16 +17654,17 @@ fn zirRetErrValue(...@@ -17254,16 +17654,17 @@ fn zirRetErrValue(
17254 block: *Block,17654 block: *Block,
17255 inst: Zir.Inst.Index,17655 inst: Zir.Inst.Index,
17256) CompileError!Zir.Inst.Index {17656) CompileError!Zir.Inst.Index {
17657 const mod = sema.mod;
17257 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;17658 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);
17259 const src = inst_data.src();17661 const src = inst_data.src();
17260
17261 // Return the error code from the function.17662 // Return the error code from the function.
17262 const kv = try sema.mod.getErrorValue(err_name);17663 const error_set_type = try mod.singleErrorSetType(err_name);
17263 const result_inst = try sema.addConstant(17664 const result_inst = try sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
17264 try Type.Tag.error_set_single.create(sema.arena, kv.key),17665 .ty = error_set_type.toIntern(),
17265 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),17666 .name = err_name,
17266 );17667 } })).toValue());
17267 return sema.analyzeRet(block, result_inst, src);17668 return sema.analyzeRet(block, result_inst, src);
17268}17669}
1726917670
...@@ -17275,16 +17676,17 @@ fn zirRetImplicit(...@@ -17275,16 +17676,17 @@ fn zirRetImplicit(
17275 const tracy = trace(@src());17676 const tracy = trace(@src());
17276 defer tracy.end();17677 defer tracy.end();
1727717678
17679 const mod = sema.mod;
17278 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;17680 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
17279 const operand = try sema.resolveInst(inst_data.operand);17681 const operand = try sema.resolveInst(inst_data.operand);
1728017682
17281 const r_brace_src = inst_data.src();17683 const r_brace_src = inst_data.src();
17282 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };17684 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);
17284 if (base_tag == .NoReturn) {17686 if (base_tag == .NoReturn) {
17285 const msg = msg: {17687 const msg = msg: {
17286 const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{17688 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),
17288 });17690 });
17289 errdefer msg.destroy(sema.gpa);17691 errdefer msg.destroy(sema.gpa);
17290 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});17692 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});
...@@ -17294,7 +17696,7 @@ fn zirRetImplicit(...@@ -17294,7 +17696,7 @@ fn zirRetImplicit(
17294 } else if (base_tag != .Void) {17696 } else if (base_tag != .Void) {
17295 const msg = msg: {17697 const msg = msg: {
17296 const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{17698 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),
17298 });17700 });
17299 errdefer msg.destroy(sema.gpa);17701 errdefer msg.destroy(sema.gpa);
17300 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});17702 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});
...@@ -17346,6 +17748,7 @@ fn retWithErrTracing(...@@ -17346,6 +17748,7 @@ fn retWithErrTracing(
17346 ret_tag: Air.Inst.Tag,17748 ret_tag: Air.Inst.Tag,
17347 operand: Air.Inst.Ref,17749 operand: Air.Inst.Ref,
17348) CompileError!Zir.Inst.Index {17750) CompileError!Zir.Inst.Index {
17751 const mod = sema.mod;
17349 const need_check = switch (is_non_err) {17752 const need_check = switch (is_non_err) {
17350 .bool_true => {17753 .bool_true => {
17351 _ = try block.addUnOp(ret_tag, operand);17754 _ = try block.addUnOp(ret_tag, operand);
...@@ -17357,7 +17760,7 @@ fn retWithErrTracing(...@@ -17357,7 +17760,7 @@ fn retWithErrTracing(
17357 const gpa = sema.gpa;17760 const gpa = sema.gpa;
17358 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");17761 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
17359 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);17762 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);
17361 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);17764 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
17362 const return_err_fn = try sema.getBuiltin("returnError");17765 const return_err_fn = try sema.getBuiltin("returnError");
17363 const args: [1]Air.Inst.Ref = .{err_return_trace};17766 const args: [1]Air.Inst.Ref = .{err_return_trace};
...@@ -17397,17 +17800,19 @@ fn retWithErrTracing(...@@ -17397,17 +17800,19 @@ fn retWithErrTracing(
17397}17800}
1739817801
17399fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {17802fn 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() and17806 return fn_ret_ty.isError(mod) and
17403 sema.mod.comp.bin_file.options.error_return_tracing;17807 mod.comp.bin_file.options.error_return_tracing;
17404}17808}
1740517809
17406fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {17810fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
17811 const mod = sema.mod;
17407 const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index;17812 const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index;
1740817813
17409 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;17814 if (!mod.backendSupportsFeature(.error_return_trace)) return;
17410 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;17815 if (!mod.comp.bin_file.options.error_return_tracing) return;
1741117816
17412 // This is only relevant at runtime.17817 // This is only relevant at runtime.
17413 if (block.is_comptime or block.is_typeof) return;17818 if (block.is_comptime or block.is_typeof) return;
...@@ -17415,7 +17820,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -17415,7 +17820,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
17415 const save_index = inst_data.operand == .none or b: {17820 const save_index = inst_data.operand == .none or b: {
17416 const operand = try sema.resolveInst(inst_data.operand);17821 const operand = try sema.resolveInst(inst_data.operand);
17417 const operand_ty = sema.typeOf(operand);17822 const operand_ty = sema.typeOf(operand);
17418 break :b operand_ty.isError();17823 break :b operand_ty.isError(mod);
17419 };17824 };
1742017825
17421 if (save_index)17826 if (save_index)
...@@ -17436,7 +17841,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -17436,7 +17841,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
17436 const tracy = trace(@src());17841 const tracy = trace(@src());
17437 defer tracy.end();17842 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: {
17440 var block = start_block;17845 var block = start_block;
17441 while (true) {17846 while (true) {
17442 if (block.label) |label| {17847 if (block.label) |label| {
...@@ -17462,22 +17867,21 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -17462,22 +17867,21 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1746217867
17463 assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere17868 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);
17466 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);17871 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);
17467}17872}
1746817873
17469fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {17874fn 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| {
17473 const op_ty = sema.typeOf(uncasted_operand);17881 const op_ty = sema.typeOf(uncasted_operand);
17474 switch (op_ty.zigTypeTag()) {17882 switch (op_ty.zigTypeTag(mod)) {
17475 .ErrorSet => {17883 .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa),
17476 try payload.data.addErrorSet(sema.gpa, op_ty);17884 .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa),
17477 },
17478 .ErrorUnion => {
17479 try payload.data.addErrorSet(sema.gpa, op_ty.errorUnionSet());
17480 },
17481 else => {},17885 else => {},
17482 }17886 }
17483 }17887 }
...@@ -17492,7 +17896,8 @@ fn analyzeRet(...@@ -17492,7 +17896,8 @@ fn analyzeRet(
17492 // Special case for returning an error to an inferred error set; we need to17896 // Special case for returning an error to an inferred error set; we need to
17493 // add the error tag to the inferred error set of the in-scope function, so17897 // add the error tag to the inferred error set of the in-scope function, so
17494 // that the coercion below works correctly.17898 // 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) {
17496 try sema.addToInferredErrorSet(uncasted_operand);17901 try sema.addToInferredErrorSet(uncasted_operand);
17497 }17902 }
17498 const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) {17903 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...@@ -17540,6 +17945,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17540 const tracy = trace(@src());17945 const tracy = trace(@src());
17541 defer tracy.end();17946 defer tracy.end();
1754217947
17948 const mod = sema.mod;
17543 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;17949 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;
17544 const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);17950 const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
17545 const elem_ty_src: LazySrcLoc = .{ .node_offset_ptr_elem = extra.data.src_node };17951 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...@@ -17552,46 +17958,54 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17552 const elem_ty = blk: {17958 const elem_ty = blk: {
17553 const air_inst = try sema.resolveInst(extra.data.elem_type);17959 const air_inst = try sema.resolveInst(extra.data.elem_type);
17554 const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| {17960 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)) {
17556 try sema.errNote(block, elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});17962 try sema.errNote(block, elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});
17557 }17963 }
17558 return err;17964 return err;
17559 };17965 };
17560 if (ty.tag() == .generic_poison) return error.GenericPoison;17966 if (ty.isGenericPoison()) return error.GenericPoison;
17561 break :blk ty;17967 break :blk ty;
17562 };17968 };
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
17565 var extra_i = extra.end;17975 var extra_i = extra.end;
1756617976
17567 const sentinel = if (inst_data.flags.has_sentinel) blk: {17977 const sentinel = if (inst_data.flags.has_sentinel) blk: {
17568 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);17978 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
17569 extra_i += 1;17979 extra_i += 1;
17570 break :blk (try sema.resolveInstConst(block, sentinel_src, ref, "pointer sentinel value must be comptime-known")).val;17980 const coerced = try sema.coerce(block, elem_ty, try sema.resolveInst(ref), sentinel_src);
17571 } else null;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: {
17574 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);17986 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
17575 extra_i += 1;17987 extra_i += 1;
17576 const coerced = try sema.coerce(block, Type.u32, try sema.resolveInst(ref), align_src);17988 const coerced = try sema.coerce(block, Type.u32, try sema.resolveInst(ref), align_src);
17577 const val = try sema.resolveConstValue(block, align_src, coerced, "pointer alignment must be comptime-known");17989 const val = try sema.resolveConstValue(block, align_src, coerced, "pointer alignment must be comptime-known");
17578 // Check if this happens to be the lazy alignment of our element type, in17990 // Check if this happens to be the lazy alignment of our element type, in
17579 // which case we can make this 0 without resolving it.17991 // which case we can make this 0 without resolving it.
17580 if (val.castTag(.lazy_align)) |payload| {17992 switch (mod.intern_pool.indexToKey(val.toIntern())) {
17581 if (payload.data.eql(elem_ty, sema.mod)) {17993 .int => |int| switch (int.storage) {
17582 break :blk 0;17994 .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.toIntern()) break :blk .none,
17583 }17995 else => {},
17996 },
17997 else => {},
17584 }17998 }
17585 const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(target, sema)).?);17999 const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(mod, sema)).?);
17586 try sema.validateAlign(block, align_src, abi_align);18000 try sema.validateAlign(block, align_src, abi_align);
17587 break :blk abi_align;18001 break :blk InternPool.Alignment.fromByteUnits(abi_align);
17588 } else 0;18002 } else .none;
1758918003
17590 const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {18004 const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {
17591 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);18005 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
17592 extra_i += 1;18006 extra_i += 1;
17593 break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer);18007 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
17596 const bit_offset = if (inst_data.flags.has_bit_range) blk: {18010 const bit_offset = if (inst_data.flags.has_bit_range) blk: {
17597 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);18011 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...@@ -17611,50 +18025,52 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17611 return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});18025 return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});
17612 }18026 }
1761318027
17614 if (elem_ty.zigTypeTag() == .NoReturn) {18028 if (elem_ty.zigTypeTag(mod) == .Fn) {
17615 return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{});
17616 } else if (elem_ty.zigTypeTag() == .Fn) {
17617 if (inst_data.size != .One) {18029 if (inst_data.size != .One) {
17618 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});18030 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});
17619 }18031 }
17620 const fn_align = elem_ty.fnInfo().alignment;18032 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
17621 if (inst_data.flags.has_align and abi_align != 0 and fn_align != 0 and18033 if (inst_data.flags.has_align and abi_align != .none and fn_align != .none and
17622 abi_align != fn_align)18034 abi_align != fn_align)
17623 {18035 {
17624 return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{});18036 return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{});
17625 }18037 }
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) {
17627 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});18039 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
17628 } else if (inst_data.size == .C) {18040 } else if (inst_data.size == .C) {
17629 if (!try sema.validateExternType(elem_ty, .other)) {18041 if (!try sema.validateExternType(elem_ty, .other)) {
17630 const msg = msg: {18042 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)});
17632 errdefer msg.destroy(sema.gpa);18044 errdefer msg.destroy(sema.gpa);
1763318045
17634 const src_decl = sema.mod.declPtr(block.src_decl);18046 const src_decl = mod.declPtr(block.src_decl);
17635 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);18047 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl, mod), elem_ty, .other);
1763618048
17637 try sema.addDeclaredHereNote(msg, elem_ty);18049 try sema.addDeclaredHereNote(msg, elem_ty);
17638 break :msg msg;18050 break :msg msg;
17639 };18051 };
17640 return sema.failWithOwnedErrorMsg(msg);18052 return sema.failWithOwnedErrorMsg(msg);
17641 }18053 }
17642 if (elem_ty.zigTypeTag() == .Opaque) {18054 if (elem_ty.zigTypeTag(mod) == .Opaque) {
17643 return sema.fail(block, elem_ty_src, "C pointers cannot point to opaque types", .{});18055 return sema.fail(block, elem_ty_src, "C pointers cannot point to opaque types", .{});
17644 }18056 }
17645 }18057 }
1764618058
17647 const ty = try Type.ptr(sema.arena, sema.mod, .{18059 const ty = try mod.ptrType(.{
17648 .pointee_type = elem_ty,18060 .child = elem_ty.toIntern(),
17649 .sentinel = sentinel,18061 .sentinel = sentinel,
17650 .@"align" = abi_align,18062 .flags = .{
17651 .@"addrspace" = address_space,18063 .alignment = abi_align,
17652 .bit_offset = bit_offset,18064 .address_space = address_space,
17653 .host_size = host_size,18065 .is_const = !inst_data.flags.is_mutable,
17654 .mutable = inst_data.flags.is_mutable,18066 .is_allowzero = inst_data.flags.is_allowzero,
17655 .@"allowzero" = inst_data.flags.is_allowzero,18067 .is_volatile = inst_data.flags.is_volatile,
17656 .@"volatile" = inst_data.flags.is_volatile,18068 .size = inst_data.size,
17657 .size = inst_data.size,18069 },
18070 .packed_offset = .{
18071 .bit_offset = bit_offset,
18072 .host_size = host_size,
18073 },
17658 });18074 });
17659 return sema.addType(ty);18075 return sema.addType(ty);
17660}18076}
...@@ -17666,8 +18082,9 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -17666,8 +18082,9 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
17666 const inst_data = sema.code.instructions.items(.data)[inst].un_node;18082 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
17667 const src = inst_data.src();18083 const src = inst_data.src();
17668 const obj_ty = try sema.resolveType(block, src, inst_data.operand);18084 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)) {
17671 .Struct => return sema.structInitEmpty(block, obj_ty, src, src),18088 .Struct => return sema.structInitEmpty(block, obj_ty, src, src),
17672 .Array, .Vector => return sema.arrayInitEmpty(block, src, obj_ty),18089 .Array, .Vector => return sema.arrayInitEmpty(block, src, obj_ty),
17673 .Void => return sema.addConstant(obj_ty, Value.void),18090 .Void => return sema.addConstant(obj_ty, Value.void),
...@@ -17683,12 +18100,13 @@ fn structInitEmpty(...@@ -17683,12 +18100,13 @@ fn structInitEmpty(
17683 dest_src: LazySrcLoc,18100 dest_src: LazySrcLoc,
17684 init_src: LazySrcLoc,18101 init_src: LazySrcLoc,
17685) CompileError!Air.Inst.Ref {18102) CompileError!Air.Inst.Ref {
18103 const mod = sema.mod;
17686 const gpa = sema.gpa;18104 const gpa = sema.gpa;
17687 // This logic must be synchronized with that in `zirStructInit`.18105 // This logic must be synchronized with that in `zirStructInit`.
17688 const struct_ty = try sema.resolveTypeFields(obj_ty);18106 const struct_ty = try sema.resolveTypeFields(obj_ty);
1768918107
17690 // The init values to use for the struct instance.18108 // 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));
17692 defer gpa.free(field_inits);18110 defer gpa.free(field_inits);
17693 @memset(field_inits, .none);18111 @memset(field_inits, .none);
1769418112
...@@ -17696,20 +18114,19 @@ fn structInitEmpty(...@@ -17696,20 +18114,19 @@ fn structInitEmpty(
17696}18114}
1769718115
17698fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {18116fn 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);
17700 if (arr_len != 0) {18119 if (arr_len != 0) {
17701 if (obj_ty.zigTypeTag() == .Array) {18120 if (obj_ty.zigTypeTag(mod) == .Array) {
17702 return sema.fail(block, src, "expected {d} array elements; found 0", .{arr_len});18121 return sema.fail(block, src, "expected {d} array elements; found 0", .{arr_len});
17703 } else {18122 } else {
17704 return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len});18123 return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len});
17705 }18124 }
17706 }18125 }
17707 if (obj_ty.sentinel()) |sentinel| {18126 return sema.addConstant(obj_ty, (try mod.intern(.{ .aggregate = .{
17708 const val = try Value.Tag.empty_array_sentinel.create(sema.arena, sentinel);18127 .ty = obj_ty.toIntern(),
17709 return sema.addConstant(obj_ty, val);18128 .storage = .{ .elems = &.{} },
17710 } else {18129 } })).toValue());
17711 return sema.addConstant(obj_ty, Value.initTag(.empty_array));
17712 }
17713}18130}
1771418131
17715fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {18132fn 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...@@ -17719,7 +18136,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
17719 const init_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };18136 const init_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
17720 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;18137 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
17721 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);18138 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");
17723 const init = try sema.resolveInst(extra.init);18140 const init = try sema.resolveInst(extra.init);
17724 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);18141 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);
17725}18142}
...@@ -17731,21 +18148,23 @@ fn unionInit(...@@ -17731,21 +18148,23 @@ fn unionInit(
17731 init_src: LazySrcLoc,18148 init_src: LazySrcLoc,
17732 union_ty: Type,18149 union_ty: Type,
17733 union_ty_src: LazySrcLoc,18150 union_ty_src: LazySrcLoc,
17734 field_name: []const u8,18151 field_name: InternPool.NullTerminatedString,
17735 field_src: LazySrcLoc,18152 field_src: LazySrcLoc,
17736) CompileError!Air.Inst.Ref {18153) CompileError!Air.Inst.Ref {
18154 const mod = sema.mod;
17737 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src);18155 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];
17739 const init = try sema.coerce(block, field.ty, uncasted_init, init_src);18157 const init = try sema.coerce(block, field.ty, uncasted_init, init_src);
1774018158
17741 if (try sema.resolveMaybeUndefVal(init)) |init_val| {18159 if (try sema.resolveMaybeUndefVal(init)) |init_val| {
17742 const tag_ty = union_ty.unionTagTypeHypothetical();18160 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
17743 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);18161 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);
17744 const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);18162 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
17745 return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{18163 return sema.addConstant(union_ty, (try mod.intern(.{ .un = .{
17746 .tag = tag_val,18164 .ty = union_ty.toIntern(),
17747 .val = init_val,18165 .tag = try tag_val.intern(tag_ty, mod),
17748 }));18166 .val = try init_val.intern(field.ty, mod),
18167 } })).toValue());
17749 }18168 }
1775018169
17751 try sema.requireRuntimeBlock(block, init_src, null);18170 try sema.requireRuntimeBlock(block, init_src, null);
...@@ -17766,29 +18185,30 @@ fn zirStructInit(...@@ -17766,29 +18185,30 @@ fn zirStructInit(
17766 const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);18185 const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
17767 const src = inst_data.src();18186 const src = inst_data.src();
1776818187
18188 const mod = sema.mod;
17769 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;18189 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
17770 const first_field_type_data = zir_datas[first_item.field_type].pl_node;18190 const first_field_type_data = zir_datas[first_item.field_type].pl_node;
17771 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;18191 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
17772 const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type);18192 const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type);
17773 try sema.resolveTypeLayout(resolved_ty);18193 try sema.resolveTypeLayout(resolved_ty);
1777418194
17775 if (resolved_ty.zigTypeTag() == .Struct) {18195 if (resolved_ty.zigTypeTag(mod) == .Struct) {
17776 // This logic must be synchronized with that in `zirStructInitEmpty`.18196 // This logic must be synchronized with that in `zirStructInitEmpty`.
1777718197
17778 // Maps field index to field_type index of where it was already initialized.18198 // Maps field index to field_type index of where it was already initialized.
17779 // For making sure all fields are accounted for and no fields are duplicated.18199 // 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));
17781 defer gpa.free(found_fields);18201 defer gpa.free(found_fields);
1778218202
17783 // The init values to use for the struct instance.18203 // 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));
17785 defer gpa.free(field_inits);18205 defer gpa.free(field_inits);
17786 @memset(field_inits, .none);18206 @memset(field_inits, .none);
1778718207
17788 var field_i: u32 = 0;18208 var field_i: u32 = 0;
17789 var extra_index = extra.end;18209 var extra_index = extra.end;
1779018210
17791 const is_packed = resolved_ty.containerLayout() == .Packed;18211 const is_packed = resolved_ty.containerLayout(mod) == .Packed;
17792 while (field_i < extra.data.fields_len) : (field_i += 1) {18212 while (field_i < extra.data.fields_len) : (field_i += 1) {
17793 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);18213 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);
17794 extra_index = item.end;18214 extra_index = item.end;
...@@ -17796,8 +18216,8 @@ fn zirStructInit(...@@ -17796,8 +18216,8 @@ fn zirStructInit(
17796 const field_type_data = zir_datas[item.data.field_type].pl_node;18216 const field_type_data = zir_datas[item.data.field_type].pl_node;
17797 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };18217 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };
17798 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;18218 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);18219 const field_name = try mod.intern_pool.getOrPutString(gpa, sema.code.nullTerminatedString(field_type_extra.name_start));
17800 const field_index = if (resolved_ty.isTuple())18220 const field_index = if (resolved_ty.isTuple(mod))
17801 try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src)18221 try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src)
17802 else18222 else
17803 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);18223 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
...@@ -17815,19 +18235,19 @@ fn zirStructInit(...@@ -17815,19 +18235,19 @@ fn zirStructInit(
17815 }18235 }
17816 found_fields[field_index] = item.data.field_type;18236 found_fields[field_index] = item.data.field_type;
17817 field_inits[field_index] = try sema.resolveInst(item.data.init);18237 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| {
17819 const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {18239 const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {
17820 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");18240 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
17821 };18241 };
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)) {
17824 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);18244 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);
17825 }18245 }
17826 };18246 };
17827 }18247 }
1782818248
17829 return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref);18249 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) {
17831 if (extra.data.fields_len != 1) {18251 if (extra.data.fields_len != 1) {
17832 return sema.fail(block, src, "union initialization expects exactly one field", .{});18252 return sema.fail(block, src, "union initialization expects exactly one field", .{});
17833 }18253 }
...@@ -17837,32 +18257,32 @@ fn zirStructInit(...@@ -17837,32 +18257,32 @@ fn zirStructInit(
17837 const field_type_data = zir_datas[item.data.field_type].pl_node;18257 const field_type_data = zir_datas[item.data.field_type].pl_node;
17838 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };18258 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };
17839 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;18259 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));
17841 const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src);18261 const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src);
17842 const tag_ty = resolved_ty.unionTagTypeHypothetical();18262 const tag_ty = resolved_ty.unionTagTypeHypothetical(mod);
17843 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);18263 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);
17844 const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);18264 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
1784518265
17846 const init_inst = try sema.resolveInst(item.data.init);18266 const init_inst = try sema.resolveInst(item.data.init);
17847 if (try sema.resolveMaybeUndefVal(init_inst)) |val| {18267 if (try sema.resolveMaybeUndefVal(init_inst)) |val| {
17848 return sema.addConstantMaybeRef(18268 const field = resolved_ty.unionFields(mod).values()[field_index];
17849 block,18269 return sema.addConstantMaybeRef(block, resolved_ty, (try mod.intern(.{ .un = .{
17850 resolved_ty,18270 .ty = resolved_ty.toIntern(),
17851 try Value.Tag.@"union".create(sema.arena, .{ .tag = tag_val, .val = val }),18271 .tag = try tag_val.intern(tag_ty, mod),
17852 is_ref,18272 .val = try val.intern(field.ty, mod),
17853 );18273 } })).toValue(), is_ref);
17854 }18274 }
1785518275
17856 if (is_ref) {18276 if (is_ref) {
17857 const target = sema.mod.getTarget();18277 const target = mod.getTarget();
17858 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{18278 const alloc_ty = try Type.ptr(sema.arena, mod, .{
17859 .pointee_type = resolved_ty,18279 .pointee_type = resolved_ty,
17860 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18280 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
17861 });18281 });
17862 const alloc = try block.addTy(.alloc, alloc_ty);18282 const alloc = try block.addTy(.alloc, alloc_ty);
17863 const field_ptr = try sema.unionFieldPtr(block, field_src, alloc, field_name, field_src, resolved_ty, true);18283 const field_ptr = try sema.unionFieldPtr(block, field_src, alloc, field_name, field_src, resolved_ty, true);
17864 try sema.storePtr(block, src, field_ptr, init_inst);18284 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);
17866 _ = try block.addBinOp(.set_union_tag, alloc, new_tag);18286 _ = try block.addBinOp(.set_union_tag, alloc, new_tag);
17867 return sema.makePtrConst(block, alloc);18287 return sema.makePtrConst(block, alloc);
17868 }18288 }
...@@ -17870,7 +18290,7 @@ fn zirStructInit(...@@ -17870,7 +18290,7 @@ fn zirStructInit(
17870 try sema.requireRuntimeBlock(block, src, null);18290 try sema.requireRuntimeBlock(block, src, null);
17871 try sema.queueFullTypeResolution(resolved_ty);18291 try sema.queueFullTypeResolution(resolved_ty);
17872 return block.addUnionInit(resolved_ty, field_index, init_inst);18292 return block.addUnionInit(resolved_ty, field_index, init_inst);
17873 } else if (resolved_ty.isAnonStruct()) {18293 } else if (resolved_ty.isAnonStruct(mod)) {
17874 return sema.fail(block, src, "TODO anon struct init validation", .{});18294 return sema.fail(block, src, "TODO anon struct init validation", .{});
17875 }18295 }
17876 unreachable;18296 unreachable;
...@@ -17885,76 +18305,70 @@ fn finishStructInit(...@@ -17885,76 +18305,70 @@ fn finishStructInit(
17885 struct_ty: Type,18305 struct_ty: Type,
17886 is_ref: bool,18306 is_ref: bool,
17887) CompileError!Air.Inst.Ref {18307) CompileError!Air.Inst.Ref {
17888 const gpa = sema.gpa;18308 const mod = sema.mod;
18309 const ip = &mod.intern_pool;
1788918310
17890 var root_msg: ?*Module.ErrorMsg = null;18311 var root_msg: ?*Module.ErrorMsg = null;
17891 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);18312 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
1789218313
17893 if (struct_ty.isAnonStruct()) {18314 switch (ip.indexToKey(struct_ty.toIntern())) {
17894 const struct_obj = struct_ty.castTag(.anon_struct).?.data;18315 .anon_struct_type => |anon_struct| {
17895 for (struct_obj.values, 0..) |default_val, i| {18316 for (anon_struct.types, anon_struct.values, 0..) |field_ty, default_val, i| {
17896 if (field_inits[i] != .none) continue;18317 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;
1791618318
17917 const default_val = struct_ty.structFieldDefaultValue(i);18319 if (default_val == .none) {
17918 if (default_val.tag() == .unreachable_value) {18320 if (anon_struct.names.len == 0) {
17919 const template = "missing tuple field with index {d}";18321 const template = "missing tuple field with index {d}";
17920 if (root_msg) |msg| {18322 if (root_msg) |msg| {
17921 try sema.errNote(block, init_src, msg, template, .{i});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 }
17922 } else {18337 } 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());
17924 }18339 }
17925 } else {
17926 field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i), default_val);
17927 }18340 }
17928 }18341 },
17929 } else {18342 .struct_type => |struct_type| {
17930 const struct_obj = struct_ty.castTag(.@"struct").?.data;18343 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
17931 for (struct_obj.fields.values(), 0..) |field, i| {18344 for (struct_obj.fields.values(), 0..) |field, i| {
17932 if (field_inits[i] != .none) continue;18345 if (field_inits[i] != .none) continue;
1793318346
17934 if (field.default_val.tag() == .unreachable_value) {18347 if (field.default_val == .none) {
17935 const field_name = struct_obj.fields.keys()[i];18348 const field_name = struct_obj.fields.keys()[i];
17936 const template = "missing struct field: {s}";18349 const template = "missing struct field: {}";
17937 const args = .{field_name};18350 const args = .{field_name.fmt(ip)};
17938 if (root_msg) |msg| {18351 if (root_msg) |msg| {
17939 try sema.errNote(block, init_src, msg, template, args);18352 try sema.errNote(block, init_src, msg, template, args);
18353 } else {
18354 root_msg = try sema.errMsg(block, init_src, template, args);
18355 }
17940 } else {18356 } 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());
17942 }18358 }
17943 } else {
17944 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
17945 }18359 }
17946 }18360 },
18361 else => unreachable,
17947 }18362 }
1794818363
17949 if (root_msg) |msg| {18364 if (root_msg) |msg| {
17950 if (struct_ty.castTag(.@"struct")) |struct_obj| {18365 if (mod.typeToStruct(struct_ty)) |struct_obj| {
17951 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);18366 const fqn = try struct_obj.getFullyQualifiedName(mod);
17952 defer gpa.free(fqn);18367 try mod.errNoteNonLazy(
17953 try sema.mod.errNoteNonLazy(18368 struct_obj.srcLoc(mod),
17954 struct_obj.data.srcLoc(sema.mod),
17955 msg,18369 msg,
17956 "struct '{s}' declared here",18370 "struct '{}' declared here",
17957 .{fqn},18371 .{fqn.fmt(ip)},
17958 );18372 );
17959 }18373 }
17960 root_msg = null;18374 root_msg = null;
...@@ -17969,18 +18383,22 @@ fn finishStructInit(...@@ -17969,18 +18383,22 @@ fn finishStructInit(
17969 } else null;18383 } else null;
1797018384
17971 const runtime_index = opt_runtime_index orelse {18385 const runtime_index = opt_runtime_index orelse {
17972 const values = try sema.arena.alloc(Value, field_inits.len);18386 const elems = try sema.arena.alloc(InternPool.Index, field_inits.len);
17973 for (field_inits, 0..) |field_init, i| {18387 for (elems, field_inits, 0..) |*elem, field_init, field_i| {
17974 values[i] = (sema.resolveMaybeUndefVal(field_init) catch unreachable).?;18388 elem.* = try (sema.resolveMaybeUndefVal(field_init) catch unreachable).?
17975 }18389 .intern(struct_ty.structFieldType(field_i, mod), mod);
17976 const struct_val = try Value.Tag.aggregate.create(sema.arena, values);18390 }
17977 return sema.addConstantMaybeRef(block, struct_ty, struct_val, is_ref);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);
17978 };18396 };
1797918397
17980 if (is_ref) {18398 if (is_ref) {
17981 try sema.resolveStructLayout(struct_ty);18399 try sema.resolveStructLayout(struct_ty);
17982 const target = sema.mod.getTarget();18400 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, .{
17984 .pointee_type = struct_ty,18402 .pointee_type = struct_ty,
17985 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18403 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
17986 });18404 });
...@@ -17997,8 +18415,8 @@ fn finishStructInit(...@@ -17997,8 +18415,8 @@ fn finishStructInit(
1799718415
17998 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {18416 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
17999 error.NeededSourceLocation => {18417 error.NeededSourceLocation => {
18000 const decl = sema.mod.declPtr(block.src_decl);18418 const decl = mod.declPtr(block.src_decl);
18001 const field_src = Module.initSrc(dest_src.node_offset.x, sema.gpa, decl, runtime_index);18419 const field_src = mod.initSrc(dest_src.node_offset.x, decl, runtime_index);
18002 try sema.requireRuntimeBlock(block, dest_src, field_src);18420 try sema.requireRuntimeBlock(block, dest_src, field_src);
18003 unreachable;18421 unreachable;
18004 },18422 },
...@@ -18014,79 +18432,85 @@ fn zirStructInitAnon(...@@ -18014,79 +18432,85 @@ fn zirStructInitAnon(
18014 inst: Zir.Inst.Index,18432 inst: Zir.Inst.Index,
18015 is_ref: bool,18433 is_ref: bool,
18016) CompileError!Air.Inst.Ref {18434) CompileError!Air.Inst.Ref {
18435 const mod = sema.mod;
18436 const gpa = sema.gpa;
18017 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;18437 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
18018 const src = inst_data.src();18438 const src = inst_data.src();
18019 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);18439 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
18020 const types = try sema.arena.alloc(Type, extra.data.fields_len);18440 const types = try sema.arena.alloc(InternPool.Index, extra.data.fields_len);
18021 const values = try sema.arena.alloc(Value, types.len);18441 const values = try sema.arena.alloc(InternPool.Index, types.len);
18022 var fields = std.StringArrayHashMapUnmanaged(u32){};18442 var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena);
18023 defer fields.deinit(sema.gpa);18443 try fields.ensureUnusedCapacity(types.len);
18024 try fields.ensureUnusedCapacity(sema.gpa, types.len);
1802518444
18026 // Find which field forces the expression to be runtime, if any.18445 // Find which field forces the expression to be runtime, if any.
18027 const opt_runtime_index = rs: {18446 const opt_runtime_index = rs: {
18028 var runtime_index: ?usize = null;18447 var runtime_index: ?usize = null;
18029 var extra_index = extra.end;18448 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);
18031 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);18451 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
18032 extra_index = item.end;18452 extra_index = item.end;
1803318453
18034 const name = sema.code.nullTerminatedString(item.data.field_name);18454 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);
18036 if (gop.found_existing) {18457 if (gop.found_existing) {
18037 const msg = msg: {18458 const msg = msg: {
18038 const decl = sema.mod.declPtr(block.src_decl);18459 const decl = mod.declPtr(block.src_decl);
18039 const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i);18460 const field_src = mod.initSrc(src.node_offset.x, decl, i);
18040 const msg = try sema.errMsg(block, field_src, "duplicate field", .{});18461 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.*);
18044 try sema.errNote(block, prev_source, msg, "other field here", .{});18465 try sema.errNote(block, prev_source, msg, "other field here", .{});
18045 break :msg msg;18466 break :msg msg;
18046 };18467 };
18047 return sema.failWithOwnedErrorMsg(msg);18468 return sema.failWithOwnedErrorMsg(msg);
18048 }18469 }
18049 gop.value_ptr.* = @intCast(u32, i);18470 gop.value_ptr.* = i;
1805018471
18051 const init = try sema.resolveInst(item.data.init);18472 const init = try sema.resolveInst(item.data.init);
18052 field_ty.* = sema.typeOf(init);18473 field_ty.* = sema.typeOf(init).toIntern();
18053 if (types[i].zigTypeTag() == .Opaque) {18474 if (field_ty.toType().zigTypeTag(mod) == .Opaque) {
18054 const msg = msg: {18475 const msg = msg: {
18055 const decl = sema.mod.declPtr(block.src_decl);18476 const decl = mod.declPtr(block.src_decl);
18056 const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i);18477 const field_src = mod.initSrc(src.node_offset.x, decl, i);
18057 const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});18478 const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
18058 errdefer msg.destroy(sema.gpa);18479 errdefer msg.destroy(sema.gpa);
1805918480
18060 try sema.addDeclaredHereNote(msg, types[i]);18481 try sema.addDeclaredHereNote(msg, field_ty.toType());
18061 break :msg msg;18482 break :msg msg;
18062 };18483 };
18063 return sema.failWithOwnedErrorMsg(msg);18484 return sema.failWithOwnedErrorMsg(msg);
18064 }18485 }
18065 if (try sema.resolveMaybeUndefVal(init)) |init_val| {18486 if (try sema.resolveMaybeUndefVal(init)) |init_val| {
18066 values[i] = init_val;18487 values[i] = try init_val.intern(field_ty.toType(), mod);
18067 } else {18488 } else {
18068 values[i] = Value.initTag(.unreachable_value);18489 values[i] = .none;
18069 runtime_index = i;18490 runtime_index = i;
18070 }18491 }
18071 }18492 }
18072 break :rs runtime_index;18493 break :rs runtime_index;
18073 };18494 };
1807418495
18075 const tuple_ty = try Type.Tag.anon_struct.create(sema.arena, .{18496 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
18076 .names = try sema.arena.dupe([]const u8, fields.keys()),18497 .names = fields.keys(),
18077 .types = types,18498 .types = types,
18078 .values = values,18499 .values = values,
18079 });18500 } });
1808018501
18081 const runtime_index = opt_runtime_index orelse {18502 const runtime_index = opt_runtime_index orelse {
18082 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);18503 const tuple_val = try mod.intern(.{ .aggregate = .{
18083 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);18504 .ty = tuple_ty,
18505 .storage = .{ .elems = values },
18506 } });
18507 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
18084 };18508 };
1808518509
18086 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {18510 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
18087 error.NeededSourceLocation => {18511 error.NeededSourceLocation => {
18088 const decl = sema.mod.declPtr(block.src_decl);18512 const decl = mod.declPtr(block.src_decl);
18089 const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, runtime_index);18513 const field_src = mod.initSrc(src.node_offset.x, decl, runtime_index);
18090 try sema.requireRuntimeBlock(block, src, field_src);18514 try sema.requireRuntimeBlock(block, src, field_src);
18091 unreachable;18515 unreachable;
18092 },18516 },
...@@ -18094,9 +18518,9 @@ fn zirStructInitAnon(...@@ -18094,9 +18518,9 @@ fn zirStructInitAnon(
18094 };18518 };
1809518519
18096 if (is_ref) {18520 if (is_ref) {
18097 const target = sema.mod.getTarget();18521 const target = mod.getTarget();
18098 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{18522 const alloc_ty = try Type.ptr(sema.arena, mod, .{
18099 .pointee_type = tuple_ty,18523 .pointee_type = tuple_ty.toType(),
18100 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18524 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18101 });18525 });
18102 const alloc = try block.addTy(.alloc, alloc_ty);18526 const alloc = try block.addTy(.alloc, alloc_ty);
...@@ -18106,12 +18530,12 @@ fn zirStructInitAnon(...@@ -18106,12 +18530,12 @@ fn zirStructInitAnon(
18106 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);18530 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
18107 extra_index = item.end;18531 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, .{
18110 .mutable = true,18534 .mutable = true,
18111 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18535 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18112 .pointee_type = field_ty,18536 .pointee_type = field_ty.toType(),
18113 });18537 });
18114 if (values[i].tag() == .unreachable_value) {18538 if (values[i] == .none) {
18115 const init = try sema.resolveInst(item.data.init);18539 const init = try sema.resolveInst(item.data.init);
18116 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);18540 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
18117 _ = try block.addBinOp(.store, field_ptr, init);18541 _ = try block.addBinOp(.store, field_ptr, init);
...@@ -18129,7 +18553,7 @@ fn zirStructInitAnon(...@@ -18129,7 +18553,7 @@ fn zirStructInitAnon(
18129 element_refs[i] = try sema.resolveInst(item.data.init);18553 element_refs[i] = try sema.resolveInst(item.data.init);
18130 }18554 }
1813118555
18132 return block.addAggregateInit(tuple_ty, element_refs);18556 return block.addAggregateInit(tuple_ty.toType(), element_refs);
18133}18557}
1813418558
18135fn zirArrayInit(18559fn zirArrayInit(
...@@ -18138,6 +18562,7 @@ fn zirArrayInit(...@@ -18138,6 +18562,7 @@ fn zirArrayInit(
18138 inst: Zir.Inst.Index,18562 inst: Zir.Inst.Index,
18139 is_ref: bool,18563 is_ref: bool,
18140) CompileError!Air.Inst.Ref {18564) CompileError!Air.Inst.Ref {
18565 const mod = sema.mod;
18141 const gpa = sema.gpa;18566 const gpa = sema.gpa;
18142 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;18567 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
18143 const src = inst_data.src();18568 const src = inst_data.src();
...@@ -18147,20 +18572,20 @@ fn zirArrayInit(...@@ -18147,20 +18572,20 @@ fn zirArrayInit(
18147 assert(args.len >= 2); // array_ty + at least one element18572 assert(args.len >= 2); // array_ty + at least one element
1814818573
18149 const array_ty = try sema.resolveType(block, src, args[0]);18574 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
18152 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));18577 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));
18153 defer gpa.free(resolved_args);18578 defer gpa.free(resolved_args);
18154 for (args[1..], 0..) |arg, i| {18579 for (args[1..], 0..) |arg, i| {
18155 const resolved_arg = try sema.resolveInst(arg);18580 const resolved_arg = try sema.resolveInst(arg);
18156 const elem_ty = if (array_ty.zigTypeTag() == .Struct)18581 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)
18157 array_ty.structFieldType(i)18582 array_ty.structFieldType(i, mod)
18158 else18583 else
18159 array_ty.elemType2();18584 array_ty.elemType2(mod);
18160 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {18585 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {
18161 error.NeededSourceLocation => {18586 error.NeededSourceLocation => {
18162 const decl = sema.mod.declPtr(block.src_decl);18587 const decl = mod.declPtr(block.src_decl);
18163 const elem_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i);18588 const elem_src = mod.initSrc(src.node_offset.x, decl, i);
18164 _ = try sema.coerce(block, elem_ty, resolved_arg, elem_src);18589 _ = try sema.coerce(block, elem_ty, resolved_arg, elem_src);
18165 unreachable;18590 unreachable;
18166 },18591 },
...@@ -18169,7 +18594,7 @@ fn zirArrayInit(...@@ -18169,7 +18594,7 @@ fn zirArrayInit(
18169 }18594 }
1817018595
18171 if (sentinel_val) |some| {18596 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);
18173 }18598 }
1817418599
18175 const opt_runtime_index: ?u32 = for (resolved_args, 0..) |arg, i| {18600 const opt_runtime_index: ?u32 = for (resolved_args, 0..) |arg, i| {
...@@ -18178,21 +18603,25 @@ fn zirArrayInit(...@@ -18178,21 +18603,25 @@ fn zirArrayInit(
18178 } else null;18603 } else null;
1817918604
18180 const runtime_index = opt_runtime_index orelse {18605 const runtime_index = opt_runtime_index orelse {
18181 const elem_vals = try sema.arena.alloc(Value, resolved_args.len);18606 const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len);
1818218607 for (elem_vals, resolved_args, 0..) |*val, arg, i| {
18183 for (resolved_args, 0..) |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);
18184 // We checked that all args are comptime above.18612 // 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);
18186 }18614 }
1818718615 return sema.addConstantMaybeRef(block, array_ty, (try mod.intern(.{ .aggregate = .{
18188 const array_val = try Value.Tag.aggregate.create(sema.arena, elem_vals);18616 .ty = array_ty.toIntern(),
18189 return sema.addConstantMaybeRef(block, array_ty, array_val, is_ref);18617 .storage = .{ .elems = elem_vals },
18618 } })).toValue(), is_ref);
18190 };18619 };
1819118620
18192 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {18621 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
18193 error.NeededSourceLocation => {18622 error.NeededSourceLocation => {
18194 const decl = sema.mod.declPtr(block.src_decl);18623 const decl = mod.declPtr(block.src_decl);
18195 const elem_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, runtime_index);18624 const elem_src = mod.initSrc(src.node_offset.x, decl, runtime_index);
18196 try sema.requireRuntimeBlock(block, src, elem_src);18625 try sema.requireRuntimeBlock(block, src, elem_src);
18197 unreachable;18626 unreachable;
18198 },18627 },
...@@ -18201,19 +18630,19 @@ fn zirArrayInit(...@@ -18201,19 +18630,19 @@ fn zirArrayInit(
18201 try sema.queueFullTypeResolution(array_ty);18630 try sema.queueFullTypeResolution(array_ty);
1820218631
18203 if (is_ref) {18632 if (is_ref) {
18204 const target = sema.mod.getTarget();18633 const target = mod.getTarget();
18205 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{18634 const alloc_ty = try Type.ptr(sema.arena, mod, .{
18206 .pointee_type = array_ty,18635 .pointee_type = array_ty,
18207 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18636 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18208 });18637 });
18209 const alloc = try block.addTy(.alloc, alloc_ty);18638 const alloc = try block.addTy(.alloc, alloc_ty);
1821018639
18211 if (array_ty.isTuple()) {18640 if (array_ty.isTuple(mod)) {
18212 for (resolved_args, 0..) |arg, i| {18641 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, .{
18214 .mutable = true,18643 .mutable = true,
18215 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18644 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18216 .pointee_type = array_ty.structFieldType(i),18645 .pointee_type = array_ty.structFieldType(i, mod),
18217 });18646 });
18218 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);18647 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1821918648
...@@ -18224,10 +18653,10 @@ fn zirArrayInit(...@@ -18224,10 +18653,10 @@ fn zirArrayInit(
18224 return sema.makePtrConst(block, alloc);18653 return sema.makePtrConst(block, alloc);
18225 }18654 }
1822618655
18227 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{18656 const elem_ptr_ty = try Type.ptr(sema.arena, mod, .{
18228 .mutable = true,18657 .mutable = true,
18229 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18658 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18230 .pointee_type = array_ty.elemType2(),18659 .pointee_type = array_ty.elemType2(mod),
18231 });18660 });
18232 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);18661 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1823318662
...@@ -18252,44 +18681,49 @@ fn zirArrayInitAnon(...@@ -18252,44 +18681,49 @@ fn zirArrayInitAnon(
18252 const src = inst_data.src();18681 const src = inst_data.src();
18253 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);18682 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
18254 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);18683 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);18686 const types = try sema.arena.alloc(InternPool.Index, operands.len);
18257 const values = try sema.arena.alloc(Value, operands.len);18687 const values = try sema.arena.alloc(InternPool.Index, operands.len);
1825818688
18259 const opt_runtime_src = rs: {18689 const opt_runtime_src = rs: {
18260 var runtime_src: ?LazySrcLoc = null;18690 var runtime_src: ?LazySrcLoc = null;
18261 for (operands, 0..) |operand, i| {18691 for (operands, 0..) |operand, i| {
18262 const operand_src = src; // TODO better source location18692 const operand_src = src; // TODO better source location
18263 const elem = try sema.resolveInst(operand);18693 const elem = try sema.resolveInst(operand);
18264 types[i] = sema.typeOf(elem);18694 types[i] = sema.typeOf(elem).toIntern();
18265 if (types[i].zigTypeTag() == .Opaque) {18695 if (types[i].toType().zigTypeTag(mod) == .Opaque) {
18266 const msg = msg: {18696 const msg = msg: {
18267 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});18697 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
18268 errdefer msg.destroy(sema.gpa);18698 errdefer msg.destroy(sema.gpa);
1826918699
18270 try sema.addDeclaredHereNote(msg, types[i]);18700 try sema.addDeclaredHereNote(msg, types[i].toType());
18271 break :msg msg;18701 break :msg msg;
18272 };18702 };
18273 return sema.failWithOwnedErrorMsg(msg);18703 return sema.failWithOwnedErrorMsg(msg);
18274 }18704 }
18275 if (try sema.resolveMaybeUndefVal(elem)) |val| {18705 if (try sema.resolveMaybeUndefVal(elem)) |val| {
18276 values[i] = val;18706 values[i] = val.toIntern();
18277 } else {18707 } else {
18278 values[i] = Value.initTag(.unreachable_value);18708 values[i] = .none;
18279 runtime_src = operand_src;18709 runtime_src = operand_src;
18280 }18710 }
18281 }18711 }
18282 break :rs runtime_src;18712 break :rs runtime_src;
18283 };18713 };
1828418714
18285 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{18715 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
18286 .types = types,18716 .types = types,
18287 .values = values,18717 .values = values,
18288 });18718 .names = &.{},
18719 } });
1828918720
18290 const runtime_src = opt_runtime_src orelse {18721 const runtime_src = opt_runtime_src orelse {
18291 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);18722 const tuple_val = try mod.intern(.{ .aggregate = .{
18292 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);18723 .ty = tuple_ty,
18724 .storage = .{ .elems = values },
18725 } });
18726 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
18293 };18727 };
1829418728
18295 try sema.requireRuntimeBlock(block, src, runtime_src);18729 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -18297,7 +18731,7 @@ fn zirArrayInitAnon(...@@ -18297,7 +18731,7 @@ fn zirArrayInitAnon(
18297 if (is_ref) {18731 if (is_ref) {
18298 const target = sema.mod.getTarget();18732 const target = sema.mod.getTarget();
18299 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{18733 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18300 .pointee_type = tuple_ty,18734 .pointee_type = tuple_ty.toType(),
18301 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18735 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18302 });18736 });
18303 const alloc = try block.addTy(.alloc, alloc_ty);18737 const alloc = try block.addTy(.alloc, alloc_ty);
...@@ -18306,9 +18740,9 @@ fn zirArrayInitAnon(...@@ -18306,9 +18740,9 @@ fn zirArrayInitAnon(
18306 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{18740 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
18307 .mutable = true,18741 .mutable = true,
18308 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18742 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18309 .pointee_type = types[i],18743 .pointee_type = types[i].toType(),
18310 });18744 });
18311 if (values[i].tag() == .unreachable_value) {18745 if (values[i] == .none) {
18312 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);18746 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
18313 _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand));18747 _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand));
18314 }18748 }
...@@ -18322,7 +18756,7 @@ fn zirArrayInitAnon(...@@ -18322,7 +18756,7 @@ fn zirArrayInitAnon(
18322 element_refs[i] = try sema.resolveInst(operand);18756 element_refs[i] = try sema.resolveInst(operand);
18323 }18757 }
1832418758
18325 return block.addAggregateInit(tuple_ty, element_refs);18759 return block.addAggregateInit(tuple_ty.toType(), element_refs);
18326}18760}
1832718761
18328fn addConstantMaybeRef(18762fn addConstantMaybeRef(
...@@ -18337,8 +18771,8 @@ fn addConstantMaybeRef(...@@ -18337,8 +18771,8 @@ fn addConstantMaybeRef(
18337 var anon_decl = try block.startAnonDecl();18771 var anon_decl = try block.startAnonDecl();
18338 defer anon_decl.deinit();18772 defer anon_decl.deinit();
18339 const decl = try anon_decl.finish(18773 const decl = try anon_decl.finish(
18340 try ty.copy(anon_decl.arena()),18774 ty,
18341 try val.copy(anon_decl.arena()),18775 val,
18342 0, // default alignment18776 0, // default alignment
18343 );18777 );
18344 return sema.analyzeDeclRef(decl);18778 return sema.analyzeDeclRef(decl);
...@@ -18350,11 +18784,13 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -18350,11 +18784,13 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
18350 const ty_src = inst_data.src();18784 const ty_src = inst_data.src();
18351 const field_src = inst_data.src();18785 const field_src = inst_data.src();
18352 const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type);18786 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");
18354 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);18788 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);
18355}18789}
1835618790
18357fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {18791fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
18792 const mod = sema.mod;
18793 const ip = &mod.intern_pool;
18358 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;18794 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
18359 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;18795 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
18360 const ty_src = inst_data.src();18796 const ty_src = inst_data.src();
...@@ -18367,7 +18803,8 @@ fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -18367,7 +18803,8 @@ fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
18367 error.GenericPoison => return Air.Inst.Ref.generic_poison_type,18803 error.GenericPoison => return Air.Inst.Ref.generic_poison_type,
18368 else => |e| return e,18804 else => |e| return e,
18369 };18805 };
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);
18371 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);18808 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);
18372}18809}
1837318810
...@@ -18375,41 +18812,43 @@ fn fieldType(...@@ -18375,41 +18812,43 @@ fn fieldType(
18375 sema: *Sema,18812 sema: *Sema,
18376 block: *Block,18813 block: *Block,
18377 aggregate_ty: Type,18814 aggregate_ty: Type,
18378 field_name: []const u8,18815 field_name: InternPool.NullTerminatedString,
18379 field_src: LazySrcLoc,18816 field_src: LazySrcLoc,
18380 ty_src: LazySrcLoc,18817 ty_src: LazySrcLoc,
18381) CompileError!Air.Inst.Ref {18818) CompileError!Air.Inst.Ref {
18819 const mod = sema.mod;
18382 var cur_ty = aggregate_ty;18820 var cur_ty = aggregate_ty;
18383 while (true) {18821 while (true) {
18384 const resolved_ty = try sema.resolveTypeFields(cur_ty);18822 const resolved_ty = try sema.resolveTypeFields(cur_ty);
18385 cur_ty = resolved_ty;18823 cur_ty = resolved_ty;
18386 switch (cur_ty.zigTypeTag()) {18824 switch (cur_ty.zigTypeTag(mod)) {
18387 .Struct => {18825 .Struct => switch (mod.intern_pool.indexToKey(cur_ty.toIntern())) {
18388 if (cur_ty.isAnonStruct()) {18826 .anon_struct_type => |anon_struct| {
18389 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);18827 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
18390 return sema.addType(cur_ty.tupleFields().types[field_index]);18828 return sema.addType(anon_struct.types[field_index].toType());
18391 }18829 },
18392 const struct_obj = cur_ty.castTag(.@"struct").?.data;18830 .struct_type => |struct_type| {
18393 const field = struct_obj.fields.get(field_name) orelse18831 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
18394 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);18832 const field = struct_obj.fields.get(field_name) orelse
18395 return sema.addType(field.ty);18833 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
18834 return sema.addType(field.ty);
18835 },
18836 else => unreachable,
18396 },18837 },
18397 .Union => {18838 .Union => {
18398 const union_obj = cur_ty.cast(Type.Payload.Union).?.data;18839 const union_obj = mod.typeToUnion(cur_ty).?;
18399 const field = union_obj.fields.get(field_name) orelse18840 const field = union_obj.fields.get(field_name) orelse
18400 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);18841 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
18401 return sema.addType(field.ty);18842 return sema.addType(field.ty);
18402 },18843 },
18403 .Optional => {18844 .Optional => {
18404 if (cur_ty.castTag(.optional)) |some| {18845 // Struct/array init through optional requires the child type to not be a pointer.
18405 // 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.
18406 // 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();
18407 cur_ty = some.data;18848 continue;
18408 continue;
18409 }
18410 },18849 },
18411 .ErrorUnion => {18850 .ErrorUnion => {
18412 cur_ty = cur_ty.errorUnionPayload();18851 cur_ty = cur_ty.errorUnionPayload(mod);
18413 continue;18852 continue;
18414 },18853 },
18415 else => {},18854 else => {},
...@@ -18425,18 +18864,23 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -18425,18 +18864,23 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
18425}18864}
1842618865
18427fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {18866fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
18867 const mod = sema.mod;
18428 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");18868 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
18429 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);18869 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
18432 if (sema.owner_func != null and18873 if (sema.owner_func != null and
18433 sema.owner_func.?.calls_or_awaits_errorable_fn and18874 sema.owner_func.?.calls_or_awaits_errorable_fn and
18434 sema.mod.comp.bin_file.options.error_return_tracing and18875 mod.comp.bin_file.options.error_return_tracing and
18435 sema.mod.backendSupportsFeature(.error_return_trace))18876 mod.backendSupportsFeature(.error_return_trace))
18436 {18877 {
18437 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);18878 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
18438 }18879 }
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());
18440}18884}
1844118885
18442fn zirFrame(18886fn zirFrame(
...@@ -18449,27 +18893,28 @@ fn zirFrame(...@@ -18449,27 +18893,28 @@ fn zirFrame(
18449}18893}
1845018894
18451fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {18895fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
18896 const mod = sema.mod;
18452 const inst_data = sema.code.instructions.items(.data)[inst].un_node;18897 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
18453 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };18898 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
18454 const ty = try sema.resolveType(block, operand_src, inst_data.operand);18899 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
18455 if (ty.isNoReturn()) {18900 if (ty.isNoReturn(mod)) {
18456 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});18901 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});
18457 }18902 }
18458 const target = sema.mod.getTarget();18903 const val = try ty.lazyAbiAlignment(mod);
18459 const val = try ty.lazyAbiAlignment(target, sema.arena);18904 if (val.isLazyAlign(mod)) {
18460 if (val.tag() == .lazy_align) {
18461 try sema.queueFullTypeResolution(ty);18905 try sema.queueFullTypeResolution(ty);
18462 }18906 }
18463 return sema.addConstant(Type.comptime_int, val);18907 return sema.addConstant(Type.comptime_int, val);
18464}18908}
1846518909
18466fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {18910fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
18911 const mod = sema.mod;
18467 const inst_data = sema.code.instructions.items(.data)[inst].un_node;18912 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
18468 const operand = try sema.resolveInst(inst_data.operand);18913 const operand = try sema.resolveInst(inst_data.operand);
18469 if (try sema.resolveMaybeUndefVal(operand)) |val| {18914 if (try sema.resolveMaybeUndefVal(operand)) |val| {
18470 if (val.isUndef()) return sema.addConstUndef(Type.u1);18915 if (val.isUndef(mod)) return sema.addConstUndef(Type.u1);
18471 if (val.toBool()) return sema.addConstant(Type.u1, Value.one);18916 if (val.toBool()) return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 1));
18472 return sema.addConstant(Type.u1, Value.zero);18917 return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
18473 }18918 }
18474 return block.addUnOp(.bool_to_int, operand);18919 return block.addUnOp(.bool_to_int, operand);
18475}18920}
...@@ -18480,8 +18925,8 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -18480,8 +18925,8 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
18480 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };18925 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1848118926
18482 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {18927 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
18483 const bytes = val.castTag(.@"error").?.data.name;18928 const err_name = sema.mod.intern_pool.indexToKey(val.toIntern()).err.name;
18484 return sema.addStrLit(block, bytes);18929 return sema.addStrLit(block, sema.mod.intern_pool.stringToSlice(err_name));
18485 }18930 }
1848618931
18487 // Similar to zirTagName, we have special AIR instruction for the error name in case an optimimzation pass18932 // Similar to zirTagName, we have special AIR instruction for the error name in case an optimimzation pass
...@@ -18499,16 +18944,17 @@ fn zirUnaryMath(...@@ -18499,16 +18944,17 @@ fn zirUnaryMath(
18499 const tracy = trace(@src());18944 const tracy = trace(@src());
18500 defer tracy.end();18945 defer tracy.end();
1850118946
18947 const mod = sema.mod;
18502 const inst_data = sema.code.instructions.items(.data)[inst].un_node;18948 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
18503 const operand = try sema.resolveInst(inst_data.operand);18949 const operand = try sema.resolveInst(inst_data.operand);
18504 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };18950 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
18505 const operand_ty = sema.typeOf(operand);18951 const operand_ty = sema.typeOf(operand);
1850618952
18507 switch (operand_ty.zigTypeTag()) {18953 switch (operand_ty.zigTypeTag(mod)) {
18508 .ComptimeFloat, .Float => {},18954 .ComptimeFloat, .Float => {},
18509 .Vector => {18955 .Vector => {
18510 const scalar_ty = operand_ty.scalarType();18956 const scalar_ty = operand_ty.scalarType(mod);
18511 switch (scalar_ty.zigTypeTag()) {18957 switch (scalar_ty.zigTypeTag(mod)) {
18512 .ComptimeFloat, .Float => {},18958 .ComptimeFloat, .Float => {},
18513 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}),18959 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}),
18514 }18960 }
...@@ -18516,25 +18962,27 @@ fn zirUnaryMath(...@@ -18516,25 +18962,27 @@ fn zirUnaryMath(
18516 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}),18962 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}),
18517 }18963 }
1851818964
18519 switch (operand_ty.zigTypeTag()) {18965 switch (operand_ty.zigTypeTag(mod)) {
18520 .Vector => {18966 .Vector => {
18521 const scalar_ty = operand_ty.scalarType();18967 const scalar_ty = operand_ty.scalarType(mod);
18522 const vec_len = operand_ty.vectorLen();18968 const vec_len = operand_ty.vectorLen(mod);
18523 const result_ty = try Type.vector(sema.arena, vec_len, scalar_ty);18969 const result_ty = try mod.vectorType(.{
18970 .len = vec_len,
18971 .child = scalar_ty.toIntern(),
18972 });
18524 if (try sema.resolveMaybeUndefVal(operand)) |val| {18973 if (try sema.resolveMaybeUndefVal(operand)) |val| {
18525 if (val.isUndef())18974 if (val.isUndef(mod))
18526 return sema.addConstUndef(result_ty);18975 return sema.addConstUndef(result_ty);
1852718976
18528 var elem_buf: Value.ElemValueBuffer = undefined;18977 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
18529 const elems = try sema.arena.alloc(Value, vec_len);
18530 for (elems, 0..) |*elem, i| {18978 for (elems, 0..) |*elem, i| {
18531 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);18979 const elem_val = try val.elemValue(sema.mod, i);
18532 elem.* = try eval(elem_val, scalar_ty, sema.arena, sema.mod);18980 elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod);
18533 }18981 }
18534 return sema.addConstant(18982 return sema.addConstant(result_ty, (try mod.intern(.{ .aggregate = .{
18535 result_ty,18983 .ty = result_ty.toIntern(),
18536 try Value.Tag.aggregate.create(sema.arena, elems),18984 .storage = .{ .elems = elems },
18537 );18985 } })).toValue());
18538 }18986 }
1853918987
18540 try sema.requireRuntimeBlock(block, operand_src, null);18988 try sema.requireRuntimeBlock(block, operand_src, null);
...@@ -18542,7 +18990,7 @@ fn zirUnaryMath(...@@ -18542,7 +18990,7 @@ fn zirUnaryMath(
18542 },18990 },
18543 .ComptimeFloat, .Float => {18991 .ComptimeFloat, .Float => {
18544 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {18992 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
18545 if (operand_val.isUndef())18993 if (operand_val.isUndef(mod))
18546 return sema.addConstUndef(operand_ty);18994 return sema.addConstUndef(operand_ty);
18547 const result_val = try eval(operand_val, operand_ty, sema.arena, sema.mod);18995 const result_val = try eval(operand_val, operand_ty, sema.arena, sema.mod);
18548 return sema.addConstant(operand_ty, result_val);18996 return sema.addConstant(operand_ty, result_val);
...@@ -18562,16 +19010,17 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18562,16 +19010,17 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18562 const operand = try sema.resolveInst(inst_data.operand);19010 const operand = try sema.resolveInst(inst_data.operand);
18563 const operand_ty = sema.typeOf(operand);19011 const operand_ty = sema.typeOf(operand);
18564 const mod = sema.mod;19012 const mod = sema.mod;
19013 const ip = &mod.intern_pool;
1856519014
18566 try sema.resolveTypeLayout(operand_ty);19015 try sema.resolveTypeLayout(operand_ty);
18567 const enum_ty = switch (operand_ty.zigTypeTag()) {19016 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {
18568 .EnumLiteral => {19017 .EnumLiteral => {
18569 const val = try sema.resolveConstValue(block, .unneeded, operand, "");19018 const val = try sema.resolveConstValue(block, .unneeded, operand, "");
18570 const bytes = val.castTag(.enum_literal).?.data;19019 const tag_name = ip.indexToKey(val.toIntern()).enum_literal;
18571 return sema.addStrLit(block, bytes);19020 return sema.addStrLit(block, ip.stringToSlice(tag_name));
18572 },19021 },
18573 .Enum => operand_ty,19022 .Enum => operand_ty,
18574 .Union => operand_ty.unionTagType() orelse {19023 .Union => operand_ty.unionTagType(mod) orelse {
18575 const msg = msg: {19024 const msg = msg: {
18576 const msg = try sema.errMsg(block, src, "union '{}' is untagged", .{19025 const msg = try sema.errMsg(block, src, "union '{}' is untagged", .{
18577 operand_ty.fmt(sema.mod),19026 operand_ty.fmt(sema.mod),
...@@ -18586,30 +19035,31 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18586,30 +19035,31 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18586 operand_ty.fmt(mod),19035 operand_ty.fmt(mod),
18587 }),19036 }),
18588 };19037 };
18589 if (enum_ty.enumFieldCount() == 0) {19038 if (enum_ty.enumFieldCount(mod) == 0) {
18590 // TODO I don't think this is the correct way to handle this but19039 // TODO I don't think this is the correct way to handle this but
18591 // it prevents a crash.19040 // it prevents a crash.
18592 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{}'", .{19041 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{}'", .{
18593 enum_ty.fmt(mod),19042 enum_ty.fmt(mod),
18594 });19043 });
18595 }19044 }
18596 const enum_decl_index = enum_ty.getOwnerDecl();19045 const enum_decl_index = enum_ty.getOwnerDecl(mod);
18597 const casted_operand = try sema.coerce(block, enum_ty, operand, operand_src);19046 const casted_operand = try sema.coerce(block, enum_ty, operand, operand_src);
18598 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {19047 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {
18599 const field_index = enum_ty.enumTagFieldIndex(val, mod) orelse {19048 const field_index = enum_ty.enumTagFieldIndex(val, mod) orelse {
18600 const enum_decl = mod.declPtr(enum_decl_index);19049 const enum_decl = mod.declPtr(enum_decl_index);
18601 const msg = msg: {19050 const msg = msg: {
18602 const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{s}'", .{19051 const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{}'", .{
18603 val.fmtValue(enum_ty, sema.mod), enum_decl.name,19052 val.fmtValue(enum_ty, sema.mod), enum_decl.name.fmt(ip),
18604 });19053 });
18605 errdefer msg.destroy(sema.gpa);19054 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", .{});
18607 break :msg msg;19056 break :msg msg;
18608 };19057 };
18609 return sema.failWithOwnedErrorMsg(msg);19058 return sema.failWithOwnedErrorMsg(msg);
18610 };19059 };
18611 const field_name = enum_ty.enumFieldName(field_index);19060 // TODO: write something like getCoercedInts to avoid needing to dupe
18612 return sema.addStrLit(block, field_name);19061 const field_name = enum_ty.enumFieldName(field_index, mod);
19062 return sema.addStrLit(block, ip.stringToSlice(field_name));
18613 }19063 }
18614 try sema.requireRuntimeBlock(block, src, operand_src);19064 try sema.requireRuntimeBlock(block, src, operand_src);
18615 if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) {19065 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...@@ -18622,8 +19072,15 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18622 return block.addUnOp(.tag_name, casted_operand);19072 return block.addUnOp(.tag_name, casted_operand);
18623}19073}
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 {
18626 const mod = sema.mod;19081 const mod = sema.mod;
19082 const gpa = sema.gpa;
19083 const ip = &mod.intern_pool;
18627 const name_strategy = @intToEnum(Zir.Inst.NameStrategy, extended.small);19084 const name_strategy = @intToEnum(Zir.Inst.NameStrategy, extended.small);
18628 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;19085 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
18629 const src = LazySrcLoc.nodeOffset(extra.node);19086 const src = LazySrcLoc.nodeOffset(extra.node);
...@@ -18632,10 +19089,10 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -18632,10 +19089,10 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
18632 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };19089 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
18633 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);19090 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
18634 const val = try sema.resolveConstValue(block, operand_src, type_info, "operand to @Type must be comptime-known");19091 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;
18636 const target = mod.getTarget();19093 const target = mod.getTarget();
18637 const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag, mod).?;19094 if (try union_val.val.toValue().anyUndef(mod)) return sema.failWithUseOfUndef(block, src);
18638 if (union_val.val.anyUndef(mod)) return sema.failWithUseOfUndef(block, src);19095 const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag.toValue(), mod).?;
18639 switch (@intToEnum(std.builtin.TypeId, tag_index)) {19096 switch (@intToEnum(std.builtin.TypeId, tag_index)) {
18640 .Type => return Air.Inst.Ref.type_type,19097 .Type => return Air.Inst.Ref.type_type,
18641 .Void => return Air.Inst.Ref.void_type,19098 .Void => return Air.Inst.Ref.void_type,
...@@ -18648,41 +19105,48 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -18648,41 +19105,48 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
18648 .AnyFrame => return sema.failWithUseOfAsync(block, src),19105 .AnyFrame => return sema.failWithUseOfAsync(block, src),
18649 .EnumLiteral => return Air.Inst.Ref.enum_literal_type,19106 .EnumLiteral => return Air.Inst.Ref.enum_literal_type,
18650 .Int => {19107 .Int => {
18651 const struct_val = union_val.val.castTag(.aggregate).?.data;19108 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18652 // TODO use reflection instead of magic numbers here19109 const signedness_val = try union_val.val.toValue().fieldValue(
18653 const signedness_val = struct_val[0];19110 mod,
18654 const bits_val = struct_val[1];19111 fields.getIndex(try ip.getOrPutString(gpa, "signedness")).?,
1865519112 );
18656 const signedness = signedness_val.toEnum(std.builtin.Signedness);19113 const bits_val = try union_val.val.toValue().fieldValue(
18657 const bits = @intCast(u16, bits_val.toUnsignedInt(target));19114 mod,
18658 const ty = switch (signedness) {19115 fields.getIndex(try ip.getOrPutString(gpa, "bits")).?,
18659 .signed => try Type.Tag.int_signed.create(sema.arena, bits),19116 );
18660 .unsigned => try Type.Tag.int_unsigned.create(sema.arena, bits),19117
18661 };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);
18662 return sema.addType(ty);19121 return sema.addType(ty);
18663 },19122 },
18664 .Vector => {19123 .Vector => {
18665 const struct_val = union_val.val.castTag(.aggregate).?.data;19124 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18666 // TODO use reflection instead of magic numbers here19125 const len_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18667 const len_val = struct_val[0];19126 try ip.getOrPutString(gpa, "len"),
18668 const child_val = struct_val[1];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);19132 const len = @intCast(u32, len_val.toUnsignedInt(mod));
18671 var buffer: Value.ToTypeBuffer = undefined;19133 const child_ty = child_val.toType();
18672 const child_ty = child_val.toType(&buffer);
1867319134
18674 try sema.checkVectorElemType(block, src, child_ty);19135 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 });
18677 return sema.addType(ty);19141 return sema.addType(ty);
18678 },19142 },
18679 .Float => {19143 .Float => {
18680 const struct_val = union_val.val.castTag(.aggregate).?.data;19144 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18681 // TODO use reflection instead of magic numbers here19145 const bits_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18682 // bits: comptime_int,19146 try ip.getOrPutString(gpa, "bits"),
18683 const bits_val = struct_val[0];19147 ).?);
1868419148
18685 const bits = @intCast(u16, bits_val.toUnsignedInt(target));19149 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
18686 const ty = switch (bits) {19150 const ty = switch (bits) {
18687 16 => Type.f16,19151 16 => Type.f16,
18688 32 => Type.f32,19152 32 => Type.f32,
...@@ -18694,25 +19158,42 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -18694,25 +19158,42 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
18694 return sema.addType(ty);19158 return sema.addType(ty);
18695 },19159 },
18696 .Pointer => {19160 .Pointer => {
18697 const struct_val = union_val.val.castTag(.aggregate).?.data;19161 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18698 // TODO use reflection instead of magic numbers here19162 const size_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18699 const size_val = struct_val[0];19163 try ip.getOrPutString(gpa, "size"),
18700 const is_const_val = struct_val[1];19164 ).?);
18701 const is_volatile_val = struct_val[2];19165 const is_const_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18702 const alignment_val = struct_val[3];19166 try ip.getOrPutString(gpa, "is_const"),
18703 const address_space_val = struct_val[4];19167 ).?);
18704 const child_val = struct_val[5];19168 const is_volatile_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18705 const is_allowzero_val = struct_val[6];19169 try ip.getOrPutString(gpa, "is_volatile"),
18706 const sentinel_val = struct_val[7];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
18708 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {19187 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
18709 return sema.fail(block, src, "alignment must fit in 'u32'", .{});19188 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
18710 }19189 }
18711 const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?);
1871219190
18713 var buffer: Value.ToTypeBuffer = undefined;19191 const abi_align = InternPool.Alignment.fromByteUnits(
18714 const unresolved_elem_ty = child_val.toType(&buffer);19192 (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?,
18715 const elem_ty = if (abi_align == 0)19193 );
19194
19195 const unresolved_elem_ty = child_val.toType();
19196 const elem_ty = if (abi_align == .none)
18716 unresolved_elem_ty19197 unresolved_elem_ty
18717 else t: {19198 else t: {
18718 const elem_ty = try sema.resolveTypeFields(unresolved_elem_ty);19199 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...@@ -18720,301 +19201,282 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
18720 break :t elem_ty;19201 break :t elem_ty;
18721 };19202 };
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;19206 const actual_sentinel: InternPool.Index = s: {
18726 if (!sentinel_val.isNull()) {19207 if (!sentinel_val.isNull(mod)) {
18727 if (ptr_size == .One or ptr_size == .C) {19208 if (ptr_size == .One or ptr_size == .C) {
18728 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});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();
18729 }19218 }
18730 const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data;19219 break :s .none;
18731 const ptr_ty = try Type.ptr(sema.arena, mod, .{19220 };
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 }
1873719221
18738 if (elem_ty.zigTypeTag() == .NoReturn) {19222 if (elem_ty.zigTypeTag(mod) == .NoReturn) {
18739 return sema.fail(block, src, "pointer to noreturn not allowed", .{});19223 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) {
18741 if (ptr_size != .One) {19225 if (ptr_size != .One) {
18742 return sema.fail(block, src, "function pointers must be single pointers", .{});19226 return sema.fail(block, src, "function pointers must be single pointers", .{});
18743 }19227 }
18744 const fn_align = elem_ty.fnInfo().alignment;19228 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
18745 if (abi_align != 0 and fn_align != 0 and19229 if (abi_align != .none and fn_align != .none and
18746 abi_align != fn_align)19230 abi_align != fn_align)
18747 {19231 {
18748 return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{});19232 return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{});
18749 }19233 }
18750 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {19234 } else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
18751 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});19235 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
18752 } else if (ptr_size == .C) {19236 } else if (ptr_size == .C) {
18753 if (!try sema.validateExternType(elem_ty, .other)) {19237 if (!try sema.validateExternType(elem_ty, .other)) {
18754 const msg = msg: {19238 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)});19239 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(mod)});
18756 errdefer msg.destroy(sema.gpa);19240 errdefer msg.destroy(gpa);
1875719241
18758 const src_decl = sema.mod.declPtr(block.src_decl);19242 const src_decl = mod.declPtr(block.src_decl);
18759 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other);19243 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), elem_ty, .other);
1876019244
18761 try sema.addDeclaredHereNote(msg, elem_ty);19245 try sema.addDeclaredHereNote(msg, elem_ty);
18762 break :msg msg;19246 break :msg msg;
18763 };19247 };
18764 return sema.failWithOwnedErrorMsg(msg);19248 return sema.failWithOwnedErrorMsg(msg);
18765 }19249 }
18766 if (elem_ty.zigTypeTag() == .Opaque) {19250 if (elem_ty.zigTypeTag(mod) == .Opaque) {
18767 return sema.fail(block, src, "C pointers cannot point to opaque types", .{});19251 return sema.fail(block, src, "C pointers cannot point to opaque types", .{});
18768 }19252 }
18769 }19253 }
1877019254
18771 const ty = try Type.ptr(sema.arena, mod, .{19255 const ty = try mod.ptrType(.{
18772 .size = ptr_size,19256 .child = elem_ty.toIntern(),
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(),
18779 .sentinel = actual_sentinel,19257 .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 },
18780 });19266 });
18781 return sema.addType(ty);19267 return sema.addType(ty);
18782 },19268 },
18783 .Array => {19269 .Array => {
18784 const struct_val = union_val.val.castTag(.aggregate).?.data;19270 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18785 // TODO use reflection instead of magic numbers here19271 const len_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18786 // len: comptime_int,19272 try ip.getOrPutString(gpa, "len"),
18787 const len_val = struct_val[0];19273 ).?);
18788 // child: type,19274 const child_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18789 const child_val = struct_val[1];19275 try ip.getOrPutString(gpa, "child"),
18790 // sentinel: ?*const anyopaque,19276 ).?);
18791 const sentinel_val = struct_val[2];19277 const sentinel_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
1879219278 try ip.getOrPutString(gpa, "sentinel"),
18793 const len = len_val.toUnsignedInt(target);19279 ).?);
18794 var buffer: Value.ToTypeBuffer = undefined;19280
18795 const child_ty = try child_val.toType(&buffer).copy(sema.arena);19281 const len = len_val.toUnsignedInt(mod);
18796 const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: {19282 const child_ty = child_val.toType();
19283 const sentinel = if (sentinel_val.optionalValue(mod)) |p| blk: {
18797 const ptr_ty = try Type.ptr(sema.arena, mod, .{19284 const ptr_ty = try Type.ptr(sema.arena, mod, .{
18798 .@"addrspace" = .generic,19285 .@"addrspace" = .generic,
18799 .pointee_type = child_ty,19286 .pointee_type = child_ty,
18800 });19287 });
18801 break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?;19288 break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?;
18802 } else null;19289 } 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);
18805 return sema.addType(ty);19292 return sema.addType(ty);
18806 },19293 },
18807 .Optional => {19294 .Optional => {
18808 const struct_val = union_val.val.castTag(.aggregate).?.data;19295 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18809 // TODO use reflection instead of magic numbers here19296 const child_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18810 // child: type,19297 try ip.getOrPutString(gpa, "child"),
18811 const child_val = struct_val[0];19298 ).?);
1881219299
18813 var buffer: Value.ToTypeBuffer = undefined;19300 const child_ty = child_val.toType();
18814 const child_ty = try child_val.toType(&buffer).copy(sema.arena);
1881519301
18816 const ty = try Type.optional(sema.arena, child_ty);19302 const ty = try Type.optional(sema.arena, child_ty, mod);
18817 return sema.addType(ty);19303 return sema.addType(ty);
18818 },19304 },
18819 .ErrorUnion => {19305 .ErrorUnion => {
18820 const struct_val = union_val.val.castTag(.aggregate).?.data;19306 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18821 // TODO use reflection instead of magic numbers here19307 const error_set_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18822 // error_set: type,19308 try ip.getOrPutString(gpa, "error_set"),
18823 const error_set_val = struct_val[0];19309 ).?);
18824 // payload: type,19310 const payload_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18825 const payload_val = struct_val[1];19311 try ip.getOrPutString(gpa, "payload"),
1882619312 ).?);
18827 var buffer: Value.ToTypeBuffer = undefined;19313
18828 const error_set_ty = try error_set_val.toType(&buffer).copy(sema.arena);19314 const error_set_ty = error_set_val.toType();
18829 const payload_ty = try payload_val.toType(&buffer).copy(sema.arena);19315 const payload_ty = payload_val.toType();
1883019316
18831 if (error_set_ty.zigTypeTag() != .ErrorSet) {19317 if (error_set_ty.zigTypeTag(mod) != .ErrorSet) {
18832 return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{});19318 return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{});
18833 }19319 }
1883419320
18835 const ty = try Type.Tag.error_union.create(sema.arena, .{19321 const ty = try mod.errorUnionType(error_set_ty, payload_ty);
18836 .error_set = error_set_ty,
18837 .payload = payload_ty,
18838 });
18839 return sema.addType(ty);19322 return sema.addType(ty);
18840 },19323 },
18841 .ErrorSet => {19324 .ErrorSet => {
18842 const payload_val = union_val.val.optionalValue() orelse19325 const payload_val = union_val.val.toValue().optionalValue(mod) orelse
18843 return sema.addType(Type.initTag(.anyerror));19326 return sema.addType(Type.anyerror);
18844 const slice_val = payload_val.castTag(.slice).?.data;
1884519327
18846 const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod.getTarget()));19328 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
18847 var names: Module.ErrorSet.NameMap = .{};19329 var names: Module.Fn.InferredErrorSet.NameMap = .{};
18848 try names.ensureUnusedCapacity(sema.arena, len);19330 try names.ensureUnusedCapacity(sema.arena, len);
18849 var i: usize = 0;19331 for (0..len) |i| {
18850 while (i < len) : (i += 1) {19332 const elem_val = try payload_val.elemValue(mod, i);
18851 var buf: Value.ElemValueBuffer = undefined;19333 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
18852 const elem_val = slice_val.ptr.elemValueBuffer(mod, i, &buf);19334 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
18853 const struct_val = elem_val.castTag(.aggregate).?.data;19335 try ip.getOrPutString(gpa, "name"),
18854 // TODO use reflection instead of magic numbers here19336 ).?);
18855 // error_set: type,19337
18856 const name_val = struct_val[0];19338 const name = try name_val.toIpString(Type.slice_const_u8, mod);
18857 const name_str = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, sema.mod);19339 _ = try mod.getErrorValue(name);
1885819340 const gop = names.getOrPutAssumeCapacity(name);
18859 const kv = try mod.getErrorValue(name_str);
18860 const gop = names.getOrPutAssumeCapacity(kv.key);
18861 if (gop.found_existing) {19341 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 });
18863 }19345 }
18864 }19346 }
1886519347
18866 // names must be sorted19348 const ty = try mod.errorSetFromUnsortedNames(names.keys());
18867 Module.ErrorSet.sortNames(&names);
18868 const ty = try Type.Tag.error_set_merged.create(sema.arena, names);
18869 return sema.addType(ty);19349 return sema.addType(ty);
18870 },19350 },
18871 .Struct => {19351 .Struct => {
18872 // TODO use reflection instead of magic numbers here19352 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18873 const struct_val = union_val.val.castTag(.aggregate).?.data;19353 const layout_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18874 // layout: containerlayout,19354 try ip.getOrPutString(gpa, "layout"),
18875 const layout_val = struct_val[0];19355 ).?);
18876 // backing_int: ?type,19356 const backing_integer_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18877 const backing_int_val = struct_val[1];19357 try ip.getOrPutString(gpa, "backing_integer"),
18878 // fields: []const enumfield,19358 ).?);
18879 const fields_val = struct_val[2];19359 const fields_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18880 // decls: []const declaration,19360 try ip.getOrPutString(gpa, "fields"),
18881 const decls_val = struct_val[3];19361 ).?);
18882 // is_tuple: bool,19362 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18883 const is_tuple_val = struct_val[4];19363 try ip.getOrPutString(gpa, "decls"),
18884 assert(struct_val.len == 5);19364 ).?);
1888519365 const is_tuple_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18886 const layout = layout_val.toEnum(std.builtin.Type.ContainerLayout);19366 try ip.getOrPutString(gpa, "is_tuple"),
19367 ).?);
19368
19369 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
1888719370
18888 // Decls19371 // Decls
18889 if (decls_val.sliceLen(mod) > 0) {19372 if (decls_val.sliceLen(mod) > 0) {
18890 return sema.fail(block, src, "reified structs must have no decls", .{});19373 return sema.fail(block, src, "reified structs must have no decls", .{});
18891 }19374 }
1889219375
18893 if (layout != .Packed and !backing_int_val.isNull()) {19376 if (layout != .Packed and !backing_integer_val.isNull(mod)) {
18894 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});19377 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});
18895 }19378 }
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());
18898 },19381 },
18899 .Enum => {19382 .Enum => {
18900 const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data;19383 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
18901 // TODO use reflection instead of magic numbers here19384 const tag_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18902 // tag_type: type,19385 try ip.getOrPutString(gpa, "tag_type"),
18903 const tag_type_val = struct_val[0];19386 ).?);
18904 // fields: []const EnumField,19387 const fields_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18905 const fields_val = struct_val[1];19388 try ip.getOrPutString(gpa, "fields"),
18906 // decls: []const Declaration,19389 ).?);
18907 const decls_val = struct_val[2];19390 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
18908 // is_exhaustive: bool,19391 try ip.getOrPutString(gpa, "decls"),
18909 const is_exhaustive_val = struct_val[3];19392 ).?);
19393 const is_exhaustive_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19394 try ip.getOrPutString(gpa, "is_exhaustive"),
19395 ).?);
1891019396
18911 // Decls19397 // Decls
18912 if (decls_val.sliceLen(mod) > 0) {19398 if (decls_val.sliceLen(mod) > 0) {
18913 return sema.fail(block, src, "reified enums must have no decls", .{});19399 return sema.fail(block, src, "reified enums must have no decls", .{});
18914 }19400 }
1891519401
18916 const gpa = sema.gpa;19402 const int_tag_ty = tag_type_val.toType();
18917 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);19403 if (int_tag_ty.zigTypeTag(mod) != .Int) {
18918 errdefer new_decl_arena.deinit();19404 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
18919 const new_decl_arena_allocator = new_decl_arena.allocator();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);
18935 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{19411 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
18936 .ty = Type.type,19412 .ty = Type.noreturn,
18937 .val = enum_val,19413 .val = Value.@"unreachable",
18938 }, name_strategy, "enum", inst);19414 }, name_strategy, "enum", inst);
18939 const new_decl = mod.declPtr(new_decl_index);19415 const new_decl = mod.declPtr(new_decl_index);
18940 new_decl.owns_tv = true;19416 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.* = .{19422 // Define our empty enum decl
18944 .owner_decl = new_decl_index,19423 const fields_len = @intCast(u32, try sema.usizeCast(block, src, fields_val.sliceLen(mod)));
18945 .tag_ty = Type.null,19424 const incomplete_enum = try ip.getIncompleteEnum(gpa, .{
18946 .tag_ty_inferred = false,19425 .decl = new_decl_index,
18947 .fields = .{},19426 .namespace = .none,
18948 .values = .{},19427 .fields_len = fields_len,
18949 .namespace = .{19428 .has_values = true,
18950 .parent = block.namespace,19429 .tag_mode = if (!is_exhaustive_val.toBool())
18951 .ty = enum_ty,19430 .nonexhaustive
18952 .file_scope = block.getFileScope(),19431 else
18953 },19432 .explicit,
18954 };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 type19438 new_decl.ty = Type.type;
18957 var buffer: Value.ToTypeBuffer = undefined;19439 new_decl.val = incomplete_enum.index.toValue();
18958 const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator);
1895919440
18960 if (int_tag_ty.zigTypeTag() != .Int) {19441 for (0..fields_len) |field_i| {
18961 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});19442 const elem_val = try fields_val.elemValue(mod, field_i);
18962 }19443 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
18963 enum_obj.tag_ty = int_tag_ty;19444 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
1896419445 try ip.getOrPutString(gpa, "name"),
18965 // Fields19446 ).?);
18966 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));19447 const value_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
18967 try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);19448 try ip.getOrPutString(gpa, "value"),
18968 try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{19449 ).?);
18969 .ty = enum_obj.tag_ty,
18970 .mod = mod,
18971 });
1897219450
18973 var field_i: usize = 0;19451 const field_name = try name_val.toIpString(Type.slice_const_u8, mod);
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 );
1898819452
18989 if (!try sema.intFitsInType(value_val, enum_obj.tag_ty, null)) {19453 if (!try sema.intFitsInType(value_val, int_tag_ty, null)) {
18990 // TODO: better source location19454 // TODO: better source location
18991 return sema.fail(block, src, "field '{s}' with enumeration value '{}' is too large for backing int type '{}'", .{19455 return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{
18992 field_name,19456 field_name.fmt(ip),
18993 value_val.fmtValue(Type.comptime_int, mod),19457 value_val.fmtValue(Type.comptime_int, mod),
18994 enum_obj.tag_ty.fmt(mod),19458 int_tag_ty.fmt(mod),
18995 });19459 });
18996 }19460 }
1899719461
18998 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);19462 if (try incomplete_enum.addFieldName(ip, gpa, field_name)) |other_index| {
18999 if (gop_field.found_existing) {
19000 const msg = msg: {19463 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 });
19002 errdefer msg.destroy(gpa);19467 errdefer msg.destroy(gpa);
19468 _ = other_index; // TODO: this note is incorrect
19003 try sema.errNote(block, src, msg, "other field here", .{});19469 try sema.errNote(block, src, msg, "other field here", .{});
19004 break :msg msg;19470 break :msg msg;
19005 };19471 };
19006 return sema.failWithOwnedErrorMsg(msg);19472 return sema.failWithOwnedErrorMsg(msg);
19007 }19473 }
1900819474
19009 const copied_tag_val = try value_val.copy(new_decl_arena_allocator);19475 if (try incomplete_enum.addFieldValue(ip, gpa, (try mod.getCoerced(value_val, int_tag_ty)).toIntern())) |other| {
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) {
19015 const msg = msg: {19476 const msg = msg: {
19016 const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{value_val.fmtValue(Type.comptime_int, mod)});19477 const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{value_val.fmtValue(Type.comptime_int, mod)});
19017 errdefer msg.destroy(gpa);19478 errdefer msg.destroy(gpa);
19479 _ = other; // TODO: this note is incorrect
19018 try sema.errNote(block, src, msg, "other enum tag value here", .{});19480 try sema.errNote(block, src, msg, "other enum tag value here", .{});
19019 break :msg msg;19481 break :msg msg;
19020 };19482 };
...@@ -19022,182 +19484,209 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -19022,182 +19484,209 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
19022 }19484 }
19023 }19485 }
1902419486
19025 try new_decl.finalizeNewArena(&new_decl_arena);19487 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19026 return sema.analyzeDeclVal(block, src, new_decl_index);19488 try mod.finalizeAnonDecl(new_decl_index);
19489 return decl_val;
19027 },19490 },
19028 .Opaque => {19491 .Opaque => {
19029 const struct_val = union_val.val.castTag(.aggregate).?.data;19492 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19030 // decls: []const Declaration,19493 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19031 const decls_val = struct_val[0];19494 try ip.getOrPutString(gpa, "decls"),
19495 ).?);
1903219496
19033 // Decls19497 // Decls
19034 if (decls_val.sliceLen(mod) > 0) {19498 if (decls_val.sliceLen(mod) > 0) {
19035 return sema.fail(block, src, "reified opaque must have no decls", .{});19499 return sema.fail(block, src, "reified opaque must have no decls", .{});
19036 }19500 }
1903719501
19038 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);19502 // Because these three things each reference each other,
19039 errdefer new_decl_arena.deinit();19503 // `undefined` placeholders are used in two places before being set
19040 const new_decl_arena_allocator = new_decl_arena.allocator();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);
19050 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{19506 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
19051 .ty = Type.type,19507 .ty = Type.noreturn,
19052 .val = opaque_val,19508 .val = Value.@"unreachable",
19053 }, name_strategy, "opaque", inst);19509 }, name_strategy, "opaque", inst);
19054 const new_decl = mod.declPtr(new_decl_index);19510 const new_decl = mod.declPtr(new_decl_index);
19055 new_decl.owns_tv = true;19511 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.* = .{19517 const new_namespace_index = try mod.createNamespace(.{
19059 .owner_decl = new_decl_index,19518 .parent = block.namespace.toOptional(),
19060 .namespace = .{19519 .ty = undefined,
19061 .parent = block.namespace,19520 .file_scope = block.getFileScope(mod),
19062 .ty = opaque_ty,19521 });
19063 .file_scope = block.getFileScope(),19522 const new_namespace = mod.namespacePtr(new_namespace_index);
19064 },19523 errdefer mod.destroyNamespace(new_namespace_index);
19065 };
1906619524
19067 try new_decl.finalizeNewArena(&new_decl_arena);19525 const opaque_ty = try mod.intern(.{ .opaque_type = .{
19068 return sema.analyzeDeclVal(block, src, new_decl_index);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;
19069 },19539 },
19070 .Union => {19540 .Union => {
19071 // TODO use reflection instead of magic numbers here19541 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19072 const struct_val = union_val.val.castTag(.aggregate).?.data;19542 const layout_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19073 // layout: containerlayout,19543 try ip.getOrPutString(gpa, "layout"),
19074 const layout_val = struct_val[0];19544 ).?);
19075 // tag_type: ?type,19545 const tag_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19076 const tag_type_val = struct_val[1];19546 try ip.getOrPutString(gpa, "tag_type"),
19077 // fields: []const enumfield,19547 ).?);
19078 const fields_val = struct_val[2];19548 const fields_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19079 // decls: []const declaration,19549 try ip.getOrPutString(gpa, "fields"),
19080 const decls_val = struct_val[3];19550 ).?);
19551 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19552 try ip.getOrPutString(gpa, "decls"),
19553 ).?);
1908119554
19082 // Decls19555 // Decls
19083 if (decls_val.sliceLen(mod) > 0) {19556 if (decls_val.sliceLen(mod) > 0) {
19084 return sema.fail(block, src, "reified unions must have no decls", .{});19557 return sema.fail(block, src, "reified unions must have no decls", .{});
19085 }19558 }
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);19561 // Because these three things each reference each other, `undefined`
19089 errdefer new_decl_arena.deinit();19562 // placeholders are used before being set after the union type gains an
19090 const new_decl_arena_allocator = new_decl_arena.allocator();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);
19108 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{19565 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
19109 .ty = Type.type,19566 .ty = Type.noreturn,
19110 .val = new_union_val,19567 .val = Value.@"unreachable",
19111 }, name_strategy, "union", inst);19568 }, name_strategy, "union", inst);
19112 const new_decl = mod.declPtr(new_decl_index);19569 const new_decl = mod.declPtr(new_decl_index);
19113 new_decl.owns_tv = true;19570 new_decl.owns_tv = true;
19114 errdefer mod.abortAnonDecl(new_decl_index);19571 errdefer {
19115 union_obj.* = .{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(.{
19116 .owner_decl = new_decl_index,19585 .owner_decl = new_decl_index,
19117 .tag_ty = Type.initTag(.null),19586 .tag_ty = Type.null,
19118 .fields = .{},19587 .fields = .{},
19119 .zir_index = inst,19588 .zir_index = inst,
19120 .layout = layout,19589 .layout = layout,
19121 .status = .have_field_types,19590 .status = .have_field_types,
19122 .namespace = .{19591 .namespace = new_namespace_index,
19123 .parent = block.namespace,19592 });
19124 .ty = union_ty,19593 const union_obj = mod.unionPtr(union_index);
19125 .file_scope = block.getFileScope(),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,
19126 },19605 },
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
19129 // Tag type19614 // Tag type
19130 var tag_ty_field_names: ?Module.EnumFull.NameMap = null;
19131 var enum_field_names: ?*Module.EnumNumbered.NameMap = null;
19132 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));19615 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
19133 if (tag_type_val.optionalValue()) |payload_val| {19616 var explicit_tags_seen: []bool = &.{};
19134 var buffer: Value.ToTypeBuffer = undefined;19617 var enum_field_names: []InternPool.NullTerminatedString = &.{};
19135 union_obj.tag_ty = try payload_val.toType(&buffer).copy(new_decl_arena_allocator);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) {19626 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
19138 return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{});19627 @memset(explicit_tags_seen, false);
19139 }
19140 tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena);
19141 } else {19628 } else {
19142 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(block, fields_len, null);19629 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
19143 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
19144 }19630 }
1914519631
19146 // Fields19632 // Fields
19147 try union_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);19633 try union_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len);
1914819634
19149 var i: usize = 0;19635 for (0..fields_len) |i| {
19150 while (i < fields_len) : (i += 1) {19636 const elem_val = try fields_val.elemValue(mod, i);
19151 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i);19637 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19152 const field_struct_val = elem_val.castTag(.aggregate).?.data;19638 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19153 // TODO use reflection instead of magic numbers here19639 try ip.getOrPutString(gpa, "name"),
19154 // name: []const u819640 ).?);
19155 const name_val = field_struct_val[0];19641 const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19156 // type: type,19642 try ip.getOrPutString(gpa, "type"),
19157 const type_val = field_struct_val[1];19643 ).?);
19158 // alignment: comptime_int,19644 const alignment_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19159 const alignment_val = field_struct_val[2];19645 try ip.getOrPutString(gpa, "alignment"),
1916019646 ).?);
19161 const field_name = try name_val.toAllocatedBytes(19647
19162 Type.initTag(.const_slice_u8),19648 const field_name = try name_val.toIpString(Type.slice_const_u8, mod);
19163 new_decl_arena_allocator,19649
19164 sema.mod,19650 if (enum_field_names.len != 0) {
19165 );19651 enum_field_names[i] = field_name;
1916619652 }
19167 if (enum_field_names) |set| {19653
19168 set.putAssumeCapacity(field_name, {});19654 if (explicit_tags_seen.len > 0) {
19169 }19655 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
1917019656 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
19171 if (tag_ty_field_names) |*names| {
19172 const enum_has_field = names.orderedRemove(field_name);
19173 if (!enum_has_field) {
19174 const msg = msg: {19657 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) });19658 const msg = try sema.errMsg(block, src, "no field named '{}' in enum '{}'", .{
19176 errdefer msg.destroy(sema.gpa);19659 field_name.fmt(ip),
19660 union_obj.tag_ty.fmt(mod),
19661 });
19662 errdefer msg.destroy(gpa);
19177 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);19663 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
19178 break :msg msg;19664 break :msg msg;
19179 };19665 };
19180 return sema.failWithOwnedErrorMsg(msg);19666 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;
19182 }19672 }
1918319673
19184 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);19674 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
19185 if (gop.found_existing) {19675 if (gop.found_existing) {
19186 // TODO: better source location19676 // 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)});
19188 }19678 }
1918919679
19190 var buffer: Value.ToTypeBuffer = undefined;19680 const field_ty = type_val.toType();
19191 const field_ty = try type_val.toType(&buffer).copy(new_decl_arena_allocator);
19192 gop.value_ptr.* = .{19681 gop.value_ptr.* = .{
19193 .ty = field_ty,19682 .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)).?),
19195 };19684 };
1919619685
19197 if (field_ty.zigTypeTag() == .Opaque) {19686 if (field_ty.zigTypeTag(mod) == .Opaque) {
19198 const msg = msg: {19687 const msg = msg: {
19199 const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});19688 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
19202 try sema.addDeclaredHereNote(msg, field_ty);19691 try sema.addDeclaredHereNote(msg, field_ty);
19203 break :msg msg;19692 break :msg msg;
...@@ -19206,23 +19695,23 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -19206,23 +19695,23 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
19206 }19695 }
19207 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {19696 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
19208 const msg = msg: {19697 const msg = msg: {
19209 const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});19698 const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
19210 errdefer msg.destroy(sema.gpa);19699 errdefer msg.destroy(gpa);
1921119700
19212 const src_decl = sema.mod.declPtr(block.src_decl);19701 const src_decl = mod.declPtr(block.src_decl);
19213 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), field_ty, .union_field);19702 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .union_field);
1921419703
19215 try sema.addDeclaredHereNote(msg, field_ty);19704 try sema.addDeclaredHereNote(msg, field_ty);
19216 break :msg msg;19705 break :msg msg;
19217 };19706 };
19218 return sema.failWithOwnedErrorMsg(msg);19707 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))) {
19220 const msg = msg: {19709 const msg = msg: {
19221 const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});19710 const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
19222 errdefer msg.destroy(sema.gpa);19711 errdefer msg.destroy(gpa);
1922319712
19224 const src_decl = sema.mod.declPtr(block.src_decl);19713 const src_decl = mod.declPtr(block.src_decl);
19225 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl), field_ty);19714 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty);
1922619715
19227 try sema.addDeclaredHereNote(msg, field_ty);19716 try sema.addDeclaredHereNote(msg, field_ty);
19228 break :msg msg;19717 break :msg msg;
...@@ -19231,47 +19720,61 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -19231,47 +19720,61 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
19231 }19720 }
19232 }19721 }
1923319722
19234 if (tag_ty_field_names) |names| {19723 if (explicit_tags_seen.len > 0) {
19235 if (names.count() > 0) {19724 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
19725 if (tag_info.names.len > fields_len) {
19236 const msg = msg: {19726 const msg = msg: {
19237 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});19727 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
19240 const enum_ty = union_obj.tag_ty;19730 const enum_ty = union_obj.tag_ty;
19241 for (names.keys()) |field_name| {19731 for (tag_info.names, 0..) |field_name, field_index| {
19242 const field_index = enum_ty.enumFieldIndex(field_name).?;19732 if (explicit_tags_seen[field_index]) continue;
19243 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});19733 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
19734 field_name.fmt(ip),
19735 });
19244 }19736 }
19245 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);19737 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
19246 break :msg msg;19738 break :msg msg;
19247 };19739 };
19248 return sema.failWithOwnedErrorMsg(msg);19740 return sema.failWithOwnedErrorMsg(msg);
19249 }19741 }
19742 } else {
19743 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(block, enum_field_names, null);
19250 }19744 }
1925119745
19252 try new_decl.finalizeNewArena(&new_decl_arena);19746 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19253 return sema.analyzeDeclVal(block, src, new_decl_index);19747 try mod.finalizeAnonDecl(new_decl_index);
19748 return decl_val;
19254 },19749 },
19255 .Fn => {19750 .Fn => {
19256 const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data;19751 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19257 // TODO use reflection instead of magic numbers here19752 const calling_convention_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19258 // calling_convention: CallingConvention,19753 try ip.getOrPutString(gpa, "calling_convention"),
19259 const cc = struct_val[0].toEnum(std.builtin.CallingConvention);19754 ).?);
19260 // alignment: comptime_int,19755 const alignment_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19261 const alignment_val = struct_val[1];19756 try ip.getOrPutString(gpa, "alignment"),
19262 // is_generic: bool,19757 ).?);
19263 const is_generic = struct_val[2].toBool();19758 const is_generic_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19264 // is_var_args: bool,19759 try ip.getOrPutString(gpa, "is_generic"),
19265 const is_var_args = struct_val[3].toBool();19760 ).?);
19266 // return_type: ?type,19761 const is_var_args_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19267 const return_type_val = struct_val[4];19762 try ip.getOrPutString(gpa, "is_var_args"),
19268 // args: []const Param,19763 ).?);
19269 const args_val = struct_val[5];19764 const return_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
1927019765 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();
19271 if (is_generic) {19772 if (is_generic) {
19272 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});19773 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});
19273 }19774 }
1927419775
19776 const is_var_args = is_var_args_val.toBool();
19777 const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val);
19275 if (is_var_args and cc != .C) {19778 if (is_var_args and cc != .C) {
19276 return sema.fail(block, src, "varargs functions must have C calling convention", .{});19779 return sema.fail(block, src, "varargs functions must have C calling convention", .{});
19277 }19780 }
...@@ -19280,63 +19783,55 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -19280,63 +19783,55 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
19280 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {19783 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
19281 return sema.fail(block, src, "alignment must fit in 'u32'", .{});19784 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
19282 }19785 }
19283 const alignment = @intCast(u29, alignment_val.toUnsignedInt(target));19786 const alignment = @intCast(u29, alignment_val.toUnsignedInt(mod));
19284 if (alignment == target_util.defaultFunctionAlignment(target)) {19787 if (alignment == target_util.defaultFunctionAlignment(target)) {
19285 break :alignment 0;19788 break :alignment .none;
19286 } else {19789 } else {
19287 break :alignment alignment;19790 break :alignment InternPool.Alignment.fromByteUnits(alignment);
19288 }19791 }
19289 };19792 };
19290 const return_type = return_type_val.optionalValue() orelse19793 const return_type = return_type_val.optionalValue(mod) orelse
19291 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});19794 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
1929219795
19293 var buf: Value.ToTypeBuffer = undefined;19796 const args_len = try sema.usizeCast(block, src, params_val.sliceLen(mod));
1929419797 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
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);
1930019798
19301 var noalias_bits: u32 = 0;19799 var noalias_bits: u32 = 0;
19302 var i: usize = 0;19800 for (param_types, 0..) |*param_type, i| {
19303 while (i < args_len) : (i += 1) {19801 const elem_val = try params_val.elemValue(mod, i);
19304 var arg_buf: Value.ElemValueBuffer = undefined;19802 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19305 const arg = args_slice_val.ptr.elemValueBuffer(mod, i, &arg_buf);19803 const param_is_generic_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19306 const arg_val = arg.castTag(.aggregate).?.data;19804 try ip.getOrPutString(gpa, "is_generic"),
19307 // TODO use reflection instead of magic numbers here19805 ).?);
19308 // is_generic: bool,19806 const param_is_noalias_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19309 const arg_is_generic = arg_val[0].toBool();19807 try ip.getOrPutString(gpa, "is_noalias"),
19310 // is_noalias: bool,19808 ).?);
19311 const arg_is_noalias = arg_val[1].toBool();19809 const opt_param_type_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19312 // type: ?type,19810 try ip.getOrPutString(gpa, "type"),
19313 const param_type_opt_val = arg_val[2];19811 ).?);
1931419812
19315 if (arg_is_generic) {19813 if (param_is_generic_val.toBool()) {
19316 return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});19814 return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});
19317 }19815 }
1931819816
19319 const param_type_val = param_type_opt_val.optionalValue() orelse19817 const param_type_val = opt_param_type_val.optionalValue(mod) orelse
19320 return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});19818 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) {19821 if (param_is_noalias_val.toBool()) {
19324 if (!param_type.isPtrAtRuntime()) {19822 if (!param_type.toType().isPtrAtRuntime(mod)) {
19325 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});19823 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});
19326 }19824 }
19327 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse19825 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse
19328 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));19826 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
19329 }19827 }
19330
19331 param_types[i] = param_type;
19332 comptime_params[i] = false;
19333 }19828 }
1933419829
19335 var fn_info = Type.Payload.Function.Data{19830 const ty = try mod.funcType(.{
19336 .param_types = param_types,19831 .param_types = param_types,
19337 .comptime_params = comptime_params.ptr,19832 .comptime_bits = 0,
19338 .noalias_bits = noalias_bits,19833 .noalias_bits = noalias_bits,
19339 .return_type = try return_type.toType(&buf).copy(sema.arena),19834 .return_type = return_type.toIntern(),
19340 .alignment = alignment,19835 .alignment = alignment,
19341 .cc = cc,19836 .cc = cc,
19342 .is_var_args = is_var_args,19837 .is_var_args = is_var_args,
...@@ -19346,9 +19841,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -19346,9 +19841,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
19346 .cc_is_generic = false,19841 .cc_is_generic = false,
19347 .section_is_generic = false,19842 .section_is_generic = false,
19348 .addrspace_is_generic = false,19843 .addrspace_is_generic = false,
19349 };19844 });
19350
19351 const ty = try Type.Tag.function.create(sema.arena, fn_info);
19352 return sema.addType(ty);19845 return sema.addType(ty);
19353 },19846 },
19354 .Frame => return sema.failWithUseOfAsync(block, src),19847 .Frame => return sema.failWithUseOfAsync(block, src),
...@@ -19366,22 +19859,34 @@ fn reifyStruct(...@@ -19366,22 +19859,34 @@ fn reifyStruct(
19366 name_strategy: Zir.Inst.NameStrategy,19859 name_strategy: Zir.Inst.NameStrategy,
19367 is_tuple: bool,19860 is_tuple: bool,
19368) CompileError!Air.Inst.Ref {19861) 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);
19376 const mod = sema.mod;19862 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
19377 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{19870 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
19378 .ty = Type.type,19871 .ty = Type.noreturn,
19379 .val = new_struct_val,19872 .val = Value.@"unreachable",
19380 }, name_strategy, "struct", inst);19873 }, name_strategy, "struct", inst);
19381 const new_decl = mod.declPtr(new_decl_index);19874 const new_decl = mod.declPtr(new_decl_index);
19382 new_decl.owns_tv = true;19875 new_decl.owns_tv = true;
19383 errdefer mod.abortAnonDecl(new_decl_index);19876 errdefer {
19384 struct_obj.* = .{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(.{
19385 .owner_decl = new_decl_index,19890 .owner_decl = new_decl_index,
19386 .fields = .{},19891 .fields = .{},
19387 .zir_index = inst,19892 .zir_index = inst,
...@@ -19389,38 +19894,49 @@ fn reifyStruct(...@@ -19389,38 +19894,49 @@ fn reifyStruct(
19389 .status = .have_field_types,19894 .status = .have_field_types,
19390 .known_non_opv = false,19895 .known_non_opv = false,
19391 .is_tuple = is_tuple,19896 .is_tuple = is_tuple,
19392 .namespace = .{19897 .namespace = new_namespace_index,
19393 .parent = block.namespace,19898 });
19394 .ty = struct_ty,19899 const struct_obj = mod.structPtr(struct_index);
19395 .file_scope = block.getFileScope(),19900 errdefer mod.destroyStruct(struct_index);
19396 },
19397 };
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
19401 // Fields19913 // Fields
19402 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));19914 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);
19404 var i: usize = 0;19916 var i: usize = 0;
19405 while (i < fields_len) : (i += 1) {19917 while (i < fields_len) : (i += 1) {
19406 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i);19918 const elem_val = try fields_val.elemValue(mod, i);
19407 const field_struct_val = elem_val.castTag(.aggregate).?.data;19919 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19408 // TODO use reflection instead of magic numbers here19920 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19409 // name: []const u819921 try ip.getOrPutString(gpa, "name"),
19410 const name_val = field_struct_val[0];19922 ).?);
19411 // type: type,19923 const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19412 const type_val = field_struct_val[1];19924 try ip.getOrPutString(gpa, "type"),
19413 // default_value: ?*const anyopaque,19925 ).?);
19414 const default_value_val = field_struct_val[2];19926 const default_value_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19415 // is_comptime: bool,19927 try ip.getOrPutString(gpa, "default_value"),
19416 const is_comptime_val = field_struct_val[3];19928 ).?);
19417 // alignment: comptime_int,19929 const is_comptime_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19418 const alignment_val = field_struct_val[4];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
19420 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {19936 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
19421 return sema.fail(block, src, "alignment must fit in 'u32'", .{});19937 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
19422 }19938 }
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
19425 if (layout == .Packed) {19941 if (layout == .Packed) {
19426 if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});19942 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(...@@ -19430,21 +19946,15 @@ fn reifyStruct(
19430 return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{});19946 return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{});
19431 }19947 }
1943219948
19433 const field_name = try name_val.toAllocatedBytes(19949 const field_name = try name_val.toIpString(Type.slice_const_u8, mod);
19434 Type.initTag(.const_slice_u8),
19435 new_decl_arena_allocator,
19436 mod,
19437 );
1943819950
19439 if (is_tuple) {19951 if (is_tuple) {
19440 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch {19952 const field_index = field_name.toUnsigned(ip) orelse return sema.fail(
19441 return sema.fail(19953 block,
19442 block,19954 src,
19443 src,19955 "tuple cannot have non-numeric field '{}'",
19444 "tuple cannot have non-numeric field '{s}'",19956 .{field_name.fmt(ip)},
19445 .{field_name},19957 );
19446 );
19447 };
1944819958
19449 if (field_index >= fields_len) {19959 if (field_index >= fields_len) {
19450 return sema.fail(19960 return sema.fail(
...@@ -19458,22 +19968,19 @@ fn reifyStruct(...@@ -19458,22 +19968,19 @@ fn reifyStruct(
19458 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);19968 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
19459 if (gop.found_existing) {19969 if (gop.found_existing) {
19460 // TODO: better source location19970 // 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)});
19462 }19972 }
1946319973
19464 const default_val = if (default_value_val.optionalValue()) |opt_val| blk: {19974 const field_ty = type_val.toType();
19465 const payload_val = if (opt_val.pointerDecl()) |opt_decl|19975 const default_val = if (default_value_val.optionalValue(mod)) |opt_val|
19466 mod.declPtr(opt_decl).val19976 (try sema.pointerDeref(block, src, opt_val, try mod.singleConstPtrType(field_ty)) orelse
19467 else19977 return sema.failWithNeededComptime(block, src, "struct field default value must be comptime-known")).toIntern()
19468 opt_val;19978 else
19469 break :blk try payload_val.copy(new_decl_arena_allocator);19979 .none;
19470 } else Value.initTag(.unreachable_value);19980 if (is_comptime_val.toBool() and default_val == .none) {
19471 if (is_comptime_val.toBool() and default_val.tag() == .unreachable_value) {
19472 return sema.fail(block, src, "comptime field without default initialization value", .{});19981 return sema.fail(block, src, "comptime field without default initialization value", .{});
19473 }19982 }
1947419983
19475 var buffer: Value.ToTypeBuffer = undefined;
19476 const field_ty = try type_val.toType(&buffer).copy(new_decl_arena_allocator);
19477 gop.value_ptr.* = .{19984 gop.value_ptr.* = .{
19478 .ty = field_ty,19985 .ty = field_ty,
19479 .abi_align = abi_align,19986 .abi_align = abi_align,
...@@ -19482,20 +19989,20 @@ fn reifyStruct(...@@ -19482,20 +19989,20 @@ fn reifyStruct(
19482 .offset = undefined,19989 .offset = undefined,
19483 };19990 };
1948419991
19485 if (field_ty.zigTypeTag() == .Opaque) {19992 if (field_ty.zigTypeTag(mod) == .Opaque) {
19486 const msg = msg: {19993 const msg = msg: {
19487 const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});19994 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
19490 try sema.addDeclaredHereNote(msg, field_ty);19997 try sema.addDeclaredHereNote(msg, field_ty);
19491 break :msg msg;19998 break :msg msg;
19492 };19999 };
19493 return sema.failWithOwnedErrorMsg(msg);20000 return sema.failWithOwnedErrorMsg(msg);
19494 }20001 }
19495 if (field_ty.zigTypeTag() == .NoReturn) {20002 if (field_ty.zigTypeTag(mod) == .NoReturn) {
19496 const msg = msg: {20003 const msg = msg: {
19497 const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{});20004 const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{});
19498 errdefer msg.destroy(sema.gpa);20005 errdefer msg.destroy(gpa);
1949920006
19500 try sema.addDeclaredHereNote(msg, field_ty);20007 try sema.addDeclaredHereNote(msg, field_ty);
19501 break :msg msg;20008 break :msg msg;
...@@ -19505,22 +20012,22 @@ fn reifyStruct(...@@ -19505,22 +20012,22 @@ fn reifyStruct(
19505 if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) {20012 if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) {
19506 const msg = msg: {20013 const msg = msg: {
19507 const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});20014 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
19510 const src_decl = sema.mod.declPtr(block.src_decl);20017 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
19513 try sema.addDeclaredHereNote(msg, field_ty);20020 try sema.addDeclaredHereNote(msg, field_ty);
19514 break :msg msg;20021 break :msg msg;
19515 };20022 };
19516 return sema.failWithOwnedErrorMsg(msg);20023 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))) {
19518 const msg = msg: {20025 const msg = msg: {
19519 const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});20026 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
19522 const src_decl = sema.mod.declPtr(block.src_decl);20029 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
19525 try sema.addDeclaredHereNote(msg, field_ty);20032 try sema.addDeclaredHereNote(msg, field_ty);
19526 break :msg msg;20033 break :msg msg;
...@@ -19536,7 +20043,7 @@ fn reifyStruct(...@@ -19536,7 +20043,7 @@ fn reifyStruct(
19536 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {20043 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
19537 error.AnalysisFail => {20044 error.AnalysisFail => {
19538 const msg = sema.err orelse return err;20045 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", .{});
19540 return err;20047 return err;
19541 },20048 },
19542 else => return err,20049 else => return err,
...@@ -19545,30 +20052,27 @@ fn reifyStruct(...@@ -19545,30 +20052,27 @@ fn reifyStruct(
1954520052
19546 var fields_bit_sum: u64 = 0;20053 var fields_bit_sum: u64 = 0;
19547 for (struct_obj.fields.values()) |field| {20054 for (struct_obj.fields.values()) |field| {
19548 fields_bit_sum += field.ty.bitSize(target);20055 fields_bit_sum += field.ty.bitSize(mod);
19549 }20056 }
1955020057
19551 if (backing_int_val.optionalValue()) |payload| {20058 if (backing_int_val.optionalValue(mod)) |payload| {
19552 var buf: Value.ToTypeBuffer = undefined;20059 const backing_int_ty = payload.toType();
19553 const backing_int_ty = payload.toType(&buf);
19554 try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum);20060 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;
19556 } else {20062 } else {
19557 var buf: Type.Payload.Bits = .{20063 struct_obj.backing_int_ty = try mod.intType(.unsigned, @intCast(u16, fields_bit_sum));
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);
19562 }20064 }
1956320065
19564 struct_obj.status = .have_layout;20066 struct_obj.status = .have_layout;
19565 }20067 }
1956620068
19567 try new_decl.finalizeNewArena(&new_decl_arena);20069 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19568 return sema.analyzeDeclVal(block, src, new_decl_index);20070 try mod.finalizeAnonDecl(new_decl_index);
20071 return decl_val;
19569}20072}
1957020073
19571fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {20074fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20075 const mod = sema.mod;
19572 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;20076 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
19573 const src = LazySrcLoc.nodeOffset(extra.node);20077 const src = LazySrcLoc.nodeOffset(extra.node);
19574 const addrspace_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };20078 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...@@ -19580,7 +20084,7 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
1958020084
19581 try sema.checkPtrOperand(block, ptr_src, ptr_ty);20085 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);
19584 const src_addrspace = ptr_info.@"addrspace";20088 const src_addrspace = ptr_info.@"addrspace";
19585 if (!target_util.addrSpaceCastIsValid(sema.mod.getTarget(), src_addrspace, dest_addrspace)) {20089 if (!target_util.addrSpaceCastIsValid(sema.mod.getTarget(), src_addrspace, dest_addrspace)) {
19586 const msg = msg: {20090 const msg = msg: {
...@@ -19594,8 +20098,8 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -19594,8 +20098,8 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
1959420098
19595 ptr_info.@"addrspace" = dest_addrspace;20099 ptr_info.@"addrspace" = dest_addrspace;
19596 const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);20100 const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
19597 const dest_ty = if (ptr_ty.zigTypeTag() == .Optional)20101 const dest_ty = if (ptr_ty.zigTypeTag(mod) == .Optional)
19598 try Type.optional(sema.arena, dest_ptr_ty)20102 try Type.optional(sema.arena, dest_ptr_ty, mod)
19599 else20103 else
19600 dest_ptr_ty;20104 dest_ptr_ty;
1960120105
...@@ -19624,6 +20128,7 @@ fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.In...@@ -19624,6 +20128,7 @@ fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.In
19624}20128}
1962520129
19626fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {20130fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20131 const mod = sema.mod;
19627 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;20132 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
19628 const src = LazySrcLoc.nodeOffset(extra.node);20133 const src = LazySrcLoc.nodeOffset(extra.node);
19629 const va_list_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };20134 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...@@ -19638,7 +20143,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
19638 errdefer msg.destroy(sema.gpa);20143 errdefer msg.destroy(sema.gpa);
1963920144
19640 const src_decl = sema.mod.declPtr(block.src_decl);20145 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
19643 try sema.addDeclaredHereNote(msg, arg_ty);20148 try sema.addDeclaredHereNote(msg, arg_ty);
19644 break :msg msg;20149 break :msg msg;
...@@ -19685,6 +20190,7 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)...@@ -19685,6 +20190,7 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
19685}20190}
1968620191
19687fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20192fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20193 const mod = sema.mod;
19688 const inst_data = sema.code.instructions.items(.data)[inst].un_node;20194 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
19689 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20195 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
19690 const ty = try sema.resolveType(block, ty_src, inst_data.operand);20196 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...@@ -19692,11 +20198,19 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19692 var anon_decl = try block.startAnonDecl();20198 var anon_decl = try block.startAnonDecl();
19693 defer anon_decl.deinit();20199 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 });
19697 const new_decl = try anon_decl.finish(20208 const new_decl = try anon_decl.finish(
19698 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),20209 decl_ty,
19699 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),20210 (try mod.intern(.{ .aggregate = .{
20211 .ty = decl_ty.toIntern(),
20212 .storage = .{ .bytes = bytes },
20213 } })).toValue(),
19700 0, // default alignment20214 0, // default alignment
19701 );20215 );
1970220216
...@@ -19716,6 +20230,7 @@ fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -19716,6 +20230,7 @@ fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
19716}20230}
1971720231
19718fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20232fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20233 const mod = sema.mod;
19719 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;20234 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19720 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;20235 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
19721 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20236 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!...@@ -19730,24 +20245,24 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
19730 if (try sema.resolveMaybeUndefVal(operand)) |val| {20245 if (try sema.resolveMaybeUndefVal(operand)) |val| {
19731 const result_val = try sema.floatToInt(block, operand_src, val, operand_ty, dest_ty);20246 const result_val = try sema.floatToInt(block, operand_src, val, operand_ty, dest_ty);
19732 return sema.addConstant(dest_ty, result_val);20247 return sema.addConstant(dest_ty, result_val);
19733 } else if (dest_ty.zigTypeTag() == .ComptimeInt) {20248 } else if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {
19734 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known");20249 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known");
19735 }20250 }
1973620251
19737 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);20252 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) {
19739 if (block.wantSafety()) {20254 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)));
19741 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);20256 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
19742 }20257 }
19743 return sema.addConstant(dest_ty, Value.zero);20258 return sema.addConstant(dest_ty, try mod.intValue(dest_ty, 0));
19744 }20259 }
19745 const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);20260 const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
19746 if (block.wantSafety()) {20261 if (block.wantSafety()) {
19747 const back = try block.addTyOp(.int_to_float, operand_ty, result);20262 const back = try block.addTyOp(.int_to_float, operand_ty, result);
19748 const diff = try block.addBinOp(.sub, operand, back);20263 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));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)));
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));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)));
19751 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);20266 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
19752 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);20267 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
19753 }20268 }
...@@ -19755,6 +20270,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -19755,6 +20270,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
19755}20270}
1975620271
19757fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20272fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20273 const mod = sema.mod;
19758 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;20274 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19759 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;20275 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
19760 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20276 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!...@@ -19769,7 +20285,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
19769 if (try sema.resolveMaybeUndefVal(operand)) |val| {20285 if (try sema.resolveMaybeUndefVal(operand)) |val| {
19770 const result_val = try val.intToFloatAdvanced(sema.arena, operand_ty, dest_ty, sema.mod, sema);20286 const result_val = try val.intToFloatAdvanced(sema.arena, operand_ty, dest_ty, sema.mod, sema);
19771 return sema.addConstant(dest_ty, result_val);20287 return sema.addConstant(dest_ty, result_val);
19772 } else if (dest_ty.zigTypeTag() == .ComptimeFloat) {20288 } else if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) {
19773 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime-known");20289 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime-known");
19774 }20290 }
1977520291
...@@ -19778,6 +20294,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -19778,6 +20294,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
19778}20294}
1977920295
19780fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20296fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20297 const mod = sema.mod;
19781 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;20298 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19782 const src = inst_data.src();20299 const src = inst_data.src();
1978320300
...@@ -19790,11 +20307,10 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19790,11 +20307,10 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19790 const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20307 const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
19791 const ptr_ty = try sema.resolveType(block, src, extra.lhs);20308 const ptr_ty = try sema.resolveType(block, src, extra.lhs);
19792 try sema.checkPtrType(block, type_src, ptr_ty);20309 try sema.checkPtrType(block, type_src, ptr_ty);
19793 const elem_ty = ptr_ty.elemType2();20310 const elem_ty = ptr_ty.elemType2(mod);
19794 const target = sema.mod.getTarget();20311 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);
19795 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(target, sema);
1979620312
19797 if (ptr_ty.isSlice()) {20313 if (ptr_ty.isSlice(mod)) {
19798 const msg = msg: {20314 const msg = msg: {
19799 const msg = try sema.errMsg(block, type_src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(sema.mod)});20315 const msg = try sema.errMsg(block, type_src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(sema.mod)});
19800 errdefer msg.destroy(sema.gpa);20316 errdefer msg.destroy(sema.gpa);
...@@ -19805,36 +20321,26 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19805,36 +20321,26 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19805 }20321 }
1980620322
19807 if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| {20323 if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| {
19808 const addr = val.toUnsignedInt(target);20324 const addr = val.toUnsignedInt(mod);
19809 if (!ptr_ty.isAllowzeroPtr() and addr == 0)20325 if (!ptr_ty.isAllowzeroPtr(mod) and addr == 0)
19810 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)});20326 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)});
19811 if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0)20327 if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0)
19812 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)});20328 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);20330 return sema.addConstant(ptr_ty, try mod.ptrIntValue(ptr_ty, addr));
19815 val_payload.* = .{
19816 .base = .{ .tag = .int_u64 },
19817 .data = addr,
19818 };
19819 return sema.addConstant(ptr_ty, Value.initPayload(&val_payload.base));
19820 }20331 }
1982120332
19822 try sema.requireRuntimeBlock(block, src, operand_src);20333 try sema.requireRuntimeBlock(block, src, operand_src);
19823 if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag() == .Fn)) {20334 if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) {
19824 if (!ptr_ty.isAllowzeroPtr()) {20335 if (!ptr_ty.isAllowzeroPtr(mod)) {
19825 const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);20336 const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
19826 try sema.addSafetyCheck(block, is_non_zero, .cast_to_null);20337 try sema.addSafetyCheck(block, is_non_zero, .cast_to_null);
19827 }20338 }
1982820339
19829 if (ptr_align > 1) {20340 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 };
19835 const align_minus_1 = try sema.addConstant(20341 const align_minus_1 = try sema.addConstant(
19836 Type.usize,20342 Type.usize,
19837 Value.initPayload(&val_payload.base),20343 try mod.intValue(Type.usize, ptr_align - 1),
19838 );20344 );
19839 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);20345 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);
19840 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);20346 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...@@ -19845,6 +20351,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19845}20351}
1984620352
19847fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {20353fn 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;
19848 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;20356 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
19849 const src = LazySrcLoc.nodeOffset(extra.node);20357 const src = LazySrcLoc.nodeOffset(extra.node);
19850 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };20358 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...@@ -19860,22 +20368,27 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1986020368
19861 if (disjoint: {20369 if (disjoint: {
19862 // Try avoiding resolving inferred error sets if we can20370 // Try avoiding resolving inferred error sets if we can
19863 if (!dest_ty.isAnyError() and dest_ty.errorSetNames().len == 0) break :disjoint true;20371 if (!dest_ty.isAnyError(mod) and dest_ty.errorSetNames(mod).len == 0) break :disjoint true;
19864 if (!operand_ty.isAnyError() and operand_ty.errorSetNames().len == 0) break :disjoint true;20372 if (!operand_ty.isAnyError(mod) and operand_ty.errorSetNames(mod).len == 0) break :disjoint true;
19865 if (dest_ty.isAnyError()) break :disjoint false;20373 if (dest_ty.isAnyError(mod)) break :disjoint false;
19866 if (operand_ty.isAnyError()) break :disjoint false;20374 if (operand_ty.isAnyError(mod)) break :disjoint false;
19867 for (dest_ty.errorSetNames()) |dest_err_name|20375 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
19868 if (operand_ty.errorSetHasField(dest_err_name))20376 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
19869 break :disjoint false;20377 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 {
19872 break :disjoint true;20383 break :disjoint true;
20384 }
1987320385
19874 try sema.resolveInferredErrorSetTy(block, dest_ty_src, dest_ty);20386 try sema.resolveInferredErrorSetTy(block, dest_ty_src, dest_ty);
19875 try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty);20387 try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty);
19876 for (dest_ty.errorSetNames()) |dest_err_name|20388 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
19877 if (operand_ty.errorSetHasField(dest_err_name))20389 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
19878 break :disjoint false;20390 break :disjoint false;
20391 }
1987920392
19880 break :disjoint true;20393 break :disjoint true;
19881 }) {20394 }) {
...@@ -19895,15 +20408,15 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -19895,15 +20408,15 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
19895 }20408 }
1989620409
19897 if (maybe_operand_val) |val| {20410 if (maybe_operand_val) |val| {
19898 if (!dest_ty.isAnyError()) {20411 if (!dest_ty.isAnyError(mod)) {
19899 const error_name = val.castTag(.@"error").?.data.name;20412 const error_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
19900 if (!dest_ty.errorSetHasField(error_name)) {20413 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) {
19901 const msg = msg: {20414 const msg = msg: {
19902 const msg = try sema.errMsg(20415 const msg = try sema.errMsg(
19903 block,20416 block,
19904 src,20417 src,
19905 "'error.{s}' not a member of error set '{}'",20418 "'error.{}' not a member of error set '{}'",
19906 .{ error_name, dest_ty.fmt(sema.mod) },20419 .{ error_name.fmt(ip), dest_ty.fmt(sema.mod) },
19907 );20420 );
19908 errdefer msg.destroy(sema.gpa);20421 errdefer msg.destroy(sema.gpa);
19909 try sema.addDeclaredHereNote(msg, dest_ty);20422 try sema.addDeclaredHereNote(msg, dest_ty);
...@@ -19913,11 +20426,11 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -19913,11 +20426,11 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
19913 }20426 }
19914 }20427 }
1991520428
19916 return sema.addConstant(dest_ty, val);20429 return sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
19917 }20430 }
1991820431
19919 try sema.requireRuntimeBlock(block, src, operand_src);20432 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)) {
19921 const err_int_inst = try block.addBitCast(Type.err_int, operand);20434 const err_int_inst = try block.addBitCast(Type.err_int, operand);
19922 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);20435 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
19923 try sema.addSafetyCheck(block, ok, .invalid_error_code);20436 try sema.addSafetyCheck(block, ok, .invalid_error_code);
...@@ -19926,6 +20439,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -19926,6 +20439,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
19926}20439}
1992720440
19928fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20441fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20442 const mod = sema.mod;
19929 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;20443 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19930 const src = inst_data.src();20444 const src = inst_data.src();
19931 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20445 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...@@ -19934,13 +20448,12 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19934 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);20448 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
19935 const operand = try sema.resolveInst(extra.rhs);20449 const operand = try sema.resolveInst(extra.rhs);
19936 const operand_ty = sema.typeOf(operand);20450 const operand_ty = sema.typeOf(operand);
19937 const target = sema.mod.getTarget();
1993820451
19939 try sema.checkPtrType(block, dest_ty_src, dest_ty);20452 try sema.checkPtrType(block, dest_ty_src, dest_ty);
19940 try sema.checkPtrOperand(block, operand_src, operand_ty);20453 try sema.checkPtrOperand(block, operand_src, operand_ty);
1994120454
19942 const operand_info = operand_ty.ptrInfo().data;20455 const operand_info = operand_ty.ptrInfo(mod);
19943 const dest_info = dest_ty.ptrInfo().data;20456 const dest_info = dest_ty.ptrInfo(mod);
19944 if (!operand_info.mutable and dest_info.mutable) {20457 if (!operand_info.mutable and dest_info.mutable) {
19945 const msg = msg: {20458 const msg = msg: {
19946 const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{});20459 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...@@ -19972,8 +20485,8 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19972 return sema.failWithOwnedErrorMsg(msg);20485 return sema.failWithOwnedErrorMsg(msg);
19973 }20486 }
1997420487
19975 const dest_is_slice = dest_ty.isSlice();20488 const dest_is_slice = dest_ty.isSlice(mod);
19976 const operand_is_slice = operand_ty.isSlice();20489 const operand_is_slice = operand_ty.isSlice(mod);
19977 if (dest_is_slice and !operand_is_slice) {20490 if (dest_is_slice and !operand_is_slice) {
19978 return sema.fail(block, dest_ty_src, "illegal pointer cast to slice", .{});20491 return sema.fail(block, dest_ty_src, "illegal pointer cast to slice", .{});
19979 }20492 }
...@@ -19982,32 +20495,31 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19982,32 +20495,31 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19982 else20495 else
19983 operand;20496 operand;
1998420497
19985 const dest_elem_ty = dest_ty.elemType2();20498 const dest_elem_ty = dest_ty.elemType2(mod);
19986 try sema.resolveTypeLayout(dest_elem_ty);20499 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);
19990 try sema.resolveTypeLayout(operand_elem_ty);20503 try sema.resolveTypeLayout(operand_elem_ty);
19991 const operand_align = operand_ty.ptrAlignment(target);20504 const operand_align = operand_ty.ptrAlignment(mod);
1999220505
19993 // If the destination is less aligned than the source, preserve the source alignment20506 // If the destination is less aligned than the source, preserve the source alignment
19994 const aligned_dest_ty = if (operand_align <= dest_align) dest_ty else blk: {20507 const aligned_dest_ty = if (operand_align <= dest_align) dest_ty else blk: {
19995 // Unwrap the pointer (or pointer-like optional) type, set alignment, and re-wrap into result20508 // Unwrap the pointer (or pointer-like optional) type, set alignment, and re-wrap into result
19996 if (dest_ty.zigTypeTag() == .Optional) {20509 if (dest_ty.zigTypeTag(mod) == .Optional) {
19997 var buf: Type.Payload.ElemType = undefined;20510 var dest_ptr_info = dest_ty.optionalChild(mod).ptrInfo(mod);
19998 var dest_ptr_info = dest_ty.optionalChild(&buf).ptrInfo().data;
19999 dest_ptr_info.@"align" = operand_align;20511 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);
20001 } else {20513 } else {
20002 var dest_ptr_info = dest_ty.ptrInfo().data;20514 var dest_ptr_info = dest_ty.ptrInfo(mod);
20003 dest_ptr_info.@"align" = operand_align;20515 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);
20005 }20517 }
20006 };20518 };
2000720519
20008 if (dest_is_slice) {20520 if (dest_is_slice) {
20009 const operand_elem_size = operand_elem_ty.abiSize(target);20521 const operand_elem_size = operand_elem_ty.abiSize(mod);
20010 const dest_elem_size = dest_elem_ty.abiSize(target);20522 const dest_elem_size = dest_elem_ty.abiSize(mod);
20011 if (operand_elem_size != dest_elem_size) {20523 if (operand_elem_size != dest_elem_size) {
20012 return sema.fail(block, dest_ty_src, "TODO: implement @ptrCast between slices changing the length", .{});20524 return sema.fail(block, dest_ty_src, "TODO: implement @ptrCast between slices changing the length", .{});
20013 }20525 }
...@@ -20019,10 +20531,10 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20019,10 +20531,10 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20019 errdefer msg.destroy(sema.gpa);20531 errdefer msg.destroy(sema.gpa);
2002020532
20021 try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{20533 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,
20023 });20535 });
20024 try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{20536 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,
20026 });20538 });
2002720539
20028 try sema.errNote(block, src, msg, "consider using '@alignCast'", .{});20540 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...@@ -20032,21 +20544,18 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20032 }20544 }
2003320545
20034 if (try sema.resolveMaybeUndefVal(ptr)) |operand_val| {20546 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)) {
20036 return sema.failWithUseOfUndef(block, operand_src);20548 return sema.failWithUseOfUndef(block, operand_src);
20037 }20549 }
20038 if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) {20550 if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) {
20039 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});20551 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(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));
20043 }20552 }
20044 return sema.addConstant(aligned_dest_ty, operand_val);20553 return sema.addConstant(aligned_dest_ty, try mod.getCoerced(operand_val, aligned_dest_ty));
20045 }20554 }
2004620555
20047 try sema.requireRuntimeBlock(block, src, null);20556 try sema.requireRuntimeBlock(block, src, null);
20048 if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and20557 if (block.wantSafety() and operand_ty.ptrAllowsZero(mod) and !dest_ty.ptrAllowsZero(mod) and
20049 (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn))20558 (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn))
20050 {20559 {
20051 const ptr_int = try block.addUnOp(.ptrtoint, ptr);20560 const ptr_int = try block.addUnOp(.ptrtoint, ptr);
20052 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);20561 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...@@ -20062,6 +20571,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20062}20571}
2006320572
20064fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {20573fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20574 const mod = sema.mod;
20065 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;20575 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20066 const src = LazySrcLoc.nodeOffset(extra.node);20576 const src = LazySrcLoc.nodeOffset(extra.node);
20067 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };20577 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...@@ -20069,12 +20579,12 @@ fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
20069 const operand_ty = sema.typeOf(operand);20579 const operand_ty = sema.typeOf(operand);
20070 try sema.checkPtrOperand(block, operand_src, operand_ty);20580 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);
20073 ptr_info.mutable = true;20583 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
20076 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {20586 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));
20078 }20588 }
2007920589
20080 try sema.requireRuntimeBlock(block, src, null);20590 try sema.requireRuntimeBlock(block, src, null);
...@@ -20082,6 +20592,7 @@ fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -20082,6 +20592,7 @@ fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
20082}20592}
2008320593
20084fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {20594fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20595 const mod = sema.mod;
20085 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;20596 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20086 const src = LazySrcLoc.nodeOffset(extra.node);20597 const src = LazySrcLoc.nodeOffset(extra.node);
20087 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };20598 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...@@ -20089,9 +20600,9 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
20089 const operand_ty = sema.typeOf(operand);20600 const operand_ty = sema.typeOf(operand);
20090 try sema.checkPtrOperand(block, operand_src, operand_ty);20601 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);
20093 ptr_info.@"volatile" = false;20604 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
20096 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {20607 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
20097 return sema.addConstant(dest_ty, operand_val);20608 return sema.addConstant(dest_ty, operand_val);
...@@ -20102,6 +20613,7 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -20102,6 +20613,7 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
20102}20613}
2010320614
20104fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20615fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20616 const mod = sema.mod;
20105 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;20617 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
20106 const src = inst_data.src();20618 const src = inst_data.src();
20107 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20619 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...@@ -20112,9 +20624,12 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20112 const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_scalar_ty);20624 const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_scalar_ty);
20113 const operand_ty = sema.typeOf(operand);20625 const operand_ty = sema.typeOf(operand);
20114 const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src);20626 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;
20116 const dest_ty = if (is_vector)20628 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 })
20118 else20633 else
20119 dest_scalar_ty;20634 dest_scalar_ty;
2012020635
...@@ -20122,22 +20637,21 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -20122,22 +20637,21 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20122 return sema.coerce(block, dest_ty, operand, operand_src);20637 return sema.coerce(block, dest_ty, operand, operand_src);
20123 }20638 }
2012420639
20125 const target = sema.mod.getTarget();20640 const dest_info = dest_scalar_ty.intInfo(mod);
20126 const dest_info = dest_scalar_ty.intInfo(target);
2012720641
20128 if (try sema.typeHasOnePossibleValue(dest_ty)) |val| {20642 if (try sema.typeHasOnePossibleValue(dest_ty)) |val| {
20129 return sema.addConstant(dest_ty, val);20643 return sema.addConstant(dest_ty, val);
20130 }20644 }
2013120645
20132 if (operand_scalar_ty.zigTypeTag() != .ComptimeInt) {20646 if (operand_scalar_ty.zigTypeTag(mod) != .ComptimeInt) {
20133 const operand_info = operand_ty.intInfo(target);20647 const operand_info = operand_ty.intInfo(mod);
20134 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {20648 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
20135 return sema.addConstant(operand_ty, val);20649 return sema.addConstant(operand_ty, val);
20136 }20650 }
2013720651
20138 if (operand_info.signedness != dest_info.signedness) {20652 if (operand_info.signedness != dest_info.signedness) {
20139 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{20653 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),
20141 });20655 });
20142 }20656 }
20143 if (operand_info.bits < dest_info.bits) {20657 if (operand_info.bits < dest_info.bits) {
...@@ -20146,7 +20660,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -20146,7 +20660,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20146 block,20660 block,
20147 src,20661 src,
20148 "destination type '{}' has more bits than source type '{}'",20662 "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) },
20150 );20664 );
20151 errdefer msg.destroy(sema.gpa);20665 errdefer msg.destroy(sema.gpa);
20152 try sema.errNote(block, dest_ty_src, msg, "destination type has {d} bits", .{20666 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...@@ -20162,23 +20676,22 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20162 }20676 }
2016320677
20164 if (try sema.resolveMaybeUndefValIntable(operand)) |val| {20678 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);
20166 if (!is_vector) {20680 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),
20168 dest_ty,20683 dest_ty,
20169 try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, sema.mod),20684 ));
20170 );
20171 }20685 }
20172 var elem_buf: Value.ElemValueBuffer = undefined;20686 const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod));
20173 const elems = try sema.arena.alloc(Value, operand_ty.vectorLen());
20174 for (elems, 0..) |*elem, i| {20687 for (elems, 0..) |*elem, i| {
20175 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);20688 const elem_val = try val.elemValue(mod, i);
20176 elem.* = try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, sema.mod);20689 elem.* = try (try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, mod)).intern(dest_scalar_ty, mod);
20177 }20690 }
20178 return sema.addConstant(20691 return sema.addConstant(dest_ty, (try mod.intern(.{ .aggregate = .{
20179 dest_ty,20692 .ty = dest_ty.toIntern(),
20180 try Value.Tag.aggregate.create(sema.arena, elems),20693 .storage = .{ .elems = elems },
20181 );20694 } })).toValue());
20182 }20695 }
2018320696
20184 try sema.requireRuntimeBlock(block, src, operand_src);20697 try sema.requireRuntimeBlock(block, src, operand_src);
...@@ -20186,6 +20699,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -20186,6 +20699,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20186}20699}
2018720700
20188fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20701fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20702 const mod = sema.mod;
20189 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;20703 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
20190 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;20704 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
20191 const align_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20705 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...@@ -20196,43 +20710,38 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2019620710
20197 try sema.checkPtrOperand(block, ptr_src, ptr_ty);20711 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);
20200 ptr_info.@"align" = dest_align;20714 ptr_info.@"align" = dest_align;
20201 var dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);20715 var dest_ty = try Type.ptr(sema.arena, mod, ptr_info);
20202 if (ptr_ty.zigTypeTag() == .Optional) {20716 if (ptr_ty.zigTypeTag(mod) == .Optional) {
20203 dest_ty = try Type.Tag.optional.create(sema.arena, dest_ty);20717 dest_ty = try mod.optionalType(dest_ty.toIntern());
20204 }20718 }
2020520719
20206 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| {20720 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| {
20208 if (addr % dest_align != 0) {20722 if (addr % dest_align != 0) {
20209 return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align });20723 return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align });
20210 }20724 }
20211 }20725 }
20212 return sema.addConstant(dest_ty, val);20726 return sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
20213 }20727 }
2021420728
20215 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);20729 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
20216 if (block.wantSafety() and dest_align > 1 and20730 if (block.wantSafety() and dest_align > 1 and
20217 try sema.typeHasRuntimeBits(ptr_info.pointee_type))20731 try sema.typeHasRuntimeBits(ptr_info.pointee_type))
20218 {20732 {
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 };
20224 const align_minus_1 = try sema.addConstant(20733 const align_minus_1 = try sema.addConstant(
20225 Type.usize,20734 Type.usize,
20226 Value.initPayload(&val_payload.base),20735 try mod.intValue(Type.usize, dest_align - 1),
20227 );20736 );
20228 const actual_ptr = if (ptr_ty.isSlice())20737 const actual_ptr = if (ptr_ty.isSlice(mod))
20229 try sema.analyzeSlicePtr(block, ptr_src, ptr, ptr_ty)20738 try sema.analyzeSlicePtr(block, ptr_src, ptr, ptr_ty)
20230 else20739 else
20231 ptr;20740 ptr;
20232 const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);20741 const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);
20233 const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);20742 const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);
20234 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);20743 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: {
20236 const len = try sema.analyzeSliceLen(block, ptr_src, ptr);20745 const len = try sema.analyzeSliceLen(block, ptr_src, ptr);
20237 const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);20746 const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);
20238 break :ok try block.addBinOp(.bit_or, len_zero, is_aligned);20747 break :ok try block.addBinOp(.bit_or, len_zero, is_aligned);
...@@ -20247,51 +20756,52 @@ fn zirBitCount(...@@ -20247,51 +20756,52 @@ fn zirBitCount(
20247 block: *Block,20756 block: *Block,
20248 inst: Zir.Inst.Index,20757 inst: Zir.Inst.Index,
20249 air_tag: Air.Inst.Tag,20758 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,
20251) CompileError!Air.Inst.Ref {20760) CompileError!Air.Inst.Ref {
20761 const mod = sema.mod;
20252 const inst_data = sema.code.instructions.items(.data)[inst].un_node;20762 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
20253 const src = inst_data.src();20763 const src = inst_data.src();
20254 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20764 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
20255 const operand = try sema.resolveInst(inst_data.operand);20765 const operand = try sema.resolveInst(inst_data.operand);
20256 const operand_ty = sema.typeOf(operand);20766 const operand_ty = sema.typeOf(operand);
20257 _ = try sema.checkIntOrVector(block, operand, operand_src);20767 _ = try sema.checkIntOrVector(block, operand, operand_src);
20258 const target = sema.mod.getTarget();20768 const bits = operand_ty.intInfo(mod).bits;
20259 const bits = operand_ty.intInfo(target).bits;
2026020769
20261 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {20770 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
20262 return sema.addConstant(operand_ty, val);20771 return sema.addConstant(operand_ty, val);
20263 }20772 }
2026420773
20265 const result_scalar_ty = try Type.smallestUnsignedInt(sema.arena, bits);20774 const result_scalar_ty = try mod.smallestUnsignedInt(bits);
20266 switch (operand_ty.zigTypeTag()) {20775 switch (operand_ty.zigTypeTag(mod)) {
20267 .Vector => {20776 .Vector => {
20268 const vec_len = operand_ty.vectorLen();20777 const vec_len = operand_ty.vectorLen(mod);
20269 const result_ty = try Type.vector(sema.arena, vec_len, result_scalar_ty);20778 const result_ty = try mod.vectorType(.{
20779 .len = vec_len,
20780 .child = result_scalar_ty.toIntern(),
20781 });
20270 if (try sema.resolveMaybeUndefVal(operand)) |val| {20782 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;20785 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
20274 const elems = try sema.arena.alloc(Value, vec_len);20786 const scalar_ty = operand_ty.scalarType(mod);
20275 const scalar_ty = operand_ty.scalarType();
20276 for (elems, 0..) |*elem, i| {20787 for (elems, 0..) |*elem, i| {
20277 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);20788 const elem_val = try val.elemValue(mod, i);
20278 const count = comptimeOp(elem_val, scalar_ty, target);20789 const count = comptimeOp(elem_val, scalar_ty, mod);
20279 elem.* = try Value.Tag.int_u64.create(sema.arena, count);20790 elem.* = (try mod.intValue(result_scalar_ty, count)).toIntern();
20280 }20791 }
20281 return sema.addConstant(20792 return sema.addConstant(result_ty, (try mod.intern(.{ .aggregate = .{
20282 result_ty,20793 .ty = result_ty.toIntern(),
20283 try Value.Tag.aggregate.create(sema.arena, elems),20794 .storage = .{ .elems = elems },
20284 );20795 } })).toValue());
20285 } else {20796 } else {
20286 try sema.requireRuntimeBlock(block, src, operand_src);20797 try sema.requireRuntimeBlock(block, src, operand_src);
20287 return block.addTyOp(air_tag, result_ty, operand);20798 return block.addTyOp(air_tag, result_ty, operand);
20288 }20799 }
20289 },20800 },
20290 .Int => {20801 .Int => {
20291 if (try sema.resolveMaybeUndefVal(operand)) |val| {20802 if (try sema.resolveMaybeUndefLazyVal(operand)) |val| {
20292 if (val.isUndef()) return sema.addConstUndef(result_scalar_ty);20803 if (val.isUndef(mod)) return sema.addConstUndef(result_scalar_ty);
20293 try sema.resolveLazyValue(val);20804 return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, mod));
20294 return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, target));
20295 } else {20805 } else {
20296 try sema.requireRuntimeBlock(block, src, operand_src);20806 try sema.requireRuntimeBlock(block, src, operand_src);
20297 return block.addTyOp(air_tag, result_scalar_ty, operand);20807 return block.addTyOp(air_tag, result_scalar_ty, operand);
...@@ -20302,20 +20812,20 @@ fn zirBitCount(...@@ -20302,20 +20812,20 @@ fn zirBitCount(
20302}20812}
2030320813
20304fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20814fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20815 const mod = sema.mod;
20305 const inst_data = sema.code.instructions.items(.data)[inst].un_node;20816 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
20306 const src = inst_data.src();20817 const src = inst_data.src();
20307 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20818 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
20308 const operand = try sema.resolveInst(inst_data.operand);20819 const operand = try sema.resolveInst(inst_data.operand);
20309 const operand_ty = sema.typeOf(operand);20820 const operand_ty = sema.typeOf(operand);
20310 const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src);20821 const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src);
20311 const target = sema.mod.getTarget();20822 const bits = scalar_ty.intInfo(mod).bits;
20312 const bits = scalar_ty.intInfo(target).bits;
20313 if (bits % 8 != 0) {20823 if (bits % 8 != 0) {
20314 return sema.fail(20824 return sema.fail(
20315 block,20825 block,
20316 operand_src,20826 operand_src,
20317 "@byteSwap requires the number of bits to be evenly divisible by 8, but {} has {} bits",20827 "@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 },
20319 );20829 );
20320 }20830 }
2032120831
...@@ -20323,11 +20833,11 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -20323,11 +20833,11 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20323 return sema.addConstant(operand_ty, val);20833 return sema.addConstant(operand_ty, val);
20324 }20834 }
2032520835
20326 switch (operand_ty.zigTypeTag()) {20836 switch (operand_ty.zigTypeTag(mod)) {
20327 .Int => {20837 .Int => {
20328 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {20838 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20329 if (val.isUndef()) return sema.addConstUndef(operand_ty);20839 if (val.isUndef(mod)) return sema.addConstUndef(operand_ty);
20330 const result_val = try val.byteSwap(operand_ty, target, sema.arena);20840 const result_val = try val.byteSwap(operand_ty, mod, sema.arena);
20331 return sema.addConstant(operand_ty, result_val);20841 return sema.addConstant(operand_ty, result_val);
20332 } else operand_src;20842 } else operand_src;
2033320843
...@@ -20336,20 +20846,19 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -20336,20 +20846,19 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20336 },20846 },
20337 .Vector => {20847 .Vector => {
20338 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {20848 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20339 if (val.isUndef())20849 if (val.isUndef(mod))
20340 return sema.addConstUndef(operand_ty);20850 return sema.addConstUndef(operand_ty);
2034120851
20342 const vec_len = operand_ty.vectorLen();20852 const vec_len = operand_ty.vectorLen(mod);
20343 var elem_buf: Value.ElemValueBuffer = undefined;20853 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
20344 const elems = try sema.arena.alloc(Value, vec_len);
20345 for (elems, 0..) |*elem, i| {20854 for (elems, 0..) |*elem, i| {
20346 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);20855 const elem_val = try val.elemValue(mod, i);
20347 elem.* = try elem_val.byteSwap(operand_ty, target, sema.arena);20856 elem.* = try (try elem_val.byteSwap(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod);
20348 }20857 }
20349 return sema.addConstant(20858 return sema.addConstant(operand_ty, (try mod.intern(.{ .aggregate = .{
20350 operand_ty,20859 .ty = operand_ty.toIntern(),
20351 try Value.Tag.aggregate.create(sema.arena, elems),20860 .storage = .{ .elems = elems },
20352 );20861 } })).toValue());
20353 } else operand_src;20862 } else operand_src;
2035420863
20355 try sema.requireRuntimeBlock(block, src, runtime_src);20864 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -20371,12 +20880,12 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -20371,12 +20880,12 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
20371 return sema.addConstant(operand_ty, val);20880 return sema.addConstant(operand_ty, val);
20372 }20881 }
2037320882
20374 const target = sema.mod.getTarget();20883 const mod = sema.mod;
20375 switch (operand_ty.zigTypeTag()) {20884 switch (operand_ty.zigTypeTag(mod)) {
20376 .Int => {20885 .Int => {
20377 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {20886 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20378 if (val.isUndef()) return sema.addConstUndef(operand_ty);20887 if (val.isUndef(mod)) return sema.addConstUndef(operand_ty);
20379 const result_val = try val.bitReverse(operand_ty, target, sema.arena);20888 const result_val = try val.bitReverse(operand_ty, mod, sema.arena);
20380 return sema.addConstant(operand_ty, result_val);20889 return sema.addConstant(operand_ty, result_val);
20381 } else operand_src;20890 } else operand_src;
2038220891
...@@ -20385,20 +20894,19 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -20385,20 +20894,19 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
20385 },20894 },
20386 .Vector => {20895 .Vector => {
20387 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {20896 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20388 if (val.isUndef())20897 if (val.isUndef(mod))
20389 return sema.addConstUndef(operand_ty);20898 return sema.addConstUndef(operand_ty);
2039020899
20391 const vec_len = operand_ty.vectorLen();20900 const vec_len = operand_ty.vectorLen(mod);
20392 var elem_buf: Value.ElemValueBuffer = undefined;20901 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
20393 const elems = try sema.arena.alloc(Value, vec_len);
20394 for (elems, 0..) |*elem, i| {20902 for (elems, 0..) |*elem, i| {
20395 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);20903 const elem_val = try val.elemValue(mod, i);
20396 elem.* = try elem_val.bitReverse(scalar_ty, target, sema.arena);20904 elem.* = try (try elem_val.bitReverse(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod);
20397 }20905 }
20398 return sema.addConstant(20906 return sema.addConstant(operand_ty, (try mod.intern(.{ .aggregate = .{
20399 operand_ty,20907 .ty = operand_ty.toIntern(),
20400 try Value.Tag.aggregate.create(sema.arena, elems),20908 .storage = .{ .elems = elems },
20401 );20909 } })).toValue());
20402 } else operand_src;20910 } else operand_src;
2040320911
20404 try sema.requireRuntimeBlock(block, src, runtime_src);20912 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -20428,15 +20936,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -20428,15 +20936,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
20428 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;20936 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2042920937
20430 const ty = try sema.resolveType(block, lhs_src, extra.lhs);20938 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");20939 const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, "name of field must be comptime-known");
20432 const target = sema.mod.getTarget();
2043320940
20941 const mod = sema.mod;
20434 try sema.resolveTypeLayout(ty);20942 try sema.resolveTypeLayout(ty);
20435 switch (ty.zigTypeTag()) {20943 switch (ty.zigTypeTag(mod)) {
20436 .Struct => {},20944 .Struct => {},
20437 else => {20945 else => {
20438 const msg = msg: {20946 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)});
20440 errdefer msg.destroy(sema.gpa);20948 errdefer msg.destroy(sema.gpa);
20441 try sema.addDeclaredHereNote(msg, ty);20949 try sema.addDeclaredHereNote(msg, ty);
20442 break :msg msg;20950 break :msg msg;
...@@ -20445,45 +20953,47 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -20445,45 +20953,47 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
20445 },20953 },
20446 }20954 }
2044720955
20448 const field_index = if (ty.isTuple()) blk: {20956 const field_index = if (ty.isTuple(mod)) blk: {
20449 if (mem.eql(u8, field_name, "len")) {20957 if (mod.intern_pool.stringEqlSlice(field_name, "len")) {
20450 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});20958 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
20451 }20959 }
20452 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);20960 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
20453 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);20961 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
2045420962
20455 if (ty.structFieldIsComptime(field_index)) {20963 if (ty.structFieldIsComptime(field_index, mod)) {
20456 return sema.fail(block, src, "no offset available for comptime field", .{});20964 return sema.fail(block, src, "no offset available for comptime field", .{});
20457 }20965 }
2045820966
20459 switch (ty.containerLayout()) {20967 switch (ty.containerLayout(mod)) {
20460 .Packed => {20968 .Packed => {
20461 var bit_sum: u64 = 0;20969 var bit_sum: u64 = 0;
20462 const fields = ty.structFields();20970 const fields = ty.structFields(mod);
20463 for (fields.values(), 0..) |field, i| {20971 for (fields.values(), 0..) |field, i| {
20464 if (i == field_index) {20972 if (i == field_index) {
20465 return bit_sum;20973 return bit_sum;
20466 }20974 }
20467 bit_sum += field.ty.bitSize(target);20975 bit_sum += field.ty.bitSize(mod);
20468 } else unreachable;20976 } else unreachable;
20469 },20977 },
20470 else => return ty.structFieldOffset(field_index, target) * 8,20978 else => return ty.structFieldOffset(field_index, mod) * 8,
20471 }20979 }
20472}20980}
2047320981
20474fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {20982fn 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)) {
20476 .Struct, .Enum, .Union, .Opaque => return,20985 .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)}),
20478 }20987 }
20479}20988}
2048020989
20481/// Returns `true` if the type was a comptime_int.20990/// Returns `true` if the type was a comptime_int.
20482fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {20991fn 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)) {
20484 .ComptimeInt => return true,20994 .ComptimeInt => return true,
20485 .Int => return false,20995 .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)}),
20487 }20997 }
20488}20998}
2048920999
...@@ -20493,8 +21003,9 @@ fn checkInvalidPtrArithmetic(...@@ -20493,8 +21003,9 @@ fn checkInvalidPtrArithmetic(
20493 src: LazySrcLoc,21003 src: LazySrcLoc,
20494 ty: Type,21004 ty: Type,
20495) CompileError!void {21005) CompileError!void {
20496 switch (try ty.zigTypeTagOrPoison()) {21006 const mod = sema.mod;
20497 .Pointer => switch (ty.ptrSize()) {21007 switch (try ty.zigTypeTagOrPoison(mod)) {
21008 .Pointer => switch (ty.ptrSize(mod)) {
20498 .One, .Slice => return,21009 .One, .Slice => return,
20499 .Many, .C => return sema.fail(21010 .Many, .C => return sema.fail(
20500 block,21011 block,
...@@ -20532,7 +21043,8 @@ fn checkPtrOperand(...@@ -20532,7 +21043,8 @@ fn checkPtrOperand(
20532 ty_src: LazySrcLoc,21043 ty_src: LazySrcLoc,
20533 ty: Type,21044 ty: Type,
20534) CompileError!void {21045) CompileError!void {
20535 switch (ty.zigTypeTag()) {21046 const mod = sema.mod;
21047 switch (ty.zigTypeTag(mod)) {
20536 .Pointer => return,21048 .Pointer => return,
20537 .Fn => {21049 .Fn => {
20538 const msg = msg: {21050 const msg = msg: {
...@@ -20540,7 +21052,7 @@ fn checkPtrOperand(...@@ -20540,7 +21052,7 @@ fn checkPtrOperand(
20540 block,21052 block,
20541 ty_src,21053 ty_src,
20542 "expected pointer, found '{}'",21054 "expected pointer, found '{}'",
20543 .{ty.fmt(sema.mod)},21055 .{ty.fmt(mod)},
20544 );21056 );
20545 errdefer msg.destroy(sema.gpa);21057 errdefer msg.destroy(sema.gpa);
2054621058
...@@ -20550,10 +21062,10 @@ fn checkPtrOperand(...@@ -20550,10 +21062,10 @@ fn checkPtrOperand(
20550 };21062 };
20551 return sema.failWithOwnedErrorMsg(msg);21063 return sema.failWithOwnedErrorMsg(msg);
20552 },21064 },
20553 .Optional => if (ty.isPtrLikeOptional()) return,21065 .Optional => if (ty.isPtrLikeOptional(mod)) return,
20554 else => {},21066 else => {},
20555 }21067 }
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)});
20557}21069}
2055821070
20559fn checkPtrType(21071fn checkPtrType(
...@@ -20562,7 +21074,8 @@ fn checkPtrType(...@@ -20562,7 +21074,8 @@ fn checkPtrType(
20562 ty_src: LazySrcLoc,21074 ty_src: LazySrcLoc,
20563 ty: Type,21075 ty: Type,
20564) CompileError!void {21076) CompileError!void {
20565 switch (ty.zigTypeTag()) {21077 const mod = sema.mod;
21078 switch (ty.zigTypeTag(mod)) {
20566 .Pointer => return,21079 .Pointer => return,
20567 .Fn => {21080 .Fn => {
20568 const msg = msg: {21081 const msg = msg: {
...@@ -20570,7 +21083,7 @@ fn checkPtrType(...@@ -20570,7 +21083,7 @@ fn checkPtrType(
20570 block,21083 block,
20571 ty_src,21084 ty_src,
20572 "expected pointer type, found '{}'",21085 "expected pointer type, found '{}'",
20573 .{ty.fmt(sema.mod)},21086 .{ty.fmt(mod)},
20574 );21087 );
20575 errdefer msg.destroy(sema.gpa);21088 errdefer msg.destroy(sema.gpa);
2057621089
...@@ -20580,10 +21093,10 @@ fn checkPtrType(...@@ -20580,10 +21093,10 @@ fn checkPtrType(
20580 };21093 };
20581 return sema.failWithOwnedErrorMsg(msg);21094 return sema.failWithOwnedErrorMsg(msg);
20582 },21095 },
20583 .Optional => if (ty.isPtrLikeOptional()) return,21096 .Optional => if (ty.isPtrLikeOptional(mod)) return,
20584 else => {},21097 else => {},
20585 }21098 }
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)});
20587}21100}
2058821101
20589fn checkVectorElemType(21102fn checkVectorElemType(
...@@ -20592,11 +21105,12 @@ fn checkVectorElemType(...@@ -20592,11 +21105,12 @@ fn checkVectorElemType(
20592 ty_src: LazySrcLoc,21105 ty_src: LazySrcLoc,
20593 ty: Type,21106 ty: Type,
20594) CompileError!void {21107) CompileError!void {
20595 switch (ty.zigTypeTag()) {21108 const mod = sema.mod;
21109 switch (ty.zigTypeTag(mod)) {
20596 .Int, .Float, .Bool => return,21110 .Int, .Float, .Bool => return,
20597 else => if (ty.isPtrAtRuntime()) return,21111 else => if (ty.isPtrAtRuntime(mod)) return,
20598 }21112 }
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)});
20600}21114}
2060121115
20602fn checkFloatType(21116fn checkFloatType(
...@@ -20605,9 +21119,10 @@ fn checkFloatType(...@@ -20605,9 +21119,10 @@ fn checkFloatType(
20605 ty_src: LazySrcLoc,21119 ty_src: LazySrcLoc,
20606 ty: Type,21120 ty: Type,
20607) CompileError!void {21121) CompileError!void {
20608 switch (ty.zigTypeTag()) {21122 const mod = sema.mod;
21123 switch (ty.zigTypeTag(mod)) {
20609 .ComptimeInt, .ComptimeFloat, .Float => {},21124 .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)}),
20611 }21126 }
20612}21127}
2061321128
...@@ -20617,13 +21132,14 @@ fn checkNumericType(...@@ -20617,13 +21132,14 @@ fn checkNumericType(
20617 ty_src: LazySrcLoc,21132 ty_src: LazySrcLoc,
20618 ty: Type,21133 ty: Type,
20619) CompileError!void {21134) CompileError!void {
20620 switch (ty.zigTypeTag()) {21135 const mod = sema.mod;
21136 switch (ty.zigTypeTag(mod)) {
20621 .ComptimeFloat, .Float, .ComptimeInt, .Int => {},21137 .ComptimeFloat, .Float, .ComptimeInt, .Int => {},
20622 .Vector => switch (ty.childType().zigTypeTag()) {21138 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
20623 .ComptimeFloat, .Float, .ComptimeInt, .Int => {},21139 .ComptimeFloat, .Float, .ComptimeInt, .Int => {},
20624 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),21140 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),
20625 },21141 },
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)}),
20627 }21143 }
20628}21144}
2062921145
...@@ -20637,9 +21153,10 @@ fn checkAtomicPtrOperand(...@@ -20637,9 +21153,10 @@ fn checkAtomicPtrOperand(
20637 ptr_src: LazySrcLoc,21153 ptr_src: LazySrcLoc,
20638 ptr_const: bool,21154 ptr_const: bool,
20639) CompileError!Air.Inst.Ref {21155) CompileError!Air.Inst.Ref {
20640 const target = sema.mod.getTarget();21156 const mod = sema.mod;
20641 var diag: target_util.AtomicPtrAlignmentDiagnostics = .{};21157 var diag: Module.AtomicPtrAlignmentDiagnostics = .{};
20642 const alignment = target_util.atomicPtrAlignment(target, elem_ty, &diag) catch |err| switch (err) {21158 const alignment = mod.atomicPtrAlignment(elem_ty, &diag) catch |err| switch (err) {
21159 error.OutOfMemory => return error.OutOfMemory,
20643 error.FloatTooBig => return sema.fail(21160 error.FloatTooBig => return sema.fail(
20644 block,21161 block,
20645 elem_ty_src,21162 elem_ty_src,
...@@ -20656,7 +21173,7 @@ fn checkAtomicPtrOperand(...@@ -20656,7 +21173,7 @@ fn checkAtomicPtrOperand(
20656 block,21173 block,
20657 elem_ty_src,21174 elem_ty_src,
20658 "expected bool, integer, float, enum, or pointer type; found '{}'",21175 "expected bool, integer, float, enum, or pointer type; found '{}'",
20659 .{elem_ty.fmt(sema.mod)},21176 .{elem_ty.fmt(mod)},
20660 ),21177 ),
20661 };21178 };
2066221179
...@@ -20668,10 +21185,10 @@ fn checkAtomicPtrOperand(...@@ -20668,10 +21185,10 @@ fn checkAtomicPtrOperand(
20668 };21185 };
2066921186
20670 const ptr_ty = sema.typeOf(ptr);21187 const ptr_ty = sema.typeOf(ptr);
20671 const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison()) {21188 const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison(mod)) {
20672 .Pointer => ptr_ty.ptrInfo().data,21189 .Pointer => ptr_ty.ptrInfo(mod),
20673 else => {21190 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);
20675 _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);21192 _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
20676 unreachable;21193 unreachable;
20677 },21194 },
...@@ -20681,7 +21198,7 @@ fn checkAtomicPtrOperand(...@@ -20681,7 +21198,7 @@ fn checkAtomicPtrOperand(
20681 wanted_ptr_data.@"allowzero" = ptr_data.@"allowzero";21198 wanted_ptr_data.@"allowzero" = ptr_data.@"allowzero";
20682 wanted_ptr_data.@"volatile" = ptr_data.@"volatile";21199 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);
20685 const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);21202 const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
2068621203
20687 return casted_ptr;21204 return casted_ptr;
...@@ -20695,7 +21212,7 @@ fn checkPtrIsNotComptimeMutable(...@@ -20695,7 +21212,7 @@ fn checkPtrIsNotComptimeMutable(
20695 operand_src: LazySrcLoc,21212 operand_src: LazySrcLoc,
20696) CompileError!void {21213) CompileError!void {
20697 _ = operand_src;21214 _ = operand_src;
20698 if (ptr_val.isComptimeMutablePtr()) {21215 if (ptr_val.isComptimeMutablePtr(sema.mod)) {
20699 return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{});21216 return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{});
20700 }21217 }
20701}21218}
...@@ -20704,7 +21221,7 @@ fn checkComptimeVarStore(...@@ -20704,7 +21221,7 @@ fn checkComptimeVarStore(
20704 sema: *Sema,21221 sema: *Sema,
20705 block: *Block,21222 block: *Block,
20706 src: LazySrcLoc,21223 src: LazySrcLoc,
20707 decl_ref_mut: Value.Payload.DeclRefMut.Data,21224 decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
20708) CompileError!void {21225) CompileError!void {
20709 if (@enumToInt(decl_ref_mut.runtime_index) < @enumToInt(block.runtime_index)) {21226 if (@enumToInt(decl_ref_mut.runtime_index) < @enumToInt(block.runtime_index)) {
20710 if (block.runtime_cond) |cond_src| {21227 if (block.runtime_cond) |cond_src| {
...@@ -20735,20 +21252,21 @@ fn checkIntOrVector(...@@ -20735,20 +21252,21 @@ fn checkIntOrVector(
20735 operand: Air.Inst.Ref,21252 operand: Air.Inst.Ref,
20736 operand_src: LazySrcLoc,21253 operand_src: LazySrcLoc,
20737) CompileError!Type {21254) CompileError!Type {
21255 const mod = sema.mod;
20738 const operand_ty = sema.typeOf(operand);21256 const operand_ty = sema.typeOf(operand);
20739 switch (try operand_ty.zigTypeTagOrPoison()) {21257 switch (try operand_ty.zigTypeTagOrPoison(mod)) {
20740 .Int => return operand_ty,21258 .Int => return operand_ty,
20741 .Vector => {21259 .Vector => {
20742 const elem_ty = operand_ty.childType();21260 const elem_ty = operand_ty.childType(mod);
20743 switch (try elem_ty.zigTypeTagOrPoison()) {21261 switch (try elem_ty.zigTypeTagOrPoison(mod)) {
20744 .Int => return elem_ty,21262 .Int => return elem_ty,
20745 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{21263 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),
20747 }),21265 }),
20748 }21266 }
20749 },21267 },
20750 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{21268 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{
20751 operand_ty.fmt(sema.mod),21269 operand_ty.fmt(mod),
20752 }),21270 }),
20753 }21271 }
20754}21272}
...@@ -20759,27 +21277,29 @@ fn checkIntOrVectorAllowComptime(...@@ -20759,27 +21277,29 @@ fn checkIntOrVectorAllowComptime(
20759 operand_ty: Type,21277 operand_ty: Type,
20760 operand_src: LazySrcLoc,21278 operand_src: LazySrcLoc,
20761) CompileError!Type {21279) CompileError!Type {
20762 switch (try operand_ty.zigTypeTagOrPoison()) {21280 const mod = sema.mod;
21281 switch (try operand_ty.zigTypeTagOrPoison(mod)) {
20763 .Int, .ComptimeInt => return operand_ty,21282 .Int, .ComptimeInt => return operand_ty,
20764 .Vector => {21283 .Vector => {
20765 const elem_ty = operand_ty.childType();21284 const elem_ty = operand_ty.childType(mod);
20766 switch (try elem_ty.zigTypeTagOrPoison()) {21285 switch (try elem_ty.zigTypeTagOrPoison(mod)) {
20767 .Int, .ComptimeInt => return elem_ty,21286 .Int, .ComptimeInt => return elem_ty,
20768 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{21287 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),
20770 }),21289 }),
20771 }21290 }
20772 },21291 },
20773 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{21292 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{
20774 operand_ty.fmt(sema.mod),21293 operand_ty.fmt(mod),
20775 }),21294 }),
20776 }21295 }
20777}21296}
2077821297
20779fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {21298fn 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)) {
20781 .ErrorSet => return,21301 .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)}),
20783 }21303 }
20784}21304}
2078521305
...@@ -20805,11 +21325,12 @@ fn checkSimdBinOp(...@@ -20805,11 +21325,12 @@ fn checkSimdBinOp(
20805 lhs_src: LazySrcLoc,21325 lhs_src: LazySrcLoc,
20806 rhs_src: LazySrcLoc,21326 rhs_src: LazySrcLoc,
20807) CompileError!SimdBinOp {21327) CompileError!SimdBinOp {
21328 const mod = sema.mod;
20808 const lhs_ty = sema.typeOf(uncasted_lhs);21329 const lhs_ty = sema.typeOf(uncasted_lhs);
20809 const rhs_ty = sema.typeOf(uncasted_rhs);21330 const rhs_ty = sema.typeOf(uncasted_rhs);
2081021331
20811 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);21332 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;
20813 const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{21334 const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{
20814 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },21335 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
20815 });21336 });
...@@ -20823,7 +21344,7 @@ fn checkSimdBinOp(...@@ -20823,7 +21344,7 @@ fn checkSimdBinOp(
20823 .lhs_val = try sema.resolveMaybeUndefVal(lhs),21344 .lhs_val = try sema.resolveMaybeUndefVal(lhs),
20824 .rhs_val = try sema.resolveMaybeUndefVal(rhs),21345 .rhs_val = try sema.resolveMaybeUndefVal(rhs),
20825 .result_ty = result_ty,21346 .result_ty = result_ty,
20826 .scalar_ty = result_ty.scalarType(),21347 .scalar_ty = result_ty.scalarType(mod),
20827 };21348 };
20828}21349}
2082921350
...@@ -20836,8 +21357,9 @@ fn checkVectorizableBinaryOperands(...@@ -20836,8 +21357,9 @@ fn checkVectorizableBinaryOperands(
20836 lhs_src: LazySrcLoc,21357 lhs_src: LazySrcLoc,
20837 rhs_src: LazySrcLoc,21358 rhs_src: LazySrcLoc,
20838) CompileError!void {21359) CompileError!void {
20839 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();21360 const mod = sema.mod;
20840 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();21361 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
21362 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
20841 if (lhs_zig_ty_tag != .Vector and rhs_zig_ty_tag != .Vector) return;21363 if (lhs_zig_ty_tag != .Vector and rhs_zig_ty_tag != .Vector) return;
2084221364
20843 const lhs_is_vector = switch (lhs_zig_ty_tag) {21365 const lhs_is_vector = switch (lhs_zig_ty_tag) {
...@@ -20850,8 +21372,8 @@ fn checkVectorizableBinaryOperands(...@@ -20850,8 +21372,8 @@ fn checkVectorizableBinaryOperands(
20850 };21372 };
2085121373
20852 if (lhs_is_vector and rhs_is_vector) {21374 if (lhs_is_vector and rhs_is_vector) {
20853 const lhs_len = lhs_ty.arrayLen();21375 const lhs_len = lhs_ty.arrayLen(mod);
20854 const rhs_len = rhs_ty.arrayLen();21376 const rhs_len = rhs_ty.arrayLen(mod);
20855 if (lhs_len != rhs_len) {21377 if (lhs_len != rhs_len) {
20856 const msg = msg: {21378 const msg = msg: {
20857 const msg = try sema.errMsg(block, src, "vector length mismatch", .{});21379 const msg = try sema.errMsg(block, src, "vector length mismatch", .{});
...@@ -20865,7 +21387,7 @@ fn checkVectorizableBinaryOperands(...@@ -20865,7 +21387,7 @@ fn checkVectorizableBinaryOperands(
20865 } else {21387 } else {
20866 const msg = msg: {21388 const msg = msg: {
20867 const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: '{}' and '{}'", .{21389 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),
20869 });21391 });
20870 errdefer msg.destroy(sema.gpa);21392 errdefer msg.destroy(sema.gpa);
20871 if (lhs_is_vector) {21393 if (lhs_is_vector) {
...@@ -20883,7 +21405,8 @@ fn checkVectorizableBinaryOperands(...@@ -20883,7 +21405,8 @@ fn checkVectorizableBinaryOperands(
2088321405
20884fn maybeOptionsSrc(sema: *Sema, block: *Block, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {21406fn maybeOptionsSrc(sema: *Sema, block: *Block, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
20885 if (base_src == .unneeded) return .unneeded;21407 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);
20887}21410}
2088821411
20889fn resolveExportOptions(21412fn resolveExportOptions(
...@@ -20891,7 +21414,10 @@ fn resolveExportOptions(...@@ -20891,7 +21414,10 @@ fn resolveExportOptions(
20891 block: *Block,21414 block: *Block,
20892 src: LazySrcLoc,21415 src: LazySrcLoc,
20893 zir_ref: Zir.Inst.Ref,21416 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;
20895 const export_options_ty = try sema.getBuiltinType("ExportOptions");21421 const export_options_ty = try sema.getBuiltinType("ExportOptions");
20896 const air_ref = try sema.resolveInst(zir_ref);21422 const air_ref = try sema.resolveInst(zir_ref);
20897 const options = try sema.coerce(block, export_options_ty, air_ref, src);21423 const options = try sema.coerce(block, export_options_ty, air_ref, src);
...@@ -20901,26 +21427,26 @@ fn resolveExportOptions(...@@ -20901,26 +21427,26 @@ fn resolveExportOptions(
20901 const section_src = sema.maybeOptionsSrc(block, src, "section");21427 const section_src = sema.maybeOptionsSrc(block, src, "section");
20902 const visibility_src = sema.maybeOptionsSrc(block, src, "visibility");21428 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);
20905 const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime-known");21431 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);21432 const name_ty = Type.slice_const_u8;
20907 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, sema.mod);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);
20910 const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_operand, "linkage of exported value must be comptime-known");21436 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);
20914 const section_opt_val = try sema.resolveConstValue(block, section_src, section_operand, "linksection of exported value must be comptime-known");21440 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);21441 const section_ty = Type.slice_const_u8;
20916 const section = if (section_opt_val.optionalValue()) |section_val|21442 const section = if (section_opt_val.optionalValue(mod)) |section_val|
20917 try section_val.toAllocatedBytes(section_ty, sema.arena, sema.mod)21443 try section_val.toAllocatedBytes(section_ty, sema.arena, mod)
20918 else21444 else
20919 null;21445 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);
20922 const visibility_val = try sema.resolveConstValue(block, visibility_src, visibility_operand, "visibility of exported value must be comptime-known");21448 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
20925 if (name.len < 1) {21451 if (name.len < 1) {
20926 return sema.fail(block, name_src, "exported symbol name cannot be empty", .{});21452 return sema.fail(block, name_src, "exported symbol name cannot be empty", .{});
...@@ -20932,10 +21458,10 @@ fn resolveExportOptions(...@@ -20932,10 +21458,10 @@ fn resolveExportOptions(
20932 });21458 });
20933 }21459 }
2093421460
20935 return std.builtin.ExportOptions{21461 return .{
20936 .name = name,21462 .name = try ip.getOrPutString(gpa, name),
20937 .linkage = linkage,21463 .linkage = linkage,
20938 .section = section,21464 .section = try ip.getOrPutStringOpt(gpa, section),
20939 .visibility = visibility,21465 .visibility = visibility,
20940 };21466 };
20941}21467}
...@@ -20948,11 +21474,12 @@ fn resolveBuiltinEnum(...@@ -20948,11 +21474,12 @@ fn resolveBuiltinEnum(
20948 comptime name: []const u8,21474 comptime name: []const u8,
20949 reason: []const u8,21475 reason: []const u8,
20950) CompileError!@field(std.builtin, name) {21476) CompileError!@field(std.builtin, name) {
21477 const mod = sema.mod;
20951 const ty = try sema.getBuiltinType(name);21478 const ty = try sema.getBuiltinType(name);
20952 const air_ref = try sema.resolveInst(zir_ref);21479 const air_ref = try sema.resolveInst(zir_ref);
20953 const coerced = try sema.coerce(block, ty, air_ref, src);21480 const coerced = try sema.coerce(block, ty, air_ref, src);
20954 const val = try sema.resolveConstValue(block, src, coerced, reason);21481 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);
20956}21483}
2095721484
20958fn resolveAtomicOrder(21485fn resolveAtomicOrder(
...@@ -20979,6 +21506,7 @@ fn zirCmpxchg(...@@ -20979,6 +21506,7 @@ fn zirCmpxchg(
20979 block: *Block,21506 block: *Block,
20980 extended: Zir.Inst.Extended.InstData,21507 extended: Zir.Inst.Extended.InstData,
20981) CompileError!Air.Inst.Ref {21508) CompileError!Air.Inst.Ref {
21509 const mod = sema.mod;
20982 const extra = sema.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;21510 const extra = sema.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;
20983 const air_tag: Air.Inst.Tag = switch (extended.small) {21511 const air_tag: Air.Inst.Tag = switch (extended.small) {
20984 0 => .cmpxchg_weak,21512 0 => .cmpxchg_weak,
...@@ -20996,12 +21524,12 @@ fn zirCmpxchg(...@@ -20996,12 +21524,12 @@ fn zirCmpxchg(
20996 // zig fmt: on21524 // zig fmt: on
20997 const expected_value = try sema.resolveInst(extra.expected_value);21525 const expected_value = try sema.resolveInst(extra.expected_value);
20998 const elem_ty = sema.typeOf(expected_value);21526 const elem_ty = sema.typeOf(expected_value);
20999 if (elem_ty.zigTypeTag() == .Float) {21527 if (elem_ty.zigTypeTag(mod) == .Float) {
21000 return sema.fail(21528 return sema.fail(
21001 block,21529 block,
21002 elem_ty_src,21530 elem_ty_src,
21003 "expected bool, integer, enum, or pointer type; found '{}'",21531 "expected bool, integer, enum, or pointer type; found '{}'",
21004 .{elem_ty.fmt(sema.mod)},21532 .{elem_ty.fmt(mod)},
21005 );21533 );
21006 }21534 }
21007 const uncasted_ptr = try sema.resolveInst(extra.ptr);21535 const uncasted_ptr = try sema.resolveInst(extra.ptr);
...@@ -21023,29 +21551,34 @@ fn zirCmpxchg(...@@ -21023,29 +21551,34 @@ fn zirCmpxchg(
21023 return sema.fail(block, failure_order_src, "failure atomic ordering must not be Release or AcqRel", .{});21551 return sema.fail(block, failure_order_src, "failure atomic ordering must not be Release or AcqRel", .{});
21024 }21552 }
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
21028 // special case zero bit types21556 // special case zero bit types
21029 if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) {21557 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());
21031 }21562 }
2103221563
21033 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {21564 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
21034 if (try sema.resolveMaybeUndefVal(expected_value)) |expected_val| {21565 if (try sema.resolveMaybeUndefVal(expected_value)) |expected_val| {
21035 if (try sema.resolveMaybeUndefVal(new_value)) |new_val| {21566 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)) {
21037 // TODO: this should probably cause the memory stored at the pointer21568 // TODO: this should probably cause the memory stored at the pointer
21038 // to become undef as well21569 // to become undef as well
21039 return sema.addConstUndef(result_ty);21570 return sema.addConstUndef(result_ty);
21040 }21571 }
21041 const ptr_ty = sema.typeOf(ptr);21572 const ptr_ty = sema.typeOf(ptr);
21042 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;21573 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: {21574 const result_val = try mod.intern(.{ .opt = .{
21044 try sema.storePtr(block, src, ptr, new_value);21575 .ty = result_ty.toIntern(),
21045 break :blk Value.null;21576 .val = if (stored_val.eql(expected_val, elem_ty, mod)) blk: {
21046 } else try Value.Tag.opt_payload.create(sema.arena, stored_val);21577 try sema.storePtr(block, src, ptr, new_value);
2104721578 break :blk .none;
21048 return sema.addConstant(result_ty, result_val);21579 } else stored_val.toIntern(),
21580 } });
21581 return sema.addConstant(result_ty, result_val.toValue());
21049 } else break :rs new_value_src;21582 } else break :rs new_value_src;
21050 } else break :rs expected_src;21583 } else break :rs expected_src;
21051 } else ptr_src;21584 } else ptr_src;
...@@ -21069,6 +21602,7 @@ fn zirCmpxchg(...@@ -21069,6 +21602,7 @@ fn zirCmpxchg(
21069}21602}
2107021603
21071fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {21604fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
21605 const mod = sema.mod;
21072 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;21606 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
21073 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;21607 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
21074 const len_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };21608 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...@@ -21077,17 +21611,13 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
21077 const scalar = try sema.resolveInst(extra.rhs);21611 const scalar = try sema.resolveInst(extra.rhs);
21078 const scalar_ty = sema.typeOf(scalar);21612 const scalar_ty = sema.typeOf(scalar);
21079 try sema.checkVectorElemType(block, scalar_src, scalar_ty);21613 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(.{
21081 .len = len,21615 .len = len,
21082 .elem_type = scalar_ty,21616 .child = scalar_ty.toIntern(),
21083 });21617 });
21084 if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {21618 if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {
21085 if (scalar_val.isUndef()) return sema.addConstUndef(vector_ty);21619 if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty);
2108621620 return sema.addConstant(vector_ty, try sema.splat(vector_ty, scalar_val));
21087 return sema.addConstant(
21088 vector_ty,
21089 try Value.Tag.repeated.create(sema.arena, scalar_val),
21090 );
21091 }21621 }
2109221622
21093 try sema.requireRuntimeBlock(block, inst_data.src(), scalar_src);21623 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....@@ -21102,31 +21632,31 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
21102 const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, "ReduceOp", "@reduce operation must be comptime-known");21632 const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, "ReduceOp", "@reduce operation must be comptime-known");
21103 const operand = try sema.resolveInst(extra.rhs);21633 const operand = try sema.resolveInst(extra.rhs);
21104 const operand_ty = sema.typeOf(operand);21634 const operand_ty = sema.typeOf(operand);
21105 const target = sema.mod.getTarget();21635 const mod = sema.mod;
2110621636
21107 if (operand_ty.zigTypeTag() != .Vector) {21637 if (operand_ty.zigTypeTag(mod) != .Vector) {
21108 return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(sema.mod)});21638 return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(mod)});
21109 }21639 }
2111021640
21111 const scalar_ty = operand_ty.childType();21641 const scalar_ty = operand_ty.childType(mod);
2111221642
21113 // Type-check depending on operation.21643 // Type-check depending on operation.
21114 switch (operation) {21644 switch (operation) {
21115 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag()) {21645 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) {
21116 .Int, .Bool => {},21646 .Int, .Bool => {},
21117 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{}'", .{21647 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),
21119 }),21649 }),
21120 },21650 },
21121 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag()) {21651 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) {
21122 .Int, .Float => {},21652 .Int, .Float => {},
21123 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{}'", .{21653 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),
21125 }),21655 }),
21126 },21656 },
21127 }21657 }
2112821658
21129 const vec_len = operand_ty.vectorLen();21659 const vec_len = operand_ty.vectorLen(mod);
21130 if (vec_len == 0) {21660 if (vec_len == 0) {
21131 // TODO re-evaluate if we should introduce a "neutral value" for some operations,21661 // TODO re-evaluate if we should introduce a "neutral value" for some operations,
21132 // e.g. zero for add and one for mul.21662 // 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....@@ -21134,21 +21664,20 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
21134 }21664 }
2113521665
21136 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {21666 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);21669 var accum: Value = try operand_val.elemValue(mod, 0);
21140 var elem_buf: Value.ElemValueBuffer = undefined;
21141 var i: u32 = 1;21670 var i: u32 = 1;
21142 while (i < vec_len) : (i += 1) {21671 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);
21144 switch (operation) {21673 switch (operation) {
21145 .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena, sema.mod),21674 .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena, mod),
21146 .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena, sema.mod),21675 .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena, mod),
21147 .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, sema.mod),21676 .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, mod),
21148 .Min => accum = accum.numberMin(elem_val, target),21677 .Min => accum = accum.numberMin(elem_val, mod),
21149 .Max => accum = accum.numberMax(elem_val, target),21678 .Max => accum = accum.numberMax(elem_val, mod),
21150 .Add => accum = try sema.numberAddWrapScalar(accum, elem_val, scalar_ty),21679 .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),
21152 }21681 }
21153 }21682 }
21154 return sema.addConstant(scalar_ty, accum);21683 return sema.addConstant(scalar_ty, accum);
...@@ -21165,6 +21694,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -21165,6 +21694,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
21165}21694}
2116621695
21167fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {21696fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
21697 const mod = sema.mod;
21168 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;21698 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
21169 const extra = sema.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;21699 const extra = sema.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;
21170 const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };21700 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...@@ -21177,13 +21707,13 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
21177 var mask = try sema.resolveInst(extra.mask);21707 var mask = try sema.resolveInst(extra.mask);
21178 var mask_ty = sema.typeOf(mask);21708 var mask_ty = sema.typeOf(mask);
2117921709
21180 const mask_len = switch (sema.typeOf(mask).zigTypeTag()) {21710 const mask_len = switch (sema.typeOf(mask).zigTypeTag(mod)) {
21181 .Array, .Vector => sema.typeOf(mask).arrayLen(),21711 .Array, .Vector => sema.typeOf(mask).arrayLen(mod),
21182 else => return sema.fail(block, mask_src, "expected vector or array, found '{}'", .{sema.typeOf(mask).fmt(sema.mod)}),21712 else => return sema.fail(block, mask_src, "expected vector or array, found '{}'", .{sema.typeOf(mask).fmt(sema.mod)}),
21183 };21713 };
21184 mask_ty = try Type.Tag.vector.create(sema.arena, .{21714 mask_ty = try mod.vectorType(.{
21185 .len = mask_len,21715 .len = @intCast(u32, mask_len),
21186 .elem_type = Type.i32,21716 .child = .i32_type,
21187 });21717 });
21188 mask = try sema.coerce(block, mask_ty, mask, mask_src);21718 mask = try sema.coerce(block, mask_ty, mask, mask_src);
21189 const mask_val = try sema.resolveConstMaybeUndefVal(block, mask_src, mask, "shuffle mask must be comptime-known");21719 const mask_val = try sema.resolveConstMaybeUndefVal(block, mask_src, mask, "shuffle mask must be comptime-known");
...@@ -21200,27 +21730,28 @@ fn analyzeShuffle(...@@ -21200,27 +21730,28 @@ fn analyzeShuffle(
21200 mask: Value,21730 mask: Value,
21201 mask_len: u32,21731 mask_len: u32,
21202) CompileError!Air.Inst.Ref {21732) CompileError!Air.Inst.Ref {
21733 const mod = sema.mod;
21203 const a_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = src_node };21734 const a_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = src_node };
21204 const b_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = src_node };21735 const b_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = src_node };
21205 const mask_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = src_node };21736 const mask_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = src_node };
21206 var a = a_arg;21737 var a = a_arg;
21207 var b = b_arg;21738 var b = b_arg;
2120821739
21209 const res_ty = try Type.Tag.vector.create(sema.arena, .{21740 const res_ty = try mod.vectorType(.{
21210 .len = mask_len,21741 .len = mask_len,
21211 .elem_type = elem_ty,21742 .child = elem_ty.toIntern(),
21212 });21743 });
2121321744
21214 var maybe_a_len = switch (sema.typeOf(a).zigTypeTag()) {21745 var maybe_a_len = switch (sema.typeOf(a).zigTypeTag(mod)) {
21215 .Array, .Vector => sema.typeOf(a).arrayLen(),21746 .Array, .Vector => sema.typeOf(a).arrayLen(mod),
21216 .Undefined => null,21747 .Undefined => null,
21217 else => return sema.fail(block, a_src, "expected vector or array with element type '{}', found '{}'", .{21748 else => return sema.fail(block, a_src, "expected vector or array with element type '{}', found '{}'", .{
21218 elem_ty.fmt(sema.mod),21749 elem_ty.fmt(sema.mod),
21219 sema.typeOf(a).fmt(sema.mod),21750 sema.typeOf(a).fmt(sema.mod),
21220 }),21751 }),
21221 };21752 };
21222 var maybe_b_len = switch (sema.typeOf(b).zigTypeTag()) {21753 var maybe_b_len = switch (sema.typeOf(b).zigTypeTag(mod)) {
21223 .Array, .Vector => sema.typeOf(b).arrayLen(),21754 .Array, .Vector => sema.typeOf(b).arrayLen(mod),
21224 .Undefined => null,21755 .Undefined => null,
21225 else => return sema.fail(block, b_src, "expected vector or array with element type '{}', found '{}'", .{21756 else => return sema.fail(block, b_src, "expected vector or array with element type '{}', found '{}'", .{
21226 elem_ty.fmt(sema.mod),21757 elem_ty.fmt(sema.mod),
...@@ -21230,16 +21761,16 @@ fn analyzeShuffle(...@@ -21230,16 +21761,16 @@ fn analyzeShuffle(
21230 if (maybe_a_len == null and maybe_b_len == null) {21761 if (maybe_a_len == null and maybe_b_len == null) {
21231 return sema.addConstUndef(res_ty);21762 return sema.addConstUndef(res_ty);
21232 }21763 }
21233 const a_len = maybe_a_len orelse maybe_b_len.?;21764 const a_len = @intCast(u32, maybe_a_len orelse maybe_b_len.?);
21234 const b_len = maybe_b_len orelse a_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(.{
21237 .len = a_len,21768 .len = a_len,
21238 .elem_type = elem_ty,21769 .child = elem_ty.toIntern(),
21239 });21770 });
21240 const b_ty = try Type.Tag.vector.create(sema.arena, .{21771 const b_ty = try mod.vectorType(.{
21241 .len = b_len,21772 .len = b_len,
21242 .elem_type = elem_ty,21773 .child = elem_ty.toIntern(),
21243 });21774 });
2124421775
21245 if (maybe_a_len == null) a = try sema.addConstUndef(a_ty) else a = try sema.coerce(block, a_ty, a, a_src);21776 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(...@@ -21250,12 +21781,10 @@ fn analyzeShuffle(
21250 .{ b_len, b_src, b_ty },21781 .{ b_len, b_src, b_ty },
21251 };21782 };
2125221783
21253 var i: usize = 0;21784 for (0..@intCast(usize, mask_len)) |i| {
21254 while (i < mask_len) : (i += 1) {21785 const elem = try mask.elemValue(sema.mod, i);
21255 var buf: Value.ElemValueBuffer = undefined;21786 if (elem.isUndef(mod)) continue;
21256 const elem = mask.elemValueBuffer(sema.mod, i, &buf);21787 const int = elem.toSignedInt(mod);
21257 if (elem.isUndef()) continue;
21258 const int = elem.toSignedInt(sema.mod.getTarget());
21259 var unsigned: u32 = undefined;21788 var unsigned: u32 = undefined;
21260 var chosen: u32 = undefined;21789 var chosen: u32 = undefined;
21261 if (int >= 0) {21790 if (int >= 0) {
...@@ -21287,26 +21816,21 @@ fn analyzeShuffle(...@@ -21287,26 +21816,21 @@ fn analyzeShuffle(
2128721816
21288 if (try sema.resolveMaybeUndefVal(a)) |a_val| {21817 if (try sema.resolveMaybeUndefVal(a)) |a_val| {
21289 if (try sema.resolveMaybeUndefVal(b)) |b_val| {21818 if (try sema.resolveMaybeUndefVal(b)) |b_val| {
21290 const values = try sema.arena.alloc(Value, mask_len);21819 const values = try sema.arena.alloc(InternPool.Index, mask_len);
2129121820 for (values, 0..) |*value, i| {
21292 i = 0;21821 const mask_elem_val = try mask.elemValue(sema.mod, i);
21293 while (i < mask_len) : (i += 1) {21822 if (mask_elem_val.isUndef(mod)) {
21294 var buf: Value.ElemValueBuffer = undefined;21823 value.* = try mod.intern(.{ .undef = elem_ty.toIntern() });
21295 const mask_elem_val = mask.elemValueBuffer(sema.mod, i, &buf);
21296 if (mask_elem_val.isUndef()) {
21297 values[i] = Value.undef;
21298 continue;21824 continue;
21299 }21825 }
21300 const int = mask_elem_val.toSignedInt(sema.mod.getTarget());21826 const int = mask_elem_val.toSignedInt(mod);
21301 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);21827 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);
21302 if (int >= 0) {21828 values[i] = try (try (if (int >= 0) a_val else b_val).elemValue(mod, unsigned)).intern(elem_ty, mod);
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 }
21307 }21829 }
21308 const res_val = try Value.Tag.aggregate.create(sema.arena, values);21830 return sema.addConstant(res_ty, (try mod.intern(.{ .aggregate = .{
21309 return sema.addConstant(res_ty, res_val);21831 .ty = res_ty.toIntern(),
21832 .storage = .{ .elems = values },
21833 } })).toValue());
21310 }21834 }
21311 }21835 }
2131221836
...@@ -21320,27 +21844,27 @@ fn analyzeShuffle(...@@ -21320,27 +21844,27 @@ fn analyzeShuffle(
21320 const max_src = if (a_len > b_len) a_src else b_src;21844 const max_src = if (a_len > b_len) a_src else b_src;
21321 const max_len = try sema.usizeCast(block, max_src, std.math.max(a_len, b_len));21845 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);21847 const expand_mask_values = try sema.arena.alloc(InternPool.Index, max_len);
21324 i = 0;21848 for (@intCast(usize, 0)..@intCast(usize, min_len)) |i| {
21325 while (i < min_len) : (i += 1) {21849 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, i)).toIntern();
21326 expand_mask_values[i] = try Value.Tag.int_u64.create(sema.arena, i);
21327 }21850 }
21328 while (i < max_len) : (i += 1) {21851 for (@intCast(usize, min_len)..@intCast(usize, max_len)) |i| {
21329 expand_mask_values[i] = Value.negative_one;21852 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, -1)).toIntern();
21330 }21853 }
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
21333 if (a_len < b_len) {21859 if (a_len < b_len) {
21334 const undef = try sema.addConstUndef(a_ty);21860 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));
21336 } else {21862 } else {
21337 const undef = try sema.addConstUndef(b_ty);21863 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));
21339 }21865 }
21340 }21866 }
2134121867
21342 const mask_index = @intCast(u32, sema.air_values.items.len);
21343 try sema.air_values.append(sema.gpa, mask);
21344 return block.addInst(.{21868 return block.addInst(.{
21345 .tag = .shuffle,21869 .tag = .shuffle,
21346 .data = .{ .ty_pl = .{21870 .data = .{ .ty_pl = .{
...@@ -21348,7 +21872,7 @@ fn analyzeShuffle(...@@ -21348,7 +21872,7 @@ fn analyzeShuffle(
21348 .payload = try block.sema.addExtra(Air.Shuffle{21872 .payload = try block.sema.addExtra(Air.Shuffle{
21349 .a = a,21873 .a = a,
21350 .b = b,21874 .b = b,
21351 .mask = mask_index,21875 .mask = mask.toIntern(),
21352 .mask_len = mask_len,21876 .mask_len = mask_len,
21353 }),21877 }),
21354 } },21878 } },
...@@ -21356,6 +21880,7 @@ fn analyzeShuffle(...@@ -21356,6 +21880,7 @@ fn analyzeShuffle(
21356}21880}
2135721881
21358fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {21882fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
21883 const mod = sema.mod;
21359 const extra = sema.code.extraData(Zir.Inst.Select, extended.operand).data;21884 const extra = sema.code.extraData(Zir.Inst.Select, extended.operand).data;
2136021885
21361 const src = LazySrcLoc.nodeOffset(extra.node);21886 const src = LazySrcLoc.nodeOffset(extra.node);
...@@ -21369,16 +21894,22 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -21369,16 +21894,22 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
21369 const pred_uncoerced = try sema.resolveInst(extra.pred);21894 const pred_uncoerced = try sema.resolveInst(extra.pred);
21370 const pred_ty = sema.typeOf(pred_uncoerced);21895 const pred_ty = sema.typeOf(pred_uncoerced);
2137121896
21372 const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison()) {21897 const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison(mod)) {
21373 .Vector, .Array => pred_ty.arrayLen(),21898 .Vector, .Array => pred_ty.arrayLen(mod),
21374 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(sema.mod)}),21899 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(mod)}),
21375 };21900 };
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 });
21379 const pred = try sema.coerce(block, bool_vec_ty, pred_uncoerced, pred_src);21907 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 });
21382 const a = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.a), a_src);21913 const a = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.a), a_src);
21383 const b = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.b), b_src);21914 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...@@ -21387,45 +21918,40 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
21387 const maybe_b = try sema.resolveMaybeUndefVal(b);21918 const maybe_b = try sema.resolveMaybeUndefVal(b);
2138821919
21389 const runtime_src = if (maybe_pred) |pred_val| rs: {21920 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
21392 if (maybe_a) |a_val| {21923 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
21395 if (maybe_b) |b_val| {21926 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;21929 const elems = try sema.gpa.alloc(InternPool.Index, vec_len);
21399 const elems = try sema.gpa.alloc(Value, vec_len);
21400 for (elems, 0..) |*elem, i| {21930 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);
21402 const should_choose_a = pred_elem_val.toBool();21932 const should_choose_a = pred_elem_val.toBool();
21403 if (should_choose_a) {21933 elem.* = try (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).intern(elem_ty, mod);
21404 elem.* = a_val.elemValueBuffer(sema.mod, i, &buf);
21405 } else {
21406 elem.* = b_val.elemValueBuffer(sema.mod, i, &buf);
21407 }
21408 }21934 }
2140921935
21410 return sema.addConstant(21936 return sema.addConstant(vec_ty, (try mod.intern(.{ .aggregate = .{
21411 vec_ty,21937 .ty = vec_ty.toIntern(),
21412 try Value.Tag.aggregate.create(sema.arena, elems),21938 .storage = .{ .elems = elems },
21413 );21939 } })).toValue());
21414 } else {21940 } else {
21415 break :rs b_src;21941 break :rs b_src;
21416 }21942 }
21417 } else {21943 } else {
21418 if (maybe_b) |b_val| {21944 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);
21420 }21946 }
21421 break :rs a_src;21947 break :rs a_src;
21422 }21948 }
21423 } else rs: {21949 } else rs: {
21424 if (maybe_a) |a_val| {21950 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);
21426 }21952 }
21427 if (maybe_b) |b_val| {21953 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);
21429 }21955 }
21430 break :rs pred_src;21956 break :rs pred_src;
21431 };21957 };
...@@ -21489,6 +22015,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -21489,6 +22015,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
21489}22015}
2149022016
21491fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {22017fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
22018 const mod = sema.mod;
21492 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;22019 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
21493 const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;22020 const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;
21494 const src = inst_data.src();22021 const src = inst_data.src();
...@@ -21505,7 +22032,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -21505,7 +22032,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
21505 const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false);22032 const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false);
21506 const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation);22033 const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation);
2150722034
21508 switch (elem_ty.zigTypeTag()) {22035 switch (elem_ty.zigTypeTag(mod)) {
21509 .Enum => if (op != .Xchg) {22036 .Enum => if (op != .Xchg) {
21510 return sema.fail(block, op_src, "@atomicRmw with enum only allowed with .Xchg", .{});22037 return sema.fail(block, op_src, "@atomicRmw with enum only allowed with .Xchg", .{});
21511 },22038 },
...@@ -21535,8 +22062,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -21535,8 +22062,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
21535 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);22062 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
21536 break :rs operand_src;22063 break :rs operand_src;
21537 };22064 };
21538 if (ptr_val.isComptimeMutablePtr()) {22065 if (ptr_val.isComptimeMutablePtr(mod)) {
21539 const target = sema.mod.getTarget();
21540 const ptr_ty = sema.typeOf(ptr);22066 const ptr_ty = sema.typeOf(ptr);
21541 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;22067 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
21542 const new_val = switch (op) {22068 const new_val = switch (op) {
...@@ -21544,12 +22070,12 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -21544,12 +22070,12 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
21544 .Xchg => operand_val,22070 .Xchg => operand_val,
21545 .Add => try sema.numberAddWrapScalar(stored_val, operand_val, elem_ty),22071 .Add => try sema.numberAddWrapScalar(stored_val, operand_val, elem_ty),
21546 .Sub => try sema.numberSubWrapScalar(stored_val, operand_val, elem_ty),22072 .Sub => try sema.numberSubWrapScalar(stored_val, operand_val, elem_ty),
21547 .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, sema.mod),22073 .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, mod),
21548 .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, sema.mod),22074 .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, mod),
21549 .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, sema.mod),22075 .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, mod),
21550 .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, sema.mod),22076 .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, mod),
21551 .Max => stored_val.numberMax (operand_val, target),22077 .Max => stored_val.numberMax (operand_val, mod),
21552 .Min => stored_val.numberMin (operand_val, target),22078 .Min => stored_val.numberMin (operand_val, mod),
21553 // zig fmt: on22079 // zig fmt: on
21554 };22080 };
21555 try sema.storePtrVal(block, src, ptr_val, new_val, elem_ty);22081 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....@@ -21623,18 +22149,19 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
21623 const maybe_mulend1 = try sema.resolveMaybeUndefVal(mulend1);22149 const maybe_mulend1 = try sema.resolveMaybeUndefVal(mulend1);
21624 const maybe_mulend2 = try sema.resolveMaybeUndefVal(mulend2);22150 const maybe_mulend2 = try sema.resolveMaybeUndefVal(mulend2);
21625 const maybe_addend = try sema.resolveMaybeUndefVal(addend);22151 const maybe_addend = try sema.resolveMaybeUndefVal(addend);
22152 const mod = sema.mod;
2162622153
21627 switch (ty.zigTypeTag()) {22154 switch (ty.zigTypeTag(mod)) {
21628 .ComptimeFloat, .Float, .Vector => {},22155 .ComptimeFloat, .Float, .Vector => {},
21629 else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(sema.mod)}),22156 else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(sema.mod)}),
21630 }22157 }
2163122158
21632 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {22159 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {
21633 if (maybe_mulend2) |mulend2_val| {22160 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
21636 if (maybe_addend) |addend_val| {22163 if (maybe_addend) |addend_val| {
21637 if (addend_val.isUndef()) return sema.addConstUndef(ty);22164 if (addend_val.isUndef(mod)) return sema.addConstUndef(ty);
21638 const result_val = try Value.mulAdd(ty, mulend1_val, mulend2_val, addend_val, sema.arena, sema.mod);22165 const result_val = try Value.mulAdd(ty, mulend1_val, mulend2_val, addend_val, sema.arena, sema.mod);
21639 return sema.addConstant(ty, result_val);22166 return sema.addConstant(ty, result_val);
21640 } else {22167 } else {
...@@ -21642,16 +22169,16 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -21642,16 +22169,16 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
21642 }22169 }
21643 } else {22170 } else {
21644 if (maybe_addend) |addend_val| {22171 if (maybe_addend) |addend_val| {
21645 if (addend_val.isUndef()) return sema.addConstUndef(ty);22172 if (addend_val.isUndef(mod)) return sema.addConstUndef(ty);
21646 }22173 }
21647 break :rs mulend2_src;22174 break :rs mulend2_src;
21648 }22175 }
21649 } else rs: {22176 } else rs: {
21650 if (maybe_mulend2) |mulend2_val| {22177 if (maybe_mulend2) |mulend2_val| {
21651 if (mulend2_val.isUndef()) return sema.addConstUndef(ty);22178 if (mulend2_val.isUndef(mod)) return sema.addConstUndef(ty);
21652 }22179 }
21653 if (maybe_addend) |addend_val| {22180 if (maybe_addend) |addend_val| {
21654 if (addend_val.isUndef()) return sema.addConstUndef(ty);22181 if (addend_val.isUndef(mod)) return sema.addConstUndef(ty);
21655 }22182 }
21656 break :rs mulend1_src;22183 break :rs mulend1_src;
21657 };22184 };
...@@ -21673,6 +22200,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -21673,6 +22200,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21673 const tracy = trace(@src());22200 const tracy = trace(@src());
21674 defer tracy.end();22201 defer tracy.end();
2167522202
22203 const mod = sema.mod;
21676 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;22204 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
21677 const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };22205 const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
21678 const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };22206 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...@@ -21686,7 +22214,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21686 const air_ref = try sema.resolveInst(extra.modifier);22214 const air_ref = try sema.resolveInst(extra.modifier);
21687 const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src);22215 const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src);
21688 const modifier_val = try sema.resolveConstValue(block, modifier_src, modifier_ref, "call modifier must be comptime-known");22216 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);
21690 switch (modifier) {22218 switch (modifier) {
21691 // These can be upgraded to comptime or nosuspend calls.22219 // These can be upgraded to comptime or nosuspend calls.
21692 .auto, .never_tail, .no_async => {22220 .auto, .never_tail, .no_async => {
...@@ -21732,18 +22260,17 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -21732,18 +22260,17 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21732 const args = try sema.resolveInst(extra.args);22260 const args = try sema.resolveInst(extra.args);
2173322261
21734 const args_ty = sema.typeOf(args);22262 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) {
21736 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});22264 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});
21737 }22265 }
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));
21740 for (resolved_args, 0..) |*resolved, i| {22268 for (resolved_args, 0..) |*resolved, i| {
21741 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);22269 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);
21742 }22270 }
2174322271
21744 const callee_ty = sema.typeOf(func);22272 const callee_ty = sema.typeOf(func);
21745 const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false);22273 const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false);
21746
21747 const ensure_result_used = extra.flags.ensure_result_used;22274 const ensure_result_used = extra.flags.ensure_result_used;
21748 return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null);22275 return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null);
21749}22276}
...@@ -21757,19 +22284,21 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -21757,19 +22284,21 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
21757 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };22284 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
2175822285
21759 const parent_ty = try sema.resolveType(block, ty_src, extra.parent_type);22286 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");
21761 const field_ptr = try sema.resolveInst(extra.field_ptr);22288 const field_ptr = try sema.resolveInst(extra.field_ptr);
21762 const field_ptr_ty = sema.typeOf(field_ptr);22289 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) {
21765 return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)});22294 return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)});
21766 }22295 }
21767 try sema.resolveTypeLayout(parent_ty);22296 try sema.resolveTypeLayout(parent_ty);
2176822297
21769 const field_index = switch (parent_ty.zigTypeTag()) {22298 const field_index = switch (parent_ty.zigTypeTag(mod)) {
21770 .Struct => blk: {22299 .Struct => blk: {
21771 if (parent_ty.isTuple()) {22300 if (parent_ty.isTuple(mod)) {
21772 if (mem.eql(u8, field_name, "len")) {22301 if (ip.stringEqlSlice(field_name, "len")) {
21773 return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});22302 return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
21774 }22303 }
21775 break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, name_src);22304 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...@@ -21781,27 +22310,27 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
21781 else => unreachable,22310 else => unreachable,
21782 };22311 };
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)) {
21785 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});22314 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
21786 }22315 }
2178722316
21788 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);22317 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
21791 var ptr_ty_data: Type.Payload.Pointer.Data = .{22320 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),
21793 .mutable = field_ptr_ty_info.mutable,22322 .mutable = field_ptr_ty_info.mutable,
21794 .@"addrspace" = field_ptr_ty_info.@"addrspace",22323 .@"addrspace" = field_ptr_ty_info.@"addrspace",
21795 };22324 };
2179622325
21797 if (parent_ty.containerLayout() == .Packed) {22326 if (parent_ty.containerLayout(mod) == .Packed) {
21798 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});22327 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});
21799 } else {22328 } else {
21800 ptr_ty_data.@"align" = blk: {22329 ptr_ty_data.@"align" = blk: {
21801 if (parent_ty.castTag(.@"struct")) |struct_obj| {22330 if (mod.typeToStruct(parent_ty)) |struct_obj| {
21802 break :blk struct_obj.data.fields.values()[field_index].abi_align;22331 break :blk struct_obj.fields.values()[field_index].abi_align;
21803 } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| {22332 } else if (mod.typeToUnion(parent_ty)) |union_obj| {
21804 break :blk union_obj.data.fields.values()[field_index].abi_align;22333 break :blk union_obj.fields.values()[field_index].abi_align;
21805 } else {22334 } else {
21806 break :blk 0;22335 break :blk 0;
21807 }22336 }
...@@ -21815,19 +22344,24 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -21815,19 +22344,24 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
21815 const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);22344 const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
2181622345
21817 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {22346 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
21818 const payload = field_ptr_val.castTag(.field_ptr) orelse {22347 const field = switch (ip.indexToKey(field_ptr_val.toIntern())) {
21819 return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});22348 .ptr => |ptr| switch (ptr.addr) {
21820 };22349 .field => |field| field,
21821 if (payload.data.field_index != field_index) {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) {
21822 const msg = msg: {22356 const msg = msg: {
21823 const msg = try sema.errMsg(22357 const msg = try sema.errMsg(
21824 block,22358 block,
21825 src,22359 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 '{}'",
21827 .{22361 .{
21828 field_name,22362 field_name.fmt(ip),
21829 field_index,22363 field_index,
21830 payload.data.field_index,22364 field.index,
21831 parent_ty.fmt(sema.mod),22365 parent_ty.fmt(sema.mod),
21832 },22366 },
21833 );22367 );
...@@ -21837,7 +22371,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -21837,7 +22371,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
21837 };22371 };
21838 return sema.failWithOwnedErrorMsg(msg);22372 return sema.failWithOwnedErrorMsg(msg);
21839 }22373 }
21840 return sema.addConstant(result_ptr, payload.data.container_ptr);22374 return sema.addConstant(result_ptr, field.base.toValue());
21841 }22375 }
2184222376
21843 try sema.requireRuntimeBlock(block, src, ptr_src);22377 try sema.requireRuntimeBlock(block, src, ptr_src);
...@@ -21913,15 +22447,14 @@ fn analyzeMinMax(...@@ -21913,15 +22447,14 @@ fn analyzeMinMax(
21913) CompileError!Air.Inst.Ref {22447) CompileError!Air.Inst.Ref {
21914 assert(operands.len == operand_srcs.len);22448 assert(operands.len == operand_srcs.len);
21915 assert(operands.len > 0);22449 assert(operands.len > 0);
22450 const mod = sema.mod;
2191622451
21917 if (operands.len == 1) return operands[0];22452 if (operands.len == 1) return operands[0];
2191822453
21919 const mod = sema.mod;
21920 const target = mod.getTarget();
21921 const opFunc = switch (air_tag) {22454 const opFunc = switch (air_tag) {
21922 .min => Value.numberMin,22455 .min => Value.numberMin,
21923 .max => Value.numberMax,22456 .max => Value.numberMax,
21924 else => unreachable,22457 else => @compileError("unreachable"),
21925 };22458 };
2192622459
21927 // First, find all comptime-known arguments, and get their min/max22460 // First, find all comptime-known arguments, and get their min/max
...@@ -21939,32 +22472,30 @@ fn analyzeMinMax(...@@ -21939,32 +22472,30 @@ fn analyzeMinMax(
2193922472
21940 runtime_known.unset(operand_idx);22473 runtime_known.unset(operand_idx);
2194122474
21942 if (cur_val.isUndef()) continue; // result is also undef22475 if (cur_val.isUndef(mod)) continue; // result is also undef
21943 if (operand_val.isUndef()) {22476 if (operand_val.isUndef(mod)) {
21944 cur_minmax = try sema.addConstUndef(simd_op.result_ty);22477 cur_minmax = try sema.addConstUndef(simd_op.result_ty);
21945 continue;22478 continue;
21946 }22479 }
2194722480
21948 try sema.resolveLazyValue(cur_val);22481 const resolved_cur_val = try sema.resolveLazyValue(cur_val);
21949 try sema.resolveLazyValue(operand_val);22482 const resolved_operand_val = try sema.resolveLazyValue(operand_val);
2195022483
21951 const vec_len = simd_op.len orelse {22484 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);
21953 cur_minmax = try sema.addConstant(simd_op.result_ty, result_val);22486 cur_minmax = try sema.addConstant(simd_op.result_ty, result_val);
21954 continue;22487 continue;
21955 };22488 };
21956 var lhs_buf: Value.ElemValueBuffer = undefined;22489 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
21957 var rhs_buf: Value.ElemValueBuffer = undefined;
21958 const elems = try sema.arena.alloc(Value, vec_len);
21959 for (elems, 0..) |*elem, i| {22490 for (elems, 0..) |*elem, i| {
21960 const lhs_elem_val = cur_val.elemValueBuffer(mod, i, &lhs_buf);22491 const lhs_elem_val = try resolved_cur_val.elemValue(mod, i);
21961 const rhs_elem_val = operand_val.elemValueBuffer(mod, i, &rhs_buf);22492 const rhs_elem_val = try resolved_operand_val.elemValue(mod, i);
21962 elem.* = opFunc(lhs_elem_val, rhs_elem_val, target);22493 elem.* = try opFunc(lhs_elem_val, rhs_elem_val, mod).intern(simd_op.scalar_ty, mod);
21963 }22494 }
21964 cur_minmax = try sema.addConstant(22495 cur_minmax = try sema.addConstant(simd_op.result_ty, (try mod.intern(.{ .aggregate = .{
21965 simd_op.result_ty,22496 .ty = simd_op.result_ty.toIntern(),
21966 try Value.Tag.aggregate.create(sema.arena, elems),22497 .storage = .{ .elems = elems },
21967 );22498 } })).toValue());
21968 } else {22499 } else {
21969 runtime_known.unset(operand_idx);22500 runtime_known.unset(operand_idx);
21970 cur_minmax = try sema.addConstant(sema.typeOf(operand), uncasted_operand_val);22501 cur_minmax = try sema.addConstant(sema.typeOf(operand), uncasted_operand_val);
...@@ -21984,28 +22515,31 @@ fn analyzeMinMax(...@@ -21984,28 +22515,31 @@ fn analyzeMinMax(
21984 break :refined orig_ty;22515 break :refined orig_ty;
21985 }22516 }
2198622517
21987 const refined_ty = if (orig_ty.zigTypeTag() == .Vector) blk: {22518 const refined_ty = if (orig_ty.zigTypeTag(mod) == .Vector) blk: {
21988 const elem_ty = orig_ty.childType();22519 const elem_ty = orig_ty.childType(mod);
21989 const len = orig_ty.vectorLen();22520 const len = orig_ty.vectorLen(mod);
2199022521
21991 if (len == 0) break :blk orig_ty;22522 if (len == 0) break :blk orig_ty;
21992 if (elem_ty.isAnyFloat()) break :blk orig_ty; // can't refine floats22523 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);
21995 var cur_max: Value = cur_min;22526 var cur_max: Value = cur_min;
21996 for (1..len) |idx| {22527 for (1..len) |idx| {
21997 const elem_val = try val.elemValue(mod, sema.arena, idx);22528 const elem_val = try val.elemValue(mod, idx);
21998 if (elem_val.isUndef()) break :blk orig_ty; // can't refine undef22529 if (elem_val.isUndef(mod)) break :blk orig_ty; // can't refine undef
21999 if (Value.order(elem_val, cur_min, target).compare(.lt)) cur_min = elem_val;22530 if (Value.order(elem_val, cur_min, mod).compare(.lt)) cur_min = elem_val;
22000 if (Value.order(elem_val, cur_max, target).compare(.gt)) cur_max = elem_val;22531 if (Value.order(elem_val, cur_max, mod).compare(.gt)) cur_max = elem_val;
22001 }22532 }
2200222533
22003 const refined_elem_ty = try Type.intFittingRange(target, sema.arena, cur_min, cur_max);22534 const refined_elem_ty = try mod.intFittingRange(cur_min, cur_max);
22004 break :blk try Type.vector(sema.arena, len, refined_elem_ty);22535 break :blk try mod.vectorType(.{
22536 .len = len,
22537 .child = refined_elem_ty.toIntern(),
22538 });
22005 } else blk: {22539 } else blk: {
22006 if (orig_ty.isAnyFloat()) break :blk orig_ty; // can't refine floats22540 if (orig_ty.isAnyFloat()) break :blk orig_ty; // can't refine floats
22007 if (val.isUndef()) break :blk orig_ty; // can't refine undef22541 if (val.isUndef(mod)) break :blk orig_ty; // can't refine undef
22008 break :blk try Type.intFittingRange(target, sema.arena, val, val);22542 break :blk try mod.intFittingRange(val, val);
22009 };22543 };
2201022544
22011 // Apply the refined type to the current value - this isn't strictly necessary in the22545 // Apply the refined type to the current value - this isn't strictly necessary in the
...@@ -22016,7 +22550,7 @@ fn analyzeMinMax(...@@ -22016,7 +22550,7 @@ fn analyzeMinMax(
22016 if (std.debug.runtime_safety) {22550 if (std.debug.runtime_safety) {
22017 assert(try sema.intFitsInType(val, refined_ty, null));22551 assert(try sema.intFitsInType(val, refined_ty, null));
22018 }22552 }
22019 cur_minmax = try sema.addConstant(refined_ty, val);22553 cur_minmax = try sema.coerceInMemory(block, val, orig_ty, refined_ty, src);
22020 }22554 }
2202122555
22022 break :refined refined_ty;22556 break :refined refined_ty;
...@@ -22032,7 +22566,7 @@ fn analyzeMinMax(...@@ -22032,7 +22566,7 @@ fn analyzeMinMax(
22032 // If the comptime-known part is undef we can avoid emitting actual instructions later22566 // If the comptime-known part is undef we can avoid emitting actual instructions later
22033 const known_undef = if (cur_minmax) |operand| blk: {22567 const known_undef = if (cur_minmax) |operand| blk: {
22034 const val = (try sema.resolveMaybeUndefVal(operand)).?;22568 const val = (try sema.resolveMaybeUndefVal(operand)).?;
22035 break :blk val.isUndef();22569 break :blk val.isUndef(mod);
22036 } else false;22570 } else false;
2203722571
22038 if (cur_minmax == null) {22572 if (cur_minmax == null) {
...@@ -22061,29 +22595,32 @@ fn analyzeMinMax(...@@ -22061,29 +22595,32 @@ fn analyzeMinMax(
22061 // Finally, refine the type based on the comptime-known bound.22595 // Finally, refine the type based on the comptime-known bound.
22062 if (known_undef) break :refine; // can't refine undef22596 if (known_undef) break :refine; // can't refine undef
22063 const unrefined_ty = sema.typeOf(cur_minmax.?);22597 const unrefined_ty = sema.typeOf(cur_minmax.?);
22064 const is_vector = unrefined_ty.zigTypeTag() == .Vector;22598 const is_vector = unrefined_ty.zigTypeTag(mod) == .Vector;
22065 const comptime_elem_ty = if (is_vector) comptime_ty.childType() else comptime_ty;22599 const comptime_elem_ty = if (is_vector) comptime_ty.childType(mod) else comptime_ty;
22066 const unrefined_elem_ty = if (is_vector) unrefined_ty.childType() else unrefined_ty;22600 const unrefined_elem_ty = if (is_vector) unrefined_ty.childType(mod) else unrefined_ty;
2206722601
22068 if (unrefined_elem_ty.isAnyFloat()) break :refine; // we can't refine floats22602 if (unrefined_elem_ty.isAnyFloat()) break :refine; // we can't refine floats
2206922603
22070 // Compute the final bounds based on the runtime type and the comptime-known bound type22604 // Compute the final bounds based on the runtime type and the comptime-known bound type
22071 const min_val = switch (air_tag) {22605 const min_val = switch (air_tag) {
22072 .min => try unrefined_elem_ty.minInt(sema.arena, target),22606 .min => try unrefined_elem_ty.minInt(mod, unrefined_elem_ty),
22073 .max => try comptime_elem_ty.minInt(sema.arena, target), // @max(ct, rt) >= ct22607 .max => try comptime_elem_ty.minInt(mod, comptime_elem_ty), // @max(ct, rt) >= ct
22074 else => unreachable,22608 else => unreachable,
22075 };22609 };
22076 const max_val = switch (air_tag) {22610 const max_val = switch (air_tag) {
22077 .min => try comptime_elem_ty.maxInt(sema.arena, target), // @min(ct, rt) <= ct22611 .min => try comptime_elem_ty.maxInt(mod, comptime_elem_ty), // @min(ct, rt) <= ct
22078 .max => try unrefined_elem_ty.maxInt(sema.arena, target),22612 .max => try unrefined_elem_ty.maxInt(mod, unrefined_elem_ty),
22079 else => unreachable,22613 else => unreachable,
22080 };22614 };
2208122615
22082 // Find the smallest type which can contain these bounds22616 // 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
22085 const final_ty = if (is_vector)22619 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 })
22087 else22624 else
22088 final_elem_ty;22625 final_elem_ty;
2208922626
...@@ -22098,7 +22635,7 @@ fn analyzeMinMax(...@@ -22098,7 +22635,7 @@ fn analyzeMinMax(
2209822635
22099fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !Air.Inst.Ref {22636fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !Air.Inst.Ref {
22100 const mod = sema.mod;22637 const mod = sema.mod;
22101 const info = sema.typeOf(ptr).ptrInfo().data;22638 const info = sema.typeOf(ptr).ptrInfo(mod);
22102 if (info.size == .One) {22639 if (info.size == .One) {
22103 // Already an array pointer.22640 // Already an array pointer.
22104 return ptr;22641 return ptr;
...@@ -22132,8 +22669,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22132,8 +22669,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22132 const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr);22669 const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr);
22133 const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr);22670 const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr);
22134 const target = sema.mod.getTarget();22671 const target = sema.mod.getTarget();
22672 const mod = sema.mod;
2213522673
22136 if (dest_ty.isConstPtr()) {22674 if (dest_ty.isConstPtr(mod)) {
22137 return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{});22675 return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{});
22138 }22676 }
2213922677
...@@ -22194,9 +22732,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22194,9 +22732,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22194 }22732 }
2219522733
22196 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {22734 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;
22198 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {22736 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)).?;
22200 const len = try sema.usizeCast(block, dest_src, len_u64);22738 const len = try sema.usizeCast(block, dest_src, len_u64);
22201 for (0..len) |i| {22739 for (0..len) |i| {
22202 const elem_index = try sema.addIntUnsigned(Type.usize, i);22740 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...@@ -22239,12 +22777,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22239 // lowering. The AIR instruction requires pointers with element types of22777 // lowering. The AIR instruction requires pointers with element types of
22240 // equal ABI size.22778 // 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) {
22243 return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the source or destination iterable is a tuple", .{});22781 return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the source or destination iterable is a tuple", .{});
22244 }22782 }
2224522783
22246 const dest_elem_ty = dest_ty.elemType2();22784 const dest_elem_ty = dest_ty.elemType2(mod);
22247 const src_elem_ty = src_ty.elemType2();22785 const src_elem_ty = src_ty.elemType2(mod);
22248 if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src)) {22786 if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src)) {
22249 return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the element types have different ABI sizes", .{});22787 return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the element types have different ABI sizes", .{});
22250 }22788 }
...@@ -22255,7 +22793,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22255,7 +22793,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22255 var new_dest_ptr = dest_ptr;22793 var new_dest_ptr = dest_ptr;
22256 var new_src_ptr = src_ptr;22794 var new_src_ptr = src_ptr;
22257 if (len_val) |val| {22795 if (len_val) |val| {
22258 const len = val.toUnsignedInt(target);22796 const len = val.toUnsignedInt(mod);
22259 if (len == 0) {22797 if (len == 0) {
22260 // This AIR instruction guarantees length > 0 if it is comptime-known.22798 // This AIR instruction guarantees length > 0 if it is comptime-known.
22261 return;22799 return;
...@@ -22268,7 +22806,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22268,7 +22806,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22268 // Change the src from slice to a many pointer, to avoid multiple ptr22806 // Change the src from slice to a many pointer, to avoid multiple ptr
22269 // slice extractions in AIR instructions.22807 // slice extractions in AIR instructions.
22270 const new_src_ptr_ty = sema.typeOf(new_src_ptr);22808 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)) {
22272 new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);22810 new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
22273 }22811 }
22274 } else if (dest_len == .none and len_val == null) {22812 } 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...@@ -22276,7 +22814,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22276 const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr);22814 const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr);
22277 new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false);22815 new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false);
22278 const new_src_ptr_ty = sema.typeOf(new_src_ptr);22816 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)) {
22280 new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);22818 new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
22281 }22819 }
22282 }22820 }
...@@ -22295,14 +22833,30 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22295,14 +22833,30 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22295 // Extract raw pointer from dest slice. The AIR instructions could support them, but22833 // Extract raw pointer from dest slice. The AIR instructions could support them, but
22296 // it would cause redundant machine code instructions.22834 // it would cause redundant machine code instructions.
22297 const new_dest_ptr_ty = sema.typeOf(new_dest_ptr);22835 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))
22299 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)22837 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
22300 else22838 else if (new_dest_ptr_ty.ptrSize(mod) == .One) ptr: {
22301 new_dest_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
22303 // ok1: dest >= src + len22857 // ok1: dest >= src + len
22304 // ok2: src >= dest + len22858 // 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);
22306 const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src);22860 const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src);
22307 const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len);22861 const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len);
22308 const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len);22862 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...@@ -22320,6 +22874,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22320}22874}
2232122875
22322fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {22876fn 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;
22323 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;22880 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
22324 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;22881 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
22325 const src = inst_data.src();22882 const src = inst_data.src();
...@@ -22330,25 +22887,24 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22330,25 +22887,24 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22330 const dest_ptr_ty = sema.typeOf(dest_ptr);22887 const dest_ptr_ty = sema.typeOf(dest_ptr);
22331 try checkMemOperand(sema, block, dest_src, dest_ptr_ty);22888 try checkMemOperand(sema, block, dest_src, dest_ptr_ty);
2233222889
22333 if (dest_ptr_ty.isConstPtr()) {22890 if (dest_ptr_ty.isConstPtr(mod)) {
22334 return sema.fail(block, dest_src, "cannot memset constant pointer", .{});22891 return sema.fail(block, dest_src, "cannot memset constant pointer", .{});
22335 }22892 }
2233622893
22337 const dest_elem_ty = dest_ptr_ty.elemType2();22894 const dest_elem_ty = dest_ptr_ty.elemType2(mod);
22338 const target = sema.mod.getTarget();
2233922895
22340 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: {22896 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);
22342 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse22898 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse
22343 break :rs dest_src;22899 break :rs dest_src;
22344 const len_u64 = (try len_val.getUnsignedIntAdvanced(target, sema)).?;22900 const len_u64 = (try len_val.getUnsignedIntAdvanced(mod, sema)).?;
22345 const len = try sema.usizeCast(block, dest_src, len_u64);22901 const len = try sema.usizeCast(block, dest_src, len_u64);
22346 if (len == 0) {22902 if (len == 0) {
22347 // This AIR instruction guarantees length > 0 if it is comptime-known.22903 // This AIR instruction guarantees length > 0 if it is comptime-known.
22348 return;22904 return;
22349 }22905 }
2235022906
22351 if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src;22907 if (!ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
22352 if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| {22908 if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| {
22353 for (0..len) |i| {22909 for (0..len) |i| {
22354 const elem_index = try sema.addIntUnsigned(Type.usize, i);22910 const elem_index = try sema.addIntUnsigned(Type.usize, i);
...@@ -22426,6 +22982,7 @@ fn zirVarExtended(...@@ -22426,6 +22982,7 @@ fn zirVarExtended(
22426 block: *Block,22982 block: *Block,
22427 extended: Zir.Inst.Extended.InstData,22983 extended: Zir.Inst.Extended.InstData,
22428) CompileError!Air.Inst.Ref {22984) CompileError!Air.Inst.Ref {
22985 const mod = sema.mod;
22429 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);22986 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
22430 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };22987 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
22431 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };22988 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
...@@ -22461,47 +23018,33 @@ fn zirVarExtended(...@@ -22461,47 +23018,33 @@ fn zirVarExtended(
22461 else23018 else
22462 uncasted_init;23019 uncasted_init;
2246323020
22464 break :blk (try sema.resolveMaybeUndefVal(init)) orelse23021 break :blk ((try sema.resolveMaybeUndefVal(init)) orelse
22465 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known");23022 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known")).toIntern();
22466 } else Value.initTag(.unreachable_value);23023 } else .none;
2246723024
22468 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);23025 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2246923026
22470 const new_var = try sema.gpa.create(Module.Var);23027 return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{
22471 errdefer sema.gpa.destroy(new_var);23028 .ty = var_ty.toIntern(),
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,
22479 .init = init_val,23029 .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,
22480 .is_extern = small.is_extern,23035 .is_extern = small.is_extern,
22481 .is_mutable = true,
22482 .is_threadlocal = small.is_threadlocal,23036 .is_threadlocal = small.is_threadlocal,
22483 .is_weak_linkage = false,23037 } })).toValue());
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;
22496}23038}
2249723039
22498fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {23040fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
22499 const tracy = trace(@src());23041 const tracy = trace(@src());
22500 defer tracy.end();23042 defer tracy.end();
2250123043
23044 const mod = sema.mod;
22502 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;23045 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
22503 const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);23046 const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
22504 const target = sema.mod.getTarget();23047 const target = mod.getTarget();
2250523048
22506 const align_src: LazySrcLoc = .{ .node_offset_fn_type_align = inst_data.src_node };23049 const align_src: LazySrcLoc = .{ .node_offset_fn_type_align = inst_data.src_node };
22507 const addrspace_src: LazySrcLoc = .{ .node_offset_fn_type_addrspace = inst_data.src_node };23050 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...@@ -22532,10 +23075,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22532 extra_index += body.len;23075 extra_index += body.len;
2253323076
22534 const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u29, "alignment must be comptime-known");23077 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()) {
22536 break :blk null;23079 break :blk null;
22537 }23080 }
22538 const alignment = @intCast(u32, val.toUnsignedInt(target));23081 const alignment = @intCast(u32, val.toUnsignedInt(mod));
22539 try sema.validateAlign(block, align_src, alignment);23082 try sema.validateAlign(block, align_src, alignment);
22540 if (alignment == target_util.defaultFunctionAlignment(target)) {23083 if (alignment == target_util.defaultFunctionAlignment(target)) {
22541 break :blk 0;23084 break :blk 0;
...@@ -22551,7 +23094,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -22551,7 +23094,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22551 },23094 },
22552 else => |e| return e,23095 else => |e| return e,
22553 };23096 };
22554 const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target));23097 const alignment = @intCast(u32, align_tv.val.toUnsignedInt(mod));
22555 try sema.validateAlign(block, align_src, alignment);23098 try sema.validateAlign(block, align_src, alignment);
22556 if (alignment == target_util.defaultFunctionAlignment(target)) {23099 if (alignment == target_util.defaultFunctionAlignment(target)) {
22557 break :blk 0;23100 break :blk 0;
...@@ -22568,10 +23111,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -22568,10 +23111,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2256823111
22569 const addrspace_ty = try sema.getBuiltinType("AddressSpace");23112 const addrspace_ty = try sema.getBuiltinType("AddressSpace");
22570 const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, "addrespace must be comptime-known");23113 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()) {
22572 break :blk null;23115 break :blk null;
22573 }23116 }
22574 break :blk val.toEnum(std.builtin.AddressSpace);23117 break :blk mod.toEnum(std.builtin.AddressSpace, val);
22575 } else if (extra.data.bits.has_addrspace_ref) blk: {23118 } else if (extra.data.bits.has_addrspace_ref) blk: {
22576 const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);23119 const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
22577 extra_index += 1;23120 extra_index += 1;
...@@ -22581,7 +23124,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -22581,7 +23124,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22581 },23124 },
22582 else => |e| return e,23125 else => |e| return e,
22583 };23126 };
22584 break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);23127 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
22585 } else target_util.defaultAddressSpace(target, .function);23128 } else target_util.defaultAddressSpace(target, .function);
2258623129
22587 const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: {23130 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...@@ -22590,16 +23133,16 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22590 const body = sema.code.extra[extra_index..][0..body_len];23133 const body = sema.code.extra[extra_index..][0..body_len];
22591 extra_index += body.len;23134 extra_index += body.len;
2259223135
22593 const ty = Type.initTag(.const_slice_u8);23136 const ty = Type.slice_const_u8;
22594 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");23137 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()) {
22596 break :blk FuncLinkSection{ .generic = {} };23139 break :blk FuncLinkSection{ .generic = {} };
22597 }23140 }
22598 break :blk FuncLinkSection{ .explicit = try val.toAllocatedBytes(ty, sema.arena, sema.mod) };23141 break :blk FuncLinkSection{ .explicit = try val.toIpString(ty, mod) };
22599 } else if (extra.data.bits.has_section_ref) blk: {23142 } else if (extra.data.bits.has_section_ref) blk: {
22600 const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);23143 const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
22601 extra_index += 1;23144 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) {
22603 error.GenericPoison => {23146 error.GenericPoison => {
22604 break :blk FuncLinkSection{ .generic = {} };23147 break :blk FuncLinkSection{ .generic = {} };
22605 },23148 },
...@@ -22616,10 +23159,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -22616,10 +23159,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2261623159
22617 const cc_ty = try sema.getBuiltinType("CallingConvention");23160 const cc_ty = try sema.getBuiltinType("CallingConvention");
22618 const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, "calling convention must be comptime-known");23161 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()) {
22620 break :blk null;23163 break :blk null;
22621 }23164 }
22622 break :blk val.toEnum(std.builtin.CallingConvention);23165 break :blk mod.toEnum(std.builtin.CallingConvention, val);
22623 } else if (extra.data.bits.has_cc_ref) blk: {23166 } else if (extra.data.bits.has_cc_ref) blk: {
22624 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);23167 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
22625 extra_index += 1;23168 extra_index += 1;
...@@ -22629,7 +23172,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -22629,7 +23172,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22629 },23172 },
22630 else => |e| return e,23173 else => |e| return e,
22631 };23174 };
22632 break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);23175 break :blk mod.toEnum(std.builtin.CallingConvention, cc_tv.val);
22633 } else if (sema.owner_decl.is_exported and has_body)23176 } else if (sema.owner_decl.is_exported and has_body)
22634 .C23177 .C
22635 else23178 else
...@@ -22642,20 +23185,18 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -22642,20 +23185,18 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22642 extra_index += body.len;23185 extra_index += body.len;
2264323186
22644 const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type, "return type must be comptime-known");23187 const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type, "return type must be comptime-known");
22645 var buffer: Value.ToTypeBuffer = undefined;23188 const ty = val.toType();
22646 const ty = try val.toType(&buffer).copy(sema.arena);
22647 break :blk ty;23189 break :blk ty;
22648 } else if (extra.data.bits.has_ret_ty_ref) blk: {23190 } else if (extra.data.bits.has_ret_ty_ref) blk: {
22649 const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);23191 const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
22650 extra_index += 1;23192 extra_index += 1;
22651 const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref, "return type must be comptime-known") catch |err| switch (err) {23193 const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref, "return type must be comptime-known") catch |err| switch (err) {
22652 error.GenericPoison => {23194 error.GenericPoison => {
22653 break :blk Type.initTag(.generic_poison);23195 break :blk Type.generic_poison;
22654 },23196 },
22655 else => |e| return e,23197 else => |e| return e,
22656 };23198 };
22657 var buffer: Value.ToTypeBuffer = undefined;23199 const ty = ret_ty_tv.val.toType();
22658 const ty = try ret_ty_tv.val.toType(&buffer).copy(sema.arena);
22659 break :blk ty;23200 break :blk ty;
22660 } else Type.void;23201 } else Type.void;
2266123202
...@@ -22727,13 +23268,14 @@ fn zirCDefine(...@@ -22727,13 +23268,14 @@ fn zirCDefine(
22727 block: *Block,23268 block: *Block,
22728 extended: Zir.Inst.Extended.InstData,23269 extended: Zir.Inst.Extended.InstData,
22729) CompileError!Air.Inst.Ref {23270) CompileError!Air.Inst.Ref {
23271 const mod = sema.mod;
22730 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;23272 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
22731 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };23273 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
22732 const val_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };23274 const val_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
2273323275
22734 const name = try sema.resolveConstString(block, name_src, extra.lhs, "name of macro being undefined must be comptime-known");23276 const name = try sema.resolveConstString(block, name_src, extra.lhs, "name of macro being undefined must be comptime-known");
22735 const rhs = try sema.resolveInst(extra.rhs);23277 const rhs = try sema.resolveInst(extra.rhs);
22736 if (sema.typeOf(rhs).zigTypeTag() != .Void) {23278 if (sema.typeOf(rhs).zigTypeTag(mod) != .Void) {
22737 const value = try sema.resolveConstString(block, val_src, extra.rhs, "value of macro being undefined must be comptime-known");23279 const value = try sema.resolveConstString(block, val_src, extra.rhs, "value of macro being undefined must be comptime-known");
22738 try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value });23280 try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value });
22739 } else {23281 } else {
...@@ -22799,27 +23341,29 @@ fn resolvePrefetchOptions(...@@ -22799,27 +23341,29 @@ fn resolvePrefetchOptions(
22799 src: LazySrcLoc,23341 src: LazySrcLoc,
22800 zir_ref: Zir.Inst.Ref,23342 zir_ref: Zir.Inst.Ref,
22801) CompileError!std.builtin.PrefetchOptions {23343) CompileError!std.builtin.PrefetchOptions {
23344 const mod = sema.mod;
23345 const gpa = sema.gpa;
23346 const ip = &mod.intern_pool;
22802 const options_ty = try sema.getBuiltinType("PrefetchOptions");23347 const options_ty = try sema.getBuiltinType("PrefetchOptions");
22803 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);23348 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);
22804 const target = sema.mod.getTarget();
2280523349
22806 const rw_src = sema.maybeOptionsSrc(block, src, "rw");23350 const rw_src = sema.maybeOptionsSrc(block, src, "rw");
22807 const locality_src = sema.maybeOptionsSrc(block, src, "locality");23351 const locality_src = sema.maybeOptionsSrc(block, src, "locality");
22808 const cache_src = sema.maybeOptionsSrc(block, src, "cache");23352 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);
22811 const rw_val = try sema.resolveConstValue(block, rw_src, rw, "prefetch read/write must be comptime-known");23355 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);
22814 const locality_val = try sema.resolveConstValue(block, locality_src, locality, "prefetch locality must be comptime-known");23358 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);
22817 const cache_val = try sema.resolveConstValue(block, cache_src, cache, "prefetch cache must be comptime-known");23361 const cache_val = try sema.resolveConstValue(block, cache_src, cache, "prefetch cache must be comptime-known");
2281823362
22819 return std.builtin.PrefetchOptions{23363 return std.builtin.PrefetchOptions{
22820 .rw = rw_val.toEnum(std.builtin.PrefetchOptions.Rw),23364 .rw = mod.toEnum(std.builtin.PrefetchOptions.Rw, rw_val),
22821 .locality = @intCast(u2, locality_val.toUnsignedInt(target)),23365 .locality = @intCast(u2, locality_val.toUnsignedInt(mod)),
22822 .cache = cache_val.toEnum(std.builtin.PrefetchOptions.Cache),23366 .cache = mod.toEnum(std.builtin.PrefetchOptions.Cache, cache_val),
22823 };23367 };
22824}23368}
2282523369
...@@ -22862,34 +23406,40 @@ fn resolveExternOptions(...@@ -22862,34 +23406,40 @@ fn resolveExternOptions(
22862 block: *Block,23406 block: *Block,
22863 src: LazySrcLoc,23407 src: LazySrcLoc,
22864 zir_ref: Zir.Inst.Ref,23408 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;
22866 const options_inst = try sema.resolveInst(zir_ref);23418 const options_inst = try sema.resolveInst(zir_ref);
22867 const extern_options_ty = try sema.getBuiltinType("ExternOptions");23419 const extern_options_ty = try sema.getBuiltinType("ExternOptions");
22868 const options = try sema.coerce(block, extern_options_ty, options_inst, src);23420 const options = try sema.coerce(block, extern_options_ty, options_inst, src);
22869 const mod = sema.mod;
2287023421
22871 const name_src = sema.maybeOptionsSrc(block, src, "name");23422 const name_src = sema.maybeOptionsSrc(block, src, "name");
22872 const library_src = sema.maybeOptionsSrc(block, src, "library");23423 const library_src = sema.maybeOptionsSrc(block, src, "library");
22873 const linkage_src = sema.maybeOptionsSrc(block, src, "linkage");23424 const linkage_src = sema.maybeOptionsSrc(block, src, "linkage");
22874 const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local");23425 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);
22877 const name_val = try sema.resolveConstValue(block, name_src, name_ref, "name of the extern symbol must be comptime-known");23428 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);
22881 const library_name_val = try sema.resolveConstValue(block, library_src, library_name_inst, "library in which extern symbol is must be comptime-known");23432 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);
22884 const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_ref, "linkage of the extern symbol must be comptime-known");23435 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);
22888 const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime-known");23439 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: {23441 const library_name = if (library_name_val.optionalValue(mod)) |payload| blk: {
22891 const payload = library_name_val.castTag(.opt_payload).?.data;23442 const library_name = try payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
22892 const library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod);
22893 if (library_name.len == 0) {23443 if (library_name.len == 0) {
22894 return sema.fail(block, library_src, "library name cannot be empty", .{});23444 return sema.fail(block, library_src, "library name cannot be empty", .{});
22895 }23445 }
...@@ -22904,9 +23454,9 @@ fn resolveExternOptions(...@@ -22904,9 +23454,9 @@ fn resolveExternOptions(
22904 return sema.fail(block, linkage_src, "extern symbol must use strong or weak linkage", .{});23454 return sema.fail(block, linkage_src, "extern symbol must use strong or weak linkage", .{});
22905 }23455 }
2290623456
22907 return std.builtin.ExternOptions{23457 return .{
22908 .name = name,23458 .name = try ip.getOrPutString(gpa, name),
22909 .library_name = library_name,23459 .library_name = try ip.getOrPutStringOpt(gpa, library_name),
22910 .linkage = linkage,23460 .linkage = linkage,
22911 .is_thread_local = is_thread_local_val.toBool(),23461 .is_thread_local = is_thread_local_val.toBool(),
22912 };23462 };
...@@ -22917,21 +23467,21 @@ fn zirBuiltinExtern(...@@ -22917,21 +23467,21 @@ fn zirBuiltinExtern(
22917 block: *Block,23467 block: *Block,
22918 extended: Zir.Inst.Extended.InstData,23468 extended: Zir.Inst.Extended.InstData,
22919) CompileError!Air.Inst.Ref {23469) CompileError!Air.Inst.Ref {
23470 const mod = sema.mod;
22920 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;23471 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
22921 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };23472 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
22922 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };23473 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
2292323474
22924 var ty = try sema.resolveType(block, ty_src, extra.lhs);23475 var ty = try sema.resolveType(block, ty_src, extra.lhs);
22925 if (!ty.isPtrAtRuntime()) {23476 if (!ty.isPtrAtRuntime(mod)) {
22926 return sema.fail(block, ty_src, "expected (optional) pointer", .{});23477 return sema.fail(block, ty_src, "expected (optional) pointer", .{});
22927 }23478 }
22928 if (!try sema.validateExternType(ty.childType(), .other)) {23479 if (!try sema.validateExternType(ty.childType(mod), .other)) {
22929 const msg = msg: {23480 const msg = msg: {
22930 const mod = sema.mod;
22931 const msg = try sema.errMsg(block, ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)});23481 const msg = try sema.errMsg(block, ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)});
22932 errdefer msg.destroy(sema.gpa);23482 errdefer msg.destroy(sema.gpa);
22933 const src_decl = sema.mod.declPtr(block.src_decl);23483 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);
22935 break :msg msg;23485 break :msg msg;
22936 };23486 };
22937 return sema.failWithOwnedErrorMsg(msg);23487 return sema.failWithOwnedErrorMsg(msg);
...@@ -22945,52 +23495,51 @@ fn zirBuiltinExtern(...@@ -22945,52 +23495,51 @@ fn zirBuiltinExtern(
22945 else => |e| return e,23495 else => |e| return e,
22946 };23496 };
2294723497
22948 if (options.linkage == .Weak and !ty.ptrAllowsZero()) {23498 if (options.linkage == .Weak and !ty.ptrAllowsZero(mod)) {
22949 ty = try Type.optional(sema.arena, ty);23499 ty = try Type.optional(sema.arena, ty, mod);
22950 }23500 }
2295123501
22952 // TODO check duplicate extern23502 // 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);23504 const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, null);
22955 errdefer sema.mod.destroyDecl(new_decl_index);23505 errdefer mod.destroyDecl(new_decl_index);
22956 const new_decl = sema.mod.declPtr(new_decl_index);23506 const new_decl = mod.declPtr(new_decl_index);
22957 new_decl.name = try sema.gpa.dupeZ(u8, options.name);23507 new_decl.name = options.name;
2295823508
22959 {23509 {
22960 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);23510 const new_var = try mod.intern(.{ .variable = .{
22961 errdefer new_decl_arena.deinit();23511 .ty = ty.toIntern(),
22962 const new_decl_arena_allocator = new_decl_arena.allocator();23512 .init = .none,
2296323513 .decl = sema.owner_decl_index,
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),
22968 .is_extern = true,23514 .is_extern = true,
22969 .is_mutable = false,23515 .is_const = true,
22970 .is_threadlocal = options.is_thread_local,23516 .is_threadlocal = options.is_thread_local,
22971 .is_weak_linkage = options.linkage == .Weak,23517 .is_weak_linkage = options.linkage == .Weak,
22972 .lib_name = null,23518 } });
22973 };
2297423519
22975 new_decl.src_line = sema.owner_decl.src_line;23520 new_decl.src_line = sema.owner_decl.src_line;
22976 // We only access this decl through the decl_ref with the correct type created23521 // We only access this decl through the decl_ref with the correct type created
22977 // below, so this type doesn't matter23522 // below, so this type doesn't matter
22978 new_decl.ty = Type.Tag.init(.anyopaque);23523 new_decl.ty = ty;
22979 new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);23524 new_decl.val = new_var.toValue();
22980 new_decl.@"align" = 0;23525 new_decl.@"align" = 0;
22981 new_decl.@"linksection" = null;23526 new_decl.@"linksection" = .none;
22982 new_decl.has_tv = true;23527 new_decl.has_tv = true;
22983 new_decl.analysis = .complete;23528 new_decl.analysis = .complete;
22984 new_decl.generation = sema.mod.generation;23529 new_decl.generation = mod.generation;
22985
22986 try new_decl.finalizeNewArena(&new_decl_arena);
22987 }23530 }
2298823531
22989 try sema.mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);23532 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
22990 try sema.ensureDeclAnalyzed(new_decl_index);23533 try sema.ensureDeclAnalyzed(new_decl_index);
2299123534
22992 const ref = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);23535 return sema.addConstant(ty, try mod.getCoerced((try mod.intern(.{ .ptr = .{
22993 return sema.addConstant(ty, ref);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));
22994}23543}
2299523544
22996fn zirWorkItem(23545fn zirWorkItem(
...@@ -23073,7 +23622,7 @@ fn validateVarType(...@@ -23073,7 +23622,7 @@ fn validateVarType(
23073 const msg = try sema.errMsg(block, src, "extern variable cannot have type '{}'", .{var_ty.fmt(mod)});23622 const msg = try sema.errMsg(block, src, "extern variable cannot have type '{}'", .{var_ty.fmt(mod)});
23074 errdefer msg.destroy(sema.gpa);23623 errdefer msg.destroy(sema.gpa);
23075 const src_decl = mod.declPtr(block.src_decl);23624 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);
23077 break :msg msg;23626 break :msg msg;
23078 };23627 };
23079 return sema.failWithOwnedErrorMsg(msg);23628 return sema.failWithOwnedErrorMsg(msg);
...@@ -23086,8 +23635,8 @@ fn validateVarType(...@@ -23086,8 +23635,8 @@ fn validateVarType(
23086 errdefer msg.destroy(sema.gpa);23635 errdefer msg.destroy(sema.gpa);
2308723636
23088 const src_decl = mod.declPtr(block.src_decl);23637 const src_decl = mod.declPtr(block.src_decl);
23089 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl), var_ty);23638 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl, mod), var_ty);
23090 if (var_ty.zigTypeTag() == .ComptimeInt or var_ty.zigTypeTag() == .ComptimeFloat) {23639 if (var_ty.zigTypeTag(mod) == .ComptimeInt or var_ty.zigTypeTag(mod) == .ComptimeFloat) {
23091 try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{});23640 try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{});
23092 }23641 }
2309323642
...@@ -23101,8 +23650,9 @@ fn validateRunTimeType(...@@ -23101,8 +23650,9 @@ fn validateRunTimeType(
23101 var_ty: Type,23650 var_ty: Type,
23102 is_extern: bool,23651 is_extern: bool,
23103) CompileError!bool {23652) CompileError!bool {
23653 const mod = sema.mod;
23104 var ty = var_ty;23654 var ty = var_ty;
23105 while (true) switch (ty.zigTypeTag()) {23655 while (true) switch (ty.zigTypeTag(mod)) {
23106 .Bool,23656 .Bool,
23107 .Int,23657 .Int,
23108 .Float,23658 .Float,
...@@ -23125,23 +23675,22 @@ fn validateRunTimeType(...@@ -23125,23 +23675,22 @@ fn validateRunTimeType(
23125 => return false,23675 => return false,
2312623676
23127 .Pointer => {23677 .Pointer => {
23128 const elem_ty = ty.childType();23678 const elem_ty = ty.childType(mod);
23129 switch (elem_ty.zigTypeTag()) {23679 switch (elem_ty.zigTypeTag(mod)) {
23130 .Opaque => return true,23680 .Opaque => return true,
23131 .Fn => return elem_ty.isFnOrHasRuntimeBits(),23681 .Fn => return elem_ty.isFnOrHasRuntimeBits(mod),
23132 else => ty = elem_ty,23682 else => ty = elem_ty,
23133 }23683 }
23134 },23684 },
23135 .Opaque => return is_extern,23685 .Opaque => return is_extern,
2313623686
23137 .Optional => {23687 .Optional => {
23138 var buf: Type.Payload.ElemType = undefined;23688 const child_ty = ty.optionalChild(mod);
23139 const child_ty = ty.optionalChild(&buf);
23140 return sema.validateRunTimeType(child_ty, is_extern);23689 return sema.validateRunTimeType(child_ty, is_extern);
23141 },23690 },
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
23146 .Struct, .Union => {23695 .Struct, .Union => {
23147 const resolved_ty = try sema.resolveTypeFields(ty);23696 const resolved_ty = try sema.resolveTypeFields(ty);
...@@ -23151,7 +23700,7 @@ fn validateRunTimeType(...@@ -23151,7 +23700,7 @@ fn validateRunTimeType(
23151 };23700 };
23152}23701}
2315323702
23154const TypeSet = std.HashMapUnmanaged(Type, void, Type.HashContext64, std.hash_map.default_max_load_percentage);23703const TypeSet = std.AutoHashMapUnmanaged(InternPool.Index, void);
2315523704
23156fn explainWhyTypeIsComptime(23705fn explainWhyTypeIsComptime(
23157 sema: *Sema,23706 sema: *Sema,
...@@ -23174,7 +23723,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -23174,7 +23723,7 @@ fn explainWhyTypeIsComptimeInner(
23174 type_set: *TypeSet,23723 type_set: *TypeSet,
23175) CompileError!void {23724) CompileError!void {
23176 const mod = sema.mod;23725 const mod = sema.mod;
23177 switch (ty.zigTypeTag()) {23726 switch (ty.zigTypeTag(mod)) {
23178 .Bool,23727 .Bool,
23179 .Int,23728 .Int,
23180 .Float,23729 .Float,
...@@ -23208,12 +23757,12 @@ fn explainWhyTypeIsComptimeInner(...@@ -23208,12 +23757,12 @@ fn explainWhyTypeIsComptimeInner(
23208 },23757 },
2320923758
23210 .Array, .Vector => {23759 .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);
23212 },23761 },
23213 .Pointer => {23762 .Pointer => {
23214 const elem_ty = ty.elemType2();23763 const elem_ty = ty.elemType2(mod);
23215 if (elem_ty.zigTypeTag() == .Fn) {23764 if (elem_ty.zigTypeTag(mod) == .Fn) {
23216 const fn_info = elem_ty.fnInfo();23765 const fn_info = mod.typeToFunc(elem_ty).?;
23217 if (fn_info.is_generic) {23766 if (fn_info.is_generic) {
23218 try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{});23767 try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{});
23219 }23768 }
...@@ -23221,29 +23770,27 @@ fn explainWhyTypeIsComptimeInner(...@@ -23221,29 +23770,27 @@ fn explainWhyTypeIsComptimeInner(
23221 .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}),23770 .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}),
23222 else => {},23771 else => {},
23223 }23772 }
23224 if (fn_info.return_type.comptimeOnly()) {23773 if (fn_info.return_type.toType().comptimeOnly(mod)) {
23225 try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{});23774 try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{});
23226 }23775 }
23227 return;23776 return;
23228 }23777 }
23229 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.elemType(), type_set);23778 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(mod), type_set);
23230 },23779 },
2323123780
23232 .Optional => {23781 .Optional => {
23233 var buf: Type.Payload.ElemType = undefined;23782 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.optionalChild(mod), type_set);
23234 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.optionalChild(&buf), type_set);
23235 },23783 },
23236 .ErrorUnion => {23784 .ErrorUnion => {
23237 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.errorUnionPayload(), type_set);23785 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.errorUnionPayload(mod), type_set);
23238 },23786 },
2323923787
23240 .Struct => {23788 .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| {23791 if (mod.typeToStruct(ty)) |struct_obj| {
23244 const struct_obj = payload.data;
23245 for (struct_obj.fields.values(), 0..) |field, i| {23792 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, .{
23247 .index = i,23794 .index = i,
23248 .range = .type,23795 .range = .type,
23249 });23796 });
...@@ -23258,12 +23805,11 @@ fn explainWhyTypeIsComptimeInner(...@@ -23258,12 +23805,11 @@ fn explainWhyTypeIsComptimeInner(
23258 },23805 },
2325923806
23260 .Union => {23807 .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| {23810 if (mod.typeToUnion(ty)) |union_obj| {
23264 const union_obj = payload.data;
23265 for (union_obj.fields.values(), 0..) |field, i| {23811 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, .{
23267 .index = i,23813 .index = i,
23268 .range = .type,23814 .range = .type,
23269 });23815 });
...@@ -23295,7 +23841,8 @@ fn validateExternType(...@@ -23295,7 +23841,8 @@ fn validateExternType(
23295 ty: Type,23841 ty: Type,
23296 position: ExternPosition,23842 position: ExternPosition,
23297) !bool {23843) !bool {
23298 switch (ty.zigTypeTag()) {23844 const mod = sema.mod;
23845 switch (ty.zigTypeTag(mod)) {
23299 .Type,23846 .Type,
23300 .ComptimeFloat,23847 .ComptimeFloat,
23301 .ComptimeInt,23848 .ComptimeInt,
...@@ -23313,8 +23860,8 @@ fn validateExternType(...@@ -23313,8 +23860,8 @@ fn validateExternType(
23313 .Float,23860 .Float,
23314 .AnyFrame,23861 .AnyFrame,
23315 => return true,23862 => return true,
23316 .Pointer => return !(ty.isSlice() or try sema.typeRequiresComptime(ty)),23863 .Pointer => return !(ty.isSlice(mod) or try sema.typeRequiresComptime(ty)),
23317 .Int => switch (ty.intInfo(sema.mod.getTarget()).bits) {23864 .Int => switch (ty.intInfo(mod).bits) {
23318 8, 16, 32, 64, 128 => return true,23865 8, 16, 32, 64, 128 => return true,
23319 else => return false,23866 else => return false,
23320 },23867 },
...@@ -23323,20 +23870,18 @@ fn validateExternType(...@@ -23323,20 +23870,18 @@ fn validateExternType(
23323 const target = sema.mod.getTarget();23870 const target = sema.mod.getTarget();
23324 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.23871 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
23325 // The goal is to experiment with more integrated CPU/GPU code.23872 // 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)) {
23327 return true;23874 return true;
23328 }23875 }
23329 return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention());23876 return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(mod));
23330 },23877 },
23331 .Enum => {23878 .Enum => {
23332 var buf: Type.Payload.Bits = undefined;23879 return sema.validateExternType(ty.intTagType(mod), position);
23333 return sema.validateExternType(ty.intTagType(&buf), position);
23334 },23880 },
23335 .Struct, .Union => switch (ty.containerLayout()) {23881 .Struct, .Union => switch (ty.containerLayout(mod)) {
23336 .Extern => return true,23882 .Extern => return true,
23337 .Packed => {23883 .Packed => {
23338 const target = sema.mod.getTarget();23884 const bit_size = try ty.bitSizeAdvanced(mod, sema);
23339 const bit_size = try ty.bitSizeAdvanced(target, sema);
23340 switch (bit_size) {23885 switch (bit_size) {
23341 8, 16, 32, 64, 128 => return true,23886 8, 16, 32, 64, 128 => return true,
23342 else => return false,23887 else => return false,
...@@ -23346,10 +23891,10 @@ fn validateExternType(...@@ -23346,10 +23891,10 @@ fn validateExternType(
23346 },23891 },
23347 .Array => {23892 .Array => {
23348 if (position == .ret_ty or position == .param_ty) return false;23893 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);
23350 },23895 },
23351 .Vector => return sema.validateExternType(ty.elemType2(), .element),23896 .Vector => return sema.validateExternType(ty.elemType2(mod), .element),
23352 .Optional => return ty.isPtrLikeOptional(),23897 .Optional => return ty.isPtrLikeOptional(mod),
23353 }23898 }
23354}23899}
2335523900
...@@ -23361,7 +23906,7 @@ fn explainWhyTypeIsNotExtern(...@@ -23361,7 +23906,7 @@ fn explainWhyTypeIsNotExtern(
23361 position: ExternPosition,23906 position: ExternPosition,
23362) CompileError!void {23907) CompileError!void {
23363 const mod = sema.mod;23908 const mod = sema.mod;
23364 switch (ty.zigTypeTag()) {23909 switch (ty.zigTypeTag(mod)) {
23365 .Opaque,23910 .Opaque,
23366 .Bool,23911 .Bool,
23367 .Float,23912 .Float,
...@@ -23380,17 +23925,17 @@ fn explainWhyTypeIsNotExtern(...@@ -23380,17 +23925,17 @@ fn explainWhyTypeIsNotExtern(
23380 => return,23925 => return,
2338123926
23382 .Pointer => {23927 .Pointer => {
23383 if (ty.isSlice()) {23928 if (ty.isSlice(mod)) {
23384 try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{});23929 try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{});
23385 } else {23930 } else {
23386 const pointee_ty = ty.childType();23931 const pointee_ty = ty.childType(mod);
23387 try mod.errNoteNonLazy(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(sema.mod)});23932 try mod.errNoteNonLazy(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(sema.mod)});
23388 try sema.explainWhyTypeIsComptime(msg, src_loc, pointee_ty);23933 try sema.explainWhyTypeIsComptime(msg, src_loc, pointee_ty);
23389 }23934 }
23390 },23935 },
23391 .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}),23936 .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}),
23392 .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}),23937 .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)) {
23394 try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{});23939 try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{});
23395 } else {23940 } else {
23396 try mod.errNoteNonLazy(src_loc, msg, "only integers with 8, 16, 32, 64 and 128 bits are extern compatible", .{});23941 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(...@@ -23401,7 +23946,7 @@ fn explainWhyTypeIsNotExtern(
23401 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});23946 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
23402 return;23947 return;
23403 }23948 }
23404 switch (ty.fnCallingConvention()) {23949 switch (ty.fnCallingConvention(mod)) {
23405 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),23950 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),
23406 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),23951 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),
23407 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),23952 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),
...@@ -23409,8 +23954,7 @@ fn explainWhyTypeIsNotExtern(...@@ -23409,8 +23954,7 @@ fn explainWhyTypeIsNotExtern(
23409 }23954 }
23410 },23955 },
23411 .Enum => {23956 .Enum => {
23412 var buf: Type.Payload.Bits = undefined;23957 const tag_ty = ty.intTagType(mod);
23413 const tag_ty = ty.intTagType(&buf);
23414 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});23958 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
23415 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);23959 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
23416 },23960 },
...@@ -23422,17 +23966,17 @@ fn explainWhyTypeIsNotExtern(...@@ -23422,17 +23966,17 @@ fn explainWhyTypeIsNotExtern(
23422 } else if (position == .param_ty) {23966 } else if (position == .param_ty) {
23423 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});23967 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
23424 }23968 }
23425 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element);23969 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element);
23426 },23970 },
23427 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element),23971 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element),
23428 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),23972 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
23429 }23973 }
23430}23974}
2343123975
23432/// Returns true if `ty` is allowed in packed types.23976/// Returns true if `ty` is allowed in packed types.
23433/// Does *NOT* require `ty` to be resolved in any way.23977/// Does *NOT* require `ty` to be resolved in any way.
23434fn validatePackedType(ty: Type) bool {23978fn validatePackedType(ty: Type, mod: *Module) bool {
23435 switch (ty.zigTypeTag()) {23979 switch (ty.zigTypeTag(mod)) {
23436 .Type,23980 .Type,
23437 .ComptimeFloat,23981 .ComptimeFloat,
23438 .ComptimeInt,23982 .ComptimeInt,
...@@ -23448,7 +23992,7 @@ fn validatePackedType(ty: Type) bool {...@@ -23448,7 +23992,7 @@ fn validatePackedType(ty: Type) bool {
23448 .Fn,23992 .Fn,
23449 .Array,23993 .Array,
23450 => return false,23994 => return false,
23451 .Optional => return ty.isPtrLikeOptional(),23995 .Optional => return ty.isPtrLikeOptional(mod),
23452 .Void,23996 .Void,
23453 .Bool,23997 .Bool,
23454 .Float,23998 .Float,
...@@ -23456,8 +24000,8 @@ fn validatePackedType(ty: Type) bool {...@@ -23456,8 +24000,8 @@ fn validatePackedType(ty: Type) bool {
23456 .Vector,24000 .Vector,
23457 .Enum,24001 .Enum,
23458 => return true,24002 => return true,
23459 .Pointer => return !ty.isSlice(),24003 .Pointer => return !ty.isSlice(mod),
23460 .Struct, .Union => return ty.containerLayout() == .Packed,24004 .Struct, .Union => return ty.containerLayout(mod) == .Packed,
23461 }24005 }
23462}24006}
2346324007
...@@ -23468,7 +24012,7 @@ fn explainWhyTypeIsNotPacked(...@@ -23468,7 +24012,7 @@ fn explainWhyTypeIsNotPacked(
23468 ty: Type,24012 ty: Type,
23469) CompileError!void {24013) CompileError!void {
23470 const mod = sema.mod;24014 const mod = sema.mod;
23471 switch (ty.zigTypeTag()) {24015 switch (ty.zigTypeTag(mod)) {
23472 .Void,24016 .Void,
23473 .Bool,24017 .Bool,
23474 .Float,24018 .Float,
...@@ -23616,7 +24160,6 @@ fn panicWithMsg(...@@ -23616,7 +24160,6 @@ fn panicWithMsg(
23616 msg_inst: Air.Inst.Ref,24160 msg_inst: Air.Inst.Ref,
23617) !void {24161) !void {
23618 const mod = sema.mod;24162 const mod = sema.mod;
23619 const arena = sema.arena;
2362024163
23621 if (!mod.backendSupportsFeature(.panic_fn)) {24164 if (!mod.backendSupportsFeature(.panic_fn)) {
23622 _ = try block.addNoOp(.trap);24165 _ = try block.addNoOp(.trap);
...@@ -23626,16 +24169,24 @@ fn panicWithMsg(...@@ -23626,16 +24169,24 @@ fn panicWithMsg(
23626 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");24169 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
23627 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);24170 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
23628 const target = mod.getTarget();24171 const target = mod.getTarget();
23629 const ptr_stack_trace_ty = try Type.ptr(arena, mod, .{24172 const ptr_stack_trace_ty = try mod.ptrType(.{
23630 .pointee_type = stack_trace_ty,24173 .child = stack_trace_ty.toIntern(),
23631 .@"addrspace" = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic24174 .flags = .{
24175 .address_space = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic
24176 },
23632 });24177 });
23633 const null_stack_trace = try sema.addConstant(24178 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
23634 try Type.optional(arena, ptr_stack_trace_ty),24179 const null_stack_trace = try sema.addConstant(opt_ptr_stack_trace_ty, (try mod.intern(.{ .opt = .{
23635 Value.null,24180 .ty = opt_ptr_stack_trace_ty.toIntern(),
23636 );24181 .val = .none,
23637 const args: [3]Air.Inst.Ref = .{ msg_inst, null_stack_trace, .null_value };24182 } })).toValue());
23638 try sema.callBuiltin(block, panic_fn, .auto, &args);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 });
23639}24190}
2364024191
23641fn panicUnwrapError(24192fn panicUnwrapError(
...@@ -23694,20 +24245,6 @@ fn panicIndexOutOfBounds(...@@ -23694,20 +24245,6 @@ fn panicIndexOutOfBounds(
23694 try sema.safetyCheckFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len });24245 try sema.safetyCheckFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len });
23695}24246}
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
23711fn panicInactiveUnionField(24248fn panicInactiveUnionField(
23712 sema: *Sema,24249 sema: *Sema,
23713 parent_block: *Block,24250 parent_block: *Block,
...@@ -23731,11 +24268,12 @@ fn panicSentinelMismatch(...@@ -23731,11 +24268,12 @@ fn panicSentinelMismatch(
23731 sentinel_index: Air.Inst.Ref,24268 sentinel_index: Air.Inst.Ref,
23732) !void {24269) !void {
23733 assert(!parent_block.is_comptime);24270 assert(!parent_block.is_comptime);
24271 const mod = sema.mod;
23734 const expected_sentinel_val = maybe_sentinel orelse return;24272 const expected_sentinel_val = maybe_sentinel orelse return;
23735 const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val);24273 const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val);
2373624274
23737 const ptr_ty = sema.typeOf(ptr);24275 const ptr_ty = sema.typeOf(ptr);
23738 const actual_sentinel = if (ptr_ty.isSlice())24276 const actual_sentinel = if (ptr_ty.isSlice(mod))
23739 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)24277 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)
23740 else blk: {24278 else blk: {
23741 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null);24279 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null);
...@@ -23743,7 +24281,7 @@ fn panicSentinelMismatch(...@@ -23743,7 +24281,7 @@ fn panicSentinelMismatch(
23743 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);24281 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);
23744 };24282 };
2374524283
23746 const ok = if (sentinel_ty.zigTypeTag() == .Vector) ok: {24284 const ok = if (sentinel_ty.zigTypeTag(mod) == .Vector) ok: {
23747 const eql =24285 const eql =
23748 try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);24286 try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
23749 break :ok try parent_block.addInst(.{24287 break :ok try parent_block.addInst(.{
...@@ -23753,7 +24291,7 @@ fn panicSentinelMismatch(...@@ -23753,7 +24291,7 @@ fn panicSentinelMismatch(
23753 .operation = .And,24291 .operation = .And,
23754 } },24292 } },
23755 });24293 });
23756 } else if (sentinel_ty.isSelfComparable(true))24294 } else if (sentinel_ty.isSelfComparable(mod, true))
23757 try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel)24295 try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel)
23758 else {24296 else {
23759 const panic_fn = try sema.getBuiltin("checkNonScalarSentinel");24297 const panic_fn = try sema.getBuiltin("checkNonScalarSentinel");
...@@ -23805,12 +24343,14 @@ fn safetyPanic(...@@ -23805,12 +24343,14 @@ fn safetyPanic(
23805 block: *Block,24343 block: *Block,
23806 panic_id: PanicId,24344 panic_id: PanicId,
23807) CompileError!void {24345) CompileError!void {
24346 const mod = sema.mod;
24347 const gpa = sema.gpa;
23808 const panic_messages_ty = try sema.getBuiltinType("panic_messages");24348 const panic_messages_ty = try sema.getBuiltinType("panic_messages");
23809 const msg_decl_index = (try sema.namespaceLookup(24349 const msg_decl_index = (try sema.namespaceLookup(
23810 block,24350 block,
23811 sema.src,24351 sema.src,
23812 panic_messages_ty.getNamespace().?,24352 panic_messages_ty.getNamespaceIndex(mod).unwrap().?,
23813 @tagName(panic_id),24353 try mod.intern_pool.getOrPutString(gpa, @tagName(panic_id)),
23814 )).?;24354 )).?;
2381524355
23816 const msg_inst = try sema.analyzeDeclVal(block, sema.src, msg_decl_index);24356 const msg_inst = try sema.analyzeDeclVal(block, sema.src, msg_decl_index);
...@@ -23842,37 +24382,38 @@ fn fieldVal(...@@ -23842,37 +24382,38 @@ fn fieldVal(
23842 block: *Block,24382 block: *Block,
23843 src: LazySrcLoc,24383 src: LazySrcLoc,
23844 object: Air.Inst.Ref,24384 object: Air.Inst.Ref,
23845 field_name: []const u8,24385 field_name: InternPool.NullTerminatedString,
23846 field_name_src: LazySrcLoc,24386 field_name_src: LazySrcLoc,
23847) CompileError!Air.Inst.Ref {24387) CompileError!Air.Inst.Ref {
23848 // When editing this function, note that there is corresponding logic to be edited24388 // When editing this function, note that there is corresponding logic to be edited
23849 // in `fieldPtr`. This function takes a value and returns a value.24389 // 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;
23852 const object_src = src; // TODO better source location24393 const object_src = src; // TODO better source location
23853 const object_ty = sema.typeOf(object);24394 const object_ty = sema.typeOf(object);
2385424395
23855 // Zig allows dereferencing a single pointer during field lookup. Note that24396 // Zig allows dereferencing a single pointer during field lookup. Note that
23856 // we don't actually need to generate the dereference some field lookups, like the24397 // we don't actually need to generate the dereference some field lookups, like the
23857 // length of arrays and other comptime operations.24398 // 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
23860 const inner_ty = if (is_pointer_to)24401 const inner_ty = if (is_pointer_to)
23861 object_ty.childType()24402 object_ty.childType(mod)
23862 else24403 else
23863 object_ty;24404 object_ty;
2386424405
23865 switch (inner_ty.zigTypeTag()) {24406 switch (inner_ty.zigTypeTag(mod)) {
23866 .Array => {24407 .Array => {
23867 if (mem.eql(u8, field_name, "len")) {24408 if (ip.stringEqlSlice(field_name, "len")) {
23868 return sema.addConstant(24409 return sema.addConstant(
23869 Type.usize,24410 Type.usize,
23870 try Value.Tag.int_u64.create(arena, inner_ty.arrayLen()),24411 try mod.intValue(Type.usize, inner_ty.arrayLen(mod)),
23871 );24412 );
23872 } else if (mem.eql(u8, field_name, "ptr") and is_pointer_to) {24413 } else if (ip.stringEqlSlice(field_name, "ptr") and is_pointer_to) {
23873 const ptr_info = object_ty.ptrInfo().data;24414 const ptr_info = object_ty.ptrInfo(mod);
23874 const result_ty = try Type.ptr(sema.arena, sema.mod, .{24415 const result_ty = try Type.ptr(sema.arena, mod, .{
23875 .pointee_type = ptr_info.pointee_type.childType(),24416 .pointee_type = ptr_info.pointee_type.childType(mod),
23876 .sentinel = ptr_info.sentinel,24417 .sentinel = ptr_info.sentinel,
23877 .@"align" = ptr_info.@"align",24418 .@"align" = ptr_info.@"align",
23878 .@"addrspace" = ptr_info.@"addrspace",24419 .@"addrspace" = ptr_info.@"addrspace",
...@@ -23889,21 +24430,21 @@ fn fieldVal(...@@ -23889,21 +24430,21 @@ fn fieldVal(
23889 return sema.fail(24430 return sema.fail(
23890 block,24431 block,
23891 field_name_src,24432 field_name_src,
23892 "no member named '{s}' in '{}'",24433 "no member named '{}' in '{}'",
23893 .{ field_name, object_ty.fmt(sema.mod) },24434 .{ field_name.fmt(ip), object_ty.fmt(mod) },
23894 );24435 );
23895 }24436 }
23896 },24437 },
23897 .Pointer => {24438 .Pointer => {
23898 const ptr_info = inner_ty.ptrInfo().data;24439 const ptr_info = inner_ty.ptrInfo(mod);
23899 if (ptr_info.size == .Slice) {24440 if (ptr_info.size == .Slice) {
23900 if (mem.eql(u8, field_name, "ptr")) {24441 if (ip.stringEqlSlice(field_name, "ptr")) {
23901 const slice = if (is_pointer_to)24442 const slice = if (is_pointer_to)
23902 try sema.analyzeLoad(block, src, object, object_src)24443 try sema.analyzeLoad(block, src, object, object_src)
23903 else24444 else
23904 object;24445 object;
23905 return sema.analyzeSlicePtr(block, object_src, slice, inner_ty);24446 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")) {
23907 const slice = if (is_pointer_to)24448 const slice = if (is_pointer_to)
23908 try sema.analyzeLoad(block, src, object, object_src)24449 try sema.analyzeLoad(block, src, object, object_src)
23909 else24450 else
...@@ -23913,8 +24454,8 @@ fn fieldVal(...@@ -23913,8 +24454,8 @@ fn fieldVal(
23913 return sema.fail(24454 return sema.fail(
23914 block,24455 block,
23915 field_name_src,24456 field_name_src,
23916 "no member named '{s}' in '{}'",24457 "no member named '{}' in '{}'",
23917 .{ field_name, object_ty.fmt(sema.mod) },24458 .{ field_name.fmt(ip), object_ty.fmt(mod) },
23918 );24459 );
23919 }24460 }
23920 }24461 }
...@@ -23926,66 +24467,74 @@ fn fieldVal(...@@ -23926,66 +24467,74 @@ fn fieldVal(
23926 object;24467 object;
2392724468
23928 const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?;24469 const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?;
23929 var to_type_buffer: Value.ToTypeBuffer = undefined;24470 const child_type = val.toType();
23930 const child_type = val.toType(&to_type_buffer);
2393124471
23932 switch (try child_type.zigTypeTagOrPoison()) {24472 switch (try child_type.zigTypeTagOrPoison(mod)) {
23933 .ErrorSet => {24473 .ErrorSet => {
23934 const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {24474 switch (ip.indexToKey(child_type.toIntern())) {
23935 if (payload.data.names.getEntry(field_name)) |entry| {24475 .error_set_type => |error_set_type| blk: {
23936 break :blk entry.key_ptr.*;24476 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;
23937 }24477 const msg = msg: {
23938 const msg = msg: {24478 const msg = try sema.errMsg(block, src, "no error named '{}' in '{}'", .{
23939 const msg = try sema.errMsg(block, src, "no error named '{s}' in '{}'", .{24479 field_name.fmt(ip), child_type.fmt(mod),
23940 field_name, child_type.fmt(sema.mod),24480 });
23941 });24481 errdefer msg.destroy(sema.gpa);
23942 errdefer msg.destroy(sema.gpa);24482 try sema.addDeclaredHereNote(msg, child_type);
23943 try sema.addDeclaredHereNote(msg, child_type);24483 break :msg msg;
23944 break :msg msg;24484 };
23945 };24485 return sema.failWithOwnedErrorMsg(msg);
23946 return sema.failWithOwnedErrorMsg(msg);24486 },
23947 } else (try sema.mod.getErrorValue(field_name)).key;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(24497 const error_set_type = if (!child_type.isAnyError(mod))
23950 if (!child_type.isAnyError())24498 child_type
23951 try child_type.copy(arena)24499 else
23952 else24500 try mod.singleErrorSetType(field_name);
23953 try Type.Tag.error_set_single.create(arena, name),24501 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
23954 try Value.Tag.@"error".create(arena, .{ .name = name }),24502 .ty = error_set_type.toIntern(),
23955 );24503 .name = field_name,
24504 } })).toValue());
23956 },24505 },
23957 .Union => {24506 .Union => {
23958 if (child_type.getNamespace()) |namespace| {24507 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
23959 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {24508 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
23960 return inst;24509 return inst;
23961 }24510 }
23962 }24511 }
23963 const union_ty = try sema.resolveTypeFields(child_type);24512 const union_ty = try sema.resolveTypeFields(child_type);
23964 if (union_ty.unionTagType()) |enum_ty| {24513 if (union_ty.unionTagType(mod)) |enum_ty| {
23965 if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| {24514 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index_usize| {
23966 const field_index = @intCast(u32, field_index_usize);24515 const field_index = @intCast(u32, field_index_usize);
23967 return sema.addConstant(24516 return sema.addConstant(
23968 enum_ty,24517 enum_ty,
23969 try Value.Tag.enum_field_index.create(sema.arena, field_index),24518 try mod.enumValueFieldIndex(enum_ty, field_index),
23970 );24519 );
23971 }24520 }
23972 }24521 }
23973 return sema.failWithBadMemberAccess(block, union_ty, field_name_src, field_name);24522 return sema.failWithBadMemberAccess(block, union_ty, field_name_src, field_name);
23974 },24523 },
23975 .Enum => {24524 .Enum => {
23976 if (child_type.getNamespace()) |namespace| {24525 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
23977 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {24526 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
23978 return inst;24527 return inst;
23979 }24528 }
23980 }24529 }
23981 const field_index_usize = child_type.enumFieldIndex(field_name) orelse24530 const field_index_usize = child_type.enumFieldIndex(field_name, mod) orelse
23982 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);24531 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
23983 const field_index = @intCast(u32, field_index_usize);24532 const field_index = @intCast(u32, field_index_usize);
23984 const enum_val = try Value.Tag.enum_field_index.create(arena, field_index);24533 const enum_val = try mod.enumValueFieldIndex(child_type, field_index);
23985 return sema.addConstant(try child_type.copy(arena), enum_val);24534 return sema.addConstant(child_type, enum_val);
23986 },24535 },
23987 .Struct, .Opaque => {24536 .Struct, .Opaque => {
23988 if (child_type.getNamespace()) |namespace| {24537 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
23989 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {24538 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
23990 return inst;24539 return inst;
23991 }24540 }
...@@ -23994,10 +24543,10 @@ fn fieldVal(...@@ -23994,10 +24543,10 @@ fn fieldVal(
23994 },24543 },
23995 else => {24544 else => {
23996 const msg = msg: {24545 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)});
23998 errdefer msg.destroy(sema.gpa);24547 errdefer msg.destroy(sema.gpa);
23999 if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{});24548 if (child_type.isSlice(mod)) 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", .{});24549 if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{});
24001 break :msg msg;24550 break :msg msg;
24002 };24551 };
24003 return sema.failWithOwnedErrorMsg(msg);24552 return sema.failWithOwnedErrorMsg(msg);
...@@ -24028,50 +24577,52 @@ fn fieldPtr(...@@ -24028,50 +24577,52 @@ fn fieldPtr(
24028 block: *Block,24577 block: *Block,
24029 src: LazySrcLoc,24578 src: LazySrcLoc,
24030 object_ptr: Air.Inst.Ref,24579 object_ptr: Air.Inst.Ref,
24031 field_name: []const u8,24580 field_name: InternPool.NullTerminatedString,
24032 field_name_src: LazySrcLoc,24581 field_name_src: LazySrcLoc,
24033 initializing: bool,24582 initializing: bool,
24034) CompileError!Air.Inst.Ref {24583) CompileError!Air.Inst.Ref {
24035 // When editing this function, note that there is corresponding logic to be edited24584 // When editing this function, note that there is corresponding logic to be edited
24036 // in `fieldVal`. This function takes a pointer and returns a pointer.24585 // in `fieldVal`. This function takes a pointer and returns a pointer.
2403724586
24587 const mod = sema.mod;
24588 const ip = &mod.intern_pool;
24038 const object_ptr_src = src; // TODO better source location24589 const object_ptr_src = src; // TODO better source location
24039 const object_ptr_ty = sema.typeOf(object_ptr);24590 const object_ptr_ty = sema.typeOf(object_ptr);
24040 const object_ty = switch (object_ptr_ty.zigTypeTag()) {24591 const object_ty = switch (object_ptr_ty.zigTypeTag(mod)) {
24041 .Pointer => object_ptr_ty.elemType(),24592 .Pointer => object_ptr_ty.childType(mod),
24042 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(sema.mod)}),24593 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(mod)}),
24043 };24594 };
2404424595
24045 // Zig allows dereferencing a single pointer during field lookup. Note that24596 // Zig allows dereferencing a single pointer during field lookup. Note that
24046 // we don't actually need to generate the dereference some field lookups, like the24597 // we don't actually need to generate the dereference some field lookups, like the
24047 // length of arrays and other comptime operations.24598 // 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
24050 const inner_ty = if (is_pointer_to)24601 const inner_ty = if (is_pointer_to)
24051 object_ty.childType()24602 object_ty.childType(mod)
24052 else24603 else
24053 object_ty;24604 object_ty;
2405424605
24055 switch (inner_ty.zigTypeTag()) {24606 switch (inner_ty.zigTypeTag(mod)) {
24056 .Array => {24607 .Array => {
24057 if (mem.eql(u8, field_name, "len")) {24608 if (ip.stringEqlSlice(field_name, "len")) {
24058 var anon_decl = try block.startAnonDecl();24609 var anon_decl = try block.startAnonDecl();
24059 defer anon_decl.deinit();24610 defer anon_decl.deinit();
24060 return sema.analyzeDeclRef(try anon_decl.finish(24611 return sema.analyzeDeclRef(try anon_decl.finish(
24061 Type.usize,24612 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)),
24063 0, // default alignment24614 0, // default alignment
24064 ));24615 ));
24065 } else {24616 } else {
24066 return sema.fail(24617 return sema.fail(
24067 block,24618 block,
24068 field_name_src,24619 field_name_src,
24069 "no member named '{s}' in '{}'",24620 "no member named '{}' in '{}'",
24070 .{ field_name, object_ty.fmt(sema.mod) },24621 .{ field_name.fmt(ip), object_ty.fmt(mod) },
24071 );24622 );
24072 }24623 }
24073 },24624 },
24074 .Pointer => if (inner_ty.isSlice()) {24625 .Pointer => if (inner_ty.isSlice(mod)) {
24075 const inner_ptr = if (is_pointer_to)24626 const inner_ptr = if (is_pointer_to)
24076 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)24627 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)
24077 else24628 else
...@@ -24079,47 +24630,44 @@ fn fieldPtr(...@@ -24079,47 +24630,44 @@ fn fieldPtr(
2407924630
24080 const attr_ptr_ty = if (is_pointer_to) object_ty else object_ptr_ty;24631 const attr_ptr_ty = if (is_pointer_to) object_ty else object_ptr_ty;
2408124632
24082 if (mem.eql(u8, field_name, "ptr")) {24633 if (ip.stringEqlSlice(field_name, "ptr")) {
24083 const buf = try sema.arena.create(Type.SlicePtrFieldTypeBuffer);24634 const slice_ptr_ty = inner_ty.slicePtrFieldType(mod);
24084 const slice_ptr_ty = inner_ty.slicePtrFieldType(buf);
2408524635
24086 const result_ty = try Type.ptr(sema.arena, sema.mod, .{24636 const result_ty = try Type.ptr(sema.arena, mod, .{
24087 .pointee_type = slice_ptr_ty,24637 .pointee_type = slice_ptr_ty,
24088 .mutable = attr_ptr_ty.ptrIsMutable(),24638 .mutable = attr_ptr_ty.ptrIsMutable(mod),
24089 .@"volatile" = attr_ptr_ty.isVolatilePtr(),24639 .@"volatile" = attr_ptr_ty.isVolatilePtr(mod),
24090 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(),24640 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(mod),
24091 });24641 });
2409224642
24093 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {24643 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24094 return sema.addConstant(24644 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24095 result_ty,24645 .ty = result_ty.toIntern(),
24096 try Value.Tag.field_ptr.create(sema.arena, .{24646 .addr = .{ .field = .{
24097 .container_ptr = val,24647 .base = val.toIntern(),
24098 .container_ty = inner_ty,24648 .index = Value.slice_ptr_index,
24099 .field_index = Value.Payload.Slice.ptr_index,24649 } },
24100 }),24650 } })).toValue());
24101 );
24102 }24651 }
24103 try sema.requireRuntimeBlock(block, src, null);24652 try sema.requireRuntimeBlock(block, src, null);
2410424653
24105 return block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr);24654 return block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr);
24106 } else if (mem.eql(u8, field_name, "len")) {24655 } else if (ip.stringEqlSlice(field_name, "len")) {
24107 const result_ty = try Type.ptr(sema.arena, sema.mod, .{24656 const result_ty = try Type.ptr(sema.arena, mod, .{
24108 .pointee_type = Type.usize,24657 .pointee_type = Type.usize,
24109 .mutable = attr_ptr_ty.ptrIsMutable(),24658 .mutable = attr_ptr_ty.ptrIsMutable(mod),
24110 .@"volatile" = attr_ptr_ty.isVolatilePtr(),24659 .@"volatile" = attr_ptr_ty.isVolatilePtr(mod),
24111 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(),24660 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(mod),
24112 });24661 });
2411324662
24114 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {24663 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24115 return sema.addConstant(24664 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24116 result_ty,24665 .ty = result_ty.toIntern(),
24117 try Value.Tag.field_ptr.create(sema.arena, .{24666 .addr = .{ .field = .{
24118 .container_ptr = val,24667 .base = val.toIntern(),
24119 .container_ty = inner_ty,24668 .index = Value.slice_len_index,
24120 .field_index = Value.Payload.Slice.len_index,24669 } },
24121 }),24670 } })).toValue());
24122 );
24123 }24671 }
24124 try sema.requireRuntimeBlock(block, src, null);24672 try sema.requireRuntimeBlock(block, src, null);
2412524673
...@@ -24128,8 +24676,8 @@ fn fieldPtr(...@@ -24128,8 +24676,8 @@ fn fieldPtr(
24128 return sema.fail(24676 return sema.fail(
24129 block,24677 block,
24130 field_name_src,24678 field_name_src,
24131 "no member named '{s}' in '{}'",24679 "no member named '{}' in '{}'",
24132 .{ field_name, object_ty.fmt(sema.mod) },24680 .{ field_name.fmt(ip), object_ty.fmt(mod) },
24133 );24681 );
24134 }24682 }
24135 },24683 },
...@@ -24142,47 +24690,59 @@ fn fieldPtr(...@@ -24142,47 +24690,59 @@ fn fieldPtr(
24142 result;24690 result;
2414324691
24144 const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?;24692 const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?;
24145 var to_type_buffer: Value.ToTypeBuffer = undefined;24693 const child_type = val.toType();
24146 const child_type = val.toType(&to_type_buffer);
2414724694
24148 switch (child_type.zigTypeTag()) {24695 switch (child_type.zigTypeTag(mod)) {
24149 .ErrorSet => {24696 .ErrorSet => {
24150 // TODO resolve inferred error sets24697 switch (ip.indexToKey(child_type.toIntern())) {
24151 const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {24698 .error_set_type => |error_set_type| blk: {
24152 if (payload.data.names.getEntry(field_name)) |entry| {24699 if (error_set_type.nameIndex(ip, field_name) != null) {
24153 break :blk entry.key_ptr.*;24700 break :blk;
24154 }24701 }
24155 return sema.fail(block, src, "no error named '{s}' in '{}'", .{24702 return sema.fail(block, src, "no error named '{}' in '{}'", .{
24156 field_name, child_type.fmt(sema.mod),24703 field_name.fmt(ip), child_type.fmt(mod),
24157 });24704 });
24158 } else (try sema.mod.getErrorValue(field_name)).key;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
24160 var anon_decl = try block.startAnonDecl();24716 var anon_decl = try block.startAnonDecl();
24161 defer anon_decl.deinit();24717 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);
24162 return sema.analyzeDeclRef(try anon_decl.finish(24722 return sema.analyzeDeclRef(try anon_decl.finish(
24163 if (!child_type.isAnyError())24723 error_set_type,
24164 try child_type.copy(anon_decl.arena())24724 (try mod.intern(.{ .err = .{
24165 else24725 .ty = error_set_type.toIntern(),
24166 try Type.Tag.error_set_single.create(anon_decl.arena(), name),24726 .name = field_name,
24167 try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }),24727 } })).toValue(),
24168 0, // default alignment24728 0, // default alignment
24169 ));24729 ));
24170 },24730 },
24171 .Union => {24731 .Union => {
24172 if (child_type.getNamespace()) |namespace| {24732 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
24173 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {24733 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
24174 return inst;24734 return inst;
24175 }24735 }
24176 }24736 }
24177 const union_ty = try sema.resolveTypeFields(child_type);24737 const union_ty = try sema.resolveTypeFields(child_type);
24178 if (union_ty.unionTagType()) |enum_ty| {24738 if (union_ty.unionTagType(mod)) |enum_ty| {
24179 if (enum_ty.enumFieldIndex(field_name)) |field_index| {24739 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index| {
24180 const field_index_u32 = @intCast(u32, field_index);24740 const field_index_u32 = @intCast(u32, field_index);
24181 var anon_decl = try block.startAnonDecl();24741 var anon_decl = try block.startAnonDecl();
24182 defer anon_decl.deinit();24742 defer anon_decl.deinit();
24183 return sema.analyzeDeclRef(try anon_decl.finish(24743 return sema.analyzeDeclRef(try anon_decl.finish(
24184 try enum_ty.copy(anon_decl.arena()),24744 enum_ty,
24185 try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),24745 try mod.enumValueFieldIndex(enum_ty, field_index_u32),
24186 0, // default alignment24746 0, // default alignment
24187 ));24747 ));
24188 }24748 }
...@@ -24190,32 +24750,32 @@ fn fieldPtr(...@@ -24190,32 +24750,32 @@ fn fieldPtr(
24190 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);24750 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
24191 },24751 },
24192 .Enum => {24752 .Enum => {
24193 if (child_type.getNamespace()) |namespace| {24753 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
24194 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {24754 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
24195 return inst;24755 return inst;
24196 }24756 }
24197 }24757 }
24198 const field_index = child_type.enumFieldIndex(field_name) orelse {24758 const field_index = child_type.enumFieldIndex(field_name, mod) orelse {
24199 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);24759 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
24200 };24760 };
24201 const field_index_u32 = @intCast(u32, field_index);24761 const field_index_u32 = @intCast(u32, field_index);
24202 var anon_decl = try block.startAnonDecl();24762 var anon_decl = try block.startAnonDecl();
24203 defer anon_decl.deinit();24763 defer anon_decl.deinit();
24204 return sema.analyzeDeclRef(try anon_decl.finish(24764 return sema.analyzeDeclRef(try anon_decl.finish(
24205 try child_type.copy(anon_decl.arena()),24765 child_type,
24206 try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),24766 try mod.enumValueFieldIndex(child_type, field_index_u32),
24207 0, // default alignment24767 0, // default alignment
24208 ));24768 ));
24209 },24769 },
24210 .Struct, .Opaque => {24770 .Struct, .Opaque => {
24211 if (child_type.getNamespace()) |namespace| {24771 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
24212 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {24772 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
24213 return inst;24773 return inst;
24214 }24774 }
24215 }24775 }
24216 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);24776 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
24217 },24777 },
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)}),
24219 }24779 }
24220 },24780 },
24221 .Struct => {24781 .Struct => {
...@@ -24252,22 +24812,24 @@ fn fieldCallBind(...@@ -24252,22 +24812,24 @@ fn fieldCallBind(
24252 block: *Block,24812 block: *Block,
24253 src: LazySrcLoc,24813 src: LazySrcLoc,
24254 raw_ptr: Air.Inst.Ref,24814 raw_ptr: Air.Inst.Ref,
24255 field_name: []const u8,24815 field_name: InternPool.NullTerminatedString,
24256 field_name_src: LazySrcLoc,24816 field_name_src: LazySrcLoc,
24257) CompileError!ResolvedFieldCallee {24817) CompileError!ResolvedFieldCallee {
24258 // When editing this function, note that there is corresponding logic to be edited24818 // When editing this function, note that there is corresponding logic to be edited
24259 // in `fieldVal`. This function takes a pointer and returns a pointer.24819 // in `fieldVal`. This function takes a pointer and returns a pointer.
2426024820
24821 const mod = sema.mod;
24822 const ip = &mod.intern_pool;
24261 const raw_ptr_src = src; // TODO better source location24823 const raw_ptr_src = src; // TODO better source location
24262 const raw_ptr_ty = sema.typeOf(raw_ptr);24824 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))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))
24264 raw_ptr_ty.childType()24826 raw_ptr_ty.childType(mod)
24265 else24827 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
24268 // Optionally dereference a second pointer to get the concrete type.24830 // Optionally dereference a second pointer to get the concrete type.
24269 const is_double_ptr = inner_ty.zigTypeTag() == .Pointer and inner_ty.ptrSize() == .One;24831 const is_double_ptr = inner_ty.zigTypeTag(mod) == .Pointer and inner_ty.ptrSize(mod) == .One;
24270 const concrete_ty = if (is_double_ptr) inner_ty.childType() else inner_ty;24832 const concrete_ty = if (is_double_ptr) inner_ty.childType(mod) else inner_ty;
24271 const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty;24833 const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty;
24272 const object_ptr = if (is_double_ptr)24834 const object_ptr = if (is_double_ptr)
24273 try sema.analyzeLoad(block, src, raw_ptr, src)24835 try sema.analyzeLoad(block, src, raw_ptr, src)
...@@ -24275,37 +24837,37 @@ fn fieldCallBind(...@@ -24275,37 +24837,37 @@ fn fieldCallBind(
24275 raw_ptr;24837 raw_ptr;
2427624838
24277 find_field: {24839 find_field: {
24278 switch (concrete_ty.zigTypeTag()) {24840 switch (concrete_ty.zigTypeTag(mod)) {
24279 .Struct => {24841 .Struct => {
24280 const struct_ty = try sema.resolveTypeFields(concrete_ty);24842 const struct_ty = try sema.resolveTypeFields(concrete_ty);
24281 if (struct_ty.castTag(.@"struct")) |struct_obj| {24843 if (mod.typeToStruct(struct_ty)) |struct_obj| {
24282 const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse24844 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24283 break :find_field;24845 break :find_field;
24284 const field_index = @intCast(u32, field_index_usize);24846 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
24287 return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr);24849 return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr);
24288 } else if (struct_ty.isTuple()) {24850 } else if (struct_ty.isTuple(mod)) {
24289 if (mem.eql(u8, field_name, "len")) {24851 if (ip.stringEqlSlice(field_name, "len")) {
24290 return .{ .direct = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount()) };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);
24291 }24857 }
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 |_| {}
24296 } else {24858 } else {
24297 const max = struct_ty.structFieldCount();24859 const max = struct_ty.structFieldCount(mod);
24298 var i: u32 = 0;24860 for (0..max) |i_usize| {
24299 while (i < max) : (i += 1) {24861 const i = @intCast(u32, i_usize);
24300 if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) {24862 if (field_name == struct_ty.structFieldName(i, mod)) {
24301 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr);24863 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i, mod), i, object_ptr);
24302 }24864 }
24303 }24865 }
24304 }24866 }
24305 },24867 },
24306 .Union => {24868 .Union => {
24307 const union_ty = try sema.resolveTypeFields(concrete_ty);24869 const union_ty = try sema.resolveTypeFields(concrete_ty);
24308 const fields = union_ty.unionFields();24870 const fields = union_ty.unionFields(mod);
24309 const field_index_usize = fields.getIndex(field_name) orelse break :find_field;24871 const field_index_usize = fields.getIndex(field_name) orelse break :find_field;
24310 const field_index = @intCast(u32, field_index_usize);24872 const field_index = @intCast(u32, field_index_usize);
24311 const field = fields.values()[field_index];24873 const field = fields.values()[field_index];
...@@ -24321,24 +24883,23 @@ fn fieldCallBind(...@@ -24321,24 +24883,23 @@ fn fieldCallBind(
24321 }24883 }
2432224884
24323 // If we get here, we need to look for a decl in the struct type instead.24885 // 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)) {
24325 .Struct, .Opaque, .Union, .Enum => found_decl: {24887 .Struct, .Opaque, .Union, .Enum => found_decl: {
24326 if (concrete_ty.getNamespace()) |namespace| {24888 if (concrete_ty.getNamespaceIndex(mod).unwrap()) |namespace| {
24327 if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| {24889 if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| {
24328 try sema.addReferencedBy(block, src, decl_idx);24890 try sema.addReferencedBy(block, src, decl_idx);
24329 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);24891 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);
24330 const decl_type = sema.typeOf(decl_val);24892 const decl_type = sema.typeOf(decl_val);
24331 if (decl_type.zigTypeTag() == .Fn and24893 if (mod.typeToFunc(decl_type)) |func_type| f: {
24332 decl_type.fnParamLen() >= 1)24894 if (func_type.param_types.len == 0) break :f;
24333 {24895
24334 const first_param_type = decl_type.fnParamType(0);24896 const first_param_type = func_type.param_types[0].toType();
24335 const first_param_tag = first_param_type.tag();
24336 // zig fmt: off24897 // zig fmt: off
24337 if (first_param_tag == .generic_poison or (24898 if (first_param_type.isGenericPoison() or (
24338 first_param_type.zigTypeTag() == .Pointer and24899 first_param_type.zigTypeTag(mod) == .Pointer and
24339 (first_param_type.ptrSize() == .One or24900 (first_param_type.ptrSize(mod) == .One or
24340 first_param_type.ptrSize() == .C) and24901 first_param_type.ptrSize(mod) == .C) and
24341 first_param_type.childType().eql(concrete_ty, sema.mod)))24902 first_param_type.childType(mod).eql(concrete_ty, mod)))
24342 {24903 {
24343 // zig fmt: on24904 // zig fmt: on
24344 // Note that if the param type is generic poison, we know that it must24905 // Note that if the param type is generic poison, we know that it must
...@@ -24350,32 +24911,31 @@ fn fieldCallBind(...@@ -24350,32 +24911,31 @@ fn fieldCallBind(
24350 .func_inst = decl_val,24911 .func_inst = decl_val,
24351 .arg0_inst = object_ptr,24912 .arg0_inst = object_ptr,
24352 } };24913 } };
24353 } else if (first_param_type.eql(concrete_ty, sema.mod)) {24914 } else if (first_param_type.eql(concrete_ty, mod)) {
24354 const deref = try sema.analyzeLoad(block, src, object_ptr, src);24915 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
24355 return .{ .method = .{24916 return .{ .method = .{
24356 .func_inst = decl_val,24917 .func_inst = decl_val,
24357 .arg0_inst = deref,24918 .arg0_inst = deref,
24358 } };24919 } };
24359 } else if (first_param_type.zigTypeTag() == .Optional) {24920 } else if (first_param_type.zigTypeTag(mod) == .Optional) {
24360 var opt_buf: Type.Payload.ElemType = undefined;24921 const child = first_param_type.optionalChild(mod);
24361 const child = first_param_type.optionalChild(&opt_buf);24922 if (child.eql(concrete_ty, mod)) {
24362 if (child.eql(concrete_ty, sema.mod)) {
24363 const deref = try sema.analyzeLoad(block, src, object_ptr, src);24923 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
24364 return .{ .method = .{24924 return .{ .method = .{
24365 .func_inst = decl_val,24925 .func_inst = decl_val,
24366 .arg0_inst = deref,24926 .arg0_inst = deref,
24367 } };24927 } };
24368 } else if (child.zigTypeTag() == .Pointer and24928 } else if (child.zigTypeTag(mod) == .Pointer and
24369 child.ptrSize() == .One and24929 child.ptrSize(mod) == .One and
24370 child.childType().eql(concrete_ty, sema.mod))24930 child.childType(mod).eql(concrete_ty, mod))
24371 {24931 {
24372 return .{ .method = .{24932 return .{ .method = .{
24373 .func_inst = decl_val,24933 .func_inst = decl_val,
24374 .arg0_inst = object_ptr,24934 .arg0_inst = object_ptr,
24375 } };24935 } };
24376 }24936 }
24377 } else if (first_param_type.zigTypeTag() == .ErrorUnion and24937 } else if (first_param_type.zigTypeTag(mod) == .ErrorUnion and
24378 first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod))24938 first_param_type.errorUnionPayload(mod).eql(concrete_ty, mod))
24379 {24939 {
24380 const deref = try sema.analyzeLoad(block, src, object_ptr, src);24940 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
24381 return .{ .method = .{24941 return .{ .method = .{
...@@ -24393,12 +24953,15 @@ fn fieldCallBind(...@@ -24393,12 +24953,15 @@ fn fieldCallBind(
24393 };24953 };
2439424954
24395 const msg = msg: {24955 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 });
24397 errdefer msg.destroy(sema.gpa);24960 errdefer msg.destroy(sema.gpa);
24398 try sema.addDeclaredHereNote(msg, concrete_ty);24961 try sema.addDeclaredHereNote(msg, concrete_ty);
24399 if (found_decl) |decl_idx| {24962 if (found_decl) |decl_idx| {
24400 const decl = sema.mod.declPtr(decl_idx);24963 const decl = mod.declPtr(decl_idx);
24401 try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "'{s}' is not a member function", .{field_name});24964 try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "'{}' is not a member function", .{field_name.fmt(ip)});
24402 }24965 }
24403 break :msg msg;24966 break :msg msg;
24404 };24967 };
...@@ -24414,29 +24977,29 @@ fn finishFieldCallBind(...@@ -24414,29 +24977,29 @@ fn finishFieldCallBind(
24414 field_index: u32,24977 field_index: u32,
24415 object_ptr: Air.Inst.Ref,24978 object_ptr: Air.Inst.Ref,
24416) CompileError!ResolvedFieldCallee {24979) CompileError!ResolvedFieldCallee {
24980 const mod = sema.mod;
24417 const arena = sema.arena;24981 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, .{
24419 .pointee_type = field_ty,24983 .pointee_type = field_ty,
24420 .mutable = ptr_ty.ptrIsMutable(),24984 .mutable = ptr_ty.ptrIsMutable(mod),
24421 .@"addrspace" = ptr_ty.ptrAddressSpace(),24985 .@"addrspace" = ptr_ty.ptrAddressSpace(mod),
24422 });24986 });
2442324987
24424 const container_ty = ptr_ty.childType();24988 const container_ty = ptr_ty.childType(mod);
24425 if (container_ty.zigTypeTag() == .Struct) {24989 if (container_ty.zigTypeTag(mod) == .Struct) {
24426 if (container_ty.structFieldValueComptime(field_index)) |default_val| {24990 if (try container_ty.structFieldValueComptime(mod, field_index)) |default_val| {
24427 return .{ .direct = try sema.addConstant(field_ty, default_val) };24991 return .{ .direct = try sema.addConstant(field_ty, default_val) };
24428 }24992 }
24429 }24993 }
2443024994
24431 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {24995 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
24432 const pointer = try sema.addConstant(24996 const pointer = try sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
24433 ptr_field_ty,24997 .ty = ptr_field_ty.toIntern(),
24434 try Value.Tag.field_ptr.create(arena, .{24998 .addr = .{ .field = .{
24435 .container_ptr = struct_ptr_val,24999 .base = struct_ptr_val.toIntern(),
24436 .container_ty = container_ty,25000 .index = field_index,
24437 .field_index = field_index,25001 } },
24438 }),25002 } })).toValue());
24439 );
24440 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };25003 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };
24441 }25004 }
2444225005
...@@ -24449,19 +25012,20 @@ fn namespaceLookup(...@@ -24449,19 +25012,20 @@ fn namespaceLookup(
24449 sema: *Sema,25012 sema: *Sema,
24450 block: *Block,25013 block: *Block,
24451 src: LazySrcLoc,25014 src: LazySrcLoc,
24452 namespace: *Namespace,25015 namespace: Namespace.Index,
24453 decl_name: []const u8,25016 decl_name: InternPool.NullTerminatedString,
24454) CompileError!?Decl.Index {25017) CompileError!?Decl.Index {
25018 const mod = sema.mod;
24455 const gpa = sema.gpa;25019 const gpa = sema.gpa;
24456 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| {25020 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| {
24457 const decl = sema.mod.declPtr(decl_index);25021 const decl = mod.declPtr(decl_index);
24458 if (!decl.is_pub and decl.getFileScope() != block.getFileScope()) {25022 if (!decl.is_pub and decl.getFileScope(mod) != block.getFileScope(mod)) {
24459 const msg = msg: {25023 const msg = msg: {
24460 const msg = try sema.errMsg(block, src, "'{s}' is not marked 'pub'", .{25024 const msg = try sema.errMsg(block, src, "'{}' is not marked 'pub'", .{
24461 decl_name,25025 decl_name.fmt(&mod.intern_pool),
24462 });25026 });
24463 errdefer msg.destroy(gpa);25027 errdefer msg.destroy(gpa);
24464 try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{});25028 try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "declared here", .{});
24465 break :msg msg;25029 break :msg msg;
24466 };25030 };
24467 return sema.failWithOwnedErrorMsg(msg);25031 return sema.failWithOwnedErrorMsg(msg);
...@@ -24475,8 +25039,8 @@ fn namespaceLookupRef(...@@ -24475,8 +25039,8 @@ fn namespaceLookupRef(
24475 sema: *Sema,25039 sema: *Sema,
24476 block: *Block,25040 block: *Block,
24477 src: LazySrcLoc,25041 src: LazySrcLoc,
24478 namespace: *Namespace,25042 namespace: Namespace.Index,
24479 decl_name: []const u8,25043 decl_name: InternPool.NullTerminatedString,
24480) CompileError!?Air.Inst.Ref {25044) CompileError!?Air.Inst.Ref {
24481 const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;25045 const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;
24482 try sema.addReferencedBy(block, src, decl);25046 try sema.addReferencedBy(block, src, decl);
...@@ -24487,8 +25051,8 @@ fn namespaceLookupVal(...@@ -24487,8 +25051,8 @@ fn namespaceLookupVal(
24487 sema: *Sema,25051 sema: *Sema,
24488 block: *Block,25052 block: *Block,
24489 src: LazySrcLoc,25053 src: LazySrcLoc,
24490 namespace: *Namespace,25054 namespace: Namespace.Index,
24491 decl_name: []const u8,25055 decl_name: InternPool.NullTerminatedString,
24492) CompileError!?Air.Inst.Ref {25056) CompileError!?Air.Inst.Ref {
24493 const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;25057 const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;
24494 return try sema.analyzeDeclVal(block, src, decl);25058 return try sema.analyzeDeclVal(block, src, decl);
...@@ -24499,29 +25063,30 @@ fn structFieldPtr(...@@ -24499,29 +25063,30 @@ fn structFieldPtr(
24499 block: *Block,25063 block: *Block,
24500 src: LazySrcLoc,25064 src: LazySrcLoc,
24501 struct_ptr: Air.Inst.Ref,25065 struct_ptr: Air.Inst.Ref,
24502 field_name: []const u8,25066 field_name: InternPool.NullTerminatedString,
24503 field_name_src: LazySrcLoc,25067 field_name_src: LazySrcLoc,
24504 unresolved_struct_ty: Type,25068 unresolved_struct_ty: Type,
24505 initializing: bool,25069 initializing: bool,
24506) CompileError!Air.Inst.Ref {25070) 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
24509 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);25074 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24510 try sema.resolveStructLayout(struct_ty);25075 try sema.resolveStructLayout(struct_ty);
2451125076
24512 if (struct_ty.isTuple()) {25077 if (struct_ty.isTuple(mod)) {
24513 if (mem.eql(u8, field_name, "len")) {25078 if (mod.intern_pool.stringEqlSlice(field_name, "len")) {
24514 const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount());25079 const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount(mod));
24515 return sema.analyzeRef(block, src, len_inst);25080 return sema.analyzeRef(block, src, len_inst);
24516 }25081 }
24517 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);25082 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
24518 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);25083 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)) {
24520 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);25085 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24521 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);25086 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
24522 }25087 }
2452325088
24524 const struct_obj = struct_ty.castTag(.@"struct").?.data;25089 const struct_obj = mod.typeToStruct(struct_ty).?;
2452525090
24526 const field_index_big = struct_obj.fields.getIndex(field_name) orelse25091 const field_index_big = struct_obj.fields.getIndex(field_name) orelse
24527 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);25092 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
...@@ -24540,14 +25105,15 @@ fn structFieldPtrByIndex(...@@ -24540,14 +25105,15 @@ fn structFieldPtrByIndex(
24540 struct_ty: Type,25105 struct_ty: Type,
24541 initializing: bool,25106 initializing: bool,
24542) CompileError!Air.Inst.Ref {25107) CompileError!Air.Inst.Ref {
24543 if (struct_ty.isAnonStruct()) {25108 const mod = sema.mod;
25109 if (struct_ty.isAnonStruct(mod)) {
24544 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);25110 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);
24545 }25111 }
2454625112
24547 const struct_obj = struct_ty.castTag(.@"struct").?.data;25113 const struct_obj = mod.typeToStruct(struct_ty).?;
24548 const field = struct_obj.fields.values()[field_index];25114 const field = struct_obj.fields.values()[field_index];
24549 const struct_ptr_ty = sema.typeOf(struct_ptr);25115 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
24552 var ptr_ty_data: Type.Payload.Pointer.Data = .{25118 var ptr_ty_data: Type.Payload.Pointer.Data = .{
24553 .pointee_type = field.ty,25119 .pointee_type = field.ty,
...@@ -24556,7 +25122,7 @@ fn structFieldPtrByIndex(...@@ -24556,7 +25122,7 @@ fn structFieldPtrByIndex(
24556 .@"addrspace" = struct_ptr_ty_info.@"addrspace",25122 .@"addrspace" = struct_ptr_ty_info.@"addrspace",
24557 };25123 };
2455825124
24559 const target = sema.mod.getTarget();25125 const target = mod.getTarget();
2456025126
24561 if (struct_obj.layout == .Packed) {25127 if (struct_obj.layout == .Packed) {
24562 comptime assert(Type.packed_struct_layout_version == 2);25128 comptime assert(Type.packed_struct_layout_version == 2);
...@@ -24568,7 +25134,7 @@ fn structFieldPtrByIndex(...@@ -24568,7 +25134,7 @@ fn structFieldPtrByIndex(
24568 if (i == field_index) {25134 if (i == field_index) {
24569 ptr_ty_data.bit_offset = running_bits;25135 ptr_ty_data.bit_offset = running_bits;
24570 }25136 }
24571 running_bits += @intCast(u16, f.ty.bitSize(target));25137 running_bits += @intCast(u16, f.ty.bitSize(mod));
24572 }25138 }
24573 ptr_ty_data.host_size = (running_bits + 7) / 8;25139 ptr_ty_data.host_size = (running_bits + 7) / 8;
2457425140
...@@ -24582,7 +25148,7 @@ fn structFieldPtrByIndex(...@@ -24582,7 +25148,7 @@ fn structFieldPtrByIndex(
24582 const parent_align = if (struct_ptr_ty_info.@"align" != 0)25148 const parent_align = if (struct_ptr_ty_info.@"align" != 0)
24583 struct_ptr_ty_info.@"align"25149 struct_ptr_ty_info.@"align"
24584 else25150 else
24585 struct_ptr_ty_info.pointee_type.abiAlignment(target);25151 struct_ptr_ty_info.pointee_type.abiAlignment(mod);
24586 ptr_ty_data.@"align" = parent_align;25152 ptr_ty_data.@"align" = parent_align;
2458725153
24588 // If the field happens to be byte-aligned, simplify the pointer type.25154 // If the field happens to be byte-aligned, simplify the pointer type.
...@@ -24596,8 +25162,8 @@ fn structFieldPtrByIndex(...@@ -24596,8 +25162,8 @@ fn structFieldPtrByIndex(
24596 if (parent_align != 0 and ptr_ty_data.bit_offset % 8 == 0 and25162 if (parent_align != 0 and ptr_ty_data.bit_offset % 8 == 0 and
24597 target.cpu.arch.endian() == .Little)25163 target.cpu.arch.endian() == .Little)
24598 {25164 {
24599 const elem_size_bytes = ptr_ty_data.pointee_type.abiSize(target);25165 const elem_size_bytes = ptr_ty_data.pointee_type.abiSize(mod);
24600 const elem_size_bits = ptr_ty_data.pointee_type.bitSize(target);25166 const elem_size_bits = ptr_ty_data.pointee_type.bitSize(mod);
24601 if (elem_size_bytes * 8 == elem_size_bits) {25167 if (elem_size_bytes * 8 == elem_size_bits) {
24602 const byte_offset = ptr_ty_data.bit_offset / 8;25168 const byte_offset = ptr_ty_data.bit_offset / 8;
24603 const new_align = @as(u32, 1) << @intCast(u5, @ctz(byte_offset | parent_align));25169 const new_align = @as(u32, 1) << @intCast(u5, @ctz(byte_offset | parent_align));
...@@ -24610,25 +25176,25 @@ fn structFieldPtrByIndex(...@@ -24610,25 +25176,25 @@ fn structFieldPtrByIndex(
24610 ptr_ty_data.@"align" = field.abi_align;25176 ptr_ty_data.@"align" = field.abi_align;
24611 }25177 }
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
24615 if (field.is_comptime) {25181 if (field.is_comptime) {
24616 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{25182 const val = try mod.intern(.{ .ptr = .{
24617 .field_ty = try field.ty.copy(sema.arena),25183 .ty = ptr_field_ty.toIntern(),
24618 .field_val = try field.default_val.copy(sema.arena),25184 .addr = .{ .comptime_field = field.default_val },
24619 });25185 } });
24620 return sema.addConstant(ptr_field_ty, val);25186 return sema.addConstant(ptr_field_ty, val.toValue());
24621 }25187 }
2462225188
24623 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {25189 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
24624 return sema.addConstant(25190 const val = try mod.intern(.{ .ptr = .{
24625 ptr_field_ty,25191 .ty = ptr_field_ty.toIntern(),
24626 try Value.Tag.field_ptr.create(sema.arena, .{25192 .addr = .{ .field = .{
24627 .container_ptr = struct_ptr_val,25193 .base = try struct_ptr_val.intern(struct_ptr_ty, mod),
24628 .container_ty = struct_ptr_ty.childType(),25194 .index = field_index,
24629 .field_index = field_index,25195 } },
24630 }),25196 } });
24631 );25197 return sema.addConstant(ptr_field_ty, val.toValue());
24632 }25198 }
2463325199
24634 try sema.requireRuntimeBlock(block, src, null);25200 try sema.requireRuntimeBlock(block, src, null);
...@@ -24640,21 +25206,17 @@ fn structFieldVal(...@@ -24640,21 +25206,17 @@ fn structFieldVal(
24640 block: *Block,25206 block: *Block,
24641 src: LazySrcLoc,25207 src: LazySrcLoc,
24642 struct_byval: Air.Inst.Ref,25208 struct_byval: Air.Inst.Ref,
24643 field_name: []const u8,25209 field_name: InternPool.NullTerminatedString,
24644 field_name_src: LazySrcLoc,25210 field_name_src: LazySrcLoc,
24645 unresolved_struct_ty: Type,25211 unresolved_struct_ty: Type,
24646) CompileError!Air.Inst.Ref {25212) 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
24649 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);25216 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24650 switch (struct_ty.tag()) {25217 switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
24651 .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),25218 .struct_type => |struct_type| {
24652 .anon_struct => {25219 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
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;
24658 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);25220 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2465925221
24660 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse25222 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
...@@ -24663,22 +25225,28 @@ fn structFieldVal(...@@ -24663,22 +25225,28 @@ fn structFieldVal(
24663 const field = struct_obj.fields.values()[field_index];25225 const field = struct_obj.fields.values()[field_index];
2466425226
24665 if (field.is_comptime) {25227 if (field.is_comptime) {
24666 return sema.addConstant(field.ty, field.default_val);25228 return sema.addConstant(field.ty, field.default_val.toValue());
24667 }25229 }
2466825230
24669 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {25231 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);
24671 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {25233 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24672 return sema.addConstant(field.ty, opv);25234 return sema.addConstant(field.ty, opv);
24673 }25235 }
2467425236 return sema.addConstant(field.ty, try struct_val.fieldValue(mod, field_index));
24675 const field_values = struct_val.castTag(.aggregate).?.data;
24676 return sema.addConstant(field.ty, field_values[field_index]);
24677 }25237 }
2467825238
24679 try sema.requireRuntimeBlock(block, src, null);25239 try sema.requireRuntimeBlock(block, src, null);
24680 return block.addStructFieldVal(struct_byval, field_index, field.ty);25240 return block.addStructFieldVal(struct_byval, field_index, field.ty);
24681 },25241 },
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 },
24682 else => unreachable,25250 else => unreachable,
24683 }25251 }
24684}25252}
...@@ -24688,12 +25256,13 @@ fn tupleFieldVal(...@@ -24688,12 +25256,13 @@ fn tupleFieldVal(
24688 block: *Block,25256 block: *Block,
24689 src: LazySrcLoc,25257 src: LazySrcLoc,
24690 tuple_byval: Air.Inst.Ref,25258 tuple_byval: Air.Inst.Ref,
24691 field_name: []const u8,25259 field_name: InternPool.NullTerminatedString,
24692 field_name_src: LazySrcLoc,25260 field_name_src: LazySrcLoc,
24693 tuple_ty: Type,25261 tuple_ty: Type,
24694) CompileError!Air.Inst.Ref {25262) CompileError!Air.Inst.Ref {
24695 if (mem.eql(u8, field_name, "len")) {25263 const mod = sema.mod;
24696 return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount());25264 if (mod.intern_pool.stringEqlSlice(field_name, "len")) {
25265 return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount(mod));
24697 }25266 }
24698 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src);25267 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src);
24699 return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty);25268 return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty);
...@@ -24704,19 +25273,20 @@ fn tupleFieldIndex(...@@ -24704,19 +25273,20 @@ fn tupleFieldIndex(
24704 sema: *Sema,25273 sema: *Sema,
24705 block: *Block,25274 block: *Block,
24706 tuple_ty: Type,25275 tuple_ty: Type,
24707 field_name: []const u8,25276 field_name: InternPool.NullTerminatedString,
24708 field_name_src: LazySrcLoc,25277 field_name_src: LazySrcLoc,
24709) CompileError!u32 {25278) CompileError!u32 {
24710 assert(!std.mem.eql(u8, field_name, "len"));25279 const mod = sema.mod;
24711 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {25280 assert(!mod.intern_pool.stringEqlSlice(field_name, "len"));
24712 if (field_index < tuple_ty.structFieldCount()) return field_index;25281 if (field_name.toUnsigned(&mod.intern_pool)) |field_index| {
24713 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{25282 if (field_index < tuple_ty.structFieldCount(mod)) return field_index;
24714 field_name, tuple_ty.fmt(sema.mod),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),
24715 });25285 });
24716 } else |_| {}25286 }
2471725287
24718 return sema.fail(block, field_name_src, "no field named '{s}' in tuple '{}'", .{25288 return sema.fail(block, field_name_src, "no field named '{}' in tuple '{}'", .{
24719 field_name, tuple_ty.fmt(sema.mod),25289 field_name.fmt(&mod.intern_pool), tuple_ty.fmt(mod),
24720 });25290 });
24721}25291}
2472225292
...@@ -24728,22 +25298,29 @@ fn tupleFieldValByIndex(...@@ -24728,22 +25298,29 @@ fn tupleFieldValByIndex(
24728 field_index: u32,25298 field_index: u32,
24729 tuple_ty: Type,25299 tuple_ty: Type,
24730) CompileError!Air.Inst.Ref {25300) 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| {
24734 return sema.addConstant(field_ty, default_value);25305 return sema.addConstant(field_ty, default_value);
24735 }25306 }
2473625307
24737 if (try sema.resolveMaybeUndefVal(tuple_byval)) |tuple_val| {25308 if (try sema.resolveMaybeUndefVal(tuple_byval)) |tuple_val| {
24738 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
24739 if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| {25309 if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| {
24740 return sema.addConstant(field_ty, opv);25310 return sema.addConstant(field_ty, opv);
24741 }25311 }
24742 const field_values = tuple_val.castTag(.aggregate).?.data;25312 return switch (mod.intern_pool.indexToKey(tuple_val.toIntern())) {
24743 return sema.addConstant(field_ty, field_values[field_index]);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 };
24744 }25321 }
2474525322
24746 if (tuple_ty.structFieldValueComptime(field_index)) |default_val| {25323 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
24747 return sema.addConstant(field_ty, default_val);25324 return sema.addConstant(field_ty, default_val);
24748 }25325 }
2474925326
...@@ -24756,33 +25333,38 @@ fn unionFieldPtr(...@@ -24756,33 +25333,38 @@ fn unionFieldPtr(
24756 block: *Block,25333 block: *Block,
24757 src: LazySrcLoc,25334 src: LazySrcLoc,
24758 union_ptr: Air.Inst.Ref,25335 union_ptr: Air.Inst.Ref,
24759 field_name: []const u8,25336 field_name: InternPool.NullTerminatedString,
24760 field_name_src: LazySrcLoc,25337 field_name_src: LazySrcLoc,
24761 unresolved_union_ty: Type,25338 unresolved_union_ty: Type,
24762 initializing: bool,25339 initializing: bool,
24763) CompileError!Air.Inst.Ref {25340) CompileError!Air.Inst.Ref {
24764 const arena = sema.arena;25341 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
24767 const union_ptr_ty = sema.typeOf(union_ptr);25347 const union_ptr_ty = sema.typeOf(union_ptr);
24768 const union_ty = try sema.resolveTypeFields(unresolved_union_ty);25348 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).?;
24770 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);25350 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
24771 const field = union_obj.fields.values()[field_index];25351 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, .{
24773 .pointee_type = field.ty,25353 .pointee_type = field.ty,
24774 .mutable = union_ptr_ty.ptrIsMutable(),25354 .mutable = union_ptr_ty.ptrIsMutable(mod),
24775 .@"volatile" = union_ptr_ty.isVolatilePtr(),25355 .@"volatile" = union_ptr_ty.isVolatilePtr(mod),
24776 .@"addrspace" = union_ptr_ty.ptrAddressSpace(),25356 .@"addrspace" = union_ptr_ty.ptrAddressSpace(mod),
24777 });25357 });
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) {
24781 const msg = msg: {25361 const msg = msg: {
24782 const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{});25362 const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{});
24783 errdefer msg.destroy(sema.gpa);25363 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 });
24786 try sema.addDeclaredHereNote(msg, union_ty);25368 try sema.addDeclaredHereNote(msg, union_ty);
24787 break :msg msg;25369 break :msg msg;
24788 };25370 };
...@@ -24794,21 +25376,20 @@ fn unionFieldPtr(...@@ -24794,21 +25376,20 @@ fn unionFieldPtr(
24794 .Auto => if (!initializing) {25376 .Auto => if (!initializing) {
24795 const union_val = (try sema.pointerDeref(block, src, union_ptr_val, union_ptr_ty)) orelse25377 const union_val = (try sema.pointerDeref(block, src, union_ptr_val, union_ptr_ty)) orelse
24796 break :ct;25378 break :ct;
24797 if (union_val.isUndef()) {25379 if (union_val.isUndef(mod)) {
24798 return sema.failWithUseOfUndef(block, src);25380 return sema.failWithUseOfUndef(block, src);
24799 }25381 }
24800 const tag_and_val = union_val.castTag(.@"union").?.data;25382 const un = ip.indexToKey(union_val.toIntern()).un;
24801 var field_tag_buf: Value.Payload.U32 = .{25383 const field_tag = try mod.enumValueFieldIndex(union_obj.tag_ty, enum_field_index);
24802 .base = .{ .tag = .enum_field_index },25384 const tag_matches = un.tag == field_tag.toIntern();
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);
24807 if (!tag_matches) {25385 if (!tag_matches) {
24808 const msg = msg: {25386 const msg = msg: {
24809 const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data;25387 const active_index = union_obj.tag_ty.enumTagFieldIndex(un.tag.toValue(), mod).?;
24810 const active_field_name = union_obj.tag_ty.enumFieldName(active_index);25388 const active_field_name = union_obj.tag_ty.enumFieldName(active_index, mod);
24811 const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name });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 });
24812 errdefer msg.destroy(sema.gpa);25393 errdefer msg.destroy(sema.gpa);
24813 try sema.addDeclaredHereNote(msg, union_ty);25394 try sema.addDeclaredHereNote(msg, union_ty);
24814 break :msg msg;25395 break :msg msg;
...@@ -24818,28 +25399,27 @@ fn unionFieldPtr(...@@ -24818,28 +25399,27 @@ fn unionFieldPtr(
24818 },25399 },
24819 .Packed, .Extern => {},25400 .Packed, .Extern => {},
24820 }25401 }
24821 return sema.addConstant(25402 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
24822 ptr_field_ty,25403 .ty = ptr_field_ty.toIntern(),
24823 try Value.Tag.field_ptr.create(arena, .{25404 .addr = .{ .field = .{
24824 .container_ptr = union_ptr_val,25405 .base = union_ptr_val.toIntern(),
24825 .container_ty = union_ty,25406 .index = field_index,
24826 .field_index = field_index,25407 } },
24827 }),25408 } })).toValue());
24828 );
24829 }25409 }
2483025410
24831 try sema.requireRuntimeBlock(block, src, null);25411 try sema.requireRuntimeBlock(block, src, null);
24832 if (!initializing and union_obj.layout == .Auto and block.wantSafety() and25412 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)
24834 {25414 {
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);
24836 const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);25416 const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);
24837 // TODO would it be better if get_union_tag supported pointers to unions?25417 // TODO would it be better if get_union_tag supported pointers to unions?
24838 const union_val = try block.addTyOp(.load, union_ty, union_ptr);25418 const union_val = try block.addTyOp(.load, union_ty, union_ptr);
24839 const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val);25419 const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val);
24840 try sema.panicInactiveUnionField(block, active_tag, wanted_tag);25420 try sema.panicInactiveUnionField(block, active_tag, wanted_tag);
24841 }25421 }
24842 if (field.ty.zigTypeTag() == .NoReturn) {25422 if (field.ty.zigTypeTag(mod) == .NoReturn) {
24843 _ = try block.addNoOp(.unreach);25423 _ = try block.addNoOp(.unreach);
24844 return Air.Inst.Ref.unreachable_value;25424 return Air.Inst.Ref.unreachable_value;
24845 }25425 }
...@@ -24851,37 +25431,37 @@ fn unionFieldVal(...@@ -24851,37 +25431,37 @@ fn unionFieldVal(
24851 block: *Block,25431 block: *Block,
24852 src: LazySrcLoc,25432 src: LazySrcLoc,
24853 union_byval: Air.Inst.Ref,25433 union_byval: Air.Inst.Ref,
24854 field_name: []const u8,25434 field_name: InternPool.NullTerminatedString,
24855 field_name_src: LazySrcLoc,25435 field_name_src: LazySrcLoc,
24856 unresolved_union_ty: Type,25436 unresolved_union_ty: Type,
24857) CompileError!Air.Inst.Ref {25437) 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
24860 const union_ty = try sema.resolveTypeFields(unresolved_union_ty);25442 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).?;
24862 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);25444 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
24863 const field = union_obj.fields.values()[field_index];25445 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
24866 if (try sema.resolveMaybeUndefVal(union_byval)) |union_val| {25448 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;25451 const un = ip.indexToKey(union_val.toIntern()).un;
24870 var field_tag_buf: Value.Payload.U32 = .{25452 const field_tag = try mod.enumValueFieldIndex(union_obj.tag_ty, enum_field_index);
24871 .base = .{ .tag = .enum_field_index },25453 const tag_matches = un.tag == field_tag.toIntern();
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);
24876 switch (union_obj.layout) {25454 switch (union_obj.layout) {
24877 .Auto => {25455 .Auto => {
24878 if (tag_matches) {25456 if (tag_matches) {
24879 return sema.addConstant(field.ty, tag_and_val.val);25457 return sema.addConstant(field.ty, un.val.toValue());
24880 } else {25458 } else {
24881 const msg = msg: {25459 const msg = msg: {
24882 const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data;25460 const active_index = union_obj.tag_ty.enumTagFieldIndex(un.tag.toValue(), mod).?;
24883 const active_field_name = union_obj.tag_ty.enumFieldName(active_index);25461 const active_field_name = union_obj.tag_ty.enumFieldName(active_index, mod);
24884 const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name });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 });
24885 errdefer msg.destroy(sema.gpa);25465 errdefer msg.destroy(sema.gpa);
24886 try sema.addDeclaredHereNote(msg, union_ty);25466 try sema.addDeclaredHereNote(msg, union_ty);
24887 break :msg msg;25467 break :msg msg;
...@@ -24891,10 +25471,10 @@ fn unionFieldVal(...@@ -24891,10 +25471,10 @@ fn unionFieldVal(
24891 },25471 },
24892 .Packed, .Extern => {25472 .Packed, .Extern => {
24893 if (tag_matches) {25473 if (tag_matches) {
24894 return sema.addConstant(field.ty, tag_and_val.val);25474 return sema.addConstant(field.ty, un.val.toValue());
24895 } else {25475 } else {
24896 const old_ty = union_ty.unionFieldType(tag_and_val.tag, sema.mod);25476 const old_ty = union_ty.unionFieldType(un.tag.toValue(), mod);
24897 if (try sema.bitCastVal(block, src, tag_and_val.val, old_ty, field.ty, 0)) |new_val| {25477 if (try sema.bitCastVal(block, src, un.val.toValue(), old_ty, field.ty, 0)) |new_val| {
24898 return sema.addConstant(field.ty, new_val);25478 return sema.addConstant(field.ty, new_val);
24899 }25479 }
24900 }25480 }
...@@ -24904,14 +25484,14 @@ fn unionFieldVal(...@@ -24904,14 +25484,14 @@ fn unionFieldVal(
2490425484
24905 try sema.requireRuntimeBlock(block, src, null);25485 try sema.requireRuntimeBlock(block, src, null);
24906 if (union_obj.layout == .Auto and block.wantSafety() and25486 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)
24908 {25488 {
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);
24910 const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);25490 const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);
24911 const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval);25491 const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval);
24912 try sema.panicInactiveUnionField(block, active_tag, wanted_tag);25492 try sema.panicInactiveUnionField(block, active_tag, wanted_tag);
24913 }25493 }
24914 if (field.ty.zigTypeTag() == .NoReturn) {25494 if (field.ty.zigTypeTag(mod) == .NoReturn) {
24915 _ = try block.addNoOp(.unreach);25495 _ = try block.addNoOp(.unreach);
24916 return Air.Inst.Ref.unreachable_value;25496 return Air.Inst.Ref.unreachable_value;
24917 }25497 }
...@@ -24928,22 +25508,22 @@ fn elemPtr(...@@ -24928,22 +25508,22 @@ fn elemPtr(
24928 init: bool,25508 init: bool,
24929 oob_safety: bool,25509 oob_safety: bool,
24930) CompileError!Air.Inst.Ref {25510) CompileError!Air.Inst.Ref {
25511 const mod = sema.mod;
24931 const indexable_ptr_src = src; // TODO better source location25512 const indexable_ptr_src = src; // TODO better source location
24932 const indexable_ptr_ty = sema.typeOf(indexable_ptr);25513 const indexable_ptr_ty = sema.typeOf(indexable_ptr);
24933 const target = sema.mod.getTarget();
2493425514
24935 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag()) {25515 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(mod)) {
24936 .Pointer => indexable_ptr_ty.elemType(),25516 .Pointer => indexable_ptr_ty.childType(mod),
24937 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}),25517 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(mod)}),
24938 };25518 };
24939 try checkIndexable(sema, block, src, indexable_ty);25519 try checkIndexable(sema, block, src, indexable_ty);
2494025520
24941 switch (indexable_ty.zigTypeTag()) {25521 switch (indexable_ty.zigTypeTag(mod)) {
24942 .Array, .Vector => return sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),25522 .Array, .Vector => return sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),
24943 .Struct => {25523 .Struct => {
24944 // Tuple field access.25524 // Tuple field access.
24945 const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known");25525 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));
24947 return sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init);25527 return sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init);
24948 },25528 },
24949 else => {25529 else => {
...@@ -24966,11 +25546,11 @@ fn elemPtrOneLayerOnly(...@@ -24966,11 +25546,11 @@ fn elemPtrOneLayerOnly(
24966) CompileError!Air.Inst.Ref {25546) CompileError!Air.Inst.Ref {
24967 const indexable_src = src; // TODO better source location25547 const indexable_src = src; // TODO better source location
24968 const indexable_ty = sema.typeOf(indexable);25548 const indexable_ty = sema.typeOf(indexable);
24969 const target = sema.mod.getTarget();25549 const mod = sema.mod;
2497025550
24971 try checkIndexable(sema, block, src, indexable_ty);25551 try checkIndexable(sema, block, src, indexable_ty);
2497225552
24973 switch (indexable_ty.ptrSize()) {25553 switch (indexable_ty.ptrSize(mod)) {
24974 .Slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),25554 .Slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
24975 .Many, .C => {25555 .Many, .C => {
24976 const maybe_ptr_val = try sema.resolveDefinedValue(block, indexable_src, indexable);25556 const maybe_ptr_val = try sema.resolveDefinedValue(block, indexable_src, indexable);
...@@ -24978,9 +25558,9 @@ fn elemPtrOneLayerOnly(...@@ -24978,9 +25558,9 @@ fn elemPtrOneLayerOnly(
24978 const runtime_src = rs: {25558 const runtime_src = rs: {
24979 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;25559 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;
24980 const index_val = maybe_index_val orelse break :rs elem_index_src;25560 const index_val = maybe_index_val orelse break :rs elem_index_src;
24981 const index = @intCast(usize, index_val.toUnsignedInt(target));25561 const index = @intCast(usize, index_val.toUnsignedInt(mod));
24982 const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);
24983 const result_ty = try sema.elemPtrType(indexable_ty, index);25562 const result_ty = try sema.elemPtrType(indexable_ty, index);
25563 const elem_ptr = try ptr_val.elemPtr(result_ty, index, mod);
24984 return sema.addConstant(result_ty, elem_ptr);25564 return sema.addConstant(result_ty, elem_ptr);
24985 };25565 };
24986 const result_ty = try sema.elemPtrType(indexable_ty, null);25566 const result_ty = try sema.elemPtrType(indexable_ty, null);
...@@ -24989,7 +25569,7 @@ fn elemPtrOneLayerOnly(...@@ -24989,7 +25569,7 @@ fn elemPtrOneLayerOnly(
24989 return block.addPtrElemPtr(indexable, elem_index, result_ty);25569 return block.addPtrElemPtr(indexable, elem_index, result_ty);
24990 },25570 },
24991 .One => {25571 .One => {
24992 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable25572 assert(indexable_ty.childType(mod).zigTypeTag(mod) == .Array); // Guaranteed by checkIndexable
24993 return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety);25573 return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety);
24994 },25574 },
24995 }25575 }
...@@ -25006,7 +25586,7 @@ fn elemVal(...@@ -25006,7 +25586,7 @@ fn elemVal(
25006) CompileError!Air.Inst.Ref {25586) CompileError!Air.Inst.Ref {
25007 const indexable_src = src; // TODO better source location25587 const indexable_src = src; // TODO better source location
25008 const indexable_ty = sema.typeOf(indexable);25588 const indexable_ty = sema.typeOf(indexable);
25009 const target = sema.mod.getTarget();25589 const mod = sema.mod;
2501025590
25011 try checkIndexable(sema, block, src, indexable_ty);25591 try checkIndexable(sema, block, src, indexable_ty);
2501225592
...@@ -25014,8 +25594,8 @@ fn elemVal(...@@ -25014,8 +25594,8 @@ fn elemVal(
25014 // index is a scalar or vector instead of unconditionally casting to usize.25594 // index is a scalar or vector instead of unconditionally casting to usize.
25015 const elem_index = try sema.coerce(block, Type.usize, elem_index_uncasted, elem_index_src);25595 const elem_index = try sema.coerce(block, Type.usize, elem_index_uncasted, elem_index_src);
2501625596
25017 switch (indexable_ty.zigTypeTag()) {25597 switch (indexable_ty.zigTypeTag(mod)) {
25018 .Pointer => switch (indexable_ty.ptrSize()) {25598 .Pointer => switch (indexable_ty.ptrSize(mod)) {
25019 .Slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),25599 .Slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
25020 .Many, .C => {25600 .Many, .C => {
25021 const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable);25601 const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable);
...@@ -25024,10 +25604,14 @@ fn elemVal(...@@ -25024,10 +25604,14 @@ fn elemVal(
25024 const runtime_src = rs: {25604 const runtime_src = rs: {
25025 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;25605 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
25026 const index_val = maybe_index_val orelse break :rs elem_index_src;25606 const index_val = maybe_index_val orelse break :rs elem_index_src;
25027 const index = @intCast(usize, index_val.toUnsignedInt(target));25607 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25028 const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);25608 const elem_ty = indexable_ty.elemType2(mod);
25029 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| {25609 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
25030 return sema.addConstant(indexable_ty.elemType2(), elem_val);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));
25031 }25615 }
25032 break :rs indexable_src;25616 break :rs indexable_src;
25033 };25617 };
...@@ -25036,7 +25620,19 @@ fn elemVal(...@@ -25036,7 +25620,19 @@ fn elemVal(
25036 return block.addBinOp(.ptr_elem_val, indexable, elem_index);25620 return block.addBinOp(.ptr_elem_val, indexable, elem_index);
25037 },25621 },
25038 .One => {25622 .One => {
25039 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable25623 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
25040 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);25636 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);
25041 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);25637 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
25042 },25638 },
...@@ -25049,7 +25645,7 @@ fn elemVal(...@@ -25049,7 +25645,7 @@ fn elemVal(
25049 .Struct => {25645 .Struct => {
25050 // Tuple field access.25646 // Tuple field access.
25051 const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known");25647 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));
25053 return sema.tupleField(block, indexable_src, indexable, elem_index_src, index);25649 return sema.tupleField(block, indexable_src, indexable, elem_index_src, index);
25054 },25650 },
25055 else => unreachable,25651 else => unreachable,
...@@ -25064,6 +25660,7 @@ fn validateRuntimeElemAccess(...@@ -25064,6 +25660,7 @@ fn validateRuntimeElemAccess(
25064 parent_ty: Type,25660 parent_ty: Type,
25065 parent_src: LazySrcLoc,25661 parent_src: LazySrcLoc,
25066) CompileError!void {25662) CompileError!void {
25663 const mod = sema.mod;
25067 const valid_rt = try sema.validateRunTimeType(elem_ty, false);25664 const valid_rt = try sema.validateRunTimeType(elem_ty, false);
25068 if (!valid_rt) {25665 if (!valid_rt) {
25069 const msg = msg: {25666 const msg = msg: {
...@@ -25071,12 +25668,12 @@ fn validateRuntimeElemAccess(...@@ -25071,12 +25668,12 @@ fn validateRuntimeElemAccess(
25071 block,25668 block,
25072 elem_index_src,25669 elem_index_src,
25073 "values of type '{}' must be comptime-known, but index value is runtime-known",25670 "values of type '{}' must be comptime-known, but index value is runtime-known",
25074 .{parent_ty.fmt(sema.mod)},25671 .{parent_ty.fmt(mod)},
25075 );25672 );
25076 errdefer msg.destroy(sema.gpa);25673 errdefer msg.destroy(sema.gpa);
2507725674
25078 const src_decl = sema.mod.declPtr(block.src_decl);25675 const src_decl = mod.declPtr(block.src_decl);
25079 try sema.explainWhyTypeIsComptime(msg, parent_src.toSrcLoc(src_decl), parent_ty);25676 try sema.explainWhyTypeIsComptime(msg, parent_src.toSrcLoc(src_decl, mod), parent_ty);
2508025677
25081 break :msg msg;25678 break :msg msg;
25082 };25679 };
...@@ -25093,10 +25690,11 @@ fn tupleFieldPtr(...@@ -25093,10 +25690,11 @@ fn tupleFieldPtr(
25093 field_index: u32,25690 field_index: u32,
25094 init: bool,25691 init: bool,
25095) CompileError!Air.Inst.Ref {25692) CompileError!Air.Inst.Ref {
25693 const mod = sema.mod;
25096 const tuple_ptr_ty = sema.typeOf(tuple_ptr);25694 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);
25098 _ = try sema.resolveTypeFields(tuple_ty);25696 _ = try sema.resolveTypeFields(tuple_ty);
25099 const field_count = tuple_ty.structFieldCount();25697 const field_count = tuple_ty.structFieldCount(mod);
2510025698
25101 if (field_count == 0) {25699 if (field_count == 0) {
25102 return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});25700 return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});
...@@ -25108,31 +25706,29 @@ fn tupleFieldPtr(...@@ -25108,31 +25706,29 @@ fn tupleFieldPtr(
25108 });25706 });
25109 }25707 }
2511025708
25111 const field_ty = tuple_ty.structFieldType(field_index);25709 const field_ty = tuple_ty.structFieldType(field_index, mod);
25112 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{25710 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
25113 .pointee_type = field_ty,25711 .pointee_type = field_ty,
25114 .mutable = tuple_ptr_ty.ptrIsMutable(),25712 .mutable = tuple_ptr_ty.ptrIsMutable(mod),
25115 .@"volatile" = tuple_ptr_ty.isVolatilePtr(),25713 .@"volatile" = tuple_ptr_ty.isVolatilePtr(mod),
25116 .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(),25714 .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(mod),
25117 });25715 });
2511825716
25119 if (tuple_ty.structFieldValueComptime(field_index)) |default_val| {25717 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
25120 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{25718 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25121 .field_ty = field_ty,25719 .ty = ptr_field_ty.toIntern(),
25122 .field_val = default_val,25720 .addr = .{ .comptime_field = default_val.toIntern() },
25123 });25721 } })).toValue());
25124 return sema.addConstant(ptr_field_ty, val);
25125 }25722 }
2512625723
25127 if (try sema.resolveMaybeUndefVal(tuple_ptr)) |tuple_ptr_val| {25724 if (try sema.resolveMaybeUndefVal(tuple_ptr)) |tuple_ptr_val| {
25128 return sema.addConstant(25725 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25129 ptr_field_ty,25726 .ty = ptr_field_ty.toIntern(),
25130 try Value.Tag.field_ptr.create(sema.arena, .{25727 .addr = .{ .field = .{
25131 .container_ptr = tuple_ptr_val,25728 .base = tuple_ptr_val.toIntern(),
25132 .container_ty = tuple_ty,25729 .index = field_index,
25133 .field_index = field_index,25730 } },
25134 }),25731 } })).toValue());
25135 );
25136 }25732 }
2513725733
25138 if (!init) {25734 if (!init) {
...@@ -25151,8 +25747,9 @@ fn tupleField(...@@ -25151,8 +25747,9 @@ fn tupleField(
25151 field_index_src: LazySrcLoc,25747 field_index_src: LazySrcLoc,
25152 field_index: u32,25748 field_index: u32,
25153) CompileError!Air.Inst.Ref {25749) CompileError!Air.Inst.Ref {
25750 const mod = sema.mod;
25154 const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple));25751 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
25157 if (field_count == 0) {25754 if (field_count == 0) {
25158 return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{});25755 return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{});
...@@ -25164,15 +25761,15 @@ fn tupleField(...@@ -25164,15 +25761,15 @@ fn tupleField(
25164 });25761 });
25165 }25762 }
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| {
25170 return sema.addConstant(field_ty, default_value); // comptime field25767 return sema.addConstant(field_ty, default_value); // comptime field
25171 }25768 }
2517225769
25173 if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {25770 if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {
25174 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);25771 if (tuple_val.isUndef(mod)) return sema.addConstUndef(field_ty);
25175 return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, field_index));25772 return sema.addConstant(field_ty, try tuple_val.fieldValue(mod, field_index));
25176 }25773 }
2517725774
25178 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);25775 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
...@@ -25191,11 +25788,12 @@ fn elemValArray(...@@ -25191,11 +25788,12 @@ fn elemValArray(
25191 elem_index: Air.Inst.Ref,25788 elem_index: Air.Inst.Ref,
25192 oob_safety: bool,25789 oob_safety: bool,
25193) CompileError!Air.Inst.Ref {25790) CompileError!Air.Inst.Ref {
25791 const mod = sema.mod;
25194 const array_ty = sema.typeOf(array);25792 const array_ty = sema.typeOf(array);
25195 const array_sent = array_ty.sentinel();25793 const array_sent = array_ty.sentinel(mod);
25196 const array_len = array_ty.arrayLen();25794 const array_len = array_ty.arrayLen(mod);
25197 const array_len_s = array_len + @boolToInt(array_sent != null);25795 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
25200 if (array_len_s == 0) {25798 if (array_len_s == 0) {
25201 return sema.fail(block, array_src, "indexing into empty array is not allowed", .{});25799 return sema.fail(block, array_src, "indexing into empty array is not allowed", .{});
...@@ -25204,10 +25802,9 @@ fn elemValArray(...@@ -25204,10 +25802,9 @@ fn elemValArray(
25204 const maybe_undef_array_val = try sema.resolveMaybeUndefVal(array);25802 const maybe_undef_array_val = try sema.resolveMaybeUndefVal(array);
25205 // index must be defined since it can access out of bounds25803 // index must be defined since it can access out of bounds
25206 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);25804 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
25207 const target = sema.mod.getTarget();
2520825805
25209 if (maybe_index_val) |index_val| {25806 if (maybe_index_val) |index_val| {
25210 const index = @intCast(usize, index_val.toUnsignedInt(target));25807 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25211 if (array_sent) |s| {25808 if (array_sent) |s| {
25212 if (index == array_len) {25809 if (index == array_len) {
25213 return sema.addConstant(elem_ty, s);25810 return sema.addConstant(elem_ty, s);
...@@ -25219,12 +25816,12 @@ fn elemValArray(...@@ -25219,12 +25816,12 @@ fn elemValArray(
25219 }25816 }
25220 }25817 }
25221 if (maybe_undef_array_val) |array_val| {25818 if (maybe_undef_array_val) |array_val| {
25222 if (array_val.isUndef()) {25819 if (array_val.isUndef(mod)) {
25223 return sema.addConstUndef(elem_ty);25820 return sema.addConstUndef(elem_ty);
25224 }25821 }
25225 if (maybe_index_val) |index_val| {25822 if (maybe_index_val) |index_val| {
25226 const index = @intCast(usize, index_val.toUnsignedInt(target));25823 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25227 const elem_val = try array_val.elemValue(sema.mod, sema.arena, index);25824 const elem_val = try array_val.elemValue(mod, index);
25228 return sema.addConstant(elem_ty, elem_val);25825 return sema.addConstant(elem_ty, elem_val);
25229 }25826 }
25230 }25827 }
...@@ -25255,11 +25852,11 @@ fn elemPtrArray(...@@ -25255,11 +25852,11 @@ fn elemPtrArray(
25255 init: bool,25852 init: bool,
25256 oob_safety: bool,25853 oob_safety: bool,
25257) CompileError!Air.Inst.Ref {25854) CompileError!Air.Inst.Ref {
25258 const target = sema.mod.getTarget();25855 const mod = sema.mod;
25259 const array_ptr_ty = sema.typeOf(array_ptr);25856 const array_ptr_ty = sema.typeOf(array_ptr);
25260 const array_ty = array_ptr_ty.childType();25857 const array_ty = array_ptr_ty.childType(mod);
25261 const array_sent = array_ty.sentinel() != null;25858 const array_sent = array_ty.sentinel(mod) != null;
25262 const array_len = array_ty.arrayLen();25859 const array_len = array_ty.arrayLen(mod);
25263 const array_len_s = array_len + @boolToInt(array_sent);25860 const array_len_s = array_len + @boolToInt(array_sent);
2526425861
25265 if (array_len_s == 0) {25862 if (array_len_s == 0) {
...@@ -25269,7 +25866,7 @@ fn elemPtrArray(...@@ -25269,7 +25866,7 @@ fn elemPtrArray(
25269 const maybe_undef_array_ptr_val = try sema.resolveMaybeUndefVal(array_ptr);25866 const maybe_undef_array_ptr_val = try sema.resolveMaybeUndefVal(array_ptr);
25270 // The index must not be undefined since it can be out of bounds.25867 // The index must not be undefined since it can be out of bounds.
25271 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {25868 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));
25273 if (index >= array_len_s) {25870 if (index >= array_len_s) {
25274 const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else "";25871 const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else "";
25275 return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label });25872 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(...@@ -25280,17 +25877,17 @@ fn elemPtrArray(
25280 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset);25877 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset);
2528125878
25282 if (maybe_undef_array_ptr_val) |array_ptr_val| {25879 if (maybe_undef_array_ptr_val) |array_ptr_val| {
25283 if (array_ptr_val.isUndef()) {25880 if (array_ptr_val.isUndef(mod)) {
25284 return sema.addConstUndef(elem_ptr_ty);25881 return sema.addConstUndef(elem_ptr_ty);
25285 }25882 }
25286 if (offset) |index| {25883 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);
25288 return sema.addConstant(elem_ptr_ty, elem_ptr);25885 return sema.addConstant(elem_ptr_ty, elem_ptr);
25289 }25886 }
25290 }25887 }
2529125888
25292 if (!init) {25889 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);
25294 }25891 }
2529525892
25296 const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src;25893 const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src;
...@@ -25316,32 +25913,33 @@ fn elemValSlice(...@@ -25316,32 +25913,33 @@ fn elemValSlice(
25316 elem_index: Air.Inst.Ref,25913 elem_index: Air.Inst.Ref,
25317 oob_safety: bool,25914 oob_safety: bool,
25318) CompileError!Air.Inst.Ref {25915) CompileError!Air.Inst.Ref {
25916 const mod = sema.mod;
25319 const slice_ty = sema.typeOf(slice);25917 const slice_ty = sema.typeOf(slice);
25320 const slice_sent = slice_ty.sentinel() != null;25918 const slice_sent = slice_ty.sentinel(mod) != null;
25321 const elem_ty = slice_ty.elemType2();25919 const elem_ty = slice_ty.elemType2(mod);
25322 var runtime_src = slice_src;25920 var runtime_src = slice_src;
2532325921
25324 // slice must be defined since it can dereferenced as null25922 // slice must be defined since it can dereferenced as null
25325 const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice);25923 const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice);
25326 // index must be defined since it can index out of bounds25924 // index must be defined since it can index out of bounds
25327 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);25925 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
25328 const target = sema.mod.getTarget();
2532925926
25330 if (maybe_slice_val) |slice_val| {25927 if (maybe_slice_val) |slice_val| {
25331 runtime_src = elem_index_src;25928 runtime_src = elem_index_src;
25332 const slice_len = slice_val.sliceLen(sema.mod);25929 const slice_len = slice_val.sliceLen(mod);
25333 const slice_len_s = slice_len + @boolToInt(slice_sent);25930 const slice_len_s = slice_len + @boolToInt(slice_sent);
25334 if (slice_len_s == 0) {25931 if (slice_len_s == 0) {
25335 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});25932 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
25336 }25933 }
25337 if (maybe_index_val) |index_val| {25934 if (maybe_index_val) |index_val| {
25338 const index = @intCast(usize, index_val.toUnsignedInt(target));25935 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25339 if (index >= slice_len_s) {25936 if (index >= slice_len_s) {
25340 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";25937 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
25341 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });25938 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
25342 }25939 }
25343 const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, sema.mod);25940 const elem_ptr_ty = try sema.elemPtrType(slice_ty, index);
25344 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| {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| {
25345 return sema.addConstant(elem_ty, elem_val);25943 return sema.addConstant(elem_ty, elem_val);
25346 }25944 }
25347 runtime_src = slice_src;25945 runtime_src = slice_src;
...@@ -25353,7 +25951,7 @@ fn elemValSlice(...@@ -25353,7 +25951,7 @@ fn elemValSlice(
25353 try sema.requireRuntimeBlock(block, src, runtime_src);25951 try sema.requireRuntimeBlock(block, src, runtime_src);
25354 if (oob_safety and block.wantSafety()) {25952 if (oob_safety and block.wantSafety()) {
25355 const len_inst = if (maybe_slice_val) |slice_val|25953 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))
25357 else25955 else
25358 try block.addTyOp(.slice_len, Type.usize, slice);25956 try block.addTyOp(.slice_len, Type.usize, slice);
25359 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;25957 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
...@@ -25373,24 +25971,24 @@ fn elemPtrSlice(...@@ -25373,24 +25971,24 @@ fn elemPtrSlice(
25373 elem_index: Air.Inst.Ref,25971 elem_index: Air.Inst.Ref,
25374 oob_safety: bool,25972 oob_safety: bool,
25375) CompileError!Air.Inst.Ref {25973) CompileError!Air.Inst.Ref {
25376 const target = sema.mod.getTarget();25974 const mod = sema.mod;
25377 const slice_ty = sema.typeOf(slice);25975 const slice_ty = sema.typeOf(slice);
25378 const slice_sent = slice_ty.sentinel() != null;25976 const slice_sent = slice_ty.sentinel(mod) != null;
2537925977
25380 const maybe_undef_slice_val = try sema.resolveMaybeUndefVal(slice);25978 const maybe_undef_slice_val = try sema.resolveMaybeUndefVal(slice);
25381 // The index must not be undefined since it can be out of bounds.25979 // The index must not be undefined since it can be out of bounds.
25382 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {25980 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));
25384 break :o index;25982 break :o index;
25385 } else null;25983 } else null;
2538625984
25387 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset);25985 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset);
2538825986
25389 if (maybe_undef_slice_val) |slice_val| {25987 if (maybe_undef_slice_val) |slice_val| {
25390 if (slice_val.isUndef()) {25988 if (slice_val.isUndef(mod)) {
25391 return sema.addConstUndef(elem_ptr_ty);25989 return sema.addConstUndef(elem_ptr_ty);
25392 }25990 }
25393 const slice_len = slice_val.sliceLen(sema.mod);25991 const slice_len = slice_val.sliceLen(mod);
25394 const slice_len_s = slice_len + @boolToInt(slice_sent);25992 const slice_len_s = slice_len + @boolToInt(slice_sent);
25395 if (slice_len_s == 0) {25993 if (slice_len_s == 0) {
25396 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});25994 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
...@@ -25400,7 +25998,7 @@ fn elemPtrSlice(...@@ -25400,7 +25998,7 @@ fn elemPtrSlice(
25400 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";25998 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
25401 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });25999 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
25402 }26000 }
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);
25404 return sema.addConstant(elem_ptr_ty, elem_ptr_val);26002 return sema.addConstant(elem_ptr_ty, elem_ptr_val);
25405 }26003 }
25406 }26004 }
...@@ -25412,8 +26010,8 @@ fn elemPtrSlice(...@@ -25412,8 +26010,8 @@ fn elemPtrSlice(
25412 if (oob_safety and block.wantSafety()) {26010 if (oob_safety and block.wantSafety()) {
25413 const len_inst = len: {26011 const len_inst = len: {
25414 if (maybe_undef_slice_val) |slice_val|26012 if (maybe_undef_slice_val) |slice_val|
25415 if (!slice_val.isUndef())26013 if (!slice_val.isUndef(mod))
25416 break :len try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod));26014 break :len try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(mod));
25417 break :len try block.addTyOp(.slice_len, Type.usize, slice);26015 break :len try block.addTyOp(.slice_len, Type.usize, slice);
25418 };26016 };
25419 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;26017 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
...@@ -25455,16 +26053,17 @@ const CoerceOpts = struct {...@@ -25455,16 +26053,17 @@ const CoerceOpts = struct {
2545526053
25456 fn get(info: @This(), sema: *Sema) !?Module.SrcLoc {26054 fn get(info: @This(), sema: *Sema) !?Module.SrcLoc {
25457 if (info.func_inst == .none) return null;26055 if (info.func_inst == .none) return null;
26056 const mod = sema.mod;
25458 const fn_decl = (try sema.funcDeclSrc(info.func_inst)) orelse return null;26057 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);
25460 if (param_src == .node_offset_param) {26059 if (param_src == .node_offset_param) {
25461 return Module.SrcLoc{26060 return Module.SrcLoc{
25462 .file_scope = fn_decl.getFileScope(),26061 .file_scope = fn_decl.getFileScope(mod),
25463 .parent_decl_node = fn_decl.src_node,26062 .parent_decl_node = fn_decl.src_node,
25464 .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param),26063 .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param),
25465 };26064 };
25466 }26065 }
25467 return param_src.toSrcLoc(fn_decl);26066 return param_src.toSrcLoc(fn_decl, mod);
25468 }26067 }
25469 } = .{},26068 } = .{},
25470};26069};
...@@ -25477,34 +26076,30 @@ fn coerceExtra(...@@ -25477,34 +26076,30 @@ fn coerceExtra(
25477 inst_src: LazySrcLoc,26076 inst_src: LazySrcLoc,
25478 opts: CoerceOpts,26077 opts: CoerceOpts,
25479) CoersionError!Air.Inst.Ref {26078) CoersionError!Air.Inst.Ref {
25480 switch (dest_ty_unresolved.tag()) {26079 if (dest_ty_unresolved.isGenericPoison()) return inst;
25481 .generic_poison => return inst,26080 const mod = sema.mod;
25482 else => {},
25483 }
25484 const dest_ty_src = inst_src; // TODO better source location26081 const dest_ty_src = inst_src; // TODO better source location
25485 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);26082 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);
25486 const inst_ty = try sema.resolveTypeFields(sema.typeOf(inst));26083 const inst_ty = try sema.resolveTypeFields(sema.typeOf(inst));
25487 const target = sema.mod.getTarget();26084 const target = mod.getTarget();
25488 // If the types are the same, we can return the operand.26085 // 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))
25490 return inst;26087 return inst;
2549126088
25492 const arena = sema.arena;
25493 const maybe_inst_val = try sema.resolveMaybeUndefVal(inst);26089 const maybe_inst_val = try sema.resolveMaybeUndefVal(inst);
2549426090
25495 var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src);26091 var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src);
25496 if (in_memory_result == .ok) {26092 if (in_memory_result == .ok) {
25497 if (maybe_inst_val) |val| {26093 if (maybe_inst_val) |val| {
25498 // Keep the comptime Value representation; take the new type.26094 return sema.coerceInMemory(block, val, inst_ty, dest_ty, dest_ty_src);
25499 return sema.addConstant(dest_ty, val);
25500 }26095 }
25501 try sema.requireRuntimeBlock(block, inst_src, null);26096 try sema.requireRuntimeBlock(block, inst_src, null);
25502 return block.addBitCast(dest_ty, inst);26097 return block.addBitCast(dest_ty, inst);
25503 }26098 }
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)) {
25508 .Optional => optional: {26103 .Optional => optional: {
25509 // undefined sets the optional bit also to undefined.26104 // undefined sets the optional bit also to undefined.
25510 if (is_undef) {26105 if (is_undef) {
...@@ -25512,18 +26107,22 @@ fn coerceExtra(...@@ -25512,18 +26107,22 @@ fn coerceExtra(
25512 }26107 }
2551326108
25514 // null to ?T26109 // null to ?T
25515 if (inst_ty.zigTypeTag() == .Null) {26110 if (inst_ty.zigTypeTag(mod) == .Null) {
25516 return sema.addConstant(dest_ty, Value.null);26111 return sema.addConstant(dest_ty, (try mod.intern(.{ .opt = .{
26112 .ty = dest_ty.toIntern(),
26113 .val = .none,
26114 } })).toValue());
25517 }26115 }
2551826116
25519 // cast from ?*T and ?[*]T to ?*anyopaque26117 // cast from ?*T and ?[*]T to ?*anyopaque
25520 // but don't do it if the source type is a double pointer26118 // but don't do it if the source type is a double pointer
25521 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and26119 if (dest_ty.isPtrLikeOptional(mod) and
25522 inst_ty.isPtrAtRuntime())26120 dest_ty.elemType2(mod).toIntern() == .anyopaque_type and
26121 inst_ty.isPtrAtRuntime(mod))
25523 anyopaque_check: {26122 anyopaque_check: {
25524 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;26123 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
25525 const elem_ty = inst_ty.elemType2();26124 const elem_ty = inst_ty.elemType2(mod);
25526 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {26125 if (elem_ty.zigTypeTag(mod) == .Pointer or elem_ty.isPtrLikeOptional(mod)) {
25527 in_memory_result = .{ .double_ptr_to_anyopaque = .{26126 in_memory_result = .{ .double_ptr_to_anyopaque = .{
25528 .actual = inst_ty,26127 .actual = inst_ty,
25529 .wanted = dest_ty,26128 .wanted = dest_ty,
...@@ -25532,12 +26131,12 @@ fn coerceExtra(...@@ -25532,12 +26131,12 @@ fn coerceExtra(
25532 }26131 }
25533 // Let the logic below handle wrapping the optional now that26132 // Let the logic below handle wrapping the optional now that
25534 // it has been checked to correctly coerce.26133 // it has been checked to correctly coerce.
25535 if (!inst_ty.isPtrLikeOptional()) break :anyopaque_check;26134 if (!inst_ty.isPtrLikeOptional(mod)) break :anyopaque_check;
25536 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);26135 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
25537 }26136 }
2553826137
25539 // T to ?T26138 // T to ?T
25540 const child_type = try dest_ty.optionalChildAlloc(sema.arena);26139 const child_type = dest_ty.optionalChild(mod);
25541 const intermediate = sema.coerceExtra(block, child_type, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) {26140 const intermediate = sema.coerceExtra(block, child_type, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) {
25542 error.NotCoercible => {26141 error.NotCoercible => {
25543 if (in_memory_result == .no_match) {26142 if (in_memory_result == .no_match) {
...@@ -25551,12 +26150,12 @@ fn coerceExtra(...@@ -25551,12 +26150,12 @@ fn coerceExtra(
25551 return try sema.wrapOptional(block, dest_ty, intermediate, inst_src);26150 return try sema.wrapOptional(block, dest_ty, intermediate, inst_src);
25552 },26151 },
25553 .Pointer => pointer: {26152 .Pointer => pointer: {
25554 const dest_info = dest_ty.ptrInfo().data;26153 const dest_info = dest_ty.ptrInfo(mod);
2555526154
25556 // Function body to function pointer.26155 // Function body to function pointer.
25557 if (inst_ty.zigTypeTag() == .Fn) {26156 if (inst_ty.zigTypeTag(mod) == .Fn) {
25558 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");26157 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
25559 const fn_decl = fn_val.pointerDecl().?;26158 const fn_decl = fn_val.pointerDecl(mod).?;
25560 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);26159 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
25561 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);26160 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
25562 }26161 }
...@@ -25564,13 +26163,13 @@ fn coerceExtra(...@@ -25564,13 +26163,13 @@ fn coerceExtra(
25564 // *T to *[1]T26163 // *T to *[1]T
25565 single_item: {26164 single_item: {
25566 if (dest_info.size != .One) break :single_item;26165 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;
25568 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;26167 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);
25570 const array_ty = dest_info.pointee_type;26169 const array_ty = dest_info.pointee_type;
25571 if (array_ty.zigTypeTag() != .Array) break :single_item;26170 if (array_ty.zigTypeTag(mod) != .Array) break :single_item;
25572 const array_elem_ty = array_ty.childType();26171 const array_elem_ty = array_ty.childType(mod);
25573 if (array_ty.arrayLen() != 1) break :single_item;26172 if (array_ty.arrayLen(mod) != 1) break :single_item;
25574 const dest_is_mut = dest_info.mutable;26173 const dest_is_mut = dest_info.mutable;
25575 switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {26174 switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
25576 .ok => {},26175 .ok => {},
...@@ -25581,11 +26180,11 @@ fn coerceExtra(...@@ -25581,11 +26180,11 @@ fn coerceExtra(
2558126180
25582 // Coercions where the source is a single pointer to an array.26181 // Coercions where the source is a single pointer to an array.
25583 src_array_ptr: {26182 src_array_ptr: {
25584 if (!inst_ty.isSinglePointer()) break :src_array_ptr;26183 if (!inst_ty.isSinglePointer(mod)) break :src_array_ptr;
25585 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;26184 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
25586 const array_ty = inst_ty.childType();26185 const array_ty = inst_ty.childType(mod);
25587 if (array_ty.zigTypeTag() != .Array) break :src_array_ptr;26186 if (array_ty.zigTypeTag(mod) != .Array) break :src_array_ptr;
25588 const array_elem_type = array_ty.childType();26187 const array_elem_type = array_ty.childType(mod);
25589 const dest_is_mut = dest_info.mutable;26188 const dest_is_mut = dest_info.mutable;
2559026189
25591 const dst_elem_type = dest_info.pointee_type;26190 const dst_elem_type = dest_info.pointee_type;
...@@ -25603,8 +26202,8 @@ fn coerceExtra(...@@ -25603,8 +26202,8 @@ fn coerceExtra(
25603 }26202 }
2560426203
25605 if (dest_info.sentinel) |dest_sent| {26204 if (dest_info.sentinel) |dest_sent| {
25606 if (array_ty.sentinel()) |inst_sent| {26205 if (array_ty.sentinel(mod)) |inst_sent| {
25607 if (!dest_sent.eql(inst_sent, dst_elem_type, sema.mod)) {26206 if (!dest_sent.eql(inst_sent, dst_elem_type, mod)) {
25608 in_memory_result = .{ .ptr_sentinel = .{26207 in_memory_result = .{ .ptr_sentinel = .{
25609 .actual = inst_sent,26208 .actual = inst_sent,
25610 .wanted = dest_sent,26209 .wanted = dest_sent,
...@@ -25614,7 +26213,7 @@ fn coerceExtra(...@@ -25614,7 +26213,7 @@ fn coerceExtra(
25614 }26213 }
25615 } else {26214 } else {
25616 in_memory_result = .{ .ptr_sentinel = .{26215 in_memory_result = .{ .ptr_sentinel = .{
25617 .actual = Value.initTag(.unreachable_value),26216 .actual = Value.@"unreachable",
25618 .wanted = dest_sent,26217 .wanted = dest_sent,
25619 .ty = dst_elem_type,26218 .ty = dst_elem_type,
25620 } };26219 } };
...@@ -25640,11 +26239,11 @@ fn coerceExtra(...@@ -25640,11 +26239,11 @@ fn coerceExtra(
25640 }26239 }
2564126240
25642 // coercion from C pointer26241 // coercion from C pointer
25643 if (inst_ty.isCPtr()) src_c_ptr: {26242 if (inst_ty.isCPtr(mod)) src_c_ptr: {
25644 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :src_c_ptr;26243 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :src_c_ptr;
25645 // In this case we must add a safety check because the C pointer26244 // In this case we must add a safety check because the C pointer
25646 // could be null.26245 // could be null.
25647 const src_elem_ty = inst_ty.childType();26246 const src_elem_ty = inst_ty.childType(mod);
25648 const dest_is_mut = dest_info.mutable;26247 const dest_is_mut = dest_info.mutable;
25649 const dst_elem_type = dest_info.pointee_type;26248 const dst_elem_type = dest_info.pointee_type;
25650 switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {26249 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(...@@ -25656,18 +26255,18 @@ fn coerceExtra(
2565626255
25657 // cast from *T and [*]T to *anyopaque26256 // cast from *T and [*]T to *anyopaque
25658 // but don't do it if the source type is a double pointer26257 // 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: {
25660 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;26259 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
25661 const elem_ty = inst_ty.elemType2();26260 const elem_ty = inst_ty.elemType2(mod);
25662 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {26261 if (elem_ty.zigTypeTag(mod) == .Pointer or elem_ty.isPtrLikeOptional(mod)) {
25663 in_memory_result = .{ .double_ptr_to_anyopaque = .{26262 in_memory_result = .{ .double_ptr_to_anyopaque = .{
25664 .actual = inst_ty,26263 .actual = inst_ty,
25665 .wanted = dest_ty,26264 .wanted = dest_ty,
25666 } };26265 } };
25667 break :pointer;26266 break :pointer;
25668 }26267 }
25669 if (dest_ty.isSlice()) break :to_anyopaque;26268 if (dest_ty.isSlice(mod)) break :to_anyopaque;
25670 if (inst_ty.isSlice()) {26269 if (inst_ty.isSlice(mod)) {
25671 in_memory_result = .{ .slice_to_anyopaque = .{26270 in_memory_result = .{ .slice_to_anyopaque = .{
25672 .actual = inst_ty,26271 .actual = inst_ty,
25673 .wanted = dest_ty,26272 .wanted = dest_ty,
...@@ -25679,9 +26278,9 @@ fn coerceExtra(...@@ -25679,9 +26278,9 @@ fn coerceExtra(
2567926278
25680 switch (dest_info.size) {26279 switch (dest_info.size) {
25681 // coercion to C pointer26280 // coercion to C pointer
25682 .C => switch (inst_ty.zigTypeTag()) {26281 .C => switch (inst_ty.zigTypeTag(mod)) {
25683 .Null => {26282 .Null => {
25684 return sema.addConstant(dest_ty, Value.null);26283 return sema.addConstant(dest_ty, try mod.getCoerced(Value.null, dest_ty));
25685 },26284 },
25686 .ComptimeInt => {26285 .ComptimeInt => {
25687 const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) {26286 const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) {
...@@ -25691,7 +26290,7 @@ fn coerceExtra(...@@ -25691,7 +26290,7 @@ fn coerceExtra(
25691 return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src);26290 return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src);
25692 },26291 },
25693 .Int => {26292 .Int => {
25694 const ptr_size_ty = switch (inst_ty.intInfo(target).signedness) {26293 const ptr_size_ty = switch (inst_ty.intInfo(mod).signedness) {
25695 .signed => Type.isize,26294 .signed => Type.isize,
25696 .unsigned => Type.usize,26295 .unsigned => Type.usize,
25697 };26296 };
...@@ -25707,7 +26306,7 @@ fn coerceExtra(...@@ -25707,7 +26306,7 @@ fn coerceExtra(
25707 },26306 },
25708 .Pointer => p: {26307 .Pointer => p: {
25709 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p;26308 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);
25711 switch (try sema.coerceInMemoryAllowed(26310 switch (try sema.coerceInMemoryAllowed(
25712 block,26311 block,
25713 dest_info.pointee_type,26312 dest_info.pointee_type,
...@@ -25723,7 +26322,7 @@ fn coerceExtra(...@@ -25723,7 +26322,7 @@ fn coerceExtra(
25723 if (inst_info.size == .Slice) {26322 if (inst_info.size == .Slice) {
25724 assert(dest_info.sentinel == null);26323 assert(dest_info.sentinel == null);
25725 if (inst_info.sentinel == null or26324 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))
25727 break :p;26326 break :p;
2572826327
25729 const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);26328 const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
...@@ -25733,11 +26332,11 @@ fn coerceExtra(...@@ -25733,11 +26332,11 @@ fn coerceExtra(
25733 },26332 },
25734 else => {},26333 else => {},
25735 },26334 },
25736 .One => switch (dest_info.pointee_type.zigTypeTag()) {26335 .One => switch (dest_info.pointee_type.zigTypeTag(mod)) {
25737 .Union => {26336 .Union => {
25738 // pointer to anonymous struct to pointer to union26337 // pointer to anonymous struct to pointer to union
25739 if (inst_ty.isSinglePointer() and26338 if (inst_ty.isSinglePointer(mod) and
25740 inst_ty.childType().isAnonStruct() and26339 inst_ty.childType(mod).isAnonStruct(mod) and
25741 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))26340 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
25742 {26341 {
25743 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);26342 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
...@@ -25745,8 +26344,8 @@ fn coerceExtra(...@@ -25745,8 +26344,8 @@ fn coerceExtra(
25745 },26344 },
25746 .Struct => {26345 .Struct => {
25747 // pointer to anonymous struct to pointer to struct26346 // pointer to anonymous struct to pointer to struct
25748 if (inst_ty.isSinglePointer() and26347 if (inst_ty.isSinglePointer(mod) and
25749 inst_ty.childType().isAnonStruct() and26348 inst_ty.childType(mod).isAnonStruct(mod) and
25750 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))26349 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
25751 {26350 {
25752 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src) catch |err| switch (err) {26351 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src) catch |err| switch (err) {
...@@ -25757,8 +26356,8 @@ fn coerceExtra(...@@ -25757,8 +26356,8 @@ fn coerceExtra(
25757 },26356 },
25758 .Array => {26357 .Array => {
25759 // pointer to tuple to pointer to array26358 // pointer to tuple to pointer to array
25760 if (inst_ty.isSinglePointer() and26359 if (inst_ty.isSinglePointer(mod) and
25761 inst_ty.childType().isTuple() and26360 inst_ty.childType(mod).isTuple(mod) and
25762 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))26361 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
25763 {26362 {
25764 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);26363 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
...@@ -25767,38 +26366,38 @@ fn coerceExtra(...@@ -25767,38 +26366,38 @@ fn coerceExtra(
25767 else => {},26366 else => {},
25768 },26367 },
25769 .Slice => to_slice: {26368 .Slice => to_slice: {
25770 if (inst_ty.zigTypeTag() == .Array) {26369 if (inst_ty.zigTypeTag(mod) == .Array) {
25771 return sema.fail(26370 return sema.fail(
25772 block,26371 block,
25773 inst_src,26372 inst_src,
25774 "array literal requires address-of operator (&) to coerce to slice type '{}'",26373 "array literal requires address-of operator (&) to coerce to slice type '{}'",
25775 .{dest_ty.fmt(sema.mod)},26374 .{dest_ty.fmt(mod)},
25776 );26375 );
25777 }26376 }
2577826377
25779 if (!inst_ty.isSinglePointer()) break :to_slice;26378 if (!inst_ty.isSinglePointer(mod)) break :to_slice;
25780 const inst_child_ty = inst_ty.childType();26379 const inst_child_ty = inst_ty.childType(mod);
25781 if (!inst_child_ty.isTuple()) break :to_slice;26380 if (!inst_child_ty.isTuple(mod)) break :to_slice;
2578226381
25783 // empty tuple to zero-length slice26382 // empty tuple to zero-length slice
25784 // note that this allows coercing to a mutable slice.26383 // note that this allows coercing to a mutable slice.
25785 if (inst_child_ty.structFieldCount() == 0) {26384 if (inst_child_ty.structFieldCount(mod) == 0) {
25786 // Optional slice is represented with a null pointer so26385 // Optional slice is represented with a null pointer so
25787 // we use a dummy pointer value with the required alignment.26386 // we use a dummy pointer value with the required alignment.
25788 const slice_val = try Value.Tag.slice.create(sema.arena, .{26387 return sema.addConstant(dest_ty, (try mod.intern(.{ .ptr = .{
25789 .ptr = if (dest_info.@"align" != 0)26388 .ty = dest_ty.toIntern(),
25790 try Value.Tag.int_u64.create(sema.arena, dest_info.@"align")26389 .addr = .{ .int = (if (dest_info.@"align" != 0)
26390 try mod.intValue(Type.usize, dest_info.@"align")
25791 else26391 else
25792 try dest_info.pointee_type.lazyAbiAlignment(target, sema.arena),26392 try mod.getCoerced(try dest_info.pointee_type.lazyAbiAlignment(mod), Type.usize)).toIntern() },
25793 .len = Value.zero,26393 .len = (try mod.intValue(Type.usize, 0)).toIntern(),
25794 });26394 } })).toValue());
25795 return sema.addConstant(dest_ty, slice_val);
25796 }26395 }
2579726396
25798 // pointer to tuple to slice26397 // pointer to tuple to slice
25799 if (dest_info.mutable) {26398 if (dest_info.mutable) {
25800 const err_msg = err_msg: {26399 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)});
25802 errdefer err_msg.deinit(sema.gpa);26401 errdefer err_msg.deinit(sema.gpa);
25803 try sema.errNote(block, dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});26402 try sema.errNote(block, dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
25804 break :err_msg err_msg;26403 break :err_msg err_msg;
...@@ -25808,9 +26407,9 @@ fn coerceExtra(...@@ -25808,9 +26407,9 @@ fn coerceExtra(
25808 return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src);26407 return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src);
25809 },26408 },
25810 .Many => p: {26409 .Many => p: {
25811 if (!inst_ty.isSlice()) break :p;26410 if (!inst_ty.isSlice(mod)) break :p;
25812 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p;26411 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
25815 switch (try sema.coerceInMemoryAllowed(26414 switch (try sema.coerceInMemoryAllowed(
25816 block,26415 block,
...@@ -25826,7 +26425,11 @@ fn coerceExtra(...@@ -25826,7 +26425,11 @@ fn coerceExtra(
25826 }26425 }
2582726426
25828 if (dest_info.sentinel == null or inst_info.sentinel == null or26427 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 ))
25830 break :p;26433 break :p;
2583126434
25832 const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);26435 const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
...@@ -25834,25 +26437,25 @@ fn coerceExtra(...@@ -25834,25 +26437,25 @@ fn coerceExtra(
25834 },26437 },
25835 }26438 }
25836 },26439 },
25837 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) {26440 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag(mod)) {
25838 .Float, .ComptimeFloat => float: {26441 .Float, .ComptimeFloat => float: {
25839 if (is_undef) {26442 if (is_undef) {
25840 return sema.addConstUndef(dest_ty);26443 return sema.addConstUndef(dest_ty);
25841 }26444 }
25842 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {26445 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
25843 if (dest_ty.zigTypeTag() == .ComptimeInt) {26446 if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {
25844 if (!opts.report_err) return error.NotCoercible;26447 if (!opts.report_err) return error.NotCoercible;
25845 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");26448 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");
25846 }26449 }
25847 break :float;26450 break :float;
25848 };26451 };
2584926452
25850 if (val.floatHasFraction()) {26453 if (val.floatHasFraction(mod)) {
25851 return sema.fail(26454 return sema.fail(
25852 block,26455 block,
25853 inst_src,26456 inst_src,
25854 "fractional component prevents float value '{}' from coercion to type '{}'",26457 "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) },
25856 );26459 );
25857 }26460 }
25858 const result_val = try sema.floatToInt(block, inst_src, val, inst_ty, dest_ty);26461 const result_val = try sema.floatToInt(block, inst_src, val, inst_ty, dest_ty);
...@@ -25866,19 +26469,19 @@ fn coerceExtra(...@@ -25866,19 +26469,19 @@ fn coerceExtra(
25866 // comptime-known integer to other number26469 // comptime-known integer to other number
25867 if (!(try sema.intFitsInType(val, dest_ty, null))) {26470 if (!(try sema.intFitsInType(val, dest_ty, null))) {
25868 if (!opts.report_err) return error.NotCoercible;26471 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) });
25870 }26473 }
25871 return try sema.addConstant(dest_ty, val);26474 return try sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
25872 }26475 }
25873 if (dest_ty.zigTypeTag() == .ComptimeInt) {26476 if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {
25874 if (!opts.report_err) return error.NotCoercible;26477 if (!opts.report_err) return error.NotCoercible;
25875 if (opts.no_cast_to_comptime_int) return inst;26478 if (opts.no_cast_to_comptime_int) return inst;
25876 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");26479 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");
25877 }26480 }
2587826481
25879 // integer widening26482 // integer widening
25880 const dst_info = dest_ty.intInfo(target);26483 const dst_info = dest_ty.intInfo(mod);
25881 const src_info = inst_ty.intInfo(target);26484 const src_info = inst_ty.intInfo(mod);
25882 if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or26485 if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or
25883 // small enough unsigned ints can get casted to large enough signed ints26486 // small enough unsigned ints can get casted to large enough signed ints
25884 (dst_info.signedness == .signed and dst_info.bits > src_info.bits))26487 (dst_info.signedness == .signed and dst_info.bits > src_info.bits))
...@@ -25892,10 +26495,10 @@ fn coerceExtra(...@@ -25892,10 +26495,10 @@ fn coerceExtra(
25892 },26495 },
25893 else => {},26496 else => {},
25894 },26497 },
25895 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {26498 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag(mod)) {
25896 .ComptimeFloat => {26499 .ComptimeFloat => {
25897 const val = try sema.resolveConstValue(block, .unneeded, inst, "");26500 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);
25899 return try sema.addConstant(dest_ty, result_val);26502 return try sema.addConstant(dest_ty, result_val);
25900 },26503 },
25901 .Float => {26504 .Float => {
...@@ -25903,17 +26506,17 @@ fn coerceExtra(...@@ -25903,17 +26506,17 @@ fn coerceExtra(
25903 return sema.addConstUndef(dest_ty);26506 return sema.addConstUndef(dest_ty);
25904 }26507 }
25905 if (try sema.resolveMaybeUndefVal(inst)) |val| {26508 if (try sema.resolveMaybeUndefVal(inst)) |val| {
25906 const result_val = try val.floatCast(sema.arena, dest_ty, target);26509 const result_val = try val.floatCast(dest_ty, mod);
25907 if (!val.eql(result_val, inst_ty, sema.mod)) {26510 if (!val.eql(try result_val.floatCast(inst_ty, mod), inst_ty, mod)) {
25908 return sema.fail(26511 return sema.fail(
25909 block,26512 block,
25910 inst_src,26513 inst_src,
25911 "type '{}' cannot represent float value '{}'",26514 "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) },
25913 );26516 );
25914 }26517 }
25915 return try sema.addConstant(dest_ty, result_val);26518 return try sema.addConstant(dest_ty, result_val);
25916 } else if (dest_ty.zigTypeTag() == .ComptimeFloat) {26519 } else if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) {
25917 if (!opts.report_err) return error.NotCoercible;26520 if (!opts.report_err) return error.NotCoercible;
25918 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");26521 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");
25919 }26522 }
...@@ -25931,13 +26534,13 @@ fn coerceExtra(...@@ -25931,13 +26534,13 @@ fn coerceExtra(
25931 return sema.addConstUndef(dest_ty);26534 return sema.addConstUndef(dest_ty);
25932 }26535 }
25933 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {26536 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
25934 if (dest_ty.zigTypeTag() == .ComptimeFloat) {26537 if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) {
25935 if (!opts.report_err) return error.NotCoercible;26538 if (!opts.report_err) return error.NotCoercible;
25936 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");26539 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");
25937 }26540 }
25938 break :int;26541 break :int;
25939 };26542 };
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);
25941 // TODO implement this compile error26544 // TODO implement this compile error
25942 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);26545 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);
25943 //if (!int_again_val.eql(val, inst_ty, mod)) {26546 //if (!int_again_val.eql(val, inst_ty, mod)) {
...@@ -25945,7 +26548,7 @@ fn coerceExtra(...@@ -25945,7 +26548,7 @@ fn coerceExtra(
25945 // block,26548 // block,
25946 // inst_src,26549 // inst_src,
25947 // "type '{}' cannot represent integer value '{}'",26550 // "type '{}' cannot represent integer value '{}'",
25948 // .{ dest_ty.fmt(sema.mod), val },26551 // .{ dest_ty.fmt(mod), val },
25949 // );26552 // );
25950 //}26553 //}
25951 return try sema.addConstant(dest_ty, result_val);26554 return try sema.addConstant(dest_ty, result_val);
...@@ -25955,18 +26558,18 @@ fn coerceExtra(...@@ -25955,18 +26558,18 @@ fn coerceExtra(
25955 },26558 },
25956 else => {},26559 else => {},
25957 },26560 },
25958 .Enum => switch (inst_ty.zigTypeTag()) {26561 .Enum => switch (inst_ty.zigTypeTag(mod)) {
25959 .EnumLiteral => {26562 .EnumLiteral => {
25960 // enum literal to enum26563 // enum literal to enum
25961 const val = try sema.resolveConstValue(block, .unneeded, inst, "");26564 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
25962 const bytes = val.castTag(.enum_literal).?.data;26565 const string = mod.intern_pool.indexToKey(val.toIntern()).enum_literal;
25963 const field_index = dest_ty.enumFieldIndex(bytes) orelse {26566 const field_index = dest_ty.enumFieldIndex(string, mod) orelse {
25964 const msg = msg: {26567 const msg = msg: {
25965 const msg = try sema.errMsg(26568 const msg = try sema.errMsg(
25966 block,26569 block,
25967 inst_src,26570 inst_src,
25968 "no field named '{s}' in enum '{}'",26571 "no field named '{}' in enum '{}'",
25969 .{ bytes, dest_ty.fmt(sema.mod) },26572 .{ string.fmt(&mod.intern_pool), dest_ty.fmt(mod) },
25970 );26573 );
25971 errdefer msg.destroy(sema.gpa);26574 errdefer msg.destroy(sema.gpa);
25972 try sema.addDeclaredHereNote(msg, dest_ty);26575 try sema.addDeclaredHereNote(msg, dest_ty);
...@@ -25976,13 +26579,13 @@ fn coerceExtra(...@@ -25976,13 +26579,13 @@ fn coerceExtra(
25976 };26579 };
25977 return sema.addConstant(26580 return sema.addConstant(
25978 dest_ty,26581 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)),
25980 );26583 );
25981 },26584 },
25982 .Union => blk: {26585 .Union => blk: {
25983 // union to its own tag type26586 // union to its own tag type
25984 const union_tag_ty = inst_ty.unionTagType() orelse break :blk;26587 const union_tag_ty = inst_ty.unionTagType(mod) orelse break :blk;
25985 if (union_tag_ty.eql(dest_ty, sema.mod)) {26588 if (union_tag_ty.eql(dest_ty, mod)) {
25986 return sema.unionToTag(block, dest_ty, inst, inst_src);26589 return sema.unionToTag(block, dest_ty, inst, inst_src);
25987 }26590 }
25988 },26591 },
...@@ -25991,27 +26594,33 @@ fn coerceExtra(...@@ -25991,27 +26594,33 @@ fn coerceExtra(
25991 },26594 },
25992 else => {},26595 else => {},
25993 },26596 },
25994 .ErrorUnion => switch (inst_ty.zigTypeTag()) {26597 .ErrorUnion => switch (inst_ty.zigTypeTag(mod)) {
25995 .ErrorUnion => eu: {26598 .ErrorUnion => eu: {
25996 if (maybe_inst_val) |inst_val| {26599 if (maybe_inst_val) |inst_val| {
25997 switch (inst_val.tag()) {26600 switch (inst_val.toIntern()) {
25998 .undef => return sema.addConstUndef(dest_ty),26601 .undef => return sema.addConstUndef(dest_ty),
25999 .eu_payload => {26602 else => switch (mod.intern_pool.indexToKey(inst_val.toIntern())) {
26000 const payload = try sema.addConstant(26603 .error_union => |error_union| switch (error_union.val) {
26001 inst_ty.errorUnionPayload(),26604 .err_name => |err_name| {
26002 inst_val.castTag(.eu_payload).?.data,26605 const error_set_ty = inst_ty.errorUnionSet(mod);
26003 );26606 const error_set_val = try sema.addConstant(error_set_ty, (try mod.intern(.{ .err = .{
26004 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {26607 .ty = error_set_ty.toIntern(),
26005 error.NotCoercible => break :eu,26608 .name = err_name,
26006 else => |e| return e,26609 } })).toValue());
26007 };26610 return sema.wrapErrorUnionSet(block, dest_ty, error_set_val, inst_src);
26008 },26611 },
26009 else => {26612 .payload => |payload| {
26010 const error_set = try sema.addConstant(26613 const payload_val = try sema.addConstant(
26011 inst_ty.errorUnionSet(),26614 inst_ty.errorUnionPayload(mod),
26012 inst_val,26615 payload.toValue(),
26013 );26616 );
26014 return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src);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,
26015 },26624 },
26016 }26625 }
26017 }26626 }
...@@ -26031,10 +26640,10 @@ fn coerceExtra(...@@ -26031,10 +26640,10 @@ fn coerceExtra(
26031 };26640 };
26032 },26641 },
26033 },26642 },
26034 .Union => switch (inst_ty.zigTypeTag()) {26643 .Union => switch (inst_ty.zigTypeTag(mod)) {
26035 .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),26644 .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),
26036 .Struct => {26645 .Struct => {
26037 if (inst_ty.isAnonStruct()) {26646 if (inst_ty.isAnonStruct(mod)) {
26038 return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src);26647 return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src);
26039 }26648 }
26040 },26649 },
...@@ -26043,13 +26652,13 @@ fn coerceExtra(...@@ -26043,13 +26652,13 @@ fn coerceExtra(
26043 },26652 },
26044 else => {},26653 else => {},
26045 },26654 },
26046 .Array => switch (inst_ty.zigTypeTag()) {26655 .Array => switch (inst_ty.zigTypeTag(mod)) {
26047 .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),26656 .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),
26048 .Struct => {26657 .Struct => {
26049 if (inst == .empty_struct) {26658 if (inst == .empty_struct) {
26050 return sema.arrayInitEmpty(block, inst_src, dest_ty);26659 return sema.arrayInitEmpty(block, inst_src, dest_ty);
26051 }26660 }
26052 if (inst_ty.isTuple()) {26661 if (inst_ty.isTuple(mod)) {
26053 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);26662 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
26054 }26663 }
26055 },26664 },
...@@ -26058,10 +26667,10 @@ fn coerceExtra(...@@ -26058,10 +26667,10 @@ fn coerceExtra(
26058 },26667 },
26059 else => {},26668 else => {},
26060 },26669 },
26061 .Vector => switch (inst_ty.zigTypeTag()) {26670 .Vector => switch (inst_ty.zigTypeTag(mod)) {
26062 .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),26671 .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),
26063 .Struct => {26672 .Struct => {
26064 if (inst_ty.isTuple()) {26673 if (inst_ty.isTuple(mod)) {
26065 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);26674 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
26066 }26675 }
26067 },26676 },
...@@ -26074,7 +26683,7 @@ fn coerceExtra(...@@ -26074,7 +26683,7 @@ fn coerceExtra(
26074 if (inst == .empty_struct) {26683 if (inst == .empty_struct) {
26075 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);26684 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);
26076 }26685 }
26077 if (inst_ty.isTupleOrAnonStruct()) {26686 if (inst_ty.isTupleOrAnonStruct(mod)) {
26078 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {26687 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {
26079 error.NotCoercible => break :blk,26688 error.NotCoercible => break :blk,
26080 else => |e| return e,26689 else => |e| return e,
...@@ -26093,35 +26702,34 @@ fn coerceExtra(...@@ -26093,35 +26702,34 @@ fn coerceExtra(
2609326702
26094 if (!opts.report_err) return error.NotCoercible;26703 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) {
26097 const msg = msg: {26706 const msg = msg: {
26098 const msg = try sema.errMsg(block, inst_src, "function declared 'noreturn' returns", .{});26707 const msg = try sema.errMsg(block, inst_src, "function declared 'noreturn' returns", .{});
26099 errdefer msg.destroy(sema.gpa);26708 errdefer msg.destroy(sema.gpa);
2610026709
26101 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };26710 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
26102 const src_decl = sema.mod.declPtr(sema.func.?.owner_decl);26711 const src_decl = mod.declPtr(sema.func.?.owner_decl);
26103 try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "'noreturn' declared here", .{});26712 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
26104 break :msg msg;26713 break :msg msg;
26105 };26714 };
26106 return sema.failWithOwnedErrorMsg(msg);26715 return sema.failWithOwnedErrorMsg(msg);
26107 }26716 }
2610826717
26109 const msg = msg: {26718 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) });
26111 errdefer msg.destroy(sema.gpa);26720 errdefer msg.destroy(sema.gpa);
2611226721
26113 // E!T to T26722 // E!T to T
26114 if (inst_ty.zigTypeTag() == .ErrorUnion and26723 if (inst_ty.zigTypeTag(mod) == .ErrorUnion and
26115 (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)26724 (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(mod), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
26116 {26725 {
26117 try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{});26726 try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{});
26118 try sema.errNote(block, inst_src, msg, "consider using 'try', 'catch', or 'if'", .{});26727 try sema.errNote(block, inst_src, msg, "consider using 'try', 'catch', or 'if'", .{});
26119 }26728 }
2612026729
26121 // ?T to T26730 // ?T to T
26122 var buf: Type.Payload.ElemType = undefined;26731 if (inst_ty.zigTypeTag(mod) == .Optional and
26123 if (inst_ty.zigTypeTag() == .Optional and26732 (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(mod), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
26124 (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(&buf), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
26125 {26733 {
26126 try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{});26734 try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{});
26127 try sema.errNote(block, inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{});26735 try sema.errNote(block, inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{});
...@@ -26130,18 +26738,18 @@ fn coerceExtra(...@@ -26130,18 +26738,18 @@ fn coerceExtra(
26130 try in_memory_result.report(sema, block, inst_src, msg);26738 try in_memory_result.report(sema, block, inst_src, msg);
2613126739
26132 // Add notes about function return type26740 // 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) {
26134 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };26742 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
26135 const src_decl = sema.mod.declPtr(sema.func.?.owner_decl);26743 const src_decl = mod.declPtr(sema.func.?.owner_decl);
26136 if (inst_ty.isError() and !dest_ty.isError()) {26744 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {
26137 try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function cannot return an error", .{});26745 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
26138 } else {26746 } 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", .{});
26140 }26748 }
26141 }26749 }
2614226750
26143 if (try opts.param_src.get(sema)) |param_src| {26751 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", .{});
26145 }26753 }
2614626754
26147 // TODO maybe add "cannot store an error in type '{}'" note26755 // TODO maybe add "cannot store an error in type '{}'" note
...@@ -26151,6 +26759,84 @@ fn coerceExtra(...@@ -26151,6 +26759,84 @@ fn coerceExtra(
26151 return sema.failWithOwnedErrorMsg(msg);26759 return sema.failWithOwnedErrorMsg(msg);
26152}26760}
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
26154const InMemoryCoercionResult = union(enum) {26840const InMemoryCoercionResult = union(enum) {
26155 ok,26841 ok,
26156 no_match: Pair,26842 no_match: Pair,
...@@ -26164,7 +26850,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -26164,7 +26850,7 @@ const InMemoryCoercionResult = union(enum) {
26164 optional_shape: Pair,26850 optional_shape: Pair,
26165 optional_child: PairAndChild,26851 optional_child: PairAndChild,
26166 from_anyerror,26852 from_anyerror,
26167 missing_error: []const []const u8,26853 missing_error: []const InternPool.NullTerminatedString,
26168 /// true if wanted is var args26854 /// true if wanted is var args
26169 fn_var_args: bool,26855 fn_var_args: bool,
26170 /// true if wanted is generic26856 /// true if wanted is generic
...@@ -26264,6 +26950,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -26264,6 +26950,7 @@ const InMemoryCoercionResult = union(enum) {
26264 }26950 }
2626526951
26266 fn report(res: *const InMemoryCoercionResult, sema: *Sema, block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg) !void {26952 fn report(res: *const InMemoryCoercionResult, sema: *Sema, block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg) !void {
26953 const mod = sema.mod;
26267 var cur = res;26954 var cur = res;
26268 while (true) switch (cur.*) {26955 while (true) switch (cur.*) {
26269 .ok => unreachable,26956 .ok => unreachable,
...@@ -26280,7 +26967,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -26280,7 +26967,7 @@ const InMemoryCoercionResult = union(enum) {
26280 },26967 },
26281 .error_union_payload => |pair| {26968 .error_union_payload => |pair| {
26282 try sema.errNote(block, src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{26969 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),
26284 });26971 });
26285 cur = pair.child;26972 cur = pair.child;
26286 },26973 },
...@@ -26291,20 +26978,20 @@ const InMemoryCoercionResult = union(enum) {...@@ -26291,20 +26978,20 @@ const InMemoryCoercionResult = union(enum) {
26291 break;26978 break;
26292 },26979 },
26293 .array_sentinel => |sentinel| {26980 .array_sentinel => |sentinel| {
26294 if (sentinel.actual.tag() != .unreachable_value) {26981 if (sentinel.actual.toIntern() != .unreachable_value) {
26295 try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{26982 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),
26297 });26984 });
26298 } else {26985 } else {
26299 try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{26986 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),
26301 });26988 });
26302 }26989 }
26303 break;26990 break;
26304 },26991 },
26305 .array_elem => |pair| {26992 .array_elem => |pair| {
26306 try sema.errNote(block, src, msg, "array element type '{}' cannot cast into array element type '{}'", .{26993 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),
26308 });26995 });
26309 cur = pair.child;26996 cur = pair.child;
26310 },26997 },
...@@ -26316,21 +27003,19 @@ const InMemoryCoercionResult = union(enum) {...@@ -26316,21 +27003,19 @@ const InMemoryCoercionResult = union(enum) {
26316 },27003 },
26317 .vector_elem => |pair| {27004 .vector_elem => |pair| {
26318 try sema.errNote(block, src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{27005 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),
26320 });27007 });
26321 cur = pair.child;27008 cur = pair.child;
26322 },27009 },
26323 .optional_shape => |pair| {27010 .optional_shape => |pair| {
26324 var buf_actual: Type.Payload.ElemType = undefined;
26325 var buf_wanted: Type.Payload.ElemType = undefined;
26326 try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{27011 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),
26328 });27013 });
26329 break;27014 break;
26330 },27015 },
26331 .optional_child => |pair| {27016 .optional_child => |pair| {
26332 try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{27017 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),
26334 });27019 });
26335 cur = pair.child;27020 cur = pair.child;
26336 },27021 },
...@@ -26340,7 +27025,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -26340,7 +27025,7 @@ const InMemoryCoercionResult = union(enum) {
26340 },27025 },
26341 .missing_error => |missing_errors| {27026 .missing_error => |missing_errors| {
26342 for (missing_errors) |err| {27027 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)});
26344 }27029 }
26345 break;27030 break;
26346 },27031 },
...@@ -26394,7 +27079,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -26394,7 +27079,7 @@ const InMemoryCoercionResult = union(enum) {
26394 },27079 },
26395 .fn_param => |param| {27080 .fn_param => |param| {
26396 try sema.errNote(block, src, msg, "parameter {d} '{}' cannot cast into '{}'", .{27081 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),
26398 });27083 });
26399 cur = param.child;27084 cur = param.child;
26400 },27085 },
...@@ -26404,13 +27089,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -26404,13 +27089,13 @@ const InMemoryCoercionResult = union(enum) {
26404 },27089 },
26405 .fn_return_type => |pair| {27090 .fn_return_type => |pair| {
26406 try sema.errNote(block, src, msg, "return type '{}' cannot cast into return type '{}'", .{27091 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),
26408 });27093 });
26409 cur = pair.child;27094 cur = pair.child;
26410 },27095 },
26411 .ptr_child => |pair| {27096 .ptr_child => |pair| {
26412 try sema.errNote(block, src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{27097 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),
26414 });27099 });
26415 cur = pair.child;27100 cur = pair.child;
26416 },27101 },
...@@ -26419,13 +27104,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -26419,13 +27104,13 @@ const InMemoryCoercionResult = union(enum) {
26419 break;27104 break;
26420 },27105 },
26421 .ptr_sentinel => |sentinel| {27106 .ptr_sentinel => |sentinel| {
26422 if (sentinel.actual.tag() != .unreachable_value) {27107 if (sentinel.actual.toIntern() != .unreachable_value) {
26423 try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{27108 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),
26425 });27110 });
26426 } else {27111 } else {
26427 try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{27112 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),
26429 });27114 });
26430 }27115 }
26431 break;27116 break;
...@@ -26445,15 +27130,15 @@ const InMemoryCoercionResult = union(enum) {...@@ -26445,15 +27130,15 @@ const InMemoryCoercionResult = union(enum) {
26445 break;27130 break;
26446 },27131 },
26447 .ptr_allowzero => |pair| {27132 .ptr_allowzero => |pair| {
26448 const wanted_allow_zero = pair.wanted.ptrAllowsZero();27133 const wanted_allow_zero = pair.wanted.ptrAllowsZero(mod);
26449 const actual_allow_zero = pair.actual.ptrAllowsZero();27134 const actual_allow_zero = pair.actual.ptrAllowsZero(mod);
26450 if (actual_allow_zero and !wanted_allow_zero) {27135 if (actual_allow_zero and !wanted_allow_zero) {
26451 try sema.errNote(block, src, msg, "'{}' could have null values which are illegal in type '{}'", .{27136 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),
26453 });27138 });
26454 } else {27139 } else {
26455 try sema.errNote(block, src, msg, "mutable '{}' allows illegal null values stored to type '{}'", .{27140 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),
26457 });27142 });
26458 }27143 }
26459 break;27144 break;
...@@ -26479,13 +27164,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -26479,13 +27164,13 @@ const InMemoryCoercionResult = union(enum) {
26479 },27164 },
26480 .double_ptr_to_anyopaque => |pair| {27165 .double_ptr_to_anyopaque => |pair| {
26481 try sema.errNote(block, src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{27166 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),
26483 });27168 });
26484 break;27169 break;
26485 },27170 },
26486 .slice_to_anyopaque => |pair| {27171 .slice_to_anyopaque => |pair| {
26487 try sema.errNote(block, src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{27172 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),
26489 });27174 });
26490 try sema.errNote(block, src, msg, "consider using '.ptr'", .{});27175 try sema.errNote(block, src, msg, "consider using '.ptr'", .{});
26491 break;27176 break;
...@@ -26522,13 +27207,18 @@ fn coerceInMemoryAllowed(...@@ -26522,13 +27207,18 @@ fn coerceInMemoryAllowed(
26522 dest_src: LazySrcLoc,27207 dest_src: LazySrcLoc,
26523 src_src: LazySrcLoc,27208 src_src: LazySrcLoc,
26524) CompileError!InMemoryCoercionResult {27209) 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))
26526 return .ok;27213 return .ok;
2652727214
27215 const dest_tag = dest_ty.zigTypeTag(mod);
27216 const src_tag = src_ty.zigTypeTag(mod);
27217
26528 // Differently-named integers with the same number of bits.27218 // Differently-named integers with the same number of bits.
26529 if (dest_ty.zigTypeTag() == .Int and src_ty.zigTypeTag() == .Int) {27219 if (dest_tag == .Int and src_tag == .Int) {
26530 const dest_info = dest_ty.intInfo(target);27220 const dest_info = dest_ty.intInfo(mod);
26531 const src_info = src_ty.intInfo(target);27221 const src_info = src_ty.intInfo(mod);
2653227222
26533 if (dest_info.signedness == src_info.signedness and27223 if (dest_info.signedness == src_info.signedness and
26534 dest_info.bits == src_info.bits)27224 dest_info.bits == src_info.bits)
...@@ -26551,7 +27241,7 @@ fn coerceInMemoryAllowed(...@@ -26551,7 +27241,7 @@ fn coerceInMemoryAllowed(
26551 }27241 }
2655227242
26553 // Differently-named floats with the same number of bits.27243 // 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) {
26555 const dest_bits = dest_ty.floatBits(target);27245 const dest_bits = dest_ty.floatBits(target);
26556 const src_bits = src_ty.floatBits(target);27246 const src_bits = src_ty.floatBits(target);
26557 if (dest_bits == src_bits) {27247 if (dest_bits == src_bits) {
...@@ -26560,10 +27250,8 @@ fn coerceInMemoryAllowed(...@@ -26560,10 +27250,8 @@ fn coerceInMemoryAllowed(
26560 }27250 }
2656127251
26562 // Pointers / Pointer-like Optionals27252 // Pointers / Pointer-like Optionals
26563 var dest_buf: Type.Payload.ElemType = undefined;27253 const maybe_dest_ptr_ty = try sema.typePtrOrOptionalPtrTy(dest_ty);
26564 var src_buf: Type.Payload.ElemType = undefined;27254 const maybe_src_ptr_ty = try sema.typePtrOrOptionalPtrTy(src_ty);
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);
26567 if (maybe_dest_ptr_ty) |dest_ptr_ty| {27255 if (maybe_dest_ptr_ty) |dest_ptr_ty| {
26568 if (maybe_src_ptr_ty) |src_ptr_ty| {27256 if (maybe_src_ptr_ty) |src_ptr_ty| {
26569 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target, dest_src, src_src);27257 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(...@@ -26571,13 +27259,10 @@ fn coerceInMemoryAllowed(
26571 }27259 }
2657227260
26573 // Slices27261 // Slices
26574 if (dest_ty.isSlice() and src_ty.isSlice()) {27262 if (dest_ty.isSlice(mod) and src_ty.isSlice(mod)) {
26575 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);27263 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);
26576 }27264 }
2657727265
26578 const dest_tag = dest_ty.zigTypeTag();
26579 const src_tag = src_ty.zigTypeTag();
26580
26581 // Functions27266 // Functions
26582 if (dest_tag == .Fn and src_tag == .Fn) {27267 if (dest_tag == .Fn and src_tag == .Fn) {
26583 return try sema.coerceInMemoryAllowedFns(block, dest_ty, src_ty, target, dest_src, src_src);27268 return try sema.coerceInMemoryAllowedFns(block, dest_ty, src_ty, target, dest_src, src_src);
...@@ -26585,8 +27270,8 @@ fn coerceInMemoryAllowed(...@@ -26585,8 +27270,8 @@ fn coerceInMemoryAllowed(
2658527270
26586 // Error Unions27271 // Error Unions
26587 if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) {27272 if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) {
26588 const dest_payload = dest_ty.errorUnionPayload();27273 const dest_payload = dest_ty.errorUnionPayload(mod);
26589 const src_payload = src_ty.errorUnionPayload();27274 const src_payload = src_ty.errorUnionPayload(mod);
26590 const child = try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src);27275 const child = try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src);
26591 if (child != .ok) {27276 if (child != .ok) {
26592 return InMemoryCoercionResult{ .error_union_payload = .{27277 return InMemoryCoercionResult{ .error_union_payload = .{
...@@ -26595,7 +27280,7 @@ fn coerceInMemoryAllowed(...@@ -26595,7 +27280,7 @@ fn coerceInMemoryAllowed(
26595 .wanted = dest_payload,27280 .wanted = dest_payload,
26596 } };27281 } };
26597 }27282 }
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);
26599 }27284 }
2660027285
26601 // Error Sets27286 // Error Sets
...@@ -26605,8 +27290,8 @@ fn coerceInMemoryAllowed(...@@ -26605,8 +27290,8 @@ fn coerceInMemoryAllowed(
2660527290
26606 // Arrays27291 // Arrays
26607 if (dest_tag == .Array and src_tag == .Array) {27292 if (dest_tag == .Array and src_tag == .Array) {
26608 const dest_info = dest_ty.arrayInfo();27293 const dest_info = dest_ty.arrayInfo(mod);
26609 const src_info = src_ty.arrayInfo();27294 const src_info = src_ty.arrayInfo(mod);
26610 if (dest_info.len != src_info.len) {27295 if (dest_info.len != src_info.len) {
26611 return InMemoryCoercionResult{ .array_len = .{27296 return InMemoryCoercionResult{ .array_len = .{
26612 .actual = src_info.len,27297 .actual = src_info.len,
...@@ -26624,11 +27309,15 @@ fn coerceInMemoryAllowed(...@@ -26624,11 +27309,15 @@ fn coerceInMemoryAllowed(
26624 }27309 }
26625 const ok_sent = dest_info.sentinel == null or27310 const ok_sent = dest_info.sentinel == null or
26626 (src_info.sentinel != null and27311 (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 ));
26628 if (!ok_sent) {27317 if (!ok_sent) {
26629 return InMemoryCoercionResult{ .array_sentinel = .{27318 return InMemoryCoercionResult{ .array_sentinel = .{
26630 .actual = src_info.sentinel orelse Value.initTag(.unreachable_value),27319 .actual = src_info.sentinel orelse Value.@"unreachable",
26631 .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value),27320 .wanted = dest_info.sentinel orelse Value.@"unreachable",
26632 .ty = dest_info.elem_type,27321 .ty = dest_info.elem_type,
26633 } };27322 } };
26634 }27323 }
...@@ -26637,8 +27326,8 @@ fn coerceInMemoryAllowed(...@@ -26637,8 +27326,8 @@ fn coerceInMemoryAllowed(
2663727326
26638 // Vectors27327 // Vectors
26639 if (dest_tag == .Vector and src_tag == .Vector) {27328 if (dest_tag == .Vector and src_tag == .Vector) {
26640 const dest_len = dest_ty.vectorLen();27329 const dest_len = dest_ty.vectorLen(mod);
26641 const src_len = src_ty.vectorLen();27330 const src_len = src_ty.vectorLen(mod);
26642 if (dest_len != src_len) {27331 if (dest_len != src_len) {
26643 return InMemoryCoercionResult{ .vector_len = .{27332 return InMemoryCoercionResult{ .vector_len = .{
26644 .actual = src_len,27333 .actual = src_len,
...@@ -26646,8 +27335,8 @@ fn coerceInMemoryAllowed(...@@ -26646,8 +27335,8 @@ fn coerceInMemoryAllowed(
26646 } };27335 } };
26647 }27336 }
2664827337
26649 const dest_elem_ty = dest_ty.scalarType();27338 const dest_elem_ty = dest_ty.scalarType(mod);
26650 const src_elem_ty = src_ty.scalarType();27339 const src_elem_ty = src_ty.scalarType(mod);
26651 const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src);27340 const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src);
26652 if (child != .ok) {27341 if (child != .ok) {
26653 return InMemoryCoercionResult{ .vector_elem = .{27342 return InMemoryCoercionResult{ .vector_elem = .{
...@@ -26668,15 +27357,15 @@ fn coerceInMemoryAllowed(...@@ -26668,15 +27357,15 @@ fn coerceInMemoryAllowed(
26668 .wanted = dest_ty,27357 .wanted = dest_ty,
26669 } };27358 } };
26670 }27359 }
26671 const dest_child_type = dest_ty.optionalChild(&dest_buf);27360 const dest_child_type = dest_ty.optionalChild(mod);
26672 const src_child_type = src_ty.optionalChild(&src_buf);27361 const src_child_type = src_ty.optionalChild(mod);
2667327362
26674 const child = try sema.coerceInMemoryAllowed(block, dest_child_type, src_child_type, dest_is_mut, target, dest_src, src_src);27363 const child = try sema.coerceInMemoryAllowed(block, dest_child_type, src_child_type, dest_is_mut, target, dest_src, src_src);
26675 if (child != .ok) {27364 if (child != .ok) {
26676 return InMemoryCoercionResult{ .optional_child = .{27365 return InMemoryCoercionResult{ .optional_child = .{
26677 .child = try child.dupe(sema.arena),27366 .child = try child.dupe(sema.arena),
26678 .actual = try src_child_type.copy(sema.arena),27367 .actual = src_child_type,
26679 .wanted = try dest_child_type.copy(sema.arena),27368 .wanted = dest_child_type,
26680 } };27369 } };
26681 }27370 }
2668227371
...@@ -26697,138 +27386,108 @@ fn coerceInMemoryAllowedErrorSets(...@@ -26697,138 +27386,108 @@ fn coerceInMemoryAllowedErrorSets(
26697 dest_src: LazySrcLoc,27386 dest_src: LazySrcLoc,
26698 src_src: LazySrcLoc,27387 src_src: LazySrcLoc,
26699) !InMemoryCoercionResult {27388) !InMemoryCoercionResult {
27389 const mod = sema.mod;
27390 const gpa = sema.gpa;
27391 const ip = &mod.intern_pool;
27392
26700 // Coercion to `anyerror`. Note that this check can return false negatives27393 // Coercion to `anyerror`. Note that this check can return false negatives
26701 // in case the error sets did not get resolved.27394 // in case the error sets did not get resolved.
26702 if (dest_ty.isAnyError()) {27395 if (dest_ty.isAnyError(mod)) {
26703 return .ok;27396 return .ok;
26704 }27397 }
2670527398
26706 if (dest_ty.castTag(.error_set_inferred)) |dst_payload| {27399 if (mod.typeToInferredErrorSetIndex(dest_ty).unwrap()) |dst_ies_index| {
26707 const dst_ies = dst_payload.data;27400 const dst_ies = mod.inferredErrorSetPtr(dst_ies_index);
26708 // We will make an effort to return `ok` without resolving either error set, to27401 // We will make an effort to return `ok` without resolving either error set, to
26709 // avoid unnecessary "unable to resolve error set" dependency loop errors.27402 // avoid unnecessary "unable to resolve error set" dependency loop errors.
26710 switch (src_ty.tag()) {27403 switch (src_ty.toIntern()) {
26711 .error_set_inferred => {27404 .anyerror_type => {},
26712 // If both are inferred error sets of functions, and27405 else => switch (ip.indexToKey(src_ty.toIntern())) {
26713 // the dest includes the source function, the coercion is OK.27406 .inferred_error_set_type => |src_index| {
26714 // This check is important because it works without forcing a full resolution27407 // If both are inferred error sets of functions, and
26715 // of inferred error sets.27408 // the dest includes the source function, the coercion is OK.
26716 const src_ies = src_ty.castTag(.error_set_inferred).?.data;27409 // This check is important because it works without forcing a full resolution
2671727410 // of inferred error sets.
26718 if (dst_ies.inferred_error_sets.contains(src_ies)) {27411 if (dst_ies.inferred_error_sets.contains(src_index)) {
26719 return .ok;27412 return .ok;
26720 }27413 }
26721 },27414 },
26722 .error_set_single => {27415 .error_set_type => |error_set_type| {
26723 const name = src_ty.castTag(.error_set_single).?.data;27416 for (error_set_type.names) |name| {
26724 if (dst_ies.errors.contains(name)) return .ok;27417 if (!dst_ies.errors.contains(name)) break;
26725 },27418 } else return .ok;
26726 .error_set_merged => {27419 },
26727 const names = src_ty.castTag(.error_set_merged).?.data.keys();27420 else => unreachable,
26728 for (names) |name| {27421 },
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,
26740 }27422 }
2674127423
26742 if (dst_ies.func == sema.owner_func) {27424 if (dst_ies.func == sema.owner_func_index.unwrap()) {
26743 // We are trying to coerce an error set to the current function's27425 // We are trying to coerce an error set to the current function's
26744 // inferred error set.27426 // inferred error set.
26745 try dst_ies.addErrorSet(sema.gpa, src_ty);27427 try dst_ies.addErrorSet(src_ty, ip, gpa);
26746 return .ok;27428 return .ok;
26747 }27429 }
2674827430
26749 try sema.resolveInferredErrorSet(block, dest_src, dst_payload.data);27431 try sema.resolveInferredErrorSet(block, dest_src, dst_ies_index);
26750 // isAnyError might have changed from a false negative to a true positive after resolution.27432 // 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)) {
26752 return .ok;27434 return .ok;
26753 }27435 }
26754 }27436 }
2675527437
26756 var missing_error_buf = std.ArrayList([]const u8).init(sema.gpa);27438 var missing_error_buf = std.ArrayList(InternPool.NullTerminatedString).init(gpa);
26757 defer missing_error_buf.deinit();27439 defer missing_error_buf.deinit();
2675827440
26759 switch (src_ty.tag()) {27441 switch (src_ty.toIntern()) {
26760 .error_set_inferred => {27442 .anyerror_type => switch (ip.indexToKey(dest_ty.toIntern())) {
26761 const src_data = src_ty.castTag(.error_set_inferred).?.data;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);27453 try sema.resolveInferredErrorSet(block, src_src, src_index);
26764 // src anyerror status might have changed after the resolution.27454 // src anyerror status might have changed after the resolution.
26765 if (src_ty.isAnyError()) {27455 if (src_ty.isAnyError(mod)) {
26766 // dest_ty.isAnyError() == true is already checked for at this point.27456 // dest_ty.isAnyError(mod) == true is already checked for at this point.
26767 return .from_anyerror;27457 return .from_anyerror;
26768 }27458 }
2676927459
26770 for (src_data.errors.keys()) |key| {27460 for (src_data.errors.keys()) |key| {
26771 if (!dest_ty.errorSetHasField(key)) {27461 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) {
26772 try missing_error_buf.append(key);27462 try missing_error_buf.append(key);
27463 }
26773 }27464 }
26774 }
2677527465
26776 if (missing_error_buf.items.len != 0) {27466 if (missing_error_buf.items.len != 0) {
26777 return InMemoryCoercionResult{27467 return InMemoryCoercionResult{
26778 .missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),27468 .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items),
26779 };27469 };
26780 }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)) {
26787 return .ok;27472 return .ok;
26788 }27473 },
26789 const list = try sema.arena.alloc([]const u8, 1);27474 .error_set_type => |error_set_type| {
26790 list[0] = name;27475 for (error_set_type.names) |name| {
26791 return InMemoryCoercionResult{ .missing_error = list };27476 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) {
26792 },27477 try missing_error_buf.append(name);
26793 .error_set_merged => {27478 }
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);
26798 }27479 }
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;27481 if (missing_error_buf.items.len != 0) {
26808 },27482 return InMemoryCoercionResult{
26809 .error_set => {27483 .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items),
26810 const names = src_ty.castTag(.error_set).?.data.names.keys();27484 };
26811 for (names) |name| {
26812 if (!dest_ty.errorSetHasField(name)) {
26813 try missing_error_buf.append(name);
26814 }27485 }
26815 }
2681627486
26817 if (missing_error_buf.items.len != 0) {27487 return .ok;
26818 return InMemoryCoercionResult{27488 },
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.
26829 else => unreachable,27489 else => unreachable,
26830 },27490 },
26831 else => unreachable,
26832 }27491 }
2683327492
26834 unreachable;27493 unreachable;
...@@ -26843,69 +27502,95 @@ fn coerceInMemoryAllowedFns(...@@ -26843,69 +27502,95 @@ fn coerceInMemoryAllowedFns(
26843 dest_src: LazySrcLoc,27502 dest_src: LazySrcLoc,
26844 src_src: LazySrcLoc,27503 src_src: LazySrcLoc,
26845) !InMemoryCoercionResult {27504) !InMemoryCoercionResult {
26846 const dest_info = dest_ty.fnInfo();27505 const mod = sema.mod;
26847 const src_info = src_ty.fnInfo();
2684827506
26849 if (dest_info.is_var_args != src_info.is_var_args) {27507 {
26850 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };27508 const dest_info = mod.typeToFunc(dest_ty).?;
26851 }27509 const src_info = mod.typeToFunc(src_ty).?;
2685227510
26853 if (dest_info.is_generic != src_info.is_generic) {27511 if (dest_info.is_var_args != src_info.is_var_args) {
26854 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };27512 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
26855 }27513 }
2685627514
26857 if (dest_info.cc != src_info.cc) {27515 if (dest_info.is_generic != src_info.is_generic) {
26858 return InMemoryCoercionResult{ .fn_cc = .{27516 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };
26859 .actual = src_info.cc,27517 }
26860 .wanted = dest_info.cc,
26861 } };
26862 }
2686327518
26864 if (!src_info.return_type.isNoReturn()) {27519 if (dest_info.cc != src_info.cc) {
26865 const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type, src_info.return_type, false, target, dest_src, src_src);27520 return InMemoryCoercionResult{ .fn_cc = .{
26866 if (rt != .ok) {27521 .actual = src_info.cc,
26867 return InMemoryCoercionResult{ .fn_return_type = .{27522 .wanted = dest_info.cc,
26868 .child = try rt.dupe(sema.arena),
26869 .actual = src_info.return_type,
26870 .wanted = dest_info.return_type,
26871 } };27523 } };
26872 }27524 }
26873 }
2687427525
26875 if (dest_info.param_types.len != src_info.param_types.len) {27526 switch (src_info.return_type) {
26876 return InMemoryCoercionResult{ .fn_param_count = .{27527 .noreturn_type, .generic_poison_type => {},
26877 .actual = src_info.param_types.len,27528 else => {
26878 .wanted = dest_info.param_types.len,27529 const dest_return_type = dest_info.return_type.toType();
26879 } };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 }
26880 }27541 }
2688127542
26882 if (dest_info.noalias_bits != src_info.noalias_bits) {27543 const params_len = params_len: {
26883 return InMemoryCoercionResult{ .fn_param_noalias = .{27544 const dest_info = mod.typeToFunc(dest_ty).?;
26884 .actual = src_info.noalias_bits,27545 const src_info = mod.typeToFunc(src_ty).?;
26885 .wanted = dest_info.noalias_bits,
26886 } };
26887 }
2688827546
26889 for (dest_info.param_types, 0..) |dest_param_ty, i| {27547 if (dest_info.param_types.len != src_info.param_types.len) {
26890 const src_param_ty = src_info.param_types[i];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]) {27554 if (dest_info.noalias_bits != src_info.noalias_bits) {
26893 return InMemoryCoercionResult{ .fn_param_comptime = .{27555 return InMemoryCoercionResult{ .fn_param_noalias = .{
26894 .index = i,27556 .actual = src_info.noalias_bits,
26895 .wanted = dest_info.comptime_params[i],27557 .wanted = dest_info.noalias_bits,
26896 } };27558 } };
26897 }27559 }
2689827560
26899 // Note: Cast direction is reversed here.27561 break :params_len dest_info.param_types.len;
26900 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);27562 };
26901 if (param != .ok) {27563
26902 return InMemoryCoercionResult{ .fn_param = .{27564 for (0..params_len) |param_i| {
26903 .child = try param.dupe(sema.arena),27565 const dest_info = mod.typeToFunc(dest_ty).?;
26904 .actual = src_param_ty,27566 const src_info = mod.typeToFunc(src_ty).?;
26905 .wanted = dest_param_ty,27567
26906 .index = i,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),
26907 } };27576 } };
26908 }27577 }
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 }
26909 }27594 }
2691027595
26911 return .ok;27596 return .ok;
...@@ -26923,8 +27608,9 @@ fn coerceInMemoryAllowedPtrs(...@@ -26923,8 +27608,9 @@ fn coerceInMemoryAllowedPtrs(
26923 dest_src: LazySrcLoc,27608 dest_src: LazySrcLoc,
26924 src_src: LazySrcLoc,27609 src_src: LazySrcLoc,
26925) !InMemoryCoercionResult {27610) !InMemoryCoercionResult {
26926 const dest_info = dest_ptr_ty.ptrInfo().data;27611 const mod = sema.mod;
26927 const src_info = src_ptr_ty.ptrInfo().data;27612 const dest_info = dest_ptr_ty.ptrInfo(mod);
27613 const src_info = src_ptr_ty.ptrInfo(mod);
2692827614
26929 const ok_ptr_size = src_info.size == dest_info.size or27615 const ok_ptr_size = src_info.size == dest_info.size or
26930 src_info.size == .C or dest_info.size == .C;27616 src_info.size == .C or dest_info.size == .C;
...@@ -26964,8 +27650,8 @@ fn coerceInMemoryAllowedPtrs(...@@ -26964,8 +27650,8 @@ fn coerceInMemoryAllowedPtrs(
26964 } };27650 } };
26965 }27651 }
2696627652
26967 const dest_allow_zero = dest_ty.ptrAllowsZero();27653 const dest_allow_zero = dest_ty.ptrAllowsZero(mod);
26968 const src_allow_zero = src_ty.ptrAllowsZero();27654 const src_allow_zero = src_ty.ptrAllowsZero(mod);
2696927655
26970 const ok_allows_zero = (dest_allow_zero and27656 const ok_allows_zero = (dest_allow_zero and
26971 (src_allow_zero or !dest_is_mut)) or27657 (src_allow_zero or !dest_is_mut)) or
...@@ -26989,12 +27675,15 @@ fn coerceInMemoryAllowedPtrs(...@@ -26989,12 +27675,15 @@ fn coerceInMemoryAllowedPtrs(
26989 }27675 }
2699027676
26991 const ok_sent = dest_info.sentinel == null or src_info.size == .C or27677 const ok_sent = dest_info.sentinel == null or src_info.size == .C or
26992 (src_info.sentinel != null and27678 (src_info.sentinel != null and dest_info.sentinel.?.eql(
26993 dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod));27679 try mod.getCoerced(src_info.sentinel.?, dest_info.pointee_type),
27680 dest_info.pointee_type,
27681 sema.mod,
27682 ));
26994 if (!ok_sent) {27683 if (!ok_sent) {
26995 return InMemoryCoercionResult{ .ptr_sentinel = .{27684 return InMemoryCoercionResult{ .ptr_sentinel = .{
26996 .actual = src_info.sentinel orelse Value.initTag(.unreachable_value),27685 .actual = src_info.sentinel orelse Value.@"unreachable",
26997 .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value),27686 .wanted = dest_info.sentinel orelse Value.@"unreachable",
26998 .ty = dest_info.pointee_type,27687 .ty = dest_info.pointee_type,
26999 } };27688 } };
27000 }27689 }
...@@ -27013,12 +27702,12 @@ fn coerceInMemoryAllowedPtrs(...@@ -27013,12 +27702,12 @@ fn coerceInMemoryAllowedPtrs(
27013 const src_align = if (src_info.@"align" != 0)27702 const src_align = if (src_info.@"align" != 0)
27014 src_info.@"align"27703 src_info.@"align"
27015 else27704 else
27016 src_info.pointee_type.abiAlignment(target);27705 src_info.pointee_type.abiAlignment(mod);
2701727706
27018 const dest_align = if (dest_info.@"align" != 0)27707 const dest_align = if (dest_info.@"align" != 0)
27019 dest_info.@"align"27708 dest_info.@"align"
27020 else27709 else
27021 dest_info.pointee_type.abiAlignment(target);27710 dest_info.pointee_type.abiAlignment(mod);
2702227711
27023 if (dest_align > src_align) {27712 if (dest_align > src_align) {
27024 return InMemoryCoercionResult{ .ptr_alignment = .{27713 return InMemoryCoercionResult{ .ptr_alignment = .{
...@@ -27041,8 +27730,9 @@ fn coerceVarArgParam(...@@ -27041,8 +27730,9 @@ fn coerceVarArgParam(
27041) !Air.Inst.Ref {27730) !Air.Inst.Ref {
27042 if (block.is_typeof) return inst;27731 if (block.is_typeof) return inst;
2704327732
27733 const mod = sema.mod;
27044 const uncasted_ty = sema.typeOf(inst);27734 const uncasted_ty = sema.typeOf(inst);
27045 const coerced = switch (uncasted_ty.zigTypeTag()) {27735 const coerced = switch (uncasted_ty.zigTypeTag(mod)) {
27046 // TODO consider casting to c_int/f64 if they fit27736 // TODO consider casting to c_int/f64 if they fit
27047 .ComptimeInt, .ComptimeFloat => return sema.fail(27737 .ComptimeInt, .ComptimeFloat => return sema.fail(
27048 block,27738 block,
...@@ -27052,7 +27742,7 @@ fn coerceVarArgParam(...@@ -27052,7 +27742,7 @@ fn coerceVarArgParam(
27052 ),27742 ),
27053 .Fn => blk: {27743 .Fn => blk: {
27054 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");27744 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
27055 const fn_decl = fn_val.pointerDecl().?;27745 const fn_decl = fn_val.pointerDecl(mod).?;
27056 break :blk try sema.analyzeDeclRef(fn_decl);27746 break :blk try sema.analyzeDeclRef(fn_decl);
27057 },27747 },
27058 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),27748 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
...@@ -27077,7 +27767,7 @@ fn coerceVarArgParam(...@@ -27077,7 +27767,7 @@ fn coerceVarArgParam(
27077 errdefer msg.destroy(sema.gpa);27767 errdefer msg.destroy(sema.gpa);
2707827768
27079 const src_decl = sema.mod.declPtr(block.src_decl);27769 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
27082 try sema.addDeclaredHereNote(msg, coerced_ty);27772 try sema.addDeclaredHereNote(msg, coerced_ty);
27083 break :msg msg;27773 break :msg msg;
...@@ -27109,11 +27799,12 @@ fn storePtr2(...@@ -27109,11 +27799,12 @@ fn storePtr2(
27109 operand_src: LazySrcLoc,27799 operand_src: LazySrcLoc,
27110 air_tag: Air.Inst.Tag,27800 air_tag: Air.Inst.Tag,
27111) CompileError!void {27801) CompileError!void {
27802 const mod = sema.mod;
27112 const ptr_ty = sema.typeOf(ptr);27803 const ptr_ty = sema.typeOf(ptr);
27113 if (ptr_ty.isConstPtr())27804 if (ptr_ty.isConstPtr(mod))
27114 return sema.fail(block, ptr_src, "cannot assign to constant", .{});27805 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
27118 // To generate better code for tuples, we detect a tuple operand here, and27809 // To generate better code for tuples, we detect a tuple operand here, and
27119 // analyze field loads and stores directly. This avoids an extra allocation + memcpy27810 // analyze field loads and stores directly. This avoids an extra allocation + memcpy
...@@ -27124,8 +27815,8 @@ fn storePtr2(...@@ -27124,8 +27815,8 @@ fn storePtr2(
27124 // this code does not handle tuple-to-struct coercion which requires dealing with missing27815 // this code does not handle tuple-to-struct coercion which requires dealing with missing
27125 // fields.27816 // fields.
27126 const operand_ty = sema.typeOf(uncasted_operand);27817 const operand_ty = sema.typeOf(uncasted_operand);
27127 if (operand_ty.isTuple() and elem_ty.zigTypeTag() == .Array) {27818 if (operand_ty.isTuple(mod) and elem_ty.zigTypeTag(mod) == .Array) {
27128 const field_count = operand_ty.structFieldCount();27819 const field_count = operand_ty.structFieldCount(mod);
27129 var i: u32 = 0;27820 var i: u32 = 0;
27130 while (i < field_count) : (i += 1) {27821 while (i < field_count) : (i += 1) {
27131 const elem_src = operand_src; // TODO better source location27822 const elem_src = operand_src; // TODO better source location
...@@ -27149,7 +27840,7 @@ fn storePtr2(...@@ -27149,7 +27840,7 @@ fn storePtr2(
27149 // as well as working around an LLVM bug:27840 // as well as working around an LLVM bug:
27150 // https://github.com/ziglang/zig/issues/1115427841 // https://github.com/ziglang/zig/issues/11154
27151 if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| {27842 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);
27153 const vector = sema.coerceExtra(block, vector_ty, uncasted_operand, operand_src, .{ .is_ret = is_ret }) catch |err| switch (err) {27844 const vector = sema.coerceExtra(block, vector_ty, uncasted_operand, operand_src, .{ .is_ret = is_ret }) catch |err| switch (err) {
27154 error.NotCoercible => unreachable,27845 error.NotCoercible => unreachable,
27155 else => |e| return e,27846 else => |e| return e,
...@@ -27169,7 +27860,7 @@ fn storePtr2(...@@ -27169,7 +27860,7 @@ fn storePtr2(
27169 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);27860 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
27170 break :rs operand_src;27861 break :rs operand_src;
27171 };27862 };
27172 if (ptr_val.isComptimeMutablePtr()) {27863 if (ptr_val.isComptimeMutablePtr(mod)) {
27173 try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);27864 try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
27174 return;27865 return;
27175 } else break :rs ptr_src;27866 } else break :rs ptr_src;
...@@ -27190,7 +27881,7 @@ fn storePtr2(...@@ -27190,7 +27881,7 @@ fn storePtr2(
27190 try sema.requireRuntimeBlock(block, src, runtime_src);27881 try sema.requireRuntimeBlock(block, src, runtime_src);
27191 try sema.queueFullTypeResolution(elem_ty);27882 try sema.queueFullTypeResolution(elem_ty);
2719227883
27193 if (ptr_ty.ptrInfo().data.vector_index == .runtime) {27884 if (ptr_ty.ptrInfo(mod).vector_index == .runtime) {
27194 const ptr_inst = Air.refToIndex(ptr).?;27885 const ptr_inst = Air.refToIndex(ptr).?;
27195 const air_tags = sema.air_instructions.items(.tag);27886 const air_tags = sema.air_instructions.items(.tag);
27196 if (air_tags[ptr_inst] == .ptr_elem_ptr) {27887 if (air_tags[ptr_inst] == .ptr_elem_ptr) {
...@@ -27224,30 +27915,27 @@ fn storePtr2(...@@ -27224,30 +27915,27 @@ fn storePtr2(
27224/// pointer. Only if the final element type matches the vector element type, and the27915/// pointer. Only if the final element type matches the vector element type, and the
27225/// lengths match.27916/// lengths match.
27226fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {27917fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {
27227 const array_ty = sema.typeOf(ptr).childType();27918 const mod = sema.mod;
27228 if (array_ty.zigTypeTag() != .Array) return null;27919 const array_ty = sema.typeOf(ptr).childType(mod);
27229 var ptr_inst = Air.refToIndex(ptr) orelse return null;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;
27230 const air_datas = sema.air_instructions.items(.data);27923 const air_datas = sema.air_instructions.items(.data);
27231 const air_tags = sema.air_instructions.items(.tag);27924 const air_tags = sema.air_instructions.items(.tag);
27232 const prev_ptr = while (air_tags[ptr_inst] == .bitcast) {27925 const vector_ty = while (air_tags[ptr_inst] == .bitcast) {
27233 const prev_ptr = air_datas[ptr_inst].ty_op.operand;27926 ptr_ref = air_datas[ptr_inst].ty_op.operand;
27234 const prev_ptr_ty = sema.typeOf(prev_ptr);27927 if (!sema.isKnownZigType(ptr_ref, .Pointer)) return null;
27235 const prev_ptr_child_ty = switch (prev_ptr_ty.tag()) {27928 const child_ty = sema.typeOf(ptr_ref).childType(mod);
27236 .single_mut_pointer => prev_ptr_ty.castTag(.single_mut_pointer).?.data,27929 if (child_ty.zigTypeTag(mod) == .Vector) break child_ty;
27237 .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type,27930 ptr_inst = Air.refToIndex(ptr_ref) orelse return null;
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;
27242 } else return null;27931 } else return null;
2724327932
27244 // We have a pointer-to-array and a pointer-to-vector. If the elements and27933 // We have a pointer-to-array and a pointer-to-vector. If the elements and
27245 // lengths match, return the result.27934 // lengths match, return the result.
27246 const vector_ty = sema.typeOf(prev_ptr).childType();27935 if (array_ty.childType(mod).eql(vector_ty.childType(mod), sema.mod) and
27247 if (array_ty.childType().eql(vector_ty.childType(), sema.mod) and27936 array_ty.arrayLen(mod) == vector_ty.vectorLen(mod))
27248 array_ty.arrayLen() == vector_ty.vectorLen())
27249 {27937 {
27250 return prev_ptr;27938 return ptr_ref;
27251 } else {27939 } else {
27252 return null;27940 return null;
27253 }27941 }
...@@ -27263,54 +27951,55 @@ fn storePtrVal(...@@ -27263,54 +27951,55 @@ fn storePtrVal(
27263 operand_val: Value,27951 operand_val: Value,
27264 operand_ty: Type,27952 operand_ty: Type,
27265) !void {27953) !void {
27954 const mod = sema.mod;
27266 var mut_kit = try sema.beginComptimePtrMutation(block, src, ptr_val, operand_ty);27955 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
27269 switch (mut_kit.pointee) {27958 switch (mut_kit.pointee) {
27270 .direct => |val_ptr| {27959 .direct => |val_ptr| {
27271 if (mut_kit.decl_ref_mut.runtime_index == .comptime_field_ptr) {27960 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {
27272 if (!operand_val.eql(val_ptr.*, operand_ty, sema.mod)) {27961 if (!operand_val.eql(val_ptr.*, operand_ty, mod)) {
27273 // TODO use failWithInvalidComptimeFieldStore27962 // TODO use failWithInvalidComptimeFieldStore
27274 return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{});27963 return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{});
27275 }27964 }
27276 return;27965 return;
27277 }27966 }
27278 const arena = mut_kit.beginArena(sema.mod);27967 val_ptr.* = (try operand_val.intern(operand_ty, mod)).toValue();
27279 defer mut_kit.finishArena(sema.mod);
27280
27281 val_ptr.* = try operand_val.copy(arena);
27282 },27968 },
27283 .reinterpret => |reinterpret| {27969 .reinterpret => |reinterpret| {
27284 const target = sema.mod.getTarget();27970 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod));
27285 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(target));
27286 const buffer = try sema.gpa.alloc(u8, abi_size);27971 const buffer = try sema.gpa.alloc(u8, abi_size);
27287 defer sema.gpa.free(buffer);27972 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,
27289 error.ReinterpretDeclRef => unreachable,27975 error.ReinterpretDeclRef => unreachable,
27290 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already27976 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)}),
27292 };27978 };
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,
27294 error.ReinterpretDeclRef => unreachable,27981 error.ReinterpretDeclRef => unreachable,
27295 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already27982 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)}),
27297 };27984 };
2729827985
27299 const arena = mut_kit.beginArena(sema.mod);27986 reinterpret.val_ptr.* = (try (try Value.readFromMemory(mut_kit.ty, mod, buffer, sema.arena)).intern(mut_kit.ty, mod)).toValue();
27300 defer mut_kit.finishArena(sema.mod);
27301
27302 reinterpret.val_ptr.* = try Value.readFromMemory(mut_kit.ty, sema.mod, buffer, arena);
27303 },27987 },
27304 .bad_decl_ty, .bad_ptr_ty => {27988 .bad_decl_ty, .bad_ptr_ty => {
27305 // TODO show the decl declaration site in a note and explain whether the decl27989 // TODO show the decl declaration site in a note and explain whether the decl
27306 // or the pointer is the problematic type27990 // 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 );
27308 },27997 },
27309 }27998 }
27310}27999}
2731128000
27312const ComptimePtrMutationKit = struct {28001const ComptimePtrMutationKit = struct {
27313 decl_ref_mut: Value.Payload.DeclRefMut.Data,28002 mut_decl: InternPool.Key.Ptr.Addr.MutDecl,
27314 pointee: union(enum) {28003 pointee: union(enum) {
27315 /// The pointer type matches the actual comptime Value so a direct28004 /// The pointer type matches the actual comptime Value so a direct
27316 /// modification is possible.28005 /// modification is possible.
...@@ -27333,18 +28022,6 @@ const ComptimePtrMutationKit = struct {...@@ -27333,18 +28022,6 @@ const ComptimePtrMutationKit = struct {
27333 bad_ptr_ty,28022 bad_ptr_ty,
27334 },28023 },
27335 ty: Type,28024 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 }
27348};28025};
2734928026
27350fn beginComptimePtrMutation(28027fn beginComptimePtrMutation(
...@@ -27354,201 +28031,251 @@ fn beginComptimePtrMutation(...@@ -27354,201 +28031,251 @@ fn beginComptimePtrMutation(
27354 ptr_val: Value,28031 ptr_val: Value,
27355 ptr_elem_ty: Type,28032 ptr_elem_ty: Type,
27356) CompileError!ComptimePtrMutationKit {28033) CompileError!ComptimePtrMutationKit {
27357 const target = sema.mod.getTarget();28034 const mod = sema.mod;
27358 switch (ptr_val.tag()) {28035 const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr;
27359 .decl_ref_mut => {28036 switch (ptr.addr) {
27360 const decl_ref_mut = ptr_val.castTag(.decl_ref_mut).?.data;28037 .decl, .int => unreachable, // isComptimeMutablePtr has been checked already
27361 const decl = sema.mod.declPtr(decl_ref_mut.decl_index);28038 .mut_decl => |mut_decl| {
27362 return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, decl_ref_mut);28039 const decl = mod.declPtr(mut_decl.decl);
27363 },28040 return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl);
27364 .comptime_field_ptr => {28041 },
27365 const payload = ptr_val.castTag(.comptime_field_ptr).?.data;28042 .comptime_field => |comptime_field| {
27366 const duped = try sema.arena.create(Value);28043 const duped = try sema.arena.create(Value);
27367 duped.* = payload.field_val;28044 duped.* = comptime_field.toValue();
27368 return sema.beginComptimePtrMutationInner(block, src, payload.field_ty, duped, ptr_elem_ty, .{28045 return sema.beginComptimePtrMutationInner(block, src, mod.intern_pool.typeOf(comptime_field).toType(), duped, ptr_elem_ty, .{
27369 .decl_index = @intToEnum(Module.Decl.Index, 0),28046 .decl = undefined,
27370 .runtime_index = .comptime_field_ptr,28047 .runtime_index = .comptime_field_ptr,
27371 });28048 });
27372 },28049 },
27373 .elem_ptr => {28050 .eu_payload => |eu_ptr| {
27374 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;28051 const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod);
27375 var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.array_ptr, elem_ptr.elem_ty);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
27377 switch (parent.pointee) {28148 switch (parent.pointee) {
27378 .direct => |val_ptr| switch (parent.ty.zigTypeTag()) {28149 .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) {
27379 .Array, .Vector => {28150 .Array, .Vector => {
27380 const check_len = parent.ty.arrayLenIncludingSentinel();28151 const check_len = parent.ty.arrayLenIncludingSentinel(mod);
27381 if (elem_ptr.index >= check_len) {28152 if (elem_ptr.index >= check_len) {
27382 // TODO have the parent include the decl so we can say "declared here"28153 // TODO have the parent include the decl so we can say "declared here"
27383 return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{28154 return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{
27384 elem_ptr.index, check_len,28155 elem_ptr.index, check_len,
27385 });28156 });
27386 }28157 }
27387 const elem_ty = parent.ty.childType();28158 const elem_ty = parent.ty.childType(mod);
2738828159
27389 // We might have a pointer to multiple elements of the array (e.g. a pointer28160 // We might have a pointer to multiple elements of the array (e.g. a pointer
27390 // to a sub-array). In this case, we just have to reinterpret the relevant28161 // to a sub-array). In this case, we just have to reinterpret the relevant
27391 // bytes of the whole array rather than any single element.28162 // 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);
27393 if (elem_abi_size_u64 < try sema.typeAbiSize(ptr_elem_ty)) {28164 if (elem_abi_size_u64 < try sema.typeAbiSize(ptr_elem_ty)) {
27394 const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64);28165 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);
27395 return .{28167 return .{
27396 .decl_ref_mut = parent.decl_ref_mut,28168 .mut_decl = parent.mut_decl,
27397 .pointee = .{ .reinterpret = .{28169 .pointee = .{ .reinterpret = .{
27398 .val_ptr = val_ptr,28170 .val_ptr = val_ptr,
27399 .byte_offset = elem_abi_size * elem_ptr.index,28171 .byte_offset = elem_abi_size * elem_idx,
27400 } },28172 } },
27401 .ty = parent.ty,28173 .ty = parent.ty,
27402 };28174 };
27403 }28175 }
2740428176
27405 switch (val_ptr.tag()) {28177 switch (val_ptr.ip_index) {
27406 .undef => {28178 .none => switch (val_ptr.tag()) {
27407 // An array has been initialized to undefined at comptime and now we28179 .bytes => {
27408 // are for the first time setting an element. We must change the representation28180 // An array is memory-optimized to store a slice of bytes, but we are about
27409 // of the array from `undef` to `array`.28181 // to modify an individual field and the representation has to change.
27410 const arena = parent.beginArena(sema.mod);28182 // If we wanted to avoid this, there would need to be special detection
27411 defer parent.finishArena(sema.mod);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 =28197 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
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);
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(28228 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
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 }
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(
27452 sema,28242 sema,
27453 block,28243 block,
27454 src,28244 src,
27455 elem_ty,28245 elem_ty,
27456 &elems[elem_ptr.index],28246 &val_ptr.castTag(.aggregate).?.data[@intCast(usize, elem_ptr.index)],
27457 ptr_elem_ty,28247 ptr_elem_ty,
27458 parent.decl_ref_mut,28248 parent.mut_decl,
27459 );28249 ),
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);
2748328250
27484 return beginComptimePtrMutationInner(28251 else => unreachable,
27485 sema,
27486 block,
27487 src,
27488 elem_ty,
27489 &elems[elem_ptr.index],
27490 ptr_elem_ty,
27491 parent.decl_ref_mut,
27492 );
27493 },28252 },
27494 .repeated => {28253 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {
27495 // An array is memory-optimized to store only a single element value, and28254 .undef => {
27496 // that value is understood to be the same for the entire length of the array.28255 // An array has been initialized to undefined at comptime and now we
27497 // However, now we want to modify an individual field and so the28256 // are for the first time setting an element. We must change the representation
27498 // representation has to change. If we wanted to avoid this, there would28257 // of the array from `undef` to `array`.
27499 // need to be special detection elsewhere to identify when writing a value to an28258 const arena = sema.arena;
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 }
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(28265 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
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 },
2752628266
27527 .aggregate => return beginComptimePtrMutationInner(28267 return beginComptimePtrMutationInner(
27528 sema,28268 sema,
27529 block,28269 block,
27530 src,28270 src,
27531 elem_ty,28271 elem_ty,
27532 &val_ptr.castTag(.aggregate).?.data[elem_ptr.index],28272 &elems[@intCast(usize, elem_ptr.index)],
27533 ptr_elem_ty,28273 ptr_elem_ty,
27534 parent.decl_ref_mut,28274 parent.mut_decl,
27535 ),28275 );
2753628276 },
27537 .the_only_possible_value => {28277 else => unreachable,
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 );
27549 },28278 },
27550
27551 else => unreachable,
27552 }28279 }
27553 },28280 },
27554 else => {28281 else => {
...@@ -27565,28 +28292,29 @@ fn beginComptimePtrMutation(...@@ -27565,28 +28292,29 @@ fn beginComptimePtrMutation(
27565 parent.ty,28292 parent.ty,
27566 val_ptr,28293 val_ptr,
27567 ptr_elem_ty,28294 ptr_elem_ty,
27568 parent.decl_ref_mut,28295 parent.mut_decl,
27569 );28296 );
27570 },28297 },
27571 },28298 },
27572 .reinterpret => |reinterpret| {28299 .reinterpret => |reinterpret| {
27573 if (!elem_ptr.elem_ty.hasWellDefinedLayout()) {28300 if (!base_elem_ty.hasWellDefinedLayout(mod)) {
27574 // Even though the parent value type has well-defined memory layout, our28301 // Even though the parent value type has well-defined memory layout, our
27575 // pointer type does not.28302 // pointer type does not.
27576 return ComptimePtrMutationKit{28303 return ComptimePtrMutationKit{
27577 .decl_ref_mut = parent.decl_ref_mut,28304 .mut_decl = parent.mut_decl,
27578 .pointee = .bad_ptr_ty,28305 .pointee = .bad_ptr_ty,
27579 .ty = elem_ptr.elem_ty,28306 .ty = base_elem_ty,
27580 };28307 };
27581 }28308 }
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);
27584 const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64);28311 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);
27585 return ComptimePtrMutationKit{28313 return ComptimePtrMutationKit{
27586 .decl_ref_mut = parent.decl_ref_mut,28314 .mut_decl = parent.mut_decl,
27587 .pointee = .{ .reinterpret = .{28315 .pointee = .{ .reinterpret = .{
27588 .val_ptr = reinterpret.val_ptr,28316 .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,
27590 } },28318 } },
27591 .ty = parent.ty,28319 .ty = parent.ty,
27592 };28320 };
...@@ -27594,162 +28322,184 @@ fn beginComptimePtrMutation(...@@ -27594,162 +28322,184 @@ fn beginComptimePtrMutation(
27594 .bad_decl_ty, .bad_ptr_ty => return parent,28322 .bad_decl_ty, .bad_ptr_ty => return parent,
27595 }28323 }
27596 },28324 },
27597 .field_ptr => {28325 .field => |field_ptr| {
27598 const field_ptr = ptr_val.castTag(.field_ptr).?.data;28326 const base_child_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
27599 const field_index = @intCast(u32, field_ptr.field_index);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);
27602 switch (parent.pointee) {28330 switch (parent.pointee) {
27603 .direct => |val_ptr| switch (val_ptr.tag()) {28331 .direct => |val_ptr| switch (val_ptr.ip_index) {
27604 .undef => {28332 .empty_struct => {
27605 // A struct or union has been initialized to undefined at comptime and now we28333 const duped = try sema.arena.create(Value);
27606 // are for the first time setting a field. We must change the representation28334 duped.* = val_ptr.*;
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
27698 return beginComptimePtrMutationInner(28335 return beginComptimePtrMutationInner(
27699 sema,28336 sema,
27700 block,28337 block,
27701 src,28338 src,
27702 parent.ty.structFieldType(field_index),28339 parent.ty.structFieldType(field_index, mod),
27703 &payload.val,28340 duped,
27704 ptr_elem_ty,28341 ptr_elem_ty,
27705 parent.decl_ref_mut,28342 parent.mut_decl,
27706 );28343 );
27707 },28344 },
27708 .slice => switch (field_index) {28345 .none => switch (val_ptr.tag()) {
27709 Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner(28346 .aggregate => return beginComptimePtrMutationInner(
27710 sema,28347 sema,
27711 block,28348 block,
27712 src,28349 src,
27713 parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)),28350 parent.ty.structFieldType(field_index, mod),
27714 &val_ptr.castTag(.slice).?.data.ptr,28351 &val_ptr.castTag(.aggregate).?.data[field_index],
27715 ptr_elem_ty,28352 ptr_elem_ty,
27716 parent.decl_ref_mut,28353 parent.mut_decl,
27717 ),28354 ),
28355 .repeated => {
28356 const arena = sema.arena;
2771828357
27719 Value.Payload.Slice.len_index => return beginComptimePtrMutationInner(28358 const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod));
27720 sema,28359 @memset(elems, val_ptr.castTag(.repeated).?.data);
27721 block,28360 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
27722 src,28361
27723 Type.usize,28362 return beginComptimePtrMutationInner(
27724 &val_ptr.castTag(.slice).?.data.len,28363 sema,
27725 ptr_elem_ty,28364 block,
27726 parent.decl_ref_mut,28365 src,
27727 ),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 },
27729 else => unreachable,28412 else => unreachable,
27730 },28413 },
2773128414 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {
27732 .empty_struct_value => {28415 .undef => {
27733 const duped = try sema.arena.create(Value);28416 // A struct or union has been initialized to undefined at comptime and now we
27734 duped.* = Value.initTag(.the_only_possible_value);28417 // are for the first time setting a field. We must change the representation
27735 return beginComptimePtrMutationInner(28418 // of the struct/union from `undef` to `struct`/`union`.
27736 sema,28419 const arena = sema.arena;
27737 block,28420
27738 src,28421 switch (parent.ty.zigTypeTag(mod)) {
27739 parent.ty.structFieldType(field_index),28422 .Struct => {
27740 duped,28423 const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod));
27741 ptr_elem_ty,28424 for (fields, 0..) |*field, i| field.* = (try mod.intern(.{
27742 parent.decl_ref_mut,28425 .undef = parent.ty.structFieldType(i, mod).toIntern(),
27743 );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,
27744 },28496 },
27745
27746 else => unreachable,
27747 },28497 },
27748 .reinterpret => |reinterpret| {28498 .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);
27750 const field_offset = try sema.usizeCast(block, src, field_offset_u64);28500 const field_offset = try sema.usizeCast(block, src, field_offset_u64);
27751 return ComptimePtrMutationKit{28501 return ComptimePtrMutationKit{
27752 .decl_ref_mut = parent.decl_ref_mut,28502 .mut_decl = parent.mut_decl,
27753 .pointee = .{ .reinterpret = .{28503 .pointee = .{ .reinterpret = .{
27754 .val_ptr = reinterpret.val_ptr,28504 .val_ptr = reinterpret.val_ptr,
27755 .byte_offset = reinterpret.byte_offset + field_offset,28505 .byte_offset = reinterpret.byte_offset + field_offset,
...@@ -27760,106 +28510,6 @@ fn beginComptimePtrMutation(...@@ -27760,106 +28510,6 @@ fn beginComptimePtrMutation(
27760 .bad_decl_ty, .bad_ptr_ty => return parent,28510 .bad_decl_ty, .bad_ptr_ty => return parent,
27761 }28511 }
27762 },28512 },
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,
27863 }28513 }
27864}28514}
2786528515
...@@ -27870,46 +28520,50 @@ fn beginComptimePtrMutationInner(...@@ -27870,46 +28520,50 @@ fn beginComptimePtrMutationInner(
27870 decl_ty: Type,28520 decl_ty: Type,
27871 decl_val: *Value,28521 decl_val: *Value,
27872 ptr_elem_ty: Type,28522 ptr_elem_ty: Type,
27873 decl_ref_mut: Value.Payload.DeclRefMut.Data,28523 mut_decl: InternPool.Key.Ptr.Addr.MutDecl,
27874) CompileError!ComptimePtrMutationKit {28524) CompileError!ComptimePtrMutationKit {
27875 const target = sema.mod.getTarget();28525 const mod = sema.mod;
28526 const target = mod.getTarget();
27876 const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok;28527 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
27877 if (coerce_ok) {28531 if (coerce_ok) {
27878 return ComptimePtrMutationKit{28532 return ComptimePtrMutationKit{
27879 .decl_ref_mut = decl_ref_mut,28533 .mut_decl = mut_decl,
27880 .pointee = .{ .direct = decl_val },28534 .pointee = .{ .direct = decl_val },
27881 .ty = decl_ty,28535 .ty = decl_ty,
27882 };28536 };
27883 }28537 }
2788428538
27885 // Handle the case that the decl is an array and we're actually trying to point to an element.28539 // Handle the case that the decl is an array and we're actually trying to point to an element.
27886 if (decl_ty.isArrayOrVector()) {28540 if (decl_ty.isArrayOrVector(mod)) {
27887 const decl_elem_ty = decl_ty.childType();28541 const decl_elem_ty = decl_ty.childType(mod);
27888 if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) {28542 if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) {
27889 return ComptimePtrMutationKit{28543 return ComptimePtrMutationKit{
27890 .decl_ref_mut = decl_ref_mut,28544 .mut_decl = mut_decl,
27891 .pointee = .{ .direct = decl_val },28545 .pointee = .{ .direct = decl_val },
27892 .ty = decl_ty,28546 .ty = decl_ty,
27893 };28547 };
27894 }28548 }
27895 }28549 }
2789628550
27897 if (!decl_ty.hasWellDefinedLayout()) {28551 if (!decl_ty.hasWellDefinedLayout(mod)) {
27898 return ComptimePtrMutationKit{28552 return ComptimePtrMutationKit{
27899 .decl_ref_mut = decl_ref_mut,28553 .mut_decl = mut_decl,
27900 .pointee = .{ .bad_decl_ty = {} },28554 .pointee = .bad_decl_ty,
27901 .ty = decl_ty,28555 .ty = decl_ty,
27902 };28556 };
27903 }28557 }
27904 if (!ptr_elem_ty.hasWellDefinedLayout()) {28558 if (!ptr_elem_ty.hasWellDefinedLayout(mod)) {
27905 return ComptimePtrMutationKit{28559 return ComptimePtrMutationKit{
27906 .decl_ref_mut = decl_ref_mut,28560 .mut_decl = mut_decl,
27907 .pointee = .{ .bad_ptr_ty = {} },28561 .pointee = .bad_ptr_ty,
27908 .ty = ptr_elem_ty,28562 .ty = ptr_elem_ty,
27909 };28563 };
27910 }28564 }
27911 return ComptimePtrMutationKit{28565 return ComptimePtrMutationKit{
27912 .decl_ref_mut = decl_ref_mut,28566 .mut_decl = mut_decl,
27913 .pointee = .{ .reinterpret = .{28567 .pointee = .{ .reinterpret = .{
27914 .val_ptr = decl_val,28568 .val_ptr = decl_val,
27915 .byte_offset = 0,28569 .byte_offset = 0,
...@@ -27951,237 +28605,227 @@ fn beginComptimePtrLoad(...@@ -27951,237 +28605,227 @@ fn beginComptimePtrLoad(
27951 ptr_val: Value,28605 ptr_val: Value,
27952 maybe_array_ty: ?Type,28606 maybe_array_ty: ?Type,
27953) ComptimePtrLoadError!ComptimePtrLoadKit {28607) ComptimePtrLoadError!ComptimePtrLoadKit {
27954 const target = sema.mod.getTarget();28608 const mod = sema.mod;
27955 var deref: ComptimePtrLoadKit = switch (ptr_val.tag()) {28609 const target = mod.getTarget();
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 },
2805528610
28056 .field_ptr => blk: {28611 var deref: ComptimePtrLoadKit = switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {
28057 const field_ptr = ptr_val.castTag(.field_ptr).?.data;28612 .ptr => |ptr| switch (ptr.addr) {
28058 const field_index = @intCast(u32, field_ptr.field_index);28613 .decl, .mut_decl => blk: {
28059 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);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()) {28642 // eu_payload and opt_payload never have a well-defined layout
28062 const struct_ty = field_ptr.container_ty.castTag(.@"struct");28643 if (deref.parent != null) {
28063 if (struct_ty != null and struct_ty.?.data.layout == .Packed) {
28064 // packed structs are not byte addressable
28065 deref.parent = null;28644 deref.parent = null;
28066 } else if (deref.parent) |*parent| {28645 deref.ty_without_well_defined_layout = container_ty;
28067 // Update the byte offset (in-place)28646 }
28068 try sema.resolveTypeLayout(field_ptr.container_ty);28647
28069 const field_offset = field_ptr.container_ty.structFieldOffset(field_index, target);28648 if (deref.pointee) |*tv| {
28070 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);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 }
28071 }28676 }
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) {
28085 deref.pointee = null;28677 deref.pointee = null;
28086 break :blk deref;28678 break :blk deref;
28087 }28679 },
2808828680 .comptime_field => |comptime_field| blk: {
28089 if (field_ptr.container_ty.isSlice()) {28681 const field_ty = mod.intern_pool.typeOf(comptime_field).toType();
28090 const slice_val = tv.val.castTag(.slice).?.data;28682 break :blk ComptimePtrLoadKit{
28091 deref.pointee = switch (field_index) {28683 .parent = null,
28092 Value.Payload.Slice.ptr_index => TypedValue{28684 .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
28093 .ty = field_ptr.container_ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)),28685 .is_mutable = false,
28094 .val = slice_val.ptr,28686 .ty_without_well_defined_layout = field_ty,
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),
28107 };28687 };
28108 }28688 },
28109 break :blk deref;28689 .elem => |elem_ptr| blk: {
28110 },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: {28704 if (elem_ptr.index != 0) {
28113 const comptime_field_ptr = ptr_val.castTag(.comptime_field_ptr).?.data;28705 if (elem_ty.hasWellDefinedLayout(mod)) {
28114 break :blk ComptimePtrLoadKit{28706 if (deref.parent) |*parent| {
28115 .parent = null,28707 // Update the byte offset (in-place)
28116 .pointee = .{ .ty = comptime_field_ptr.field_ty, .val = comptime_field_ptr.field_val },28708 const elem_size = try sema.typeAbiSize(elem_ty);
28117 .is_mutable = false,28709 const offset = parent.byte_offset + elem_size * elem_ptr.index;
28118 .ty_without_well_defined_layout = comptime_field_ptr.field_ty,28710 parent.byte_offset = try sema.usizeCast(block, src, offset);
28119 };28711 }
28120 },28712 } else {
28713 deref.parent = null;
28714 deref.ty_without_well_defined_layout = elem_ty;
28715 }
28716 }
2812128717
28122 .opt_payload_ptr,28718 // If we're loading an elem that was derived from a different type
28123 .eu_payload_ptr,28719 // than the true type of the underlying decl, we cannot deref directly
28124 => blk: {28720 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
28125 const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data;28721 const deref_elem_ty = deref.pointee.?.ty.childType(mod);
28126 const payload_ty = switch (ptr_val.tag()) {28722 break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or
28127 .eu_payload_ptr => payload_ptr.container_ty.errorUnionPayload(),28723 (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok;
28128 .opt_payload_ptr => try payload_ptr.container_ty.optionalChildAlloc(sema.arena),28724 } else false;
28129 else => unreachable,28725 if (!ty_matches) {
28130 };28726 deref.pointee = null;
28131 var deref = try sema.beginComptimePtrLoad(block, src, payload_ptr.container_ptr, payload_ptr.container_ty);28727 break :blk deref;
28728 }
2813228729
28133 // eu_payload_ptr and opt_payload_ptr never have a well-defined layout28730 var array_tv = deref.pointee.?;
28134 if (deref.parent != null) {28731 const check_len = array_tv.ty.arrayLenIncludingSentinel(mod);
28135 deref.parent = null;28732 if (maybe_array_ty) |load_ty| {
28136 deref.ty_without_well_defined_layout = payload_ptr.container_ty;28733 // It's possible that we're loading a [N]T, in which case we'd like to slice
28137 }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 };
28140 const coerce_in_mem_ok =28790 const coerce_in_mem_ok =
28141 (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or28791 (try sema.coerceInMemoryAllowed(block, 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;28792 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28143 if (coerce_in_mem_ok) {28793 if (!coerce_in_mem_ok) {
28144 const payload_val = switch (ptr_val.tag()) {28794 deref.pointee = null;
28145 .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else {28795 break :blk deref;
28146 return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name});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),
28147 },28803 },
28148 .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: {28804 Value.slice_len_index => TypedValue{
28149 if (tv.val.isNull()) return sema.fail(block, src, "attempt to use null value", .{});28805 .ty = Type.usize,
28150 break :opt tv.val;28806 .val = mod.intern_pool.indexToKey(tv.val.toIntern()).ptr.len.toValue(),
28151 },28807 },
28152 else => unreachable,28808 else => unreachable,
28153 };28809 };
28154 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };28810 } else {
28155 break :blk deref;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 };
28156 }28816 }
28157 }28817 break :blk deref;
28158 deref.pointee = null;28818 },
28159 break :blk deref;
28160 },
28161 .null_value => {
28162 return sema.fail(block, src, "attempt to use null value", .{});
28163 },28819 },
28164 .opt_payload => blk: {28820 .opt => |opt| switch (opt.val) {
28165 const opt_payload = ptr_val.castTag(.opt_payload).?.data;28821 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28166 break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null);28822 else => |payload| try sema.beginComptimePtrLoad(block, src, payload.toValue(), null),
28167 },28823 },
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
28180 else => unreachable,28824 else => unreachable,
28181 };28825 };
2818228826
28183 if (deref.pointee) |tv| {28827 if (deref.pointee) |tv| {
28184 if (deref.parent == null and tv.ty.hasWellDefinedLayout()) {28828 if (deref.parent == null and tv.ty.hasWellDefinedLayout(mod)) {
28185 deref.parent = .{ .tv = tv, .byte_offset = 0 };28829 deref.parent = .{ .tv = tv, .byte_offset = 0 };
28186 }28830 }
28187 }28831 }
...@@ -28196,21 +28840,21 @@ fn bitCast(...@@ -28196,21 +28840,21 @@ fn bitCast(
28196 inst_src: LazySrcLoc,28840 inst_src: LazySrcLoc,
28197 operand_src: ?LazySrcLoc,28841 operand_src: ?LazySrcLoc,
28198) CompileError!Air.Inst.Ref {28842) CompileError!Air.Inst.Ref {
28843 const mod = sema.mod;
28199 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);28844 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);
28200 try sema.resolveTypeLayout(dest_ty);28845 try sema.resolveTypeLayout(dest_ty);
2820128846
28202 const old_ty = try sema.resolveTypeFields(sema.typeOf(inst));28847 const old_ty = try sema.resolveTypeFields(sema.typeOf(inst));
28203 try sema.resolveTypeLayout(old_ty);28848 try sema.resolveTypeLayout(old_ty);
2820428849
28205 const target = sema.mod.getTarget();28850 const dest_bits = dest_ty.bitSize(mod);
28206 const dest_bits = dest_ty.bitSize(target);28851 const old_bits = old_ty.bitSize(mod);
28207 const old_bits = old_ty.bitSize(target);
2820828852
28209 if (old_bits != dest_bits) {28853 if (old_bits != dest_bits) {
28210 return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{28854 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),
28212 dest_bits,28856 dest_bits,
28213 old_ty.fmt(sema.mod),28857 old_ty.fmt(mod),
28214 old_bits,28858 old_bits,
28215 });28859 });
28216 }28860 }
...@@ -28233,20 +28877,21 @@ fn bitCastVal(...@@ -28233,20 +28877,21 @@ fn bitCastVal(
28233 new_ty: Type,28877 new_ty: Type,
28234 buffer_offset: usize,28878 buffer_offset: usize,
28235) !?Value {28879) !?Value {
28236 const target = sema.mod.getTarget();28880 const mod = sema.mod;
28237 if (old_ty.eql(new_ty, sema.mod)) return val;28881 if (old_ty.eql(new_ty, mod)) return val;
2823828882
28239 // For types with well-defined memory layouts, we serialize them a byte buffer,28883 // For types with well-defined memory layouts, we serialize them a byte buffer,
28240 // then deserialize to the new type.28884 // 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));
28242 const buffer = try sema.gpa.alloc(u8, abi_size);28886 const buffer = try sema.gpa.alloc(u8, abi_size);
28243 defer sema.gpa.free(buffer);28887 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,
28245 error.ReinterpretDeclRef => return null,28890 error.ReinterpretDeclRef => return null,
28246 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already28891 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)}),
28248 };28893 };
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);
28250}28895}
2825128896
28252fn coerceArrayPtrToSlice(28897fn coerceArrayPtrToSlice(
...@@ -28256,25 +28901,32 @@ fn coerceArrayPtrToSlice(...@@ -28256,25 +28901,32 @@ fn coerceArrayPtrToSlice(
28256 inst: Air.Inst.Ref,28901 inst: Air.Inst.Ref,
28257 inst_src: LazySrcLoc,28902 inst_src: LazySrcLoc,
28258) CompileError!Air.Inst.Ref {28903) CompileError!Air.Inst.Ref {
28904 const mod = sema.mod;
28259 if (try sema.resolveMaybeUndefVal(inst)) |val| {28905 if (try sema.resolveMaybeUndefVal(inst)) |val| {
28260 const ptr_array_ty = sema.typeOf(inst);28906 const ptr_array_ty = sema.typeOf(inst);
28261 const array_ty = ptr_array_ty.childType();28907 const array_ty = ptr_array_ty.childType(mod);
28262 const slice_val = try Value.Tag.slice.create(sema.arena, .{28908 const slice_val = try mod.intern(.{ .ptr = .{
28263 .ptr = val,28909 .ty = dest_ty.toIntern(),
28264 .len = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen()),28910 .addr = switch (mod.intern_pool.indexToKey(val.toIntern())) {
28265 });28911 .undef => .{ .int = try mod.intern(.{ .undef = .usize_type }) },
28266 return sema.addConstant(dest_ty, slice_val);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());
28267 }28918 }
28268 try sema.requireRuntimeBlock(block, inst_src, null);28919 try sema.requireRuntimeBlock(block, inst_src, null);
28269 return block.addTyOp(.array_to_slice, dest_ty, inst);28920 return block.addTyOp(.array_to_slice, dest_ty, inst);
28270}28921}
2827128922
28272fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_result: *InMemoryCoercionResult) bool {28923fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_result: *InMemoryCoercionResult) bool {
28273 const dest_info = dest_ty.ptrInfo().data;28924 const mod = sema.mod;
28274 const inst_info = inst_ty.ptrInfo().data;28925 const dest_info = dest_ty.ptrInfo(mod);
28275 const len0 = (inst_info.pointee_type.zigTypeTag() == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel() == 0 or28926 const inst_info = inst_ty.ptrInfo(mod);
28276 (inst_info.pointee_type.arrayLen() == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or28927 const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or
28277 (inst_info.pointee_type.isTuple() and inst_info.pointee_type.structFieldCount() == 0);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
28279 const ok_cv_qualifiers =28931 const ok_cv_qualifiers =
28280 ((inst_info.mutable or !dest_info.mutable) or len0) and28932 ((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...@@ -28298,17 +28950,16 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
28298 }28950 }
28299 if (inst_info.@"align" == 0 and dest_info.@"align" == 0) return true;28951 if (inst_info.@"align" == 0 and dest_info.@"align" == 0) return true;
28300 if (len0) return true;28952 if (len0) return true;
28301 const target = sema.mod.getTarget();
2830228953
28303 const inst_align = if (inst_info.@"align" != 0)28954 const inst_align = if (inst_info.@"align" != 0)
28304 inst_info.@"align"28955 inst_info.@"align"
28305 else28956 else
28306 inst_info.pointee_type.abiAlignment(target);28957 inst_info.pointee_type.abiAlignment(mod);
2830728958
28308 const dest_align = if (dest_info.@"align" != 0)28959 const dest_align = if (dest_info.@"align" != 0)
28309 dest_info.@"align"28960 dest_info.@"align"
28310 else28961 else
28311 dest_info.pointee_type.abiAlignment(target);28962 dest_info.pointee_type.abiAlignment(mod);
2831228963
28313 if (dest_align > inst_align) {28964 if (dest_align > inst_align) {
28314 in_memory_result.* = .{ .ptr_alignment = .{28965 in_memory_result.* = .{ .ptr_alignment = .{
...@@ -28327,26 +28978,30 @@ fn coerceCompatiblePtrs(...@@ -28327,26 +28978,30 @@ fn coerceCompatiblePtrs(
28327 inst: Air.Inst.Ref,28978 inst: Air.Inst.Ref,
28328 inst_src: LazySrcLoc,28979 inst_src: LazySrcLoc,
28329) !Air.Inst.Ref {28980) !Air.Inst.Ref {
28981 const mod = sema.mod;
28330 const inst_ty = sema.typeOf(inst);28982 const inst_ty = sema.typeOf(inst);
28331 if (try sema.resolveMaybeUndefVal(inst)) |val| {28983 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)) {
28333 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});28985 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
28334 }28986 }
28335 // The comptime Value representation is compatible with both types.28987 // 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 );
28337 }28992 }
28338 try sema.requireRuntimeBlock(block, inst_src, null);28993 try sema.requireRuntimeBlock(block, inst_src, null);
28339 const inst_allows_zero = inst_ty.zigTypeTag() != .Pointer or inst_ty.ptrAllowsZero();28994 const inst_allows_zero = inst_ty.zigTypeTag(mod) != .Pointer or inst_ty.ptrAllowsZero(mod);
28340 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and28995 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(mod) and
28341 (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn))28996 (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn))
28342 {28997 {
28343 const actual_ptr = if (inst_ty.isSlice())28998 const actual_ptr = if (inst_ty.isSlice(mod))
28344 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)28999 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
28345 else29000 else
28346 inst;29001 inst;
28347 const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);29002 const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);
28348 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);29003 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: {
28350 const len = try sema.analyzeSliceLen(block, inst_src, inst);29005 const len = try sema.analyzeSliceLen(block, inst_src, inst);
28351 const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);29006 const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);
28352 break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero);29007 break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero);
...@@ -28364,9 +29019,11 @@ fn coerceEnumToUnion(...@@ -28364,9 +29019,11 @@ fn coerceEnumToUnion(
28364 inst: Air.Inst.Ref,29019 inst: Air.Inst.Ref,
28365 inst_src: LazySrcLoc,29020 inst_src: LazySrcLoc,
28366) !Air.Inst.Ref {29021) !Air.Inst.Ref {
29022 const mod = sema.mod;
29023 const ip = &mod.intern_pool;
28367 const inst_ty = sema.typeOf(inst);29024 const inst_ty = sema.typeOf(inst);
2836829025
28369 const tag_ty = union_ty.unionTagType() orelse {29026 const tag_ty = union_ty.unionTagType(mod) orelse {
28370 const msg = msg: {29027 const msg = msg: {
28371 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{29028 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{
28372 union_ty.fmt(sema.mod), inst_ty.fmt(sema.mod),29029 union_ty.fmt(sema.mod), inst_ty.fmt(sema.mod),
...@@ -28393,16 +29050,18 @@ fn coerceEnumToUnion(...@@ -28393,16 +29050,18 @@ fn coerceEnumToUnion(
28393 return sema.failWithOwnedErrorMsg(msg);29050 return sema.failWithOwnedErrorMsg(msg);
28394 };29051 };
2839529052
28396 const union_obj = union_ty.cast(Type.Payload.Union).?.data;29053 const union_obj = mod.typeToUnion(union_ty).?;
28397 const field = union_obj.fields.values()[field_index];29054 const field = union_obj.fields.values()[field_index];
28398 const field_ty = try sema.resolveTypeFields(field.ty);29055 const field_ty = try sema.resolveTypeFields(field.ty);
28399 if (field_ty.zigTypeTag() == .NoReturn) {29056 if (field_ty.zigTypeTag(mod) == .NoReturn) {
28400 const msg = msg: {29057 const msg = msg: {
28401 const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{});29058 const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{});
28402 errdefer msg.destroy(sema.gpa);29059 errdefer msg.destroy(sema.gpa);
2840329060
28404 const field_name = union_obj.fields.keys()[field_index];29061 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 });
28406 try sema.addDeclaredHereNote(msg, union_ty);29065 try sema.addDeclaredHereNote(msg, union_ty);
28407 break :msg msg;29066 break :msg msg;
28408 };29067 };
...@@ -28411,27 +29070,27 @@ fn coerceEnumToUnion(...@@ -28411,27 +29070,27 @@ fn coerceEnumToUnion(
28411 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {29070 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
28412 const msg = msg: {29071 const msg = msg: {
28413 const field_name = union_obj.fields.keys()[field_index];29072 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}'", .{29073 const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{
28415 inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod), field_ty.fmt(sema.mod), field_name,29074 inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod),
29075 field_ty.fmt(sema.mod), field_name.fmt(ip),
28416 });29076 });
28417 errdefer msg.destroy(sema.gpa);29077 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 });
28420 try sema.addDeclaredHereNote(msg, union_ty);29082 try sema.addDeclaredHereNote(msg, union_ty);
28421 break :msg msg;29083 break :msg msg;
28422 };29084 };
28423 return sema.failWithOwnedErrorMsg(msg);29085 return sema.failWithOwnedErrorMsg(msg);
28424 };29086 };
2842529087
28426 return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{29088 return sema.addConstant(union_ty, try mod.unionValue(union_ty, val, opv));
28427 .tag = val,
28428 .val = opv,
28429 }));
28430 }29089 }
2843129090
28432 try sema.requireRuntimeBlock(block, inst_src, null);29091 try sema.requireRuntimeBlock(block, inst_src, null);
2843329092
28434 if (tag_ty.isNonexhaustiveEnum()) {29093 if (tag_ty.isNonexhaustiveEnum(mod)) {
28435 const msg = msg: {29094 const msg = msg: {
28436 const msg = try sema.errMsg(block, inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{29095 const msg = try sema.errMsg(block, inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{
28437 union_ty.fmt(sema.mod),29096 union_ty.fmt(sema.mod),
...@@ -28443,13 +29102,13 @@ fn coerceEnumToUnion(...@@ -28443,13 +29102,13 @@ fn coerceEnumToUnion(
28443 return sema.failWithOwnedErrorMsg(msg);29102 return sema.failWithOwnedErrorMsg(msg);
28444 }29103 }
2844529104
28446 const union_obj = union_ty.cast(Type.Payload.Union).?.data;29105 const union_obj = mod.typeToUnion(union_ty).?;
28447 {29106 {
28448 var msg: ?*Module.ErrorMsg = null;29107 var msg: ?*Module.ErrorMsg = null;
28449 errdefer if (msg) |some| some.destroy(sema.gpa);29108 errdefer if (msg) |some| some.destroy(sema.gpa);
2845029109
28451 for (union_obj.fields.values(), 0..) |field, i| {29110 for (union_obj.fields.values(), 0..) |field, i| {
28452 if (field.ty.zigTypeTag() == .NoReturn) {29111 if (field.ty.zigTypeTag(mod) == .NoReturn) {
28453 const err_msg = msg orelse try sema.errMsg(29112 const err_msg = msg orelse try sema.errMsg(
28454 block,29113 block,
28455 inst_src,29114 inst_src,
...@@ -28469,7 +29128,7 @@ fn coerceEnumToUnion(...@@ -28469,7 +29128,7 @@ fn coerceEnumToUnion(
28469 }29128 }
2847029129
28471 // If the union has all fields 0 bits, the union value is just the enum value.29130 // 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)) {
28473 return block.addBitCast(union_ty, enum_tag);29132 return block.addBitCast(union_ty, enum_tag);
28474 }29133 }
2847529134
...@@ -28487,8 +29146,11 @@ fn coerceEnumToUnion(...@@ -28487,8 +29146,11 @@ fn coerceEnumToUnion(
28487 while (it.next()) |field| : (field_index += 1) {29146 while (it.next()) |field| : (field_index += 1) {
28488 const field_name = field.key_ptr.*;29147 const field_name = field.key_ptr.*;
28489 const field_ty = field.value_ptr.ty;29148 const field_ty = field.value_ptr.ty;
28490 if (!field_ty.hasRuntimeBits()) continue;29149 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
28491 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) });29150 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{
29151 field_name.fmt(ip),
29152 field_ty.fmt(sema.mod),
29153 });
28492 }29154 }
28493 try sema.addDeclaredHereNote(msg, union_ty);29155 try sema.addDeclaredHereNote(msg, union_ty);
28494 break :msg msg;29156 break :msg msg;
...@@ -28504,36 +29166,55 @@ fn coerceAnonStructToUnion(...@@ -28504,36 +29166,55 @@ fn coerceAnonStructToUnion(
28504 inst: Air.Inst.Ref,29166 inst: Air.Inst.Ref,
28505 inst_src: LazySrcLoc,29167 inst_src: LazySrcLoc,
28506) !Air.Inst.Ref {29168) !Air.Inst.Ref {
29169 const mod = sema.mod;
28507 const inst_ty = sema.typeOf(inst);29170 const inst_ty = sema.typeOf(inst);
28508 const field_count = inst_ty.structFieldCount();29171 const field_info: union(enum) {
28509 if (field_count != 1) {29172 name: InternPool.NullTerminatedString,
28510 const msg = msg: {29173 count: usize,
28511 const msg = if (field_count > 1) try sema.errMsg(29174 } = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
28512 block,29175 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)
28513 inst_src,29176 .{ .name = anon_struct_type.names[0] }
28514 "cannot initialize multiple union fields at once; unions can only have one active field",29177 else
28515 .{},29178 .{ .count = anon_struct_type.names.len },
28516 ) else try sema.errMsg(29179 .struct_type => |struct_type| name: {
28517 block,29180 const field_names = mod.structPtrUnwrap(struct_type.index).?.fields.keys();
28518 inst_src,29181 break :name if (field_names.len == 1)
28519 "union initializer must initialize one field",29182 .{ .name = field_names[0] }
28520 .{},29183 else
28521 );29184 .{ .count = field_names.len };
28522 errdefer msg.destroy(sema.gpa);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 out29209 // TODO add notes for where the anon struct was created to point out
28525 // the extra fields.29210 // the extra fields.
2852629211
28527 try sema.addDeclaredHereNote(msg, union_ty);29212 try sema.addDeclaredHereNote(msg, union_ty);
28528 break :msg msg;29213 break :msg msg;
28529 };29214 };
28530 return sema.failWithOwnedErrorMsg(msg);29215 return sema.failWithOwnedErrorMsg(msg);
29216 },
28531 }29217 }
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);
28537}29218}
2853829219
28539fn coerceAnonStructToUnionPtrs(29220fn coerceAnonStructToUnionPtrs(
...@@ -28544,7 +29225,8 @@ fn coerceAnonStructToUnionPtrs(...@@ -28544,7 +29225,8 @@ fn coerceAnonStructToUnionPtrs(
28544 ptr_anon_struct: Air.Inst.Ref,29225 ptr_anon_struct: Air.Inst.Ref,
28545 anon_struct_src: LazySrcLoc,29226 anon_struct_src: LazySrcLoc,
28546) !Air.Inst.Ref {29227) !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);
28548 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);29230 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);
28549 const union_inst = try sema.coerceAnonStructToUnion(block, union_ty, union_ty_src, anon_struct, anon_struct_src);29231 const union_inst = try sema.coerceAnonStructToUnion(block, union_ty, union_ty_src, anon_struct, anon_struct_src);
28550 return sema.analyzeRef(block, union_ty_src, union_inst);29232 return sema.analyzeRef(block, union_ty_src, union_inst);
...@@ -28558,7 +29240,8 @@ fn coerceAnonStructToStructPtrs(...@@ -28558,7 +29240,8 @@ fn coerceAnonStructToStructPtrs(
28558 ptr_anon_struct: Air.Inst.Ref,29240 ptr_anon_struct: Air.Inst.Ref,
28559 anon_struct_src: LazySrcLoc,29241 anon_struct_src: LazySrcLoc,
28560) !Air.Inst.Ref {29242) !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);
28562 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);29245 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);
28563 const struct_inst = try sema.coerceTupleToStruct(block, struct_ty, anon_struct, anon_struct_src);29246 const struct_inst = try sema.coerceTupleToStruct(block, struct_ty, anon_struct, anon_struct_src);
28564 return sema.analyzeRef(block, struct_ty_src, struct_inst);29247 return sema.analyzeRef(block, struct_ty_src, struct_inst);
...@@ -28573,15 +29256,16 @@ fn coerceArrayLike(...@@ -28573,15 +29256,16 @@ fn coerceArrayLike(
28573 inst: Air.Inst.Ref,29256 inst: Air.Inst.Ref,
28574 inst_src: LazySrcLoc,29257 inst_src: LazySrcLoc,
28575) !Air.Inst.Ref {29258) !Air.Inst.Ref {
29259 const mod = sema.mod;
28576 const inst_ty = sema.typeOf(inst);29260 const inst_ty = sema.typeOf(inst);
28577 const inst_len = inst_ty.arrayLen();29261 const inst_len = inst_ty.arrayLen(mod);
28578 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen());29262 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(mod));
28579 const target = sema.mod.getTarget();29263 const target = mod.getTarget();
2858029264
28581 if (dest_len != inst_len) {29265 if (dest_len != inst_len) {
28582 const msg = msg: {29266 const msg = msg: {
28583 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{29267 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),
28585 });29269 });
28586 errdefer msg.destroy(sema.gpa);29270 errdefer msg.destroy(sema.gpa);
28587 try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len});29271 try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len});
...@@ -28591,35 +29275,32 @@ fn coerceArrayLike(...@@ -28591,35 +29275,32 @@ fn coerceArrayLike(
28591 return sema.failWithOwnedErrorMsg(msg);29275 return sema.failWithOwnedErrorMsg(msg);
28592 }29276 }
2859329277
28594 const dest_elem_ty = dest_ty.childType();29278 const dest_elem_ty = dest_ty.childType(mod);
28595 const inst_elem_ty = inst_ty.childType();29279 const inst_elem_ty = inst_ty.childType(mod);
28596 const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, false, target, dest_ty_src, inst_src);29280 const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, false, target, dest_ty_src, inst_src);
28597 if (in_memory_result == .ok) {29281 if (in_memory_result == .ok) {
28598 if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {29282 if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {
28599 // These types share the same comptime value representation.29283 // 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);
28601 }29285 }
28602 try sema.requireRuntimeBlock(block, inst_src, null);29286 try sema.requireRuntimeBlock(block, inst_src, null);
28603 return block.addBitCast(dest_ty, inst);29287 return block.addBitCast(dest_ty, inst);
28604 }29288 }
2860529289
28606 const element_vals = try sema.arena.alloc(Value, dest_len);29290 const element_vals = try sema.arena.alloc(InternPool.Index, dest_len);
28607 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len);29291 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len);
28608 var runtime_src: ?LazySrcLoc = null;29292 var runtime_src: ?LazySrcLoc = null;
2860929293
28610 for (element_vals, 0..) |*elem, i| {29294 for (element_vals, element_refs, 0..) |*val, *ref, i| {
28611 const index_ref = try sema.addConstant(29295 const index_ref = try sema.addConstant(Type.usize, try mod.intValue(Type.usize, i));
28612 Type.usize,
28613 try Value.Tag.int_u64.create(sema.arena, i),
28614 );
28615 const src = inst_src; // TODO better source location29296 const src = inst_src; // TODO better source location
28616 const elem_src = inst_src; // TODO better source location29297 const elem_src = inst_src; // TODO better source location
28617 const elem_ref = try sema.elemValArray(block, src, inst_src, inst, elem_src, index_ref, true);29298 const elem_ref = try sema.elemValArray(block, src, inst_src, inst, elem_src, index_ref, true);
28618 const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src);29299 const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src);
28619 element_refs[i] = coerced;29300 ref.* = coerced;
28620 if (runtime_src == null) {29301 if (runtime_src == null) {
28621 if (try sema.resolveMaybeUndefVal(coerced)) |elem_val| {29302 if (try sema.resolveMaybeUndefVal(coerced)) |elem_val| {
28622 elem.* = elem_val;29303 val.* = try elem_val.intern(dest_elem_ty, mod);
28623 } else {29304 } else {
28624 runtime_src = elem_src;29305 runtime_src = elem_src;
28625 }29306 }
...@@ -28631,10 +29312,10 @@ fn coerceArrayLike(...@@ -28631,10 +29312,10 @@ fn coerceArrayLike(
28631 return block.addAggregateInit(dest_ty, element_refs);29312 return block.addAggregateInit(dest_ty, element_refs);
28632 }29313 }
2863329314
28634 return sema.addConstant(29315 return sema.addConstant(dest_ty, (try mod.intern(.{ .aggregate = .{
28635 dest_ty,29316 .ty = dest_ty.toIntern(),
28636 try Value.Tag.aggregate.create(sema.arena, element_vals),29317 .storage = .{ .elems = element_vals },
28637 );29318 } })).toValue());
28638}29319}
2863929320
28640/// If the lengths match, coerces element-wise.29321/// If the lengths match, coerces element-wise.
...@@ -28646,9 +29327,10 @@ fn coerceTupleToArray(...@@ -28646,9 +29327,10 @@ fn coerceTupleToArray(
28646 inst: Air.Inst.Ref,29327 inst: Air.Inst.Ref,
28647 inst_src: LazySrcLoc,29328 inst_src: LazySrcLoc,
28648) !Air.Inst.Ref {29329) !Air.Inst.Ref {
29330 const mod = sema.mod;
28649 const inst_ty = sema.typeOf(inst);29331 const inst_ty = sema.typeOf(inst);
28650 const inst_len = inst_ty.arrayLen();29332 const inst_len = inst_ty.arrayLen(mod);
28651 const dest_len = dest_ty.arrayLen();29333 const dest_len = dest_ty.arrayLen(mod);
2865229334
28653 if (dest_len != inst_len) {29335 if (dest_len != inst_len) {
28654 const msg = msg: {29336 const msg = msg: {
...@@ -28663,26 +29345,27 @@ fn coerceTupleToArray(...@@ -28663,26 +29345,27 @@ fn coerceTupleToArray(
28663 return sema.failWithOwnedErrorMsg(msg);29345 return sema.failWithOwnedErrorMsg(msg);
28664 }29346 }
2866529347
28666 const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLenIncludingSentinel());29348 const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_len);
28667 const element_vals = try sema.arena.alloc(Value, dest_elems);29349 const element_vals = try sema.arena.alloc(InternPool.Index, dest_elems);
28668 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_elems);29350 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
28671 var runtime_src: ?LazySrcLoc = null;29353 var runtime_src: ?LazySrcLoc = null;
28672 for (element_vals, 0..) |*elem, i_usize| {29354 for (element_vals, element_refs, 0..) |*val, *ref, i_usize| {
28673 const i = @intCast(u32, i_usize);29355 const i = @intCast(u32, i_usize);
28674 if (i_usize == inst_len) {29356 if (i_usize == inst_len) {
28675 elem.* = dest_ty.sentinel().?;29357 const sentinel_val = dest_ty.sentinel(mod).?;
28676 element_refs[i] = try sema.addConstant(dest_elem_ty, elem.*);29358 val.* = sentinel_val.toIntern();
29359 ref.* = try sema.addConstant(dest_elem_ty, sentinel_val);
28677 break;29360 break;
28678 }29361 }
28679 const elem_src = inst_src; // TODO better source location29362 const elem_src = inst_src; // TODO better source location
28680 const elem_ref = try sema.tupleField(block, inst_src, inst, elem_src, i);29363 const elem_ref = try sema.tupleField(block, inst_src, inst, elem_src, i);
28681 const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src);29364 const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src);
28682 element_refs[i] = coerced;29365 ref.* = coerced;
28683 if (runtime_src == null) {29366 if (runtime_src == null) {
28684 if (try sema.resolveMaybeUndefVal(coerced)) |elem_val| {29367 if (try sema.resolveMaybeUndefVal(coerced)) |elem_val| {
28685 elem.* = elem_val;29368 val.* = try elem_val.intern(dest_elem_ty, mod);
28686 } else {29369 } else {
28687 runtime_src = elem_src;29370 runtime_src = elem_src;
28688 }29371 }
...@@ -28694,10 +29377,10 @@ fn coerceTupleToArray(...@@ -28694,10 +29377,10 @@ fn coerceTupleToArray(
28694 return block.addAggregateInit(dest_ty, element_refs);29377 return block.addAggregateInit(dest_ty, element_refs);
28695 }29378 }
2869629379
28697 return sema.addConstant(29380 return sema.addConstant(dest_ty, (try mod.intern(.{ .aggregate = .{
28698 dest_ty,29381 .ty = dest_ty.toIntern(),
28699 try Value.Tag.aggregate.create(sema.arena, element_vals),29382 .storage = .{ .elems = element_vals },
28700 );29383 } })).toValue());
28701}29384}
2870229385
28703/// If the lengths match, coerces element-wise.29386/// If the lengths match, coerces element-wise.
...@@ -28709,10 +29392,11 @@ fn coerceTupleToSlicePtrs(...@@ -28709,10 +29392,11 @@ fn coerceTupleToSlicePtrs(
28709 ptr_tuple: Air.Inst.Ref,29392 ptr_tuple: Air.Inst.Ref,
28710 tuple_src: LazySrcLoc,29393 tuple_src: LazySrcLoc,
28711) !Air.Inst.Ref {29394) !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);
28713 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);29397 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);
28714 const slice_info = slice_ty.ptrInfo().data;29398 const slice_info = slice_ty.ptrInfo(mod);
28715 const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(), slice_info.sentinel, slice_info.pointee_type, sema.mod);29399 const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(mod), slice_info.sentinel, slice_info.pointee_type, sema.mod);
28716 const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src);29400 const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src);
28717 if (slice_info.@"align" != 0) {29401 if (slice_info.@"align" != 0) {
28718 return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{});29402 return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{});
...@@ -28730,8 +29414,9 @@ fn coerceTupleToArrayPtrs(...@@ -28730,8 +29414,9 @@ fn coerceTupleToArrayPtrs(
28730 ptr_tuple: Air.Inst.Ref,29414 ptr_tuple: Air.Inst.Ref,
28731 tuple_src: LazySrcLoc,29415 tuple_src: LazySrcLoc,
28732) !Air.Inst.Ref {29416) !Air.Inst.Ref {
29417 const mod = sema.mod;
28733 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);29418 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);
28735 const array_ty = ptr_info.pointee_type;29420 const array_ty = ptr_info.pointee_type;
28736 const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src);29421 const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src);
28737 if (ptr_info.@"align" != 0) {29422 if (ptr_info.@"align" != 0) {
...@@ -28750,27 +29435,41 @@ fn coerceTupleToStruct(...@@ -28750,27 +29435,41 @@ fn coerceTupleToStruct(
28750 inst: Air.Inst.Ref,29435 inst: Air.Inst.Ref,
28751 inst_src: LazySrcLoc,29436 inst_src: LazySrcLoc,
28752) !Air.Inst.Ref {29437) !Air.Inst.Ref {
29438 const mod = sema.mod;
29439 const ip = &mod.intern_pool;
28753 const struct_ty = try sema.resolveTypeFields(dest_ty);29440 const struct_ty = try sema.resolveTypeFields(dest_ty);
2875429441
28755 if (struct_ty.isTupleOrAnonStruct()) {29442 if (struct_ty.isTupleOrAnonStruct(mod)) {
28756 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);29443 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
28757 }29444 }
2875829445
28759 const fields = struct_ty.structFields();29446 const fields = struct_ty.structFields(mod);
28760 const field_vals = try sema.arena.alloc(Value, fields.count());29447 const field_vals = try sema.arena.alloc(InternPool.Index, fields.count());
28761 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);29448 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
28762 @memset(field_refs, .none);29449 @memset(field_refs, .none);
2876329450
28764 const inst_ty = sema.typeOf(inst);29451 const inst_ty = sema.typeOf(inst);
28765 var runtime_src: ?LazySrcLoc = null;29452 var runtime_src: ?LazySrcLoc = null;
28766 const field_count = inst_ty.structFieldCount();29453 const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
28767 var field_i: u32 = 0;29454 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
28768 while (field_i < field_count) : (field_i += 1) {29455 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
28769 const field_src = inst_src; // TODO better source location29456 struct_obj.fields.count()
28770 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|
28771 payload.data.names[field_i]
28772 else29457 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 };
28774 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);29473 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
28775 const field = fields.values()[field_index];29474 const field = fields.values()[field_index];
28776 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);29475 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
...@@ -28781,13 +29480,13 @@ fn coerceTupleToStruct(...@@ -28781,13 +29480,13 @@ fn coerceTupleToStruct(
28781 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");29480 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
28782 };29481 };
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)) {
28785 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);29484 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
28786 }29485 }
28787 }29486 }
28788 if (runtime_src == null) {29487 if (runtime_src == null) {
28789 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {29488 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {
28790 field_vals[field_index] = field_val;29489 field_vals[field_index] = field_val.toIntern();
28791 } else {29490 } else {
28792 runtime_src = field_src;29491 runtime_src = field_src;
28793 }29492 }
...@@ -28804,9 +29503,9 @@ fn coerceTupleToStruct(...@@ -28804,9 +29503,9 @@ fn coerceTupleToStruct(
28804 const field_name = fields.keys()[i];29503 const field_name = fields.keys()[i];
28805 const field = fields.values()[i];29504 const field = fields.values()[i];
28806 const field_src = inst_src; // TODO better source location29505 const field_src = inst_src; // TODO better source location
28807 if (field.default_val.tag() == .unreachable_value) {29506 if (field.default_val == .none) {
28808 const template = "missing struct field: {s}";29507 const template = "missing struct field: {}";
28809 const args = .{field_name};29508 const args = .{field_name.fmt(ip)};
28810 if (root_msg) |msg| {29509 if (root_msg) |msg| {
28811 try sema.errNote(block, field_src, msg, template, args);29510 try sema.errNote(block, field_src, msg, template, args);
28812 } else {29511 } else {
...@@ -28817,7 +29516,7 @@ fn coerceTupleToStruct(...@@ -28817,7 +29516,7 @@ fn coerceTupleToStruct(
28817 if (runtime_src == null) {29516 if (runtime_src == null) {
28818 field_vals[i] = field.default_val;29517 field_vals[i] = field.default_val;
28819 } else {29518 } else {
28820 field_ref.* = try sema.addConstant(field.ty, field.default_val);29519 field_ref.* = try sema.addConstant(field.ty, field.default_val.toValue());
28821 }29520 }
28822 }29521 }
2882329522
...@@ -28832,10 +29531,14 @@ fn coerceTupleToStruct(...@@ -28832,10 +29531,14 @@ fn coerceTupleToStruct(
28832 return block.addAggregateInit(struct_ty, field_refs);29531 return block.addAggregateInit(struct_ty, field_refs);
28833 }29532 }
2883429533
28835 return sema.addConstant(29534 const struct_val = try mod.intern(.{ .aggregate = .{
28836 struct_ty,29535 .ty = struct_ty.toIntern(),
28837 try Value.Tag.aggregate.create(sema.arena, field_vals),29536 .storage = .{ .elems = field_vals },
28838 );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());
28839}29542}
2884029543
28841fn coerceTupleToTuple(29544fn coerceTupleToTuple(
...@@ -28845,47 +29548,76 @@ fn coerceTupleToTuple(...@@ -28845,47 +29548,76 @@ fn coerceTupleToTuple(
28845 inst: Air.Inst.Ref,29548 inst: Air.Inst.Ref,
28846 inst_src: LazySrcLoc,29549 inst_src: LazySrcLoc,
28847) !Air.Inst.Ref {29550) !Air.Inst.Ref {
28848 const dest_field_count = tuple_ty.structFieldCount();29551 const mod = sema.mod;
28849 const field_vals = try sema.arena.alloc(Value, dest_field_count);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);
28850 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);29562 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
28851 @memset(field_refs, .none);29563 @memset(field_refs, .none);
2885229564
28853 const inst_ty = sema.typeOf(inst);29565 const inst_ty = sema.typeOf(inst);
28854 const inst_field_count = inst_ty.structFieldCount();29566 const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
28855 if (inst_field_count > dest_field_count) return error.NotCoercible;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
28857 var runtime_src: ?LazySrcLoc = null;29576 var runtime_src: ?LazySrcLoc = null;
28858 var field_i: u32 = 0;29577 for (0..dest_field_count) |field_index_usize| {
28859 while (field_i < inst_field_count) : (field_i += 1) {29578 const field_i = @intCast(u32, field_index_usize);
28860 const field_src = inst_src; // TODO better source location29579 const field_src = inst_src; // TODO better source location
28861 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|29580 // https://github.com/ziglang/zig/issues/15709
28862 payload.data.names[field_i]29581 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {
28863 else29582 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
28864 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});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"))
28867 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});29591 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
28870 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);29604 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);
28874 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);29606 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
28875 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);29607 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
28876 field_refs[field_index] = coerced;29608 field_refs[field_index] = coerced;
28877 if (default_val.tag() != .unreachable_value) {29609 if (default_val != .none) {
28878 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {29610 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
28879 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");29611 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
28880 };29612 };
2888129613
28882 if (!init_val.eql(default_val, field_ty, sema.mod)) {29614 if (!init_val.eql(default_val.toValue(), field_ty, sema.mod)) {
28883 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);29615 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
28884 }29616 }
28885 }29617 }
28886 if (runtime_src == null) {29618 if (runtime_src == null) {
28887 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {29619 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {
28888 field_vals[field_index] = field_val;29620 field_vals[field_index] = field_val.toIntern();
28889 } else {29621 } else {
28890 runtime_src = field_src;29622 runtime_src = field_src;
28891 }29623 }
...@@ -28899,12 +29631,15 @@ fn coerceTupleToTuple(...@@ -28899,12 +29631,15 @@ fn coerceTupleToTuple(
28899 for (field_refs, 0..) |*field_ref, i| {29631 for (field_refs, 0..) |*field_ref, i| {
28900 if (field_ref.* != .none) continue;29632 if (field_ref.* != .none) continue;
2890129633
28902 const default_val = tuple_ty.structFieldDefaultValue(i);29634 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
28903 const field_ty = tuple_ty.structFieldType(i);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
28905 const field_src = inst_src; // TODO better source location29640 const field_src = inst_src; // TODO better source location
28906 if (default_val.tag() == .unreachable_value) {29641 if (default_val == .none) {
28907 if (tuple_ty.isTuple()) {29642 if (tuple_ty.isTuple(mod)) {
28908 const template = "missing tuple field: {d}";29643 const template = "missing tuple field: {d}";
28909 if (root_msg) |msg| {29644 if (root_msg) |msg| {
28910 try sema.errNote(block, field_src, msg, template, .{i});29645 try sema.errNote(block, field_src, msg, template, .{i});
...@@ -28913,8 +29648,8 @@ fn coerceTupleToTuple(...@@ -28913,8 +29648,8 @@ fn coerceTupleToTuple(
28913 }29648 }
28914 continue;29649 continue;
28915 }29650 }
28916 const template = "missing struct field: {s}";29651 const template = "missing struct field: {}";
28917 const args = .{tuple_ty.structFieldName(i)};29652 const args = .{tuple_ty.structFieldName(i, mod).fmt(ip)};
28918 if (root_msg) |msg| {29653 if (root_msg) |msg| {
28919 try sema.errNote(block, field_src, msg, template, args);29654 try sema.errNote(block, field_src, msg, template, args);
28920 } else {29655 } else {
...@@ -28925,7 +29660,12 @@ fn coerceTupleToTuple(...@@ -28925,7 +29660,12 @@ fn coerceTupleToTuple(
28925 if (runtime_src == null) {29660 if (runtime_src == null) {
28926 field_vals[i] = default_val;29661 field_vals[i] = default_val;
28927 } else {29662 } 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());
28929 }29669 }
28930 }29670 }
2893129671
...@@ -28942,7 +29682,10 @@ fn coerceTupleToTuple(...@@ -28942,7 +29682,10 @@ fn coerceTupleToTuple(
2894229682
28943 return sema.addConstant(29683 return sema.addConstant(
28944 tuple_ty,29684 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(),
28946 );29689 );
28947}29690}
2894829691
...@@ -28959,7 +29702,7 @@ fn analyzeDeclVal(...@@ -28959,7 +29702,7 @@ fn analyzeDeclVal(
28959 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);29702 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);
28960 const result = try sema.analyzeLoad(block, src, decl_ref, src);29703 const result = try sema.analyzeLoad(block, src, decl_ref, src);
28961 if (Air.refToIndex(result)) |index| {29704 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) {
28963 try sema.decl_val_table.put(sema.gpa, decl_index, result);29706 try sema.decl_val_table.put(sema.gpa, decl_index, result);
28964 }29707 }
28965 }29708 }
...@@ -28980,13 +29723,14 @@ fn addReferencedBy(...@@ -28980,13 +29723,14 @@ fn addReferencedBy(
28980}29723}
2898129724
28982fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {29725fn 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);
28984 if (decl.analysis == .in_progress) {29728 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", .{});
28986 return sema.failWithOwnedErrorMsg(msg);29730 return sema.failWithOwnedErrorMsg(msg);
28987 }29731 }
2898829732
28989 sema.mod.ensureDeclAnalyzed(decl_index) catch |err| {29733 mod.ensureDeclAnalyzed(decl_index) catch |err| {
28990 if (sema.owner_func) |owner_func| {29734 if (sema.owner_func) |owner_func| {
28991 owner_func.state = .dependency_failure;29735 owner_func.state = .dependency_failure;
28992 } else {29736 } else {
...@@ -28996,7 +29740,7 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {...@@ -28996,7 +29740,7 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
28996 };29740 };
28997}29741}
2899829742
28999fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {29743fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {
29000 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {29744 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
29001 if (sema.owner_func) |owner_func| {29745 if (sema.owner_func) |owner_func| {
29002 owner_func.state = .dependency_failure;29746 owner_func.state = .dependency_failure;
...@@ -29008,23 +29752,33 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {...@@ -29008,23 +29752,33 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
29008}29752}
2900929753
29010fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {29754fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
29755 const mod = sema.mod;
29011 var anon_decl = try block.startAnonDecl();29756 var anon_decl = try block.startAnonDecl();
29012 defer anon_decl.deinit();29757 defer anon_decl.deinit();
29013 const decl = try anon_decl.finish(29758 const decl = try anon_decl.finish(
29014 try ty.copy(anon_decl.arena()),29759 ty,
29015 try val.copy(anon_decl.arena()),29760 val,
29016 0, // default alignment29761 0, // default alignment
29017 );29762 );
29018 try sema.maybeQueueFuncBodyAnalysis(decl);29763 try sema.maybeQueueFuncBodyAnalysis(decl);
29019 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl);29764 try mod.declareDeclDependency(sema.owner_decl_index, decl);
29020 return try Value.Tag.decl_ref.create(sema.arena, decl);29765 const result = try mod.intern(.{ .ptr = .{
29766 .ty = (try mod.singleConstPtrType(ty)).toIntern(),
29767 .addr = .{ .decl = decl },
29768 } });
29769 return result.toValue();
29021}29770}
2902229771
29023fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {29772fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {
29024 const val = opt_val orelse return Value.null;29773 const mod = sema.mod;
29025 const ptr_val = try sema.refValue(block, ty, val);29774 const ptr_anyopaque_ty = try mod.singleConstPtrType(Type.anyopaque);
29026 const result = try Value.Tag.opt_payload.create(sema.arena, ptr_val);29775 return (try mod.intern(.{ .opt = .{
29027 return result;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();
29028}29782}
2902929783
29030fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref {29784fn 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...@@ -29036,42 +29790,37 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref
29036/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps29790/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps
29037/// this function with `analyze_fn_body` set to true.29791/// this function with `analyze_fn_body` set to true.
29038fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: bool) CompileError!Air.Inst.Ref {29792fn 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);
29040 try sema.ensureDeclAnalyzed(decl_index);29795 try sema.ensureDeclAnalyzed(decl_index);
2904129796
29042 const decl = sema.mod.declPtr(decl_index);29797 const decl = mod.declPtr(decl_index);
29043 const decl_tv = try decl.typedValue();29798 const decl_tv = try decl.typedValue();
29044 if (decl_tv.val.castTag(.variable)) |payload| {29799 const ptr_ty = try mod.ptrType(.{
29045 const variable = payload.data;29800 .child = decl_tv.ty.toIntern(),
29046 const ty = try Type.ptr(sema.arena, sema.mod, .{29801 .flags = .{
29047 .pointee_type = decl_tv.ty,29802 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29048 .mutable = variable.is_mutable,29803 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
29049 .@"addrspace" = decl.@"addrspace",29804 .address_space = decl.@"addrspace",
29050 .@"align" = decl.@"align",29805 },
29051 });29806 });
29052 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl_index));
29053 }
29054 if (analyze_fn_body) {29807 if (analyze_fn_body) {
29055 try sema.maybeQueueFuncBodyAnalysis(decl_index);29808 try sema.maybeQueueFuncBodyAnalysis(decl_index);
29056 }29809 }
29057 return sema.addConstant(29810 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
29058 try Type.ptr(sema.arena, sema.mod, .{29811 .ty = ptr_ty.toIntern(),
29059 .pointee_type = decl_tv.ty,29812 .addr = .{ .decl = decl_index },
29060 .mutable = false,29813 } })).toValue());
29061 .@"addrspace" = decl.@"addrspace",
29062 .@"align" = decl.@"align",
29063 }),
29064 try Value.Tag.decl_ref.create(sema.arena, decl_index),
29065 );
29066}29814}
2906729815
29068fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {29816fn 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);
29070 const tv = try decl.typedValue();29819 const tv = try decl.typedValue();
29071 if (tv.ty.zigTypeTag() != .Fn) return;29820 if (tv.ty.zigTypeTag(mod) != .Fn) return;
29072 if (!try sema.fnHasRuntimeBits(tv.ty)) return;29821 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
29073 const func = tv.val.castTag(.function) orelse return; // undef or extern_fn29822 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn
29074 try sema.mod.ensureFuncBodyAnalysisQueued(func.data);29823 try mod.ensureFuncBodyAnalysisQueued(func_index);
29075}29824}
2907629825
29077fn analyzeRef(29826fn analyzeRef(
...@@ -29083,18 +29832,16 @@ fn analyzeRef(...@@ -29083,18 +29832,16 @@ fn analyzeRef(
29083 const operand_ty = sema.typeOf(operand);29832 const operand_ty = sema.typeOf(operand);
2908429833
29085 if (try sema.resolveMaybeUndefVal(operand)) |val| {29834 if (try sema.resolveMaybeUndefVal(operand)) |val| {
29086 switch (val.tag()) {29835 switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
29087 .extern_fn, .function => {29836 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
29088 const decl_index = val.pointerDecl().?;29837 .func => |func| return sema.analyzeDeclRef(sema.mod.funcPtr(func.index).owner_decl),
29089 return sema.analyzeDeclRef(decl_index);
29090 },
29091 else => {},29838 else => {},
29092 }29839 }
29093 var anon_decl = try block.startAnonDecl();29840 var anon_decl = try block.startAnonDecl();
29094 defer anon_decl.deinit();29841 defer anon_decl.deinit();
29095 return sema.analyzeDeclRef(try anon_decl.finish(29842 return sema.analyzeDeclRef(try anon_decl.finish(
29096 try operand_ty.copy(anon_decl.arena()),29843 operand_ty,
29097 try val.copy(anon_decl.arena()),29844 val,
29098 0, // default alignment29845 0, // default alignment
29099 ));29846 ));
29100 }29847 }
...@@ -29124,9 +29871,10 @@ fn analyzeLoad(...@@ -29124,9 +29871,10 @@ fn analyzeLoad(
29124 ptr: Air.Inst.Ref,29871 ptr: Air.Inst.Ref,
29125 ptr_src: LazySrcLoc,29872 ptr_src: LazySrcLoc,
29126) CompileError!Air.Inst.Ref {29873) CompileError!Air.Inst.Ref {
29874 const mod = sema.mod;
29127 const ptr_ty = sema.typeOf(ptr);29875 const ptr_ty = sema.typeOf(ptr);
29128 const elem_ty = switch (ptr_ty.zigTypeTag()) {29876 const elem_ty = switch (ptr_ty.zigTypeTag(mod)) {
29129 .Pointer => ptr_ty.childType(),29877 .Pointer => ptr_ty.childType(mod),
29130 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}),29878 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}),
29131 };29879 };
2913229880
...@@ -29136,11 +29884,11 @@ fn analyzeLoad(...@@ -29136,11 +29884,11 @@ fn analyzeLoad(
2913629884
29137 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {29885 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
29138 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {29886 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));
29140 }29888 }
29141 }29889 }
2914229890
29143 if (ptr_ty.ptrInfo().data.vector_index == .runtime) {29891 if (ptr_ty.ptrInfo(mod).vector_index == .runtime) {
29144 const ptr_inst = Air.refToIndex(ptr).?;29892 const ptr_inst = Air.refToIndex(ptr).?;
29145 const air_tags = sema.air_instructions.items(.tag);29893 const air_tags = sema.air_instructions.items(.tag);
29146 if (air_tags[ptr_inst] == .ptr_elem_ptr) {29894 if (air_tags[ptr_inst] == .ptr_elem_ptr) {
...@@ -29163,11 +29911,11 @@ fn analyzeSlicePtr(...@@ -29163,11 +29911,11 @@ fn analyzeSlicePtr(
29163 slice: Air.Inst.Ref,29911 slice: Air.Inst.Ref,
29164 slice_ty: Type,29912 slice_ty: Type,
29165) CompileError!Air.Inst.Ref {29913) CompileError!Air.Inst.Ref {
29166 const buf = try sema.arena.create(Type.SlicePtrFieldTypeBuffer);29914 const mod = sema.mod;
29167 const result_ty = slice_ty.slicePtrFieldType(buf);29915 const result_ty = slice_ty.slicePtrFieldType(mod);
29168 if (try sema.resolveMaybeUndefVal(slice)) |val| {29916 if (try sema.resolveMaybeUndefVal(slice)) |val| {
29169 if (val.isUndef()) return sema.addConstUndef(result_ty);29917 if (val.isUndef(mod)) return sema.addConstUndef(result_ty);
29170 return sema.addConstant(result_ty, val.slicePtr());29918 return sema.addConstant(result_ty, val.slicePtr(mod));
29171 }29919 }
29172 try sema.requireRuntimeBlock(block, slice_src, null);29920 try sema.requireRuntimeBlock(block, slice_src, null);
29173 return block.addTyOp(.slice_ptr, result_ty, slice);29921 return block.addTyOp(.slice_ptr, result_ty, slice);
...@@ -29179,8 +29927,9 @@ fn analyzeSliceLen(...@@ -29179,8 +29927,9 @@ fn analyzeSliceLen(
29179 src: LazySrcLoc,29927 src: LazySrcLoc,
29180 slice_inst: Air.Inst.Ref,29928 slice_inst: Air.Inst.Ref,
29181) CompileError!Air.Inst.Ref {29929) CompileError!Air.Inst.Ref {
29930 const mod = sema.mod;
29182 if (try sema.resolveMaybeUndefVal(slice_inst)) |slice_val| {29931 if (try sema.resolveMaybeUndefVal(slice_inst)) |slice_val| {
29183 if (slice_val.isUndef()) {29932 if (slice_val.isUndef(mod)) {
29184 return sema.addConstUndef(Type.usize);29933 return sema.addConstUndef(Type.usize);
29185 }29934 }
29186 return sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod));29935 return sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod));
...@@ -29196,12 +29945,13 @@ fn analyzeIsNull(...@@ -29196,12 +29945,13 @@ fn analyzeIsNull(
29196 operand: Air.Inst.Ref,29945 operand: Air.Inst.Ref,
29197 invert_logic: bool,29946 invert_logic: bool,
29198) CompileError!Air.Inst.Ref {29947) CompileError!Air.Inst.Ref {
29948 const mod = sema.mod;
29199 const result_ty = Type.bool;29949 const result_ty = Type.bool;
29200 if (try sema.resolveMaybeUndefVal(operand)) |opt_val| {29950 if (try sema.resolveMaybeUndefVal(operand)) |opt_val| {
29201 if (opt_val.isUndef()) {29951 if (opt_val.isUndef(mod)) {
29202 return sema.addConstUndef(result_ty);29952 return sema.addConstUndef(result_ty);
29203 }29953 }
29204 const is_null = opt_val.isNull();29954 const is_null = opt_val.isNull(mod);
29205 const bool_value = if (invert_logic) !is_null else is_null;29955 const bool_value = if (invert_logic) !is_null else is_null;
29206 if (bool_value) {29956 if (bool_value) {
29207 return Air.Inst.Ref.bool_true;29957 return Air.Inst.Ref.bool_true;
...@@ -29212,11 +29962,10 @@ fn analyzeIsNull(...@@ -29212,11 +29962,10 @@ fn analyzeIsNull(
2921229962
29213 const inverted_non_null_res = if (invert_logic) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;29963 const inverted_non_null_res = if (invert_logic) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
29214 const operand_ty = sema.typeOf(operand);29964 const operand_ty = sema.typeOf(operand);
29215 var buf: Type.Payload.ElemType = undefined;29965 if (operand_ty.zigTypeTag(mod) == .Optional and operand_ty.optionalChild(mod).zigTypeTag(mod) == .NoReturn) {
29216 if (operand_ty.zigTypeTag() == .Optional and operand_ty.optionalChild(&buf).zigTypeTag() == .NoReturn) {
29217 return inverted_non_null_res;29966 return inverted_non_null_res;
29218 }29967 }
29219 if (operand_ty.zigTypeTag() != .Optional and !operand_ty.isPtrLikeOptional()) {29968 if (operand_ty.zigTypeTag(mod) != .Optional and !operand_ty.isPtrLikeOptional(mod)) {
29220 return inverted_non_null_res;29969 return inverted_non_null_res;
29221 }29970 }
29222 try sema.requireRuntimeBlock(block, src, null);29971 try sema.requireRuntimeBlock(block, src, null);
...@@ -29230,11 +29979,12 @@ fn analyzePtrIsNonErrComptimeOnly(...@@ -29230,11 +29979,12 @@ fn analyzePtrIsNonErrComptimeOnly(
29230 src: LazySrcLoc,29979 src: LazySrcLoc,
29231 operand: Air.Inst.Ref,29980 operand: Air.Inst.Ref,
29232) CompileError!Air.Inst.Ref {29981) CompileError!Air.Inst.Ref {
29982 const mod = sema.mod;
29233 const ptr_ty = sema.typeOf(operand);29983 const ptr_ty = sema.typeOf(operand);
29234 assert(ptr_ty.zigTypeTag() == .Pointer);29984 assert(ptr_ty.zigTypeTag(mod) == .Pointer);
29235 const child_ty = ptr_ty.childType();29985 const child_ty = ptr_ty.childType(mod);
2923629986
29237 const child_tag = child_ty.zigTypeTag();29987 const child_tag = child_ty.zigTypeTag(mod);
29238 if (child_tag != .ErrorSet and child_tag != .ErrorUnion) return Air.Inst.Ref.bool_true;29988 if (child_tag != .ErrorSet and child_tag != .ErrorUnion) return Air.Inst.Ref.bool_true;
29239 if (child_tag == .ErrorSet) return Air.Inst.Ref.bool_false;29989 if (child_tag == .ErrorSet) return Air.Inst.Ref.bool_false;
29240 assert(child_tag == .ErrorUnion);29990 assert(child_tag == .ErrorUnion);
...@@ -29251,14 +30001,15 @@ fn analyzeIsNonErrComptimeOnly(...@@ -29251,14 +30001,15 @@ fn analyzeIsNonErrComptimeOnly(
29251 src: LazySrcLoc,30001 src: LazySrcLoc,
29252 operand: Air.Inst.Ref,30002 operand: Air.Inst.Ref,
29253) CompileError!Air.Inst.Ref {30003) CompileError!Air.Inst.Ref {
30004 const mod = sema.mod;
29254 const operand_ty = sema.typeOf(operand);30005 const operand_ty = sema.typeOf(operand);
29255 const ot = operand_ty.zigTypeTag();30006 const ot = operand_ty.zigTypeTag(mod);
29256 if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true;30007 if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true;
29257 if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;30008 if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;
29258 assert(ot == .ErrorUnion);30009 assert(ot == .ErrorUnion);
2925930010
29260 const payload_ty = operand_ty.errorUnionPayload();30011 const payload_ty = operand_ty.errorUnionPayload(mod);
29261 if (payload_ty.zigTypeTag() == .NoReturn) {30012 if (payload_ty.zigTypeTag(mod) == .NoReturn) {
29262 return Air.Inst.Ref.bool_false;30013 return Air.Inst.Ref.bool_false;
29263 }30014 }
2926430015
...@@ -29279,50 +30030,56 @@ fn analyzeIsNonErrComptimeOnly(...@@ -29279,50 +30030,56 @@ fn analyzeIsNonErrComptimeOnly(
2927930030
29280 // exception if the error union error set is known to be empty,30031 // exception if the error union error set is known to be empty,
29281 // we allow the comparison but always make it comptime-known.30032 // we allow the comparison but always make it comptime-known.
29282 const set_ty = operand_ty.errorUnionSet();30033 const set_ty = operand_ty.errorUnionSet(mod);
29283 switch (set_ty.tag()) {30034 switch (set_ty.toIntern()) {
29284 .anyerror => {},30035 .anyerror_type => {},
29285 .error_set_inferred => blk: {30036 else => switch (mod.intern_pool.indexToKey(set_ty.toIntern())) {
29286 // If the error set is empty, we must return a comptime true or false.30037 .error_set_type => |error_set_type| {
29287 // However we want to avoid unnecessarily resolving an inferred error set30038 if (error_set_type.names.len == 0) return Air.Inst.Ref.bool_true;
29288 // in case it is already non-empty.30039 },
29289 const ies = set_ty.castTag(.error_set_inferred).?.data;30040 .inferred_error_set_type => |ies_index| blk: {
29290 if (ies.is_anyerror) break :blk;30041 // If the error set is empty, we must return a comptime true or false.
29291 if (ies.errors.count() != 0) break :blk;30042 // However we want to avoid unnecessarily resolving an inferred error set
29292 if (maybe_operand_val == null) {30043 // in case it is already non-empty.
29293 // Try to avoid resolving inferred error set if possible.30044 const ies = mod.inferredErrorSetPtr(ies_index);
29294 if (ies.errors.count() != 0) break :blk;
29295 if (ies.is_anyerror) break :blk;30045 if (ies.is_anyerror) break :blk;
29296 for (ies.inferred_error_sets.keys()) |other_ies| {30046 if (ies.errors.count() != 0) break :blk;
29297 if (ies == other_ies) continue;30047 if (maybe_operand_val == null) {
29298 try sema.resolveInferredErrorSet(block, src, other_ies);30048 // Try to avoid resolving inferred error set if possible.
29299 if (other_ies.is_anyerror) {30049 if (ies.errors.count() != 0) break :blk;
29300 ies.is_anyerror = true;30050 if (ies.is_anyerror) break :blk;
29301 ies.is_resolved = true;30051 for (ies.inferred_error_sets.keys()) |other_ies_index| {
29302 break :blk;30052 if (ies_index == other_ies_index) continue;
29303 }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;30061 if (other_ies.errors.count() != 0) break :blk;
29306 }30062 }
29307 if (ies.func == sema.owner_func) {30063 if (ies.func == sema.owner_func_index.unwrap()) {
29308 // We're checking the inferred errorset of the current function and none of30064 // 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 value30065 // its child inferred error sets contained any errors meaning that any value
29310 // so far with this type can't contain errors either.30066 // so far with this type can't contain errors either.
29311 return Air.Inst.Ref.bool_true;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;
29312 }30072 }
29313 try sema.resolveInferredErrorSet(block, src, ies);30073 },
29314 if (ies.is_anyerror) break :blk;30074 else => unreachable,
29315 if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true;
29316 }
29317 },30075 },
29318 else => if (set_ty.errorSetNames().len == 0) return Air.Inst.Ref.bool_true,
29319 }30076 }
2932030077
29321 if (maybe_operand_val) |err_union| {30078 if (maybe_operand_val) |err_union| {
29322 if (err_union.isUndef()) {30079 if (err_union.isUndef(mod)) {
29323 return sema.addConstUndef(Type.bool);30080 return sema.addConstUndef(Type.bool);
29324 }30081 }
29325 if (err_union.getError() == null) {30082 if (err_union.getErrorName(mod) == .none) {
29326 return Air.Inst.Ref.bool_true;30083 return Air.Inst.Ref.bool_true;
29327 } else {30084 } else {
29328 return Air.Inst.Ref.bool_false;30085 return Air.Inst.Ref.bool_false;
...@@ -29375,72 +30132,78 @@ fn analyzeSlice(...@@ -29375,72 +30132,78 @@ fn analyzeSlice(
29375 end_src: LazySrcLoc,30132 end_src: LazySrcLoc,
29376 by_length: bool,30133 by_length: bool,
29377) CompileError!Air.Inst.Ref {30134) CompileError!Air.Inst.Ref {
30135 const mod = sema.mod;
29378 // Slice expressions can operate on a variable whose type is an array. This requires30136 // Slice expressions can operate on a variable whose type is an array. This requires
29379 // the slice operand to be a pointer. In the case of a non-array, it will be a double pointer.30137 // the slice operand to be a pointer. In the case of a non-array, it will be a double pointer.
29380 const ptr_ptr_ty = sema.typeOf(ptr_ptr);30138 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
29381 const target = sema.mod.getTarget();30139 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(mod)) {
29382 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag()) {30140 .Pointer => ptr_ptr_ty.childType(mod),
29383 .Pointer => ptr_ptr_ty.elemType(),30141 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(mod)}),
29384 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}),
29385 };30142 };
29386 const mod = sema.mod;
2938730143
29388 var array_ty = ptr_ptr_child_ty;30144 var array_ty = ptr_ptr_child_ty;
29389 var slice_ty = ptr_ptr_ty;30145 var slice_ty = ptr_ptr_ty;
29390 var ptr_or_slice = ptr_ptr;30146 var ptr_or_slice = ptr_ptr;
29391 var elem_ty: Type = undefined;30147 var elem_ty: Type = undefined;
29392 var ptr_sentinel: ?Value = null;30148 var ptr_sentinel: ?Value = null;
29393 switch (ptr_ptr_child_ty.zigTypeTag()) {30149 switch (ptr_ptr_child_ty.zigTypeTag(mod)) {
29394 .Array => {30150 .Array => {
29395 ptr_sentinel = ptr_ptr_child_ty.sentinel();30151 ptr_sentinel = ptr_ptr_child_ty.sentinel(mod);
29396 elem_ty = ptr_ptr_child_ty.childType();30152 elem_ty = ptr_ptr_child_ty.childType(mod);
29397 },30153 },
29398 .Pointer => switch (ptr_ptr_child_ty.ptrSize()) {30154 .Pointer => switch (ptr_ptr_child_ty.ptrSize(mod)) {
29399 .One => {30155 .One => {
29400 const double_child_ty = ptr_ptr_child_ty.childType();30156 const double_child_ty = ptr_ptr_child_ty.childType(mod);
29401 if (double_child_ty.zigTypeTag() == .Array) {30157 if (double_child_ty.zigTypeTag(mod) == .Array) {
29402 ptr_sentinel = double_child_ty.sentinel();30158 ptr_sentinel = double_child_ty.sentinel(mod);
29403 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);30159 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
29404 slice_ty = ptr_ptr_child_ty;30160 slice_ty = ptr_ptr_child_ty;
29405 array_ty = double_child_ty;30161 array_ty = double_child_ty;
29406 elem_ty = double_child_ty.childType();30162 elem_ty = double_child_ty.childType(mod);
29407 } else {30163 } else {
29408 return sema.fail(block, src, "slice of single-item pointer", .{});30164 return sema.fail(block, src, "slice of single-item pointer", .{});
29409 }30165 }
29410 },30166 },
29411 .Many, .C => {30167 .Many, .C => {
29412 ptr_sentinel = ptr_ptr_child_ty.sentinel();30168 ptr_sentinel = ptr_ptr_child_ty.sentinel(mod);
29413 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);30169 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
29414 slice_ty = ptr_ptr_child_ty;30170 slice_ty = ptr_ptr_child_ty;
29415 array_ty = ptr_ptr_child_ty;30171 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) {
29419 if (try sema.resolveDefinedValue(block, ptr_src, ptr_or_slice)) |ptr_val| {30175 if (try sema.resolveDefinedValue(block, ptr_src, ptr_or_slice)) |ptr_val| {
29420 if (ptr_val.isNull()) {30176 if (ptr_val.isNull(mod)) {
29421 return sema.fail(block, src, "slice of null pointer", .{});30177 return sema.fail(block, src, "slice of null pointer", .{});
29422 }30178 }
29423 }30179 }
29424 }30180 }
29425 },30181 },
29426 .Slice => {30182 .Slice => {
29427 ptr_sentinel = ptr_ptr_child_ty.sentinel();30183 ptr_sentinel = ptr_ptr_child_ty.sentinel(mod);
29428 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);30184 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
29429 slice_ty = ptr_ptr_child_ty;30185 slice_ty = ptr_ptr_child_ty;
29430 array_ty = ptr_ptr_child_ty;30186 array_ty = ptr_ptr_child_ty;
29431 elem_ty = ptr_ptr_child_ty.childType();30187 elem_ty = ptr_ptr_child_ty.childType(mod);
29432 },30188 },
29433 },30189 },
29434 else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(mod)}),30190 else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(mod)}),
29435 }30191 }
2943630192
29437 const ptr = if (slice_ty.isSlice())30193 const ptr = if (slice_ty.isSlice(mod))
29438 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)30194 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
29439 else30195 else if (array_ty.zigTypeTag(mod) == .Array) ptr: {
29440 ptr_or_slice;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
29442 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);30204 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);
29443 const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src);30205 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
29445 // true if and only if the end index of the slice, implicitly or explicitly, equals30208 // true if and only if the end index of the slice, implicitly or explicitly, equals
29446 // the length of the underlying object being sliced. we might learn the length of the30209 // the length of the underlying object being sliced. we might learn the length of the
...@@ -29448,8 +30211,8 @@ fn analyzeSlice(...@@ -29448,8 +30211,8 @@ fn analyzeSlice(
29448 // we might learn of the length because it is a comptime-known slice value.30211 // we might learn of the length because it is a comptime-known slice value.
29449 var end_is_len = uncasted_end_opt == .none;30212 var end_is_len = uncasted_end_opt == .none;
29450 const end = e: {30213 const end = e: {
29451 if (array_ty.zigTypeTag() == .Array) {30214 if (array_ty.zigTypeTag(mod) == .Array) {
29452 const len_val = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen());30215 const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod));
2945330216
29454 if (!end_is_len) {30217 if (!end_is_len) {
29455 const end = if (by_length) end: {30218 const end = if (by_length) end: {
...@@ -29458,12 +30221,12 @@ fn analyzeSlice(...@@ -29458,12 +30221,12 @@ fn analyzeSlice(
29458 break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);30221 break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);
29459 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);30222 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
29460 if (try sema.resolveMaybeUndefVal(end)) |end_val| {30223 if (try sema.resolveMaybeUndefVal(end)) |end_val| {
29461 const len_s_val = try Value.Tag.int_u64.create(30224 const len_s_val = try mod.intValue(
29462 sema.arena,30225 Type.usize,
29463 array_ty.arrayLenIncludingSentinel(),30226 array_ty.arrayLenIncludingSentinel(mod),
29464 );30227 );
29465 if (!(try sema.compareAll(end_val, .lte, len_s_val, Type.usize))) {30228 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)
29467 " +1 (sentinel)"30230 " +1 (sentinel)"
29468 else30231 else
29469 "";30232 "";
...@@ -29491,7 +30254,7 @@ fn analyzeSlice(...@@ -29491,7 +30254,7 @@ fn analyzeSlice(
29491 }30254 }
2949230255
29493 break :e try sema.addConstant(Type.usize, len_val);30256 break :e try sema.addConstant(Type.usize, len_val);
29494 } else if (slice_ty.isSlice()) {30257 } else if (slice_ty.isSlice(mod)) {
29495 if (!end_is_len) {30258 if (!end_is_len) {
29496 const end = if (by_length) end: {30259 const end = if (by_length) end: {
29497 const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);30260 const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
...@@ -29500,16 +30263,14 @@ fn analyzeSlice(...@@ -29500,16 +30263,14 @@ fn analyzeSlice(
29500 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);30263 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
29501 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {30264 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
29502 if (try sema.resolveMaybeUndefVal(ptr_or_slice)) |slice_val| {30265 if (try sema.resolveMaybeUndefVal(ptr_or_slice)) |slice_val| {
29503 if (slice_val.isUndef()) {30266 if (slice_val.isUndef(mod)) {
29504 return sema.fail(block, src, "slice of undefined", .{});30267 return sema.fail(block, src, "slice of undefined", .{});
29505 }30268 }
29506 const has_sentinel = slice_ty.sentinel() != null;30269 const has_sentinel = slice_ty.sentinel(mod) != null;
29507 var int_payload: Value.Payload.U64 = .{30270 const slice_len = slice_val.sliceLen(mod);
29508 .base = .{ .tag = .int_u64 },30271 const len_plus_sent = slice_len + @boolToInt(has_sentinel);
29509 .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel),30272 const slice_len_val_with_sentinel = try mod.intValue(Type.usize, len_plus_sent);
29510 };30273 if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) {
29511 const slice_len_val = Value.initPayload(&int_payload.base);
29512 if (!(try sema.compareAll(end_val, .lte, slice_len_val, Type.usize))) {
29513 const sentinel_label: []const u8 = if (has_sentinel)30274 const sentinel_label: []const u8 = if (has_sentinel)
29514 " +1 (sentinel)"30275 " +1 (sentinel)"
29515 else30276 else
...@@ -29527,13 +30288,10 @@ fn analyzeSlice(...@@ -29527,13 +30288,10 @@ fn analyzeSlice(
29527 );30288 );
29528 }30289 }
2952930290
29530 // If the slice has a sentinel, we subtract one so that30291 // If the slice has a sentinel, we consider end_is_len
29531 // end_is_len is only true if it equals the length WITHOUT30292 // is only true if it equals the length WITHOUT the
29532 // the sentinel, so we don't add a sentinel type.30293 // sentinel, so we don't add a sentinel type.
29533 if (has_sentinel) {30294 const slice_len_val = try mod.intValue(Type.usize, slice_len);
29534 int_payload.data -= 1;
29535 }
29536
29537 if (end_val.eql(slice_len_val, Type.usize, mod)) {30295 if (end_val.eql(slice_len_val, Type.usize, mod)) {
29538 end_is_len = true;30296 end_is_len = true;
29539 }30297 }
...@@ -29569,11 +30327,12 @@ fn analyzeSlice(...@@ -29569,11 +30327,12 @@ fn analyzeSlice(
29569 };30327 };
29570 const slice_sentinel = if (sentinel_opt != .none) sentinel else null;30328 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
29572 // requirement: start <= end30333 // requirement: start <= end
29573 var need_start_gt_end_check = true;
29574 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {30334 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
29575 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {30335 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {
29576 need_start_gt_end_check = false;
29577 if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, Type.usize))) {30336 if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, Type.usize))) {
29578 return sema.fail(30337 return sema.fail(
29579 block,30338 block,
...@@ -29585,14 +30344,18 @@ fn analyzeSlice(...@@ -29585,14 +30344,18 @@ fn analyzeSlice(
29585 },30344 },
29586 );30345 );
29587 }30346 }
30347 checked_start_lte_end = true;
29588 if (try sema.resolveMaybeUndefVal(new_ptr)) |ptr_val| sentinel_check: {30348 if (try sema.resolveMaybeUndefVal(new_ptr)) |ptr_val| sentinel_check: {
29589 const expected_sentinel = sentinel orelse break :sentinel_check;30349 const expected_sentinel = sentinel orelse break :sentinel_check;
29590 const start_int = start_val.getUnsignedInt(sema.mod.getTarget()).?;30350 const start_int = start_val.getUnsignedInt(mod).?;
29591 const end_int = end_val.getUnsignedInt(sema.mod.getTarget()).?;30351 const end_int = end_val.getUnsignedInt(mod).?;
29592 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);30352 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);30354 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
29595 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false);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);
29596 const actual_sentinel = switch (res) {30359 const actual_sentinel = switch (res) {
29597 .runtime_load => break :sentinel_check,30360 .runtime_load => break :sentinel_check,
29598 .val => |v| v,30361 .val => |v| v,
...@@ -29600,36 +30363,49 @@ fn analyzeSlice(...@@ -29600,36 +30363,49 @@ fn analyzeSlice(
29600 block,30363 block,
29601 src,30364 src,
29602 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",30365 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",
29603 .{ty.fmt(sema.mod)},30366 .{ty.fmt(mod)},
29604 ),30367 ),
29605 .out_of_bounds => |ty| return sema.fail(30368 .out_of_bounds => |ty| return sema.fail(
29606 block,30369 block,
29607 end_src,30370 end_src,
29608 "slice end index {d} exceeds bounds of containing decl of type '{}'",30371 "slice end index {d} exceeds bounds of containing decl of type '{}'",
29609 .{ end_int, ty.fmt(sema.mod) },30372 .{ end_int, ty.fmt(mod) },
29610 ),30373 ),
29611 };30374 };
2961230375
29613 if (!actual_sentinel.eql(expected_sentinel, elem_ty, sema.mod)) {30376 if (!actual_sentinel.eql(expected_sentinel, elem_ty, mod)) {
29614 const msg = msg: {30377 const msg = msg: {
29615 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});30378 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});
29616 errdefer msg.destroy(sema.gpa);30379 errdefer msg.destroy(sema.gpa);
29617 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{30380 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{
29618 expected_sentinel.fmtValue(elem_ty, sema.mod),30381 expected_sentinel.fmtValue(elem_ty, mod),
29619 actual_sentinel.fmtValue(elem_ty, sema.mod),30382 actual_sentinel.fmtValue(elem_ty, mod),
29620 });30383 });
2962130384
29622 break :msg msg;30385 break :msg msg;
29623 };30386 };
29624 return sema.failWithOwnedErrorMsg(msg);30387 return sema.failWithOwnedErrorMsg(msg);
29625 }30388 }
30389 } else {
30390 runtime_src = ptr_src;
29626 }30391 }
30392 } else {
30393 runtime_src = start_src;
29627 }30394 }
30395 } else {
30396 runtime_src = end_src;
29628 }30397 }
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) {
29631 // requirement: start <= end30400 // 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 }
29633 }30409 }
29634 const new_len = if (by_length)30410 const new_len = if (by_length)
29635 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)30411 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
...@@ -29637,11 +30413,11 @@ fn analyzeSlice(...@@ -29637,11 +30413,11 @@ fn analyzeSlice(
29637 try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false);30413 try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false);
29638 const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len);30414 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;30416 const new_ptr_ty_info = new_ptr_ty.ptrInfo(mod);
29641 const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize() != .C;30417 const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize(mod) != .C;
2964230418
29643 if (opt_new_len_val) |new_len_val| {30419 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
29646 const return_ty = try Type.ptr(sema.arena, mod, .{30422 const return_ty = try Type.ptr(sema.arena, mod, .{
29647 .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty, mod),30423 .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty, mod),
...@@ -29659,14 +30435,14 @@ fn analyzeSlice(...@@ -29659,14 +30435,14 @@ fn analyzeSlice(
29659 const result = try block.addBitCast(return_ty, new_ptr);30435 const result = try block.addBitCast(return_ty, new_ptr);
29660 if (block.wantSafety()) {30436 if (block.wantSafety()) {
29661 // requirement: slicing C ptr is non-null30437 // requirement: slicing C ptr is non-null
29662 if (ptr_ptr_child_ty.isCPtr()) {30438 if (ptr_ptr_child_ty.isCPtr(mod)) {
29663 const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);30439 const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);
29664 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);30440 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
29665 }30441 }
2966630442
29667 if (slice_ty.isSlice()) {30443 if (slice_ty.isSlice(mod)) {
29668 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);30444 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)
29670 slice_len_inst30446 slice_len_inst
29671 else30447 else
29672 try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);30448 try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
...@@ -29685,8 +30461,11 @@ fn analyzeSlice(...@@ -29685,8 +30461,11 @@ fn analyzeSlice(
29685 return result;30461 return result;
29686 };30462 };
2968730463
29688 if (!new_ptr_val.isUndef()) {30464 if (!new_ptr_val.isUndef(mod)) {
29689 return sema.addConstant(return_ty, new_ptr_val);30465 return sema.addConstant(return_ty, try mod.getCoerced(
30466 (try new_ptr_val.intern(new_ptr_ty, mod)).toValue(),
30467 return_ty,
30468 ));
29690 }30469 }
2969130470
29692 // Special case: @as([]i32, undefined)[x..x]30471 // Special case: @as([]i32, undefined)[x..x]
...@@ -29708,25 +30487,18 @@ fn analyzeSlice(...@@ -29708,25 +30487,18 @@ fn analyzeSlice(
29708 .size = .Slice,30487 .size = .Slice,
29709 });30488 });
2971030489
29711 const runtime_src = if ((try sema.resolveMaybeUndefVal(ptr_or_slice)) == null)30490 try sema.requireRuntimeBlock(block, src, runtime_src.?);
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);
29719 if (block.wantSafety()) {30491 if (block.wantSafety()) {
29720 // requirement: slicing C ptr is non-null30492 // requirement: slicing C ptr is non-null
29721 if (ptr_ptr_child_ty.isCPtr()) {30493 if (ptr_ptr_child_ty.isCPtr(mod)) {
29722 const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);30494 const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);
29723 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);30495 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
29724 }30496 }
2972530497
29726 // requirement: end <= len30498 // requirement: end <= len
29727 const opt_len_inst = if (array_ty.zigTypeTag() == .Array)30499 const opt_len_inst = if (array_ty.zigTypeTag(mod) == .Array)
29728 try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel())30500 try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel(mod))
29729 else if (slice_ty.isSlice()) blk: {30501 else if (slice_ty.isSlice(mod)) blk: {
29730 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {30502 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {
29731 // we don't need to add one for sentinels because the30503 // we don't need to add one for sentinels because the
29732 // underlying value data includes the sentinel30504 // underlying value data includes the sentinel
...@@ -29734,7 +30506,7 @@ fn analyzeSlice(...@@ -29734,7 +30506,7 @@ fn analyzeSlice(
29734 }30506 }
2973530507
29736 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);30508 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
29739 // we have to add one because slice lengths don't include the sentinel30511 // we have to add one because slice lengths don't include the sentinel
29740 break :blk try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);30512 break :blk try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
...@@ -29778,15 +30550,16 @@ fn cmpNumeric(...@@ -29778,15 +30550,16 @@ fn cmpNumeric(
29778 lhs_src: LazySrcLoc,30550 lhs_src: LazySrcLoc,
29779 rhs_src: LazySrcLoc,30551 rhs_src: LazySrcLoc,
29780) CompileError!Air.Inst.Ref {30552) CompileError!Air.Inst.Ref {
30553 const mod = sema.mod;
29781 const lhs_ty = sema.typeOf(uncasted_lhs);30554 const lhs_ty = sema.typeOf(uncasted_lhs);
29782 const rhs_ty = sema.typeOf(uncasted_rhs);30555 const rhs_ty = sema.typeOf(uncasted_rhs);
2978330556
29784 assert(lhs_ty.isNumeric());30557 assert(lhs_ty.isNumeric(mod));
29785 assert(rhs_ty.isNumeric());30558 assert(rhs_ty.isNumeric(mod));
2978630559
29787 const lhs_ty_tag = lhs_ty.zigTypeTag();30560 const lhs_ty_tag = lhs_ty.zigTypeTag(mod);
29788 const rhs_ty_tag = rhs_ty.zigTypeTag();30561 const rhs_ty_tag = rhs_ty.zigTypeTag(mod);
29789 const target = sema.mod.getTarget();30562 const target = mod.getTarget();
2979030563
29791 // One exception to heterogeneous comparison: comptime_float needs to30564 // One exception to heterogeneous comparison: comptime_float needs to
29792 // coerce to fixed-width float.30565 // coerce to fixed-width float.
...@@ -29805,49 +30578,45 @@ fn cmpNumeric(...@@ -29805,49 +30578,45 @@ fn cmpNumeric(
29805 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {30578 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {
29806 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {30579 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
29807 // Compare ints: const vs. undefined (or vice versa)30580 // 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()) {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)) {
29809 try sema.resolveLazyValue(lhs_val);30582 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(lhs_val), op, rhs_ty)) |res| {
29810 if (sema.compareIntsOnlyPossibleResult(target, lhs_val, op, rhs_ty)) |res| {
29811 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;30583 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
29812 }30584 }
29813 } else if (!rhs_val.isUndef() and (rhs_ty.isInt() or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt() and lhs_val.isUndef()) {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)) {
29814 try sema.resolveLazyValue(rhs_val);30586 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(rhs_val), op.reverse(), lhs_ty)) |res| {
29815 if (sema.compareIntsOnlyPossibleResult(target, rhs_val, op.reverse(), lhs_ty)) |res| {
29816 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;30587 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
29817 }30588 }
29818 }30589 }
2981930590
29820 if (lhs_val.isUndef() or rhs_val.isUndef()) {30591 if (lhs_val.isUndef(mod) or rhs_val.isUndef(mod)) {
29821 return sema.addConstUndef(Type.bool);30592 return sema.addConstUndef(Type.bool);
29822 }30593 }
29823 if (lhs_val.isNan() or rhs_val.isNan()) {30594 if (lhs_val.isNan(mod) or rhs_val.isNan(mod)) {
29824 if (op == std.math.CompareOperator.neq) {30595 if (op == std.math.CompareOperator.neq) {
29825 return Air.Inst.Ref.bool_true;30596 return Air.Inst.Ref.bool_true;
29826 } else {30597 } else {
29827 return Air.Inst.Ref.bool_false;30598 return Air.Inst.Ref.bool_false;
29828 }30599 }
29829 }30600 }
29830 if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, target, sema)) {30601 if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, mod, sema)) {
29831 return Air.Inst.Ref.bool_true;30602 return Air.Inst.Ref.bool_true;
29832 } else {30603 } else {
29833 return Air.Inst.Ref.bool_false;30604 return Air.Inst.Ref.bool_false;
29834 }30605 }
29835 } else {30606 } 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)) {
29837 // Compare ints: const vs. var30608 // Compare ints: const vs. var
29838 try sema.resolveLazyValue(lhs_val);30609 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(lhs_val), op, rhs_ty)) |res| {
29839 if (sema.compareIntsOnlyPossibleResult(target, lhs_val, op, rhs_ty)) |res| {
29840 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;30610 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
29841 }30611 }
29842 }30612 }
29843 break :src rhs_src;30613 break :src rhs_src;
29844 }30614 }
29845 } else {30615 } else {
29846 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {30616 if (try sema.resolveMaybeUndefLazyVal(rhs)) |rhs_val| {
29847 if (!rhs_val.isUndef() and (rhs_ty.isInt() or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt()) {30617 if (!rhs_val.isUndef(mod) and (rhs_ty.isInt(mod) or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt(mod)) {
29848 // Compare ints: var vs. const30618 // Compare ints: var vs. const
29849 try sema.resolveLazyValue(rhs_val);30619 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(rhs_val), op.reverse(), lhs_ty)) |res| {
29850 if (sema.compareIntsOnlyPossibleResult(target, rhs_val, op.reverse(), lhs_ty)) |res| {
29851 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;30620 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
29852 }30621 }
29853 }30622 }
...@@ -29901,32 +30670,31 @@ fn cmpNumeric(...@@ -29901,32 +30670,31 @@ fn cmpNumeric(
29901 const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val|30670 const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val|
29902 !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema))30671 !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema))
29903 else30672 else
29904 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt());30673 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(mod));
29905 const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val|30674 const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val|
29906 !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema))30675 !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema))
29907 else30676 else
29908 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt());30677 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(mod));
29909 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;30678 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
2991030679
29911 var dest_float_type: ?Type = null;30680 var dest_float_type: ?Type = null;
2991230681
29913 var lhs_bits: usize = undefined;30682 var lhs_bits: usize = undefined;
29914 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {30683 if (try sema.resolveMaybeUndefLazyVal(lhs)) |lhs_val| {
29915 try sema.resolveLazyValue(lhs_val);30684 if (lhs_val.isUndef(mod))
29916 if (lhs_val.isUndef())
29917 return sema.addConstUndef(Type.bool);30685 return sema.addConstUndef(Type.bool);
29918 if (lhs_val.isNan()) switch (op) {30686 if (lhs_val.isNan(mod)) switch (op) {
29919 .neq => return Air.Inst.Ref.bool_true,30687 .neq => return Air.Inst.Ref.bool_true,
29920 else => return Air.Inst.Ref.bool_false,30688 else => return Air.Inst.Ref.bool_false,
29921 };30689 };
29922 if (lhs_val.isInf()) switch (op) {30690 if (lhs_val.isInf(mod)) switch (op) {
29923 .neq => return Air.Inst.Ref.bool_true,30691 .neq => return Air.Inst.Ref.bool_true,
29924 .eq => return Air.Inst.Ref.bool_false,30692 .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,30693 .gt, .gte => return if (lhs_val.isNegativeInf(mod)) 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,30694 .lt, .lte => return if (lhs_val.isNegativeInf(mod)) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false,
29927 };30695 };
29928 if (!rhs_is_signed) {30696 if (!rhs_is_signed) {
29929 switch (lhs_val.orderAgainstZero()) {30697 switch (lhs_val.orderAgainstZero(mod)) {
29930 .gt => {},30698 .gt => {},
29931 .eq => switch (op) { // LHS = 0, RHS is unsigned30699 .eq => switch (op) { // LHS = 0, RHS is unsigned
29932 .lte => return Air.Inst.Ref.bool_true,30700 .lte => return Air.Inst.Ref.bool_true,
...@@ -29940,7 +30708,7 @@ fn cmpNumeric(...@@ -29940,7 +30708,7 @@ fn cmpNumeric(
29940 }30708 }
29941 }30709 }
29942 if (lhs_is_float) {30710 if (lhs_is_float) {
29943 if (lhs_val.floatHasFraction()) {30711 if (lhs_val.floatHasFraction(mod)) {
29944 switch (op) {30712 switch (op) {
29945 .eq => return Air.Inst.Ref.bool_false,30713 .eq => return Air.Inst.Ref.bool_false,
29946 .neq => return Air.Inst.Ref.bool_true,30714 .neq => return Air.Inst.Ref.bool_true,
...@@ -29948,9 +30716,9 @@ fn cmpNumeric(...@@ -29948,9 +30716,9 @@ fn cmpNumeric(
29948 }30716 }
29949 }30717 }
2995030718
29951 var bigint = try float128IntPartToBigInt(sema.gpa, lhs_val.toFloat(f128));30719 var bigint = try float128IntPartToBigInt(sema.gpa, lhs_val.toFloat(f128, mod));
29952 defer bigint.deinit();30720 defer bigint.deinit();
29953 if (lhs_val.floatHasFraction()) {30721 if (lhs_val.floatHasFraction(mod)) {
29954 if (lhs_is_signed) {30722 if (lhs_is_signed) {
29955 try bigint.addScalar(&bigint, -1);30723 try bigint.addScalar(&bigint, -1);
29956 } else {30724 } else {
...@@ -29959,33 +30727,32 @@ fn cmpNumeric(...@@ -29959,33 +30727,32 @@ fn cmpNumeric(
29959 }30727 }
29960 lhs_bits = bigint.toConst().bitCountTwosComp();30728 lhs_bits = bigint.toConst().bitCountTwosComp();
29961 } else {30729 } else {
29962 lhs_bits = lhs_val.intBitCountTwosComp(target);30730 lhs_bits = lhs_val.intBitCountTwosComp(mod);
29963 }30731 }
29964 lhs_bits += @boolToInt(!lhs_is_signed and dest_int_is_signed);30732 lhs_bits += @boolToInt(!lhs_is_signed and dest_int_is_signed);
29965 } else if (lhs_is_float) {30733 } else if (lhs_is_float) {
29966 dest_float_type = lhs_ty;30734 dest_float_type = lhs_ty;
29967 } else {30735 } else {
29968 const int_info = lhs_ty.intInfo(target);30736 const int_info = lhs_ty.intInfo(mod);
29969 lhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);30737 lhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
29970 }30738 }
2997130739
29972 var rhs_bits: usize = undefined;30740 var rhs_bits: usize = undefined;
29973 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {30741 if (try sema.resolveMaybeUndefLazyVal(rhs)) |rhs_val| {
29974 try sema.resolveLazyValue(rhs_val);30742 if (rhs_val.isUndef(mod))
29975 if (rhs_val.isUndef())
29976 return sema.addConstUndef(Type.bool);30743 return sema.addConstUndef(Type.bool);
29977 if (rhs_val.isNan()) switch (op) {30744 if (rhs_val.isNan(mod)) switch (op) {
29978 .neq => return Air.Inst.Ref.bool_true,30745 .neq => return Air.Inst.Ref.bool_true,
29979 else => return Air.Inst.Ref.bool_false,30746 else => return Air.Inst.Ref.bool_false,
29980 };30747 };
29981 if (rhs_val.isInf()) switch (op) {30748 if (rhs_val.isInf(mod)) switch (op) {
29982 .neq => return Air.Inst.Ref.bool_true,30749 .neq => return Air.Inst.Ref.bool_true,
29983 .eq => return Air.Inst.Ref.bool_false,30750 .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,30751 .gt, .gte => return if (rhs_val.isNegativeInf(mod)) 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,30752 .lt, .lte => return if (rhs_val.isNegativeInf(mod)) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true,
29986 };30753 };
29987 if (!lhs_is_signed) {30754 if (!lhs_is_signed) {
29988 switch (rhs_val.orderAgainstZero()) {30755 switch (rhs_val.orderAgainstZero(mod)) {
29989 .gt => {},30756 .gt => {},
29990 .eq => switch (op) { // RHS = 0, LHS is unsigned30757 .eq => switch (op) { // RHS = 0, LHS is unsigned
29991 .gte => return Air.Inst.Ref.bool_true,30758 .gte => return Air.Inst.Ref.bool_true,
...@@ -29999,7 +30766,7 @@ fn cmpNumeric(...@@ -29999,7 +30766,7 @@ fn cmpNumeric(
29999 }30766 }
30000 }30767 }
30001 if (rhs_is_float) {30768 if (rhs_is_float) {
30002 if (rhs_val.floatHasFraction()) {30769 if (rhs_val.floatHasFraction(mod)) {
30003 switch (op) {30770 switch (op) {
30004 .eq => return Air.Inst.Ref.bool_false,30771 .eq => return Air.Inst.Ref.bool_false,
30005 .neq => return Air.Inst.Ref.bool_true,30772 .neq => return Air.Inst.Ref.bool_true,
...@@ -30007,9 +30774,9 @@ fn cmpNumeric(...@@ -30007,9 +30774,9 @@ fn cmpNumeric(
30007 }30774 }
30008 }30775 }
3000930776
30010 var bigint = try float128IntPartToBigInt(sema.gpa, rhs_val.toFloat(f128));30777 var bigint = try float128IntPartToBigInt(sema.gpa, rhs_val.toFloat(f128, mod));
30011 defer bigint.deinit();30778 defer bigint.deinit();
30012 if (rhs_val.floatHasFraction()) {30779 if (rhs_val.floatHasFraction(mod)) {
30013 if (rhs_is_signed) {30780 if (rhs_is_signed) {
30014 try bigint.addScalar(&bigint, -1);30781 try bigint.addScalar(&bigint, -1);
30015 } else {30782 } else {
...@@ -30018,13 +30785,13 @@ fn cmpNumeric(...@@ -30018,13 +30785,13 @@ fn cmpNumeric(
30018 }30785 }
30019 rhs_bits = bigint.toConst().bitCountTwosComp();30786 rhs_bits = bigint.toConst().bitCountTwosComp();
30020 } else {30787 } else {
30021 rhs_bits = rhs_val.intBitCountTwosComp(target);30788 rhs_bits = rhs_val.intBitCountTwosComp(mod);
30022 }30789 }
30023 rhs_bits += @boolToInt(!rhs_is_signed and dest_int_is_signed);30790 rhs_bits += @boolToInt(!rhs_is_signed and dest_int_is_signed);
30024 } else if (rhs_is_float) {30791 } else if (rhs_is_float) {
30025 dest_float_type = rhs_ty;30792 dest_float_type = rhs_ty;
30026 } else {30793 } else {
30027 const int_info = rhs_ty.intInfo(target);30794 const int_info = rhs_ty.intInfo(mod);
30028 rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);30795 rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
30029 }30796 }
3003030797
...@@ -30032,7 +30799,7 @@ fn cmpNumeric(...@@ -30032,7 +30799,7 @@ fn cmpNumeric(
30032 const max_bits = std.math.max(lhs_bits, rhs_bits);30799 const max_bits = std.math.max(lhs_bits, rhs_bits);
30033 const casted_bits = std.math.cast(u16, max_bits) orelse return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits});30800 const casted_bits = std.math.cast(u16, max_bits) orelse return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits});
30034 const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned;30801 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);
30036 };30803 };
30037 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);30804 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
30038 const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);30805 const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
...@@ -30040,13 +30807,20 @@ fn cmpNumeric(...@@ -30040,13 +30807,20 @@ fn cmpNumeric(
30040 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs);30807 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs);
30041}30808}
3004230809
30043/// Asserts that LHS value is an int or comptime int and not undefined, and that RHS type is an int.30810/// Asserts that LHS value is an int or comptime int and not undefined, and
30044/// Given a const LHS and an unknown RHS, attempt to determine whether `op` has a guaranteed result.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.
30045/// If it cannot be determined, returns null.30813/// If it cannot be determined, returns null.
30046/// Otherwise returns a bool for the guaranteed comparison operation.30814/// 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 {30815fn compareIntsOnlyPossibleResult(
30048 const rhs_info = rhs_ty.intInfo(target);30816 sema: *Sema,
30049 const vs_zero = lhs_val.orderAgainstZeroAdvanced(sema) catch unreachable;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;
30050 const is_zero = vs_zero == .eq;30824 const is_zero = vs_zero == .eq;
30051 const is_negative = vs_zero == .lt;30825 const is_negative = vs_zero == .lt;
30052 const is_positive = vs_zero == .gt;30826 const is_positive = vs_zero == .gt;
...@@ -30078,7 +30852,7 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value...@@ -30078,7 +30852,7 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value
30078 };30852 };
3007930853
30080 const sign_adj = @boolToInt(!is_negative and rhs_info.signedness == .signed);30854 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
30083 // No sized type can have more than 65535 bits.30857 // No sized type can have more than 65535 bits.
30084 // The RHS type operand is either a runtime value or sized (but undefined) constant.30858 // 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...@@ -30111,12 +30885,11 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value
30111 .max = false,30885 .max = false,
30112 };30886 };
3011330887
30114 var ty_buffer: Type.Payload.Bits = .{30888 const ty = try mod.intType(
30115 .base = .{ .tag = if (is_negative) .int_signed else .int_unsigned },30889 if (is_negative) .signed else .unsigned,
30116 .data = @intCast(u16, req_bits),30890 @intCast(u16, req_bits),
30117 };30891 );
30118 const ty = Type.initPayload(&ty_buffer.base);30892 const pop_count = lhs_val.popCount(ty, mod);
30119 const pop_count = lhs_val.popCount(ty, target);
3012030893
30121 if (is_negative) {30894 if (is_negative) {
30122 break :edge .{30895 break :edge .{
...@@ -30152,22 +30925,26 @@ fn cmpVector(...@@ -30152,22 +30925,26 @@ fn cmpVector(
30152 lhs_src: LazySrcLoc,30925 lhs_src: LazySrcLoc,
30153 rhs_src: LazySrcLoc,30926 rhs_src: LazySrcLoc,
30154) CompileError!Air.Inst.Ref {30927) CompileError!Air.Inst.Ref {
30928 const mod = sema.mod;
30155 const lhs_ty = sema.typeOf(lhs);30929 const lhs_ty = sema.typeOf(lhs);
30156 const rhs_ty = sema.typeOf(rhs);30930 const rhs_ty = sema.typeOf(rhs);
30157 assert(lhs_ty.zigTypeTag() == .Vector);30931 assert(lhs_ty.zigTypeTag(mod) == .Vector);
30158 assert(rhs_ty.zigTypeTag() == .Vector);30932 assert(rhs_ty.zigTypeTag(mod) == .Vector);
30159 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);30933 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
3016030934
30161 const resolved_ty = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{ .override = &.{ lhs_src, rhs_src } });30935 const resolved_ty = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{ .override = &.{ lhs_src, rhs_src } });
30162 const casted_lhs = try sema.coerce(block, resolved_ty, lhs, lhs_src);30936 const casted_lhs = try sema.coerce(block, resolved_ty, lhs, lhs_src);
30163 const casted_rhs = try sema.coerce(block, resolved_ty, rhs, rhs_src);30937 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
30167 const runtime_src: LazySrcLoc = src: {30944 const runtime_src: LazySrcLoc = src: {
30168 if (try sema.resolveMaybeUndefVal(casted_lhs)) |lhs_val| {30945 if (try sema.resolveMaybeUndefVal(casted_lhs)) |lhs_val| {
30169 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {30946 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)) {
30171 return sema.addConstUndef(result_ty);30948 return sema.addConstUndef(result_ty);
30172 }30949 }
30173 const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_ty);30950 const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_ty);
...@@ -30192,7 +30969,10 @@ fn wrapOptional(...@@ -30192,7 +30969,10 @@ fn wrapOptional(
30192 inst_src: LazySrcLoc,30969 inst_src: LazySrcLoc,
30193) !Air.Inst.Ref {30970) !Air.Inst.Ref {
30194 if (try sema.resolveMaybeUndefVal(inst)) |val| {30971 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());
30196 }30976 }
3019730977
30198 try sema.requireRuntimeBlock(block, inst_src, null);30978 try sema.requireRuntimeBlock(block, inst_src, null);
...@@ -30206,10 +30986,14 @@ fn wrapErrorUnionPayload(...@@ -30206,10 +30986,14 @@ fn wrapErrorUnionPayload(
30206 inst: Air.Inst.Ref,30986 inst: Air.Inst.Ref,
30207 inst_src: LazySrcLoc,30987 inst_src: LazySrcLoc,
30208) !Air.Inst.Ref {30988) !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);
30210 const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false });30991 const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false });
30211 if (try sema.resolveMaybeUndefVal(coerced)) |val| {30992 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());
30213 }30997 }
30214 try sema.requireRuntimeBlock(block, inst_src, null);30998 try sema.requireRuntimeBlock(block, inst_src, null);
30215 try sema.queueFullTypeResolution(dest_payload_ty);30999 try sema.queueFullTypeResolution(dest_payload_ty);
...@@ -30223,48 +31007,41 @@ fn wrapErrorUnionSet(...@@ -30223,48 +31007,41 @@ fn wrapErrorUnionSet(
30223 inst: Air.Inst.Ref,31007 inst: Air.Inst.Ref,
30224 inst_src: LazySrcLoc,31008 inst_src: LazySrcLoc,
30225) !Air.Inst.Ref {31009) !Air.Inst.Ref {
31010 const mod = sema.mod;
31011 const ip = &mod.intern_pool;
30226 const inst_ty = sema.typeOf(inst);31012 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);
30228 if (try sema.resolveMaybeUndefVal(inst)) |val| {31014 if (try sema.resolveMaybeUndefVal(inst)) |val| {
30229 switch (dest_err_set_ty.tag()) {31015 switch (dest_err_set_ty.toIntern()) {
30230 .anyerror => {},31016 .anyerror_type => {},
30231 .error_set_single => ok: {31017 else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) {
30232 const expected_name = val.castTag(.@"error").?.data.name;31018 .error_set_type => |error_set_type| ok: {
30233 const n = dest_err_set_ty.castTag(.error_set_single).?.data;31019 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
30234 if (mem.eql(u8, expected_name, n)) break :ok;31020 if (error_set_type.nameIndex(ip, expected_name) != null) 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)) {
30241 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);31021 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30242 }31022 },
30243 },31023 .inferred_error_set_type => |ies_index| ok: {
30244 .error_set_inferred => ok: {31024 const ies = mod.inferredErrorSetPtr(ies_index);
30245 const expected_name = val.castTag(.@"error").?.data.name;31025 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
30246 const ies = dest_err_set_ty.castTag(.error_set_inferred).?.data;
3024731026
30248 // We carefully do this in an order that avoids unnecessarily31027 // We carefully do this in an order that avoids unnecessarily
30249 // resolving the destination error set type.31028 // resolving the destination error set type.
30250 if (ies.is_anyerror) break :ok;31029 if (ies.is_anyerror) break :ok;
30251 if (ies.errors.contains(expected_name)) break :ok;31030
30252 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {31031 if (ies.errors.contains(expected_name)) break :ok;
30253 break :ok;31032 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok;
30254 }
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)) {
30262 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);31034 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30263 }31035 },
31036 else => unreachable,
30264 },31037 },
30265 else => unreachable,
30266 }31038 }
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());
30268 }31045 }
3026931046
30270 try sema.requireRuntimeBlock(block, inst_src, null);31047 try sema.requireRuntimeBlock(block, inst_src, null);
...@@ -30279,11 +31056,12 @@ fn unionToTag(...@@ -30279,11 +31056,12 @@ fn unionToTag(
30279 un: Air.Inst.Ref,31056 un: Air.Inst.Ref,
30280 un_src: LazySrcLoc,31057 un_src: LazySrcLoc,
30281) !Air.Inst.Ref {31058) !Air.Inst.Ref {
31059 const mod = sema.mod;
30282 if ((try sema.typeHasOnePossibleValue(enum_ty))) |opv| {31060 if ((try sema.typeHasOnePossibleValue(enum_ty))) |opv| {
30283 return sema.addConstant(enum_ty, opv);31061 return sema.addConstant(enum_ty, opv);
30284 }31062 }
30285 if (try sema.resolveMaybeUndefVal(un)) |un_val| {31063 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));
30287 }31065 }
30288 try sema.requireRuntimeBlock(block, un_src, null);31066 try sema.requireRuntimeBlock(block, un_src, null);
30289 return block.addTyOp(.get_union_tag, enum_ty, un);31067 return block.addTyOp(.get_union_tag, enum_ty, un);
...@@ -30296,16 +31074,17 @@ fn resolvePeerTypes(...@@ -30296,16 +31074,17 @@ fn resolvePeerTypes(
30296 instructions: []const Air.Inst.Ref,31074 instructions: []const Air.Inst.Ref,
30297 candidate_srcs: Module.PeerTypeCandidateSrc,31075 candidate_srcs: Module.PeerTypeCandidateSrc,
30298) !Type {31076) !Type {
31077 const mod = sema.mod;
30299 switch (instructions.len) {31078 switch (instructions.len) {
30300 0 => return Type.initTag(.noreturn),31079 0 => return Type.noreturn,
30301 1 => return sema.typeOf(instructions[0]),31080 1 => return sema.typeOf(instructions[0]),
30302 else => {},31081 else => {},
30303 }31082 }
3030431083
30305 const target = sema.mod.getTarget();31084 const target = mod.getTarget();
3030631085
30307 var chosen = instructions[0];31086 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).
30309 // * ErrorSet: this is an override31088 // * ErrorSet: this is an override
30310 // * ErrorUnion: this is an override of the error set only31089 // * ErrorUnion: this is an override of the error set only
30311 // * other: at the end we make an ErrorUnion with the other thing and this31090 // * other: at the end we make an ErrorUnion with the other thing and this
...@@ -30318,8 +31097,8 @@ fn resolvePeerTypes(...@@ -30318,8 +31097,8 @@ fn resolvePeerTypes(
30318 const candidate_ty = sema.typeOf(candidate);31097 const candidate_ty = sema.typeOf(candidate);
30319 const chosen_ty = sema.typeOf(chosen);31098 const chosen_ty = sema.typeOf(chosen);
3032031099
30321 const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison();31100 const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison(mod);
30322 const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison();31101 const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison(mod);
3032331102
30324 // If the candidate can coerce into our chosen type, we're done.31103 // If the candidate can coerce into our chosen type, we're done.
30325 // If the chosen type can coerce into the candidate, use that.31104 // If the chosen type can coerce into the candidate, use that.
...@@ -30347,8 +31126,8 @@ fn resolvePeerTypes(...@@ -30347,8 +31126,8 @@ fn resolvePeerTypes(
30347 continue;31126 continue;
30348 },31127 },
30349 .Int => {31128 .Int => {
30350 const chosen_info = chosen_ty.intInfo(target);31129 const chosen_info = chosen_ty.intInfo(mod);
30351 const candidate_info = candidate_ty.intInfo(target);31130 const candidate_info = candidate_ty.intInfo(mod);
3035231131
30353 if (chosen_info.bits < candidate_info.bits) {31132 if (chosen_info.bits < candidate_info.bits) {
30354 chosen = candidate;31133 chosen = candidate;
...@@ -30356,12 +31135,12 @@ fn resolvePeerTypes(...@@ -30356,12 +31135,12 @@ fn resolvePeerTypes(
30356 }31135 }
30357 continue;31136 continue;
30358 },31137 },
30359 .Pointer => if (chosen_ty.ptrSize() == .C) continue,31138 .Pointer => if (chosen_ty.ptrSize(mod) == .C) continue,
30360 else => {},31139 else => {},
30361 },31140 },
30362 .ComptimeInt => switch (chosen_ty_tag) {31141 .ComptimeInt => switch (chosen_ty_tag) {
30363 .Int, .Float, .ComptimeFloat => continue,31142 .Int, .Float, .ComptimeFloat => continue,
30364 .Pointer => if (chosen_ty.ptrSize() == .C) continue,31143 .Pointer => if (chosen_ty.ptrSize(mod) == .C) continue,
30365 else => {},31144 else => {},
30366 },31145 },
30367 .Float => switch (chosen_ty_tag) {31146 .Float => switch (chosen_ty_tag) {
...@@ -30426,11 +31205,11 @@ fn resolvePeerTypes(...@@ -30426,11 +31205,11 @@ fn resolvePeerTypes(
30426 continue;31205 continue;
30427 }31206 }
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);
30430 continue;31209 continue;
30431 },31210 },
30432 .ErrorUnion => {31211 .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
30435 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_ty, src, src)) {31214 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_ty, src, src)) {
30436 continue;31215 continue;
...@@ -30440,7 +31219,7 @@ fn resolvePeerTypes(...@@ -30440,7 +31219,7 @@ fn resolvePeerTypes(
30440 continue;31219 continue;
30441 }31220 }
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);
30444 continue;31223 continue;
30445 },31224 },
30446 else => {31225 else => {
...@@ -30453,7 +31232,7 @@ fn resolvePeerTypes(...@@ -30453,7 +31232,7 @@ fn resolvePeerTypes(
30453 continue;31232 continue;
30454 }31233 }
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);
30457 continue;31236 continue;
30458 } else {31237 } else {
30459 err_set_ty = candidate_ty;31238 err_set_ty = candidate_ty;
...@@ -30464,14 +31243,14 @@ fn resolvePeerTypes(...@@ -30464,14 +31243,14 @@ fn resolvePeerTypes(
30464 .ErrorUnion => switch (chosen_ty_tag) {31243 .ErrorUnion => switch (chosen_ty_tag) {
30465 .ErrorSet => {31244 .ErrorSet => {
30466 const chosen_set_ty = err_set_ty orelse chosen_ty;31245 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
30469 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {31248 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {
30470 err_set_ty = chosen_set_ty;31249 err_set_ty = chosen_set_ty;
30471 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {31250 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {
30472 err_set_ty = null;31251 err_set_ty = null;
30473 } else {31252 } 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);
30475 }31254 }
30476 chosen = candidate;31255 chosen = candidate;
30477 chosen_i = candidate_i + 1;31256 chosen_i = candidate_i + 1;
...@@ -30479,8 +31258,8 @@ fn resolvePeerTypes(...@@ -30479,8 +31258,8 @@ fn resolvePeerTypes(
30479 },31258 },
3048031259
30481 .ErrorUnion => {31260 .ErrorUnion => {
30482 const chosen_payload_ty = chosen_ty.errorUnionPayload();31261 const chosen_payload_ty = chosen_ty.errorUnionPayload(mod);
30483 const candidate_payload_ty = candidate_ty.errorUnionPayload();31262 const candidate_payload_ty = candidate_ty.errorUnionPayload(mod);
3048431263
30485 const coerce_chosen = (try sema.coerceInMemoryAllowed(block, chosen_payload_ty, candidate_payload_ty, false, target, src, src)) == .ok;31264 const coerce_chosen = (try sema.coerceInMemoryAllowed(block, chosen_payload_ty, candidate_payload_ty, false, target, src, src)) == .ok;
30486 const coerce_candidate = (try sema.coerceInMemoryAllowed(block, candidate_payload_ty, chosen_payload_ty, false, target, src, src)) == .ok;31265 const coerce_candidate = (try sema.coerceInMemoryAllowed(block, candidate_payload_ty, chosen_payload_ty, false, target, src, src)) == .ok;
...@@ -30494,15 +31273,15 @@ fn resolvePeerTypes(...@@ -30494,15 +31273,15 @@ fn resolvePeerTypes(
30494 chosen_i = candidate_i + 1;31273 chosen_i = candidate_i + 1;
30495 }31274 }
3049631275
30497 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet();31276 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet(mod);
30498 const candidate_set_ty = candidate_ty.errorUnionSet();31277 const candidate_set_ty = candidate_ty.errorUnionSet(mod);
3049931278
30500 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {31279 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {
30501 err_set_ty = chosen_set_ty;31280 err_set_ty = chosen_set_ty;
30502 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {31281 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {
30503 err_set_ty = candidate_set_ty;31282 err_set_ty = candidate_set_ty;
30504 } else {31283 } 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);
30506 }31285 }
30507 continue;31286 continue;
30508 }31287 }
...@@ -30510,26 +31289,26 @@ fn resolvePeerTypes(...@@ -30510,26 +31289,26 @@ fn resolvePeerTypes(
3051031289
30511 else => {31290 else => {
30512 if (err_set_ty) |chosen_set_ty| {31291 if (err_set_ty) |chosen_set_ty| {
30513 const candidate_set_ty = candidate_ty.errorUnionSet();31292 const candidate_set_ty = candidate_ty.errorUnionSet(mod);
30514 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {31293 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {
30515 err_set_ty = chosen_set_ty;31294 err_set_ty = chosen_set_ty;
30516 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {31295 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {
30517 err_set_ty = null;31296 err_set_ty = null;
30518 } else {31297 } 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);
30520 }31299 }
30521 }31300 }
30522 seen_const = seen_const or chosen_ty.isConstPtr();31301 seen_const = seen_const or chosen_ty.isConstPtr(mod);
30523 chosen = candidate;31302 chosen = candidate;
30524 chosen_i = candidate_i + 1;31303 chosen_i = candidate_i + 1;
30525 continue;31304 continue;
30526 },31305 },
30527 },31306 },
30528 .Pointer => {31307 .Pointer => {
30529 const cand_info = candidate_ty.ptrInfo().data;31308 const cand_info = candidate_ty.ptrInfo(mod);
30530 switch (chosen_ty_tag) {31309 switch (chosen_ty_tag) {
30531 .Pointer => {31310 .Pointer => {
30532 const chosen_info = chosen_ty.ptrInfo().data;31311 const chosen_info = chosen_ty.ptrInfo(mod);
3053331312
30534 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;31313 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;
3053531314
...@@ -30537,7 +31316,7 @@ fn resolvePeerTypes(...@@ -30537,7 +31316,7 @@ fn resolvePeerTypes(
30537 // *[N]T to []T31316 // *[N]T to []T
30538 if ((cand_info.size == .Many or cand_info.size == .Slice) and31317 if ((cand_info.size == .Many or cand_info.size == .Slice) and
30539 chosen_info.size == .One and31318 chosen_info.size == .One and
30540 chosen_info.pointee_type.zigTypeTag() == .Array)31319 chosen_info.pointee_type.zigTypeTag(mod) == .Array)
30541 {31320 {
30542 // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T`31321 // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T`
30543 convert_to_slice = false;31322 convert_to_slice = false;
...@@ -30546,7 +31325,7 @@ fn resolvePeerTypes(...@@ -30546,7 +31325,7 @@ fn resolvePeerTypes(
30546 continue;31325 continue;
30547 }31326 }
30548 if (cand_info.size == .One and31327 if (cand_info.size == .One and
30549 cand_info.pointee_type.zigTypeTag() == .Array and31328 cand_info.pointee_type.zigTypeTag(mod) == .Array and
30550 (chosen_info.size == .Many or chosen_info.size == .Slice))31329 (chosen_info.size == .Many or chosen_info.size == .Slice))
30551 {31330 {
30552 // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T`31331 // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T`
...@@ -30559,11 +31338,11 @@ fn resolvePeerTypes(...@@ -30559,11 +31338,11 @@ fn resolvePeerTypes(
30559 // Keep the one whose element type can be coerced into.31338 // Keep the one whose element type can be coerced into.
30560 if (chosen_info.size == .One and31339 if (chosen_info.size == .One and
30561 cand_info.size == .One and31340 cand_info.size == .One and
30562 chosen_info.pointee_type.zigTypeTag() == .Array and31341 chosen_info.pointee_type.zigTypeTag(mod) == .Array and
30563 cand_info.pointee_type.zigTypeTag() == .Array)31342 cand_info.pointee_type.zigTypeTag(mod) == .Array)
30564 {31343 {
30565 const chosen_elem_ty = chosen_info.pointee_type.childType();31344 const chosen_elem_ty = chosen_info.pointee_type.childType(mod);
30566 const cand_elem_ty = cand_info.pointee_type.childType();31345 const cand_elem_ty = cand_info.pointee_type.childType(mod);
3056731346
30568 const chosen_ok = .ok == try sema.coerceInMemoryAllowed(block, chosen_elem_ty, cand_elem_ty, chosen_info.mutable, target, src, src);31347 const chosen_ok = .ok == try sema.coerceInMemoryAllowed(block, chosen_elem_ty, cand_elem_ty, chosen_info.mutable, target, src, src);
30569 if (chosen_ok) {31348 if (chosen_ok) {
...@@ -30629,17 +31408,16 @@ fn resolvePeerTypes(...@@ -30629,17 +31408,16 @@ fn resolvePeerTypes(
30629 }31408 }
30630 },31409 },
30631 .Optional => {31410 .Optional => {
30632 var opt_child_buf: Type.Payload.ElemType = undefined;31411 const chosen_ptr_ty = chosen_ty.optionalChild(mod);
30633 const chosen_ptr_ty = chosen_ty.optionalChild(&opt_child_buf);31412 if (chosen_ptr_ty.zigTypeTag(mod) == .Pointer) {
30634 if (chosen_ptr_ty.zigTypeTag() == .Pointer) {31413 const chosen_info = chosen_ptr_ty.ptrInfo(mod);
30635 const chosen_info = chosen_ptr_ty.ptrInfo().data;
3063631414
30637 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;31415 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;
3063831416
30639 // *[N]T to ?![*]T31417 // *[N]T to ?![*]T
30640 // *[N]T to ?![]T31418 // *[N]T to ?![]T
30641 if (cand_info.size == .One and31419 if (cand_info.size == .One and
30642 cand_info.pointee_type.zigTypeTag() == .Array and31420 cand_info.pointee_type.zigTypeTag(mod) == .Array and
30643 (chosen_info.size == .Many or chosen_info.size == .Slice))31421 (chosen_info.size == .Many or chosen_info.size == .Slice))
30644 {31422 {
30645 continue;31423 continue;
...@@ -30647,16 +31425,16 @@ fn resolvePeerTypes(...@@ -30647,16 +31425,16 @@ fn resolvePeerTypes(
30647 }31425 }
30648 },31426 },
30649 .ErrorUnion => {31427 .ErrorUnion => {
30650 const chosen_ptr_ty = chosen_ty.errorUnionPayload();31428 const chosen_ptr_ty = chosen_ty.errorUnionPayload(mod);
30651 if (chosen_ptr_ty.zigTypeTag() == .Pointer) {31429 if (chosen_ptr_ty.zigTypeTag(mod) == .Pointer) {
30652 const chosen_info = chosen_ptr_ty.ptrInfo().data;31430 const chosen_info = chosen_ptr_ty.ptrInfo(mod);
3065331431
30654 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;31432 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;
3065531433
30656 // *[N]T to E![*]T31434 // *[N]T to E![*]T
30657 // *[N]T to E![]T31435 // *[N]T to E![]T
30658 if (cand_info.size == .One and31436 if (cand_info.size == .One and
30659 cand_info.pointee_type.zigTypeTag() == .Array and31437 cand_info.pointee_type.zigTypeTag(mod) == .Array and
30660 (chosen_info.size == .Many or chosen_info.size == .Slice))31438 (chosen_info.size == .Many or chosen_info.size == .Slice))
30661 {31439 {
30662 continue;31440 continue;
...@@ -30664,7 +31442,7 @@ fn resolvePeerTypes(...@@ -30664,7 +31442,7 @@ fn resolvePeerTypes(
30664 }31442 }
30665 },31443 },
30666 .Fn => {31444 .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)) {
30668 chosen = candidate;31446 chosen = candidate;
30669 chosen_i = candidate_i + 1;31447 chosen_i = candidate_i + 1;
30670 continue;31448 continue;
...@@ -30674,15 +31452,14 @@ fn resolvePeerTypes(...@@ -30674,15 +31452,14 @@ fn resolvePeerTypes(
30674 }31452 }
30675 },31453 },
30676 .Optional => {31454 .Optional => {
30677 var opt_child_buf: Type.Payload.ElemType = undefined;31455 const opt_child_ty = candidate_ty.optionalChild(mod);
30678 const opt_child_ty = candidate_ty.optionalChild(&opt_child_buf);
30679 if ((try sema.coerceInMemoryAllowed(block, chosen_ty, opt_child_ty, false, target, src, src)) == .ok) {31456 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);
30681 any_are_null = true;31458 any_are_null = true;
30682 continue;31459 continue;
30683 }31460 }
3068431461
30685 seen_const = seen_const or chosen_ty.isConstPtr();31462 seen_const = seen_const or chosen_ty.isConstPtr(mod);
30686 any_are_null = false;31463 any_are_null = false;
30687 chosen = candidate;31464 chosen = candidate;
30688 chosen_i = candidate_i + 1;31465 chosen_i = candidate_i + 1;
...@@ -30690,23 +31467,23 @@ fn resolvePeerTypes(...@@ -30690,23 +31467,23 @@ fn resolvePeerTypes(
30690 },31467 },
30691 .Vector => switch (chosen_ty_tag) {31468 .Vector => switch (chosen_ty_tag) {
30692 .Vector => {31469 .Vector => {
30693 const chosen_len = chosen_ty.vectorLen();31470 const chosen_len = chosen_ty.vectorLen(mod);
30694 const candidate_len = candidate_ty.vectorLen();31471 const candidate_len = candidate_ty.vectorLen(mod);
30695 if (chosen_len != candidate_len)31472 if (chosen_len != candidate_len)
30696 continue;31473 continue;
3069731474
30698 const chosen_child_ty = chosen_ty.childType();31475 const chosen_child_ty = chosen_ty.childType(mod);
30699 const candidate_child_ty = candidate_ty.childType();31476 const candidate_child_ty = candidate_ty.childType(mod);
30700 if (chosen_child_ty.zigTypeTag() == .Int and candidate_child_ty.zigTypeTag() == .Int) {31477 if (chosen_child_ty.zigTypeTag(mod) == .Int and candidate_child_ty.zigTypeTag(mod) == .Int) {
30701 const chosen_info = chosen_child_ty.intInfo(target);31478 const chosen_info = chosen_child_ty.intInfo(mod);
30702 const candidate_info = candidate_child_ty.intInfo(target);31479 const candidate_info = candidate_child_ty.intInfo(mod);
30703 if (chosen_info.bits < candidate_info.bits) {31480 if (chosen_info.bits < candidate_info.bits) {
30704 chosen = candidate;31481 chosen = candidate;
30705 chosen_i = candidate_i + 1;31482 chosen_i = candidate_i + 1;
30706 }31483 }
30707 continue;31484 continue;
30708 }31485 }
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) {
30710 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {31487 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {
30711 chosen = candidate;31488 chosen = candidate;
30712 chosen_i = candidate_i + 1;31489 chosen_i = candidate_i + 1;
...@@ -30725,8 +31502,8 @@ fn resolvePeerTypes(...@@ -30725,8 +31502,8 @@ fn resolvePeerTypes(
30725 .Vector => continue,31502 .Vector => continue,
30726 else => {},31503 else => {},
30727 },31504 },
30728 .Fn => if (chosen_ty.isSinglePointer() and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag() == .Fn) {31505 .Fn => if (chosen_ty.isSinglePointer(mod) and chosen_ty.isConstPtr(mod) and chosen_ty.childType(mod).zigTypeTag(mod) == .Fn) {
30729 if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(), candidate_ty, target, src, src)) {31506 if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(mod), candidate_ty, target, src, src)) {
30730 continue;31507 continue;
30731 }31508 }
30732 },31509 },
...@@ -30746,8 +31523,7 @@ fn resolvePeerTypes(...@@ -30746,8 +31523,7 @@ fn resolvePeerTypes(
30746 continue;31523 continue;
30747 },31524 },
30748 .Optional => {31525 .Optional => {
30749 var opt_child_buf: Type.Payload.ElemType = undefined;31526 const opt_child_ty = chosen_ty.optionalChild(mod);
30750 const opt_child_ty = chosen_ty.optionalChild(&opt_child_buf);
30751 if ((try sema.coerceInMemoryAllowed(block, opt_child_ty, candidate_ty, false, target, src, src)) == .ok) {31527 if ((try sema.coerceInMemoryAllowed(block, opt_child_ty, candidate_ty, false, target, src, src)) == .ok) {
30752 continue;31528 continue;
30753 }31529 }
...@@ -30759,7 +31535,7 @@ fn resolvePeerTypes(...@@ -30759,7 +31535,7 @@ fn resolvePeerTypes(
30759 }31535 }
30760 },31536 },
30761 .ErrorUnion => {31537 .ErrorUnion => {
30762 const payload_ty = chosen_ty.errorUnionPayload();31538 const payload_ty = chosen_ty.errorUnionPayload(mod);
30763 if ((try sema.coerceInMemoryAllowed(block, payload_ty, candidate_ty, false, target, src, src)) == .ok) {31539 if ((try sema.coerceInMemoryAllowed(block, payload_ty, candidate_ty, false, target, src, src)) == .ok) {
30764 continue;31540 continue;
30765 }31541 }
...@@ -30776,7 +31552,7 @@ fn resolvePeerTypes(...@@ -30776,7 +31552,7 @@ fn resolvePeerTypes(
30776 continue;31552 continue;
30777 }31553 }
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);
30780 continue;31556 continue;
30781 } else {31557 } else {
30782 err_set_ty = chosen_ty;31558 err_set_ty = chosen_ty;
...@@ -30789,28 +31565,28 @@ fn resolvePeerTypes(...@@ -30789,28 +31565,28 @@ fn resolvePeerTypes(
30789 // At this point, we hit a compile error. We need to recover31565 // At this point, we hit a compile error. We need to recover
30790 // the source locations.31566 // the source locations.
30791 const chosen_src = candidate_srcs.resolve(31567 const chosen_src = candidate_srcs.resolve(
30792 sema.gpa,31568 mod,
30793 sema.mod.declPtr(block.src_decl),31569 mod.declPtr(block.src_decl),
30794 chosen_i,31570 chosen_i,
30795 );31571 );
30796 const candidate_src = candidate_srcs.resolve(31572 const candidate_src = candidate_srcs.resolve(
30797 sema.gpa,31573 mod,
30798 sema.mod.declPtr(block.src_decl),31574 mod.declPtr(block.src_decl),
30799 candidate_i + 1,31575 candidate_i + 1,
30800 );31576 );
3080131577
30802 const msg = msg: {31578 const msg = msg: {
30803 const msg = try sema.errMsg(block, src, "incompatible types: '{}' and '{}'", .{31579 const msg = try sema.errMsg(block, src, "incompatible types: '{}' and '{}'", .{
30804 chosen_ty.fmt(sema.mod),31580 chosen_ty.fmt(mod),
30805 candidate_ty.fmt(sema.mod),31581 candidate_ty.fmt(mod),
30806 });31582 });
30807 errdefer msg.destroy(sema.gpa);31583 errdefer msg.destroy(sema.gpa);
3080831584
30809 if (chosen_src) |src_loc|31585 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
30812 if (candidate_src) |src_loc|31588 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
30815 break :msg msg;31591 break :msg msg;
30816 };31592 };
...@@ -30821,139 +31597,231 @@ fn resolvePeerTypes(...@@ -30821,139 +31597,231 @@ fn resolvePeerTypes(
3082131597
30822 if (convert_to_slice) {31598 if (convert_to_slice) {
30823 // turn *[N]T => []T31599 // turn *[N]T => []T
30824 const chosen_child_ty = chosen_ty.childType();31600 const chosen_child_ty = chosen_ty.childType(mod);
30825 var info = chosen_ty.ptrInfo();31601 var info = chosen_ty.ptrInfo(mod);
30826 info.data.sentinel = chosen_child_ty.sentinel();31602 info.sentinel = chosen_child_ty.sentinel(mod);
30827 info.data.size = .Slice;31603 info.size = .Slice;
30828 info.data.mutable = !(seen_const or chosen_child_ty.isConstPtr());31604 info.mutable = !(seen_const or chosen_child_ty.isConstPtr(mod));
30829 info.data.pointee_type = chosen_child_ty.elemType2();31605 info.pointee_type = chosen_child_ty.elemType2(mod);
3083031606
30831 const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data);31607 const new_ptr_ty = try Type.ptr(sema.arena, mod, info);
30832 const opt_ptr_ty = if (any_are_null)31608 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)
30834 else31610 else
30835 new_ptr_ty;31611 new_ptr_ty;
30836 const set_ty = err_set_ty orelse return opt_ptr_ty;31612 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);
30838 }31614 }
3083931615
30840 if (seen_const) {31616 if (seen_const) {
30841 // turn []T => []const T31617 // turn []T => []const T
30842 switch (chosen_ty.zigTypeTag()) {31618 switch (chosen_ty.zigTypeTag(mod)) {
30843 .ErrorUnion => {31619 .ErrorUnion => {
30844 const ptr_ty = chosen_ty.errorUnionPayload();31620 const ptr_ty = chosen_ty.errorUnionPayload(mod);
30845 var info = ptr_ty.ptrInfo();31621 var info = ptr_ty.ptrInfo(mod);
30846 info.data.mutable = false;31622 info.mutable = false;
30847 const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data);31623 const new_ptr_ty = try Type.ptr(sema.arena, mod, info);
30848 const opt_ptr_ty = if (any_are_null)31624 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)
30850 else31626 else
30851 new_ptr_ty;31627 new_ptr_ty;
30852 const set_ty = err_set_ty orelse chosen_ty.errorUnionSet();31628 const set_ty = err_set_ty orelse chosen_ty.errorUnionSet(mod);
30853 return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod);31629 return try mod.errorUnionType(set_ty, opt_ptr_ty);
30854 },31630 },
30855 .Pointer => {31631 .Pointer => {
30856 var info = chosen_ty.ptrInfo();31632 var info = chosen_ty.ptrInfo(mod);
30857 info.data.mutable = false;31633 info.mutable = false;
30858 const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data);31634 const new_ptr_ty = try Type.ptr(sema.arena, mod, info);
30859 const opt_ptr_ty = if (any_are_null)31635 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)
30861 else31637 else
30862 new_ptr_ty;31638 new_ptr_ty;
30863 const set_ty = err_set_ty orelse return opt_ptr_ty;31639 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);
30865 },31641 },
30866 else => return chosen_ty,31642 else => return chosen_ty,
30867 }31643 }
30868 }31644 }
3086931645
30870 if (any_are_null) {31646 if (any_are_null) {
30871 const opt_ty = switch (chosen_ty.zigTypeTag()) {31647 const opt_ty = switch (chosen_ty.zigTypeTag(mod)) {
30872 .Null, .Optional => chosen_ty,31648 .Null, .Optional => chosen_ty,
30873 else => try Type.optional(sema.arena, chosen_ty),31649 else => try Type.optional(sema.arena, chosen_ty, mod),
30874 };31650 };
30875 const set_ty = err_set_ty orelse return opt_ty;31651 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);
30877 }31653 }
3087831654
30879 if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) {31655 if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag(mod)) {
30880 .ErrorSet => return ty,31656 .ErrorSet => return ty,
30881 .ErrorUnion => {31657 .ErrorUnion => {
30882 const payload_ty = chosen_ty.errorUnionPayload();31658 const payload_ty = chosen_ty.errorUnionPayload(mod);
30883 return try Type.errorUnion(sema.arena, ty, payload_ty, sema.mod);31659 return try mod.errorUnionType(ty, payload_ty);
30884 },31660 },
30885 else => return try Type.errorUnion(sema.arena, ty, chosen_ty, sema.mod),31661 else => return try mod.errorUnionType(ty, chosen_ty),
30886 };31662 };
3088731663
30888 return chosen_ty;31664 return chosen_ty;
30889}31665}
3089031666
30891pub fn resolveFnTypes(sema: *Sema, fn_info: Type.Payload.Function.Data) CompileError!void {31667pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
30892 try sema.resolveTypeFully(fn_info.return_type);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)) {
30895 // Ensure the type exists so that backends can assume that.31672 // Ensure the type exists so that backends can assume that.
30896 _ = try sema.getBuiltinType("StackTrace");31673 _ = try sema.getBuiltinType("StackTrace");
30897 }31674 }
3089831675
30899 for (fn_info.param_types) |param_ty| {31676 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {
30900 try sema.resolveTypeFully(param_ty);31677 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());
30901 }31678 }
30902}31679}
3090331680
30904/// Make it so that calling hash() and eql() on `val` will not assert due31681/// Make it so that calling hash() and eql() on `val` will not assert due
30905/// to a type not having its layout resolved.31682/// to a type not having its layout resolved.
30906fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void {31683fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
30907 switch (val.tag()) {31684 const mod = sema.mod;
30908 .lazy_align => {31685 switch (mod.intern_pool.indexToKey(val.toIntern())) {
30909 const ty = val.castTag(.lazy_align).?.data;31686 .int => |int| switch (int.storage) {
30910 return sema.resolveTypeLayout(ty);31687 .u64, .i64, .big_int => return val,
30911 },31688 .lazy_align, .lazy_size => return (try mod.intern(.{ .int = .{
30912 .lazy_size => {31689 .ty = int.ty,
30913 const ty = val.castTag(.lazy_size).?.data;31690 .storage = .{ .u64 = (try val.getUnsignedIntAdvanced(mod, sema)).? },
30914 return sema.resolveTypeLayout(ty);31691 } })).toValue(),
30915 },31692 },
30916 .comptime_field_ptr => {31693 .ptr => |ptr| {
30917 const field_ptr = val.castTag(.comptime_field_ptr).?.data;31694 const resolved_len = switch (ptr.len) {
30918 return sema.resolveLazyValue(field_ptr.field_val);31695 .none => .none,
30919 },31696 else => (try sema.resolveLazyValue(ptr.len.toValue())).toIntern(),
30920 .eu_payload,31697 };
30921 .opt_payload,31698 switch (ptr.addr) {
30922 => {31699 .decl, .mut_decl => return if (resolved_len == ptr.len)
30923 const sub_val = val.cast(Value.Payload.SubValue).?.data;31700 val
30924 return sema.resolveLazyValue(sub_val);31701 else
30925 },31702 (try mod.intern(.{ .ptr = .{
30926 .@"union" => {31703 .ty = ptr.ty,
30927 const union_val = val.castTag(.@"union").?.data;31704 .addr = switch (ptr.addr) {
30928 return sema.resolveLazyValue(union_val.val);31705 .decl => |decl| .{ .decl = decl },
30929 },31706 .mut_decl => |mut_decl| .{ .mut_decl = mut_decl },
30930 .aggregate => {31707 else => unreachable,
30931 const aggregate = val.castTag(.aggregate).?.data;31708 },
30932 for (aggregate) |elem_val| {31709 .len = resolved_len,
30933 try sema.resolveLazyValue(elem_val);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 },
30934 }31770 }
30935 },31771 },
30936 .slice => {31772 .aggregate => |aggregate| switch (aggregate.storage) {
30937 const slice = val.castTag(.slice).?.data;31773 .bytes => return val,
30938 try sema.resolveLazyValue(slice.ptr);31774 .elems => |elems| {
30939 return sema.resolveLazyValue(slice.len);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();
30940 },31808 },
30941 else => return,31809 else => return val,
30942 }31810 }
30943}31811}
3094431812
30945pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {31813pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
30946 switch (ty.zigTypeTag()) {31814 const mod = sema.mod;
31815 switch (ty.zigTypeTag(mod)) {
30947 .Struct => return sema.resolveStructLayout(ty),31816 .Struct => return sema.resolveStructLayout(ty),
30948 .Union => return sema.resolveUnionLayout(ty),31817 .Union => return sema.resolveUnionLayout(ty),
30949 .Array => {31818 .Array => {
30950 if (ty.arrayLenIncludingSentinel() == 0) return;31819 if (ty.arrayLenIncludingSentinel(mod) == 0) return;
30951 const elem_ty = ty.childType();31820 const elem_ty = ty.childType(mod);
30952 return sema.resolveTypeLayout(elem_ty);31821 return sema.resolveTypeLayout(elem_ty);
30953 },31822 },
30954 .Optional => {31823 .Optional => {
30955 var buf: Type.Payload.ElemType = undefined;31824 const payload_ty = ty.optionalChild(mod);
30956 const payload_ty = ty.optionalChild(&buf);
30957 // In case of querying the ABI alignment of this optional, we will ask31825 // In case of querying the ABI alignment of this optional, we will ask
30958 // for hasRuntimeBits() of the payload type, so we need "requires comptime"31826 // for hasRuntimeBits() of the payload type, so we need "requires comptime"
30959 // to be known already before this function returns.31827 // to be known already before this function returns.
...@@ -30961,37 +31829,37 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -30961,37 +31829,37 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
30961 return sema.resolveTypeLayout(payload_ty);31829 return sema.resolveTypeLayout(payload_ty);
30962 },31830 },
30963 .ErrorUnion => {31831 .ErrorUnion => {
30964 const payload_ty = ty.errorUnionPayload();31832 const payload_ty = ty.errorUnionPayload(mod);
30965 return sema.resolveTypeLayout(payload_ty);31833 return sema.resolveTypeLayout(payload_ty);
30966 },31834 },
30967 .Fn => {31835 .Fn => {
30968 const info = ty.fnInfo();31836 const info = mod.typeToFunc(ty).?;
30969 if (info.is_generic) {31837 if (info.is_generic) {
30970 // Resolving of generic function types is deferred to when31838 // Resolving of generic function types is deferred to when
30971 // the function is instantiated.31839 // the function is instantiated.
30972 return;31840 return;
30973 }31841 }
30974 for (info.param_types) |param_ty| {31842 for (info.param_types) |param_ty| {
30975 try sema.resolveTypeLayout(param_ty);31843 try sema.resolveTypeLayout(param_ty.toType());
30976 }31844 }
30977 try sema.resolveTypeLayout(info.return_type);31845 try sema.resolveTypeLayout(info.return_type.toType());
30978 },31846 },
30979 else => {},31847 else => {},
30980 }31848 }
30981}31849}
3098231850
30983fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {31851fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31852 const mod = sema.mod;
30984 const resolved_ty = try sema.resolveTypeFields(ty);31853 const resolved_ty = try sema.resolveTypeFields(ty);
30985 if (resolved_ty.castTag(.@"struct")) |payload| {31854 if (mod.typeToStruct(resolved_ty)) |struct_obj| {
30986 const struct_obj = payload.data;
30987 switch (struct_obj.status) {31855 switch (struct_obj.status) {
30988 .none, .have_field_types => {},31856 .none, .have_field_types => {},
30989 .field_types_wip, .layout_wip => {31857 .field_types_wip, .layout_wip => {
30990 const msg = try Module.ErrorMsg.create(31858 const msg = try Module.ErrorMsg.create(
30991 sema.gpa,31859 sema.gpa,
30992 struct_obj.srcLoc(sema.mod),31860 struct_obj.srcLoc(mod),
30993 "struct '{}' depends on itself",31861 "struct '{}' depends on itself",
30994 .{ty.fmt(sema.mod)},31862 .{ty.fmt(mod)},
30995 );31863 );
30996 return sema.failWithOwnedErrorMsg(msg);31864 return sema.failWithOwnedErrorMsg(msg);
30997 },31865 },
...@@ -31015,35 +31883,27 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31015,35 +31883,27 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31015 }31883 }
3101631884
31017 if (struct_obj.layout == .Packed) {31885 if (struct_obj.layout == .Packed) {
31018 try semaBackingIntType(sema.mod, struct_obj);31886 try semaBackingIntType(mod, struct_obj);
31019 }31887 }
3102031888
31021 struct_obj.status = .have_layout;31889 struct_obj.status = .have_layout;
31022 _ = try sema.resolveTypeRequiresComptime(resolved_ty);31890 _ = 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))) {
31025 const msg = try Module.ErrorMsg.create(31893 const msg = try Module.ErrorMsg.create(
31026 sema.gpa,31894 sema.gpa,
31027 struct_obj.srcLoc(sema.mod),31895 struct_obj.srcLoc(mod),
31028 "struct layout depends on it having runtime bits",31896 "struct layout depends on it having runtime bits",
31029 .{},31897 .{},
31030 );31898 );
31031 return sema.failWithOwnedErrorMsg(msg);31899 return sema.failWithOwnedErrorMsg(msg);
31032 }31900 }
3103331901
31034 if (struct_obj.layout == .Auto and sema.mod.backendSupportsFeature(.field_reordering)) {31902 if (struct_obj.layout == .Auto and mod.backendSupportsFeature(.field_reordering)) {
31035 const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index)31903 const optimized_order = try mod.tmp_hack_arena.allocator().alloc(u32, struct_obj.fields.count());
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 };
3104431904
31045 for (struct_obj.fields.values(), 0..) |field, i| {31905 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))
31047 @intCast(u32, i)31907 @intCast(u32, i)
31048 else31908 else
31049 Module.Struct.omitted_field;31909 Module.Struct.omitted_field;
...@@ -31054,11 +31914,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31054,11 +31914,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31054 sema: *Sema,31914 sema: *Sema,
3105531915
31056 fn lessThan(ctx: @This(), a: u32, b: u32) bool {31916 fn lessThan(ctx: @This(), a: u32, b: u32) bool {
31917 const m = ctx.sema.mod;
31057 if (a == Module.Struct.omitted_field) return false;31918 if (a == Module.Struct.omitted_field) return false;
31058 if (b == Module.Struct.omitted_field) return true;31919 if (b == Module.Struct.omitted_field) return true;
31059 const target = ctx.sema.mod.getTarget();31920 return ctx.struct_obj.fields.values()[a].ty.abiAlignment(m) >
31060 return ctx.struct_obj.fields.values()[a].ty.abiAlignment(target) >31921 ctx.struct_obj.fields.values()[b].ty.abiAlignment(m);
31061 ctx.struct_obj.fields.values()[b].ty.abiAlignment(target);
31062 }31922 }
31063 };31923 };
31064 mem.sort(u32, optimized_order, AlignSortContext{31924 mem.sort(u32, optimized_order, AlignSortContext{
...@@ -31073,20 +31933,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31073,20 +31933,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3107331933
31074fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!void {31934fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!void {
31075 const gpa = mod.gpa;31935 const gpa = mod.gpa;
31076 const target = mod.getTarget();
3107731936
31078 var fields_bit_sum: u64 = 0;31937 var fields_bit_sum: u64 = 0;
31079 for (struct_obj.fields.values()) |field| {31938 for (struct_obj.fields.values()) |field| {
31080 fields_bit_sum += field.ty.bitSize(target);31939 fields_bit_sum += field.ty.bitSize(mod);
31081 }31940 }
3108231941
31083 const decl_index = struct_obj.owner_decl;31942 const decl_index = struct_obj.owner_decl;
31084 const decl = mod.declPtr(decl_index);31943 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;
31090 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;31946 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
31091 assert(extended.opcode == .struct_decl);31947 assert(extended.opcode == .struct_decl);
31092 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);31948 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
...@@ -31103,28 +31959,33 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -31103,28 +31959,33 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
31103 var analysis_arena = std.heap.ArenaAllocator.init(gpa);31959 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
31104 defer analysis_arena.deinit();31960 defer analysis_arena.deinit();
3110531961
31962 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
31963 defer comptime_mutable_decls.deinit();
31964
31106 var sema: Sema = .{31965 var sema: Sema = .{
31107 .mod = mod,31966 .mod = mod,
31108 .gpa = gpa,31967 .gpa = gpa,
31109 .arena = analysis_arena.allocator(),31968 .arena = analysis_arena.allocator(),
31110 .perm_arena = decl_arena_allocator,
31111 .code = zir,31969 .code = zir,
31112 .owner_decl = decl,31970 .owner_decl = decl,
31113 .owner_decl_index = decl_index,31971 .owner_decl_index = decl_index,
31114 .func = null,31972 .func = null,
31973 .func_index = .none,
31115 .fn_ret_ty = Type.void,31974 .fn_ret_ty = Type.void,
31116 .owner_func = null,31975 .owner_func = null,
31976 .owner_func_index = .none,
31977 .comptime_mutable_decls = &comptime_mutable_decls,
31117 };31978 };
31118 defer sema.deinit();31979 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);
31121 defer wip_captures.deinit();31982 defer wip_captures.deinit();
3112231983
31123 var block: Block = .{31984 var block: Block = .{
31124 .parent = null,31985 .parent = null,
31125 .sema = &sema,31986 .sema = &sema,
31126 .src_decl = decl_index,31987 .src_decl = decl_index,
31127 .namespace = &struct_obj.namespace,31988 .namespace = struct_obj.namespace,
31128 .wip_capture_scope = wip_captures.scope,31989 .wip_capture_scope = wip_captures.scope,
31129 .instructions = .{},31990 .instructions = .{},
31130 .inlining = null,31991 .inlining = null,
...@@ -31148,21 +32009,27 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -31148,21 +32009,27 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
31148 };32009 };
3114932010
31150 try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);32011 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;
31152 try wip_captures.finalize();32013 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 }
31153 } else {32018 } else {
31154 if (fields_bit_sum > std.math.maxInt(u16)) {32019 if (fields_bit_sum > std.math.maxInt(u16)) {
31155 var sema: Sema = .{32020 var sema: Sema = .{
31156 .mod = mod,32021 .mod = mod,
31157 .gpa = gpa,32022 .gpa = gpa,
31158 .arena = undefined,32023 .arena = undefined,
31159 .perm_arena = decl_arena_allocator,
31160 .code = zir,32024 .code = zir,
31161 .owner_decl = decl,32025 .owner_decl = decl,
31162 .owner_decl_index = decl_index,32026 .owner_decl_index = decl_index,
31163 .func = null,32027 .func = null,
32028 .func_index = .none,
31164 .fn_ret_ty = Type.void,32029 .fn_ret_ty = Type.void,
31165 .owner_func = null,32030 .owner_func = null,
32031 .owner_func_index = .none,
32032 .comptime_mutable_decls = undefined,
31166 };32033 };
31167 defer sema.deinit();32034 defer sema.deinit();
3116832035
...@@ -31170,7 +32037,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -31170,7 +32037,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
31170 .parent = null,32037 .parent = null,
31171 .sema = &sema,32038 .sema = &sema,
31172 .src_decl = decl_index,32039 .src_decl = decl_index,
31173 .namespace = &struct_obj.namespace,32040 .namespace = struct_obj.namespace,
31174 .wip_capture_scope = undefined,32041 .wip_capture_scope = undefined,
31175 .instructions = .{},32042 .instructions = .{},
31176 .inlining = null,32043 .inlining = null,
...@@ -31178,32 +32045,29 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -31178,32 +32045,29 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
31178 };32045 };
31179 return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});32046 return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
31180 }32047 }
31181 var buf: Type.Payload.Bits = .{32048 struct_obj.backing_int_ty = try mod.intType(.unsigned, @intCast(u16, fields_bit_sum));
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);
31186 }32049 }
31187}32050}
3118832051
31189fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void {32052fn 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)) {
31193 return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(sema.mod)});32056 return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(sema.mod)});
31194 }32057 }
31195 if (backing_int_ty.bitSize(target) != fields_bit_sum) {32058 if (backing_int_ty.bitSize(mod) != fields_bit_sum) {
31196 return sema.fail(32059 return sema.fail(
31197 block,32060 block,
31198 src,32061 src,
31199 "backing integer type '{}' has bit size {} but the struct fields have a total bit size of {}",32062 "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 },
31201 );32064 );
31202 }32065 }
31203}32066}
3120432067
31205fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {32068fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31206 if (!ty.isIndexable()) {32069 const mod = sema.mod;
32070 if (!ty.isIndexable(mod)) {
31207 const msg = msg: {32071 const msg = msg: {
31208 const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)});32072 const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)});
31209 errdefer msg.destroy(sema.gpa);32073 errdefer msg.destroy(sema.gpa);
...@@ -31215,12 +32079,13 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {...@@ -31215,12 +32079,13 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31215}32079}
3121632080
31217fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {32081fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31218 if (ty.zigTypeTag() == .Pointer) {32082 const mod = sema.mod;
31219 switch (ty.ptrSize()) {32083 if (ty.zigTypeTag(mod) == .Pointer) {
32084 switch (ty.ptrSize(mod)) {
31220 .Slice, .Many, .C => return,32085 .Slice, .Many, .C => return,
31221 .One => {32086 .One => {
31222 const elem_ty = ty.childType();32087 const elem_ty = ty.childType(mod);
31223 if (elem_ty.zigTypeTag() == .Array) return;32088 if (elem_ty.zigTypeTag(mod) == .Array) return;
31224 // TODO https://github.com/ziglang/zig/issues/1547932089 // TODO https://github.com/ziglang/zig/issues/15479
31225 // if (elem_ty.isTuple()) return;32090 // if (elem_ty.isTuple()) return;
31226 },32091 },
...@@ -31236,8 +32101,9 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void...@@ -31236,8 +32101,9 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
31236}32101}
3123732102
31238fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {32103fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
32104 const mod = sema.mod;
31239 const resolved_ty = try sema.resolveTypeFields(ty);32105 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).?;
31241 switch (union_obj.status) {32107 switch (union_obj.status) {
31242 .none, .have_field_types => {},32108 .none, .have_field_types => {},
31243 .field_types_wip, .layout_wip => {32109 .field_types_wip, .layout_wip => {
...@@ -31270,7 +32136,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31270,7 +32136,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
31270 union_obj.status = .have_layout;32136 union_obj.status = .have_layout;
31271 _ = try sema.resolveTypeRequiresComptime(resolved_ty);32137 _ = 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))) {
31274 const msg = try Module.ErrorMsg.create(32140 const msg = try Module.ErrorMsg.create(
31275 sema.gpa,32141 sema.gpa,
31276 union_obj.srcLoc(sema.mod),32142 union_obj.srcLoc(sema.mod),
...@@ -31285,188 +32151,154 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31285,188 +32151,154 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
31285// for hasRuntimeBits() of each field, so we need "requires comptime"32151// for hasRuntimeBits() of each field, so we need "requires comptime"
31286// to be known already before this function returns.32152// to be known already before this function returns.
31287pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {32153pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31288 return switch (ty.tag()) {32154 const mod = sema.mod;
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 },
3140432155
31405 .tuple, .anon_struct => {32156 return switch (ty.toIntern()) {
31406 const tuple = ty.tupleFields();32157 .empty_struct_type => false,
31407 for (tuple.types, 0..) |field_ty, i| {32158 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
31408 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;32159 .int_type => false,
31409 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {32160 .ptr_type => |ptr_type| {
31410 return true;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);
31411 }32166 }
31412 }32167 },
31413 return false;32168 .anyframe_type => |child| {
31414 },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" => {32246 .anon_struct_type => |tuple| {
31417 const struct_obj = ty.castTag(.@"struct").?.data;32247 for (tuple.types, tuple.values) |field_ty, field_val| {
31418 switch (struct_obj.requires_comptime) {32248 const have_comptime_val = field_val != .none;
31419 .no, .wip => return false,32249 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty.toType())) {
31420 .yes => return true,32250 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;
31426 }32251 }
31427 if (requires_comptime) {32252 }
31428 struct_obj.requires_comptime = .yes;32253 return false;
31429 } else {32254 },
31430 struct_obj.requires_comptime = .no;
31431 }
31432 return requires_comptime;
31433 },
31434 }
31435 },
3143632255
31437 .@"union", .union_safety_tagged, .union_tagged => {32256 .union_type => |union_type| {
31438 const union_obj = ty.cast(Type.Payload.Union).?.data;32257 const union_obj = mod.unionPtr(union_type.index);
31439 switch (union_obj.requires_comptime) {32258 switch (union_obj.requires_comptime) {
31440 .no, .wip => return false,32259 .no, .wip => return false,
31441 .yes => return true,32260 .yes => return true,
31442 .unknown => {32261 .unknown => {
31443 var requires_comptime = false;32262 var requires_comptime = false;
31444 union_obj.requires_comptime = .wip;32263 union_obj.requires_comptime = .wip;
31445 for (union_obj.fields.values()) |field| {32264 for (union_obj.fields.values()) |field| {
31446 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;32265 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31447 }32266 }
31448 if (requires_comptime) {32267 if (requires_comptime) {
31449 union_obj.requires_comptime = .yes;32268 union_obj.requires_comptime = .yes;
31450 } else {32269 } else {
31451 union_obj.requires_comptime = .no;32270 union_obj.requires_comptime = .no;
31452 }32271 }
31453 return requires_comptime;32272 return requires_comptime;
31454 },32273 },
31455 }32274 }
31456 },32275 },
3145732276
31458 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),32277 .opaque_type => false,
31459 .anyframe_T => {32278
31460 const child_ty = ty.castTag(.anyframe_T).?.data;32279 .enum_type => |enum_type| try sema.resolveTypeRequiresComptime(enum_type.tag_ty.toType()),
31461 return sema.resolveTypeRequiresComptime(child_ty);32280
31462 },32281 // values, not types
31463 .enum_numbered => {32282 .undef,
31464 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;32283 .runtime_value,
31465 return sema.resolveTypeRequiresComptime(tag_ty);32284 .simple_value,
31466 },32285 .variable,
31467 .enum_full, .enum_nonexhaustive => {32286 .extern_func,
31468 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;32287 .func,
31469 return sema.resolveTypeRequiresComptime(tag_ty);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,
31470 },32302 },
31471 };32303 };
31472}32304}
...@@ -31474,40 +32306,38 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31474,40 +32306,38 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31474/// Returns `error.AnalysisFail` if any of the types (recursively) failed to32306/// Returns `error.AnalysisFail` if any of the types (recursively) failed to
31475/// be resolved.32307/// be resolved.
31476pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {32308pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
31477 switch (ty.zigTypeTag()) {32309 const mod = sema.mod;
32310 switch (ty.zigTypeTag(mod)) {
31478 .Pointer => {32311 .Pointer => {
31479 const child_ty = try sema.resolveTypeFields(ty.childType());32312 const child_ty = try sema.resolveTypeFields(ty.childType(mod));
31480 return sema.resolveTypeFully(child_ty);32313 return sema.resolveTypeFully(child_ty);
31481 },32314 },
31482 .Struct => switch (ty.tag()) {32315 .Struct => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
31483 .@"struct" => return sema.resolveStructFully(ty),32316 .struct_type => return sema.resolveStructFully(ty),
31484 .tuple, .anon_struct => {32317 .anon_struct_type => |tuple| {
31485 const tuple = ty.tupleFields();
31486
31487 for (tuple.types) |field_ty| {32318 for (tuple.types) |field_ty| {
31488 try sema.resolveTypeFully(field_ty);32319 try sema.resolveTypeFully(field_ty.toType());
31489 }32320 }
31490 },32321 },
31491 else => {},32322 else => {},
31492 },32323 },
31493 .Union => return sema.resolveUnionFully(ty),32324 .Union => return sema.resolveUnionFully(ty),
31494 .Array => return sema.resolveTypeFully(ty.childType()),32325 .Array => return sema.resolveTypeFully(ty.childType(mod)),
31495 .Optional => {32326 .Optional => {
31496 var buf: Type.Payload.ElemType = undefined;32327 return sema.resolveTypeFully(ty.optionalChild(mod));
31497 return sema.resolveTypeFully(ty.optionalChild(&buf));
31498 },32328 },
31499 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload()),32329 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload(mod)),
31500 .Fn => {32330 .Fn => {
31501 const info = ty.fnInfo();32331 const info = mod.typeToFunc(ty).?;
31502 if (info.is_generic) {32332 if (info.is_generic) {
31503 // Resolving of generic function types is deferred to when32333 // Resolving of generic function types is deferred to when
31504 // the function is instantiated.32334 // the function is instantiated.
31505 return;32335 return;
31506 }32336 }
31507 for (info.param_types) |param_ty| {32337 for (info.param_types) |param_ty| {
31508 try sema.resolveTypeFully(param_ty);32338 try sema.resolveTypeFully(param_ty.toType());
31509 }32339 }
31510 try sema.resolveTypeFully(info.return_type);32340 try sema.resolveTypeFully(info.return_type.toType());
31511 },32341 },
31512 else => {},32342 else => {},
31513 }32343 }
...@@ -31516,9 +32346,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -31516,9 +32346,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
31516fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {32346fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
31517 try sema.resolveStructLayout(ty);32347 try sema.resolveStructLayout(ty);
3151832348
32349 const mod = sema.mod;
31519 const resolved_ty = try sema.resolveTypeFields(ty);32350 const resolved_ty = try sema.resolveTypeFields(ty);
31520 const payload = resolved_ty.castTag(.@"struct").?;32351 const struct_obj = mod.typeToStruct(resolved_ty).?;
31521 const struct_obj = payload.data;
3152232352
31523 switch (struct_obj.status) {32353 switch (struct_obj.status) {
31524 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},32354 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
...@@ -31546,8 +32376,9 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {...@@ -31546,8 +32376,9 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
31546fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {32376fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
31547 try sema.resolveUnionLayout(ty);32377 try sema.resolveUnionLayout(ty);
3154832378
32379 const mod = sema.mod;
31549 const resolved_ty = try sema.resolveTypeFields(ty);32380 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).?;
31551 switch (union_obj.status) {32382 switch (union_obj.status) {
31552 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},32383 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
31553 .fully_resolved_wip, .fully_resolved => return,32384 .fully_resolved_wip, .fully_resolved => return,
...@@ -31572,30 +32403,111 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {...@@ -31572,30 +32403,111 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
31572}32403}
3157332404
31574pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {32405pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
31575 switch (ty.tag()) {32406 const mod = sema.mod;
31576 .@"struct" => {32407
31577 const struct_obj = ty.castTag(.@"struct").?.data;32408 switch (ty.toIntern()) {
31578 try sema.resolveTypeFieldsStruct(ty, struct_obj);32409 .var_args_param_type => unreachable,
31579 return ty;32410
31580 },32411 .none => unreachable,
31581 .@"union", .union_safety_tagged, .union_tagged => {32412
31582 const union_obj = ty.cast(Type.Payload.Union).?.data;32413 .u1_type,
31583 try sema.resolveTypeFieldsUnion(ty, union_obj);32414 .u8_type,
31584 return ty;32415 .i8_type,
31585 },32416 .u16_type,
31586 .type_info => return sema.getBuiltinType("Type"),32417 .i16_type,
31587 .extern_options => return sema.getBuiltinType("ExternOptions"),32418 .u29_type,
31588 .export_options => return sema.getBuiltinType("ExportOptions"),32419 .u32_type,
31589 .atomic_order => return sema.getBuiltinType("AtomicOrder"),32420 .i32_type,
31590 .atomic_rmw_op => return sema.getBuiltinType("AtomicRmwOp"),32421 .u64_type,
31591 .calling_convention => return sema.getBuiltinType("CallingConvention"),32422 .i64_type,
31592 .address_space => return sema.getBuiltinType("AddressSpace"),32423 .u80_type,
31593 .float_mode => return sema.getBuiltinType("FloatMode"),32424 .u128_type,
31594 .reduce_op => return sema.getBuiltinType("ReduceOp"),32425 .i128_type,
31595 .modifier => return sema.getBuiltinType("CallModifier"),32426 .usize_type,
31596 .prefetch_options => return sema.getBuiltinType("PrefetchOptions"),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 },
31599 }32511 }
31600}32512}
3160132513
...@@ -31682,35 +32594,39 @@ fn resolveInferredErrorSet(...@@ -31682,35 +32594,39 @@ fn resolveInferredErrorSet(
31682 sema: *Sema,32594 sema: *Sema,
31683 block: *Block,32595 block: *Block,
31684 src: LazySrcLoc,32596 src: LazySrcLoc,
31685 ies: *Module.Fn.InferredErrorSet,32597 ies_index: Module.Fn.InferredErrorSet.Index,
31686) CompileError!void {32598) CompileError!void {
32599 const mod = sema.mod;
32600 const ies = mod.inferredErrorSetPtr(ies_index);
32601
31687 if (ies.is_resolved) return;32602 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) {
31690 return sema.fail(block, src, "unable to resolve inferred error set", .{});32606 return sema.fail(block, src, "unable to resolve inferred error set", .{});
31691 }32607 }
3169232608
31693 // In order to ensure that all dependencies are properly added to the set, we32609 // In order to ensure that all dependencies are properly added to the set, we
31694 // need to ensure the function body is analyzed of the inferred error set.32610 // need to ensure the function body is analyzed of the inferred error set.
31695 // However, in the case of comptime/inline function calls with inferred error sets,32611 // 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 same32612 // each call gets a new InferredErrorSet object, which contains the same
31697 // `*Module.Fn`. Not only is the function not relevant to the inferred error set32613 // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set
31698 // in this case, it may be a generic function which would cause an assertion failure32614 // in this case, it may be a generic function which would cause an assertion failure
31699 // if we called `ensureFuncBodyAnalyzed` on it here.32615 // if we called `ensureFuncBodyAnalyzed` on it here.
31700 const ies_func_owner_decl = sema.mod.declPtr(ies.func.owner_decl);32616 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
31701 const ies_func_info = ies_func_owner_decl.ty.fnInfo();32617 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
31702 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,32618 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
31703 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,32619 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
31704 // so here we can simply skip this case.32620 // 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) {
31706 assert(ies_func_info.cc == .Inline);32622 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) {
31708 if (ies_func_info.is_generic) {32624 if (ies_func_info.is_generic) {
31709 const msg = msg: {32625 const msg = msg: {
31710 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});32626 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});
31711 errdefer msg.destroy(sema.gpa);32627 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", .{});
31714 break :msg msg;32630 break :msg msg;
31715 };32631 };
31716 return sema.failWithOwnedErrorMsg(msg);32632 return sema.failWithOwnedErrorMsg(msg);
...@@ -31722,10 +32638,11 @@ fn resolveInferredErrorSet(...@@ -31722,10 +32638,11 @@ fn resolveInferredErrorSet(
3172232638
31723 ies.is_resolved = true;32639 ies.is_resolved = true;
3172432640
31725 for (ies.inferred_error_sets.keys()) |other_ies| {32641 for (ies.inferred_error_sets.keys()) |other_ies_index| {
31726 if (ies == other_ies) continue;32642 if (ies_index == other_ies_index) continue;
31727 try sema.resolveInferredErrorSet(block, src, other_ies);32643 try sema.resolveInferredErrorSet(block, src, other_ies_index);
3172832644
32645 const other_ies = mod.inferredErrorSetPtr(other_ies_index);
31729 for (other_ies.errors.keys()) |key| {32646 for (other_ies.errors.keys()) |key| {
31730 try ies.errors.put(sema.gpa, key, {});32647 try ies.errors.put(sema.gpa, key, {});
31731 }32648 }
...@@ -31740,15 +32657,17 @@ fn resolveInferredErrorSetTy(...@@ -31740,15 +32657,17 @@ fn resolveInferredErrorSetTy(
31740 src: LazySrcLoc,32657 src: LazySrcLoc,
31741 ty: Type,32658 ty: Type,
31742) CompileError!void {32659) CompileError!void {
31743 if (ty.castTag(.error_set_inferred)) |inferred| {32660 const mod = sema.mod;
31744 try sema.resolveInferredErrorSet(block, src, inferred.data);32661 if (mod.typeToInferredErrorSetIndex(ty).unwrap()) |ies_index| {
32662 try sema.resolveInferredErrorSet(block, src, ies_index);
31745 }32663 }
31746}32664}
3174732665
31748fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void {32666fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void {
31749 const gpa = mod.gpa;32667 const gpa = mod.gpa;
32668 const ip = &mod.intern_pool;
31750 const decl_index = struct_obj.owner_decl;32669 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;
31752 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;32671 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
31753 assert(extended.opcode == .struct_decl);32672 assert(extended.opcode == .struct_decl);
31754 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);32673 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
...@@ -31794,35 +32713,37 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31794,35 +32713,37 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31794 }32713 }
3179532714
31796 const decl = mod.declPtr(decl_index);32715 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
31801 var analysis_arena = std.heap.ArenaAllocator.init(gpa);32717 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
31802 defer analysis_arena.deinit();32718 defer analysis_arena.deinit();
3180332719
32720 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
32721 defer comptime_mutable_decls.deinit();
32722
31804 var sema: Sema = .{32723 var sema: Sema = .{
31805 .mod = mod,32724 .mod = mod,
31806 .gpa = gpa,32725 .gpa = gpa,
31807 .arena = analysis_arena.allocator(),32726 .arena = analysis_arena.allocator(),
31808 .perm_arena = decl_arena_allocator,
31809 .code = zir,32727 .code = zir,
31810 .owner_decl = decl,32728 .owner_decl = decl,
31811 .owner_decl_index = decl_index,32729 .owner_decl_index = decl_index,
31812 .func = null,32730 .func = null,
32731 .func_index = .none,
31813 .fn_ret_ty = Type.void,32732 .fn_ret_ty = Type.void,
31814 .owner_func = null,32733 .owner_func = null,
32734 .owner_func_index = .none,
32735 .comptime_mutable_decls = &comptime_mutable_decls,
31815 };32736 };
31816 defer sema.deinit();32737 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);
31819 defer wip_captures.deinit();32740 defer wip_captures.deinit();
3182032741
31821 var block_scope: Block = .{32742 var block_scope: Block = .{
31822 .parent = null,32743 .parent = null,
31823 .sema = &sema,32744 .sema = &sema,
31824 .src_decl = decl_index,32745 .src_decl = decl_index,
31825 .namespace = &struct_obj.namespace,32746 .namespace = struct_obj.namespace,
31826 .wip_capture_scope = wip_captures.scope,32747 .wip_capture_scope = wip_captures.scope,
31827 .instructions = .{},32748 .instructions = .{},
31828 .inlining = null,32749 .inlining = null,
...@@ -31834,13 +32755,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31834,13 +32755,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31834 }32755 }
3183532756
31836 struct_obj.fields = .{};32757 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
31839 const Field = struct {32760 const Field = struct {
31840 type_body_len: u32 = 0,32761 type_body_len: u32 = 0,
31841 align_body_len: u32 = 0,32762 align_body_len: u32 = 0,
31842 init_body_len: u32 = 0,32763 init_body_len: u32 = 0,
31843 type_ref: Air.Inst.Ref = .none,32764 type_ref: Zir.Inst.Ref = .none,
31844 };32765 };
31845 const fields = try sema.arena.alloc(Field, fields_len);32766 const fields = try sema.arena.alloc(Field, fields_len);
31846 var any_inits = false;32767 var any_inits = false;
...@@ -31885,30 +32806,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31885,30 +32806,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31885 extra_index += 1;32806 extra_index += 1;
3188632807
31887 // This string needs to outlive the ZIR code.32808 // This string needs to outlive the ZIR code.
31888 const field_name = if (field_name_zir) |some|32809 const field_name = try ip.getOrPutString(gpa, if (field_name_zir) |s|
31889 try decl_arena_allocator.dupe(u8, some)32810 s
31890 else32811 else
31891 try std.fmt.allocPrint(decl_arena_allocator, "{d}", .{field_i});32812 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}));
3189232813
31893 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);32814 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
31894 if (gop.found_existing) {32815 if (gop.found_existing) {
31895 const msg = msg: {32816 const msg = msg: {
31896 const field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;32817 const field_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{ .index = field_i }).lazy;
31897 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});32818 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{}'", .{field_name.fmt(ip)});
31898 errdefer msg.destroy(gpa);32819 errdefer msg.destroy(gpa);
3189932820
31900 const prev_field_index = struct_obj.fields.getIndex(field_name).?;32821 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
31901 const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index });32822 const prev_field_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{ .index = prev_field_index });
31902 try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});32823 try mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
31903 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});32824 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
31904 break :msg msg;32825 break :msg msg;
31905 };32826 };
31906 return sema.failWithOwnedErrorMsg(msg);32827 return sema.failWithOwnedErrorMsg(msg);
31907 }32828 }
31908 gop.value_ptr.* = .{32829 gop.value_ptr.* = .{
31909 .ty = Type.initTag(.noreturn),32830 .ty = Type.noreturn,
31910 .abi_align = 0,32831 .abi_align = 0,
31911 .default_val = Value.initTag(.unreachable_value),32832 .default_val = .none,
31912 .is_comptime = is_comptime,32833 .is_comptime = is_comptime,
31913 .offset = undefined,32834 .offset = undefined,
31914 };32835 };
...@@ -31934,7 +32855,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31934,7 +32855,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31934 if (zir_field.type_ref != .none) {32855 if (zir_field.type_ref != .none) {
31935 break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) {32856 break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) {
31936 error.NeededSourceLocation => {32857 error.NeededSourceLocation => {
31937 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{32858 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
31938 .index = field_i,32859 .index = field_i,
31939 .range = .type,32860 .range = .type,
31940 }).lazy;32861 }).lazy;
...@@ -31950,7 +32871,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31950,7 +32871,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31950 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);32871 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
31951 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {32872 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
31952 error.NeededSourceLocation => {32873 error.NeededSourceLocation => {
31953 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{32874 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
31954 .index = field_i,32875 .index = field_i,
31955 .range = .type,32876 .range = .type,
31956 }).lazy;32877 }).lazy;
...@@ -31960,16 +32881,16 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31960,16 +32881,16 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31960 else => |e| return e,32881 else => |e| return e,
31961 };32882 };
31962 };32883 };
31963 if (field_ty.tag() == .generic_poison) {32884 if (field_ty.isGenericPoison()) {
31964 return error.GenericPoison;32885 return error.GenericPoison;
31965 }32886 }
3196632887
31967 const field = &struct_obj.fields.values()[field_i];32888 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) {
31971 const msg = msg: {32892 const msg = msg: {
31972 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{32893 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
31973 .index = field_i,32894 .index = field_i,
31974 .range = .type,32895 .range = .type,
31975 }).lazy;32896 }).lazy;
...@@ -31981,9 +32902,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31981,9 +32902,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31981 };32902 };
31982 return sema.failWithOwnedErrorMsg(msg);32903 return sema.failWithOwnedErrorMsg(msg);
31983 }32904 }
31984 if (field_ty.zigTypeTag() == .NoReturn) {32905 if (field_ty.zigTypeTag(mod) == .NoReturn) {
31985 const msg = msg: {32906 const msg = msg: {
31986 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{32907 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
31987 .index = field_i,32908 .index = field_i,
31988 .range = .type,32909 .range = .type,
31989 }).lazy;32910 }).lazy;
...@@ -31997,11 +32918,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -31997,11 +32918,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
31997 }32918 }
31998 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {32919 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {
31999 const msg = msg: {32920 const msg = msg: {
32000 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{32921 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
32001 .index = field_i,32922 .index = field_i,
32002 .range = .type,32923 .range = .type,
32003 });32924 });
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)});
32005 errdefer msg.destroy(sema.gpa);32926 errdefer msg.destroy(sema.gpa);
3200632927
32007 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);32928 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);
...@@ -32010,13 +32931,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -32010,13 +32931,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
32010 break :msg msg;32931 break :msg msg;
32011 };32932 };
32012 return sema.failWithOwnedErrorMsg(msg);32933 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))) {
32014 const msg = msg: {32935 const msg = msg: {
32015 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{32936 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
32016 .index = field_i,32937 .index = field_i,
32017 .range = .type,32938 .range = .type,
32018 });32939 });
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)});
32020 errdefer msg.destroy(sema.gpa);32941 errdefer msg.destroy(sema.gpa);
3202132942
32022 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);32943 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);
...@@ -32033,7 +32954,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -32033,7 +32954,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
32033 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);32954 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
32034 field.abi_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {32955 field.abi_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
32035 error.NeededSourceLocation => {32956 error.NeededSourceLocation => {
32036 const align_src = struct_obj.fieldSrcLoc(sema.mod, .{32957 const align_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
32037 .index = field_i,32958 .index = field_i,
32038 .range = .alignment,32959 .range = .alignment,
32039 }).lazy;32960 }).lazy;
...@@ -32061,7 +32982,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -32061,7 +32982,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
32061 const field = &struct_obj.fields.values()[field_i];32982 const field = &struct_obj.fields.values()[field_i];
32062 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {32983 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {
32063 error.NeededSourceLocation => {32984 error.NeededSourceLocation => {
32064 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{32985 const init_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
32065 .index = field_i,32986 .index = field_i,
32066 .range = .value,32987 .range = .value,
32067 }).lazy;32988 }).lazy;
...@@ -32071,17 +32992,21 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -32071,17 +32992,21 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
32071 else => |e| return e,32992 else => |e| return e,
32072 };32993 };
32073 const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {32994 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, .{
32075 .index = field_i,32996 .index = field_i,
32076 .range = .value,32997 .range = .value,
32077 }).lazy;32998 }).lazy;
32078 return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");32999 return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");
32079 };33000 };
32080 field.default_val = try default_val.copy(decl_arena_allocator);33001 field.default_val = try default_val.intern(field.ty, mod);
32081 }33002 }
32082 }33003 }
32083 }33004 }
32084 try wip_captures.finalize();33005 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
32086 struct_obj.have_field_inits = true;33011 struct_obj.have_field_inits = true;
32087}33012}
...@@ -32091,8 +33016,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32091,8 +33016,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32091 defer tracy.end();33016 defer tracy.end();
3209233017
32093 const gpa = mod.gpa;33018 const gpa = mod.gpa;
33019 const ip = &mod.intern_pool;
32094 const decl_index = union_obj.owner_decl;33020 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;
32096 const extended = zir.instructions.items(.data)[union_obj.zir_index].extended;33022 const extended = zir.instructions.items(.data)[union_obj.zir_index].extended;
32097 assert(extended.opcode == .union_decl);33023 assert(extended.opcode == .union_decl);
32098 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);33024 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
...@@ -32134,35 +33060,37 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32134,35 +33060,37 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32134 extra_index += body.len;33060 extra_index += body.len;
3213533061
32136 const decl = mod.declPtr(decl_index);33062 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
32141 var analysis_arena = std.heap.ArenaAllocator.init(gpa);33064 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
32142 defer analysis_arena.deinit();33065 defer analysis_arena.deinit();
3214333066
33067 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
33068 defer comptime_mutable_decls.deinit();
33069
32144 var sema: Sema = .{33070 var sema: Sema = .{
32145 .mod = mod,33071 .mod = mod,
32146 .gpa = gpa,33072 .gpa = gpa,
32147 .arena = analysis_arena.allocator(),33073 .arena = analysis_arena.allocator(),
32148 .perm_arena = decl_arena_allocator,
32149 .code = zir,33074 .code = zir,
32150 .owner_decl = decl,33075 .owner_decl = decl,
32151 .owner_decl_index = decl_index,33076 .owner_decl_index = decl_index,
32152 .func = null,33077 .func = null,
33078 .func_index = .none,
32153 .fn_ret_ty = Type.void,33079 .fn_ret_ty = Type.void,
32154 .owner_func = null,33080 .owner_func = null,
33081 .owner_func_index = .none,
33082 .comptime_mutable_decls = &comptime_mutable_decls,
32155 };33083 };
32156 defer sema.deinit();33084 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);
32159 defer wip_captures.deinit();33087 defer wip_captures.deinit();
3216033088
32161 var block_scope: Block = .{33089 var block_scope: Block = .{
32162 .parent = null,33090 .parent = null,
32163 .sema = &sema,33091 .sema = &sema,
32164 .src_decl = decl_index,33092 .src_decl = decl_index,
32165 .namespace = &union_obj.namespace,33093 .namespace = union_obj.namespace,
32166 .wip_capture_scope = wip_captures.scope,33094 .wip_capture_scope = wip_captures.scope,
32167 .instructions = .{},33095 .instructions = .{},
32168 .inlining = null,33096 .inlining = null,
...@@ -32178,66 +33106,61 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32178,66 +33106,61 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32178 }33106 }
3217933107
32180 try wip_captures.finalize();33108 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
32184 var int_tag_ty: Type = undefined;33116 var int_tag_ty: Type = undefined;
32185 var enum_field_names: ?*Module.EnumNumbered.NameMap = null;33117 var enum_field_names: []InternPool.NullTerminatedString = &.{};
32186 var enum_value_map: ?*Module.EnumNumbered.ValueMap = null;33118 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};
32187 var tag_ty_field_names: ?Module.EnumFull.NameMap = null;33119 var explicit_tags_seen: []bool = &.{};
32188 if (tag_type_ref != .none) {33120 if (tag_type_ref != .none) {
32189 const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };33121 const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };
32190 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);33122 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
32191 if (small.auto_enum_tag) {33123 if (small.auto_enum_tag) {
32192 // The provided type is an integer type and we must construct the enum tag type here.33124 // The provided type is an integer type and we must construct the enum tag type here.
32193 int_tag_ty = provided_ty;33125 int_tag_ty = provided_ty;
32194 if (int_tag_ty.zigTypeTag() != .Int and int_tag_ty.zigTypeTag() != .ComptimeInt) {33126 if (int_tag_ty.zigTypeTag(mod) != .Int and int_tag_ty.zigTypeTag(mod) != .ComptimeInt) {
32195 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(sema.mod)});33127 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(mod)});
32196 }33128 }
3219733129
32198 if (fields_len > 0) {33130 if (fields_len > 0) {
32199 var field_count_val: Value.Payload.U64 = .{33131 const field_count_val = try mod.intValue(Type.comptime_int, fields_len - 1);
32200 .base = .{ .tag = .int_u64 },33132 if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) {
32201 .data = fields_len - 1,
32202 };
32203 if (!(try sema.intFitsInType(Value.initPayload(&field_count_val.base), int_tag_ty, null))) {
32204 const msg = msg: {33133 const msg = msg: {
32205 const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{});33134 const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{});
32206 errdefer msg.destroy(sema.gpa);33135 errdefer msg.destroy(sema.gpa);
32207 try sema.errNote(&block_scope, tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{33136 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),
32209 fields_len - 1,33138 fields_len - 1,
32210 });33139 });
32211 break :msg msg;33140 break :msg msg;
32212 };33141 };
32213 return sema.failWithOwnedErrorMsg(msg);33142 return sema.failWithOwnedErrorMsg(msg);
32214 }33143 }
33144 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
33145 try enum_field_vals.ensureTotalCapacity(sema.arena, fields_len);
32215 }33146 }
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;
32220 } else {33147 } else {
32221 // The provided type is the enum tag type.33148 // The provided type is the enum tag type.
32222 union_obj.tag_ty = try provided_ty.copy(decl_arena_allocator);33149 union_obj.tag_ty = provided_ty;
32223 if (union_obj.tag_ty.zigTypeTag() != .Enum) {33150 const enum_type = switch (ip.indexToKey(union_obj.tag_ty.toIntern())) {
32224 return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)});33151 .enum_type => |x| x,
32225 }33152 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(mod)}),
33153 };
32226 // The fields of the union must match the enum exactly.33154 // The fields of the union must match the enum exactly.
32227 // Store a copy of the enum field names so we can check for33155 // A flag per field is used to check for missing and extraneous fields.
32228 // missing or extraneous fields later.33156 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
32229 tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena);33157 @memset(explicit_tags_seen, false);
32230 }33158 }
32231 } else {33159 } else {
32232 // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis33160 // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis
32233 // purposes, we still auto-generate an enum tag type the same way. That the union is33161 // purposes, we still auto-generate an enum tag type the same way. That the union is
32234 // untagged is represented by the Type tag (union vs union_tagged).33162 // 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);33163 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
32236 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
32237 }
32238
32239 if (fields_len == 0) {
32240 return;
32241 }33164 }
3224233165
32243 const bits_per_field = 4;33166 const bits_per_field = 4;
...@@ -32281,17 +33204,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32281,17 +33204,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32281 break :blk align_ref;33204 break :blk align_ref;
32282 } else .none;33205 } 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: {
32285 const tag_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);33208 const tag_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
32286 extra_index += 1;33209 extra_index += 1;
32287 break :blk try sema.resolveInst(tag_ref);33210 break :blk try sema.resolveInst(tag_ref);
32288 } else .none;33211 } else .none;
3228933212
32290 if (enum_value_map) |map| {33213 if (enum_field_vals.capacity() > 0) {
32291 const copied_val = if (tag_ref != .none) blk: {33214 const enum_tag_val = if (tag_ref != .none) blk: {
32292 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {33215 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
32293 error.NeededSourceLocation => {33216 error.NeededSourceLocation => {
32294 const val_src = union_obj.fieldSrcLoc(sema.mod, .{33217 const val_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
32295 .index = field_i,33218 .index = field_i,
32296 .range = .value,33219 .range = .value,
32297 }).lazy;33220 }).lazy;
...@@ -32302,27 +33225,22 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32302,27 +33225,22 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32302 };33225 };
32303 last_tag_val = val;33226 last_tag_val = val;
3230433227
32305 // This puts the memory into the union arena, not the enum arena, but33228 break :blk val;
32306 // it is OK since they share the same lifetime.
32307 break :blk try val.copy(decl_arena_allocator);
32308 } else blk: {33229 } else blk: {
32309 const val = if (last_tag_val) |val|33230 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)
32311 else33232 else
32312 Value.zero;33233 try mod.intValue(int_tag_ty, 0);
32313 last_tag_val = val;33234 last_tag_val = val;
3231433235
32315 break :blk try val.copy(decl_arena_allocator);33236 break :blk val;
32316 };33237 };
32317 const gop = map.getOrPutAssumeCapacityContext(copied_val, .{33238 const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern());
32318 .ty = int_tag_ty,
32319 .mod = mod,
32320 });
32321 if (gop.found_existing) {33239 if (gop.found_existing) {
32322 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;33240 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
32323 const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = gop.index }).lazy;33241 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;
32324 const msg = msg: {33242 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)});
32326 errdefer msg.destroy(gpa);33244 errdefer msg.destroy(gpa);
32327 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});33245 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
32328 break :msg msg;33246 break :msg msg;
...@@ -32332,19 +33250,19 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32332,19 +33250,19 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32332 }33250 }
3233333251
32334 // This string needs to outlive the ZIR code.33252 // This string needs to outlive the ZIR code.
32335 const field_name = try decl_arena_allocator.dupe(u8, field_name_zir);33253 const field_name = try ip.getOrPutString(gpa, field_name_zir);
32336 if (enum_field_names) |set| {33254 if (enum_field_names.len != 0) {
32337 set.putAssumeCapacity(field_name, {});33255 enum_field_names[field_i] = field_name;
32338 }33256 }
3233933257
32340 const field_ty: Type = if (!has_type)33258 const field_ty: Type = if (!has_type)
32341 Type.void33259 Type.void
32342 else if (field_type_ref == .none)33260 else if (field_type_ref == .none)
32343 Type.initTag(.noreturn)33261 Type.noreturn
32344 else33262 else
32345 sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {33263 sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {
32346 error.NeededSourceLocation => {33264 error.NeededSourceLocation => {
32347 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{33265 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
32348 .index = field_i,33266 .index = field_i,
32349 .range = .type,33267 .range = .type,
32350 }).lazy;33268 }).lazy;
...@@ -32354,46 +33272,54 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32354,46 +33272,54 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32354 else => |e| return e,33272 else => |e| return e,
32355 };33273 };
3235633274
32357 if (field_ty.tag() == .generic_poison) {33275 if (field_ty.isGenericPoison()) {
32358 return error.GenericPoison;33276 return error.GenericPoison;
32359 }33277 }
3236033278
32361 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);33279 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
32362 if (gop.found_existing) {33280 if (gop.found_existing) {
32363 const msg = msg: {33281 const msg = msg: {
32364 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;33282 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
32365 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});33283 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{}'", .{
33284 field_name.fmt(ip),
33285 });
32366 errdefer msg.destroy(gpa);33286 errdefer msg.destroy(gpa);
3236733287
32368 const prev_field_index = union_obj.fields.getIndex(field_name).?;33288 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;33289 const prev_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = prev_field_index }).lazy;
32370 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});33290 try mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl, mod), msg, "other field here", .{});
32371 try sema.errNote(&block_scope, src, msg, "union declared here", .{});33291 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
32372 break :msg msg;33292 break :msg msg;
32373 };33293 };
32374 return sema.failWithOwnedErrorMsg(msg);33294 return sema.failWithOwnedErrorMsg(msg);
32375 }33295 }
3237633296
32377 if (tag_ty_field_names) |*names| {33297 if (explicit_tags_seen.len > 0) {
32378 const enum_has_field = names.orderedRemove(field_name);33298 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
32379 if (!enum_has_field) {33299 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
32380 const msg = msg: {33300 const msg = msg: {
32381 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{33301 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
32382 .index = field_i,33302 .index = field_i,
32383 .range = .type,33303 .range = .type,
32384 }).lazy;33304 }).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 });
32386 errdefer msg.destroy(sema.gpa);33308 errdefer msg.destroy(sema.gpa);
32387 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);33309 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
32388 break :msg msg;33310 break :msg msg;
32389 };33311 };
32390 return sema.failWithOwnedErrorMsg(msg);33312 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;
32392 }33318 }
3239333319
32394 if (field_ty.zigTypeTag() == .Opaque) {33320 if (field_ty.zigTypeTag(mod) == .Opaque) {
32395 const msg = msg: {33321 const msg = msg: {
32396 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{33322 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
32397 .index = field_i,33323 .index = field_i,
32398 .range = .type,33324 .range = .type,
32399 }).lazy;33325 }).lazy;
...@@ -32407,11 +33333,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32407,11 +33333,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32407 }33333 }
32408 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {33334 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
32409 const msg = msg: {33335 const msg = msg: {
32410 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{33336 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
32411 .index = field_i,33337 .index = field_i,
32412 .range = .type,33338 .range = .type,
32413 });33339 });
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)});
32415 errdefer msg.destroy(sema.gpa);33341 errdefer msg.destroy(sema.gpa);
3241633342
32417 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);33343 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);
...@@ -32420,13 +33346,13 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32420,13 +33346,13 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32420 break :msg msg;33346 break :msg msg;
32421 };33347 };
32422 return sema.failWithOwnedErrorMsg(msg);33348 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))) {
32424 const msg = msg: {33350 const msg = msg: {
32425 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{33351 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
32426 .index = field_i,33352 .index = field_i,
32427 .range = .type,33353 .range = .type,
32428 });33354 });
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)});
32430 errdefer msg.destroy(sema.gpa);33356 errdefer msg.destroy(sema.gpa);
3243133357
32432 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);33358 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
...@@ -32438,14 +33364,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32438,14 +33364,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32438 }33364 }
3243933365
32440 gop.value_ptr.* = .{33366 gop.value_ptr.* = .{
32441 .ty = try field_ty.copy(decl_arena_allocator),33367 .ty = field_ty,
32442 .abi_align = 0,33368 .abi_align = 0,
32443 };33369 };
3244433370
32445 if (align_ref != .none) {33371 if (align_ref != .none) {
32446 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {33372 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
32447 error.NeededSourceLocation => {33373 error.NeededSourceLocation => {
32448 const align_src = union_obj.fieldSrcLoc(sema.mod, .{33374 const align_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
32449 .index = field_i,33375 .index = field_i,
32450 .range = .alignment,33376 .range = .alignment,
32451 }).lazy;33377 }).lazy;
...@@ -32459,22 +33385,29 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32459,22 +33385,29 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32459 }33385 }
32460 }33386 }
3246133387
32462 if (tag_ty_field_names) |names| {33388 if (explicit_tags_seen.len > 0) {
32463 if (names.count() > 0) {33389 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
33390 if (tag_info.names.len > fields_len) {
32464 const msg = msg: {33391 const msg = msg: {
32465 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});33392 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});
32466 errdefer msg.destroy(sema.gpa);33393 errdefer msg.destroy(sema.gpa);
3246733394
32468 const enum_ty = union_obj.tag_ty;33395 const enum_ty = union_obj.tag_ty;
32469 for (names.keys()) |field_name| {33396 for (tag_info.names, 0..) |field_name, field_index| {
32470 const field_index = enum_ty.enumFieldIndex(field_name).?;33397 if (explicit_tags_seen[field_index]) continue;
32471 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});33398 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
33399 field_name.fmt(ip),
33400 });
32472 }33401 }
32473 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);33402 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
32474 break :msg msg;33403 break :msg msg;
32475 };33404 };
32476 return sema.failWithOwnedErrorMsg(msg);33405 return sema.failWithOwnedErrorMsg(msg);
32477 }33406 }
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);
32478 }33411 }
32479}33412}
3248033413
...@@ -32486,116 +33419,103 @@ fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Ty...@@ -32486,116 +33419,103 @@ fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Ty
32486fn generateUnionTagTypeNumbered(33419fn generateUnionTagTypeNumbered(
32487 sema: *Sema,33420 sema: *Sema,
32488 block: *Block,33421 block: *Block,
32489 fields_len: u32,33422 enum_field_names: []const InternPool.NullTerminatedString,
32490 int_ty: Type,33423 enum_field_vals: []const InternPool.Index,
32491 union_obj: *Module.Union,33424 union_obj: *Module.Union,
32492) !Type {33425) !Type {
32493 const mod = sema.mod;33426 const mod = sema.mod;
3249433427 const gpa = sema.gpa;
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);
3250733428
32508 const src_decl = mod.declPtr(block.src_decl);33429 const src_decl = mod.declPtr(block.src_decl);
32509 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);33430 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
32510 errdefer mod.destroyDecl(new_decl_index);33431 errdefer mod.destroyDecl(new_decl_index);
32511 const name = name: {33432 const fqn = try union_obj.getFullyQualifiedName(mod);
32512 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)});
32513 defer sema.gpa.free(fqn);
32514 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
32515 };
32516 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{33434 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
32517 .ty = Type.type,33435 .ty = Type.noreturn,
32518 .val = enum_val,33436 .val = Value.@"unreachable",
32519 }, name);33437 }, name);
32520 sema.mod.declPtr(new_decl_index).name_fully_qualified = true;33438 errdefer mod.abortAnonDecl(new_decl_index);
3252133439
32522 const new_decl = mod.declPtr(new_decl_index);33440 const new_decl = mod.declPtr(new_decl_index);
33441 new_decl.name_fully_qualified = true;
32523 new_decl.owns_tv = true;33442 new_decl.owns_tv = true;
32524 new_decl.name_fully_qualified = true;33443 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);33445 const enum_ty = try mod.intern(.{ .enum_type = .{
32528 enum_obj.* = .{33446 .decl = new_decl_index,
32529 .owner_decl = new_decl_index,33447 .namespace = .none,
32530 .tag_ty = copied_int_ty,33448 .tag_ty = if (enum_field_vals.len == 0)
32531 .fields = .{},33449 (try mod.intType(.unsigned, 0)).toIntern()
32532 .values = .{},33450 else
32533 };33451 mod.intern_pool.typeOf(enum_field_vals[0]),
32534 // Here we pre-allocate the maps using the decl arena.33452 .names = enum_field_names,
32535 try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);33453 .values = enum_field_vals,
32536 try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{33454 .tag_mode = .explicit,
32537 .ty = copied_int_ty,33455 } });
32538 .mod = mod,
32539 });
32540 try new_decl.finalizeNewArena(&new_decl_arena);
32541 return enum_ty;
32542}
3254333456
32544fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize, maybe_union_obj: ?*Module.Union) !Type {33457 new_decl.ty = Type.type;
32545 const mod = sema.mod;33458 new_decl.val = enum_ty.toValue();
3254633459
32547 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);33460 try mod.finalizeAnonDecl(new_decl_index);
32548 errdefer new_decl_arena.deinit();33461 return enum_ty.toType();
32549 const new_decl_arena_allocator = new_decl_arena.allocator();33462}
3255033463
32551 const enum_obj = try new_decl_arena_allocator.create(Module.EnumSimple);33464fn generateUnionTagTypeSimple(
32552 const enum_ty_payload = try new_decl_arena_allocator.create(Type.Payload.EnumSimple);33465 sema: *Sema,
32553 enum_ty_payload.* = .{33466 block: *Block,
32554 .base = .{ .tag = .enum_simple },33467 enum_field_names: []const InternPool.NullTerminatedString,
32555 .data = enum_obj,33468 maybe_union_obj: ?*Module.Union,
32556 };33469) !Type {
32557 const enum_ty = Type.initPayload(&enum_ty_payload.base);33470 const mod = sema.mod;
32558 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);33471 const gpa = sema.gpa;
3255933472
32560 const new_decl_index = new_decl_index: {33473 const new_decl_index = new_decl_index: {
32561 const union_obj = maybe_union_obj orelse {33474 const union_obj = maybe_union_obj orelse {
32562 break :new_decl_index try mod.createAnonymousDecl(block, .{33475 break :new_decl_index try mod.createAnonymousDecl(block, .{
32563 .ty = Type.type,33476 .ty = Type.noreturn,
32564 .val = enum_val,33477 .val = Value.@"unreachable",
32565 });33478 });
32566 };33479 };
32567 const src_decl = mod.declPtr(block.src_decl);33480 const src_decl = mod.declPtr(block.src_decl);
32568 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);33481 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
32569 errdefer mod.destroyDecl(new_decl_index);33482 errdefer mod.destroyDecl(new_decl_index);
32570 const name = name: {33483 const fqn = try union_obj.getFullyQualifiedName(mod);
32571 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)});
32572 defer sema.gpa.free(fqn);
32573 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
32574 };
32575 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{33485 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
32576 .ty = Type.type,33486 .ty = Type.noreturn,
32577 .val = enum_val,33487 .val = Value.@"unreachable",
32578 }, name);33488 }, name);
32579 sema.mod.declPtr(new_decl_index).name_fully_qualified = true;33489 mod.declPtr(new_decl_index).name_fully_qualified = true;
32580 break :new_decl_index new_decl_index;33490 break :new_decl_index new_decl_index;
32581 };33491 };
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
32583 const new_decl = mod.declPtr(new_decl_index);33506 const new_decl = mod.declPtr(new_decl_index);
32584 new_decl.owns_tv = true;33507 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.* = .{33511 try mod.finalizeAnonDecl(new_decl_index);
32588 .owner_decl = new_decl_index,33512 return enum_ty.toType();
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;
32595}33513}
3259633514
32597fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {33515fn 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);
32599 defer wip_captures.deinit();33519 defer wip_captures.deinit();
3260033520
32601 var block: Block = .{33521 var block: Block = .{
...@@ -32609,19 +33529,20 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {...@@ -32609,19 +33529,20 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
32609 .is_comptime = true,33529 .is_comptime = true,
32610 };33530 };
32611 defer {33531 defer {
32612 block.instructions.deinit(sema.gpa);33532 block.instructions.deinit(gpa);
32613 block.params.deinit(sema.gpa);33533 block.params.deinit(gpa);
32614 }33534 }
32615 const src = LazySrcLoc.nodeOffset(0);33535 const src = LazySrcLoc.nodeOffset(0);
3261633536
32617 const mod = sema.mod;33537 const mod = sema.mod;
33538 const ip = &mod.intern_pool;
32618 const std_pkg = mod.main_pkg.table.get("std").?;33539 const std_pkg = mod.main_pkg.table.get("std").?;
32619 const std_file = (mod.importPkg(std_pkg) catch unreachable).file;33540 const std_file = (mod.importPkg(std_pkg) catch unreachable).file;
32620 const opt_builtin_inst = (try sema.namespaceLookupRef(33541 const opt_builtin_inst = (try sema.namespaceLookupRef(
32621 &block,33542 &block,
32622 src,33543 src,
32623 mod.declPtr(std_file.root_decl.unwrap().?).src_namespace,33544 mod.declPtr(std_file.root_decl.unwrap().?).src_namespace,
32624 "builtin",33545 try ip.getOrPutString(gpa, "builtin"),
32625 )) orelse @panic("lib/std.zig is corrupt and missing 'builtin'");33546 )) orelse @panic("lib/std.zig is corrupt and missing 'builtin'");
32626 const builtin_inst = try sema.analyzeLoad(&block, src, opt_builtin_inst, src);33547 const builtin_inst = try sema.analyzeLoad(&block, src, opt_builtin_inst, src);
32627 const builtin_ty = sema.analyzeAsType(&block, src, builtin_inst) catch |err| switch (err) {33548 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 {...@@ -32631,8 +33552,8 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
32631 const opt_ty_decl = (try sema.namespaceLookup(33552 const opt_ty_decl = (try sema.namespaceLookup(
32632 &block,33553 &block,
32633 src,33554 src,
32634 builtin_ty.getNamespace().?,33555 builtin_ty.getNamespaceIndex(mod).unwrap().?,
32635 name,33556 try ip.getOrPutString(gpa, name),
32636 )) orelse std.debug.panic("lib/std/builtin.zig is corrupt and missing '{s}'", .{name});33557 )) orelse std.debug.panic("lib/std/builtin.zig is corrupt and missing '{s}'", .{name});
32637 return sema.analyzeDeclVal(&block, src, opt_ty_decl);33558 return sema.analyzeDeclVal(&block, src, opt_ty_decl);
32638}33559}
...@@ -32640,7 +33561,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {...@@ -32640,7 +33561,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
32640fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {33561fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
32641 const ty_inst = try sema.getBuiltin(name);33562 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);
32644 defer wip_captures.deinit();33565 defer wip_captures.deinit();
3264533566
32646 var block: Block = .{33567 var block: Block = .{
...@@ -32673,341 +33594,287 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -32673,341 +33594,287 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
32673/// that the types are already resolved.33594/// that the types are already resolved.
32674/// TODO assert the return value matches `ty.onePossibleValue`33595/// TODO assert the return value matches `ty.onePossibleValue`
32675pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {33596pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
32676 switch (ty.tag()) {33597 const mod = sema.mod;
32677 .f16,33598 return switch (ty.toIntern()) {
32678 .f32,33599 .empty_struct_type => Value.empty_struct,
32679 .f64,33600 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
32680 .f80,33601 .int_type => |int_type| {
32681 .f128,33602 if (int_type.bits == 0) {
32682 .c_longdouble,33603 return try mod.intValue(ty, 0);
32683 .comptime_int,33604 } else {
32684 .comptime_float,33605 return null;
32685 .u1,33606 }
32686 .u8,33607 },
32687 .i8,33608
32688 .u16,33609 .ptr_type,
32689 .i16,33610 .error_union_type,
32690 .u29,33611 .func_type,
32691 .u32,33612 .anyframe_type,
32692 .i32,33613 .error_set_type,
32693 .u64,33614 .inferred_error_set_type,
32694 .i64,33615 => null,
32695 .u128,33616
32696 .i128,33617 inline .array_type, .vector_type => |seq_type, seq_tag| {
32697 .usize,33618 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
32698 .isize,33619 if (seq_type.len + @boolToInt(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{
32699 .c_char,33620 .ty = ty.toIntern(),
32700 .c_short,33621 .storage = .{ .elems = &.{} },
32701 .c_ushort,33622 } })).toValue();
32702 .c_int,33623
32703 .c_uint,33624 if (try sema.typeHasOnePossibleValue(seq_type.child.toType())) |opv| {
32704 .c_long,33625 return (try mod.intern(.{ .aggregate = .{
32705 .c_ulong,33626 .ty = ty.toIntern(),
32706 .c_longlong,33627 .storage = .{ .repeated_elem = opv.toIntern() },
32707 .c_ulonglong,33628 } })).toValue();
32708 .bool,33629 }
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 {
32765 return null;33630 return null;
32766 }33631 },
32767 },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" => {33640 .simple_type => |t| switch (t) {
32770 const resolved_ty = try sema.resolveTypeFields(ty);33641 .f16,
32771 const s = resolved_ty.castTag(.@"struct").?.data;33642 .f32,
32772 for (s.fields.values(), 0..) |field, i| {33643 .f64,
32773 if (field.is_comptime) continue;33644 .f80,
32774 if (field.ty.eql(resolved_ty, sema.mod)) {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)) {
32775 const msg = try Module.ErrorMsg.create(33750 const msg = try Module.ErrorMsg.create(
32776 sema.gpa,33751 sema.gpa,
32777 s.srcLoc(sema.mod),33752 union_obj.srcLoc(sema.mod),
32778 "struct '{}' depends on itself",33753 "union '{}' depends on itself",
32779 .{ty.fmt(sema.mod)},33754 .{ty.fmt(sema.mod)},
32780 );33755 );
32781 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});33756 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
32782 return sema.failWithOwnedErrorMsg(msg);33757 return sema.failWithOwnedErrorMsg(msg);
32783 }33758 }
32784 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {33759 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
32785 return null;33760 return null;
32786 }33761 const only = try mod.intern(.{ .un = .{
32787 }33762 .ty = resolved_ty.toIntern(),
32788 return Value.initTag(.empty_struct_value);33763 .tag = tag_val.toIntern(),
32789 },33764 .val = val_val.toIntern(),
3279033765 } });
32791 .tuple, .anon_struct => {33766 return only.toValue();
32792 const tuple = ty.tupleFields();33767 },
32793 for (tuple.values, 0..) |val, i| {33768 .opaque_type => null,
32794 const is_comptime = val.tag() != .unreachable_value;33769 .enum_type => |enum_type| switch (enum_type.tag_mode) {
32795 if (is_comptime) continue;33770 .nonexhaustive => {
32796 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;33771 if (enum_type.tag_ty == .comptime_int_type) return null;
32797 return null;33772
32798 }33773 if (try sema.typeHasOnePossibleValue(enum_type.tag_ty.toType())) |int_opv| {
32799 return Value.initTag(.empty_struct_value);33774 const only = try mod.intern(.{ .enum_tag = .{
32800 },33775 .ty = ty.toIntern(),
33776 .int = int_opv.toIntern(),
33777 } });
33778 return only.toValue();
33779 }
3280133780
32802 .enum_numbered => {33781 return null;
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];
32831 },33782 },
32832 else => return null,33783 .auto, .explicit => {
32833 }33784 if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
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 },
3287933785
32880 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),33786 switch (enum_type.names.len) {
32881 .void => return Value.void,33787 0 => {
32882 .noreturn => return Value.initTag(.unreachable_value),33788 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
32883 .null => return Value.null,33789 return only.toValue();
32884 .undefined => return Value.initTag(.undef),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 => {33803 // values, not types
32887 if (ty.cast(Type.Payload.Bits).?.data == 0) {33804 .undef,
32888 return Value.zero;33805 .runtime_value,
32889 } else {33806 .simple_value,
32890 return null;33807 .variable,
32891 }33808 .extern_func,
32892 },33809 .func,
32893 .vector, .array, .array_u8 => {33810 .int,
32894 if (ty.arrayLen() == 0)33811 .err,
32895 return Value.initTag(.empty_array);33812 .error_union,
32896 if ((try sema.typeHasOnePossibleValue(ty.elemType())) != null) {33813 .enum_literal,
32897 return Value.initTag(.the_only_possible_value);33814 .enum_tag,
32898 }33815 .empty_enum_value,
32899 return null;33816 .float,
33817 .ptr,
33818 .opt,
33819 .aggregate,
33820 .un,
33821 // memoization, not types
33822 .memoized_call,
33823 => unreachable,
32900 },33824 },
3290133825 };
32902 .inferred_alloc_const => unreachable,
32903 .inferred_alloc_mut => unreachable,
32904 .generic_poison => return error.GenericPoison,
32905 }
32906}33826}
3290733827
32908/// Returns the type of the AIR instruction.33828/// Returns the type of the AIR instruction.
32909fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {33829fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
32910 return sema.getTmpAir().typeOf(inst);33830 return sema.getTmpAir().typeOf(inst, &sema.mod.intern_pool);
32911}33831}
3291233832
32913pub fn getTmpAir(sema: Sema) Air {33833pub fn getTmpAir(sema: Sema) Air {
32914 return .{33834 return .{
32915 .instructions = sema.air_instructions.slice(),33835 .instructions = sema.air_instructions.slice(),
32916 .extra = sema.air_extra.items,33836 .extra = sema.air_extra.items,
32917 .values = sema.air_values.items,
32918 };33837 };
32919}33838}
3292033839
32921pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {33840pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
32922 switch (ty.tag()) {33841 if (@enumToInt(ty.toIntern()) < Air.ref_start_index)
32923 .u1 => return .u1_type,33842 return @intToEnum(Air.Inst.Ref, @enumToInt(ty.toIntern()));
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 }
32986 try sema.air_instructions.append(sema.gpa, .{33843 try sema.air_instructions.append(sema.gpa, .{
32987 .tag = .const_ty,33844 .tag = .interned,
32988 .data = .{ .ty = ty },33845 .data = .{ .interned = ty.toIntern() },
32989 });33846 });
32990 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));33847 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
32991}33848}
3299233849
32993fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {33850fn 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));
32995}33853}
3299633854
32997fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {33855fn 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());
32999}33857}
3300033858
33001pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref {33859pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref {
33860 const mod = sema.mod;
33002 const gpa = sema.gpa;33861 const gpa = sema.gpa;
33003 const ty_inst = try sema.addType(ty);33862
33004 try sema.air_values.append(gpa, val);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()));
33005 try sema.air_instructions.append(gpa, .{33875 try sema.air_instructions.append(gpa, .{
33006 .tag = .constant,33876 .tag = .interned,
33007 .data = .{ .ty_pl = .{33877 .data = .{ .interned = val.toIntern() },
33008 .ty = ty_inst,
33009 .payload = @intCast(u32, sema.air_values.items.len - 1),
33010 } },
33011 });33878 });
33012 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));33879 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
33013}33880}
...@@ -33026,7 +33893,8 @@ pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 {...@@ -33026,7 +33893,8 @@ pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 {
33026 u32 => @field(extra, field.name),33893 u32 => @field(extra, field.name),
33027 Air.Inst.Ref => @enumToInt(@field(extra, field.name)),33894 Air.Inst.Ref => @enumToInt(@field(extra, field.name)),
33028 i32 => @bitCast(u32, @field(extra, field.name)),33895 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)),
33030 });33898 });
33031 }33899 }
33032 return result;33900 return result;
...@@ -33072,21 +33940,25 @@ fn analyzeComptimeAlloc(...@@ -33072,21 +33940,25 @@ fn analyzeComptimeAlloc(
33072 defer anon_decl.deinit();33940 defer anon_decl.deinit();
3307333941
33074 const decl_index = try anon_decl.finish(33942 const decl_index = try anon_decl.finish(
33075 try var_type.copy(anon_decl.arena()),33943 var_type,
33076 // There will be stores before the first load, but they may be to sub-elements or33944 // There will be stores before the first load, but they may be to sub-elements or
33077 // sub-fields. So we need to initialize with undef to allow the mechanism to expand33945 // sub-fields. So we need to initialize with undef to allow the mechanism to expand
33078 // into fields/elements and have those overridden with stored values.33946 // into fields/elements and have those overridden with stored values.
33079 Value.undef,33947 (try sema.mod.intern(.{ .undef = var_type.toIntern() })).toValue(),
33080 alignment,33948 alignment,
33081 );33949 );
33082 const decl = sema.mod.declPtr(decl_index);33950 const decl = sema.mod.declPtr(decl_index);
33083 decl.@"align" = alignment;33951 decl.@"align" = alignment;
3308433952
33953 try sema.comptime_mutable_decls.append(decl_index);
33085 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);33954 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, .{33955 return sema.addConstant(ptr_type, (try sema.mod.intern(.{ .ptr = .{
33087 .runtime_index = block.runtime_index,33956 .ty = ptr_type.toIntern(),
33088 .decl_index = decl_index,33957 .addr = .{ .mut_decl = .{
33089 }));33958 .decl = decl_index,
33959 .runtime_index = block.runtime_index,
33960 } },
33961 } })).toValue());
33090}33962}
3309133963
33092/// The places where a user can specify an address space attribute33964/// The places where a user can specify an address space attribute
...@@ -33114,8 +33986,9 @@ pub fn analyzeAddressSpace(...@@ -33114,8 +33986,9 @@ pub fn analyzeAddressSpace(
33114 zir_ref: Zir.Inst.Ref,33986 zir_ref: Zir.Inst.Ref,
33115 ctx: AddressSpaceContext,33987 ctx: AddressSpaceContext,
33116) !std.builtin.AddressSpace {33988) !std.builtin.AddressSpace {
33989 const mod = sema.mod;
33117 const addrspace_tv = try sema.resolveInstConst(block, src, zir_ref, "addresspace must be comptime-known");33990 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);
33119 const target = sema.mod.getTarget();33992 const target = sema.mod.getTarget();
33120 const arch = target.cpu.arch;33993 const arch = target.cpu.arch;
3312133994
...@@ -33158,8 +34031,9 @@ pub fn analyzeAddressSpace(...@@ -33158,8 +34031,9 @@ pub fn analyzeAddressSpace(
33158/// Asserts the value is a pointer and dereferences it.34031/// Asserts the value is a pointer and dereferences it.
33159/// Returns `null` if the pointer contents cannot be loaded at comptime.34032/// Returns `null` if the pointer contents cannot be loaded at comptime.
33160fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value {34033fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value {
33161 const load_ty = ptr_ty.childType();34034 const mod = sema.mod;
33162 const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty, true);34035 const load_ty = ptr_ty.childType(mod);
34036 const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty);
33163 switch (res) {34037 switch (res) {
33164 .runtime_load => return null,34038 .runtime_load => return null,
33165 .val => |v| return v,34039 .val => |v| return v,
...@@ -33185,8 +34059,9 @@ const DerefResult = union(enum) {...@@ -33185,8 +34059,9 @@ const DerefResult = union(enum) {
33185 out_of_bounds: Type,34059 out_of_bounds: Type,
33186};34060};
3318734061
33188fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type, want_mutable: bool) CompileError!DerefResult {34062fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type) CompileError!DerefResult {
33189 const target = sema.mod.getTarget();34063 const mod = sema.mod;
34064 const target = mod.getTarget();
33190 const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) {34065 const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) {
33191 error.RuntimeLoad => return DerefResult{ .runtime_load = {} },34066 error.RuntimeLoad => return DerefResult{ .runtime_load = {} },
33192 else => |e| return e,34067 else => |e| return e,
...@@ -33199,19 +34074,17 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -33199,19 +34074,17 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
33199 if (coerce_in_mem_ok) {34074 if (coerce_in_mem_ok) {
33200 // We have a Value that lines up in virtual memory exactly with what we want to load,34075 // We have a Value that lines up in virtual memory exactly with what we want to load,
33201 // and it is in-memory coercible to load_ty. It may be returned without modifications.34076 // and it is in-memory coercible to load_ty. It may be returned without modifications.
33202 if (deref.is_mutable and want_mutable) {34077 // Move mutable decl values to the InternPool and assert other decls are already in
33203 // The decl whose value we are obtaining here may be overwritten with34078 // the InternPool.
33204 // a different value upon further semantic analysis, which would34079 const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern();
33205 // invalidate this memory. So we must copy here.34080 const coerced_val = try sema.coerceValueInMemory(block, uncoerced_val.toValue(), tv.ty, load_ty, src);
33206 return DerefResult{ .val = try tv.val.copy(sema.arena) };34081 return .{ .val = coerced_val };
33207 }
33208 return DerefResult{ .val = tv.val };
33209 }34082 }
33210 }34083 }
3321134084
33212 // The type is not in-memory coercible or the direct dereference failed, so it must34085 // The type is not in-memory coercible or the direct dereference failed, so it must
33213 // be bitcast according to the pointer type we are performing the load through.34086 // be bitcast according to the pointer type we are performing the load through.
33214 if (!load_ty.hasWellDefinedLayout()) {34087 if (!load_ty.hasWellDefinedLayout(mod)) {
33215 return DerefResult{ .needed_well_defined = load_ty };34088 return DerefResult{ .needed_well_defined = load_ty };
33216 }34089 }
3321734090
...@@ -33248,59 +34121,32 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError...@@ -33248,59 +34121,32 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError
33248/// This can return `error.AnalysisFail` because it sometimes requires resolving whether34121/// This can return `error.AnalysisFail` because it sometimes requires resolving whether
33249/// a type has zero bits, which can cause a "foo depends on itself" compile error.34122/// a type has zero bits, which can cause a "foo depends on itself" compile error.
33250/// This logic must be kept in sync with `Type.isPtrLikeOptional`.34123/// This logic must be kept in sync with `Type.isPtrLikeOptional`.
33251fn typePtrOrOptionalPtrTy(34124fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
33252 sema: *Sema,34125 const mod = sema.mod;
33253 ty: Type,34126 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
33254 buf: *Type.Payload.ElemType,34127 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
33255) !?Type {34128 .One, .Many, .C => ty,
33256 switch (ty.tag()) {34129 .Slice => null,
33257 .optional_single_const_pointer,34130 },
33258 .optional_single_mut_pointer,34131 .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) {
33259 .c_const_pointer,34132 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
33260 .c_mut_pointer,34133 .Slice, .C => null,
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,
33289 .Many, .One => {34134 .Many, .One => {
33290 if (info.@"allowzero") return null;34135 if (ptr_type.flags.is_allowzero) return null;
3329134136
33292 // optionals of zero sized types behave like bools, not pointers34137 // 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) {
33294 return null;34140 return null;
33295 }34141 }
3329634142
33297 return child_type;34143 return payload_ty;
33298 },34144 },
33299 }34145 },
34146 else => null,
33300 },34147 },
3330134148 else => null,
33302 else => return null,34149 };
33303 }
33304}34150}
3330534151
33306/// `generic_poison` will return false.34152/// `generic_poison` will return false.
...@@ -33310,201 +34156,170 @@ fn typePtrOrOptionalPtrTy(...@@ -33310,201 +34156,170 @@ fn typePtrOrOptionalPtrTy(
33310/// TODO merge these implementations together with the "advanced"/opt_sema pattern seen34156/// TODO merge these implementations together with the "advanced"/opt_sema pattern seen
33311/// elsewhere in value.zig34157/// elsewhere in value.zig
33312pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {34158pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33313 return switch (ty.tag()) {34159 const mod = sema.mod;
33314 .u1,34160 return switch (ty.toIntern()) {
33315 .u8,34161 .empty_struct_type => false,
33316 .i8,34162
33317 .u16,34163 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
33318 .i16,34164 .int_type => return false,
33319 .u29,34165 .ptr_type => |ptr_type| {
33320 .u32,34166 const child_ty = ptr_type.child.toType();
33321 .i32,34167 if (child_ty.zigTypeTag(mod) == .Fn) {
33322 .u64,34168 return mod.typeToFunc(child_ty).?.is_generic;
33323 .i64,34169 } else {
33324 .u128,34170 return sema.typeRequiresComptime(child_ty);
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;
33436 }34171 }
33437 }34172 },
33438 return false;34173 .anyframe_type => |child| {
33439 },34174 if (child == .none) return false;
3344034175 return sema.typeRequiresComptime(child.toType());
33441 .@"struct" => {34176 },
33442 const struct_obj = ty.castTag(.@"struct").?.data;34177 .array_type => |array_type| return sema.typeRequiresComptime(array_type.child.toType()),
33443 switch (struct_obj.requires_comptime) {34178 .vector_type => |vector_type| return sema.typeRequiresComptime(vector_type.child.toType()),
33444 .no, .wip => return false,34179 .opt_type => |child| return sema.typeRequiresComptime(child.toType()),
33445 .yes => return true,
33446 .unknown => {
33447 if (struct_obj.status == .field_types_wip)
33448 return false;
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;34185 .error_set_type, .inferred_error_set_type => false,
33453 for (struct_obj.fields.values()) |field| {34186
33454 if (field.is_comptime) continue;34187 .func_type => true,
33455 if (try sema.typeRequiresComptime(field.ty)) {34188
33456 struct_obj.requires_comptime = .yes;34189 .simple_type => |t| return switch (t) {
33457 return true;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 }
33458 }34252 }
33459 }34253 struct_obj.requires_comptime = .no;
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)
33473 return false;34254 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);34268 .union_type => |union_type| {
3347634269 const union_obj = mod.unionPtr(union_type.index);
33477 union_obj.requires_comptime = .wip;34270 switch (union_obj.requires_comptime) {
33478 for (union_obj.fields.values()) |field| {34271 .no, .wip => return false,
33479 if (try sema.typeRequiresComptime(field.ty)) {34272 .yes => return true,
33480 union_obj.requires_comptime = .yes;34273 .unknown => {
33481 return true;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 }
33482 }34285 }
33483 }34286 union_obj.requires_comptime = .no;
33484 union_obj.requires_comptime = .no;34287 return false;
33485 return false;34288 },
33486 },34289 }
33487 }34290 },
33488 },
3348934291
33490 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),34292 .opaque_type => false,
33491 .anyframe_T => {34293 .enum_type => |enum_type| try sema.typeRequiresComptime(enum_type.tag_ty.toType()),
33492 const child_ty = ty.castTag(.anyframe_T).?.data;34294
33493 return sema.typeRequiresComptime(child_ty);34295 // values, not types
33494 },34296 .undef,
33495 .enum_numbered => {34297 .runtime_value,
33496 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;34298 .simple_value,
33497 return sema.typeRequiresComptime(tag_ty);34299 .variable,
33498 },34300 .extern_func,
33499 .enum_full, .enum_nonexhaustive => {34301 .func,
33500 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;34302 .int,
33501 return sema.typeRequiresComptime(tag_ty);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,
33502 },34316 },
33503 };34317 };
33504}34318}
3350534319
33506pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {34320pub 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) {
33508 error.NeedLazy => unreachable,34323 error.NeedLazy => unreachable,
33509 else => |e| return e,34324 else => |e| return e,
33510 };34325 };
...@@ -33512,19 +34327,18 @@ pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {...@@ -33512,19 +34327,18 @@ pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
3351234327
33513fn typeAbiSize(sema: *Sema, ty: Type) !u64 {34328fn typeAbiSize(sema: *Sema, ty: Type) !u64 {
33514 try sema.resolveTypeLayout(ty);34329 try sema.resolveTypeLayout(ty);
33515 const target = sema.mod.getTarget();34330 return ty.abiSize(sema.mod);
33516 return ty.abiSize(target);
33517}34331}
3351834332
33519fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!u32 {34333fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!u32 {
33520 const target = sema.mod.getTarget();34334 return (try ty.abiAlignmentAdvanced(sema.mod, .{ .sema = sema })).scalar;
33521 return (try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar;
33522}34335}
3352334336
33524/// Not valid to call for packed unions.34337/// Not valid to call for packed unions.
33525/// Keep implementation in sync with `Module.Union.Field.normalAlignment`.34338/// Keep implementation in sync with `Module.Union.Field.normalAlignment`.
33526fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {34339fn 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) {
33528 return @as(u32, 0);34342 return @as(u32, 0);
33529 } else if (field.abi_align == 0) {34343 } else if (field.abi_align == 0) {
33530 return sema.typeAbiAlignment(field.ty);34344 return sema.typeAbiAlignment(field.ty);
...@@ -33535,7 +34349,8 @@ fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {...@@ -33535,7 +34349,8 @@ fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {
3353534349
33536/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.34350/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
33537pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {34351pub 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).?;
33539 if (fn_info.is_generic) return false;34354 if (fn_info.is_generic) return false;
33540 if (fn_info.is_var_args) return true;34355 if (fn_info.is_var_args) return true;
33541 switch (fn_info.cc) {34356 switch (fn_info.cc) {
...@@ -33543,7 +34358,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {...@@ -33543,7 +34358,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
33543 .Inline => return false,34358 .Inline => return false,
33544 else => {},34359 else => {},
33545 }34360 }
33546 if (try sema.typeRequiresComptime(fn_info.return_type)) {34361 if (try sema.typeRequiresComptime(fn_info.return_type.toType())) {
33547 return false;34362 return false;
33548 }34363 }
33549 return true;34364 return true;
...@@ -33553,11 +34368,12 @@ fn unionFieldIndex(...@@ -33553,11 +34368,12 @@ fn unionFieldIndex(
33553 sema: *Sema,34368 sema: *Sema,
33554 block: *Block,34369 block: *Block,
33555 unresolved_union_ty: Type,34370 unresolved_union_ty: Type,
33556 field_name: []const u8,34371 field_name: InternPool.NullTerminatedString,
33557 field_src: LazySrcLoc,34372 field_src: LazySrcLoc,
33558) !u32 {34373) !u32 {
34374 const mod = sema.mod;
33559 const union_ty = try sema.resolveTypeFields(unresolved_union_ty);34375 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).?;
33561 const field_index_usize = union_obj.fields.getIndex(field_name) orelse34377 const field_index_usize = union_obj.fields.getIndex(field_name) orelse
33562 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);34378 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
33563 return @intCast(u32, field_index_usize);34379 return @intCast(u32, field_index_usize);
...@@ -33567,14 +34383,15 @@ fn structFieldIndex(...@@ -33567,14 +34383,15 @@ fn structFieldIndex(
33567 sema: *Sema,34383 sema: *Sema,
33568 block: *Block,34384 block: *Block,
33569 unresolved_struct_ty: Type,34385 unresolved_struct_ty: Type,
33570 field_name: []const u8,34386 field_name: InternPool.NullTerminatedString,
33571 field_src: LazySrcLoc,34387 field_src: LazySrcLoc,
33572) !u32 {34388) !u32 {
34389 const mod = sema.mod;
33573 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);34390 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
33574 if (struct_ty.isAnonStruct()) {34391 if (struct_ty.isAnonStruct(mod)) {
33575 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);34392 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
33576 } else {34393 } else {
33577 const struct_obj = struct_ty.castTag(.@"struct").?.data;34394 const struct_obj = mod.typeToStruct(struct_ty).?;
33578 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse34395 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
33579 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);34396 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
33580 return @intCast(u32, field_index_usize);34397 return @intCast(u32, field_index_usize);
...@@ -33585,55 +34402,98 @@ fn anonStructFieldIndex(...@@ -33585,55 +34402,98 @@ fn anonStructFieldIndex(
33585 sema: *Sema,34402 sema: *Sema,
33586 block: *Block,34403 block: *Block,
33587 struct_ty: Type,34404 struct_ty: Type,
33588 field_name: []const u8,34405 field_name: InternPool.NullTerminatedString,
33589 field_src: LazySrcLoc,34406 field_src: LazySrcLoc,
33590) !u32 {34407) !u32 {
33591 const anon_struct = struct_ty.castTag(.anon_struct).?.data;34408 const mod = sema.mod;
33592 for (anon_struct.names, 0..) |name, i| {34409 switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
33593 if (mem.eql(u8, name, field_name)) {34410 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names, 0..) |name, i| {
33594 return @intCast(u32, i);34411 if (name == field_name) return @intCast(u32, i);
33595 }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,
33596 }34421 }
33597 return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{34422 return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{
33598 field_name, struct_ty.fmt(sema.mod),34423 field_name.fmt(&mod.intern_pool), struct_ty.fmt(sema.mod),
33599 });34424 });
33600}34425}
3360134426
33602fn queueFullTypeResolution(sema: *Sema, ty: Type) !void {34427fn queueFullTypeResolution(sema: *Sema, ty: Type) !void {
33603 const inst_ref = try sema.addType(ty);34428 try sema.types_to_resolve.put(sema.gpa, ty.toIntern(), {});
33604 try sema.types_to_resolve.append(sema.gpa, inst_ref);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 };
33605}34450}
3360634451
33607fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value {34452fn intAddInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize) !Value {
33608 if (ty.zigTypeTag() == .Vector) {34453 const mod = sema.mod;
33609 const result_data = try sema.arena.alloc(Value, ty.vectorLen());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);
33610 for (result_data, 0..) |*scalar, i| {34457 for (result_data, 0..) |*scalar, i| {
33611 var lhs_buf: Value.ElemValueBuffer = undefined;34458 const lhs_elem = try lhs.elemValue(mod, i);
33612 var rhs_buf: Value.ElemValueBuffer = undefined;34459 const rhs_elem = try rhs.elemValue(mod, i);
33613 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);34460 const val = sema.intAddScalar(lhs_elem, rhs_elem, scalar_ty) catch |err| switch (err) {
33614 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);34461 error.Overflow => {
33615 scalar.* = try sema.intAddScalar(lhs_elem, rhs_elem);34462 overflow_idx.* = i;
34463 return error.Overflow;
34464 },
34465 else => |e| return e,
34466 };
34467 scalar.* = try val.intern(scalar_ty, mod);
33616 }34468 }
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();
33618 }34473 }
33619 return sema.intAddScalar(lhs, rhs);34474 return sema.intAddScalar(lhs, rhs, ty);
33620}34475}
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 }
33623 // TODO is this a performance issue? maybe we should try the operation without34484 // TODO is this a performance issue? maybe we should try the operation without
33624 // resorting to BigInt first.34485 // resorting to BigInt first.
33625 var lhs_space: Value.BigIntSpace = undefined;34486 var lhs_space: Value.BigIntSpace = undefined;
33626 var rhs_space: Value.BigIntSpace = undefined;34487 var rhs_space: Value.BigIntSpace = undefined;
33627 const target = sema.mod.getTarget();34488 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
33628 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);34489 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
33629 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);
33630 const limbs = try sema.arena.alloc(34490 const limbs = try sema.arena.alloc(
33631 std.math.big.Limb,34491 std.math.big.Limb,
33632 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,34492 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
33633 );34493 );
33634 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };34494 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
33635 result_bigint.add(lhs_bigint, rhs_bigint);34495 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());
33637}34497}
3363834498
33639/// Supports both floats and ints; handles undefined.34499/// Supports both floats and ints; handles undefined.
...@@ -33643,55 +34503,87 @@ fn numberAddWrapScalar(...@@ -33643,55 +34503,87 @@ fn numberAddWrapScalar(
33643 rhs: Value,34503 rhs: Value,
33644 ty: Type,34504 ty: Type,
33645) !Value {34505) !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) {34509 if (ty.zigTypeTag(mod) == .ComptimeInt) {
33649 return sema.intAdd(lhs, rhs, ty);34510 return sema.intAdd(lhs, rhs, ty, undefined);
33650 }34511 }
3365134512
33652 if (ty.isAnyFloat()) {34513 if (ty.isAnyFloat()) {
33653 return sema.floatAdd(lhs, rhs, ty);34514 return Value.floatAdd(lhs, rhs, ty, sema.arena, mod);
33654 }34515 }
3365534516
33656 const overflow_result = try sema.intAddWithOverflow(lhs, rhs, ty);34517 const overflow_result = try sema.intAddWithOverflow(lhs, rhs, ty);
33657 return overflow_result.wrapped_result;34518 return overflow_result.wrapped_result;
33658}34519}
3365934520
33660fn intSub(34521/// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting
33661 sema: *Sema,34522/// overflow_idx to the vector index the overflow was at (or 0 for a scalar).
33662 lhs: Value,34523fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value {
33663 rhs: Value,34524 var overflow: usize = undefined;
33664 ty: Type,34525 return sema.intSubInner(lhs, rhs, ty, &overflow) catch |err| switch (err) {
33665) !Value {34526 error.Overflow => {
33666 if (ty.zigTypeTag() == .Vector) {34527 const is_vec = ty.isVector(sema.mod);
33667 const result_data = try sema.arena.alloc(Value, ty.vectorLen());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);
33668 for (result_data, 0..) |*scalar, i| {34547 for (result_data, 0..) |*scalar, i| {
33669 var lhs_buf: Value.ElemValueBuffer = undefined;34548 const lhs_elem = try lhs.elemValue(sema.mod, i);
33670 var rhs_buf: Value.ElemValueBuffer = undefined;34549 const rhs_elem = try rhs.elemValue(sema.mod, i);
33671 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);34550 const val = sema.intSubScalar(lhs_elem, rhs_elem, scalar_ty) catch |err| switch (err) {
33672 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);34551 error.Overflow => {
33673 scalar.* = try sema.intSubScalar(lhs_elem, rhs_elem);34552 overflow_idx.* = i;
34553 return error.Overflow;
34554 },
34555 else => |e| return e,
34556 };
34557 scalar.* = try val.intern(scalar_ty, mod);
33674 }34558 }
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();
33676 }34563 }
33677 return sema.intSubScalar(lhs, rhs);34564 return sema.intSubScalar(lhs, rhs, ty);
33678}34565}
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 }
33681 // TODO is this a performance issue? maybe we should try the operation without34574 // TODO is this a performance issue? maybe we should try the operation without
33682 // resorting to BigInt first.34575 // resorting to BigInt first.
33683 var lhs_space: Value.BigIntSpace = undefined;34576 var lhs_space: Value.BigIntSpace = undefined;
33684 var rhs_space: Value.BigIntSpace = undefined;34577 var rhs_space: Value.BigIntSpace = undefined;
33685 const target = sema.mod.getTarget();34578 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
33686 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);34579 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
33687 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);
33688 const limbs = try sema.arena.alloc(34580 const limbs = try sema.arena.alloc(
33689 std.math.big.Limb,34581 std.math.big.Limb,
33690 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,34582 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
33691 );34583 );
33692 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };34584 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
33693 result_bigint.sub(lhs_bigint, rhs_bigint);34585 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());
33695}34587}
3369634588
33697/// Supports both floats and ints; handles undefined.34589/// Supports both floats and ints; handles undefined.
...@@ -33701,155 +34593,49 @@ fn numberSubWrapScalar(...@@ -33701,155 +34593,49 @@ fn numberSubWrapScalar(
33701 rhs: Value,34593 rhs: Value,
33702 ty: Type,34594 ty: Type,
33703) !Value {34595) !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) {34599 if (ty.zigTypeTag(mod) == .ComptimeInt) {
33707 return sema.intSub(lhs, rhs, ty);34600 return sema.intSub(lhs, rhs, ty, undefined);
33708 }34601 }
3370934602
33710 if (ty.isAnyFloat()) {34603 if (ty.isAnyFloat()) {
33711 return sema.floatSub(lhs, rhs, ty);34604 return Value.floatSub(lhs, rhs, ty, sema.arena, mod);
33712 }34605 }
3371334606
33714 const overflow_result = try sema.intSubWithOverflow(lhs, rhs, ty);34607 const overflow_result = try sema.intSubWithOverflow(lhs, rhs, ty);
33715 return overflow_result.wrapped_result;34608 return overflow_result.wrapped_result;
33716}34609}
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
33832fn intSubWithOverflow(34611fn intSubWithOverflow(
33833 sema: *Sema,34612 sema: *Sema,
33834 lhs: Value,34613 lhs: Value,
33835 rhs: Value,34614 rhs: Value,
33836 ty: Type,34615 ty: Type,
33837) !Value.OverflowArithmeticResult {34616) !Value.OverflowArithmeticResult {
33838 if (ty.zigTypeTag() == .Vector) {34617 const mod = sema.mod;
33839 const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen());34618 if (ty.zigTypeTag(mod) == .Vector) {
33840 const result_data = try sema.arena.alloc(Value, ty.vectorLen());34619 const vec_len = ty.vectorLen(mod);
33841 for (result_data, 0..) |*scalar, i| {34620 const overflowed_data = try sema.arena.alloc(InternPool.Index, vec_len);
33842 var lhs_buf: Value.ElemValueBuffer = undefined;34621 const result_data = try sema.arena.alloc(InternPool.Index, vec_len);
33843 var rhs_buf: Value.ElemValueBuffer = undefined;34622 const scalar_ty = ty.scalarType(mod);
33844 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);34623 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
33845 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);34624 const lhs_elem = try lhs.elemValue(sema.mod, i);
33846 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType());34625 const rhs_elem = try rhs.elemValue(sema.mod, i);
33847 overflowed_data[i] = of_math_result.overflow_bit;34626 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
33848 scalar.* = of_math_result.wrapped_result;34627 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
34628 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
33849 }34629 }
33850 return Value.OverflowArithmeticResult{34630 return Value.OverflowArithmeticResult{
33851 .overflow_bit = try Value.Tag.aggregate.create(sema.arena, overflowed_data),34631 .overflow_bit = (try mod.intern(.{ .aggregate = .{
33852 .wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data),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(),
33853 };34639 };
33854 }34640 }
33855 return sema.intSubWithOverflowScalar(lhs, rhs, ty);34641 return sema.intSubWithOverflowScalar(lhs, rhs, ty);
...@@ -33861,22 +34647,22 @@ fn intSubWithOverflowScalar(...@@ -33861,22 +34647,22 @@ fn intSubWithOverflowScalar(
33861 rhs: Value,34647 rhs: Value,
33862 ty: Type,34648 ty: Type,
33863) !Value.OverflowArithmeticResult {34649) !Value.OverflowArithmeticResult {
33864 const target = sema.mod.getTarget();34650 const mod = sema.mod;
33865 const info = ty.intInfo(target);34651 const info = ty.intInfo(mod);
3386634652
33867 var lhs_space: Value.BigIntSpace = undefined;34653 var lhs_space: Value.BigIntSpace = undefined;
33868 var rhs_space: Value.BigIntSpace = undefined;34654 var rhs_space: Value.BigIntSpace = undefined;
33869 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);34655 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
33870 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);34656 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
33871 const limbs = try sema.arena.alloc(34657 const limbs = try sema.arena.alloc(
33872 std.math.big.Limb,34658 std.math.big.Limb,
33873 std.math.big.int.calcTwosCompLimbCount(info.bits),34659 std.math.big.int.calcTwosCompLimbCount(info.bits),
33874 );34660 );
33875 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };34661 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
33876 const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);34662 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());
33878 return Value.OverflowArithmeticResult{34664 return Value.OverflowArithmeticResult{
33879 .overflow_bit = Value.boolToInt(overflowed),34665 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
33880 .wrapped_result = wrapped_result,34666 .wrapped_result = wrapped_result,
33881 };34667 };
33882}34668}
...@@ -33889,15 +34675,19 @@ fn floatToInt(...@@ -33889,15 +34675,19 @@ fn floatToInt(
33889 float_ty: Type,34675 float_ty: Type,
33890 int_ty: Type,34676 int_ty: Type,
33891) CompileError!Value {34677) CompileError!Value {
33892 if (float_ty.zigTypeTag() == .Vector) {34678 const mod = sema.mod;
33893 const elem_ty = float_ty.childType();34679 if (float_ty.zigTypeTag(mod) == .Vector) {
33894 const result_data = try sema.arena.alloc(Value, float_ty.vectorLen());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);
33895 for (result_data, 0..) |*scalar, i| {34683 for (result_data, 0..) |*scalar, i| {
33896 var buf: Value.ElemValueBuffer = undefined;34684 const elem_val = try val.elemValue(sema.mod, i);
33897 const elem_val = val.elemValueBuffer(sema.mod, i, &buf);34685 scalar.* = try (try sema.floatToIntScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod))).intern(scalar_ty, mod);
33898 scalar.* = try sema.floatToIntScalar(block, src, elem_val, elem_ty, int_ty.scalarType());
33899 }34686 }
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();
33901 }34691 }
33902 return sema.floatToIntScalar(block, src, val, float_ty, int_ty);34692 return sema.floatToIntScalar(block, src, val, float_ty, int_ty);
33903}34693}
...@@ -33935,9 +34725,9 @@ fn floatToIntScalar(...@@ -33935,9 +34725,9 @@ fn floatToIntScalar(
33935 float_ty: Type,34725 float_ty: Type,
33936 int_ty: Type,34726 int_ty: Type,
33937) CompileError!Value {34727) 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);
33941 if (std.math.isNan(float)) {34731 if (std.math.isNan(float)) {
33942 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{34732 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{
33943 int_ty.fmt(sema.mod),34733 int_ty.fmt(sema.mod),
...@@ -33952,18 +34742,14 @@ fn floatToIntScalar(...@@ -33952,18 +34742,14 @@ fn floatToIntScalar(
33952 var big_int = try float128IntPartToBigInt(sema.arena, float);34742 var big_int = try float128IntPartToBigInt(sema.arena, float);
33953 defer big_int.deinit();34743 defer big_int.deinit();
3395434744
33955 const result_limbs = try sema.arena.dupe(Limb, big_int.toConst().limbs);34745 const cti_result = try mod.intValue_big(Type.comptime_int, big_int.toConst());
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);
3396034746
33961 if (!(try sema.intFitsInType(result, int_ty, null))) {34747 if (!(try sema.intFitsInType(cti_result, int_ty, null))) {
33962 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{34748 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{
33963 val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),34749 val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),
33964 });34750 });
33965 }34751 }
33966 return result;34752 return mod.getCoerced(cti_result, int_ty);
33967}34753}
3396834754
33969/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.34755/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
...@@ -33976,208 +34762,91 @@ fn intFitsInType(...@@ -33976,208 +34762,91 @@ fn intFitsInType(
33976 ty: Type,34762 ty: Type,
33977 vector_index: ?*usize,34763 vector_index: ?*usize,
33978) CompileError!bool {34764) CompileError!bool {
33979 const target = sema.mod.getTarget();34765 const mod = sema.mod;
33980 switch (val.tag()) {34766 if (ty.toIntern() == .comptime_int_type) return true;
33981 .zero,34767 const info = ty.intInfo(mod);
33982 .undef,34768 switch (val.toIntern()) {
33983 .bool_false,34769 .zero_usize, .zero_u8 => return true,
33984 => return true,34770 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
3398534771 .undef => return true,
33986 .one,34772 .variable, .extern_func, .func, .ptr => {
33987 .bool_true,34773 const target = mod.getTarget();
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);
34083 const ptr_bits = target.ptrBitWidth();34774 const ptr_bits = target.ptrBitWidth();
34084 return switch (info.signedness) {34775 return switch (info.signedness) {
34085 .signed => info.bits > ptr_bits,34776 .signed => info.bits > ptr_bits,
34086 .unsigned => info.bits >= ptr_bits,34777 .unsigned => info.bits >= ptr_bits,
34087 };34778 };
34088 },34779 },
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 },
34090 else => unreachable,34826 else => unreachable,
34091 },34827 },
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,
34105 }34828 }
34106}34829}
3410734830
34108fn intInRange(34831fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool {
34109 sema: *Sema,34832 const mod = sema.mod;
34110 tag_ty: Type,
34111 int_val: Value,
34112 end: usize,
34113) !bool {
34114 if (!(try int_val.compareAllWithZeroAdvanced(.gte, sema))) return false;34833 if (!(try int_val.compareAllWithZeroAdvanced(.gte, sema))) return false;
34115 var end_payload: Value.Payload.U64 = .{34834 const end_val = try mod.intValue(tag_ty, end);
34116 .base = .{ .tag = .int_u64 },
34117 .data = end,
34118 };
34119 const end_val = Value.initPayload(&end_payload.base);
34120 if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false;34835 if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false;
34121 return true;34836 return true;
34122}34837}
3412334838
34124/// Asserts the type is an enum.34839/// Asserts the type is an enum.
34125fn enumHasInt(34840fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool {
34126 sema: *Sema,34841 const mod = sema.mod;
34127 ty: Type,34842 const enum_type = mod.intern_pool.indexToKey(ty.toIntern()).enum_type;
34128 int: Value,34843 assert(enum_type.tag_mode != .nonexhaustive);
34129) CompileError!bool {34844 // The `tagValueIndex` function call below relies on the type being the integer tag type.
34130 switch (ty.tag()) {34845 // `getCoerced` assumes the value will fit the new type.
34131 .enum_nonexhaustive => unreachable,34846 if (!(try sema.intFitsInType(int, enum_type.tag_ty.toType(), null))) return false;
34132 .enum_full => {34847 const int_coerced = try mod.getCoerced(int, enum_type.tag_ty.toType());
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,
3417834848
34179 else => unreachable,34849 return enum_type.tagValueIndex(&mod.intern_pool, int_coerced.toIntern()) != null;
34180 }
34181}34850}
3418234851
34183fn intAddWithOverflow(34852fn intAddWithOverflow(
...@@ -34186,21 +34855,28 @@ fn intAddWithOverflow(...@@ -34186,21 +34855,28 @@ fn intAddWithOverflow(
34186 rhs: Value,34855 rhs: Value,
34187 ty: Type,34856 ty: Type,
34188) !Value.OverflowArithmeticResult {34857) !Value.OverflowArithmeticResult {
34189 if (ty.zigTypeTag() == .Vector) {34858 const mod = sema.mod;
34190 const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen());34859 if (ty.zigTypeTag(mod) == .Vector) {
34191 const result_data = try sema.arena.alloc(Value, ty.vectorLen());34860 const vec_len = ty.vectorLen(mod);
34192 for (result_data, 0..) |*scalar, i| {34861 const overflowed_data = try sema.arena.alloc(InternPool.Index, vec_len);
34193 var lhs_buf: Value.ElemValueBuffer = undefined;34862 const result_data = try sema.arena.alloc(InternPool.Index, vec_len);
34194 var rhs_buf: Value.ElemValueBuffer = undefined;34863 const scalar_ty = ty.scalarType(mod);
34195 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);34864 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
34196 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);34865 const lhs_elem = try lhs.elemValue(sema.mod, i);
34197 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType());34866 const rhs_elem = try rhs.elemValue(sema.mod, i);
34198 overflowed_data[i] = of_math_result.overflow_bit;34867 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
34199 scalar.* = of_math_result.wrapped_result;34868 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
34869 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
34200 }34870 }
34201 return Value.OverflowArithmeticResult{34871 return Value.OverflowArithmeticResult{
34202 .overflow_bit = try Value.Tag.aggregate.create(sema.arena, overflowed_data),34872 .overflow_bit = (try mod.intern(.{ .aggregate = .{
34203 .wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data),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(),
34204 };34880 };
34205 }34881 }
34206 return sema.intAddWithOverflowScalar(lhs, rhs, ty);34882 return sema.intAddWithOverflowScalar(lhs, rhs, ty);
...@@ -34212,22 +34888,22 @@ fn intAddWithOverflowScalar(...@@ -34212,22 +34888,22 @@ fn intAddWithOverflowScalar(
34212 rhs: Value,34888 rhs: Value,
34213 ty: Type,34889 ty: Type,
34214) !Value.OverflowArithmeticResult {34890) !Value.OverflowArithmeticResult {
34215 const target = sema.mod.getTarget();34891 const mod = sema.mod;
34216 const info = ty.intInfo(target);34892 const info = ty.intInfo(mod);
3421734893
34218 var lhs_space: Value.BigIntSpace = undefined;34894 var lhs_space: Value.BigIntSpace = undefined;
34219 var rhs_space: Value.BigIntSpace = undefined;34895 var rhs_space: Value.BigIntSpace = undefined;
34220 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);34896 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
34221 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);34897 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
34222 const limbs = try sema.arena.alloc(34898 const limbs = try sema.arena.alloc(
34223 std.math.big.Limb,34899 std.math.big.Limb,
34224 std.math.big.int.calcTwosCompLimbCount(info.bits),34900 std.math.big.int.calcTwosCompLimbCount(info.bits),
34225 );34901 );
34226 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };34902 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
34227 const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);34903 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());
34229 return Value.OverflowArithmeticResult{34905 return Value.OverflowArithmeticResult{
34230 .overflow_bit = Value.boolToInt(overflowed),34906 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
34231 .wrapped_result = result,34907 .wrapped_result = result,
34232 };34908 };
34233}34909}
...@@ -34243,14 +34919,13 @@ fn compareAll(...@@ -34243,14 +34919,13 @@ fn compareAll(
34243 rhs: Value,34919 rhs: Value,
34244 ty: Type,34920 ty: Type,
34245) CompileError!bool {34921) CompileError!bool {
34246 if (ty.zigTypeTag() == .Vector) {34922 const mod = sema.mod;
34923 if (ty.zigTypeTag(mod) == .Vector) {
34247 var i: usize = 0;34924 var i: usize = 0;
34248 while (i < ty.vectorLen()) : (i += 1) {34925 while (i < ty.vectorLen(mod)) : (i += 1) {
34249 var lhs_buf: Value.ElemValueBuffer = undefined;34926 const lhs_elem = try lhs.elemValue(sema.mod, i);
34250 var rhs_buf: Value.ElemValueBuffer = undefined;34927 const rhs_elem = try rhs.elemValue(sema.mod, i);
34251 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);34928 if (!(try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod)))) {
34252 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
34253 if (!(try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType()))) {
34254 return false;34929 return false;
34255 }34930 }
34256 }34931 }
...@@ -34267,10 +34942,13 @@ fn compareScalar(...@@ -34267,10 +34942,13 @@ fn compareScalar(
34267 rhs: Value,34942 rhs: Value,
34268 ty: Type,34943 ty: Type,
34269) CompileError!bool {34944) 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);
34270 switch (op) {34948 switch (op) {
34271 .eq => return sema.valuesEqual(lhs, rhs, ty),34949 .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),
34272 .neq => return !(try sema.valuesEqual(lhs, rhs, ty)),34950 .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),
34273 else => return Value.compareHeteroAdvanced(lhs, op, rhs, sema.mod.getTarget(), sema),34951 else => return Value.compareHeteroAdvanced(coerced_lhs, op, coerced_rhs, mod, sema),
34274 }34952 }
34275}34953}
3427634954
...@@ -34291,17 +34969,19 @@ fn compareVector(...@@ -34291,17 +34969,19 @@ fn compareVector(
34291 rhs: Value,34969 rhs: Value,
34292 ty: Type,34970 ty: Type,
34293) !Value {34971) !Value {
34294 assert(ty.zigTypeTag() == .Vector);34972 const mod = sema.mod;
34295 const result_data = try sema.arena.alloc(Value, ty.vectorLen());34973 assert(ty.zigTypeTag(mod) == .Vector);
34974 const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod));
34296 for (result_data, 0..) |*scalar, i| {34975 for (result_data, 0..) |*scalar, i| {
34297 var lhs_buf: Value.ElemValueBuffer = undefined;34976 const lhs_elem = try lhs.elemValue(sema.mod, i);
34298 var rhs_buf: Value.ElemValueBuffer = undefined;34977 const rhs_elem = try rhs.elemValue(sema.mod, i);
34299 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);34978 const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod));
34300 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);34979 scalar.* = try Value.makeBool(res_bool).intern(Type.bool, mod);
34301 const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType());
34302 scalar.* = Value.makeBool(res_bool);
34303 }34980 }
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();
34305}34985}
3430634986
34307/// Returns the type of a pointer to an element.34987/// Returns the type of a pointer to an element.
...@@ -34312,11 +34992,11 @@ fn compareVector(...@@ -34312,11 +34992,11 @@ fn compareVector(
34312/// Handles const-ness and address spaces in particular.34992/// Handles const-ness and address spaces in particular.
34313/// This code is duplicated in `analyzePtrArithmetic`.34993/// This code is duplicated in `analyzePtrArithmetic`.
34314fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {34994fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
34315 const ptr_info = ptr_ty.ptrInfo().data;34995 const mod = sema.mod;
34316 const elem_ty = ptr_ty.elemType2();34996 const ptr_info = ptr_ty.ptrInfo(mod);
34997 const elem_ty = ptr_ty.elemType2(mod);
34317 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;34998 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;
34318 const target = sema.mod.getTarget();34999 const parent_ty = ptr_ty.childType(mod);
34319 const parent_ty = ptr_ty.childType();
3432035000
34321 const VI = Type.Payload.Pointer.Data.VectorIndex;35001 const VI = Type.Payload.Pointer.Data.VectorIndex;
3432235002
...@@ -34324,15 +35004,15 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {...@@ -34324,15 +35004,15 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
34324 host_size: u16 = 0,35004 host_size: u16 = 0,
34325 alignment: u32 = 0,35005 alignment: u32 = 0,
34326 vector_index: VI = .none,35006 vector_index: VI = .none,
34327 } = if (parent_ty.tag() == .vector and ptr_info.size == .One) blk: {35007 } = if (parent_ty.isVector(mod) and ptr_info.size == .One) blk: {
34328 const elem_bits = elem_ty.bitSize(target);35008 const elem_bits = elem_ty.bitSize(mod);
34329 if (elem_bits == 0) break :blk .{};35009 if (elem_bits == 0) break :blk .{};
34330 const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);35010 const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);
34331 if (!is_packed) break :blk .{};35011 if (!is_packed) break :blk .{};
3433235012
34333 break :blk .{35013 break :blk .{
34334 .host_size = @intCast(u16, parent_ty.arrayLen()),35014 .host_size = @intCast(u16, parent_ty.arrayLen(mod)),
34335 .alignment = @intCast(u16, parent_ty.abiAlignment(target)),35015 .alignment = @intCast(u16, parent_ty.abiAlignment(mod)),
34336 .vector_index = if (offset) |some| @intToEnum(VI, some) else .runtime,35016 .vector_index = if (offset) |some| @intToEnum(VI, some) else .runtime,
34337 };35017 };
34338 } else .{};35018 } else .{};
...@@ -34366,3 +35046,42 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {...@@ -34366,3 +35046,42 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
34366 .vector_index = vector_info.vector_index,35046 .vector_index = vector_info.vector_index,
34367 });35047 });
34368}35048}
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 {...@@ -27,13 +27,13 @@ pub const Managed = struct {
27/// Assumes arena allocation. Does a recursive copy.27/// Assumes arena allocation. Does a recursive copy.
28pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue {28pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue {
29 return TypedValue{29 return TypedValue{
30 .ty = try self.ty.copy(arena),30 .ty = self.ty,
31 .val = try self.val.copy(arena),31 .val = try self.val.copy(arena),
32 };32 };
33}33}
3434
35pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool {35pub 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;
37 return a.val.eql(b.val, a.ty, mod);37 return a.val.eql(b.val, a.ty, mod);
38}38}
3939
...@@ -41,8 +41,8 @@ pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void {...@@ -41,8 +41,8 @@ pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void {
41 return tv.val.hash(tv.ty, hasher, mod);41 return tv.val.hash(tv.ty, hasher, mod);
42}42}
4343
44pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value {44pub fn enumToInt(tv: TypedValue, mod: *Module) Allocator.Error!Value {
45 return tv.val.enumToInt(tv.ty, buffer);45 return tv.val.enumToInt(tv.ty, mod);
46}46}
4747
48const max_aggregate_items = 100;48const max_aggregate_items = 100;
...@@ -61,7 +61,10 @@ pub fn format(...@@ -61,7 +61,10 @@ pub fn format(
61) !void {61) !void {
62 _ = options;62 _ = options;
63 comptime std.debug.assert(fmt.len == 0);63 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 };
65}68}
6669
67/// Prints the Value according to the Type, not according to the Value Tag.70/// Prints the Value according to the Type, not according to the Value Tag.
...@@ -70,106 +73,61 @@ pub fn print(...@@ -70,106 +73,61 @@ pub fn print(
70 writer: anytype,73 writer: anytype,
71 level: u8,74 level: u8,
72 mod: *Module,75 mod: *Module,
73) @TypeOf(writer).Error!void {76) (@TypeOf(writer).Error || Allocator.Error)!void {
74 const target = mod.getTarget();
75 var val = tv.val;77 var val = tv.val;
76 var ty = tv.ty;78 var ty = tv.ty;
77 if (val.isVariable(mod))79 const ip = &mod.intern_pool;
78 return writer.writeAll("(variable)");80 while (true) switch (val.ip_index) {
7981 .none => switch (val.tag()) {
80 while (true) switch (val.tag()) {82 .aggregate => return printAggregate(ty, val, writer, level, mod),
81 .u1_type => return writer.writeAll("u1"),83 .@"union" => {
82 .u8_type => return writer.writeAll("u8"),84 if (level == 0) {
83 .i8_type => return writer.writeAll("i8"),85 return writer.writeAll(".{ ... }");
84 .u16_type => return writer.writeAll("u16"),86 }
85 .i16_type => return writer.writeAll("i16"),87 const union_val = val.castTag(.@"union").?.data;
86 .u29_type => return writer.writeAll("u29"),88 try writer.writeAll(".{ ");
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"),
14589
146 .empty_struct_value, .aggregate => {90 try print(.{
147 if (level == 0) {91 .ty = mod.unionPtr(ip.indexToKey(ty.toIntern()).union_type.index).tag_ty,
148 return writer.writeAll(".{ ... }");92 .val = union_val.tag,
149 }93 }, writer, level - 1, mod);
150 if (ty.zigTypeTag() == .Struct) {94 try writer.writeAll(" = ");
151 try writer.writeAll(".{");95 try print(.{
152 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);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 }
154 var i: u32 = 0;107 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);
155 while (i < max_len) : (i += 1) {115 while (i < max_len) : (i += 1) {
156 if (i != 0) try writer.writeAll(", ");116 if (i != 0) try writer.writeAll(", ");
157 switch (ty.tag()) {117 try print(elem_tv, writer, level - 1, mod);
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);
165 }118 }
166 if (ty.structFieldCount() > max_aggregate_items) {119 if (len > max_aggregate_items) {
167 try writer.writeAll(", ...");120 try writer.writeAll(", ...");
168 }121 }
169 return writer.writeAll("}");122 return writer.writeAll(" }");
170 } else {123 },
171 const elem_ty = ty.elemType2();124 .slice => {
172 const len = ty.arrayLen();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
174 if (elem_ty.eql(Type.u8, mod)) str: {132 if (elem_ty.eql(Type.u8, mod)) str: {
175 const max_len = @intCast(usize, std.math.min(len, max_string_len));133 const max_len = @intCast(usize, std.math.min(len, max_string_len));
...@@ -177,11 +135,14 @@ pub fn print(...@@ -177,11 +135,14 @@ pub fn print(
177135
178 var i: u32 = 0;136 var i: u32 = 0;
179 while (i < max_len) : (i += 1) {137 while (i < max_len) : (i += 1) {
180 const elem = val.fieldValue(ty, i);138 const elem_val = payload.ptr.elemValue(mod, i) catch |err| switch (err) {
181 if (elem.isUndef()) break :str;139 error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic
182 buf[i] = std.math.cast(u8, elem.toUnsignedInt(target)) orelse break :str;140 };
141 if (elem_val.isUndef(mod)) break :str;
142 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str;
183 }143 }
184144
145 // TODO would be nice if this had a bit of unicode awareness.
185 const truncated = if (len > max_string_len) " (truncated)" else "";146 const truncated = if (len > max_string_len) " (truncated)" else "";
186 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });147 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
187 }148 }
...@@ -192,315 +153,334 @@ pub fn print(...@@ -192,315 +153,334 @@ pub fn print(
192 var i: u32 = 0;153 var i: u32 = 0;
193 while (i < max_len) : (i += 1) {154 while (i < max_len) : (i += 1) {
194 if (i != 0) try writer.writeAll(", ");155 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 };
195 try print(.{159 try print(.{
196 .ty = elem_ty,160 .ty = elem_ty,
197 .val = val.fieldValue(ty, i),161 .val = elem_val,
198 }, writer, level - 1, mod);162 }, writer, level - 1, mod);
199 }163 }
200 if (len > max_aggregate_items) {164 if (len > max_aggregate_items) {
201 try writer.writeAll(", ...");165 try writer.writeAll(", ...");
202 }166 }
203 return writer.writeAll(" }");167 return writer.writeAll(" }");
204 }168 },
205 },169 .eu_payload => {
206 .@"union" => {170 val = val.castTag(.eu_payload).?.data;
207 if (level == 0) {171 ty = ty.errorUnionPayload(mod);
208 return writer.writeAll(".{ ... }");172 },
209 }173 .opt_payload => {
210 const union_val = val.castTag(.@"union").?.data;174 val = val.castTag(.opt_payload).?.data;
211 try writer.writeAll(".{ ");175 ty = ty.optionalChild(mod);
212176 },
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});
250 },177 },
251 .lazy_size => {178 else => switch (ip.indexToKey(val.toIntern())) {
252 const sub_ty = val.castTag(.lazy_size).?.data;179 .int_type,
253 const x = sub_ty.abiSize(target);180 .ptr_type,
254 return writer.print("{d}", .{x});181 .array_type,
255 },182 .vector_type,
256 .function => return writer.print("(function '{s}')", .{183 .opt_type,
257 mod.declPtr(val.castTag(.function).?.data.owner_decl).name,184 .anyframe_type,
258 }),185 .error_union_type,
259 .extern_fn => return writer.writeAll("(extern function)"),186 .simple_type,
260 .variable => unreachable,187 .struct_type,
261 .decl_ref_mut => {188 .anon_struct_type,
262 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;189 .union_type,
263 const decl = mod.declPtr(decl_index);190 .opaque_type,
264 if (level == 0) {191 .enum_type,
265 return writer.print("(decl ref mut '{s}')", .{decl.name});192 .func_type,
266 }193 .error_set_type,
267 return print(.{194 .inferred_error_set_type,
268 .ty = decl.ty,195 => return Type.print(val.toType(), writer, mod),
269 .val = decl.val,196 .undef => return writer.writeAll("undefined"),
270 }, writer, level - 1, mod);197 .runtime_value => return writer.writeAll("(runtime value)"),
271 },198 .simple_value => |simple_value| switch (simple_value) {
272 .decl_ref => {199 .empty_struct => return printAggregate(ty, val, writer, level, mod),
273 const decl_index = val.castTag(.decl_ref).?.data;200 .generic_poison => return writer.writeAll("(generic poison)"),
274 const decl = mod.declPtr(decl_index);201 else => return writer.writeAll(@tagName(simple_value)),
275 if (level == 0) {202 },
276 return writer.print("(decl ref '{s}')", .{decl.name});203 .variable => return writer.writeAll("(variable)"),
277 }204 .extern_func => |extern_func| return writer.print("(extern function '{}')", .{
278 return print(.{205 mod.declPtr(extern_func.decl).name.fmt(ip),
279 .ty = decl.ty,206 }),
280 .val = decl.val,207 .func => |func| return writer.print("(function '{}')", .{
281 }, writer, level - 1, mod);208 mod.declPtr(mod.funcPtr(func.index).owner_decl).name.fmt(ip),
282 },209 }),
283 .comptime_field_ptr => {210 .int => |int| switch (int.storage) {
284 const payload = val.castTag(.comptime_field_ptr).?.data;211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
285 if (level == 0) {212 .lazy_align => |lazy_ty| return writer.print("{d}", .{
286 return writer.writeAll("(comptime field ptr)");213 lazy_ty.toType().abiAlignment(mod),
287 }214 }),
288 return print(.{215 .lazy_size => |lazy_ty| return writer.print("{d}", .{
289 .ty = payload.field_ty,216 lazy_ty.toType().abiSize(mod),
290 .val = payload.field_val,217 }),
291 }, writer, level - 1, mod);218 },
292 },219 .err => |err| return writer.print("error.{}", .{
293 .elem_ptr => {220 err.name.fmt(ip),
294 const elem_ptr = val.castTag(.elem_ptr).?.data;221 }),
295 try writer.writeAll("&");222 .error_union => |error_union| switch (error_union.val) {
296 if (level == 0) {223 .err_name => |err_name| return writer.print("error.{}", .{
297 try writer.writeAll("(ptr)");224 err_name.fmt(ip),
298 } else {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(");
299 try print(.{244 try print(.{
300 .ty = elem_ptr.elem_ty,245 .ty = Type.type,
301 .val = elem_ptr.array_ptr,246 .val = enum_tag.ty.toValue(),
302 }, writer, level - 1, mod);247 }, writer, level - 1, mod);
303 }248 try writer.writeAll(", ");
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 {
312 try print(.{249 try print(.{
313 .ty = field_ptr.container_ty,250 .ty = ip.typeOf(enum_tag.int).toType(),
314 .val = field_ptr.container_ptr,251 .val = enum_tag.int.toValue(),
315 }, writer, level - 1, mod);252 }, writer, level - 1, mod);
316 }253 try writer.writeAll(")");
317254 return;
318 if (field_ptr.container_ty.zigTypeTag() == .Struct) {255 },
319 switch (field_ptr.container_ty.tag()) {256 .empty_enum_value => return writer.writeAll("(empty enum value)"),
320 .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}),257 .float => |float| switch (float.storage) {
321 else => {258 inline else => |x| return writer.print("{d}", .{@floatCast(f64, x)}),
322 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index);259 },
323 return writer.print(".{s}", .{field_name});260 .ptr => |ptr| {
324 },261 if (ptr.addr == .int) {
325 }262 const i = ip.indexToKey(ptr.addr.int).int;
326 } else if (field_ptr.container_ty.zigTypeTag() == .Union) {263 switch (i.storage) {
327 const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index];264 inline else => |addr| return writer.print("{x:0>8}", .{addr}),
328 return writer.print(".{s}", .{field_name});265 }
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,
334 }266 }
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: {268 const ptr_ty = ip.indexToKey(ty.toIntern()).ptr_type;
389 const max_len = @intCast(usize, std.math.min(len, max_string_len));269 if (ptr_ty.flags.size == .Slice) {
390 var buf: [max_string_len]u8 = undefined;270 if (level == 0) {
391271 return writer.writeAll(".{ ... }");
392 var i: u32 = 0;272 }
393 while (i < max_len) : (i += 1) {273 const elem_ty = ptr_ty.child.toType();
394 var elem_buf: Value.ElemValueBuffer = undefined;274 const len = ptr.len.toValue().toUnsignedInt(mod);
395 const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);275 if (elem_ty.eql(Type.u8, mod)) str: {
396 if (elem_val.isUndef()) break :str;276 const max_len = @min(len, max_string_len);
397 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(target)) orelse break :str;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(" }");
398 }299 }
399300
400 // TODO would be nice if this had a bit of unicode awareness.301 switch (ptr.addr) {
401 const truncated = if (len > max_string_len) " (truncated)" else "";302 .decl => |decl_index| {
402 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });303 const decl = mod.declPtr(decl_index);
403 }304 if (level == 0) return writer.print("(decl '{}')", .{decl.name.fmt(ip)});
404305 return print(.{
405 try writer.writeAll(".{ ");306 .ty = decl.ty,
406307 .val = decl.val,
407 const max_len = std.math.min(len, max_aggregate_items);308 }, writer, level - 1, mod);
408 var i: u32 = 0;309 },
409 while (i < max_len) : (i += 1) {310 .mut_decl => |mut_decl| {
410 if (i != 0) try writer.writeAll(", ");311 const decl = mod.declPtr(mut_decl.decl);
411 var buf: Value.ElemValueBuffer = undefined;312 if (level == 0) return writer.print("(mut decl '{}')", .{decl.name.fmt(ip)});
412 try print(.{313 return print(.{
413 .ty = elem_ty,314 .ty = decl.ty,
414 .val = payload.ptr.elemValueBuffer(mod, i, &buf),315 .val = decl.val,
415 }, writer, level - 1, mod);316 }, writer, level - 1, mod);
416 }317 },
417 if (len > max_aggregate_items) {318 .comptime_field => |field_val_ip| {
418 try writer.writeAll(", ...");319 return print(.{
419 }320 .ty = ip.typeOf(field_val_ip).toType(),
420 return writer.writeAll(" }");321 .val = field_val_ip.toValue(),
421 },322 }, writer, level - 1, mod);
422 .float_16 => return writer.print("{d}", .{val.castTag(.float_16).?.data}),323 },
423 .float_32 => return writer.print("{d}", .{val.castTag(.float_32).?.data}),324 .int => unreachable,
424 .float_64 => return writer.print("{d}", .{val.castTag(.float_64).?.data}),325 .eu_payload => |eu_ip| {
425 .float_80 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_80).?.data)}),326 try writer.writeAll("(payload of ");
426 .float_128 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_128).?.data)}),327 try print(.{
427 .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}),328 .ty = ip.typeOf(eu_ip).toType(),
428 .eu_payload => {329 .val = eu_ip.toValue(),
429 val = val.castTag(.eu_payload).?.data;330 }, writer, level - 1, mod);
430 ty = ty.errorUnionPayload();331 try writer.writeAll(")");
431 },332 },
432 .opt_payload => {333 .opt_payload => |opt_ip| {
433 val = val.castTag(.opt_payload).?.data;334 try print(.{
434 var buf: Type.Payload.ElemType = undefined;335 .ty = ip.typeOf(opt_ip).toType(),
435 ty = ty.optionalChild(&buf);336 .val = opt_ip.toValue(),
436 return print(.{ .ty = ty, .val = val }, writer, level, mod);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,
437 },414 },
438 .eu_payload_ptr => {415 };
439 try writer.writeAll("&");416}
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 };
447417
448 try writer.writeAll("@as(");418fn printAggregate(
449 try print(.{419 ty: Type,
450 .ty = Type.type,420 val: Value,
451 .val = Value.initPayload(&ty_val.base),421 writer: anytype,
452 }, writer, level - 1, mod);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 = .{435 const field_name = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
457 .base = .{ .tag = .single_mut_pointer },436 .struct_type => |x| mod.structPtrUnwrap(x.index).?.fields.keys()[i].toOptional(),
458 .data = data.container_ty,437 .anon_struct_type => |x| if (x.isTuple()) .none else x.names[i].toOptional(),
438 else => unreachable,
459 };439 };
460440
441 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(&mod.intern_pool)});
461 try print(.{442 try print(.{
462 .ty = Type.initPayload(&ptr_ty.base),443 .ty = ty.structFieldType(i, mod),
463 .val = data.container_ptr,444 .val = try val.fieldValue(mod, i),
464 }, writer, level - 1, mod);445 }, 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("))");459 var i: u32 = 0;
467 return;460 while (i < max_len) : (i += 1) {
468 },461 const elem = try val.fieldValue(mod, i);
469 .opt_payload_ptr => {462 if (elem.isUndef(mod)) break :str;
470 const data = val.castTag(.opt_payload_ptr).?.data;463 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
471464 }
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);
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 = .{470 try writer.writeAll(".{ ");
486 .base = .{ .tag = .single_mut_pointer },
487 .data = data.container_ty,
488 };
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(", ");
490 try print(.{476 try print(.{
491 .ty = Type.initPayload(&ptr_ty.base),477 .ty = elem_ty,
492 .val = data.container_ptr,478 .val = try val.fieldValue(mod, i),
493 }, writer, level - 1, mod);479 }, writer, level - 1, mod);
494480 }
495 try writer.writeAll("))");481 if (len > max_aggregate_items) {
496 return;482 try writer.writeAll(", ...");
497 },483 }
498484 return writer.writeAll(" }");
499 // TODO these should not appear in this function485 }
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 };
506}486}
src/Zir.zig+97-435
...@@ -19,6 +19,7 @@ const BigIntConst = std.math.big.int.Const;...@@ -19,6 +19,7 @@ const BigIntConst = std.math.big.int.Const;
19const BigIntMutable = std.math.big.int.Mutable;19const BigIntMutable = std.math.big.int.Mutable;
20const Ast = std.zig.Ast;20const Ast = std.zig.Ast;
2121
22const InternPool = @import("InternPool.zig");
22const Zir = @This();23const Zir = @This();
23const Type = @import("type.zig").Type;24const Type = @import("type.zig").Type;
24const Value = @import("value.zig").Value;25const Value = @import("value.zig").Value;
...@@ -2041,448 +2042,103 @@ pub const Inst = struct {...@@ -2041,448 +2042,103 @@ pub const Inst = struct {
2041 /// The position of a ZIR instruction within the `Zir` instructions array.2042 /// The position of a ZIR instruction within the `Zir` instructions array.
2042 pub const Index = u32;2043 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.
2045 ///2046 ///
2046 /// If the Ref has a tag in this enum, it refers to a TypedValue.2047 /// If the integer tag value is < InternPool.static_len, then it
2047 ///2048 /// corresponds to an InternPool index. Otherwise, this refers to a ZIR
2048 /// If the value of a Ref does not have a tag, it refers to a ZIR instruction.2049 /// 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.
2055 ///2050 ///
2056 /// The tag type is specified so that it is safe to bitcast between `[]u32`2051 /// The tag type is specified so that it is safe to bitcast between `[]u32`
2057 /// and `[]Ref`.2052 /// and `[]Ref`.
2058 pub const Ref = enum(u32) {2053 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),
2059 /// This Ref does not correspond to any ZIR instruction or constant2138 /// This Ref does not correspond to any ZIR instruction or constant
2060 /// value and may instead be used as a sentinel to indicate null.2139 /// value and may instead be used as a sentinel to indicate null.
2061 none,2140 none = @enumToInt(InternPool.Index.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
2160 _,2141 _,
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),
2486 };2142 };
24872143
2488 /// All instructions have an 8-byte payload, which is contained within2144 /// 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 {...@@ -4163,13 +3819,14 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4163 };3819 };
4164}3820}
41653821
4166const ref_start_index: u32 = Inst.Ref.typed_value_map.len;3822pub const ref_start_index: u32 = InternPool.static_len;
41673823
4168pub fn indexToRef(inst: Inst.Index) Inst.Ref {3824pub fn indexToRef(inst: Inst.Index) Inst.Ref {
4169 return @intToEnum(Inst.Ref, ref_start_index + inst);3825 return @intToEnum(Inst.Ref, ref_start_index + inst);
4170}3826}
41713827
4172pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {3828pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
3829 assert(inst != .none);
4173 const ref_int = @enumToInt(inst);3830 const ref_int = @enumToInt(inst);
4174 if (ref_int >= ref_start_index) {3831 if (ref_int >= ref_start_index) {
4175 return ref_int - ref_start_index;3832 return ref_int - ref_start_index;
...@@ -4177,3 +3834,8 @@ pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {...@@ -4177,3 +3834,8 @@ pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
4177 return null;3834 return null;
4178 }3835 }
4179}3836}
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();...@@ -328,7 +328,7 @@ const Self = @This();
328pub fn generate(328pub fn generate(
329 bin_file: *link.File,329 bin_file: *link.File,
330 src_loc: Module.SrcLoc,330 src_loc: Module.SrcLoc,
331 module_fn: *Module.Fn,331 module_fn_index: Module.Fn.Index,
332 air: Air,332 air: Air,
333 liveness: Liveness,333 liveness: Liveness,
334 code: *std.ArrayList(u8),334 code: *std.ArrayList(u8),
...@@ -339,6 +339,7 @@ pub fn generate(...@@ -339,6 +339,7 @@ pub fn generate(
339 }339 }
340340
341 const mod = bin_file.options.module.?;341 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);
342 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
343 assert(fn_owner_decl.has_tv);344 assert(fn_owner_decl.has_tv);
344 const fn_type = fn_owner_decl.ty;345 const fn_type = fn_owner_decl.ty;
...@@ -471,7 +472,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -471,7 +472,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
471}472}
472473
473fn gen(self: *Self) !void {474fn 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);
475 if (cc != .Naked) {477 if (cc != .Naked) {
476 // stp fp, lr, [sp, #-16]!478 // stp fp, lr, [sp, #-16]!
477 _ = try self.addInst(.{479 _ = try self.addInst(.{
...@@ -520,10 +522,10 @@ fn gen(self: *Self) !void {...@@ -520,10 +522,10 @@ fn gen(self: *Self) !void {
520 const inst = self.air.getMainBody()[arg_index];522 const inst = self.air.getMainBody()[arg_index];
521 assert(self.air.instructions.items(.tag)[inst] == .arg);523 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.*));527 const abi_size = @intCast(u32, ty.abiSize(mod));
526 const abi_align = ty.abiAlignment(self.target.*);528 const abi_align = ty.abiAlignment(mod);
527 const stack_offset = try self.allocMem(abi_size, abi_align, inst);529 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
528 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });530 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
529531
...@@ -652,13 +654,14 @@ fn gen(self: *Self) !void {...@@ -652,13 +654,14 @@ fn gen(self: *Self) !void {
652}654}
653655
654fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {656fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
657 const mod = self.bin_file.options.module.?;
658 const ip = &mod.intern_pool;
655 const air_tags = self.air.instructions.items(.tag);659 const air_tags = self.air.instructions.items(.tag);
656660
657 for (body) |inst| {661 for (body) |inst| {
658 // TODO: remove now-redundant isUnused calls from AIR handler functions662 // 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))
660 continue;664 continue;
661 }
662665
663 const old_air_bookkeeping = self.air_bookkeeping;666 const old_air_bookkeeping = self.air_bookkeeping;
664 try self.ensureProcessDeathCapacity(Liveness.bpi);667 try self.ensureProcessDeathCapacity(Liveness.bpi);
...@@ -842,8 +845,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -842,8 +845,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
842 .ptr_elem_val => try self.airPtrElemVal(inst),845 .ptr_elem_val => try self.airPtrElemVal(inst),
843 .ptr_elem_ptr => try self.airPtrElemPtr(inst),846 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
844847
845 .constant => unreachable, // excluded from function bodies848 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
846 .const_ty => unreachable, // excluded from function bodies
847 .unreach => self.finishAirBookkeeping(),849 .unreach => self.finishAirBookkeeping(),
848850
849 .optional_payload => try self.airOptionalPayload(inst),851 .optional_payload => try self.airOptionalPayload(inst),
...@@ -916,8 +918,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -916,8 +918,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
916918
917/// Asserts there is already capacity to insert into top branch inst_table.919/// Asserts there is already capacity to insert into top branch inst_table.
918fn processDeath(self: *Self, inst: Air.Inst.Index) void {920fn processDeath(self: *Self, inst: Air.Inst.Index) void {
919 const air_tags = self.air.instructions.items(.tag);921 assert(self.air.instructions.items(.tag)[inst] != .interned);
920 if (air_tags[inst] == .constant) return; // Constants are immortal.
921 // When editing this function, note that the logic must synchronize with `reuseOperand`.922 // When editing this function, note that the logic must synchronize with `reuseOperand`.
922 const prev_value = self.getResolvedInstValue(inst);923 const prev_value = self.getResolvedInstValue(inst);
923 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];924 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...@@ -951,8 +952,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
951 tomb_bits >>= 1;952 tomb_bits >>= 1;
952 if (!dies) continue;953 if (!dies) continue;
953 const op_int = @enumToInt(op);954 const op_int = @enumToInt(op);
954 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;955 if (op_int < Air.ref_start_index) continue;
955 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);956 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
956 self.processDeath(op_index);957 self.processDeath(op_index);
957 }958 }
958 const is_used = @truncate(u1, tomb_bits) == 0;959 const is_used = @truncate(u1, tomb_bits) == 0;
...@@ -1026,31 +1027,31 @@ fn allocMem(...@@ -1026,31 +1027,31 @@ fn allocMem(
10261027
1027/// Use a pointer instruction as the basis for allocating stack memory.1028/// Use a pointer instruction as the basis for allocating stack memory.
1028fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {1029fn 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)) {
1032 // return the stack offset 0. Stack offset 0 will be where all1034 // return the stack offset 0. Stack offset 0 will be where all
1033 // zero-sized stack allocations live as non-zero-sized1035 // zero-sized stack allocations live as non-zero-sized
1034 // allocations will always have an offset > 0.1036 // allocations will always have an offset > 0.
1035 return @as(u32, 0);1037 return @as(u32, 0);
1036 }1038 }
10371039
1038 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {1040 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
1039 const mod = self.bin_file.options.module.?;
1040 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});1041 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
1041 };1042 };
1042 // TODO swap this for inst.ty.ptrAlign1043 // 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
1045 return self.allocMem(abi_size, abi_align, inst);1046 return self.allocMem(abi_size, abi_align, inst);
1046}1047}
10471048
1048fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {1049fn 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 {
1051 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});1052 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
1052 };1053 };
1053 const abi_align = elem_ty.abiAlignment(self.target.*);1054 const abi_align = elem_ty.abiAlignment(mod);
10541055
1055 if (reg_ok) {1056 if (reg_ok) {
1056 // Make sure the type can fit in a register before we try to allocate one.1057 // 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...@@ -1066,7 +1067,7 @@ fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst
1066}1067}
10671068
1068pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {1069pub 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);
1070 log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });1071 log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });
10711072
1072 const reg_mcv = self.getResolvedInstValue(inst);1073 const reg_mcv = self.getResolvedInstValue(inst);
...@@ -1078,14 +1079,14 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -1078,14 +1079,14 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
10781079
1079 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1080 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1080 try branch.inst_table.put(self.gpa, inst, stack_mcv);1081 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);
1082}1083}
10831084
1084/// Save the current instruction stored in the compare flags if1085/// Save the current instruction stored in the compare flags if
1085/// occupied1086/// occupied
1086fn spillCompareFlagsIfOccupied(self: *Self) !void {1087fn spillCompareFlagsIfOccupied(self: *Self) !void {
1087 if (self.compare_flags_inst) |inst_to_save| {1088 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);
1089 const mcv = self.getResolvedInstValue(inst_to_save);1090 const mcv = self.getResolvedInstValue(inst_to_save);
1090 const new_mcv = switch (mcv) {1091 const new_mcv = switch (mcv) {
1091 .compare_flags => try self.allocRegOrMem(ty, true, inst_to_save),1092 .compare_flags => try self.allocRegOrMem(ty, true, inst_to_save),
...@@ -1093,7 +1094,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -1093,7 +1094,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
1093 else => unreachable, // mcv doesn't occupy the compare flags1094 else => unreachable, // mcv doesn't occupy the compare flags
1094 };1095 };
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);
1097 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });1098 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
10981099
1099 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1100 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 {...@@ -1125,9 +1126,9 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
1125/// This can have a side effect of spilling instructions to the stack to free up a register.1126/// This can have a side effect of spilling instructions to the stack to free up a register.
1126fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {1127fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
1127 const raw_reg = try self.register_manager.allocReg(reg_owner, gp);1128 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);
1129 const reg = self.registerAlias(raw_reg, ty);1130 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);
1131 return MCValue{ .register = reg };1132 return MCValue{ .register = reg };
1132}1133}
11331134
...@@ -1137,17 +1138,14 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {...@@ -1137,17 +1138,14 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
1137}1138}
11381139
1139fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {1140fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1141 const mod = self.bin_file.options.module.?;
1140 const result: MCValue = switch (self.ret_mcv) {1142 const result: MCValue = switch (self.ret_mcv) {
1141 .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) },1143 .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) },
1142 .stack_offset => blk: {1144 .stack_offset => blk: {
1143 // self.ret_mcv is an address to where this function1145 // self.ret_mcv is an address to where this function
1144 // should store its result into1146 // should store its result into
1145 const ret_ty = self.fn_type.fnReturnType();1147 const ret_ty = self.fn_type.fnReturnType(mod);
1146 var ptr_ty_payload: Type.Payload.ElemType = .{1148 const ptr_ty = try mod.singleMutPtrType(ret_ty);
1147 .base = .{ .tag = .single_mut_pointer },
1148 .data = ret_ty,
1149 };
1150 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
11511149
1152 // addr_reg will contain the address of where to store the1150 // addr_reg will contain the address of where to store the
1153 // result into1151 // result into
...@@ -1177,13 +1175,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1177,13 +1175,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1177 if (self.liveness.isUnused(inst))1175 if (self.liveness.isUnused(inst))
1178 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });1176 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
11791177
1178 const mod = self.bin_file.options.module.?;
1180 const operand = ty_op.operand;1179 const operand = ty_op.operand;
1181 const operand_mcv = try self.resolveInst(operand);1180 const operand_mcv = try self.resolveInst(operand);
1182 const operand_ty = self.air.typeOf(operand);1181 const operand_ty = self.typeOf(operand);
1183 const operand_info = operand_ty.intInfo(self.target.*);1182 const operand_info = operand_ty.intInfo(mod);
11841183
1185 const dest_ty = self.air.typeOfIndex(inst);1184 const dest_ty = self.typeOfIndex(inst);
1186 const dest_info = dest_ty.intInfo(self.target.*);1185 const dest_info = dest_ty.intInfo(mod);
11871186
1188 const result: MCValue = result: {1187 const result: MCValue = result: {
1189 const operand_lock: ?RegisterLock = switch (operand_mcv) {1188 const operand_lock: ?RegisterLock = switch (operand_mcv) {
...@@ -1199,14 +1198,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1199,14 +1198,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
11991198
1200 if (dest_info.bits > operand_info.bits) {1199 if (dest_info.bits > operand_info.bits) {
1201 const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst);1200 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);
1203 break :result dest_mcv;1202 break :result dest_mcv;
1204 } else {1203 } else {
1205 if (self.reuseOperand(inst, operand, 0, truncated)) {1204 if (self.reuseOperand(inst, operand, 0, truncated)) {
1206 break :result truncated;1205 break :result truncated;
1207 } else {1206 } else {
1208 const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst);1207 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);
1210 break :result dest_mcv;1209 break :result dest_mcv;
1211 }1210 }
1212 }1211 }
...@@ -1257,8 +1256,9 @@ fn trunc(...@@ -1257,8 +1256,9 @@ fn trunc(
1257 operand_ty: Type,1256 operand_ty: Type,
1258 dest_ty: Type,1257 dest_ty: Type,
1259) !MCValue {1258) !MCValue {
1260 const info_a = operand_ty.intInfo(self.target.*);1259 const mod = self.bin_file.options.module.?;
1261 const info_b = dest_ty.intInfo(self.target.*);1260 const info_a = operand_ty.intInfo(mod);
1261 const info_b = dest_ty.intInfo(mod);
12621262
1263 if (info_b.bits <= 64) {1263 if (info_b.bits <= 64) {
1264 const operand_reg = switch (operand) {1264 const operand_reg = switch (operand) {
...@@ -1300,8 +1300,8 @@ fn trunc(...@@ -1300,8 +1300,8 @@ fn trunc(
1300fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {1300fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
1301 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1301 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1302 const operand = try self.resolveInst(ty_op.operand);1302 const operand = try self.resolveInst(ty_op.operand);
1303 const operand_ty = self.air.typeOf(ty_op.operand);1303 const operand_ty = self.typeOf(ty_op.operand);
1304 const dest_ty = self.air.typeOfIndex(inst);1304 const dest_ty = self.typeOfIndex(inst);
13051305
1306 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {1306 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
1307 break :blk try self.trunc(inst, operand, operand_ty, dest_ty);1307 break :blk try self.trunc(inst, operand, operand_ty, dest_ty);
...@@ -1319,15 +1319,16 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -1319,15 +1319,16 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
13191319
1320fn airNot(self: *Self, inst: Air.Inst.Index) !void {1320fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1321 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1321 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1322 const mod = self.bin_file.options.module.?;
1322 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1323 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1323 const operand = try self.resolveInst(ty_op.operand);1324 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);
1325 switch (operand) {1326 switch (operand) {
1326 .dead => unreachable,1327 .dead => unreachable,
1327 .unreach => unreachable,1328 .unreach => unreachable,
1328 .compare_flags => |cond| break :result MCValue{ .compare_flags = cond.negate() },1329 .compare_flags => |cond| break :result MCValue{ .compare_flags = cond.negate() },
1329 else => {1330 else => {
1330 switch (operand_ty.zigTypeTag()) {1331 switch (operand_ty.zigTypeTag(mod)) {
1331 .Bool => {1332 .Bool => {
1332 // TODO convert this to mvn + and1333 // TODO convert this to mvn + and
1333 const op_reg = switch (operand) {1334 const op_reg = switch (operand) {
...@@ -1361,7 +1362,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1361,7 +1362,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1361 },1362 },
1362 .Vector => return self.fail("TODO bitwise not for vectors", .{}),1363 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
1363 .Int => {1364 .Int => {
1364 const int_info = operand_ty.intInfo(self.target.*);1365 const int_info = operand_ty.intInfo(mod);
1365 if (int_info.bits <= 64) {1366 if (int_info.bits <= 64) {
1366 const op_reg = switch (operand) {1367 const op_reg = switch (operand) {
1367 .register => |r| r,1368 .register => |r| r,
...@@ -1413,13 +1414,13 @@ fn minMax(...@@ -1413,13 +1414,13 @@ fn minMax(
1413 rhs_ty: Type,1414 rhs_ty: Type,
1414 maybe_inst: ?Air.Inst.Index,1415 maybe_inst: ?Air.Inst.Index,
1415) !MCValue {1416) !MCValue {
1416 switch (lhs_ty.zigTypeTag()) {1417 const mod = self.bin_file.options.module.?;
1418 switch (lhs_ty.zigTypeTag(mod)) {
1417 .Float => return self.fail("TODO ARM min/max on floats", .{}),1419 .Float => return self.fail("TODO ARM min/max on floats", .{}),
1418 .Vector => return self.fail("TODO ARM min/max on vectors", .{}),1420 .Vector => return self.fail("TODO ARM min/max on vectors", .{}),
1419 .Int => {1421 .Int => {
1420 const mod = self.bin_file.options.module.?;
1421 assert(lhs_ty.eql(rhs_ty, mod));1422 assert(lhs_ty.eql(rhs_ty, mod));
1422 const int_info = lhs_ty.intInfo(self.target.*);1423 const int_info = lhs_ty.intInfo(mod);
1423 if (int_info.bits <= 64) {1424 if (int_info.bits <= 64) {
1424 var lhs_reg: Register = undefined;1425 var lhs_reg: Register = undefined;
1425 var rhs_reg: Register = undefined;1426 var rhs_reg: Register = undefined;
...@@ -1488,8 +1489,8 @@ fn minMax(...@@ -1488,8 +1489,8 @@ fn minMax(
1488fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {1489fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {
1489 const tag = self.air.instructions.items(.tag)[inst];1490 const tag = self.air.instructions.items(.tag)[inst];
1490 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1491 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1491 const lhs_ty = self.air.typeOf(bin_op.lhs);1492 const lhs_ty = self.typeOf(bin_op.lhs);
1492 const rhs_ty = self.air.typeOf(bin_op.rhs);1493 const rhs_ty = self.typeOf(bin_op.rhs);
14931494
1494 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1495 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1495 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };1496 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
...@@ -1508,9 +1509,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -1508,9 +1509,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1508 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1509 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1509 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1510 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1510 const ptr = try self.resolveInst(bin_op.lhs);1511 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);
1512 const len = try self.resolveInst(bin_op.rhs);1513 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
1515 const ptr_bits = self.target.ptrBitWidth();1516 const ptr_bits = self.target.ptrBitWidth();
1516 const ptr_bytes = @divExact(ptr_bits, 8);1517 const ptr_bytes = @divExact(ptr_bits, 8);
...@@ -1907,12 +1908,12 @@ fn addSub(...@@ -1907,12 +1908,12 @@ fn addSub(
1907 maybe_inst: ?Air.Inst.Index,1908 maybe_inst: ?Air.Inst.Index,
1908) InnerError!MCValue {1909) InnerError!MCValue {
1909 const mod = self.bin_file.options.module.?;1910 const mod = self.bin_file.options.module.?;
1910 switch (lhs_ty.zigTypeTag()) {1911 switch (lhs_ty.zigTypeTag(mod)) {
1911 .Float => return self.fail("TODO binary operations on floats", .{}),1912 .Float => return self.fail("TODO binary operations on floats", .{}),
1912 .Vector => return self.fail("TODO binary operations on vectors", .{}),1913 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1913 .Int => {1914 .Int => {
1914 assert(lhs_ty.eql(rhs_ty, mod));1915 assert(lhs_ty.eql(rhs_ty, mod));
1915 const int_info = lhs_ty.intInfo(self.target.*);1916 const int_info = lhs_ty.intInfo(mod);
1916 if (int_info.bits <= 64) {1917 if (int_info.bits <= 64) {
1917 const lhs_immediate = try lhs_bind.resolveToImmediate(self);1918 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
1918 const rhs_immediate = try rhs_bind.resolveToImmediate(self);1919 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
...@@ -1968,11 +1969,11 @@ fn mul(...@@ -1968,11 +1969,11 @@ fn mul(
1968 maybe_inst: ?Air.Inst.Index,1969 maybe_inst: ?Air.Inst.Index,
1969) InnerError!MCValue {1970) InnerError!MCValue {
1970 const mod = self.bin_file.options.module.?;1971 const mod = self.bin_file.options.module.?;
1971 switch (lhs_ty.zigTypeTag()) {1972 switch (lhs_ty.zigTypeTag(mod)) {
1972 .Vector => return self.fail("TODO binary operations on vectors", .{}),1973 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1973 .Int => {1974 .Int => {
1974 assert(lhs_ty.eql(rhs_ty, mod));1975 assert(lhs_ty.eql(rhs_ty, mod));
1975 const int_info = lhs_ty.intInfo(self.target.*);1976 const int_info = lhs_ty.intInfo(mod);
1976 if (int_info.bits <= 64) {1977 if (int_info.bits <= 64) {
1977 // TODO add optimisations for multiplication1978 // TODO add optimisations for multiplication
1978 // with immediates, for example a * 2 can be1979 // with immediates, for example a * 2 can be
...@@ -1999,7 +2000,8 @@ fn divFloat(...@@ -1999,7 +2000,8 @@ fn divFloat(
1999 _ = rhs_ty;2000 _ = rhs_ty;
2000 _ = maybe_inst;2001 _ = maybe_inst;
20012002
2002 switch (lhs_ty.zigTypeTag()) {2003 const mod = self.bin_file.options.module.?;
2004 switch (lhs_ty.zigTypeTag(mod)) {
2003 .Float => return self.fail("TODO div_float", .{}),2005 .Float => return self.fail("TODO div_float", .{}),
2004 .Vector => return self.fail("TODO div_float on vectors", .{}),2006 .Vector => return self.fail("TODO div_float on vectors", .{}),
2005 else => unreachable,2007 else => unreachable,
...@@ -2015,12 +2017,12 @@ fn divTrunc(...@@ -2015,12 +2017,12 @@ fn divTrunc(
2015 maybe_inst: ?Air.Inst.Index,2017 maybe_inst: ?Air.Inst.Index,
2016) InnerError!MCValue {2018) InnerError!MCValue {
2017 const mod = self.bin_file.options.module.?;2019 const mod = self.bin_file.options.module.?;
2018 switch (lhs_ty.zigTypeTag()) {2020 switch (lhs_ty.zigTypeTag(mod)) {
2019 .Float => return self.fail("TODO div on floats", .{}),2021 .Float => return self.fail("TODO div on floats", .{}),
2020 .Vector => return self.fail("TODO div on vectors", .{}),2022 .Vector => return self.fail("TODO div on vectors", .{}),
2021 .Int => {2023 .Int => {
2022 assert(lhs_ty.eql(rhs_ty, mod));2024 assert(lhs_ty.eql(rhs_ty, mod));
2023 const int_info = lhs_ty.intInfo(self.target.*);2025 const int_info = lhs_ty.intInfo(mod);
2024 if (int_info.bits <= 64) {2026 if (int_info.bits <= 64) {
2025 switch (int_info.signedness) {2027 switch (int_info.signedness) {
2026 .signed => {2028 .signed => {
...@@ -2049,12 +2051,12 @@ fn divFloor(...@@ -2049,12 +2051,12 @@ fn divFloor(
2049 maybe_inst: ?Air.Inst.Index,2051 maybe_inst: ?Air.Inst.Index,
2050) InnerError!MCValue {2052) InnerError!MCValue {
2051 const mod = self.bin_file.options.module.?;2053 const mod = self.bin_file.options.module.?;
2052 switch (lhs_ty.zigTypeTag()) {2054 switch (lhs_ty.zigTypeTag(mod)) {
2053 .Float => return self.fail("TODO div on floats", .{}),2055 .Float => return self.fail("TODO div on floats", .{}),
2054 .Vector => return self.fail("TODO div on vectors", .{}),2056 .Vector => return self.fail("TODO div on vectors", .{}),
2055 .Int => {2057 .Int => {
2056 assert(lhs_ty.eql(rhs_ty, mod));2058 assert(lhs_ty.eql(rhs_ty, mod));
2057 const int_info = lhs_ty.intInfo(self.target.*);2059 const int_info = lhs_ty.intInfo(mod);
2058 if (int_info.bits <= 64) {2060 if (int_info.bits <= 64) {
2059 switch (int_info.signedness) {2061 switch (int_info.signedness) {
2060 .signed => {2062 .signed => {
...@@ -2082,12 +2084,12 @@ fn divExact(...@@ -2082,12 +2084,12 @@ fn divExact(
2082 maybe_inst: ?Air.Inst.Index,2084 maybe_inst: ?Air.Inst.Index,
2083) InnerError!MCValue {2085) InnerError!MCValue {
2084 const mod = self.bin_file.options.module.?;2086 const mod = self.bin_file.options.module.?;
2085 switch (lhs_ty.zigTypeTag()) {2087 switch (lhs_ty.zigTypeTag(mod)) {
2086 .Float => return self.fail("TODO div on floats", .{}),2088 .Float => return self.fail("TODO div on floats", .{}),
2087 .Vector => return self.fail("TODO div on vectors", .{}),2089 .Vector => return self.fail("TODO div on vectors", .{}),
2088 .Int => {2090 .Int => {
2089 assert(lhs_ty.eql(rhs_ty, mod));2091 assert(lhs_ty.eql(rhs_ty, mod));
2090 const int_info = lhs_ty.intInfo(self.target.*);2092 const int_info = lhs_ty.intInfo(mod);
2091 if (int_info.bits <= 64) {2093 if (int_info.bits <= 64) {
2092 switch (int_info.signedness) {2094 switch (int_info.signedness) {
2093 .signed => {2095 .signed => {
...@@ -2118,12 +2120,12 @@ fn rem(...@@ -2118,12 +2120,12 @@ fn rem(
2118 _ = maybe_inst;2120 _ = maybe_inst;
21192121
2120 const mod = self.bin_file.options.module.?;2122 const mod = self.bin_file.options.module.?;
2121 switch (lhs_ty.zigTypeTag()) {2123 switch (lhs_ty.zigTypeTag(mod)) {
2122 .Float => return self.fail("TODO rem/mod on floats", .{}),2124 .Float => return self.fail("TODO rem/mod on floats", .{}),
2123 .Vector => return self.fail("TODO rem/mod on vectors", .{}),2125 .Vector => return self.fail("TODO rem/mod on vectors", .{}),
2124 .Int => {2126 .Int => {
2125 assert(lhs_ty.eql(rhs_ty, mod));2127 assert(lhs_ty.eql(rhs_ty, mod));
2126 const int_info = lhs_ty.intInfo(self.target.*);2128 const int_info = lhs_ty.intInfo(mod);
2127 if (int_info.bits <= 64) {2129 if (int_info.bits <= 64) {
2128 var lhs_reg: Register = undefined;2130 var lhs_reg: Register = undefined;
2129 var rhs_reg: Register = undefined;2131 var rhs_reg: Register = undefined;
...@@ -2188,7 +2190,8 @@ fn modulo(...@@ -2188,7 +2190,8 @@ fn modulo(
2188 _ = rhs_ty;2190 _ = rhs_ty;
2189 _ = maybe_inst;2191 _ = maybe_inst;
21902192
2191 switch (lhs_ty.zigTypeTag()) {2193 const mod = self.bin_file.options.module.?;
2194 switch (lhs_ty.zigTypeTag(mod)) {
2192 .Float => return self.fail("TODO mod on floats", .{}),2195 .Float => return self.fail("TODO mod on floats", .{}),
2193 .Vector => return self.fail("TODO mod on vectors", .{}),2196 .Vector => return self.fail("TODO mod on vectors", .{}),
2194 .Int => return self.fail("TODO mod on ints", .{}),2197 .Int => return self.fail("TODO mod on ints", .{}),
...@@ -2205,10 +2208,11 @@ fn wrappingArithmetic(...@@ -2205,10 +2208,11 @@ fn wrappingArithmetic(
2205 rhs_ty: Type,2208 rhs_ty: Type,
2206 maybe_inst: ?Air.Inst.Index,2209 maybe_inst: ?Air.Inst.Index,
2207) InnerError!MCValue {2210) InnerError!MCValue {
2208 switch (lhs_ty.zigTypeTag()) {2211 const mod = self.bin_file.options.module.?;
2212 switch (lhs_ty.zigTypeTag(mod)) {
2209 .Vector => return self.fail("TODO binary operations on vectors", .{}),2213 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2210 .Int => {2214 .Int => {
2211 const int_info = lhs_ty.intInfo(self.target.*);2215 const int_info = lhs_ty.intInfo(mod);
2212 if (int_info.bits <= 64) {2216 if (int_info.bits <= 64) {
2213 // Generate an add/sub/mul2217 // Generate an add/sub/mul
2214 const result: MCValue = switch (tag) {2218 const result: MCValue = switch (tag) {
...@@ -2240,11 +2244,11 @@ fn bitwise(...@@ -2240,11 +2244,11 @@ fn bitwise(
2240 maybe_inst: ?Air.Inst.Index,2244 maybe_inst: ?Air.Inst.Index,
2241) InnerError!MCValue {2245) InnerError!MCValue {
2242 const mod = self.bin_file.options.module.?;2246 const mod = self.bin_file.options.module.?;
2243 switch (lhs_ty.zigTypeTag()) {2247 switch (lhs_ty.zigTypeTag(mod)) {
2244 .Vector => return self.fail("TODO binary operations on vectors", .{}),2248 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2245 .Int => {2249 .Int => {
2246 assert(lhs_ty.eql(rhs_ty, mod));2250 assert(lhs_ty.eql(rhs_ty, mod));
2247 const int_info = lhs_ty.intInfo(self.target.*);2251 const int_info = lhs_ty.intInfo(mod);
2248 if (int_info.bits <= 64) {2252 if (int_info.bits <= 64) {
2249 // TODO implement bitwise operations with immediates2253 // TODO implement bitwise operations with immediates
2250 const mir_tag: Mir.Inst.Tag = switch (tag) {2254 const mir_tag: Mir.Inst.Tag = switch (tag) {
...@@ -2274,10 +2278,11 @@ fn shiftExact(...@@ -2274,10 +2278,11 @@ fn shiftExact(
2274) InnerError!MCValue {2278) InnerError!MCValue {
2275 _ = rhs_ty;2279 _ = rhs_ty;
22762280
2277 switch (lhs_ty.zigTypeTag()) {2281 const mod = self.bin_file.options.module.?;
2282 switch (lhs_ty.zigTypeTag(mod)) {
2278 .Vector => return self.fail("TODO binary operations on vectors", .{}),2283 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2279 .Int => {2284 .Int => {
2280 const int_info = lhs_ty.intInfo(self.target.*);2285 const int_info = lhs_ty.intInfo(mod);
2281 if (int_info.bits <= 64) {2286 if (int_info.bits <= 64) {
2282 const rhs_immediate = try rhs_bind.resolveToImmediate(self);2287 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
22832288
...@@ -2323,10 +2328,11 @@ fn shiftNormal(...@@ -2323,10 +2328,11 @@ fn shiftNormal(
2323 rhs_ty: Type,2328 rhs_ty: Type,
2324 maybe_inst: ?Air.Inst.Index,2329 maybe_inst: ?Air.Inst.Index,
2325) InnerError!MCValue {2330) InnerError!MCValue {
2326 switch (lhs_ty.zigTypeTag()) {2331 const mod = self.bin_file.options.module.?;
2332 switch (lhs_ty.zigTypeTag(mod)) {
2327 .Vector => return self.fail("TODO binary operations on vectors", .{}),2333 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2328 .Int => {2334 .Int => {
2329 const int_info = lhs_ty.intInfo(self.target.*);2335 const int_info = lhs_ty.intInfo(mod);
2330 if (int_info.bits <= 64) {2336 if (int_info.bits <= 64) {
2331 // Generate a shl_exact/shr_exact2337 // Generate a shl_exact/shr_exact
2332 const result: MCValue = switch (tag) {2338 const result: MCValue = switch (tag) {
...@@ -2362,7 +2368,8 @@ fn booleanOp(...@@ -2362,7 +2368,8 @@ fn booleanOp(
2362 rhs_ty: Type,2368 rhs_ty: Type,
2363 maybe_inst: ?Air.Inst.Index,2369 maybe_inst: ?Air.Inst.Index,
2364) InnerError!MCValue {2370) InnerError!MCValue {
2365 switch (lhs_ty.zigTypeTag()) {2371 const mod = self.bin_file.options.module.?;
2372 switch (lhs_ty.zigTypeTag(mod)) {
2366 .Bool => {2373 .Bool => {
2367 assert((try lhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema2374 assert((try lhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema
2368 assert((try rhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema2375 assert((try rhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema
...@@ -2388,17 +2395,17 @@ fn ptrArithmetic(...@@ -2388,17 +2395,17 @@ fn ptrArithmetic(
2388 rhs_ty: Type,2395 rhs_ty: Type,
2389 maybe_inst: ?Air.Inst.Index,2396 maybe_inst: ?Air.Inst.Index,
2390) InnerError!MCValue {2397) InnerError!MCValue {
2391 switch (lhs_ty.zigTypeTag()) {2398 const mod = self.bin_file.options.module.?;
2399 switch (lhs_ty.zigTypeTag(mod)) {
2392 .Pointer => {2400 .Pointer => {
2393 const mod = self.bin_file.options.module.?;
2394 assert(rhs_ty.eql(Type.usize, mod));2401 assert(rhs_ty.eql(Type.usize, mod));
23952402
2396 const ptr_ty = lhs_ty;2403 const ptr_ty = lhs_ty;
2397 const elem_ty = switch (ptr_ty.ptrSize()) {2404 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
2398 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type2405 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
2399 else => ptr_ty.childType(),2406 else => ptr_ty.childType(mod),
2400 };2407 };
2401 const elem_size = elem_ty.abiSize(self.target.*);2408 const elem_size = elem_ty.abiSize(mod);
24022409
2403 const base_tag: Air.Inst.Tag = switch (tag) {2410 const base_tag: Air.Inst.Tag = switch (tag) {
2404 .ptr_add => .add,2411 .ptr_add => .add,
...@@ -2426,8 +2433,8 @@ fn ptrArithmetic(...@@ -2426,8 +2433,8 @@ fn ptrArithmetic(
24262433
2427fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2434fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2428 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2435 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2429 const lhs_ty = self.air.typeOf(bin_op.lhs);2436 const lhs_ty = self.typeOf(bin_op.lhs);
2430 const rhs_ty = self.air.typeOf(bin_op.rhs);2437 const rhs_ty = self.typeOf(bin_op.rhs);
24312438
2432 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2439 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2433 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };2440 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 {...@@ -2477,8 +2484,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2477fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2484fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2478 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2485 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2479 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2486 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2480 const lhs_ty = self.air.typeOf(bin_op.lhs);2487 const lhs_ty = self.typeOf(bin_op.lhs);
2481 const rhs_ty = self.air.typeOf(bin_op.rhs);2488 const rhs_ty = self.typeOf(bin_op.rhs);
24822489
2483 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2490 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2484 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };2491 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
...@@ -2511,23 +2518,23 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2511,23 +2518,23 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
2511 const tag = self.air.instructions.items(.tag)[inst];2518 const tag = self.air.instructions.items(.tag)[inst];
2512 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2519 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2513 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2520 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2521 const mod = self.bin_file.options.module.?;
2514 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2522 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2515 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };2523 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2516 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };2524 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2517 const lhs_ty = self.air.typeOf(extra.lhs);2525 const lhs_ty = self.typeOf(extra.lhs);
2518 const rhs_ty = self.air.typeOf(extra.rhs);2526 const rhs_ty = self.typeOf(extra.rhs);
25192527
2520 const tuple_ty = self.air.typeOfIndex(inst);2528 const tuple_ty = self.typeOfIndex(inst);
2521 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));2529 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
2522 const tuple_align = tuple_ty.abiAlignment(self.target.*);2530 const tuple_align = tuple_ty.abiAlignment(mod);
2523 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));2531 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
25242532
2525 switch (lhs_ty.zigTypeTag()) {2533 switch (lhs_ty.zigTypeTag(mod)) {
2526 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),2534 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),
2527 .Int => {2535 .Int => {
2528 const mod = self.bin_file.options.module.?;
2529 assert(lhs_ty.eql(rhs_ty, mod));2536 assert(lhs_ty.eql(rhs_ty, mod));
2530 const int_info = lhs_ty.intInfo(self.target.*);2537 const int_info = lhs_ty.intInfo(mod);
2531 switch (int_info.bits) {2538 switch (int_info.bits) {
2532 1...31, 33...63 => {2539 1...31, 33...63 => {
2533 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);2540 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
...@@ -2565,7 +2572,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2565,7 +2572,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
2565 });2572 });
25662573
2567 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });2574 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
2570 break :result MCValue{ .stack_offset = stack_offset };2577 break :result MCValue{ .stack_offset = stack_offset };
2571 },2578 },
...@@ -2639,24 +2646,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2639,24 +2646,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2639 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2646 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2640 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2647 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2641 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });2648 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
2649 const mod = self.bin_file.options.module.?;
2642 const result: MCValue = result: {2650 const result: MCValue = result: {
2643 const mod = self.bin_file.options.module.?;
2644
2645 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };2651 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2646 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };2652 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2647 const lhs_ty = self.air.typeOf(extra.lhs);2653 const lhs_ty = self.typeOf(extra.lhs);
2648 const rhs_ty = self.air.typeOf(extra.rhs);2654 const rhs_ty = self.typeOf(extra.rhs);
26492655
2650 const tuple_ty = self.air.typeOfIndex(inst);2656 const tuple_ty = self.typeOfIndex(inst);
2651 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));2657 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
2652 const tuple_align = tuple_ty.abiAlignment(self.target.*);2658 const tuple_align = tuple_ty.abiAlignment(mod);
2653 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));2659 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
26542660
2655 switch (lhs_ty.zigTypeTag()) {2661 switch (lhs_ty.zigTypeTag(mod)) {
2656 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),2662 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
2657 .Int => {2663 .Int => {
2658 assert(lhs_ty.eql(rhs_ty, mod));2664 assert(lhs_ty.eql(rhs_ty, mod));
2659 const int_info = lhs_ty.intInfo(self.target.*);2665 const int_info = lhs_ty.intInfo(mod);
2660 if (int_info.bits <= 32) {2666 if (int_info.bits <= 32) {
2661 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);2667 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 {...@@ -2709,7 +2715,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2709 }2715 }
27102716
2711 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });2717 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
2714 break :result MCValue{ .stack_offset = stack_offset };2720 break :result MCValue{ .stack_offset = stack_offset };
2715 } else if (int_info.bits <= 64) {2721 } else if (int_info.bits <= 64) {
...@@ -2849,7 +2855,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2849,7 +2855,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2849 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);2855 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
28502856
2851 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });2857 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
2854 break :result MCValue{ .stack_offset = stack_offset };2860 break :result MCValue{ .stack_offset = stack_offset };
2855 } else return self.fail("TODO implement mul_with_overflow for integers > u64/i64", .{});2861 } 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 {...@@ -2864,21 +2870,22 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2864 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2870 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2865 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2871 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2866 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });2872 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
2873 const mod = self.bin_file.options.module.?;
2867 const result: MCValue = result: {2874 const result: MCValue = result: {
2868 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };2875 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2869 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };2876 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2870 const lhs_ty = self.air.typeOf(extra.lhs);2877 const lhs_ty = self.typeOf(extra.lhs);
2871 const rhs_ty = self.air.typeOf(extra.rhs);2878 const rhs_ty = self.typeOf(extra.rhs);
28722879
2873 const tuple_ty = self.air.typeOfIndex(inst);2880 const tuple_ty = self.typeOfIndex(inst);
2874 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));2881 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
2875 const tuple_align = tuple_ty.abiAlignment(self.target.*);2882 const tuple_align = tuple_ty.abiAlignment(mod);
2876 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));2883 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
28772884
2878 switch (lhs_ty.zigTypeTag()) {2885 switch (lhs_ty.zigTypeTag(mod)) {
2879 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),2886 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
2880 .Int => {2887 .Int => {
2881 const int_info = lhs_ty.intInfo(self.target.*);2888 const int_info = lhs_ty.intInfo(mod);
2882 if (int_info.bits <= 64) {2889 if (int_info.bits <= 64) {
2883 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);2890 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 {...@@ -2981,7 +2988,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2981 });2988 });
29822989
2983 try self.genSetStack(lhs_ty, stack_offset, .{ .register = dest_reg });2990 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
2986 break :result MCValue{ .stack_offset = stack_offset };2993 break :result MCValue{ .stack_offset = stack_offset };
2987 } else {2994 } else {
...@@ -3003,7 +3010,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3003,7 +3010,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
3003fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {3010fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
3004 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3011 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3005 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3012 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);
3007 const mcv = try self.resolveInst(ty_op.operand);3014 const mcv = try self.resolveInst(ty_op.operand);
3008 break :result try self.optionalPayload(inst, mcv, optional_ty);3015 break :result try self.optionalPayload(inst, mcv, optional_ty);
3009 };3016 };
...@@ -3011,10 +3018,10 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -3011,10 +3018,10 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
3011}3018}
30123019
3013fn optionalPayload(self: *Self, inst: Air.Inst.Index, mcv: MCValue, optional_ty: Type) !MCValue {3020fn optionalPayload(self: *Self, inst: Air.Inst.Index, mcv: MCValue, optional_ty: Type) !MCValue {
3014 var opt_buf: Type.Payload.ElemType = undefined;3021 const mod = self.bin_file.options.module.?;
3015 const payload_ty = optional_ty.optionalChild(&opt_buf);3022 const payload_ty = optional_ty.optionalChild(mod);
3016 if (!payload_ty.hasRuntimeBits()) return MCValue.none;3023 if (!payload_ty.hasRuntimeBits(mod)) return MCValue.none;
3017 if (optional_ty.isPtrLikeOptional()) {3024 if (optional_ty.isPtrLikeOptional(mod)) {
3018 // TODO should we reuse the operand here?3025 // TODO should we reuse the operand here?
3019 const raw_reg = try self.register_manager.allocReg(inst, gp);3026 const raw_reg = try self.register_manager.allocReg(inst, gp);
3020 const reg = self.registerAlias(raw_reg, payload_ty);3027 const reg = self.registerAlias(raw_reg, payload_ty);
...@@ -3055,16 +3062,17 @@ fn errUnionErr(...@@ -3055,16 +3062,17 @@ fn errUnionErr(
3055 error_union_ty: Type,3062 error_union_ty: Type,
3056 maybe_inst: ?Air.Inst.Index,3063 maybe_inst: ?Air.Inst.Index,
3057) !MCValue {3064) !MCValue {
3058 const err_ty = error_union_ty.errorUnionSet();3065 const mod = self.bin_file.options.module.?;
3059 const payload_ty = error_union_ty.errorUnionPayload();3066 const err_ty = error_union_ty.errorUnionSet(mod);
3060 if (err_ty.errorSetIsEmpty()) {3067 const payload_ty = error_union_ty.errorUnionPayload(mod);
3068 if (err_ty.errorSetIsEmpty(mod)) {
3061 return MCValue{ .immediate = 0 };3069 return MCValue{ .immediate = 0 };
3062 }3070 }
3063 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3071 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3064 return try error_union_bind.resolveToMcv(self);3072 return try error_union_bind.resolveToMcv(self);
3065 }3073 }
30663074
3067 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));3075 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, mod));
3068 switch (try error_union_bind.resolveToMcv(self)) {3076 switch (try error_union_bind.resolveToMcv(self)) {
3069 .register => {3077 .register => {
3070 var operand_reg: Register = undefined;3078 var operand_reg: Register = undefined;
...@@ -3086,7 +3094,7 @@ fn errUnionErr(...@@ -3086,7 +3094,7 @@ fn errUnionErr(
3086 );3094 );
30873095
3088 const err_bit_offset = err_offset * 8;3096 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
3091 _ = try self.addInst(.{3099 _ = try self.addInst(.{
3092 .tag = .ubfx, // errors are unsigned integers3100 .tag = .ubfx, // errors are unsigned integers
...@@ -3120,7 +3128,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3120,7 +3128,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
3120 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3128 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3121 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3129 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3122 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };3130 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
3125 break :result try self.errUnionErr(error_union_bind, error_union_ty, inst);3133 break :result try self.errUnionErr(error_union_bind, error_union_ty, inst);
3126 };3134 };
...@@ -3134,16 +3142,17 @@ fn errUnionPayload(...@@ -3134,16 +3142,17 @@ fn errUnionPayload(
3134 error_union_ty: Type,3142 error_union_ty: Type,
3135 maybe_inst: ?Air.Inst.Index,3143 maybe_inst: ?Air.Inst.Index,
3136) !MCValue {3144) !MCValue {
3137 const err_ty = error_union_ty.errorUnionSet();3145 const mod = self.bin_file.options.module.?;
3138 const payload_ty = error_union_ty.errorUnionPayload();3146 const err_ty = error_union_ty.errorUnionSet(mod);
3139 if (err_ty.errorSetIsEmpty()) {3147 const payload_ty = error_union_ty.errorUnionPayload(mod);
3148 if (err_ty.errorSetIsEmpty(mod)) {
3140 return try error_union_bind.resolveToMcv(self);3149 return try error_union_bind.resolveToMcv(self);
3141 }3150 }
3142 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3151 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3143 return MCValue.none;3152 return MCValue.none;
3144 }3153 }
31453154
3146 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));3155 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
3147 switch (try error_union_bind.resolveToMcv(self)) {3156 switch (try error_union_bind.resolveToMcv(self)) {
3148 .register => {3157 .register => {
3149 var operand_reg: Register = undefined;3158 var operand_reg: Register = undefined;
...@@ -3165,10 +3174,10 @@ fn errUnionPayload(...@@ -3165,10 +3174,10 @@ fn errUnionPayload(
3165 );3174 );
31663175
3167 const payload_bit_offset = payload_offset * 8;3176 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
3170 _ = try self.addInst(.{3179 _ = 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,
3172 .data = .{3181 .data = .{
3173 .rr_lsb_width = .{3182 .rr_lsb_width = .{
3174 // Set both registers to the X variant to get the full width3183 // 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 {...@@ -3199,7 +3208,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
3199 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3208 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3200 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3209 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3201 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };3210 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
3204 break :result try self.errUnionPayload(error_union_bind, error_union_ty, inst);3213 break :result try self.errUnionPayload(error_union_bind, error_union_ty, inst);
3205 };3214 };
...@@ -3245,6 +3254,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {...@@ -3245,6 +3254,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
3245}3254}
32463255
3247fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {3256fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3257 const mod = self.bin_file.options.module.?;
3248 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3258 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
32493259
3250 if (self.liveness.isUnused(inst)) {3260 if (self.liveness.isUnused(inst)) {
...@@ -3252,12 +3262,12 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -3252,12 +3262,12 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3252 }3262 }
32533263
3254 const result: MCValue = result: {3264 const result: MCValue = result: {
3255 const payload_ty = self.air.typeOf(ty_op.operand);3265 const payload_ty = self.typeOf(ty_op.operand);
3256 if (!payload_ty.hasRuntimeBits()) {3266 if (!payload_ty.hasRuntimeBits(mod)) {
3257 break :result MCValue{ .immediate = 1 };3267 break :result MCValue{ .immediate = 1 };
3258 }3268 }
32593269
3260 const optional_ty = self.air.typeOfIndex(inst);3270 const optional_ty = self.typeOfIndex(inst);
3261 const operand = try self.resolveInst(ty_op.operand);3271 const operand = try self.resolveInst(ty_op.operand);
3262 const operand_lock: ?RegisterLock = switch (operand) {3272 const operand_lock: ?RegisterLock = switch (operand) {
3263 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),3273 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -3265,7 +3275,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -3265,7 +3275,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3265 };3275 };
3266 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);3276 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
32673277
3268 if (optional_ty.isPtrLikeOptional()) {3278 if (optional_ty.isPtrLikeOptional(mod)) {
3269 // TODO should we check if we can reuse the operand?3279 // TODO should we check if we can reuse the operand?
3270 const raw_reg = try self.register_manager.allocReg(inst, gp);3280 const raw_reg = try self.register_manager.allocReg(inst, gp);
3271 const reg = self.registerAlias(raw_reg, payload_ty);3281 const reg = self.registerAlias(raw_reg, payload_ty);
...@@ -3273,9 +3283,9 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -3273,9 +3283,9 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3273 break :result MCValue{ .register = reg };3283 break :result MCValue{ .register = reg };
3274 }3284 }
32753285
3276 const optional_abi_size = @intCast(u32, optional_ty.abiSize(self.target.*));3286 const optional_abi_size = @intCast(u32, optional_ty.abiSize(mod));
3277 const optional_abi_align = optional_ty.abiAlignment(self.target.*);3287 const optional_abi_align = optional_ty.abiAlignment(mod);
3278 const offset = @intCast(u32, payload_ty.abiSize(self.target.*));3288 const offset = @intCast(u32, payload_ty.abiSize(mod));
32793289
3280 const stack_offset = try self.allocMem(optional_abi_size, optional_abi_align, inst);3290 const stack_offset = try self.allocMem(optional_abi_size, optional_abi_align, inst);
3281 try self.genSetStack(payload_ty, stack_offset, operand);3291 try self.genSetStack(payload_ty, stack_offset, operand);
...@@ -3289,19 +3299,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -3289,19 +3299,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
32893299
3290/// T to E!T3300/// T to E!T
3291fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {3301fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
3302 const mod = self.bin_file.options.module.?;
3292 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3303 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3293 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3304 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3294 const error_union_ty = self.air.getRefType(ty_op.ty);3305 const error_union_ty = self.air.getRefType(ty_op.ty);
3295 const error_ty = error_union_ty.errorUnionSet();3306 const error_ty = error_union_ty.errorUnionSet(mod);
3296 const payload_ty = error_union_ty.errorUnionPayload();3307 const payload_ty = error_union_ty.errorUnionPayload(mod);
3297 const operand = try self.resolveInst(ty_op.operand);3308 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.*));3311 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
3301 const abi_align = error_union_ty.abiAlignment(self.target.*);3312 const abi_align = error_union_ty.abiAlignment(mod);
3302 const stack_offset = try self.allocMem(abi_size, abi_align, inst);3313 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
3303 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);3314 const payload_off = errUnionPayloadOffset(payload_ty, mod);
3304 const err_off = errUnionErrorOffset(payload_ty, self.target.*);3315 const err_off = errUnionErrorOffset(payload_ty, mod);
3305 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);3316 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);
3306 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 });3317 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 {...@@ -3314,17 +3325,18 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
3314fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {3325fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
3315 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3326 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3316 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3327 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3328 const mod = self.bin_file.options.module.?;
3317 const error_union_ty = self.air.getRefType(ty_op.ty);3329 const error_union_ty = self.air.getRefType(ty_op.ty);
3318 const error_ty = error_union_ty.errorUnionSet();3330 const error_ty = error_union_ty.errorUnionSet(mod);
3319 const payload_ty = error_union_ty.errorUnionPayload();3331 const payload_ty = error_union_ty.errorUnionPayload(mod);
3320 const operand = try self.resolveInst(ty_op.operand);3332 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.*));3335 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
3324 const abi_align = error_union_ty.abiAlignment(self.target.*);3336 const abi_align = error_union_ty.abiAlignment(mod);
3325 const stack_offset = try self.allocMem(abi_size, abi_align, inst);3337 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
3326 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);3338 const payload_off = errUnionPayloadOffset(payload_ty, mod);
3327 const err_off = errUnionErrorOffset(payload_ty, self.target.*);3339 const err_off = errUnionErrorOffset(payload_ty, mod);
3328 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand);3340 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand);
3329 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef);3341 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 {...@@ -3416,11 +3428,11 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
3416}3428}
34173429
3418fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {3430fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
3431 const mod = self.bin_file.options.module.?;
3419 const bin_op = self.air.instructions.items(.data)[inst].bin_op;3432 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
3420 const slice_ty = self.air.typeOf(bin_op.lhs);3433 const slice_ty = self.typeOf(bin_op.lhs);
3421 const result: MCValue = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {3434 const result: MCValue = if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
3422 var buf: Type.SlicePtrFieldTypeBuffer = undefined;3435 const ptr_ty = slice_ty.slicePtrFieldType(mod);
3423 const ptr_ty = slice_ty.slicePtrFieldType(&buf);
34243436
3425 const slice_mcv = try self.resolveInst(bin_op.lhs);3437 const slice_mcv = try self.resolveInst(bin_op.lhs);
3426 const base_mcv = slicePtr(slice_mcv);3438 const base_mcv = slicePtr(slice_mcv);
...@@ -3440,8 +3452,9 @@ fn ptrElemVal(...@@ -3440,8 +3452,9 @@ fn ptrElemVal(
3440 ptr_ty: Type,3452 ptr_ty: Type,
3441 maybe_inst: ?Air.Inst.Index,3453 maybe_inst: ?Air.Inst.Index,
3442) !MCValue {3454) !MCValue {
3443 const elem_ty = ptr_ty.childType();3455 const mod = self.bin_file.options.module.?;
3444 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));3456 const elem_ty = ptr_ty.childType(mod);
3457 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
34453458
3446 // TODO optimize for elem_sizes of 1, 2, 4, 83459 // TODO optimize for elem_sizes of 1, 2, 4, 8
3447 switch (elem_size) {3460 switch (elem_size) {
...@@ -3465,8 +3478,8 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3465,8 +3478,8 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
3465 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };3478 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };
3466 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };3479 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
34673480
3468 const slice_ty = self.air.typeOf(extra.lhs);3481 const slice_ty = self.typeOf(extra.lhs);
3469 const index_ty = self.air.typeOf(extra.rhs);3482 const index_ty = self.typeOf(extra.rhs);
34703483
3471 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ty, index_ty, null);3484 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ty, index_ty, null);
3472 break :result addr;3485 break :result addr;
...@@ -3481,9 +3494,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3481,9 +3494,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
3481}3494}
34823495
3483fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {3496fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
3497 const mod = self.bin_file.options.module.?;
3484 const bin_op = self.air.instructions.items(.data)[inst].bin_op;3498 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
3485 const ptr_ty = self.air.typeOf(bin_op.lhs);3499 const ptr_ty = self.typeOf(bin_op.lhs);
3486 const result: MCValue = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {3500 const result: MCValue = if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
3487 const base_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };3501 const base_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
3488 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };3502 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
34893503
...@@ -3499,8 +3513,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3499,8 +3513,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
3499 const ptr_bind: ReadArg.Bind = .{ .inst = extra.lhs };3513 const ptr_bind: ReadArg.Bind = .{ .inst = extra.lhs };
3500 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };3514 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
35013515
3502 const ptr_ty = self.air.typeOf(extra.lhs);3516 const ptr_ty = self.typeOf(extra.lhs);
3503 const index_ty = self.air.typeOf(extra.rhs);3517 const index_ty = self.typeOf(extra.rhs);
35043518
3505 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, index_ty, null);3519 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, index_ty, null);
3506 break :result addr;3520 break :result addr;
...@@ -3597,8 +3611,9 @@ fn reuseOperand(...@@ -3597,8 +3611,9 @@ fn reuseOperand(
3597}3611}
35983612
3599fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {3613fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
3600 const elem_ty = ptr_ty.elemType();3614 const mod = self.bin_file.options.module.?;
3601 const elem_size = elem_ty.abiSize(self.target.*);3615 const elem_ty = ptr_ty.childType(mod);
3616 const elem_size = elem_ty.abiSize(mod);
36023617
3603 switch (ptr) {3618 switch (ptr) {
3604 .none => unreachable,3619 .none => unreachable,
...@@ -3753,14 +3768,14 @@ fn genInlineMemset(...@@ -3753,14 +3768,14 @@ fn genInlineMemset(
3753) !void {3768) !void {
3754 const dst_reg = switch (dst) {3769 const dst_reg = switch (dst) {
3755 .register => |r| r,3770 .register => |r| r,
3756 else => try self.copyToTmpRegister(Type.initTag(.manyptr_u8), dst),3771 else => try self.copyToTmpRegister(Type.manyptr_u8, dst),
3757 };3772 };
3758 const dst_reg_lock = self.register_manager.lockReg(dst_reg);3773 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
3759 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);3774 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
37603775
3761 const val_reg = switch (val) {3776 const val_reg = switch (val) {
3762 .register => |r| r,3777 .register => |r| r,
3763 else => try self.copyToTmpRegister(Type.initTag(.u8), val),3778 else => try self.copyToTmpRegister(Type.u8, val),
3764 };3779 };
3765 const val_reg_lock = self.register_manager.lockReg(val_reg);3780 const val_reg_lock = self.register_manager.lockReg(val_reg);
3766 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);3781 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -3844,15 +3859,16 @@ fn genInlineMemsetCode(...@@ -3844,15 +3859,16 @@ fn genInlineMemsetCode(
3844}3859}
38453860
3846fn airLoad(self: *Self, inst: Air.Inst.Index) !void {3861fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
3862 const mod = self.bin_file.options.module.?;
3847 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3863 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3848 const elem_ty = self.air.typeOfIndex(inst);3864 const elem_ty = self.typeOfIndex(inst);
3849 const elem_size = elem_ty.abiSize(self.target.*);3865 const elem_size = elem_ty.abiSize(mod);
3850 const result: MCValue = result: {3866 const result: MCValue = result: {
3851 if (!elem_ty.hasRuntimeBits())3867 if (!elem_ty.hasRuntimeBits(mod))
3852 break :result MCValue.none;3868 break :result MCValue.none;
38533869
3854 const ptr = try self.resolveInst(ty_op.operand);3870 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);
3856 if (self.liveness.isUnused(inst) and !is_volatile)3872 if (self.liveness.isUnused(inst) and !is_volatile)
3857 break :result MCValue.dead;3873 break :result MCValue.dead;
38583874
...@@ -3867,18 +3883,19 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -3867,18 +3883,19 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
3867 break :blk try self.allocRegOrMem(elem_ty, true, inst);3883 break :blk try self.allocRegOrMem(elem_ty, true, inst);
3868 }3884 }
3869 };3885 };
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));
3871 break :result dst_mcv;3887 break :result dst_mcv;
3872 };3888 };
3873 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3889 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3874}3890}
38753891
3876fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void {3892fn 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
3879 const tag: Mir.Inst.Tag = switch (abi_size) {3896 const tag: Mir.Inst.Tag = switch (abi_size) {
3880 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_immediate else .ldrb_immediate,3897 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_immediate else .ldrb_immediate,
3881 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_immediate else .ldrh_immediate,3898 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_immediate else .ldrh_immediate,
3882 4 => .ldr_immediate,3899 4 => .ldr_immediate,
3883 8 => .ldr_immediate,3900 8 => .ldr_immediate,
3884 3, 5, 6, 7 => return self.fail("TODO: genLdrRegister for more abi_sizes", .{}),3901 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...@@ -3896,7 +3913,8 @@ fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type
3896}3913}
38973914
3898fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void {3915fn 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
3901 const tag: Mir.Inst.Tag = switch (abi_size) {3919 const tag: Mir.Inst.Tag = switch (abi_size) {
3902 1 => .strb_immediate,3920 1 => .strb_immediate,
...@@ -3917,8 +3935,9 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type...@@ -3917,8 +3935,9 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type
3917}3935}
39183936
3919fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {3937fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
3938 const mod = self.bin_file.options.module.?;
3920 log.debug("store: storing {} to {}", .{ value, ptr });3939 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
3923 switch (ptr) {3942 switch (ptr) {
3924 .none => unreachable,3943 .none => unreachable,
...@@ -4046,8 +4065,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -4046,8 +4065,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
4046 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4065 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4047 const ptr = try self.resolveInst(bin_op.lhs);4066 const ptr = try self.resolveInst(bin_op.lhs);
4048 const value = try self.resolveInst(bin_op.rhs);4067 const value = try self.resolveInst(bin_op.rhs);
4049 const ptr_ty = self.air.typeOf(bin_op.lhs);4068 const ptr_ty = self.typeOf(bin_op.lhs);
4050 const value_ty = self.air.typeOf(bin_op.rhs);4069 const value_ty = self.typeOf(bin_op.rhs);
40514070
4052 try self.store(ptr, value, ptr_ty, value_ty);4071 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 {...@@ -4069,10 +4088,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
40694088
4070fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {4089fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
4071 return if (self.liveness.isUnused(inst)) .dead else result: {4090 return if (self.liveness.isUnused(inst)) .dead else result: {
4091 const mod = self.bin_file.options.module.?;
4072 const mcv = try self.resolveInst(operand);4092 const mcv = try self.resolveInst(operand);
4073 const ptr_ty = self.air.typeOf(operand);4093 const ptr_ty = self.typeOf(operand);
4074 const struct_ty = ptr_ty.childType();4094 const struct_ty = ptr_ty.childType(mod);
4075 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));4095 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
4076 switch (mcv) {4096 switch (mcv) {
4077 .ptr_stack_offset => |off| {4097 .ptr_stack_offset => |off| {
4078 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };4098 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };
...@@ -4093,10 +4113,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4093,10 +4113,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
4093 const operand = extra.struct_operand;4113 const operand = extra.struct_operand;
4094 const index = extra.field_index;4114 const index = extra.field_index;
4095 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4115 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4116 const mod = self.bin_file.options.module.?;
4096 const mcv = try self.resolveInst(operand);4117 const mcv = try self.resolveInst(operand);
4097 const struct_ty = self.air.typeOf(operand);4118 const struct_ty = self.typeOf(operand);
4098 const struct_field_ty = struct_ty.structFieldType(index);4119 const struct_field_ty = struct_ty.structFieldType(index, mod);
4099 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));4120 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
41004121
4101 switch (mcv) {4122 switch (mcv) {
4102 .dead, .unreach => unreachable,4123 .dead, .unreach => unreachable,
...@@ -4142,12 +4163,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4142,12 +4163,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
4142}4163}
41434164
4144fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {4165fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
4166 const mod = self.bin_file.options.module.?;
4145 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4167 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4146 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;4168 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
4147 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4169 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4148 const field_ptr = try self.resolveInst(extra.field_ptr);4170 const field_ptr = try self.resolveInst(extra.field_ptr);
4149 const struct_ty = self.air.getRefType(ty_pl.ty).childType();4171 const struct_ty = self.air.getRefType(ty_pl.ty).childType(mod);
4150 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, self.target.*));4172 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, mod));
4151 switch (field_ptr) {4173 switch (field_ptr) {
4152 .ptr_stack_offset => |off| {4174 .ptr_stack_offset => |off| {
4153 break :result MCValue{ .ptr_stack_offset = off + struct_field_offset };4175 break :result MCValue{ .ptr_stack_offset = off + struct_field_offset };
...@@ -4169,7 +4191,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4169,7 +4191,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4169 while (self.args[arg_index] == .none) arg_index += 1;4191 while (self.args[arg_index] == .none) arg_index += 1;
4170 self.arg_index = arg_index + 1;4192 self.arg_index = arg_index + 1;
41714193
4172 const ty = self.air.typeOfIndex(inst);4194 const ty = self.typeOfIndex(inst);
4173 const tag = self.air.instructions.items(.tag)[inst];4195 const tag = self.air.instructions.items(.tag)[inst];
4174 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;4196 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4175 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);4197 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...@@ -4222,11 +4244,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4222 const callee = pl_op.operand;4244 const callee = pl_op.operand;
4223 const extra = self.air.extraData(Air.Call, pl_op.payload);4245 const extra = self.air.extraData(Air.Call, pl_op.payload);
4224 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);4246 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)) {
4228 .Fn => ty,4251 .Fn => ty,
4229 .Pointer => ty.childType(),4252 .Pointer => ty.childType(mod),
4230 else => unreachable,4253 else => unreachable,
4231 };4254 };
42324255
...@@ -4245,18 +4268,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4245,18 +4268,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42454268
4246 if (info.return_value == .stack_offset) {4269 if (info.return_value == .stack_offset) {
4247 log.debug("airCall: return by reference", .{});4270 log.debug("airCall: return by reference", .{});
4248 const ret_ty = fn_ty.fnReturnType();4271 const ret_ty = fn_ty.fnReturnType(mod);
4249 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));4272 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
4250 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));4273 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
4251 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);4274 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
42524275
4253 const ret_ptr_reg = self.registerAlias(.x0, Type.usize);4276 const ret_ptr_reg = self.registerAlias(.x0, Type.usize);
42544277
4255 var ptr_ty_payload: Type.Payload.ElemType = .{4278 const ptr_ty = try mod.singleMutPtrType(ret_ty);
4256 .base = .{ .tag = .single_mut_pointer },
4257 .data = ret_ty,
4258 };
4259 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4260 try self.register_manager.getReg(ret_ptr_reg, null);4279 try self.register_manager.getReg(ret_ptr_reg, null);
4261 try self.genSetReg(ptr_ty, ret_ptr_reg, .{ .ptr_stack_offset = stack_offset });4280 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...@@ -4268,7 +4287,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42684287
4269 for (info.args, 0..) |mc_arg, arg_i| {4288 for (info.args, 0..) |mc_arg, arg_i| {
4270 const arg = args[arg_i];4289 const arg = args[arg_i];
4271 const arg_ty = self.air.typeOf(arg);4290 const arg_ty = self.typeOf(arg);
4272 const arg_mcv = try self.resolveInst(args[arg_i]);4291 const arg_mcv = try self.resolveInst(args[arg_i]);
42734292
4274 switch (mc_arg) {4293 switch (mc_arg) {
...@@ -4289,21 +4308,18 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4289,21 +4308,18 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42894308
4290 // Due to incremental compilation, how function calls are generated depends4309 // Due to incremental compilation, how function calls are generated depends
4291 // on linking.4310 // on linking.
4292 const mod = self.bin_file.options.module.?;4311 if (try self.air.value(callee, mod)) |func_value| {
4293 if (self.air.value(callee)) |func_value| {4312 if (func_value.getFunction(mod)) |func| {
4294 if (func_value.castTag(.function)) |func_payload| {
4295 const func = func_payload.data;
4296
4297 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4313 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4298 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);4314 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
4299 const atom = elf_file.getAtom(atom_index);4315 const atom = elf_file.getAtom(atom_index);
4300 _ = try atom.getOrCreateOffsetTableEntry(elf_file);4316 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
4301 const got_addr = @intCast(u32, atom.getOffsetTableAddress(elf_file));4317 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 });
4303 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {4319 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4304 const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);4320 const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
4305 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;4321 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
4306 try self.genSetReg(Type.initTag(.u64), .x30, .{4322 try self.genSetReg(Type.u64, .x30, .{
4307 .linker_load = .{4323 .linker_load = .{
4308 .type = .got,4324 .type = .got,
4309 .sym_index = sym_index,4325 .sym_index = sym_index,
...@@ -4312,7 +4328,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4312,7 +4328,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4312 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {4328 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
4313 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);4329 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);
4314 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;4330 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
4315 try self.genSetReg(Type.initTag(.u64), .x30, .{4331 try self.genSetReg(Type.u64, .x30, .{
4316 .linker_load = .{4332 .linker_load = .{
4317 .type = .got,4333 .type = .got,
4318 .sym_index = sym_index,4334 .sym_index = sym_index,
...@@ -4326,17 +4342,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4326,17 +4342,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4326 const got_addr = p9.bases.data;4342 const got_addr = p9.bases.data;
4327 const got_index = decl_block.got_index.?;4343 const got_index = decl_block.got_index.?;
4328 const fn_got_addr = got_addr + got_index * ptr_bytes;4344 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 });
4330 } else unreachable;4346 } else unreachable;
43314347
4332 _ = try self.addInst(.{4348 _ = try self.addInst(.{
4333 .tag = .blr,4349 .tag = .blr,
4334 .data = .{ .reg = .x30 },4350 .data = .{ .reg = .x30 },
4335 });4351 });
4336 } else if (func_value.castTag(.extern_fn)) |func_payload| {4352 } else if (func_value.getExternFunc(mod)) |extern_func| {
4337 const extern_fn = func_payload.data;4353 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
4338 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);4354 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
4339 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
4340 if (self.bin_file.cast(link.File.MachO)) |macho_file| {4355 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4341 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);4356 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
4342 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4357 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...@@ -4352,7 +4367,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4352 });4367 });
4353 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {4368 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
4354 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);4369 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, .{
4356 .linker_load = .{4371 .linker_load = .{
4357 .type = .import,4372 .type = .import,
4358 .sym_index = sym_index,4373 .sym_index = sym_index,
...@@ -4369,7 +4384,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4369,7 +4384,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4369 return self.fail("TODO implement calling bitcasted functions", .{});4384 return self.fail("TODO implement calling bitcasted functions", .{});
4370 }4385 }
4371 } else {4386 } else {
4372 assert(ty.zigTypeTag() == .Pointer);4387 assert(ty.zigTypeTag(mod) == .Pointer);
4373 const mcv = try self.resolveInst(callee);4388 const mcv = try self.resolveInst(callee);
4374 try self.genSetReg(ty, .x30, mcv);4389 try self.genSetReg(ty, .x30, mcv);
43754390
...@@ -4407,14 +4422,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4407,14 +4422,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4407}4422}
44084423
4409fn airRet(self: *Self, inst: Air.Inst.Index) !void {4424fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4425 const mod = self.bin_file.options.module.?;
4410 const un_op = self.air.instructions.items(.data)[inst].un_op;4426 const un_op = self.air.instructions.items(.data)[inst].un_op;
4411 const operand = try self.resolveInst(un_op);4427 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
4414 switch (self.ret_mcv) {4430 switch (self.ret_mcv) {
4415 .none => {},4431 .none => {},
4416 .immediate => {4432 .immediate => {
4417 assert(ret_ty.isError());4433 assert(ret_ty.isError(mod));
4418 },4434 },
4419 .register => |reg| {4435 .register => |reg| {
4420 // Return result by value4436 // Return result by value
...@@ -4425,11 +4441,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4425,11 +4441,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4425 //4441 //
4426 // self.ret_mcv is an address to where this function4442 // self.ret_mcv is an address to where this function
4427 // should store its result into4443 // should store its result into
4428 var ptr_ty_payload: Type.Payload.ElemType = .{4444 const ptr_ty = try mod.singleMutPtrType(ret_ty);
4429 .base = .{ .tag = .single_mut_pointer },
4430 .data = ret_ty,
4431 };
4432 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4433 try self.store(self.ret_mcv, operand, ptr_ty, ret_ty);4445 try self.store(self.ret_mcv, operand, ptr_ty, ret_ty);
4434 },4446 },
4435 else => unreachable,4447 else => unreachable,
...@@ -4442,10 +4454,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4442,10 +4454,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4442}4454}
44434455
4444fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {4456fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4457 const mod = self.bin_file.options.module.?;
4445 const un_op = self.air.instructions.items(.data)[inst].un_op;4458 const un_op = self.air.instructions.items(.data)[inst].un_op;
4446 const ptr = try self.resolveInst(un_op);4459 const ptr = try self.resolveInst(un_op);
4447 const ptr_ty = self.air.typeOf(un_op);4460 const ptr_ty = self.typeOf(un_op);
4448 const ret_ty = self.fn_type.fnReturnType();4461 const ret_ty = self.fn_type.fnReturnType(mod);
44494462
4450 switch (self.ret_mcv) {4463 switch (self.ret_mcv) {
4451 .none => {},4464 .none => {},
...@@ -4465,8 +4478,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4465,8 +4478,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4465 // location.4478 // location.
4466 const op_inst = Air.refToIndex(un_op).?;4479 const op_inst = Air.refToIndex(un_op).?;
4467 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {4480 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4468 const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));4481 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
4469 const abi_align = ret_ty.abiAlignment(self.target.*);4482 const abi_align = ret_ty.abiAlignment(mod);
44704483
4471 const offset = try self.allocMem(abi_size, abi_align, null);4484 const offset = try self.allocMem(abi_size, abi_align, null);
44724485
...@@ -4485,7 +4498,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4485,7 +4498,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44854498
4486fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {4499fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
4487 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4500 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
4490 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {4503 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
4491 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);4504 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);
...@@ -4501,29 +4514,28 @@ fn cmp(...@@ -4501,29 +4514,28 @@ fn cmp(
4501 lhs_ty: Type,4514 lhs_ty: Type,
4502 op: math.CompareOperator,4515 op: math.CompareOperator,
4503) !MCValue {4516) !MCValue {
4504 var int_buffer: Type.Payload.Bits = undefined;4517 const mod = self.bin_file.options.module.?;
4505 const int_ty = switch (lhs_ty.zigTypeTag()) {4518 const int_ty = switch (lhs_ty.zigTypeTag(mod)) {
4506 .Optional => blk: {4519 .Optional => blk: {
4507 var opt_buffer: Type.Payload.ElemType = undefined;4520 const payload_ty = lhs_ty.optionalChild(mod);
4508 const payload_ty = lhs_ty.optionalChild(&opt_buffer);4521 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4509 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4522 break :blk Type.u1;
4510 break :blk Type.initTag(.u1);4523 } else if (lhs_ty.isPtrLikeOptional(mod)) {
4511 } else if (lhs_ty.isPtrLikeOptional()) {
4512 break :blk Type.usize;4524 break :blk Type.usize;
4513 } else {4525 } else {
4514 return self.fail("TODO ARM cmp non-pointer optionals", .{});4526 return self.fail("TODO ARM cmp non-pointer optionals", .{});
4515 }4527 }
4516 },4528 },
4517 .Float => return self.fail("TODO ARM cmp floats", .{}),4529 .Float => return self.fail("TODO ARM cmp floats", .{}),
4518 .Enum => lhs_ty.intTagType(&int_buffer),4530 .Enum => lhs_ty.intTagType(mod),
4519 .Int => lhs_ty,4531 .Int => lhs_ty,
4520 .Bool => Type.initTag(.u1),4532 .Bool => Type.u1,
4521 .Pointer => Type.usize,4533 .Pointer => Type.usize,
4522 .ErrorSet => Type.initTag(.u16),4534 .ErrorSet => Type.u16,
4523 else => unreachable,4535 else => unreachable,
4524 };4536 };
45254537
4526 const int_info = int_ty.intInfo(self.target.*);4538 const int_info = int_ty.intInfo(mod);
4527 if (int_info.bits <= 64) {4539 if (int_info.bits <= 64) {
4528 try self.spillCompareFlagsIfOccupied();4540 try self.spillCompareFlagsIfOccupied();
45294541
...@@ -4609,8 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4609,8 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
4609}4621}
46104622
4611fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4623fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4612 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4624 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4613 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;4625 const mod = self.bin_file.options.module.?;
4626 const function = mod.funcPtr(ty_fn.func);
4614 // TODO emit debug info for function change4627 // TODO emit debug info for function change
4615 _ = function;4628 _ = function;
4616 return self.finishAir(inst, .dead, .{ .none, .none, .none });4629 return self.finishAir(inst, .dead, .{ .none, .none, .none });
...@@ -4625,7 +4638,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -4625,7 +4638,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4625 const pl_op = self.air.instructions.items(.data)[inst].pl_op;4638 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
4626 const operand = pl_op.operand;4639 const operand = pl_op.operand;
4627 const tag = self.air.instructions.items(.tag)[inst];4640 const tag = self.air.instructions.items(.tag)[inst];
4628 const ty = self.air.typeOf(operand);4641 const ty = self.typeOf(operand);
4629 const mcv = try self.resolveInst(operand);4642 const mcv = try self.resolveInst(operand);
4630 const name = self.air.nullTerminatedString(pl_op.payload);4643 const name = self.air.nullTerminatedString(pl_op.payload);
46314644
...@@ -4687,8 +4700,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4687,8 +4700,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4687 // whether it needs to be spilled in the branches4700 // whether it needs to be spilled in the branches
4688 if (self.liveness.operandDies(inst, 0)) {4701 if (self.liveness.operandDies(inst, 0)) {
4689 const op_int = @enumToInt(pl_op.operand);4702 const op_int = @enumToInt(pl_op.operand);
4690 if (op_int >= Air.Inst.Ref.typed_value_map.len) {4703 if (op_int >= Air.ref_start_index) {
4691 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);4704 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
4692 self.processDeath(op_index);4705 self.processDeath(op_index);
4693 }4706 }
4694 }4707 }
...@@ -4777,7 +4790,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4777,7 +4790,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4777 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });4790 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });
4778 // TODO make sure the destination stack offset / register does not already have something4791 // TODO make sure the destination stack offset / register does not already have something
4779 // going on there.4792 // 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);
4781 // TODO track the new register / stack allocation4794 // TODO track the new register / stack allocation
4782 }4795 }
4783 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count());4796 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 {...@@ -4804,7 +4817,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4804 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });4817 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });
4805 // TODO make sure the destination stack offset / register does not already have something4818 // TODO make sure the destination stack offset / register does not already have something
4806 // going on there.4819 // 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);
4808 // TODO track the new register / stack allocation4821 // TODO track the new register / stack allocation
4809 }4822 }
48104823
...@@ -4819,13 +4832,13 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4819,13 +4832,13 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4819}4832}
48204833
4821fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue {4834fn 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: {4835 const mod = self.bin_file.options.module.?;
4823 var buf: Type.Payload.ElemType = undefined;4836 const sentinel: struct { ty: Type, bind: ReadArg.Bind } = if (!operand_ty.isPtrLikeOptional(mod)) blk: {
4824 const payload_ty = operand_ty.optionalChild(&buf);4837 const payload_ty = operand_ty.optionalChild(mod);
4825 if (!payload_ty.hasRuntimeBitsIgnoreComptime())4838 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
4826 break :blk .{ .ty = operand_ty, .bind = operand_bind };4839 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));
4829 const operand_mcv = try operand_bind.resolveToMcv(self);4842 const operand_mcv = try operand_bind.resolveToMcv(self);
4830 const new_mcv: MCValue = switch (operand_mcv) {4843 const new_mcv: MCValue = switch (operand_mcv) {
4831 .register => |source_reg| new: {4844 .register => |source_reg| new: {
...@@ -4838,7 +4851,7 @@ fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue {...@@ -4838,7 +4851,7 @@ fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue {
4838 try self.genSetReg(payload_ty, dest_reg, operand_mcv);4851 try self.genSetReg(payload_ty, dest_reg, operand_mcv);
4839 } else {4852 } else {
4840 _ = try self.addInst(.{4853 _ = try self.addInst(.{
4841 .tag = if (payload_ty.isSignedInt())4854 .tag = if (payload_ty.isSignedInt(mod))
4842 Mir.Inst.Tag.asr_immediate4855 Mir.Inst.Tag.asr_immediate
4843 else4856 else
4844 Mir.Inst.Tag.lsr_immediate,4857 Mir.Inst.Tag.lsr_immediate,
...@@ -4875,9 +4888,10 @@ fn isErr(...@@ -4875,9 +4888,10 @@ fn isErr(
4875 error_union_bind: ReadArg.Bind,4888 error_union_bind: ReadArg.Bind,
4876 error_union_ty: Type,4889 error_union_ty: Type,
4877) !MCValue {4890) !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)) {
4881 return MCValue{ .immediate = 0 }; // always false4895 return MCValue{ .immediate = 0 }; // always false
4882 }4896 }
48834897
...@@ -4908,7 +4922,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4908,7 +4922,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
4908 const un_op = self.air.instructions.items(.data)[inst].un_op;4922 const un_op = self.air.instructions.items(.data)[inst].un_op;
4909 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4923 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4910 const operand = try self.resolveInst(un_op);4924 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
4913 break :result try self.isNull(.{ .mcv = operand }, operand_ty);4927 break :result try self.isNull(.{ .mcv = operand }, operand_ty);
4914 };4928 };
...@@ -4916,11 +4930,12 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4916,11 +4930,12 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
4916}4930}
49174931
4918fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {4932fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4933 const mod = self.bin_file.options.module.?;
4919 const un_op = self.air.instructions.items(.data)[inst].un_op;4934 const un_op = self.air.instructions.items(.data)[inst].un_op;
4920 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4935 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4921 const operand_ptr = try self.resolveInst(un_op);4936 const operand_ptr = try self.resolveInst(un_op);
4922 const ptr_ty = self.air.typeOf(un_op);4937 const ptr_ty = self.typeOf(un_op);
4923 const elem_ty = ptr_ty.elemType();4938 const elem_ty = ptr_ty.childType(mod);
49244939
4925 const operand = try self.allocRegOrMem(elem_ty, true, null);4940 const operand = try self.allocRegOrMem(elem_ty, true, null);
4926 try self.load(operand, operand_ptr, ptr_ty);4941 try self.load(operand, operand_ptr, ptr_ty);
...@@ -4934,7 +4949,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4934,7 +4949,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
4934 const un_op = self.air.instructions.items(.data)[inst].un_op;4949 const un_op = self.air.instructions.items(.data)[inst].un_op;
4935 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4950 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4936 const operand = try self.resolveInst(un_op);4951 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
4939 break :result try self.isNonNull(.{ .mcv = operand }, operand_ty);4954 break :result try self.isNonNull(.{ .mcv = operand }, operand_ty);
4940 };4955 };
...@@ -4942,11 +4957,12 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4942,11 +4957,12 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
4942}4957}
49434958
4944fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {4959fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4960 const mod = self.bin_file.options.module.?;
4945 const un_op = self.air.instructions.items(.data)[inst].un_op;4961 const un_op = self.air.instructions.items(.data)[inst].un_op;
4946 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4962 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4947 const operand_ptr = try self.resolveInst(un_op);4963 const operand_ptr = try self.resolveInst(un_op);
4948 const ptr_ty = self.air.typeOf(un_op);4964 const ptr_ty = self.typeOf(un_op);
4949 const elem_ty = ptr_ty.elemType();4965 const elem_ty = ptr_ty.childType(mod);
49504966
4951 const operand = try self.allocRegOrMem(elem_ty, true, null);4967 const operand = try self.allocRegOrMem(elem_ty, true, null);
4952 try self.load(operand, operand_ptr, ptr_ty);4968 try self.load(operand, operand_ptr, ptr_ty);
...@@ -4960,7 +4976,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4960,7 +4976,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
4960 const un_op = self.air.instructions.items(.data)[inst].un_op;4976 const un_op = self.air.instructions.items(.data)[inst].un_op;
4961 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4977 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4962 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };4978 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
4965 break :result try self.isErr(error_union_bind, error_union_ty);4981 break :result try self.isErr(error_union_bind, error_union_ty);
4966 };4982 };
...@@ -4968,11 +4984,12 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4968,11 +4984,12 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
4968}4984}
49694985
4970fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {4986fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4987 const mod = self.bin_file.options.module.?;
4971 const un_op = self.air.instructions.items(.data)[inst].un_op;4988 const un_op = self.air.instructions.items(.data)[inst].un_op;
4972 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4989 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4973 const operand_ptr = try self.resolveInst(un_op);4990 const operand_ptr = try self.resolveInst(un_op);
4974 const ptr_ty = self.air.typeOf(un_op);4991 const ptr_ty = self.typeOf(un_op);
4975 const elem_ty = ptr_ty.elemType();4992 const elem_ty = ptr_ty.childType(mod);
49764993
4977 const operand = try self.allocRegOrMem(elem_ty, true, null);4994 const operand = try self.allocRegOrMem(elem_ty, true, null);
4978 try self.load(operand, operand_ptr, ptr_ty);4995 try self.load(operand, operand_ptr, ptr_ty);
...@@ -4986,7 +5003,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4986,7 +5003,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
4986 const un_op = self.air.instructions.items(.data)[inst].un_op;5003 const un_op = self.air.instructions.items(.data)[inst].un_op;
4987 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {5004 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4988 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };5005 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
4991 break :result try self.isNonErr(error_union_bind, error_union_ty);5008 break :result try self.isNonErr(error_union_bind, error_union_ty);
4992 };5009 };
...@@ -4994,11 +5011,12 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4994,11 +5011,12 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
4994}5011}
49955012
4996fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {5013fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
5014 const mod = self.bin_file.options.module.?;
4997 const un_op = self.air.instructions.items(.data)[inst].un_op;5015 const un_op = self.air.instructions.items(.data)[inst].un_op;
4998 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {5016 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4999 const operand_ptr = try self.resolveInst(un_op);5017 const operand_ptr = try self.resolveInst(un_op);
5000 const ptr_ty = self.air.typeOf(un_op);5018 const ptr_ty = self.typeOf(un_op);
5001 const elem_ty = ptr_ty.elemType();5019 const elem_ty = ptr_ty.childType(mod);
50025020
5003 const operand = try self.allocRegOrMem(elem_ty, true, null);5021 const operand = try self.allocRegOrMem(elem_ty, true, null);
5004 try self.load(operand, operand_ptr, ptr_ty);5022 try self.load(operand, operand_ptr, ptr_ty);
...@@ -5065,7 +5083,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -5065,7 +5083,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
50655083
5066fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {5084fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
5067 const pl_op = self.air.instructions.items(.data)[inst].pl_op;5085 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);
5069 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);5087 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
5070 const liveness = try self.liveness.getSwitchBr(5088 const liveness = try self.liveness.getSwitchBr(
5071 self.gpa,5089 self.gpa,
...@@ -5210,9 +5228,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -5210,9 +5228,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
5210}5228}
52115229
5212fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {5230fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
5231 const mod = self.bin_file.options.module.?;
5213 const block_data = self.blocks.getPtr(block).?;5232 const block_data = self.blocks.getPtr(block).?;
52145233
5215 if (self.air.typeOf(operand).hasRuntimeBits()) {5234 if (self.typeOf(operand).hasRuntimeBits(mod)) {
5216 const operand_mcv = try self.resolveInst(operand);5235 const operand_mcv = try self.resolveInst(operand);
5217 const block_mcv = block_data.mcv;5236 const block_mcv = block_data.mcv;
5218 if (block_mcv == .none) {5237 if (block_mcv == .none) {
...@@ -5220,14 +5239,14 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -5220,14 +5239,14 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
5220 .none, .dead, .unreach => unreachable,5239 .none, .dead, .unreach => unreachable,
5221 .register, .stack_offset, .memory => operand_mcv,5240 .register, .stack_offset, .memory => operand_mcv,
5222 .immediate, .stack_argument_offset, .compare_flags => blk: {5241 .immediate, .stack_argument_offset, .compare_flags => blk: {
5223 const new_mcv = try self.allocRegOrMem(self.air.typeOfIndex(block), true, block);5242 const new_mcv = try self.allocRegOrMem(self.typeOfIndex(block), true, block);
5224 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);5243 try self.setRegOrMem(self.typeOfIndex(block), new_mcv, operand_mcv);
5225 break :blk new_mcv;5244 break :blk new_mcv;
5226 },5245 },
5227 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),5246 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
5228 };5247 };
5229 } else {5248 } else {
5230 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);5249 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
5231 }5250 }
5232 }5251 }
5233 return self.brVoid(block);5252 return self.brVoid(block);
...@@ -5293,7 +5312,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -5293,7 +5312,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
52935312
5294 const arg_mcv = try self.resolveInst(input);5313 const arg_mcv = try self.resolveInst(input);
5295 try self.register_manager.getReg(reg, null);5314 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);
5297 }5316 }
52985317
5299 {5318 {
...@@ -5386,7 +5405,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {...@@ -5386,7 +5405,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
5386}5405}
53875406
5388fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {5407fn 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));
5390 switch (mcv) {5410 switch (mcv) {
5391 .dead => unreachable,5411 .dead => unreachable,
5392 .unreach, .none => return, // Nothing to do.5412 .unreach, .none => return, // Nothing to do.
...@@ -5441,11 +5461,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5441,11 +5461,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5441 const reg_lock = self.register_manager.lockReg(rwo.reg);5461 const reg_lock = self.register_manager.lockReg(rwo.reg);
5442 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);5462 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);
5445 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });5465 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });
54465466
5447 const overflow_bit_ty = ty.structFieldType(1);5467 const overflow_bit_ty = ty.structFieldType(1, mod);
5448 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));5468 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
5449 const raw_cond_reg = try self.register_manager.allocReg(null, gp);5469 const raw_cond_reg = try self.register_manager.allocReg(null, gp);
5450 const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty);5470 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...@@ -5478,11 +5498,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5478 const reg = try self.copyToTmpRegister(ty, mcv);5498 const reg = try self.copyToTmpRegister(ty, mcv);
5479 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });5499 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
5480 } else {5500 } else {
5481 var ptr_ty_payload: Type.Payload.ElemType = .{5501 const ptr_ty = try mod.singleMutPtrType(ty);
5482 .base = .{ .tag = .single_mut_pointer },
5483 .data = ty,
5484 };
5485 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
54865502
5487 // TODO call extern memcpy5503 // TODO call extern memcpy
5488 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);5504 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...@@ -5559,6 +5575,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5559}5575}
55605576
5561fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {5577fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
5578 const mod = self.bin_file.options.module.?;
5562 switch (mcv) {5579 switch (mcv) {
5563 .dead => unreachable,5580 .dead => unreachable,
5564 .unreach, .none => return, // Nothing to do.5581 .unreach, .none => return, // Nothing to do.
...@@ -5669,13 +5686,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5669,13 +5686,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5669 try self.genLdrRegister(reg, reg.toX(), ty);5686 try self.genLdrRegister(reg, reg.toX(), ty);
5670 },5687 },
5671 .stack_offset => |off| {5688 .stack_offset => |off| {
5672 const abi_size = ty.abiSize(self.target.*);5689 const abi_size = ty.abiSize(mod);
56735690
5674 switch (abi_size) {5691 switch (abi_size) {
5675 1, 2, 4, 8 => {5692 1, 2, 4, 8 => {
5676 const tag: Mir.Inst.Tag = switch (abi_size) {5693 const tag: Mir.Inst.Tag = switch (abi_size) {
5677 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack else .ldrb_stack,5694 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_stack else .ldrb_stack,
5678 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack else .ldrh_stack,5695 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack else .ldrh_stack,
5679 4, 8 => .ldr_stack,5696 4, 8 => .ldr_stack,
5680 else => unreachable, // unexpected abi size5697 else => unreachable, // unexpected abi size
5681 };5698 };
...@@ -5693,13 +5710,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5693,13 +5710,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5693 }5710 }
5694 },5711 },
5695 .stack_argument_offset => |off| {5712 .stack_argument_offset => |off| {
5696 const abi_size = ty.abiSize(self.target.*);5713 const abi_size = ty.abiSize(mod);
56975714
5698 switch (abi_size) {5715 switch (abi_size) {
5699 1, 2, 4, 8 => {5716 1, 2, 4, 8 => {
5700 const tag: Mir.Inst.Tag = switch (abi_size) {5717 const tag: Mir.Inst.Tag = switch (abi_size) {
5701 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,5718 1 => if (ty.isSignedInt(mod)) 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,5719 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
5703 4, 8 => .ldr_stack_argument,5720 4, 8 => .ldr_stack_argument,
5704 else => unreachable, // unexpected abi size5721 else => unreachable, // unexpected abi size
5705 };5722 };
...@@ -5720,7 +5737,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5720,7 +5737,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5720}5737}
57215738
5722fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {5739fn 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));
5724 switch (mcv) {5742 switch (mcv) {
5725 .dead => unreachable,5743 .dead => unreachable,
5726 .none, .unreach => return,5744 .none, .unreach => return,
...@@ -5728,7 +5746,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5728,7 +5746,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5728 if (!self.wantSafety())5746 if (!self.wantSafety())
5729 return; // The already existing value will do just fine.5747 return; // The already existing value will do just fine.
5730 // TODO Upgrade this to a memset call when we have that available.5748 // TODO Upgrade this to a memset call when we have that available.
5731 switch (ty.abiSize(self.target.*)) {5749 switch (ty.abiSize(mod)) {
5732 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),5750 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
5733 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),5751 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
5734 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),5752 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...@@ -5798,11 +5816,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5798 const reg = try self.copyToTmpRegister(ty, mcv);5816 const reg = try self.copyToTmpRegister(ty, mcv);
5799 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });5817 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
5800 } else {5818 } else {
5801 var ptr_ty_payload: Type.Payload.ElemType = .{5819 const ptr_ty = try mod.singleMutPtrType(ty);
5802 .base = .{ .tag = .single_mut_pointer },
5803 .data = ty,
5804 };
5805 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
58065820
5807 // TODO call extern memcpy5821 // TODO call extern memcpy
5808 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);5822 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 {...@@ -5913,7 +5927,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
5913 };5927 };
5914 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);5928 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);
5917 const dest = try self.allocRegOrMem(dest_ty, true, inst);5931 const dest = try self.allocRegOrMem(dest_ty, true, inst);
5918 try self.setRegOrMem(dest_ty, dest, operand);5932 try self.setRegOrMem(dest_ty, dest, operand);
5919 break :result dest;5933 break :result dest;
...@@ -5922,19 +5936,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -5922,19 +5936,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
5922}5936}
59235937
5924fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {5938fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
5939 const mod = self.bin_file.options.module.?;
5925 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5940 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5926 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {5941 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);
5928 const ptr = try self.resolveInst(ty_op.operand);5943 const ptr = try self.resolveInst(ty_op.operand);
5929 const array_ty = ptr_ty.childType();5944 const array_ty = ptr_ty.childType(mod);
5930 const array_len = @intCast(u32, array_ty.arrayLen());5945 const array_len = @intCast(u32, array_ty.arrayLen(mod));
59315946
5932 const ptr_bits = self.target.ptrBitWidth();5947 const ptr_bits = self.target.ptrBitWidth();
5933 const ptr_bytes = @divExact(ptr_bits, 8);5948 const ptr_bytes = @divExact(ptr_bits, 8);
59345949
5935 const stack_offset = try self.allocMem(ptr_bytes * 2, ptr_bytes * 2, inst);5950 const stack_offset = try self.allocMem(ptr_bytes * 2, ptr_bytes * 2, inst);
5936 try self.genSetStack(ptr_ty, stack_offset, ptr);5951 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 });
5938 break :result MCValue{ .stack_offset = stack_offset };5953 break :result MCValue{ .stack_offset = stack_offset };
5939 };5954 };
5940 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5955 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -6044,8 +6059,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {...@@ -6044,8 +6059,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
6044}6059}
60456060
6046fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {6061fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
6047 const vector_ty = self.air.typeOfIndex(inst);6062 const mod = self.bin_file.options.module.?;
6048 const len = vector_ty.vectorLen();6063 const vector_ty = self.typeOfIndex(inst);
6064 const len = vector_ty.vectorLen(mod);
6049 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6065 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
6050 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);6066 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
6051 const result: MCValue = res: {6067 const result: MCValue = res: {
...@@ -6087,14 +6103,15 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {...@@ -6087,14 +6103,15 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
6087}6103}
60886104
6089fn airTry(self: *Self, inst: Air.Inst.Index) !void {6105fn airTry(self: *Self, inst: Air.Inst.Index) !void {
6106 const mod = self.bin_file.options.module.?;
6090 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6107 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
6091 const extra = self.air.extraData(Air.Try, pl_op.payload);6108 const extra = self.air.extraData(Air.Try, pl_op.payload);
6092 const body = self.air.extra[extra.end..][0..extra.data.body_len];6109 const body = self.air.extra[extra.end..][0..extra.data.body_len];
6093 const result: MCValue = result: {6110 const result: MCValue = result: {
6094 const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand };6111 const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand };
6095 const error_union_ty = self.air.typeOf(pl_op.operand);6112 const error_union_ty = self.typeOf(pl_op.operand);
6096 const error_union_size = @intCast(u32, error_union_ty.abiSize(self.target.*));6113 const error_union_size = @intCast(u32, error_union_ty.abiSize(mod));
6097 const error_union_align = error_union_ty.abiAlignment(self.target.*);6114 const error_union_align = error_union_ty.abiAlignment(mod);
60986115
6099 // The error union will die in the body. However, we need the6116 // The error union will die in the body. However, we need the
6100 // error union after the body in order to extract the payload6117 // error union after the body in order to extract the payload
...@@ -6123,37 +6140,32 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -6123,37 +6140,32 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
6123}6140}
61246141
6125fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {6142fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6126 // First section of indexes correspond to a set number of constant values.6143 const mod = self.bin_file.options.module.?;
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 }
61356144
6136 // If the type has no codegen bits, no need to store it.6145 // If the type has no codegen bits, no need to store it.
6137 const inst_ty = self.air.typeOf(inst);6146 const inst_ty = self.typeOf(inst);
6138 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())6147 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))
6139 return MCValue{ .none = {} };6148 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
6142 switch (self.air.instructions.items(.tag)[inst_index]) {6155 switch (self.air.instructions.items(.tag)[inst_index]) {
6143 .constant => {6156 .interned => {
6144 // Constants have static lifetimes, so they are always memoized in the outer most table.6157 // Constants have static lifetimes, so they are always memoized in the outer most table.
6145 const branch = &self.branch_stack.items[0];6158 const branch = &self.branch_stack.items[0];
6146 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);6159 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
6147 if (!gop.found_existing) {6160 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;
6149 gop.value_ptr.* = try self.genTypedValue(.{6162 gop.value_ptr.* = try self.genTypedValue(.{
6150 .ty = inst_ty,6163 .ty = inst_ty,
6151 .val = self.air.values[ty_pl.payload],6164 .val = interned.toValue(),
6152 });6165 });
6153 }6166 }
6154 return gop.value_ptr.*;6167 return gop.value_ptr.*;
6155 },6168 },
6156 .const_ty => unreachable,
6157 else => return self.getResolvedInstValue(inst_index),6169 else => return self.getResolvedInstValue(inst_index),
6158 }6170 }
6159}6171}
...@@ -6208,12 +6220,11 @@ const CallMCValues = struct {...@@ -6208,12 +6220,11 @@ const CallMCValues = struct {
62086220
6209/// Caller must call `CallMCValues.deinit`.6221/// Caller must call `CallMCValues.deinit`.
6210fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6222fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6211 const cc = fn_ty.fnCallingConvention();6223 const mod = self.bin_file.options.module.?;
6212 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());6224 const fn_info = mod.typeToFunc(fn_ty).?;
6213 defer self.gpa.free(param_types);6225 const cc = fn_info.cc;
6214 fn_ty.fnParamTypes(param_types);
6215 var result: CallMCValues = .{6226 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),
6217 // These undefined values must be populated before returning from this function.6228 // These undefined values must be populated before returning from this function.
6218 .return_value = undefined,6229 .return_value = undefined,
6219 .stack_byte_count = undefined,6230 .stack_byte_count = undefined,
...@@ -6221,7 +6232,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6221,7 +6232,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6221 };6232 };
6222 errdefer self.gpa.free(result.args);6233 errdefer self.gpa.free(result.args);
62236234
6224 const ret_ty = fn_ty.fnReturnType();6235 const ret_ty = fn_ty.fnReturnType(mod);
62256236
6226 switch (cc) {6237 switch (cc) {
6227 .Naked => {6238 .Naked => {
...@@ -6236,14 +6247,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6236,14 +6247,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6236 var ncrn: usize = 0; // Next Core Register Number6247 var ncrn: usize = 0; // Next Core Register Number
6237 var nsaa: u32 = 0; // Next stacked argument address6248 var nsaa: u32 = 0; // Next stacked argument address
62386249
6239 if (ret_ty.zigTypeTag() == .NoReturn) {6250 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
6240 result.return_value = .{ .unreach = {} };6251 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)) {
6242 result.return_value = .{ .none = {} };6253 result.return_value = .{ .none = {} };
6243 } else {6254 } else {
6244 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));6255 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
6245 if (ret_ty_size == 0) {6256 if (ret_ty_size == 0) {
6246 assert(ret_ty.isError());6257 assert(ret_ty.isError(mod));
6247 result.return_value = .{ .immediate = 0 };6258 result.return_value = .{ .immediate = 0 };
6248 } else if (ret_ty_size <= 8) {6259 } else if (ret_ty_size <= 8) {
6249 result.return_value = .{ .register = self.registerAlias(c_abi_int_return_regs[0], ret_ty) };6260 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 {...@@ -6252,8 +6263,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6252 }6263 }
6253 }6264 }
62546265
6255 for (param_types, 0..) |ty, i| {6266 for (fn_info.param_types, 0..) |ty, i| {
6256 const param_size = @intCast(u32, ty.abiSize(self.target.*));6267 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6257 if (param_size == 0) {6268 if (param_size == 0) {
6258 result.args[i] = .{ .none = {} };6269 result.args[i] = .{ .none = {} };
6259 continue;6270 continue;
...@@ -6261,14 +6272,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6261,14 +6272,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62616272
6262 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned6273 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
6263 // values to spread across odd-numbered registers.6274 // 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()) {
6265 // Round up NCRN to the next even number6276 // Round up NCRN to the next even number
6266 ncrn += ncrn % 2;6277 ncrn += ncrn % 2;
6267 }6278 }
62686279
6269 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {6280 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
6270 if (param_size <= 8) {6281 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()) };
6272 ncrn += 1;6283 ncrn += 1;
6273 } else {6284 } else {
6274 return self.fail("TODO MCValues with multiple registers", .{});6285 return self.fail("TODO MCValues with multiple registers", .{});
...@@ -6279,7 +6290,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6279,7 +6290,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6279 ncrn = 8;6290 ncrn = 8;
6280 // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided6291 // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided
6281 // that the entire stack space consumed by the arguments is 8-byte aligned.6292 // 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) {
6283 if (nsaa % 8 != 0) {6294 if (nsaa % 8 != 0) {
6284 nsaa += 8 - (nsaa % 8);6295 nsaa += 8 - (nsaa % 8);
6285 }6296 }
...@@ -6294,14 +6305,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6294,14 +6305,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6294 result.stack_align = 16;6305 result.stack_align = 16;
6295 },6306 },
6296 .Unspecified => {6307 .Unspecified => {
6297 if (ret_ty.zigTypeTag() == .NoReturn) {6308 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
6298 result.return_value = .{ .unreach = {} };6309 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)) {
6300 result.return_value = .{ .none = {} };6311 result.return_value = .{ .none = {} };
6301 } else {6312 } else {
6302 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));6313 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
6303 if (ret_ty_size == 0) {6314 if (ret_ty_size == 0) {
6304 assert(ret_ty.isError());6315 assert(ret_ty.isError(mod));
6305 result.return_value = .{ .immediate = 0 };6316 result.return_value = .{ .immediate = 0 };
6306 } else if (ret_ty_size <= 8) {6317 } else if (ret_ty_size <= 8) {
6307 result.return_value = .{ .register = self.registerAlias(.x0, ret_ty) };6318 result.return_value = .{ .register = self.registerAlias(.x0, ret_ty) };
...@@ -6317,10 +6328,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6317,10 +6328,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63176328
6318 var stack_offset: u32 = 0;6329 var stack_offset: u32 = 0;
63196330
6320 for (param_types, 0..) |ty, i| {6331 for (fn_info.param_types, 0..) |ty, i| {
6321 if (ty.abiSize(self.target.*) > 0) {6332 if (ty.toType().abiSize(mod) > 0) {
6322 const param_size = @intCast(u32, ty.abiSize(self.target.*));6333 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6323 const param_alignment = ty.abiAlignment(self.target.*);6334 const param_alignment = ty.toType().abiAlignment(mod);
63246335
6325 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);6336 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
6326 result.args[i] = .{ .stack_argument_offset = stack_offset };6337 result.args[i] = .{ .stack_argument_offset = stack_offset };
...@@ -6371,7 +6382,8 @@ fn parseRegName(name: []const u8) ?Register {...@@ -6371,7 +6382,8 @@ fn parseRegName(name: []const u8) ?Register {
6371}6382}
63726383
6373fn registerAlias(self: *Self, reg: Register, ty: Type) Register {6384fn 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
6376 switch (reg.class()) {6388 switch (reg.class()) {
6377 .general_purpose => {6389 .general_purpose => {
...@@ -6397,3 +6409,13 @@ fn registerAlias(self: *Self, reg: Register, ty: Type) Register {...@@ -6397,3 +6409,13 @@ fn registerAlias(self: *Self, reg: Register, ty: Type) Register {
6397 },6409 },
6398 }6410 }
6399}6411}
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");...@@ -4,6 +4,7 @@ const bits = @import("bits.zig");
4const Register = bits.Register;4const Register = bits.Register;
5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
6const Type = @import("../../type.zig").Type;6const Type = @import("../../type.zig").Type;
7const Module = @import("../../Module.zig");
78
8pub const Class = union(enum) {9pub const Class = union(enum) {
9 memory,10 memory,
...@@ -14,44 +15,44 @@ pub const Class = union(enum) {...@@ -14,44 +15,44 @@ pub const Class = union(enum) {
14};15};
1516
16/// For `float_array` the second element will be the amount of floats.17/// For `float_array` the second element will be the amount of floats.
17pub fn classifyType(ty: Type, target: std.Target) Class {18pub fn classifyType(ty: Type, mod: *Module) Class {
18 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime());19 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod));
1920
20 var maybe_float_bits: ?u16 = null;21 var maybe_float_bits: ?u16 = null;
21 switch (ty.zigTypeTag()) {22 switch (ty.zigTypeTag(mod)) {
22 .Struct => {23 .Struct => {
23 if (ty.containerLayout() == .Packed) return .byval;24 if (ty.containerLayout(mod) == .Packed) return .byval;
24 const float_count = countFloats(ty, target, &maybe_float_bits);25 const float_count = countFloats(ty, mod, &maybe_float_bits);
25 if (float_count <= sret_float_count) return .{ .float_array = float_count };26 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);
28 if (bit_size > 128) return .memory;29 if (bit_size > 128) return .memory;
29 if (bit_size > 64) return .double_integer;30 if (bit_size > 64) return .double_integer;
30 return .integer;31 return .integer;
31 },32 },
32 .Union => {33 .Union => {
33 if (ty.containerLayout() == .Packed) return .byval;34 if (ty.containerLayout(mod) == .Packed) return .byval;
34 const float_count = countFloats(ty, target, &maybe_float_bits);35 const float_count = countFloats(ty, mod, &maybe_float_bits);
35 if (float_count <= sret_float_count) return .{ .float_array = float_count };36 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);
38 if (bit_size > 128) return .memory;39 if (bit_size > 128) return .memory;
39 if (bit_size > 64) return .double_integer;40 if (bit_size > 64) return .double_integer;
40 return .integer;41 return .integer;
41 },42 },
42 .Int, .Enum, .ErrorSet, .Float, .Bool => return .byval,43 .Int, .Enum, .ErrorSet, .Float, .Bool => return .byval,
43 .Vector => {44 .Vector => {
44 const bit_size = ty.bitSize(target);45 const bit_size = ty.bitSize(mod);
45 // TODO is this controlled by a cpu feature?46 // TODO is this controlled by a cpu feature?
46 if (bit_size > 128) return .memory;47 if (bit_size > 128) return .memory;
47 return .byval;48 return .byval;
48 },49 },
49 .Optional => {50 .Optional => {
50 std.debug.assert(ty.isPtrLikeOptional());51 std.debug.assert(ty.isPtrLikeOptional(mod));
51 return .byval;52 return .byval;
52 },53 },
53 .Pointer => {54 .Pointer => {
54 std.debug.assert(!ty.isSlice());55 std.debug.assert(!ty.isSlice(mod));
55 return .byval;56 return .byval;
56 },57 },
57 .ErrorUnion,58 .ErrorUnion,
...@@ -73,14 +74,15 @@ pub fn classifyType(ty: Type, target: std.Target) Class {...@@ -73,14 +74,15 @@ pub fn classifyType(ty: Type, target: std.Target) Class {
73}74}
7475
75const sret_float_count = 4;76const 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();
77 const invalid = std.math.maxInt(u8);79 const invalid = std.math.maxInt(u8);
78 switch (ty.zigTypeTag()) {80 switch (ty.zigTypeTag(mod)) {
79 .Union => {81 .Union => {
80 const fields = ty.unionFields();82 const fields = ty.unionFields(mod);
81 var max_count: u8 = 0;83 var max_count: u8 = 0;
82 for (fields.values()) |field| {84 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);
84 if (field_count == invalid) return invalid;86 if (field_count == invalid) return invalid;
85 if (field_count > max_count) max_count = field_count;87 if (field_count > max_count) max_count = field_count;
86 if (max_count > sret_float_count) return invalid;88 if (max_count > sret_float_count) return invalid;
...@@ -88,12 +90,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {...@@ -88,12 +90,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {
88 return max_count;90 return max_count;
89 },91 },
90 .Struct => {92 .Struct => {
91 const fields_len = ty.structFieldCount();93 const fields_len = ty.structFieldCount(mod);
92 var count: u8 = 0;94 var count: u8 = 0;
93 var i: u32 = 0;95 var i: u32 = 0;
94 while (i < fields_len) : (i += 1) {96 while (i < fields_len) : (i += 1) {
95 const field_ty = ty.structFieldType(i);97 const field_ty = ty.structFieldType(i, mod);
96 const field_count = countFloats(field_ty, target, maybe_float_bits);98 const field_count = countFloats(field_ty, mod, maybe_float_bits);
97 if (field_count == invalid) return invalid;99 if (field_count == invalid) return invalid;
98 count += field_count;100 count += field_count;
99 if (count > sret_float_count) return invalid;101 if (count > sret_float_count) return invalid;
...@@ -113,21 +115,21 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {...@@ -113,21 +115,21 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {
113 }115 }
114}116}
115117
116pub fn getFloatArrayType(ty: Type) ?Type {118pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type {
117 switch (ty.zigTypeTag()) {119 switch (ty.zigTypeTag(mod)) {
118 .Union => {120 .Union => {
119 const fields = ty.unionFields();121 const fields = ty.unionFields(mod);
120 for (fields.values()) |field| {122 for (fields.values()) |field| {
121 if (getFloatArrayType(field.ty)) |some| return some;123 if (getFloatArrayType(field.ty, mod)) |some| return some;
122 }124 }
123 return null;125 return null;
124 },126 },
125 .Struct => {127 .Struct => {
126 const fields_len = ty.structFieldCount();128 const fields_len = ty.structFieldCount(mod);
127 var i: u32 = 0;129 var i: u32 = 0;
128 while (i < fields_len) : (i += 1) {130 while (i < fields_len) : (i += 1) {
129 const field_ty = ty.structFieldType(i);131 const field_ty = ty.structFieldType(i, mod);
130 if (getFloatArrayType(field_ty)) |some| return some;132 if (getFloatArrayType(field_ty, mod)) |some| return some;
131 }133 }
132 return null;134 return null;
133 },135 },
src/arch/arm/CodeGen.zig+365-342
...@@ -334,7 +334,7 @@ const Self = @This();...@@ -334,7 +334,7 @@ const Self = @This();
334pub fn generate(334pub fn generate(
335 bin_file: *link.File,335 bin_file: *link.File,
336 src_loc: Module.SrcLoc,336 src_loc: Module.SrcLoc,
337 module_fn: *Module.Fn,337 module_fn_index: Module.Fn.Index,
338 air: Air,338 air: Air,
339 liveness: Liveness,339 liveness: Liveness,
340 code: *std.ArrayList(u8),340 code: *std.ArrayList(u8),
...@@ -345,6 +345,7 @@ pub fn generate(...@@ -345,6 +345,7 @@ pub fn generate(
345 }345 }
346346
347 const mod = bin_file.options.module.?;347 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);
348 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
349 assert(fn_owner_decl.has_tv);350 assert(fn_owner_decl.has_tv);
350 const fn_type = fn_owner_decl.ty;351 const fn_type = fn_owner_decl.ty;
...@@ -477,7 +478,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -477,7 +478,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
477}478}
478479
479fn gen(self: *Self) !void {480fn 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);
481 if (cc != .Naked) {483 if (cc != .Naked) {
482 // push {fp, lr}484 // push {fp, lr}
483 const push_reloc = try self.addNop();485 const push_reloc = try self.addNop();
...@@ -518,10 +520,10 @@ fn gen(self: *Self) !void {...@@ -518,10 +520,10 @@ fn gen(self: *Self) !void {
518 const inst = self.air.getMainBody()[arg_index];520 const inst = self.air.getMainBody()[arg_index];
519 assert(self.air.instructions.items(.tag)[inst] == .arg);521 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.*));525 const abi_size = @intCast(u32, ty.abiSize(mod));
524 const abi_align = ty.abiAlignment(self.target.*);526 const abi_align = ty.abiAlignment(mod);
525 const stack_offset = try self.allocMem(abi_size, abi_align, inst);527 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
526 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });528 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
527529
...@@ -636,13 +638,14 @@ fn gen(self: *Self) !void {...@@ -636,13 +638,14 @@ fn gen(self: *Self) !void {
636}638}
637639
638fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {640fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
641 const mod = self.bin_file.options.module.?;
642 const ip = &mod.intern_pool;
639 const air_tags = self.air.instructions.items(.tag);643 const air_tags = self.air.instructions.items(.tag);
640644
641 for (body) |inst| {645 for (body) |inst| {
642 // TODO: remove now-redundant isUnused calls from AIR handler functions646 // 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))
644 continue;648 continue;
645 }
646649
647 const old_air_bookkeeping = self.air_bookkeeping;650 const old_air_bookkeeping = self.air_bookkeeping;
648 try self.ensureProcessDeathCapacity(Liveness.bpi);651 try self.ensureProcessDeathCapacity(Liveness.bpi);
...@@ -826,8 +829,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -826,8 +829,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
826 .ptr_elem_val => try self.airPtrElemVal(inst),829 .ptr_elem_val => try self.airPtrElemVal(inst),
827 .ptr_elem_ptr => try self.airPtrElemPtr(inst),830 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
828831
829 .constant => unreachable, // excluded from function bodies832 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
830 .const_ty => unreachable, // excluded from function bodies
831 .unreach => self.finishAirBookkeeping(),833 .unreach => self.finishAirBookkeeping(),
832834
833 .optional_payload => try self.airOptionalPayload(inst),835 .optional_payload => try self.airOptionalPayload(inst),
...@@ -900,8 +902,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -900,8 +902,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
900902
901/// Asserts there is already capacity to insert into top branch inst_table.903/// Asserts there is already capacity to insert into top branch inst_table.
902fn processDeath(self: *Self, inst: Air.Inst.Index) void {904fn processDeath(self: *Self, inst: Air.Inst.Index) void {
903 const air_tags = self.air.instructions.items(.tag);905 assert(self.air.instructions.items(.tag)[inst] != .interned);
904 if (air_tags[inst] == .constant) return; // Constants are immortal.
905 // When editing this function, note that the logic must synchronize with `reuseOperand`.906 // When editing this function, note that the logic must synchronize with `reuseOperand`.
906 const prev_value = self.getResolvedInstValue(inst);907 const prev_value = self.getResolvedInstValue(inst);
907 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];908 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...@@ -937,8 +938,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
937 tomb_bits >>= 1;938 tomb_bits >>= 1;
938 if (!dies) continue;939 if (!dies) continue;
939 const op_int = @enumToInt(op);940 const op_int = @enumToInt(op);
940 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;941 if (op_int < Air.ref_start_index) continue;
941 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);942 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
942 self.processDeath(op_index);943 self.processDeath(op_index);
943 }944 }
944 const is_used = @truncate(u1, tomb_bits) == 0;945 const is_used = @truncate(u1, tomb_bits) == 0;
...@@ -1006,9 +1007,10 @@ fn allocMem(...@@ -1006,9 +1007,10 @@ fn allocMem(
10061007
1007/// Use a pointer instruction as the basis for allocating stack memory.1008/// Use a pointer instruction as the basis for allocating stack memory.
1008fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {1009fn 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)) {
1012 // As this stack item will never be dereferenced at runtime,1014 // As this stack item will never be dereferenced at runtime,
1013 // return the stack offset 0. Stack offset 0 will be where all1015 // return the stack offset 0. Stack offset 0 will be where all
1014 // zero-sized stack allocations live as non-zero-sized1016 // zero-sized stack allocations live as non-zero-sized
...@@ -1016,22 +1018,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -1016,22 +1018,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
1016 return @as(u32, 0);1018 return @as(u32, 0);
1017 }1019 }
10181020
1019 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {1021 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
1020 const mod = self.bin_file.options.module.?;
1021 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});1022 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
1022 };1023 };
1023 // TODO swap this for inst.ty.ptrAlign1024 // 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
1026 return self.allocMem(abi_size, abi_align, inst);1027 return self.allocMem(abi_size, abi_align, inst);
1027}1028}
10281029
1029fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {1030fn 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 {
1032 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});1033 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
1033 };1034 };
1034 const abi_align = elem_ty.abiAlignment(self.target.*);1035 const abi_align = elem_ty.abiAlignment(mod);
10351036
1036 if (reg_ok) {1037 if (reg_ok) {
1037 // Make sure the type can fit in a register before we try to allocate one.1038 // 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...@@ -1049,7 +1050,7 @@ fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst
1049}1050}
10501051
1051pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {1052pub 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);
1053 log.debug("spilling {} (%{d}) to stack mcv {any}", .{ reg, inst, stack_mcv });1054 log.debug("spilling {} (%{d}) to stack mcv {any}", .{ reg, inst, stack_mcv });
10541055
1055 const reg_mcv = self.getResolvedInstValue(inst);1056 const reg_mcv = self.getResolvedInstValue(inst);
...@@ -1063,14 +1064,14 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -1063,14 +1064,14 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
10631064
1064 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1065 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1065 try branch.inst_table.put(self.gpa, inst, stack_mcv);1066 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);
1067}1068}
10681069
1069/// Save the current instruction stored in the compare flags if1070/// Save the current instruction stored in the compare flags if
1070/// occupied1071/// occupied
1071fn spillCompareFlagsIfOccupied(self: *Self) !void {1072fn spillCompareFlagsIfOccupied(self: *Self) !void {
1072 if (self.cpsr_flags_inst) |inst_to_save| {1073 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);
1074 const mcv = self.getResolvedInstValue(inst_to_save);1075 const mcv = self.getResolvedInstValue(inst_to_save);
1075 const new_mcv = switch (mcv) {1076 const new_mcv = switch (mcv) {
1076 .cpsr_flags => try self.allocRegOrMem(ty, true, inst_to_save),1077 .cpsr_flags => try self.allocRegOrMem(ty, true, inst_to_save),
...@@ -1080,7 +1081,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -1080,7 +1081,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
1080 else => unreachable, // mcv doesn't occupy the compare flags1081 else => unreachable, // mcv doesn't occupy the compare flags
1081 };1082 };
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);
1084 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });1085 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
10851086
1086 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1087 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 {...@@ -1114,17 +1115,14 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
1114}1115}
11151116
1116fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {1117fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1118 const mod = self.bin_file.options.module.?;
1117 const result: MCValue = switch (self.ret_mcv) {1119 const result: MCValue = switch (self.ret_mcv) {
1118 .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) },1120 .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) },
1119 .stack_offset => blk: {1121 .stack_offset => blk: {
1120 // self.ret_mcv is an address to where this function1122 // self.ret_mcv is an address to where this function
1121 // should store its result into1123 // should store its result into
1122 const ret_ty = self.fn_type.fnReturnType();1124 const ret_ty = self.fn_type.fnReturnType(mod);
1123 var ptr_ty_payload: Type.Payload.ElemType = .{1125 const ptr_ty = try mod.singleMutPtrType(ret_ty);
1124 .base = .{ .tag = .single_mut_pointer },
1125 .data = ret_ty,
1126 };
1127 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
11281126
1129 // addr_reg will contain the address of where to store the1127 // addr_reg will contain the address of where to store the
1130 // result into1128 // result into
...@@ -1150,18 +1148,19 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {...@@ -1150,18 +1148,19 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
1150}1148}
11511149
1152fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {1150fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1151 const mod = self.bin_file.options.module.?;
1153 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1152 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1154 if (self.liveness.isUnused(inst))1153 if (self.liveness.isUnused(inst))
1155 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });1154 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
11561155
1157 const operand = try self.resolveInst(ty_op.operand);1156 const operand = try self.resolveInst(ty_op.operand);
1158 const operand_ty = self.air.typeOf(ty_op.operand);1157 const operand_ty = self.typeOf(ty_op.operand);
1159 const dest_ty = self.air.typeOfIndex(inst);1158 const dest_ty = self.typeOfIndex(inst);
11601159
1161 const operand_abi_size = operand_ty.abiSize(self.target.*);1160 const operand_abi_size = operand_ty.abiSize(mod);
1162 const dest_abi_size = dest_ty.abiSize(self.target.*);1161 const dest_abi_size = dest_ty.abiSize(mod);
1163 const info_a = operand_ty.intInfo(self.target.*);1162 const info_a = operand_ty.intInfo(mod);
1164 const info_b = dest_ty.intInfo(self.target.*);1163 const info_b = dest_ty.intInfo(mod);
11651164
1166 const dst_mcv: MCValue = blk: {1165 const dst_mcv: MCValue = blk: {
1167 if (info_a.bits == info_b.bits) {1166 if (info_a.bits == info_b.bits) {
...@@ -1215,8 +1214,9 @@ fn trunc(...@@ -1215,8 +1214,9 @@ fn trunc(
1215 operand_ty: Type,1214 operand_ty: Type,
1216 dest_ty: Type,1215 dest_ty: Type,
1217) !MCValue {1216) !MCValue {
1218 const info_a = operand_ty.intInfo(self.target.*);1217 const mod = self.bin_file.options.module.?;
1219 const info_b = dest_ty.intInfo(self.target.*);1218 const info_a = operand_ty.intInfo(mod);
1219 const info_b = dest_ty.intInfo(mod);
12201220
1221 if (info_b.bits <= 32) {1221 if (info_b.bits <= 32) {
1222 if (info_a.bits > 32) {1222 if (info_a.bits > 32) {
...@@ -1259,8 +1259,8 @@ fn trunc(...@@ -1259,8 +1259,8 @@ fn trunc(
1259fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {1259fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
1260 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1260 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1261 const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand };1261 const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
1262 const operand_ty = self.air.typeOf(ty_op.operand);1262 const operand_ty = self.typeOf(ty_op.operand);
1263 const dest_ty = self.air.typeOfIndex(inst);1263 const dest_ty = self.typeOfIndex(inst);
12641264
1265 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {1265 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
1266 break :blk try self.trunc(inst, operand_bind, operand_ty, dest_ty);1266 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 {...@@ -1278,15 +1278,16 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
12781278
1279fn airNot(self: *Self, inst: Air.Inst.Index) !void {1279fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1280 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1280 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1281 const mod = self.bin_file.options.module.?;
1281 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1282 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1282 const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand };1283 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);
1284 switch (try operand_bind.resolveToMcv(self)) {1285 switch (try operand_bind.resolveToMcv(self)) {
1285 .dead => unreachable,1286 .dead => unreachable,
1286 .unreach => unreachable,1287 .unreach => unreachable,
1287 .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() },1288 .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() },
1288 else => {1289 else => {
1289 switch (operand_ty.zigTypeTag()) {1290 switch (operand_ty.zigTypeTag(mod)) {
1290 .Bool => {1291 .Bool => {
1291 var op_reg: Register = undefined;1292 var op_reg: Register = undefined;
1292 var dest_reg: Register = undefined;1293 var dest_reg: Register = undefined;
...@@ -1319,7 +1320,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1319,7 +1320,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1319 },1320 },
1320 .Vector => return self.fail("TODO bitwise not for vectors", .{}),1321 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
1321 .Int => {1322 .Int => {
1322 const int_info = operand_ty.intInfo(self.target.*);1323 const int_info = operand_ty.intInfo(mod);
1323 if (int_info.bits <= 32) {1324 if (int_info.bits <= 32) {
1324 var op_reg: Register = undefined;1325 var op_reg: Register = undefined;
1325 var dest_reg: Register = undefined;1326 var dest_reg: Register = undefined;
...@@ -1373,13 +1374,13 @@ fn minMax(...@@ -1373,13 +1374,13 @@ fn minMax(
1373 rhs_ty: Type,1374 rhs_ty: Type,
1374 maybe_inst: ?Air.Inst.Index,1375 maybe_inst: ?Air.Inst.Index,
1375) !MCValue {1376) !MCValue {
1376 switch (lhs_ty.zigTypeTag()) {1377 const mod = self.bin_file.options.module.?;
1378 switch (lhs_ty.zigTypeTag(mod)) {
1377 .Float => return self.fail("TODO ARM min/max on floats", .{}),1379 .Float => return self.fail("TODO ARM min/max on floats", .{}),
1378 .Vector => return self.fail("TODO ARM min/max on vectors", .{}),1380 .Vector => return self.fail("TODO ARM min/max on vectors", .{}),
1379 .Int => {1381 .Int => {
1380 const mod = self.bin_file.options.module.?;
1381 assert(lhs_ty.eql(rhs_ty, mod));1382 assert(lhs_ty.eql(rhs_ty, mod));
1382 const int_info = lhs_ty.intInfo(self.target.*);1383 const int_info = lhs_ty.intInfo(mod);
1383 if (int_info.bits <= 32) {1384 if (int_info.bits <= 32) {
1384 var lhs_reg: Register = undefined;1385 var lhs_reg: Register = undefined;
1385 var rhs_reg: Register = undefined;1386 var rhs_reg: Register = undefined;
...@@ -1463,8 +1464,8 @@ fn minMax(...@@ -1463,8 +1464,8 @@ fn minMax(
1463fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {1464fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {
1464 const tag = self.air.instructions.items(.tag)[inst];1465 const tag = self.air.instructions.items(.tag)[inst];
1465 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1466 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1466 const lhs_ty = self.air.typeOf(bin_op.lhs);1467 const lhs_ty = self.typeOf(bin_op.lhs);
1467 const rhs_ty = self.air.typeOf(bin_op.rhs);1468 const rhs_ty = self.typeOf(bin_op.rhs);
14681469
1469 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1470 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1470 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };1471 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
...@@ -1483,9 +1484,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -1483,9 +1484,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1483 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1484 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1484 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1485 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1485 const ptr = try self.resolveInst(bin_op.lhs);1486 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);
1487 const len = try self.resolveInst(bin_op.rhs);1488 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
1490 const stack_offset = try self.allocMem(8, 4, inst);1491 const stack_offset = try self.allocMem(8, 4, inst);
1491 try self.genSetStack(ptr_ty, stack_offset, ptr);1492 try self.genSetStack(ptr_ty, stack_offset, ptr);
...@@ -1497,8 +1498,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -1497,8 +1498,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
14971498
1498fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {1499fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1499 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1500 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1500 const lhs_ty = self.air.typeOf(bin_op.lhs);1501 const lhs_ty = self.typeOf(bin_op.lhs);
1501 const rhs_ty = self.air.typeOf(bin_op.rhs);1502 const rhs_ty = self.typeOf(bin_op.rhs);
15021503
1503 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1504 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1504 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };1505 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 {...@@ -1548,8 +1549,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1548fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {1549fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1549 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1550 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1550 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1551 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1551 const lhs_ty = self.air.typeOf(bin_op.lhs);1552 const lhs_ty = self.typeOf(bin_op.lhs);
1552 const rhs_ty = self.air.typeOf(bin_op.rhs);1553 const rhs_ty = self.typeOf(bin_op.rhs);
15531554
1554 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1555 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1555 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };1556 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
...@@ -1582,23 +1583,23 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1582,23 +1583,23 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1582 const tag = self.air.instructions.items(.tag)[inst];1583 const tag = self.air.instructions.items(.tag)[inst];
1583 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1584 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1584 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1585 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1586 const mod = self.bin_file.options.module.?;
1585 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1587 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1586 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };1588 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
1587 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };1589 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
1588 const lhs_ty = self.air.typeOf(extra.lhs);1590 const lhs_ty = self.typeOf(extra.lhs);
1589 const rhs_ty = self.air.typeOf(extra.rhs);1591 const rhs_ty = self.typeOf(extra.rhs);
15901592
1591 const tuple_ty = self.air.typeOfIndex(inst);1593 const tuple_ty = self.typeOfIndex(inst);
1592 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));1594 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
1593 const tuple_align = tuple_ty.abiAlignment(self.target.*);1595 const tuple_align = tuple_ty.abiAlignment(mod);
1594 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));1596 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
15951597
1596 switch (lhs_ty.zigTypeTag()) {1598 switch (lhs_ty.zigTypeTag(mod)) {
1597 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),1599 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),
1598 .Int => {1600 .Int => {
1599 const mod = self.bin_file.options.module.?;
1600 assert(lhs_ty.eql(rhs_ty, mod));1601 assert(lhs_ty.eql(rhs_ty, mod));
1601 const int_info = lhs_ty.intInfo(self.target.*);1602 const int_info = lhs_ty.intInfo(mod);
1602 if (int_info.bits < 32) {1603 if (int_info.bits < 32) {
1603 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);1604 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 {...@@ -1631,7 +1632,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1631 });1632 });
16321633
1633 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1634 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
1636 break :result MCValue{ .stack_offset = stack_offset };1637 break :result MCValue{ .stack_offset = stack_offset };
1637 } else if (int_info.bits == 32) {1638 } else if (int_info.bits == 32) {
...@@ -1695,23 +1696,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1695,23 +1696,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1695 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1696 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1696 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1697 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1697 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });1698 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
1699 const mod = self.bin_file.options.module.?;
1698 const result: MCValue = result: {1700 const result: MCValue = result: {
1699 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };1701 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
1700 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };1702 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
1701 const lhs_ty = self.air.typeOf(extra.lhs);1703 const lhs_ty = self.typeOf(extra.lhs);
1702 const rhs_ty = self.air.typeOf(extra.rhs);1704 const rhs_ty = self.typeOf(extra.rhs);
17031705
1704 const tuple_ty = self.air.typeOfIndex(inst);1706 const tuple_ty = self.typeOfIndex(inst);
1705 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));1707 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
1706 const tuple_align = tuple_ty.abiAlignment(self.target.*);1708 const tuple_align = tuple_ty.abiAlignment(mod);
1707 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));1709 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
17081710
1709 switch (lhs_ty.zigTypeTag()) {1711 switch (lhs_ty.zigTypeTag(mod)) {
1710 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),1712 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
1711 .Int => {1713 .Int => {
1712 const mod = self.bin_file.options.module.?;
1713 assert(lhs_ty.eql(rhs_ty, mod));1714 assert(lhs_ty.eql(rhs_ty, mod));
1714 const int_info = lhs_ty.intInfo(self.target.*);1715 const int_info = lhs_ty.intInfo(mod);
1715 if (int_info.bits <= 16) {1716 if (int_info.bits <= 16) {
1716 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);1717 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 {...@@ -1744,7 +1745,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1744 });1745 });
17451746
1746 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1747 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
1749 break :result MCValue{ .stack_offset = stack_offset };1750 break :result MCValue{ .stack_offset = stack_offset };
1750 } else if (int_info.bits <= 32) {1751 } else if (int_info.bits <= 32) {
...@@ -1842,7 +1843,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1842,7 +1843,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1842 });1843 });
18431844
1844 // strb rdlo, [...]1845 // 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
1847 break :result MCValue{ .stack_offset = stack_offset };1848 break :result MCValue{ .stack_offset = stack_offset };
1848 } else {1849 } else {
...@@ -1859,19 +1860,20 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1859,19 +1860,20 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1859 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1860 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1860 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1861 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1861 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });1862 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
1863 const mod = self.bin_file.options.module.?;
1862 const result: MCValue = result: {1864 const result: MCValue = result: {
1863 const lhs_ty = self.air.typeOf(extra.lhs);1865 const lhs_ty = self.typeOf(extra.lhs);
1864 const rhs_ty = self.air.typeOf(extra.rhs);1866 const rhs_ty = self.typeOf(extra.rhs);
18651867
1866 const tuple_ty = self.air.typeOfIndex(inst);1868 const tuple_ty = self.typeOfIndex(inst);
1867 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));1869 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
1868 const tuple_align = tuple_ty.abiAlignment(self.target.*);1870 const tuple_align = tuple_ty.abiAlignment(mod);
1869 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));1871 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
18701872
1871 switch (lhs_ty.zigTypeTag()) {1873 switch (lhs_ty.zigTypeTag(mod)) {
1872 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),1874 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
1873 .Int => {1875 .Int => {
1874 const int_info = lhs_ty.intInfo(self.target.*);1876 const int_info = lhs_ty.intInfo(mod);
1875 if (int_info.bits <= 32) {1877 if (int_info.bits <= 32) {
1876 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);1878 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 {...@@ -1976,7 +1978,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1976 });1978 });
19771979
1978 try self.genSetStack(lhs_ty, stack_offset, .{ .register = dest_reg });1980 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
1981 break :result MCValue{ .stack_offset = stack_offset };1983 break :result MCValue{ .stack_offset = stack_offset };
1982 } else {1984 } else {
...@@ -2014,10 +2016,11 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -2014,10 +2016,11 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
2014}2016}
20152017
2016fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {2018fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2019 const mod = self.bin_file.options.module.?;
2017 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2020 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2018 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2021 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2019 const optional_ty = self.air.typeOfIndex(inst);2022 const optional_ty = self.typeOfIndex(inst);
2020 const abi_size = @intCast(u32, optional_ty.abiSize(self.target.*));2023 const abi_size = @intCast(u32, optional_ty.abiSize(mod));
20212024
2022 // Optional with a zero-bit payload type is just a boolean true2025 // Optional with a zero-bit payload type is just a boolean true
2023 if (abi_size == 1) {2026 if (abi_size == 1) {
...@@ -2036,16 +2039,17 @@ fn errUnionErr(...@@ -2036,16 +2039,17 @@ fn errUnionErr(
2036 error_union_ty: Type,2039 error_union_ty: Type,
2037 maybe_inst: ?Air.Inst.Index,2040 maybe_inst: ?Air.Inst.Index,
2038) !MCValue {2041) !MCValue {
2039 const err_ty = error_union_ty.errorUnionSet();2042 const mod = self.bin_file.options.module.?;
2040 const payload_ty = error_union_ty.errorUnionPayload();2043 const err_ty = error_union_ty.errorUnionSet(mod);
2041 if (err_ty.errorSetIsEmpty()) {2044 const payload_ty = error_union_ty.errorUnionPayload(mod);
2045 if (err_ty.errorSetIsEmpty(mod)) {
2042 return MCValue{ .immediate = 0 };2046 return MCValue{ .immediate = 0 };
2043 }2047 }
2044 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2048 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2045 return try error_union_bind.resolveToMcv(self);2049 return try error_union_bind.resolveToMcv(self);
2046 }2050 }
20472051
2048 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));2052 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, mod));
2049 switch (try error_union_bind.resolveToMcv(self)) {2053 switch (try error_union_bind.resolveToMcv(self)) {
2050 .register => {2054 .register => {
2051 var operand_reg: Register = undefined;2055 var operand_reg: Register = undefined;
...@@ -2067,7 +2071,7 @@ fn errUnionErr(...@@ -2067,7 +2071,7 @@ fn errUnionErr(
2067 );2071 );
20682072
2069 const err_bit_offset = err_offset * 8;2073 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
2072 _ = try self.addInst(.{2076 _ = try self.addInst(.{
2073 .tag = .ubfx, // errors are unsigned integers2077 .tag = .ubfx, // errors are unsigned integers
...@@ -2098,7 +2102,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2098,7 +2102,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2098 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2102 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2099 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2103 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2100 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };2104 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
2103 break :result try self.errUnionErr(error_union_bind, error_union_ty, inst);2107 break :result try self.errUnionErr(error_union_bind, error_union_ty, inst);
2104 };2108 };
...@@ -2112,16 +2116,17 @@ fn errUnionPayload(...@@ -2112,16 +2116,17 @@ fn errUnionPayload(
2112 error_union_ty: Type,2116 error_union_ty: Type,
2113 maybe_inst: ?Air.Inst.Index,2117 maybe_inst: ?Air.Inst.Index,
2114) !MCValue {2118) !MCValue {
2115 const err_ty = error_union_ty.errorUnionSet();2119 const mod = self.bin_file.options.module.?;
2116 const payload_ty = error_union_ty.errorUnionPayload();2120 const err_ty = error_union_ty.errorUnionSet(mod);
2117 if (err_ty.errorSetIsEmpty()) {2121 const payload_ty = error_union_ty.errorUnionPayload(mod);
2122 if (err_ty.errorSetIsEmpty(mod)) {
2118 return try error_union_bind.resolveToMcv(self);2123 return try error_union_bind.resolveToMcv(self);
2119 }2124 }
2120 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2125 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2121 return MCValue.none;2126 return MCValue.none;
2122 }2127 }
21232128
2124 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));2129 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
2125 switch (try error_union_bind.resolveToMcv(self)) {2130 switch (try error_union_bind.resolveToMcv(self)) {
2126 .register => {2131 .register => {
2127 var operand_reg: Register = undefined;2132 var operand_reg: Register = undefined;
...@@ -2143,10 +2148,10 @@ fn errUnionPayload(...@@ -2143,10 +2148,10 @@ fn errUnionPayload(
2143 );2148 );
21442149
2145 const payload_bit_offset = payload_offset * 8;2150 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
2148 _ = try self.addInst(.{2153 _ = 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,
2150 .data = .{ .rr_lsb_width = .{2155 .data = .{ .rr_lsb_width = .{
2151 .rd = dest_reg,2156 .rd = dest_reg,
2152 .rn = operand_reg,2157 .rn = operand_reg,
...@@ -2174,7 +2179,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -2174,7 +2179,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
2174 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2179 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2175 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2180 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2176 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };2181 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
2179 break :result try self.errUnionPayload(error_union_bind, error_union_ty, inst);2184 break :result try self.errUnionPayload(error_union_bind, error_union_ty, inst);
2180 };2185 };
...@@ -2221,19 +2226,20 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {...@@ -2221,19 +2226,20 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
22212226
2222/// T to E!T2227/// T to E!T
2223fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {2228fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2229 const mod = self.bin_file.options.module.?;
2224 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2230 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2225 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2231 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2226 const error_union_ty = self.air.getRefType(ty_op.ty);2232 const error_union_ty = self.air.getRefType(ty_op.ty);
2227 const error_ty = error_union_ty.errorUnionSet();2233 const error_ty = error_union_ty.errorUnionSet(mod);
2228 const payload_ty = error_union_ty.errorUnionPayload();2234 const payload_ty = error_union_ty.errorUnionPayload(mod);
2229 const operand = try self.resolveInst(ty_op.operand);2235 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.*));2238 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
2233 const abi_align = error_union_ty.abiAlignment(self.target.*);2239 const abi_align = error_union_ty.abiAlignment(mod);
2234 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));2240 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));
2235 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);2241 const payload_off = errUnionPayloadOffset(payload_ty, mod);
2236 const err_off = errUnionErrorOffset(payload_ty, self.target.*);2242 const err_off = errUnionErrorOffset(payload_ty, mod);
2237 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);2243 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);
2238 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 });2244 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 {...@@ -2244,19 +2250,20 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
22442250
2245/// E to E!T2251/// E to E!T
2246fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {2252fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2253 const mod = self.bin_file.options.module.?;
2247 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2254 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2248 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2255 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2249 const error_union_ty = self.air.getRefType(ty_op.ty);2256 const error_union_ty = self.air.getRefType(ty_op.ty);
2250 const error_ty = error_union_ty.errorUnionSet();2257 const error_ty = error_union_ty.errorUnionSet(mod);
2251 const payload_ty = error_union_ty.errorUnionPayload();2258 const payload_ty = error_union_ty.errorUnionPayload(mod);
2252 const operand = try self.resolveInst(ty_op.operand);2259 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.*));2262 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
2256 const abi_align = error_union_ty.abiAlignment(self.target.*);2263 const abi_align = error_union_ty.abiAlignment(mod);
2257 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));2264 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));
2258 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);2265 const payload_off = errUnionPayloadOffset(payload_ty, mod);
2259 const err_off = errUnionErrorOffset(payload_ty, self.target.*);2266 const err_off = errUnionErrorOffset(payload_ty, mod);
2260 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand);2267 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand);
2261 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef);2268 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef);
22622269
...@@ -2360,8 +2367,9 @@ fn ptrElemVal(...@@ -2360,8 +2367,9 @@ fn ptrElemVal(
2360 ptr_ty: Type,2367 ptr_ty: Type,
2361 maybe_inst: ?Air.Inst.Index,2368 maybe_inst: ?Air.Inst.Index,
2362) !MCValue {2369) !MCValue {
2363 const elem_ty = ptr_ty.childType();2370 const mod = self.bin_file.options.module.?;
2364 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));2371 const elem_ty = ptr_ty.childType(mod);
2372 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
23652373
2366 switch (elem_size) {2374 switch (elem_size) {
2367 1, 4 => {2375 1, 4 => {
...@@ -2418,11 +2426,11 @@ fn ptrElemVal(...@@ -2418,11 +2426,11 @@ fn ptrElemVal(
2418}2426}
24192427
2420fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {2428fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2429 const mod = self.bin_file.options.module.?;
2421 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2430 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2422 const slice_ty = self.air.typeOf(bin_op.lhs);2431 const slice_ty = self.typeOf(bin_op.lhs);
2423 const result: MCValue = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {2432 const result: MCValue = if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
2424 var buf: Type.SlicePtrFieldTypeBuffer = undefined;2433 const ptr_ty = slice_ty.slicePtrFieldType(mod);
2425 const ptr_ty = slice_ty.slicePtrFieldType(&buf);
24262434
2427 const slice_mcv = try self.resolveInst(bin_op.lhs);2435 const slice_mcv = try self.resolveInst(bin_op.lhs);
2428 const base_mcv = slicePtr(slice_mcv);2436 const base_mcv = slicePtr(slice_mcv);
...@@ -2445,8 +2453,8 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2445,8 +2453,8 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2445 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };2453 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };
2446 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };2454 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
24472455
2448 const slice_ty = self.air.typeOf(extra.lhs);2456 const slice_ty = self.typeOf(extra.lhs);
2449 const index_ty = self.air.typeOf(extra.rhs);2457 const index_ty = self.typeOf(extra.rhs);
24502458
2451 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ty, index_ty, null);2459 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ty, index_ty, null);
2452 break :result addr;2460 break :result addr;
...@@ -2461,7 +2469,8 @@ fn arrayElemVal(...@@ -2461,7 +2469,8 @@ fn arrayElemVal(
2461 array_ty: Type,2469 array_ty: Type,
2462 maybe_inst: ?Air.Inst.Index,2470 maybe_inst: ?Air.Inst.Index,
2463) InnerError!MCValue {2471) 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
2466 const mcv = try array_bind.resolveToMcv(self);2475 const mcv = try array_bind.resolveToMcv(self);
2467 switch (mcv) {2476 switch (mcv) {
...@@ -2495,11 +2504,7 @@ fn arrayElemVal(...@@ -2495,11 +2504,7 @@ fn arrayElemVal(
24952504
2496 const base_bind: ReadArg.Bind = .{ .mcv = ptr_to_mcv };2505 const base_bind: ReadArg.Bind = .{ .mcv = ptr_to_mcv };
24972506
2498 var ptr_ty_payload: Type.Payload.ElemType = .{2507 const ptr_ty = try mod.singleMutPtrType(elem_ty);
2499 .base = .{ .tag = .single_mut_pointer },
2500 .data = elem_ty,
2501 };
2502 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
25032508
2504 return try self.ptrElemVal(base_bind, index_bind, ptr_ty, maybe_inst);2509 return try self.ptrElemVal(base_bind, index_bind, ptr_ty, maybe_inst);
2505 },2510 },
...@@ -2512,7 +2517,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2512,7 +2517,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2512 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2517 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2513 const array_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };2518 const array_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
2514 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };2519 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
2517 break :result try self.arrayElemVal(array_bind, index_bind, array_ty, inst);2522 break :result try self.arrayElemVal(array_bind, index_bind, array_ty, inst);
2518 };2523 };
...@@ -2520,9 +2525,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2520,9 +2525,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2520}2525}
25212526
2522fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {2527fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2528 const mod = self.bin_file.options.module.?;
2523 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2529 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2524 const ptr_ty = self.air.typeOf(bin_op.lhs);2530 const ptr_ty = self.typeOf(bin_op.lhs);
2525 const result: MCValue = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {2531 const result: MCValue = if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
2526 const base_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };2532 const base_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
2527 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };2533 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
25282534
...@@ -2538,8 +2544,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2538,8 +2544,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2538 const ptr_bind: ReadArg.Bind = .{ .inst = extra.lhs };2544 const ptr_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2539 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };2545 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
25402546
2541 const ptr_ty = self.air.typeOf(extra.lhs);2547 const ptr_ty = self.typeOf(extra.lhs);
2542 const index_ty = self.air.typeOf(extra.rhs);2548 const index_ty = self.typeOf(extra.rhs);
25432549
2544 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, index_ty, null);2550 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, index_ty, null);
2545 break :result addr;2551 break :result addr;
...@@ -2646,8 +2652,9 @@ fn reuseOperand(...@@ -2646,8 +2652,9 @@ fn reuseOperand(
2646}2652}
26472653
2648fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {2654fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
2649 const elem_ty = ptr_ty.elemType();2655 const mod = self.bin_file.options.module.?;
2650 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));2656 const elem_ty = ptr_ty.childType(mod);
2657 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
26512658
2652 switch (ptr) {2659 switch (ptr) {
2653 .none => unreachable,2660 .none => unreachable,
...@@ -2722,19 +2729,20 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2722,19 +2729,20 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2722}2729}
27232730
2724fn airLoad(self: *Self, inst: Air.Inst.Index) !void {2731fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
2732 const mod = self.bin_file.options.module.?;
2725 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2733 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);
2727 const result: MCValue = result: {2735 const result: MCValue = result: {
2728 if (!elem_ty.hasRuntimeBits())2736 if (!elem_ty.hasRuntimeBits(mod))
2729 break :result MCValue.none;2737 break :result MCValue.none;
27302738
2731 const ptr = try self.resolveInst(ty_op.operand);2739 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);
2733 if (self.liveness.isUnused(inst) and !is_volatile)2741 if (self.liveness.isUnused(inst) and !is_volatile)
2734 break :result MCValue.dead;2742 break :result MCValue.dead;
27352743
2736 const dest_mcv: MCValue = blk: {2744 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;
2738 if (ptr_fits_dest and self.reuseOperand(inst, ty_op.operand, 0, ptr)) {2746 if (ptr_fits_dest and self.reuseOperand(inst, ty_op.operand, 0, ptr)) {
2739 // The MCValue that holds the pointer can be re-used as the value.2747 // The MCValue that holds the pointer can be re-used as the value.
2740 break :blk ptr;2748 break :blk ptr;
...@@ -2742,7 +2750,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -2742,7 +2750,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
2742 break :blk try self.allocRegOrMem(elem_ty, true, inst);2750 break :blk try self.allocRegOrMem(elem_ty, true, inst);
2743 }2751 }
2744 };2752 };
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
2747 break :result dest_mcv;2755 break :result dest_mcv;
2748 };2756 };
...@@ -2750,7 +2758,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -2750,7 +2758,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
2750}2758}
27512759
2752fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {2760fn 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
2755 switch (ptr) {2764 switch (ptr) {
2756 .none => unreachable,2765 .none => unreachable,
...@@ -2846,8 +2855,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -2846,8 +2855,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
2846 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2855 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2847 const ptr = try self.resolveInst(bin_op.lhs);2856 const ptr = try self.resolveInst(bin_op.lhs);
2848 const value = try self.resolveInst(bin_op.rhs);2857 const value = try self.resolveInst(bin_op.rhs);
2849 const ptr_ty = self.air.typeOf(bin_op.lhs);2858 const ptr_ty = self.typeOf(bin_op.lhs);
2850 const value_ty = self.air.typeOf(bin_op.rhs);2859 const value_ty = self.typeOf(bin_op.rhs);
28512860
2852 try self.store(ptr, value, ptr_ty, value_ty);2861 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 {...@@ -2869,10 +2878,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
28692878
2870fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {2879fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
2871 return if (self.liveness.isUnused(inst)) .dead else result: {2880 return if (self.liveness.isUnused(inst)) .dead else result: {
2881 const mod = self.bin_file.options.module.?;
2872 const mcv = try self.resolveInst(operand);2882 const mcv = try self.resolveInst(operand);
2873 const ptr_ty = self.air.typeOf(operand);2883 const ptr_ty = self.typeOf(operand);
2874 const struct_ty = ptr_ty.childType();2884 const struct_ty = ptr_ty.childType(mod);
2875 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));2885 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
2876 switch (mcv) {2886 switch (mcv) {
2877 .ptr_stack_offset => |off| {2887 .ptr_stack_offset => |off| {
2878 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };2888 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };
...@@ -2892,11 +2902,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2892,11 +2902,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2892 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;2902 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
2893 const operand = extra.struct_operand;2903 const operand = extra.struct_operand;
2894 const index = extra.field_index;2904 const index = extra.field_index;
2905 const mod = self.bin_file.options.module.?;
2895 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2906 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2896 const mcv = try self.resolveInst(operand);2907 const mcv = try self.resolveInst(operand);
2897 const struct_ty = self.air.typeOf(operand);2908 const struct_ty = self.typeOf(operand);
2898 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));2909 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
2899 const struct_field_ty = struct_ty.structFieldType(index);2910 const struct_field_ty = struct_ty.structFieldType(index, mod);
29002911
2901 switch (mcv) {2912 switch (mcv) {
2902 .dead, .unreach => unreachable,2913 .dead, .unreach => unreachable,
...@@ -2959,10 +2970,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2959,10 +2970,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2959 );2970 );
29602971
2961 const field_bit_offset = struct_field_offset * 8;2972 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
2964 _ = try self.addInst(.{2975 _ = 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,
2966 .data = .{ .rr_lsb_width = .{2977 .data = .{ .rr_lsb_width = .{
2967 .rd = dest_reg,2978 .rd = dest_reg,
2968 .rn = operand_reg,2979 .rn = operand_reg,
...@@ -2981,17 +2992,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2981,17 +2992,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2981}2992}
29822993
2983fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {2994fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
2995 const mod = self.bin_file.options.module.?;
2984 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2996 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2985 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;2997 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
2986 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2998 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2987 const field_ptr = try self.resolveInst(extra.field_ptr);2999 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) {
2991 return self.fail("TODO implement @fieldParentPtr codegen for unions", .{});3003 return self.fail("TODO implement @fieldParentPtr codegen for unions", .{});
2992 }3004 }
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));
2995 switch (field_ptr) {3007 switch (field_ptr) {
2996 .ptr_stack_offset => |off| {3008 .ptr_stack_offset => |off| {
2997 break :result MCValue{ .ptr_stack_offset = off + struct_field_offset };3009 break :result MCValue{ .ptr_stack_offset = off + struct_field_offset };
...@@ -3375,12 +3387,12 @@ fn addSub(...@@ -3375,12 +3387,12 @@ fn addSub(
3375 maybe_inst: ?Air.Inst.Index,3387 maybe_inst: ?Air.Inst.Index,
3376) InnerError!MCValue {3388) InnerError!MCValue {
3377 const mod = self.bin_file.options.module.?;3389 const mod = self.bin_file.options.module.?;
3378 switch (lhs_ty.zigTypeTag()) {3390 switch (lhs_ty.zigTypeTag(mod)) {
3379 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3391 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3380 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3392 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3381 .Int => {3393 .Int => {
3382 assert(lhs_ty.eql(rhs_ty, mod));3394 assert(lhs_ty.eql(rhs_ty, mod));
3383 const int_info = lhs_ty.intInfo(self.target.*);3395 const int_info = lhs_ty.intInfo(mod);
3384 if (int_info.bits <= 32) {3396 if (int_info.bits <= 32) {
3385 const lhs_immediate = try lhs_bind.resolveToImmediate(self);3397 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
3386 const rhs_immediate = try rhs_bind.resolveToImmediate(self);3398 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
...@@ -3431,12 +3443,12 @@ fn mul(...@@ -3431,12 +3443,12 @@ fn mul(
3431 maybe_inst: ?Air.Inst.Index,3443 maybe_inst: ?Air.Inst.Index,
3432) InnerError!MCValue {3444) InnerError!MCValue {
3433 const mod = self.bin_file.options.module.?;3445 const mod = self.bin_file.options.module.?;
3434 switch (lhs_ty.zigTypeTag()) {3446 switch (lhs_ty.zigTypeTag(mod)) {
3435 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3447 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3436 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3448 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3437 .Int => {3449 .Int => {
3438 assert(lhs_ty.eql(rhs_ty, mod));3450 assert(lhs_ty.eql(rhs_ty, mod));
3439 const int_info = lhs_ty.intInfo(self.target.*);3451 const int_info = lhs_ty.intInfo(mod);
3440 if (int_info.bits <= 32) {3452 if (int_info.bits <= 32) {
3441 // TODO add optimisations for multiplication3453 // TODO add optimisations for multiplication
3442 // with immediates, for example a * 2 can be3454 // with immediates, for example a * 2 can be
...@@ -3463,7 +3475,8 @@ fn divFloat(...@@ -3463,7 +3475,8 @@ fn divFloat(
3463 _ = rhs_ty;3475 _ = rhs_ty;
3464 _ = maybe_inst;3476 _ = maybe_inst;
34653477
3466 switch (lhs_ty.zigTypeTag()) {3478 const mod = self.bin_file.options.module.?;
3479 switch (lhs_ty.zigTypeTag(mod)) {
3467 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3480 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3468 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3481 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3469 else => unreachable,3482 else => unreachable,
...@@ -3479,12 +3492,12 @@ fn divTrunc(...@@ -3479,12 +3492,12 @@ fn divTrunc(
3479 maybe_inst: ?Air.Inst.Index,3492 maybe_inst: ?Air.Inst.Index,
3480) InnerError!MCValue {3493) InnerError!MCValue {
3481 const mod = self.bin_file.options.module.?;3494 const mod = self.bin_file.options.module.?;
3482 switch (lhs_ty.zigTypeTag()) {3495 switch (lhs_ty.zigTypeTag(mod)) {
3483 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3496 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3484 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3497 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3485 .Int => {3498 .Int => {
3486 assert(lhs_ty.eql(rhs_ty, mod));3499 assert(lhs_ty.eql(rhs_ty, mod));
3487 const int_info = lhs_ty.intInfo(self.target.*);3500 const int_info = lhs_ty.intInfo(mod);
3488 if (int_info.bits <= 32) {3501 if (int_info.bits <= 32) {
3489 switch (int_info.signedness) {3502 switch (int_info.signedness) {
3490 .signed => {3503 .signed => {
...@@ -3522,12 +3535,12 @@ fn divFloor(...@@ -3522,12 +3535,12 @@ fn divFloor(
3522 maybe_inst: ?Air.Inst.Index,3535 maybe_inst: ?Air.Inst.Index,
3523) InnerError!MCValue {3536) InnerError!MCValue {
3524 const mod = self.bin_file.options.module.?;3537 const mod = self.bin_file.options.module.?;
3525 switch (lhs_ty.zigTypeTag()) {3538 switch (lhs_ty.zigTypeTag(mod)) {
3526 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3539 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3527 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3540 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3528 .Int => {3541 .Int => {
3529 assert(lhs_ty.eql(rhs_ty, mod));3542 assert(lhs_ty.eql(rhs_ty, mod));
3530 const int_info = lhs_ty.intInfo(self.target.*);3543 const int_info = lhs_ty.intInfo(mod);
3531 if (int_info.bits <= 32) {3544 if (int_info.bits <= 32) {
3532 switch (int_info.signedness) {3545 switch (int_info.signedness) {
3533 .signed => {3546 .signed => {
...@@ -3569,7 +3582,8 @@ fn divExact(...@@ -3569,7 +3582,8 @@ fn divExact(
3569 _ = rhs_ty;3582 _ = rhs_ty;
3570 _ = maybe_inst;3583 _ = maybe_inst;
35713584
3572 switch (lhs_ty.zigTypeTag()) {3585 const mod = self.bin_file.options.module.?;
3586 switch (lhs_ty.zigTypeTag(mod)) {
3573 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3587 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3574 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3588 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3575 .Int => return self.fail("TODO ARM div_exact", .{}),3589 .Int => return self.fail("TODO ARM div_exact", .{}),
...@@ -3586,12 +3600,12 @@ fn rem(...@@ -3586,12 +3600,12 @@ fn rem(
3586 maybe_inst: ?Air.Inst.Index,3600 maybe_inst: ?Air.Inst.Index,
3587) InnerError!MCValue {3601) InnerError!MCValue {
3588 const mod = self.bin_file.options.module.?;3602 const mod = self.bin_file.options.module.?;
3589 switch (lhs_ty.zigTypeTag()) {3603 switch (lhs_ty.zigTypeTag(mod)) {
3590 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3604 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3591 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3605 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3592 .Int => {3606 .Int => {
3593 assert(lhs_ty.eql(rhs_ty, mod));3607 assert(lhs_ty.eql(rhs_ty, mod));
3594 const int_info = lhs_ty.intInfo(self.target.*);3608 const int_info = lhs_ty.intInfo(mod);
3595 if (int_info.bits <= 32) {3609 if (int_info.bits <= 32) {
3596 switch (int_info.signedness) {3610 switch (int_info.signedness) {
3597 .signed => {3611 .signed => {
...@@ -3654,7 +3668,8 @@ fn modulo(...@@ -3654,7 +3668,8 @@ fn modulo(
3654 _ = rhs_ty;3668 _ = rhs_ty;
3655 _ = maybe_inst;3669 _ = maybe_inst;
36563670
3657 switch (lhs_ty.zigTypeTag()) {3671 const mod = self.bin_file.options.module.?;
3672 switch (lhs_ty.zigTypeTag(mod)) {
3658 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3673 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
3659 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3674 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3660 .Int => return self.fail("TODO ARM mod", .{}),3675 .Int => return self.fail("TODO ARM mod", .{}),
...@@ -3671,10 +3686,11 @@ fn wrappingArithmetic(...@@ -3671,10 +3686,11 @@ fn wrappingArithmetic(
3671 rhs_ty: Type,3686 rhs_ty: Type,
3672 maybe_inst: ?Air.Inst.Index,3687 maybe_inst: ?Air.Inst.Index,
3673) InnerError!MCValue {3688) InnerError!MCValue {
3674 switch (lhs_ty.zigTypeTag()) {3689 const mod = self.bin_file.options.module.?;
3690 switch (lhs_ty.zigTypeTag(mod)) {
3675 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3691 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3676 .Int => {3692 .Int => {
3677 const int_info = lhs_ty.intInfo(self.target.*);3693 const int_info = lhs_ty.intInfo(mod);
3678 if (int_info.bits <= 32) {3694 if (int_info.bits <= 32) {
3679 // Generate an add/sub/mul3695 // Generate an add/sub/mul
3680 const result: MCValue = switch (tag) {3696 const result: MCValue = switch (tag) {
...@@ -3708,12 +3724,12 @@ fn bitwise(...@@ -3708,12 +3724,12 @@ fn bitwise(
3708 rhs_ty: Type,3724 rhs_ty: Type,
3709 maybe_inst: ?Air.Inst.Index,3725 maybe_inst: ?Air.Inst.Index,
3710) InnerError!MCValue {3726) InnerError!MCValue {
3711 switch (lhs_ty.zigTypeTag()) {3727 const mod = self.bin_file.options.module.?;
3728 switch (lhs_ty.zigTypeTag(mod)) {
3712 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3729 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3713 .Int => {3730 .Int => {
3714 const mod = self.bin_file.options.module.?;
3715 assert(lhs_ty.eql(rhs_ty, mod));3731 assert(lhs_ty.eql(rhs_ty, mod));
3716 const int_info = lhs_ty.intInfo(self.target.*);3732 const int_info = lhs_ty.intInfo(mod);
3717 if (int_info.bits <= 32) {3733 if (int_info.bits <= 32) {
3718 const lhs_immediate = try lhs_bind.resolveToImmediate(self);3734 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
3719 const rhs_immediate = try rhs_bind.resolveToImmediate(self);3735 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
...@@ -3753,16 +3769,17 @@ fn shiftExact(...@@ -3753,16 +3769,17 @@ fn shiftExact(
3753 rhs_ty: Type,3769 rhs_ty: Type,
3754 maybe_inst: ?Air.Inst.Index,3770 maybe_inst: ?Air.Inst.Index,
3755) InnerError!MCValue {3771) InnerError!MCValue {
3756 switch (lhs_ty.zigTypeTag()) {3772 const mod = self.bin_file.options.module.?;
3773 switch (lhs_ty.zigTypeTag(mod)) {
3757 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3774 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3758 .Int => {3775 .Int => {
3759 const int_info = lhs_ty.intInfo(self.target.*);3776 const int_info = lhs_ty.intInfo(mod);
3760 if (int_info.bits <= 32) {3777 if (int_info.bits <= 32) {
3761 const rhs_immediate = try rhs_bind.resolveToImmediate(self);3778 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
37623779
3763 const mir_tag: Mir.Inst.Tag = switch (tag) {3780 const mir_tag: Mir.Inst.Tag = switch (tag) {
3764 .shl_exact => .lsl,3781 .shl_exact => .lsl,
3765 .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {3782 .shr_exact => switch (lhs_ty.intInfo(mod).signedness) {
3766 .signed => Mir.Inst.Tag.asr,3783 .signed => Mir.Inst.Tag.asr,
3767 .unsigned => Mir.Inst.Tag.lsr,3784 .unsigned => Mir.Inst.Tag.lsr,
3768 },3785 },
...@@ -3791,10 +3808,11 @@ fn shiftNormal(...@@ -3791,10 +3808,11 @@ fn shiftNormal(
3791 rhs_ty: Type,3808 rhs_ty: Type,
3792 maybe_inst: ?Air.Inst.Index,3809 maybe_inst: ?Air.Inst.Index,
3793) InnerError!MCValue {3810) InnerError!MCValue {
3794 switch (lhs_ty.zigTypeTag()) {3811 const mod = self.bin_file.options.module.?;
3812 switch (lhs_ty.zigTypeTag(mod)) {
3795 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),3813 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3796 .Int => {3814 .Int => {
3797 const int_info = lhs_ty.intInfo(self.target.*);3815 const int_info = lhs_ty.intInfo(mod);
3798 if (int_info.bits <= 32) {3816 if (int_info.bits <= 32) {
3799 // Generate a shl_exact/shr_exact3817 // Generate a shl_exact/shr_exact
3800 const result: MCValue = switch (tag) {3818 const result: MCValue = switch (tag) {
...@@ -3833,7 +3851,8 @@ fn booleanOp(...@@ -3833,7 +3851,8 @@ fn booleanOp(
3833 rhs_ty: Type,3851 rhs_ty: Type,
3834 maybe_inst: ?Air.Inst.Index,3852 maybe_inst: ?Air.Inst.Index,
3835) InnerError!MCValue {3853) InnerError!MCValue {
3836 switch (lhs_ty.zigTypeTag()) {3854 const mod = self.bin_file.options.module.?;
3855 switch (lhs_ty.zigTypeTag(mod)) {
3837 .Bool => {3856 .Bool => {
3838 const lhs_immediate = try lhs_bind.resolveToImmediate(self);3857 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
3839 const rhs_immediate = try rhs_bind.resolveToImmediate(self);3858 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
...@@ -3866,17 +3885,17 @@ fn ptrArithmetic(...@@ -3866,17 +3885,17 @@ fn ptrArithmetic(
3866 rhs_ty: Type,3885 rhs_ty: Type,
3867 maybe_inst: ?Air.Inst.Index,3886 maybe_inst: ?Air.Inst.Index,
3868) InnerError!MCValue {3887) InnerError!MCValue {
3869 switch (lhs_ty.zigTypeTag()) {3888 const mod = self.bin_file.options.module.?;
3889 switch (lhs_ty.zigTypeTag(mod)) {
3870 .Pointer => {3890 .Pointer => {
3871 const mod = self.bin_file.options.module.?;
3872 assert(rhs_ty.eql(Type.usize, mod));3891 assert(rhs_ty.eql(Type.usize, mod));
38733892
3874 const ptr_ty = lhs_ty;3893 const ptr_ty = lhs_ty;
3875 const elem_ty = switch (ptr_ty.ptrSize()) {3894 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
3876 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type3895 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
3877 else => ptr_ty.childType(),3896 else => ptr_ty.childType(mod),
3878 };3897 };
3879 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));3898 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
38803899
3881 const base_tag: Air.Inst.Tag = switch (tag) {3900 const base_tag: Air.Inst.Tag = switch (tag) {
3882 .ptr_add => .add,3901 .ptr_add => .add,
...@@ -3903,11 +3922,12 @@ fn ptrArithmetic(...@@ -3903,11 +3922,12 @@ fn ptrArithmetic(
3903}3922}
39043923
3905fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void {3924fn 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
3908 const tag: Mir.Inst.Tag = switch (abi_size) {3928 const tag: Mir.Inst.Tag = switch (abi_size) {
3909 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb,3929 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb else .ldrb,
3910 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh,3930 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh else .ldrh,
3911 3, 4 => .ldr,3931 3, 4 => .ldr,
3912 else => unreachable,3932 else => unreachable,
3913 };3933 };
...@@ -3924,7 +3944,7 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type)...@@ -3924,7 +3944,7 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type)
3924 } };3944 } };
39253945
3926 const data: Mir.Inst.Data = switch (abi_size) {3946 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,
3928 2 => rr_extra_offset,3948 2 => rr_extra_offset,
3929 3, 4 => rr_offset,3949 3, 4 => rr_offset,
3930 else => unreachable,3950 else => unreachable,
...@@ -3937,7 +3957,8 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type)...@@ -3937,7 +3957,8 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type)
3937}3957}
39383958
3939fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Type) !void {3959fn 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
3942 const tag: Mir.Inst.Tag = switch (abi_size) {3963 const tag: Mir.Inst.Tag = switch (abi_size) {
3943 1 => .strb,3964 1 => .strb,
...@@ -4051,14 +4072,14 @@ fn genInlineMemset(...@@ -4051,14 +4072,14 @@ fn genInlineMemset(
4051) !void {4072) !void {
4052 const dst_reg = switch (dst) {4073 const dst_reg = switch (dst) {
4053 .register => |r| r,4074 .register => |r| r,
4054 else => try self.copyToTmpRegister(Type.initTag(.manyptr_u8), dst),4075 else => try self.copyToTmpRegister(Type.manyptr_u8, dst),
4055 };4076 };
4056 const dst_reg_lock = self.register_manager.lockReg(dst_reg);4077 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
4057 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);4078 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
40584079
4059 const val_reg = switch (val) {4080 const val_reg = switch (val) {
4060 .register => |r| r,4081 .register => |r| r,
4061 else => try self.copyToTmpRegister(Type.initTag(.u8), val),4082 else => try self.copyToTmpRegister(Type.u8, val),
4062 };4083 };
4063 const val_reg_lock = self.register_manager.lockReg(val_reg);4084 const val_reg_lock = self.register_manager.lockReg(val_reg);
4064 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);4085 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -4143,7 +4164,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4143,7 +4164,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4143 while (self.args[arg_index] == .none) arg_index += 1;4164 while (self.args[arg_index] == .none) arg_index += 1;
4144 self.arg_index = arg_index + 1;4165 self.arg_index = arg_index + 1;
41454166
4146 const ty = self.air.typeOfIndex(inst);4167 const ty = self.typeOfIndex(inst);
4147 const tag = self.air.instructions.items(.tag)[inst];4168 const tag = self.air.instructions.items(.tag)[inst];
4148 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;4169 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4149 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);4170 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...@@ -4196,11 +4217,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4196 const callee = pl_op.operand;4217 const callee = pl_op.operand;
4197 const extra = self.air.extraData(Air.Call, pl_op.payload);4218 const extra = self.air.extraData(Air.Call, pl_op.payload);
4198 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);4219 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)) {
4202 .Fn => ty,4224 .Fn => ty,
4203 .Pointer => ty.childType(),4225 .Pointer => ty.childType(mod),
4204 else => unreachable,4226 else => unreachable,
4205 };4227 };
42064228
...@@ -4225,16 +4247,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4225,16 +4247,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4225 // untouched by the parameter passing code4247 // untouched by the parameter passing code
4226 const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {4248 const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {
4227 log.debug("airCall: return by reference", .{});4249 log.debug("airCall: return by reference", .{});
4228 const ret_ty = fn_ty.fnReturnType();4250 const ret_ty = fn_ty.fnReturnType(mod);
4229 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));4251 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
4230 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));4252 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
4231 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);4253 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
42324254
4233 var ptr_ty_payload: Type.Payload.ElemType = .{4255 const ptr_ty = try mod.singleMutPtrType(ret_ty);
4234 .base = .{ .tag = .single_mut_pointer },
4235 .data = ret_ty,
4236 };
4237 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4238 try self.register_manager.getReg(.r0, null);4256 try self.register_manager.getReg(.r0, null);
4239 try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset });4257 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...@@ -4249,7 +4267,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42494267
4250 for (info.args, 0..) |mc_arg, arg_i| {4268 for (info.args, 0..) |mc_arg, arg_i| {
4251 const arg = args[arg_i];4269 const arg = args[arg_i];
4252 const arg_ty = self.air.typeOf(arg);4270 const arg_ty = self.typeOf(arg);
4253 const arg_mcv = try self.resolveInst(args[arg_i]);4271 const arg_mcv = try self.resolveInst(args[arg_i]);
42544272
4255 switch (mc_arg) {4273 switch (mc_arg) {
...@@ -4270,16 +4288,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4270,16 +4288,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42704288
4271 // Due to incremental compilation, how function calls are generated depends4289 // Due to incremental compilation, how function calls are generated depends
4272 // on linking.4290 // on linking.
4273 if (self.air.value(callee)) |func_value| {4291 if (try self.air.value(callee, mod)) |func_value| {
4274 if (func_value.castTag(.function)) |func_payload| {4292 if (func_value.getFunction(mod)) |func| {
4275 const func = func_payload.data;
4276
4277 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4293 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4278 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);4294 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
4279 const atom = elf_file.getAtom(atom_index);4295 const atom = elf_file.getAtom(atom_index);
4280 _ = try atom.getOrCreateOffsetTableEntry(elf_file);4296 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
4281 const got_addr = @intCast(u32, atom.getOffsetTableAddress(elf_file));4297 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 });
4283 } else if (self.bin_file.cast(link.File.MachO)) |_| {4299 } else if (self.bin_file.cast(link.File.MachO)) |_| {
4284 unreachable; // unsupported architecture for MachO4300 unreachable; // unsupported architecture for MachO
4285 } else {4301 } else {
...@@ -4288,16 +4304,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4288,16 +4304,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4288 @tagName(self.target.cpu.arch),4304 @tagName(self.target.cpu.arch),
4289 });4305 });
4290 }4306 }
4291 } else if (func_value.castTag(.extern_fn)) |_| {4307 } else if (func_value.getExternFunc(mod)) |_| {
4292 return self.fail("TODO implement calling extern functions", .{});4308 return self.fail("TODO implement calling extern functions", .{});
4293 } else {4309 } else {
4294 return self.fail("TODO implement calling bitcasted functions", .{});4310 return self.fail("TODO implement calling bitcasted functions", .{});
4295 }4311 }
4296 } else {4312 } else {
4297 assert(ty.zigTypeTag() == .Pointer);4313 assert(ty.zigTypeTag(mod) == .Pointer);
4298 const mcv = try self.resolveInst(callee);4314 const mcv = try self.resolveInst(callee);
42994315
4300 try self.genSetReg(Type.initTag(.usize), .lr, mcv);4316 try self.genSetReg(Type.usize, .lr, mcv);
4301 }4317 }
43024318
4303 // TODO: add Instruction.supportedOn4319 // TODO: add Instruction.supportedOn
...@@ -4329,7 +4345,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4329,7 +4345,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4329 if (RegisterManager.indexOfRegIntoTracked(reg) == null) {4345 if (RegisterManager.indexOfRegIntoTracked(reg) == null) {
4330 // Save function return value into a tracked register4346 // Save function return value into a tracked register
4331 log.debug("airCall: copying {} as it is not tracked", .{reg});4347 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);
4333 break :result MCValue{ .register = new_reg };4349 break :result MCValue{ .register = new_reg };
4334 }4350 }
4335 },4351 },
...@@ -4353,14 +4369,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4353,14 +4369,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4353}4369}
43544370
4355fn airRet(self: *Self, inst: Air.Inst.Index) !void {4371fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4372 const mod = self.bin_file.options.module.?;
4356 const un_op = self.air.instructions.items(.data)[inst].un_op;4373 const un_op = self.air.instructions.items(.data)[inst].un_op;
4357 const operand = try self.resolveInst(un_op);4374 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
4360 switch (self.ret_mcv) {4377 switch (self.ret_mcv) {
4361 .none => {},4378 .none => {},
4362 .immediate => {4379 .immediate => {
4363 assert(ret_ty.isError());4380 assert(ret_ty.isError(mod));
4364 },4381 },
4365 .register => |reg| {4382 .register => |reg| {
4366 // Return result by value4383 // Return result by value
...@@ -4371,11 +4388,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4371,11 +4388,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4371 //4388 //
4372 // self.ret_mcv is an address to where this function4389 // self.ret_mcv is an address to where this function
4373 // should store its result into4390 // should store its result into
4374 var ptr_ty_payload: Type.Payload.ElemType = .{4391 const ptr_ty = try mod.singleMutPtrType(ret_ty);
4375 .base = .{ .tag = .single_mut_pointer },
4376 .data = ret_ty,
4377 };
4378 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4379 try self.store(self.ret_mcv, operand, ptr_ty, ret_ty);4392 try self.store(self.ret_mcv, operand, ptr_ty, ret_ty);
4380 },4393 },
4381 else => unreachable, // invalid return result4394 else => unreachable, // invalid return result
...@@ -4388,10 +4401,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4388,10 +4401,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4388}4401}
43894402
4390fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {4403fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4404 const mod = self.bin_file.options.module.?;
4391 const un_op = self.air.instructions.items(.data)[inst].un_op;4405 const un_op = self.air.instructions.items(.data)[inst].un_op;
4392 const ptr = try self.resolveInst(un_op);4406 const ptr = try self.resolveInst(un_op);
4393 const ptr_ty = self.air.typeOf(un_op);4407 const ptr_ty = self.typeOf(un_op);
4394 const ret_ty = self.fn_type.fnReturnType();4408 const ret_ty = self.fn_type.fnReturnType(mod);
43954409
4396 switch (self.ret_mcv) {4410 switch (self.ret_mcv) {
4397 .none => {},4411 .none => {},
...@@ -4411,8 +4425,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4411,8 +4425,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4411 // location.4425 // location.
4412 const op_inst = Air.refToIndex(un_op).?;4426 const op_inst = Air.refToIndex(un_op).?;
4413 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {4427 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4414 const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));4428 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
4415 const abi_align = ret_ty.abiAlignment(self.target.*);4429 const abi_align = ret_ty.abiAlignment(mod);
44164430
4417 const offset = try self.allocMem(abi_size, abi_align, null);4431 const offset = try self.allocMem(abi_size, abi_align, null);
44184432
...@@ -4432,7 +4446,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4432,7 +4446,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44324446
4433fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {4447fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
4434 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4448 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
4437 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {4451 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
4438 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);4452 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);
...@@ -4448,29 +4462,28 @@ fn cmp(...@@ -4448,29 +4462,28 @@ fn cmp(
4448 lhs_ty: Type,4462 lhs_ty: Type,
4449 op: math.CompareOperator,4463 op: math.CompareOperator,
4450) !MCValue {4464) !MCValue {
4451 var int_buffer: Type.Payload.Bits = undefined;4465 const mod = self.bin_file.options.module.?;
4452 const int_ty = switch (lhs_ty.zigTypeTag()) {4466 const int_ty = switch (lhs_ty.zigTypeTag(mod)) {
4453 .Optional => blk: {4467 .Optional => blk: {
4454 var opt_buffer: Type.Payload.ElemType = undefined;4468 const payload_ty = lhs_ty.optionalChild(mod);
4455 const payload_ty = lhs_ty.optionalChild(&opt_buffer);4469 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4456 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4470 break :blk Type.u1;
4457 break :blk Type.initTag(.u1);4471 } else if (lhs_ty.isPtrLikeOptional(mod)) {
4458 } else if (lhs_ty.isPtrLikeOptional()) {
4459 break :blk Type.usize;4472 break :blk Type.usize;
4460 } else {4473 } else {
4461 return self.fail("TODO ARM cmp non-pointer optionals", .{});4474 return self.fail("TODO ARM cmp non-pointer optionals", .{});
4462 }4475 }
4463 },4476 },
4464 .Float => return self.fail("TODO ARM cmp floats", .{}),4477 .Float => return self.fail("TODO ARM cmp floats", .{}),
4465 .Enum => lhs_ty.intTagType(&int_buffer),4478 .Enum => lhs_ty.intTagType(mod),
4466 .Int => lhs_ty,4479 .Int => lhs_ty,
4467 .Bool => Type.initTag(.u1),4480 .Bool => Type.u1,
4468 .Pointer => Type.usize,4481 .Pointer => Type.usize,
4469 .ErrorSet => Type.initTag(.u16),4482 .ErrorSet => Type.u16,
4470 else => unreachable,4483 else => unreachable,
4471 };4484 };
44724485
4473 const int_info = int_ty.intInfo(self.target.*);4486 const int_info = int_ty.intInfo(mod);
4474 if (int_info.bits <= 32) {4487 if (int_info.bits <= 32) {
4475 try self.spillCompareFlagsIfOccupied();4488 try self.spillCompareFlagsIfOccupied();
44764489
...@@ -4555,8 +4568,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4555,8 +4568,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
4555}4568}
45564569
4557fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4570fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4558 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4571 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4559 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;4572 const mod = self.bin_file.options.module.?;
4573 const function = mod.funcPtr(ty_fn.func);
4560 // TODO emit debug info for function change4574 // TODO emit debug info for function change
4561 _ = function;4575 _ = function;
4562 return self.finishAir(inst, .dead, .{ .none, .none, .none });4576 return self.finishAir(inst, .dead, .{ .none, .none, .none });
...@@ -4571,7 +4585,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -4571,7 +4585,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4571 const pl_op = self.air.instructions.items(.data)[inst].pl_op;4585 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
4572 const operand = pl_op.operand;4586 const operand = pl_op.operand;
4573 const tag = self.air.instructions.items(.tag)[inst];4587 const tag = self.air.instructions.items(.tag)[inst];
4574 const ty = self.air.typeOf(operand);4588 const ty = self.typeOf(operand);
4575 const mcv = try self.resolveInst(operand);4589 const mcv = try self.resolveInst(operand);
4576 const name = self.air.nullTerminatedString(pl_op.payload);4590 const name = self.air.nullTerminatedString(pl_op.payload);
45774591
...@@ -4636,8 +4650,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4636,8 +4650,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4636 // whether it needs to be spilled in the branches4650 // whether it needs to be spilled in the branches
4637 if (self.liveness.operandDies(inst, 0)) {4651 if (self.liveness.operandDies(inst, 0)) {
4638 const op_int = @enumToInt(pl_op.operand);4652 const op_int = @enumToInt(pl_op.operand);
4639 if (op_int >= Air.Inst.Ref.typed_value_map.len) {4653 if (op_int >= Air.ref_start_index) {
4640 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);4654 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
4641 self.processDeath(op_index);4655 self.processDeath(op_index);
4642 }4656 }
4643 }4657 }
...@@ -4726,7 +4740,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4726,7 +4740,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4726 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });4740 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });
4727 // TODO make sure the destination stack offset / register does not already have something4741 // TODO make sure the destination stack offset / register does not already have something
4728 // going on there.4742 // 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);
4730 // TODO track the new register / stack allocation4744 // TODO track the new register / stack allocation
4731 }4745 }
4732 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count());4746 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 {...@@ -4753,7 +4767,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4753 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });4767 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });
4754 // TODO make sure the destination stack offset / register does not already have something4768 // TODO make sure the destination stack offset / register does not already have something
4755 // going on there.4769 // 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);
4757 // TODO track the new register / stack allocation4771 // TODO track the new register / stack allocation
4758 }4772 }
47594773
...@@ -4772,8 +4786,9 @@ fn isNull(...@@ -4772,8 +4786,9 @@ fn isNull(
4772 operand_bind: ReadArg.Bind,4786 operand_bind: ReadArg.Bind,
4773 operand_ty: Type,4787 operand_ty: Type,
4774) !MCValue {4788) !MCValue {
4775 if (operand_ty.isPtrLikeOptional()) {4789 const mod = self.bin_file.options.module.?;
4776 assert(operand_ty.abiSize(self.target.*) == 4);4790 if (operand_ty.isPtrLikeOptional(mod)) {
4791 assert(operand_ty.abiSize(mod) == 4);
47774792
4778 const imm_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 0 } };4793 const imm_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 0 } };
4779 return self.cmp(operand_bind, imm_bind, Type.usize, .eq);4794 return self.cmp(operand_bind, imm_bind, Type.usize, .eq);
...@@ -4797,7 +4812,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4797,7 +4812,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
4797 const un_op = self.air.instructions.items(.data)[inst].un_op;4812 const un_op = self.air.instructions.items(.data)[inst].un_op;
4798 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4813 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4799 const operand_bind: ReadArg.Bind = .{ .inst = un_op };4814 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
4802 break :result try self.isNull(operand_bind, operand_ty);4817 break :result try self.isNull(operand_bind, operand_ty);
4803 };4818 };
...@@ -4805,11 +4820,12 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4805,11 +4820,12 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
4805}4820}
48064821
4807fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {4822fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4823 const mod = self.bin_file.options.module.?;
4808 const un_op = self.air.instructions.items(.data)[inst].un_op;4824 const un_op = self.air.instructions.items(.data)[inst].un_op;
4809 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4825 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4810 const operand_ptr = try self.resolveInst(un_op);4826 const operand_ptr = try self.resolveInst(un_op);
4811 const ptr_ty = self.air.typeOf(un_op);4827 const ptr_ty = self.typeOf(un_op);
4812 const elem_ty = ptr_ty.elemType();4828 const elem_ty = ptr_ty.childType(mod);
48134829
4814 const operand = try self.allocRegOrMem(elem_ty, true, null);4830 const operand = try self.allocRegOrMem(elem_ty, true, null);
4815 try self.load(operand, operand_ptr, ptr_ty);4831 try self.load(operand, operand_ptr, ptr_ty);
...@@ -4823,7 +4839,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4823,7 +4839,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
4823 const un_op = self.air.instructions.items(.data)[inst].un_op;4839 const un_op = self.air.instructions.items(.data)[inst].un_op;
4824 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4840 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4825 const operand_bind: ReadArg.Bind = .{ .inst = un_op };4841 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
4828 break :result try self.isNonNull(operand_bind, operand_ty);4844 break :result try self.isNonNull(operand_bind, operand_ty);
4829 };4845 };
...@@ -4831,11 +4847,12 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -4831,11 +4847,12 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
4831}4847}
48324848
4833fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {4849fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4850 const mod = self.bin_file.options.module.?;
4834 const un_op = self.air.instructions.items(.data)[inst].un_op;4851 const un_op = self.air.instructions.items(.data)[inst].un_op;
4835 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4852 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4836 const operand_ptr = try self.resolveInst(un_op);4853 const operand_ptr = try self.resolveInst(un_op);
4837 const ptr_ty = self.air.typeOf(un_op);4854 const ptr_ty = self.typeOf(un_op);
4838 const elem_ty = ptr_ty.elemType();4855 const elem_ty = ptr_ty.childType(mod);
48394856
4840 const operand = try self.allocRegOrMem(elem_ty, true, null);4857 const operand = try self.allocRegOrMem(elem_ty, true, null);
4841 try self.load(operand, operand_ptr, ptr_ty);4858 try self.load(operand, operand_ptr, ptr_ty);
...@@ -4850,9 +4867,10 @@ fn isErr(...@@ -4850,9 +4867,10 @@ fn isErr(
4850 error_union_bind: ReadArg.Bind,4867 error_union_bind: ReadArg.Bind,
4851 error_union_ty: Type,4868 error_union_ty: Type,
4852) !MCValue {4869) !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)) {
4856 return MCValue{ .immediate = 0 }; // always false4874 return MCValue{ .immediate = 0 }; // always false
4857 }4875 }
48584876
...@@ -4883,7 +4901,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4883,7 +4901,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
4883 const un_op = self.air.instructions.items(.data)[inst].un_op;4901 const un_op = self.air.instructions.items(.data)[inst].un_op;
4884 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4902 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4885 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };4903 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
4888 break :result try self.isErr(error_union_bind, error_union_ty);4906 break :result try self.isErr(error_union_bind, error_union_ty);
4889 };4907 };
...@@ -4891,11 +4909,12 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4891,11 +4909,12 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
4891}4909}
48924910
4893fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {4911fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4912 const mod = self.bin_file.options.module.?;
4894 const un_op = self.air.instructions.items(.data)[inst].un_op;4913 const un_op = self.air.instructions.items(.data)[inst].un_op;
4895 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4914 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4896 const operand_ptr = try self.resolveInst(un_op);4915 const operand_ptr = try self.resolveInst(un_op);
4897 const ptr_ty = self.air.typeOf(un_op);4916 const ptr_ty = self.typeOf(un_op);
4898 const elem_ty = ptr_ty.elemType();4917 const elem_ty = ptr_ty.childType(mod);
48994918
4900 const operand = try self.allocRegOrMem(elem_ty, true, null);4919 const operand = try self.allocRegOrMem(elem_ty, true, null);
4901 try self.load(operand, operand_ptr, ptr_ty);4920 try self.load(operand, operand_ptr, ptr_ty);
...@@ -4909,7 +4928,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4909,7 +4928,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
4909 const un_op = self.air.instructions.items(.data)[inst].un_op;4928 const un_op = self.air.instructions.items(.data)[inst].un_op;
4910 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4929 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4911 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };4930 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
4914 break :result try self.isNonErr(error_union_bind, error_union_ty);4933 break :result try self.isNonErr(error_union_bind, error_union_ty);
4915 };4934 };
...@@ -4917,11 +4936,12 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4917,11 +4936,12 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
4917}4936}
49184937
4919fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {4938fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4939 const mod = self.bin_file.options.module.?;
4920 const un_op = self.air.instructions.items(.data)[inst].un_op;4940 const un_op = self.air.instructions.items(.data)[inst].un_op;
4921 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4941 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4922 const operand_ptr = try self.resolveInst(un_op);4942 const operand_ptr = try self.resolveInst(un_op);
4923 const ptr_ty = self.air.typeOf(un_op);4943 const ptr_ty = self.typeOf(un_op);
4924 const elem_ty = ptr_ty.elemType();4944 const elem_ty = ptr_ty.childType(mod);
49254945
4926 const operand = try self.allocRegOrMem(elem_ty, true, null);4946 const operand = try self.allocRegOrMem(elem_ty, true, null);
4927 try self.load(operand, operand_ptr, ptr_ty);4947 try self.load(operand, operand_ptr, ptr_ty);
...@@ -4988,7 +5008,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -4988,7 +5008,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
49885008
4989fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {5009fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
4990 const pl_op = self.air.instructions.items(.data)[inst].pl_op;5010 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);
4992 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);5012 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
4993 const liveness = try self.liveness.getSwitchBr(5013 const liveness = try self.liveness.getSwitchBr(
4994 self.gpa,5014 self.gpa,
...@@ -5131,9 +5151,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -5131,9 +5151,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
5131}5151}
51325152
5133fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {5153fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
5154 const mod = self.bin_file.options.module.?;
5134 const block_data = self.blocks.getPtr(block).?;5155 const block_data = self.blocks.getPtr(block).?;
51355156
5136 if (self.air.typeOf(operand).hasRuntimeBits()) {5157 if (self.typeOf(operand).hasRuntimeBits(mod)) {
5137 const operand_mcv = try self.resolveInst(operand);5158 const operand_mcv = try self.resolveInst(operand);
5138 const block_mcv = block_data.mcv;5159 const block_mcv = block_data.mcv;
5139 if (block_mcv == .none) {5160 if (block_mcv == .none) {
...@@ -5141,14 +5162,14 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -5141,14 +5162,14 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
5141 .none, .dead, .unreach => unreachable,5162 .none, .dead, .unreach => unreachable,
5142 .register, .stack_offset, .memory => operand_mcv,5163 .register, .stack_offset, .memory => operand_mcv,
5143 .immediate, .stack_argument_offset, .cpsr_flags => blk: {5164 .immediate, .stack_argument_offset, .cpsr_flags => blk: {
5144 const new_mcv = try self.allocRegOrMem(self.air.typeOfIndex(block), true, block);5165 const new_mcv = try self.allocRegOrMem(self.typeOfIndex(block), true, block);
5145 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);5166 try self.setRegOrMem(self.typeOfIndex(block), new_mcv, operand_mcv);
5146 break :blk new_mcv;5167 break :blk new_mcv;
5147 },5168 },
5148 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),5169 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
5149 };5170 };
5150 } else {5171 } else {
5151 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);5172 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
5152 }5173 }
5153 }5174 }
5154 return self.brVoid(block);5175 return self.brVoid(block);
...@@ -5212,7 +5233,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -5212,7 +5233,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
52125233
5213 const arg_mcv = try self.resolveInst(input);5234 const arg_mcv = try self.resolveInst(input);
5214 try self.register_manager.getReg(reg, null);5235 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);
5216 }5237 }
52175238
5218 {5239 {
...@@ -5301,7 +5322,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {...@@ -5301,7 +5322,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
5301}5322}
53025323
5303fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {5324fn 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));
5305 switch (mcv) {5327 switch (mcv) {
5306 .dead => unreachable,5328 .dead => unreachable,
5307 .unreach, .none => return, // Nothing to do.5329 .unreach, .none => return, // Nothing to do.
...@@ -5332,7 +5354,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5332,7 +5354,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5332 1, 4 => {5354 1, 4 => {
5333 const offset = if (math.cast(u12, stack_offset)) |imm| blk: {5355 const offset = if (math.cast(u12, stack_offset)) |imm| blk: {
5334 break :blk Instruction.Offset.imm(imm);5356 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
5337 const tag: Mir.Inst.Tag = switch (abi_size) {5359 const tag: Mir.Inst.Tag = switch (abi_size) {
5338 1 => .strb,5360 1 => .strb,
...@@ -5355,7 +5377,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5355,7 +5377,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5355 2 => {5377 2 => {
5356 const offset = if (stack_offset <= math.maxInt(u8)) blk: {5378 const offset = if (stack_offset <= math.maxInt(u8)) blk: {
5357 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, stack_offset));5379 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
5360 _ = try self.addInst(.{5382 _ = try self.addInst(.{
5361 .tag = .strh,5383 .tag = .strh,
...@@ -5378,11 +5400,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5378,11 +5400,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5378 const reg_lock = self.register_manager.lockReg(reg);5400 const reg_lock = self.register_manager.lockReg(reg);
5379 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);5401 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);
5382 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });5404 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });
53835405
5384 const overflow_bit_ty = ty.structFieldType(1);5406 const overflow_bit_ty = ty.structFieldType(1, mod);
5385 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));5407 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
5386 const cond_reg = try self.register_manager.allocReg(null, gp);5408 const cond_reg = try self.register_manager.allocReg(null, gp);
53875409
5388 // C flag: movcs reg, #15410 // C flag: movcs reg, #1
...@@ -5420,11 +5442,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5420,11 +5442,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5420 const reg = try self.copyToTmpRegister(ty, mcv);5442 const reg = try self.copyToTmpRegister(ty, mcv);
5421 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });5443 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
5422 } else {5444 } else {
5423 var ptr_ty_payload: Type.Payload.ElemType = .{5445 const ptr_ty = try mod.singleMutPtrType(ty);
5424 .base = .{ .tag = .single_mut_pointer },
5425 .data = ty,
5426 };
5427 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
54285446
5429 // TODO call extern memcpy5447 // TODO call extern memcpy
5430 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);5448 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...@@ -5466,6 +5484,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5466}5484}
54675485
5468fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {5486fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
5487 const mod = self.bin_file.options.module.?;
5469 switch (mcv) {5488 switch (mcv) {
5470 .dead => unreachable,5489 .dead => unreachable,
5471 .unreach, .none => return, // Nothing to do.5490 .unreach, .none => return, // Nothing to do.
...@@ -5640,17 +5659,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5640,17 +5659,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5640 },5659 },
5641 .stack_offset => |off| {5660 .stack_offset => |off| {
5642 // TODO: maybe addressing from sp instead of fp5661 // 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
5645 const tag: Mir.Inst.Tag = switch (abi_size) {5664 const tag: Mir.Inst.Tag = switch (abi_size) {
5646 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb,5665 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb else .ldrb,
5647 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh,5666 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh else .ldrh,
5648 3, 4 => .ldr,5667 3, 4 => .ldr,
5649 else => unreachable,5668 else => unreachable,
5650 };5669 };
56515670
5652 const extra_offset = switch (abi_size) {5671 const extra_offset = switch (abi_size) {
5653 1 => ty.isSignedInt(),5672 1 => ty.isSignedInt(mod),
5654 2 => true,5673 2 => true,
5655 3, 4 => false,5674 3, 4 => false,
5656 else => unreachable,5675 else => unreachable,
...@@ -5659,7 +5678,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5659,7 +5678,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5659 if (extra_offset) {5678 if (extra_offset) {
5660 const offset = if (off <= math.maxInt(u8)) blk: {5679 const offset = if (off <= math.maxInt(u8)) blk: {
5661 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, off));5680 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
5664 _ = try self.addInst(.{5683 _ = try self.addInst(.{
5665 .tag = tag,5684 .tag = tag,
...@@ -5675,7 +5694,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5675,7 +5694,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5675 } else {5694 } else {
5676 const offset = if (off <= math.maxInt(u12)) blk: {5695 const offset = if (off <= math.maxInt(u12)) blk: {
5677 break :blk Instruction.Offset.imm(@intCast(u12, off));5696 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
5680 _ = try self.addInst(.{5699 _ = try self.addInst(.{
5681 .tag = tag,5700 .tag = tag,
...@@ -5691,11 +5710,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5691,11 +5710,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5691 }5710 }
5692 },5711 },
5693 .stack_argument_offset => |off| {5712 .stack_argument_offset => |off| {
5694 const abi_size = ty.abiSize(self.target.*);5713 const abi_size = ty.abiSize(mod);
56955714
5696 const tag: Mir.Inst.Tag = switch (abi_size) {5715 const tag: Mir.Inst.Tag = switch (abi_size) {
5697 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,5716 1 => if (ty.isSignedInt(mod)) 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,5717 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
5699 3, 4 => .ldr_stack_argument,5718 3, 4 => .ldr_stack_argument,
5700 else => unreachable,5719 else => unreachable,
5701 };5720 };
...@@ -5712,7 +5731,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5712,7 +5731,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5712}5731}
57135732
5714fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {5733fn 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));
5716 switch (mcv) {5736 switch (mcv) {
5717 .dead => unreachable,5737 .dead => unreachable,
5718 .none, .unreach => return,5738 .none, .unreach => return,
...@@ -5732,7 +5752,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5732,7 +5752,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5732 1, 4 => {5752 1, 4 => {
5733 const offset = if (math.cast(u12, stack_offset)) |imm| blk: {5753 const offset = if (math.cast(u12, stack_offset)) |imm| blk: {
5734 break :blk Instruction.Offset.imm(imm);5754 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
5737 const tag: Mir.Inst.Tag = switch (abi_size) {5757 const tag: Mir.Inst.Tag = switch (abi_size) {
5738 1 => .strb,5758 1 => .strb,
...@@ -5752,7 +5772,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5752,7 +5772,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5752 2 => {5772 2 => {
5753 const offset = if (stack_offset <= math.maxInt(u8)) blk: {5773 const offset = if (stack_offset <= math.maxInt(u8)) blk: {
5754 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, stack_offset));5774 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
5757 _ = try self.addInst(.{5777 _ = try self.addInst(.{
5758 .tag = .strh,5778 .tag = .strh,
...@@ -5779,11 +5799,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5779,11 +5799,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5779 const reg = try self.copyToTmpRegister(ty, mcv);5799 const reg = try self.copyToTmpRegister(ty, mcv);
5780 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });5800 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
5781 } else {5801 } else {
5782 var ptr_ty_payload: Type.Payload.ElemType = .{5802 const ptr_ty = try mod.singleMutPtrType(ty);
5783 .base = .{ .tag = .single_mut_pointer },
5784 .data = ty,
5785 };
5786 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
57875803
5788 // TODO call extern memcpy5804 // TODO call extern memcpy
5789 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);5805 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 {...@@ -5862,7 +5878,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
5862 };5878 };
5863 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);5879 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);
5866 const dest = try self.allocRegOrMem(dest_ty, true, inst);5882 const dest = try self.allocRegOrMem(dest_ty, true, inst);
5867 try self.setRegOrMem(dest_ty, dest, operand);5883 try self.setRegOrMem(dest_ty, dest, operand);
5868 break :result dest;5884 break :result dest;
...@@ -5871,16 +5887,17 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -5871,16 +5887,17 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
5871}5887}
58725888
5873fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {5889fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
5890 const mod = self.bin_file.options.module.?;
5874 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5891 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5875 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {5892 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);
5877 const ptr = try self.resolveInst(ty_op.operand);5894 const ptr = try self.resolveInst(ty_op.operand);
5878 const array_ty = ptr_ty.childType();5895 const array_ty = ptr_ty.childType(mod);
5879 const array_len = @intCast(u32, array_ty.arrayLen());5896 const array_len = @intCast(u32, array_ty.arrayLen(mod));
58805897
5881 const stack_offset = try self.allocMem(8, 8, inst);5898 const stack_offset = try self.allocMem(8, 8, inst);
5882 try self.genSetStack(ptr_ty, stack_offset, ptr);5899 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 });
5884 break :result MCValue{ .stack_offset = stack_offset };5901 break :result MCValue{ .stack_offset = stack_offset };
5885 };5902 };
5886 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5903 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -5989,8 +6006,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {...@@ -5989,8 +6006,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
5989}6006}
59906007
5991fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {6008fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
5992 const vector_ty = self.air.typeOfIndex(inst);6009 const mod = self.bin_file.options.module.?;
5993 const len = vector_ty.vectorLen();6010 const vector_ty = self.typeOfIndex(inst);
6011 const len = vector_ty.vectorLen(mod);
5994 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6012 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5995 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);6013 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
5996 const result: MCValue = res: {6014 const result: MCValue = res: {
...@@ -6038,9 +6056,10 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {...@@ -6038,9 +6056,10 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
6038 const body = self.air.extra[extra.end..][0..extra.data.body_len];6056 const body = self.air.extra[extra.end..][0..extra.data.body_len];
6039 const result: MCValue = result: {6057 const result: MCValue = result: {
6040 const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand };6058 const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand };
6041 const error_union_ty = self.air.typeOf(pl_op.operand);6059 const error_union_ty = self.typeOf(pl_op.operand);
6042 const error_union_size = @intCast(u32, error_union_ty.abiSize(self.target.*));6060 const mod = self.bin_file.options.module.?;
6043 const error_union_align = error_union_ty.abiAlignment(self.target.*);6061 const error_union_size = @intCast(u32, error_union_ty.abiSize(mod));
6062 const error_union_align = error_union_ty.abiAlignment(mod);
60446063
6045 // The error union will die in the body. However, we need the6064 // The error union will die in the body. However, we need the
6046 // error union after the body in order to extract the payload6065 // error union after the body in order to extract the payload
...@@ -6069,37 +6088,32 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -6069,37 +6088,32 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
6069}6088}
60706089
6071fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {6090fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6072 // First section of indexes correspond to a set number of constant values.6091 const mod = self.bin_file.options.module.?;
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 }
60816092
6082 // If the type has no codegen bits, no need to store it.6093 // If the type has no codegen bits, no need to store it.
6083 const inst_ty = self.air.typeOf(inst);6094 const inst_ty = self.typeOf(inst);
6084 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())6095 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))
6085 return MCValue{ .none = {} };6096 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
6088 switch (self.air.instructions.items(.tag)[inst_index]) {6103 switch (self.air.instructions.items(.tag)[inst_index]) {
6089 .constant => {6104 .interned => {
6090 // Constants have static lifetimes, so they are always memoized in the outer most table.6105 // Constants have static lifetimes, so they are always memoized in the outer most table.
6091 const branch = &self.branch_stack.items[0];6106 const branch = &self.branch_stack.items[0];
6092 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);6107 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
6093 if (!gop.found_existing) {6108 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;
6095 gop.value_ptr.* = try self.genTypedValue(.{6110 gop.value_ptr.* = try self.genTypedValue(.{
6096 .ty = inst_ty,6111 .ty = inst_ty,
6097 .val = self.air.values[ty_pl.payload],6112 .val = interned.toValue(),
6098 });6113 });
6099 }6114 }
6100 return gop.value_ptr.*;6115 return gop.value_ptr.*;
6101 },6116 },
6102 .const_ty => unreachable,
6103 else => return self.getResolvedInstValue(inst_index),6117 else => return self.getResolvedInstValue(inst_index),
6104 }6118 }
6105}6119}
...@@ -6152,12 +6166,11 @@ const CallMCValues = struct {...@@ -6152,12 +6166,11 @@ const CallMCValues = struct {
61526166
6153/// Caller must call `CallMCValues.deinit`.6167/// Caller must call `CallMCValues.deinit`.
6154fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6168fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6155 const cc = fn_ty.fnCallingConvention();6169 const mod = self.bin_file.options.module.?;
6156 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());6170 const fn_info = mod.typeToFunc(fn_ty).?;
6157 defer self.gpa.free(param_types);6171 const cc = fn_info.cc;
6158 fn_ty.fnParamTypes(param_types);
6159 var result: CallMCValues = .{6172 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),
6161 // These undefined values must be populated before returning from this function.6174 // These undefined values must be populated before returning from this function.
6162 .return_value = undefined,6175 .return_value = undefined,
6163 .stack_byte_count = undefined,6176 .stack_byte_count = undefined,
...@@ -6165,7 +6178,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6165,7 +6178,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6165 };6178 };
6166 errdefer self.gpa.free(result.args);6179 errdefer self.gpa.free(result.args);
61676180
6168 const ret_ty = fn_ty.fnReturnType();6181 const ret_ty = fn_ty.fnReturnType(mod);
61696182
6170 switch (cc) {6183 switch (cc) {
6171 .Naked => {6184 .Naked => {
...@@ -6180,12 +6193,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6180,12 +6193,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6180 var ncrn: usize = 0; // Next Core Register Number6193 var ncrn: usize = 0; // Next Core Register Number
6181 var nsaa: u32 = 0; // Next stacked argument address6194 var nsaa: u32 = 0; // Next stacked argument address
61826195
6183 if (ret_ty.zigTypeTag() == .NoReturn) {6196 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
6184 result.return_value = .{ .unreach = {} };6197 result.return_value = .{ .unreach = {} };
6185 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {6198 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6186 result.return_value = .{ .none = {} };6199 result.return_value = .{ .none = {} };
6187 } else {6200 } else {
6188 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));6201 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
6189 // TODO handle cases where multiple registers are used6202 // TODO handle cases where multiple registers are used
6190 if (ret_ty_size <= 4) {6203 if (ret_ty_size <= 4) {
6191 result.return_value = .{ .register = c_abi_int_return_regs[0] };6204 result.return_value = .{ .register = c_abi_int_return_regs[0] };
...@@ -6199,11 +6212,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6199,11 +6212,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6199 }6212 }
6200 }6213 }
62016214
6202 for (param_types, 0..) |ty, i| {6215 for (fn_info.param_types, 0..) |ty, i| {
6203 if (ty.abiAlignment(self.target.*) == 8)6216 if (ty.toType().abiAlignment(mod) == 8)
6204 ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2);6217 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));
6207 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {6220 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
6208 if (param_size <= 4) {6221 if (param_size <= 4) {
6209 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };6222 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
...@@ -6215,7 +6228,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6215,7 +6228,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6215 return self.fail("TODO MCValues split between registers and stack", .{});6228 return self.fail("TODO MCValues split between registers and stack", .{});
6216 } else {6229 } else {
6217 ncrn = 4;6230 ncrn = 4;
6218 if (ty.abiAlignment(self.target.*) == 8)6231 if (ty.toType().abiAlignment(mod) == 8)
6219 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);6232 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
62206233
6221 result.args[i] = .{ .stack_argument_offset = nsaa };6234 result.args[i] = .{ .stack_argument_offset = nsaa };
...@@ -6227,14 +6240,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6227,14 +6240,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6227 result.stack_align = 8;6240 result.stack_align = 8;
6228 },6241 },
6229 .Unspecified => {6242 .Unspecified => {
6230 if (ret_ty.zigTypeTag() == .NoReturn) {6243 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
6231 result.return_value = .{ .unreach = {} };6244 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)) {
6233 result.return_value = .{ .none = {} };6246 result.return_value = .{ .none = {} };
6234 } else {6247 } else {
6235 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));6248 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
6236 if (ret_ty_size == 0) {6249 if (ret_ty_size == 0) {
6237 assert(ret_ty.isError());6250 assert(ret_ty.isError(mod));
6238 result.return_value = .{ .immediate = 0 };6251 result.return_value = .{ .immediate = 0 };
6239 } else if (ret_ty_size <= 4) {6252 } else if (ret_ty_size <= 4) {
6240 result.return_value = .{ .register = .r0 };6253 result.return_value = .{ .register = .r0 };
...@@ -6249,10 +6262,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6249,10 +6262,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62496262
6250 var stack_offset: u32 = 0;6263 var stack_offset: u32 = 0;
62516264
6252 for (param_types, 0..) |ty, i| {6265 for (fn_info.param_types, 0..) |ty, i| {
6253 if (ty.abiSize(self.target.*) > 0) {6266 if (ty.toType().abiSize(mod) > 0) {
6254 const param_size = @intCast(u32, ty.abiSize(self.target.*));6267 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6255 const param_alignment = ty.abiAlignment(self.target.*);6268 const param_alignment = ty.toType().abiAlignment(mod);
62566269
6257 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);6270 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
6258 result.args[i] = .{ .stack_argument_offset = stack_offset };6271 result.args[i] = .{ .stack_argument_offset = stack_offset };
...@@ -6301,3 +6314,13 @@ fn parseRegName(name: []const u8) ?Register {...@@ -6301,3 +6314,13 @@ fn parseRegName(name: []const u8) ?Register {
6301 }6314 }
6302 return std.meta.stringToEnum(Register, name);6315 return std.meta.stringToEnum(Register, name);
6303}6316}
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 @@...@@ -1,8 +1,10 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;
2const bits = @import("bits.zig");3const bits = @import("bits.zig");
3const Register = bits.Register;4const Register = bits.Register;
4const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
5const Type = @import("../../type.zig").Type;6const Type = @import("../../type.zig").Type;
7const Module = @import("../../Module.zig");
68
7pub const Class = union(enum) {9pub const Class = union(enum) {
8 memory,10 memory,
...@@ -22,28 +24,28 @@ pub const Class = union(enum) {...@@ -22,28 +24,28 @@ pub const Class = union(enum) {
2224
23pub const Context = enum { ret, arg };25pub const Context = enum { ret, arg };
2426
25pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {27pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
26 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime());28 assert(ty.hasRuntimeBitsIgnoreComptime(mod));
2729
28 var maybe_float_bits: ?u16 = null;30 var maybe_float_bits: ?u16 = null;
29 const max_byval_size = 512;31 const max_byval_size = 512;
30 switch (ty.zigTypeTag()) {32 switch (ty.zigTypeTag(mod)) {
31 .Struct => {33 .Struct => {
32 const bit_size = ty.bitSize(target);34 const bit_size = ty.bitSize(mod);
33 if (ty.containerLayout() == .Packed) {35 if (ty.containerLayout(mod) == .Packed) {
34 if (bit_size > 64) return .memory;36 if (bit_size > 64) return .memory;
35 return .byval;37 return .byval;
36 }38 }
37 if (bit_size > max_byval_size) return .memory;39 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);
39 if (float_count <= byval_float_count) return .byval;41 if (float_count <= byval_float_count) return .byval;
4042
41 const fields = ty.structFieldCount();43 const fields = ty.structFieldCount(mod);
42 var i: u32 = 0;44 var i: u32 = 0;
43 while (i < fields) : (i += 1) {45 while (i < fields) : (i += 1) {
44 const field_ty = ty.structFieldType(i);46 const field_ty = ty.structFieldType(i, mod);
45 const field_alignment = ty.structFieldAlign(i, target);47 const field_alignment = ty.structFieldAlign(i, mod);
46 const field_size = field_ty.bitSize(target);48 const field_size = field_ty.bitSize(mod);
47 if (field_size > 32 or field_alignment > 32) {49 if (field_size > 32 or field_alignment > 32) {
48 return Class.arrSize(bit_size, 64);50 return Class.arrSize(bit_size, 64);
49 }51 }
...@@ -51,17 +53,17 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {...@@ -51,17 +53,17 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {
51 return Class.arrSize(bit_size, 32);53 return Class.arrSize(bit_size, 32);
52 },54 },
53 .Union => {55 .Union => {
54 const bit_size = ty.bitSize(target);56 const bit_size = ty.bitSize(mod);
55 if (ty.containerLayout() == .Packed) {57 if (ty.containerLayout(mod) == .Packed) {
56 if (bit_size > 64) return .memory;58 if (bit_size > 64) return .memory;
57 return .byval;59 return .byval;
58 }60 }
59 if (bit_size > max_byval_size) return .memory;61 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);
61 if (float_count <= byval_float_count) return .byval;63 if (float_count <= byval_float_count) return .byval;
6264
63 for (ty.unionFields().values()) |field| {65 for (ty.unionFields(mod).values()) |field| {
64 if (field.ty.bitSize(target) > 32 or field.normalAlignment(target) > 32) {66 if (field.ty.bitSize(mod) > 32 or field.normalAlignment(mod) > 32) {
65 return Class.arrSize(bit_size, 64);67 return Class.arrSize(bit_size, 64);
66 }68 }
67 }69 }
...@@ -71,28 +73,28 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {...@@ -71,28 +73,28 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {
71 .Int => {73 .Int => {
72 // TODO this is incorrect for _BitInt(128) but implementing74 // TODO this is incorrect for _BitInt(128) but implementing
73 // this correctly makes implementing compiler-rt impossible.75 // this correctly makes implementing compiler-rt impossible.
74 // const bit_size = ty.bitSize(target);76 // const bit_size = ty.bitSize(mod);
75 // if (bit_size > 64) return .memory;77 // if (bit_size > 64) return .memory;
76 return .byval;78 return .byval;
77 },79 },
78 .Enum, .ErrorSet => {80 .Enum, .ErrorSet => {
79 const bit_size = ty.bitSize(target);81 const bit_size = ty.bitSize(mod);
80 if (bit_size > 64) return .memory;82 if (bit_size > 64) return .memory;
81 return .byval;83 return .byval;
82 },84 },
83 .Vector => {85 .Vector => {
84 const bit_size = ty.bitSize(target);86 const bit_size = ty.bitSize(mod);
85 // TODO is this controlled by a cpu feature?87 // TODO is this controlled by a cpu feature?
86 if (ctx == .ret and bit_size > 128) return .memory;88 if (ctx == .ret and bit_size > 128) return .memory;
87 if (bit_size > 512) return .memory;89 if (bit_size > 512) return .memory;
88 return .byval;90 return .byval;
89 },91 },
90 .Optional => {92 .Optional => {
91 std.debug.assert(ty.isPtrLikeOptional());93 assert(ty.isPtrLikeOptional(mod));
92 return .byval;94 return .byval;
93 },95 },
94 .Pointer => {96 .Pointer => {
95 std.debug.assert(!ty.isSlice());97 assert(!ty.isSlice(mod));
96 return .byval;98 return .byval;
97 },99 },
98 .ErrorUnion,100 .ErrorUnion,
...@@ -114,14 +116,15 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {...@@ -114,14 +116,15 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {
114}116}
115117
116const byval_float_count = 4;118const 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();
118 const invalid = std.math.maxInt(u32);121 const invalid = std.math.maxInt(u32);
119 switch (ty.zigTypeTag()) {122 switch (ty.zigTypeTag(mod)) {
120 .Union => {123 .Union => {
121 const fields = ty.unionFields();124 const fields = ty.unionFields(mod);
122 var max_count: u32 = 0;125 var max_count: u32 = 0;
123 for (fields.values()) |field| {126 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);
125 if (field_count == invalid) return invalid;128 if (field_count == invalid) return invalid;
126 if (field_count > max_count) max_count = field_count;129 if (field_count > max_count) max_count = field_count;
127 if (max_count > byval_float_count) return invalid;130 if (max_count > byval_float_count) return invalid;
...@@ -129,12 +132,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {...@@ -129,12 +132,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {
129 return max_count;132 return max_count;
130 },133 },
131 .Struct => {134 .Struct => {
132 const fields_len = ty.structFieldCount();135 const fields_len = ty.structFieldCount(mod);
133 var count: u32 = 0;136 var count: u32 = 0;
134 var i: u32 = 0;137 var i: u32 = 0;
135 while (i < fields_len) : (i += 1) {138 while (i < fields_len) : (i += 1) {
136 const field_ty = ty.structFieldType(i);139 const field_ty = ty.structFieldType(i, mod);
137 const field_count = countFloats(field_ty, target, maybe_float_bits);140 const field_count = countFloats(field_ty, mod, maybe_float_bits);
138 if (field_count == invalid) return invalid;141 if (field_count == invalid) return invalid;
139 count += field_count;142 count += field_count;
140 if (count > byval_float_count) return invalid;143 if (count > byval_float_count) return invalid;
src/arch/riscv64/CodeGen.zig+108-95
...@@ -217,7 +217,7 @@ const Self = @This();...@@ -217,7 +217,7 @@ const Self = @This();
217pub fn generate(217pub fn generate(
218 bin_file: *link.File,218 bin_file: *link.File,
219 src_loc: Module.SrcLoc,219 src_loc: Module.SrcLoc,
220 module_fn: *Module.Fn,220 module_fn_index: Module.Fn.Index,
221 air: Air,221 air: Air,
222 liveness: Liveness,222 liveness: Liveness,
223 code: *std.ArrayList(u8),223 code: *std.ArrayList(u8),
...@@ -228,6 +228,7 @@ pub fn generate(...@@ -228,6 +228,7 @@ pub fn generate(
228 }228 }
229229
230 const mod = bin_file.options.module.?;230 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);
231 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
232 assert(fn_owner_decl.has_tv);233 assert(fn_owner_decl.has_tv);
233 const fn_type = fn_owner_decl.ty;234 const fn_type = fn_owner_decl.ty;
...@@ -347,7 +348,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -347,7 +348,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
347}348}
348349
349fn gen(self: *Self) !void {350fn 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);
351 if (cc != .Naked) {353 if (cc != .Naked) {
352 // TODO Finish function prologue and epilogue for riscv64.354 // TODO Finish function prologue and epilogue for riscv64.
353355
...@@ -470,13 +472,14 @@ fn gen(self: *Self) !void {...@@ -470,13 +472,14 @@ fn gen(self: *Self) !void {
470}472}
471473
472fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {474fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
475 const mod = self.bin_file.options.module.?;
476 const ip = &mod.intern_pool;
473 const air_tags = self.air.instructions.items(.tag);477 const air_tags = self.air.instructions.items(.tag);
474478
475 for (body) |inst| {479 for (body) |inst| {
476 // TODO: remove now-redundant isUnused calls from AIR handler functions480 // 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))
478 continue;482 continue;
479 }
480483
481 const old_air_bookkeeping = self.air_bookkeeping;484 const old_air_bookkeeping = self.air_bookkeeping;
482 try self.ensureProcessDeathCapacity(Liveness.bpi);485 try self.ensureProcessDeathCapacity(Liveness.bpi);
...@@ -656,8 +659,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -656,8 +659,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
656 .ptr_elem_val => try self.airPtrElemVal(inst),659 .ptr_elem_val => try self.airPtrElemVal(inst),
657 .ptr_elem_ptr => try self.airPtrElemPtr(inst),660 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
658661
659 .constant => unreachable, // excluded from function bodies662 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
660 .const_ty => unreachable, // excluded from function bodies
661 .unreach => self.finishAirBookkeeping(),663 .unreach => self.finishAirBookkeeping(),
662664
663 .optional_payload => try self.airOptionalPayload(inst),665 .optional_payload => try self.airOptionalPayload(inst),
...@@ -727,8 +729,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -727,8 +729,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
727729
728/// Asserts there is already capacity to insert into top branch inst_table.730/// Asserts there is already capacity to insert into top branch inst_table.
729fn processDeath(self: *Self, inst: Air.Inst.Index) void {731fn processDeath(self: *Self, inst: Air.Inst.Index) void {
730 const air_tags = self.air.instructions.items(.tag);732 assert(self.air.instructions.items(.tag)[inst] != .interned);
731 if (air_tags[inst] == .constant) return; // Constants are immortal.
732 // When editing this function, note that the logic must synchronize with `reuseOperand`.733 // When editing this function, note that the logic must synchronize with `reuseOperand`.
733 const prev_value = self.getResolvedInstValue(inst);734 const prev_value = self.getResolvedInstValue(inst);
734 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];735 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...@@ -755,8 +756,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
755 tomb_bits >>= 1;756 tomb_bits >>= 1;
756 if (!dies) continue;757 if (!dies) continue;
757 const op_int = @enumToInt(op);758 const op_int = @enumToInt(op);
758 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;759 if (op_int < Air.ref_start_index) continue;
759 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);760 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
760 self.processDeath(op_index);761 self.processDeath(op_index);
761 }762 }
762 const is_used = @truncate(u1, tomb_bits) == 0;763 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...@@ -804,23 +805,23 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
804805
805/// Use a pointer instruction as the basis for allocating stack memory.806/// Use a pointer instruction as the basis for allocating stack memory.
806fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {807fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
807 const elem_ty = self.air.typeOfIndex(inst).elemType();808 const mod = self.bin_file.options.module.?;
808 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {809 const elem_ty = self.typeOfIndex(inst).childType(mod);
809 const mod = self.bin_file.options.module.?;810 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
810 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});811 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
811 };812 };
812 // TODO swap this for inst.ty.ptrAlign813 // TODO swap this for inst.ty.ptrAlign
813 const abi_align = elem_ty.abiAlignment(self.target.*);814 const abi_align = elem_ty.abiAlignment(mod);
814 return self.allocMem(inst, abi_size, abi_align);815 return self.allocMem(inst, abi_size, abi_align);
815}816}
816817
817fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {818fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
818 const elem_ty = self.air.typeOfIndex(inst);819 const mod = self.bin_file.options.module.?;
819 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {820 const elem_ty = self.typeOfIndex(inst);
820 const mod = self.bin_file.options.module.?;821 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
821 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});822 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
822 };823 };
823 const abi_align = elem_ty.abiAlignment(self.target.*);824 const abi_align = elem_ty.abiAlignment(mod);
824 if (abi_align > self.stack_align)825 if (abi_align > self.stack_align)
825 self.stack_align = abi_align;826 self.stack_align = abi_align;
826827
...@@ -845,7 +846,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -845,7 +846,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
845 assert(reg == reg_mcv.register);846 assert(reg == reg_mcv.register);
846 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];847 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
847 try branch.inst_table.put(self.gpa, inst, stack_mcv);848 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);
849}850}
850851
851/// Copies a value to a register without tracking the register. The register is not considered852/// 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 {...@@ -862,7 +863,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
862/// This can have a side effect of spilling instructions to the stack to free up a register.863/// This can have a side effect of spilling instructions to the stack to free up a register.
863fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {864fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
864 const reg = try self.register_manager.allocReg(reg_owner, gp);865 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);
866 return MCValue{ .register = reg };867 return MCValue{ .register = reg };
867}868}
868869
...@@ -893,10 +894,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -893,10 +894,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
893 if (self.liveness.isUnused(inst))894 if (self.liveness.isUnused(inst))
894 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });895 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);
897 const operand = try self.resolveInst(ty_op.operand);899 const operand = try self.resolveInst(ty_op.operand);
898 const info_a = operand_ty.intInfo(self.target.*);900 const info_a = operand_ty.intInfo(mod);
899 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);901 const info_b = self.typeOfIndex(inst).intInfo(mod);
900 if (info_a.signedness != info_b.signedness)902 if (info_a.signedness != info_b.signedness)
901 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});903 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
902904
...@@ -1068,18 +1070,18 @@ fn binOp(...@@ -1068,18 +1070,18 @@ fn binOp(
1068 lhs_ty: Type,1070 lhs_ty: Type,
1069 rhs_ty: Type,1071 rhs_ty: Type,
1070) InnerError!MCValue {1072) InnerError!MCValue {
1073 const mod = self.bin_file.options.module.?;
1071 switch (tag) {1074 switch (tag) {
1072 // Arithmetic operations on integers and floats1075 // Arithmetic operations on integers and floats
1073 .add,1076 .add,
1074 .sub,1077 .sub,
1075 => {1078 => {
1076 switch (lhs_ty.zigTypeTag()) {1079 switch (lhs_ty.zigTypeTag(mod)) {
1077 .Float => return self.fail("TODO binary operations on floats", .{}),1080 .Float => return self.fail("TODO binary operations on floats", .{}),
1078 .Vector => return self.fail("TODO binary operations on vectors", .{}),1081 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1079 .Int => {1082 .Int => {
1080 const mod = self.bin_file.options.module.?;
1081 assert(lhs_ty.eql(rhs_ty, mod));1083 assert(lhs_ty.eql(rhs_ty, mod));
1082 const int_info = lhs_ty.intInfo(self.target.*);1084 const int_info = lhs_ty.intInfo(mod);
1083 if (int_info.bits <= 64) {1085 if (int_info.bits <= 64) {
1084 // TODO immediate operands1086 // TODO immediate operands
1085 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);1087 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
...@@ -1093,14 +1095,14 @@ fn binOp(...@@ -1093,14 +1095,14 @@ fn binOp(
1093 .ptr_add,1095 .ptr_add,
1094 .ptr_sub,1096 .ptr_sub,
1095 => {1097 => {
1096 switch (lhs_ty.zigTypeTag()) {1098 switch (lhs_ty.zigTypeTag(mod)) {
1097 .Pointer => {1099 .Pointer => {
1098 const ptr_ty = lhs_ty;1100 const ptr_ty = lhs_ty;
1099 const elem_ty = switch (ptr_ty.ptrSize()) {1101 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
1100 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type1102 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
1101 else => ptr_ty.childType(),1103 else => ptr_ty.childType(mod),
1102 };1104 };
1103 const elem_size = elem_ty.abiSize(self.target.*);1105 const elem_size = elem_ty.abiSize(mod);
11041106
1105 if (elem_size == 1) {1107 if (elem_size == 1) {
1106 const base_tag: Air.Inst.Tag = switch (tag) {1108 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 {...@@ -1125,8 +1127,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1125 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1127 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1126 const lhs = try self.resolveInst(bin_op.lhs);1128 const lhs = try self.resolveInst(bin_op.lhs);
1127 const rhs = try self.resolveInst(bin_op.rhs);1129 const rhs = try self.resolveInst(bin_op.rhs);
1128 const lhs_ty = self.air.typeOf(bin_op.lhs);1130 const lhs_ty = self.typeOf(bin_op.lhs);
1129 const rhs_ty = self.air.typeOf(bin_op.rhs);1131 const rhs_ty = self.typeOf(bin_op.rhs);
11301132
1131 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);1133 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
1132 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1134 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...@@ -1137,8 +1139,8 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
1137 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1139 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1138 const lhs = try self.resolveInst(bin_op.lhs);1140 const lhs = try self.resolveInst(bin_op.lhs);
1139 const rhs = try self.resolveInst(bin_op.rhs);1141 const rhs = try self.resolveInst(bin_op.rhs);
1140 const lhs_ty = self.air.typeOf(bin_op.lhs);1142 const lhs_ty = self.typeOf(bin_op.lhs);
1141 const rhs_ty = self.air.typeOf(bin_op.rhs);1143 const rhs_ty = self.typeOf(bin_op.rhs);
11421144
1143 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);1145 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
1144 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1146 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 {...@@ -1331,10 +1333,11 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
1331fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {1333fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1332 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1334 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1333 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1335 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
1336 // Optional with a zero-bit payload type is just a boolean true1339 // 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)
1338 break :result MCValue{ .immediate = 1 };1341 break :result MCValue{ .immediate = 1 };
13391342
1340 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});1343 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...@@ -1498,7 +1501,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
1498}1501}
14991502
1500fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {1503fn 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);
1502 switch (ptr) {1506 switch (ptr) {
1503 .none => unreachable,1507 .none => unreachable,
1504 .undef => unreachable,1508 .undef => unreachable,
...@@ -1523,14 +1527,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1523,14 +1527,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1523}1527}
15241528
1525fn airLoad(self: *Self, inst: Air.Inst.Index) !void {1529fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1530 const mod = self.bin_file.options.module.?;
1526 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1531 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);
1528 const result: MCValue = result: {1533 const result: MCValue = result: {
1529 if (!elem_ty.hasRuntimeBits())1534 if (!elem_ty.hasRuntimeBits(mod))
1530 break :result MCValue.none;1535 break :result MCValue.none;
15311536
1532 const ptr = try self.resolveInst(ty_op.operand);1537 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);
1534 if (self.liveness.isUnused(inst) and !is_volatile)1539 if (self.liveness.isUnused(inst) and !is_volatile)
1535 break :result MCValue.dead;1540 break :result MCValue.dead;
15361541
...@@ -1542,7 +1547,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1542,7 +1547,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1542 break :blk try self.allocRegOrMem(inst, true);1547 break :blk try self.allocRegOrMem(inst, true);
1543 }1548 }
1544 };1549 };
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));
1546 break :result dst_mcv;1551 break :result dst_mcv;
1547 };1552 };
1548 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1553 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 {...@@ -1583,8 +1588,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1583 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1588 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1584 const ptr = try self.resolveInst(bin_op.lhs);1589 const ptr = try self.resolveInst(bin_op.lhs);
1585 const value = try self.resolveInst(bin_op.rhs);1590 const value = try self.resolveInst(bin_op.rhs);
1586 const ptr_ty = self.air.typeOf(bin_op.lhs);1591 const ptr_ty = self.typeOf(bin_op.lhs);
1587 const value_ty = self.air.typeOf(bin_op.rhs);1592 const value_ty = self.typeOf(bin_op.rhs);
15881593
1589 try self.store(ptr, value, ptr_ty, value_ty);1594 try self.store(ptr, value, ptr_ty, value_ty);
15901595
...@@ -1644,7 +1649,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -1644,7 +1649,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1644 const arg_index = self.arg_index;1649 const arg_index = self.arg_index;
1645 self.arg_index += 1;1650 self.arg_index += 1;
16461651
1647 const ty = self.air.typeOfIndex(inst);1652 const ty = self.typeOfIndex(inst);
1648 _ = ty;1653 _ = ty;
16491654
1650 const result = self.args[arg_index];1655 const result = self.args[arg_index];
...@@ -1698,9 +1703,10 @@ fn airFence(self: *Self) !void {...@@ -1698,9 +1703,10 @@ fn airFence(self: *Self) !void {
1698}1703}
16991704
1700fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {1705fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
1706 const mod = self.bin_file.options.module.?;
1701 if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{});1707 if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{});
1702 const pl_op = self.air.instructions.items(.data)[inst].pl_op;1708 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);
1704 const callee = pl_op.operand;1710 const callee = pl_op.operand;
1705 const extra = self.air.extraData(Air.Call, pl_op.payload);1711 const extra = self.air.extraData(Air.Call, pl_op.payload);
1706 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);1712 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...@@ -1713,7 +1719,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1713 if (self.bin_file.cast(link.File.Elf)) |elf_file| {1719 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
1714 for (info.args, 0..) |mc_arg, arg_i| {1720 for (info.args, 0..) |mc_arg, arg_i| {
1715 const arg = args[arg_i];1721 const arg = args[arg_i];
1716 const arg_ty = self.air.typeOf(arg);1722 const arg_ty = self.typeOf(arg);
1717 const arg_mcv = try self.resolveInst(args[arg_i]);1723 const arg_mcv = try self.resolveInst(args[arg_i]);
17181724
1719 switch (mc_arg) {1725 switch (mc_arg) {
...@@ -1736,14 +1742,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1736,14 +1742,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1736 }1742 }
1737 }1743 }
17381744
1739 if (self.air.value(callee)) |func_value| {1745 if (try self.air.value(callee, mod)) |func_value| {
1740 if (func_value.castTag(.function)) |func_payload| {1746 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1741 const func = func_payload.data;
1742 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1747 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1743 const atom = elf_file.getAtom(atom_index);1748 const atom = elf_file.getAtom(atom_index);
1744 _ = try atom.getOrCreateOffsetTableEntry(elf_file);1749 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1745 const got_addr = @intCast(u32, atom.getOffsetTableAddress(elf_file));1750 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 });
1747 _ = try self.addInst(.{1752 _ = try self.addInst(.{
1748 .tag = .jalr,1753 .tag = .jalr,
1749 .data = .{ .i_type = .{1754 .data = .{ .i_type = .{
...@@ -1752,7 +1757,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1752,7 +1757,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1752 .imm12 = 0,1757 .imm12 = 0,
1753 } },1758 } },
1754 });1759 });
1755 } else if (func_value.castTag(.extern_fn)) |_| {1760 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1756 return self.fail("TODO implement calling extern functions", .{});1761 return self.fail("TODO implement calling extern functions", .{});
1757 } else {1762 } else {
1758 return self.fail("TODO implement calling bitcasted functions", .{});1763 return self.fail("TODO implement calling bitcasted functions", .{});
...@@ -1796,7 +1801,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1796,7 +1801,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1796}1801}
17971802
1798fn ret(self: *Self, mcv: MCValue) !void {1803fn 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);
1800 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);1806 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
1801 // Just add space for an instruction, patch this later1807 // Just add space for an instruction, patch this later
1802 const index = try self.addInst(.{1808 const index = try self.addInst(.{
...@@ -1825,10 +1831,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -1825,10 +1831,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1825 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1831 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1826 if (self.liveness.isUnused(inst))1832 if (self.liveness.isUnused(inst))
1827 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });1833 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);
1829 const mod = self.bin_file.options.module.?;1835 const mod = self.bin_file.options.module.?;
1830 assert(ty.eql(self.air.typeOf(bin_op.rhs), mod));1836 assert(ty.eql(self.typeOf(bin_op.rhs), mod));
1831 if (ty.zigTypeTag() == .ErrorSet)1837 if (ty.zigTypeTag(mod) == .ErrorSet)
1832 return self.fail("TODO implement cmp for errors", .{});1838 return self.fail("TODO implement cmp for errors", .{});
18331839
1834 const lhs = try self.resolveInst(bin_op.lhs);1840 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -1869,8 +1875,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -1869,8 +1875,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
1869}1875}
18701876
1871fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1877fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1872 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1878 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1873 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;1879 const mod = self.bin_file.options.module.?;
1880 const function = mod.funcPtr(ty_fn.func);
1874 // TODO emit debug info for function change1881 // TODO emit debug info for function change
1875 _ = function;1882 _ = function;
1876 return self.finishAir(inst, .dead, .{ .none, .none, .none });1883 return self.finishAir(inst, .dead, .{ .none, .none, .none });
...@@ -1946,7 +1953,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1946,7 +1953,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
1946 break :blk try self.allocRegOrMem(inst, true);1953 break :blk try self.allocRegOrMem(inst, true);
1947 }1954 }
1948 };1955 };
1949 try self.load(operand, operand_ptr, self.air.typeOf(un_op));1956 try self.load(operand, operand_ptr, self.typeOf(un_op));
1950 break :result try self.isNull(operand);1957 break :result try self.isNull(operand);
1951 };1958 };
1952 return self.finishAir(inst, result, .{ un_op, .none, .none });1959 return self.finishAir(inst, result, .{ un_op, .none, .none });
...@@ -1973,7 +1980,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1973,7 +1980,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
1973 break :blk try self.allocRegOrMem(inst, true);1980 break :blk try self.allocRegOrMem(inst, true);
1974 }1981 }
1975 };1982 };
1976 try self.load(operand, operand_ptr, self.air.typeOf(un_op));1983 try self.load(operand, operand_ptr, self.typeOf(un_op));
1977 break :result try self.isNonNull(operand);1984 break :result try self.isNonNull(operand);
1978 };1985 };
1979 return self.finishAir(inst, result, .{ un_op, .none, .none });1986 return self.finishAir(inst, result, .{ un_op, .none, .none });
...@@ -2000,7 +2007,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2000,7 +2007,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2000 break :blk try self.allocRegOrMem(inst, true);2007 break :blk try self.allocRegOrMem(inst, true);
2001 }2008 }
2002 };2009 };
2003 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2010 try self.load(operand, operand_ptr, self.typeOf(un_op));
2004 break :result try self.isErr(operand);2011 break :result try self.isErr(operand);
2005 };2012 };
2006 return self.finishAir(inst, result, .{ un_op, .none, .none });2013 return self.finishAir(inst, result, .{ un_op, .none, .none });
...@@ -2027,7 +2034,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2027,7 +2034,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2027 break :blk try self.allocRegOrMem(inst, true);2034 break :blk try self.allocRegOrMem(inst, true);
2028 }2035 }
2029 };2036 };
2030 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2037 try self.load(operand, operand_ptr, self.typeOf(un_op));
2031 break :result try self.isNonErr(operand);2038 break :result try self.isNonErr(operand);
2032 };2039 };
2033 return self.finishAir(inst, result, .{ un_op, .none, .none });2040 return self.finishAir(inst, result, .{ un_op, .none, .none });
...@@ -2107,13 +2114,14 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -2107,13 +2114,14 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
2107fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {2114fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
2108 const block_data = self.blocks.getPtr(block).?;2115 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)) {
2111 const operand_mcv = try self.resolveInst(operand);2119 const operand_mcv = try self.resolveInst(operand);
2112 const block_mcv = block_data.mcv;2120 const block_mcv = block_data.mcv;
2113 if (block_mcv == .none) {2121 if (block_mcv == .none) {
2114 block_data.mcv = operand_mcv;2122 block_data.mcv = operand_mcv;
2115 } else {2123 } else {
2116 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);2124 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
2117 }2125 }
2118 }2126 }
2119 return self.brVoid(block);2127 return self.brVoid(block);
...@@ -2176,7 +2184,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -2176,7 +2184,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
21762184
2177 const arg_mcv = try self.resolveInst(input);2185 const arg_mcv = try self.resolveInst(input);
2178 try self.register_manager.getReg(reg, null);2186 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);
2180 }2188 }
21812189
2182 {2190 {
...@@ -2372,7 +2380,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -2372,7 +2380,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
2372 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);2380 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
23732381
2374 const dest = try self.allocRegOrMem(inst, true);2382 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);
2376 break :result dest;2384 break :result dest;
2377 };2385 };
2378 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2386 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -2489,8 +2497,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {...@@ -2489,8 +2497,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
2489}2497}
24902498
2491fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {2499fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
2492 const vector_ty = self.air.typeOfIndex(inst);2500 const mod = self.bin_file.options.module.?;
2493 const len = vector_ty.vectorLen();2501 const vector_ty = self.typeOfIndex(inst);
2502 const len = vector_ty.vectorLen(mod);
2494 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2503 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2495 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);2504 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
2496 const result: MCValue = res: {2505 const result: MCValue = res: {
...@@ -2533,37 +2542,32 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {...@@ -2533,37 +2542,32 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
2533}2542}
25342543
2535fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {2544fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
2536 // First section of indexes correspond to a set number of constant values.2545 const mod = self.bin_file.options.module.?;
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 }
25452546
2546 // If the type has no codegen bits, no need to store it.2547 // If the type has no codegen bits, no need to store it.
2547 const inst_ty = self.air.typeOf(inst);2548 const inst_ty = self.typeOf(inst);
2548 if (!inst_ty.hasRuntimeBits())2549 if (!inst_ty.hasRuntimeBits(mod))
2549 return MCValue{ .none = {} };2550 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
2552 switch (self.air.instructions.items(.tag)[inst_index]) {2557 switch (self.air.instructions.items(.tag)[inst_index]) {
2553 .constant => {2558 .interned => {
2554 // Constants have static lifetimes, so they are always memoized in the outer most table.2559 // Constants have static lifetimes, so they are always memoized in the outer most table.
2555 const branch = &self.branch_stack.items[0];2560 const branch = &self.branch_stack.items[0];
2556 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);2561 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
2557 if (!gop.found_existing) {2562 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;
2559 gop.value_ptr.* = try self.genTypedValue(.{2564 gop.value_ptr.* = try self.genTypedValue(.{
2560 .ty = inst_ty,2565 .ty = inst_ty,
2561 .val = self.air.values[ty_pl.payload],2566 .val = interned.toValue(),
2562 });2567 });
2563 }2568 }
2564 return gop.value_ptr.*;2569 return gop.value_ptr.*;
2565 },2570 },
2566 .const_ty => unreachable,
2567 else => return self.getResolvedInstValue(inst_index),2571 else => return self.getResolvedInstValue(inst_index),
2568 }2572 }
2569}2573}
...@@ -2616,12 +2620,11 @@ const CallMCValues = struct {...@@ -2616,12 +2620,11 @@ const CallMCValues = struct {
26162620
2617/// Caller must call `CallMCValues.deinit`.2621/// Caller must call `CallMCValues.deinit`.
2618fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {2622fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2619 const cc = fn_ty.fnCallingConvention();2623 const mod = self.bin_file.options.module.?;
2620 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());2624 const fn_info = mod.typeToFunc(fn_ty).?;
2621 defer self.gpa.free(param_types);2625 const cc = fn_info.cc;
2622 fn_ty.fnParamTypes(param_types);
2623 var result: CallMCValues = .{2626 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),
2625 // These undefined values must be populated before returning from this function.2628 // These undefined values must be populated before returning from this function.
2626 .return_value = undefined,2629 .return_value = undefined,
2627 .stack_byte_count = undefined,2630 .stack_byte_count = undefined,
...@@ -2629,7 +2632,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2629,7 +2632,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2629 };2632 };
2630 errdefer self.gpa.free(result.args);2633 errdefer self.gpa.free(result.args);
26312634
2632 const ret_ty = fn_ty.fnReturnType();2635 const ret_ty = fn_ty.fnReturnType(mod);
26332636
2634 switch (cc) {2637 switch (cc) {
2635 .Naked => {2638 .Naked => {
...@@ -2649,8 +2652,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2649,8 +2652,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2649 var next_stack_offset: u32 = 0;2652 var next_stack_offset: u32 = 0;
2650 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };2653 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
26512654
2652 for (param_types, 0..) |ty, i| {2655 for (fn_info.param_types, 0..) |ty, i| {
2653 const param_size = @intCast(u32, ty.abiSize(self.target.*));2656 const param_size = @intCast(u32, ty.toType().abiSize(mod));
2654 if (param_size <= 8) {2657 if (param_size <= 8) {
2655 if (next_register < argument_registers.len) {2658 if (next_register < argument_registers.len) {
2656 result.args[i] = .{ .register = argument_registers[next_register] };2659 result.args[i] = .{ .register = argument_registers[next_register] };
...@@ -2680,14 +2683,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2680,14 +2683,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2680 else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}),2683 else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}),
2681 }2684 }
26822685
2683 if (ret_ty.zigTypeTag() == .NoReturn) {2686 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
2684 result.return_value = .{ .unreach = {} };2687 result.return_value = .{ .unreach = {} };
2685 } else if (!ret_ty.hasRuntimeBits()) {2688 } else if (!ret_ty.hasRuntimeBits(mod)) {
2686 result.return_value = .{ .none = {} };2689 result.return_value = .{ .none = {} };
2687 } else switch (cc) {2690 } else switch (cc) {
2688 .Naked => unreachable,2691 .Naked => unreachable,
2689 .Unspecified, .C => {2692 .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));
2691 if (ret_ty_size <= 8) {2694 if (ret_ty_size <= 8) {
2692 result.return_value = .{ .register = .a0 };2695 result.return_value = .{ .register = .a0 };
2693 } else if (ret_ty_size <= 16) {2696 } else if (ret_ty_size <= 16) {
...@@ -2731,3 +2734,13 @@ fn parseRegName(name: []const u8) ?Register {...@@ -2731,3 +2734,13 @@ fn parseRegName(name: []const u8) ?Register {
2731 }2734 }
2732 return std.meta.stringToEnum(Register, name);2735 return std.meta.stringToEnum(Register, name);
2733}2736}
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");...@@ -3,17 +3,19 @@ const bits = @import("bits.zig");
3const Register = bits.Register;3const Register = bits.Register;
4const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;4const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
5const Type = @import("../../type.zig").Type;5const Type = @import("../../type.zig").Type;
6const Module = @import("../../Module.zig");
67
7pub const Class = enum { memory, byval, integer, double_integer };8pub const Class = enum { memory, byval, integer, double_integer };
89
9pub fn classifyType(ty: Type, target: std.Target) Class {10pub fn classifyType(ty: Type, mod: *Module) Class {
10 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime());11 const target = mod.getTarget();
12 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod));
1113
12 const max_byval_size = target.ptrBitWidth() * 2;14 const max_byval_size = target.ptrBitWidth() * 2;
13 switch (ty.zigTypeTag()) {15 switch (ty.zigTypeTag(mod)) {
14 .Struct => {16 .Struct => {
15 const bit_size = ty.bitSize(target);17 const bit_size = ty.bitSize(mod);
16 if (ty.containerLayout() == .Packed) {18 if (ty.containerLayout(mod) == .Packed) {
17 if (bit_size > max_byval_size) return .memory;19 if (bit_size > max_byval_size) return .memory;
18 return .byval;20 return .byval;
19 }21 }
...@@ -23,8 +25,8 @@ pub fn classifyType(ty: Type, target: std.Target) Class {...@@ -23,8 +25,8 @@ pub fn classifyType(ty: Type, target: std.Target) Class {
23 return .integer;25 return .integer;
24 },26 },
25 .Union => {27 .Union => {
26 const bit_size = ty.bitSize(target);28 const bit_size = ty.bitSize(mod);
27 if (ty.containerLayout() == .Packed) {29 if (ty.containerLayout(mod) == .Packed) {
28 if (bit_size > max_byval_size) return .memory;30 if (bit_size > max_byval_size) return .memory;
29 return .byval;31 return .byval;
30 }32 }
...@@ -36,21 +38,21 @@ pub fn classifyType(ty: Type, target: std.Target) Class {...@@ -36,21 +38,21 @@ pub fn classifyType(ty: Type, target: std.Target) Class {
36 .Bool => return .integer,38 .Bool => return .integer,
37 .Float => return .byval,39 .Float => return .byval,
38 .Int, .Enum, .ErrorSet => {40 .Int, .Enum, .ErrorSet => {
39 const bit_size = ty.bitSize(target);41 const bit_size = ty.bitSize(mod);
40 if (bit_size > max_byval_size) return .memory;42 if (bit_size > max_byval_size) return .memory;
41 return .byval;43 return .byval;
42 },44 },
43 .Vector => {45 .Vector => {
44 const bit_size = ty.bitSize(target);46 const bit_size = ty.bitSize(mod);
45 if (bit_size > max_byval_size) return .memory;47 if (bit_size > max_byval_size) return .memory;
46 return .integer;48 return .integer;
47 },49 },
48 .Optional => {50 .Optional => {
49 std.debug.assert(ty.isPtrLikeOptional());51 std.debug.assert(ty.isPtrLikeOptional(mod));
50 return .byval;52 return .byval;
51 },53 },
52 .Pointer => {54 .Pointer => {
53 std.debug.assert(!ty.isSlice());55 std.debug.assert(!ty.isSlice(mod));
54 return .byval;56 return .byval;
55 },57 },
56 .ErrorUnion,58 .ErrorUnion,
src/arch/sparc64/CodeGen.zig+244-222
...@@ -260,7 +260,7 @@ const BigTomb = struct {...@@ -260,7 +260,7 @@ const BigTomb = struct {
260pub fn generate(260pub fn generate(
261 bin_file: *link.File,261 bin_file: *link.File,
262 src_loc: Module.SrcLoc,262 src_loc: Module.SrcLoc,
263 module_fn: *Module.Fn,263 module_fn_index: Module.Fn.Index,
264 air: Air,264 air: Air,
265 liveness: Liveness,265 liveness: Liveness,
266 code: *std.ArrayList(u8),266 code: *std.ArrayList(u8),
...@@ -271,12 +271,11 @@ pub fn generate(...@@ -271,12 +271,11 @@ pub fn generate(
271 }271 }
272272
273 const mod = bin_file.options.module.?;273 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);
274 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
275 assert(fn_owner_decl.has_tv);276 assert(fn_owner_decl.has_tv);
276 const fn_type = fn_owner_decl.ty;277 const fn_type = fn_owner_decl.ty;
277278
278 log.debug("fn {s}", .{fn_owner_decl.name});
279
280 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);279 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
281 defer {280 defer {
282 assert(branch_stack.items.len == 1);281 assert(branch_stack.items.len == 1);
...@@ -363,7 +362,8 @@ pub fn generate(...@@ -363,7 +362,8 @@ pub fn generate(
363}362}
364363
365fn gen(self: *Self) !void {364fn 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);
367 if (cc != .Naked) {367 if (cc != .Naked) {
368 // TODO Finish function prologue and epilogue for sparc64.368 // TODO Finish function prologue and epilogue for sparc64.
369369
...@@ -490,13 +490,14 @@ fn gen(self: *Self) !void {...@@ -490,13 +490,14 @@ fn gen(self: *Self) !void {
490}490}
491491
492fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {492fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
493 const mod = self.bin_file.options.module.?;
494 const ip = &mod.intern_pool;
493 const air_tags = self.air.instructions.items(.tag);495 const air_tags = self.air.instructions.items(.tag);
494496
495 for (body) |inst| {497 for (body) |inst| {
496 // TODO: remove now-redundant isUnused calls from AIR handler functions498 // 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))
498 continue;500 continue;
499 }
500501
501 const old_air_bookkeeping = self.air_bookkeeping;502 const old_air_bookkeeping = self.air_bookkeeping;
502 try self.ensureProcessDeathCapacity(Liveness.bpi);503 try self.ensureProcessDeathCapacity(Liveness.bpi);
...@@ -676,8 +677,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -676,8 +677,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
676 .ptr_elem_val => try self.airPtrElemVal(inst),677 .ptr_elem_val => try self.airPtrElemVal(inst),
677 .ptr_elem_ptr => try self.airPtrElemPtr(inst),678 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
678679
679 .constant => unreachable, // excluded from function bodies680 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
680 .const_ty => unreachable, // excluded from function bodies
681 .unreach => self.finishAirBookkeeping(),681 .unreach => self.finishAirBookkeeping(),
682682
683 .optional_payload => try self.airOptionalPayload(inst),683 .optional_payload => try self.airOptionalPayload(inst),
...@@ -758,18 +758,18 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -758,18 +758,18 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
758 const tag = self.air.instructions.items(.tag)[inst];758 const tag = self.air.instructions.items(.tag)[inst];
759 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;759 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
760 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;760 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
761 const mod = self.bin_file.options.module.?;
761 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {762 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
762 const lhs = try self.resolveInst(extra.lhs);763 const lhs = try self.resolveInst(extra.lhs);
763 const rhs = try self.resolveInst(extra.rhs);764 const rhs = try self.resolveInst(extra.rhs);
764 const lhs_ty = self.air.typeOf(extra.lhs);765 const lhs_ty = self.typeOf(extra.lhs);
765 const rhs_ty = self.air.typeOf(extra.rhs);766 const rhs_ty = self.typeOf(extra.rhs);
766767
767 switch (lhs_ty.zigTypeTag()) {768 switch (lhs_ty.zigTypeTag(mod)) {
768 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),769 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),
769 .Int => {770 .Int => {
770 const mod = self.bin_file.options.module.?;
771 assert(lhs_ty.eql(rhs_ty, mod));771 assert(lhs_ty.eql(rhs_ty, mod));
772 const int_info = lhs_ty.intInfo(self.target.*);772 const int_info = lhs_ty.intInfo(mod);
773 switch (int_info.bits) {773 switch (int_info.bits) {
774 32, 64 => {774 32, 64 => {
775 // Only say yes if the operation is775 // Only say yes if the operation is
...@@ -836,8 +836,9 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -836,8 +836,9 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
836}836}
837837
838fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {838fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
839 const vector_ty = self.air.typeOfIndex(inst);839 const mod = self.bin_file.options.module.?;
840 const len = vector_ty.vectorLen();840 const vector_ty = self.typeOfIndex(inst);
841 const len = vector_ty.vectorLen(mod);
841 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;842 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
842 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);843 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
843 const result: MCValue = res: {844 const result: MCValue = res: {
...@@ -869,19 +870,20 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -869,19 +870,20 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
869}870}
870871
871fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {872fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
873 const mod = self.bin_file.options.module.?;
872 const ty_op = self.air.instructions.items(.data)[inst].ty_op;874 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
873 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {875 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);
875 const ptr = try self.resolveInst(ty_op.operand);877 const ptr = try self.resolveInst(ty_op.operand);
876 const array_ty = ptr_ty.childType();878 const array_ty = ptr_ty.childType(mod);
877 const array_len = @intCast(u32, array_ty.arrayLen());879 const array_len = @intCast(u32, array_ty.arrayLen(mod));
878880
879 const ptr_bits = self.target.ptrBitWidth();881 const ptr_bits = self.target.ptrBitWidth();
880 const ptr_bytes = @divExact(ptr_bits, 8);882 const ptr_bytes = @divExact(ptr_bits, 8);
881883
882 const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);884 const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
883 try self.genSetStack(ptr_ty, stack_offset, ptr);885 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 });
885 break :result MCValue{ .stack_offset = stack_offset };887 break :result MCValue{ .stack_offset = stack_offset };
886 };888 };
887 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });889 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -935,7 +937,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -935,7 +937,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
935937
936 const arg_mcv = try self.resolveInst(input);938 const arg_mcv = try self.resolveInst(input);
937 try self.register_manager.getReg(reg, null);939 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);
939 }941 }
940942
941 {943 {
...@@ -1008,17 +1010,17 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -1008,17 +1010,17 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1008}1010}
10091011
1010fn airArg(self: *Self, inst: Air.Inst.Index) !void {1012fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1013 const mod = self.bin_file.options.module.?;
1011 const arg_index = self.arg_index;1014 const arg_index = self.arg_index;
1012 self.arg_index += 1;1015 self.arg_index += 1;
10131016
1014 const ty = self.air.typeOfIndex(inst);1017 const ty = self.typeOfIndex(inst);
10151018
1016 const arg = self.args[arg_index];1019 const arg = self.args[arg_index];
1017 const mcv = blk: {1020 const mcv = blk: {
1018 switch (arg) {1021 switch (arg) {
1019 .stack_offset => |off| {1022 .stack_offset => |off| {
1020 const mod = self.bin_file.options.module.?;1023 const abi_size = math.cast(u32, ty.abiSize(mod)) orelse {
1021 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) orelse {
1022 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});1024 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
1023 };1025 };
1024 const offset = off + abi_size;1026 const offset = off + abi_size;
...@@ -1063,8 +1065,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -1063,8 +1065,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1063 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1065 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1064 const lhs = try self.resolveInst(bin_op.lhs);1066 const lhs = try self.resolveInst(bin_op.lhs);
1065 const rhs = try self.resolveInst(bin_op.rhs);1067 const rhs = try self.resolveInst(bin_op.rhs);
1066 const lhs_ty = self.air.typeOf(bin_op.lhs);1068 const lhs_ty = self.typeOf(bin_op.lhs);
1067 const rhs_ty = self.air.typeOf(bin_op.rhs);1069 const rhs_ty = self.typeOf(bin_op.rhs);
1068 const result: MCValue = if (self.liveness.isUnused(inst))1070 const result: MCValue = if (self.liveness.isUnused(inst))
1069 .dead1071 .dead
1070 else1072 else
...@@ -1088,8 +1090,8 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void...@@ -1088,8 +1090,8 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
1088 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1090 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1089 const lhs = try self.resolveInst(bin_op.lhs);1091 const lhs = try self.resolveInst(bin_op.lhs);
1090 const rhs = try self.resolveInst(bin_op.rhs);1092 const rhs = try self.resolveInst(bin_op.rhs);
1091 const lhs_ty = self.air.typeOf(bin_op.lhs);1093 const lhs_ty = self.typeOf(bin_op.lhs);
1092 const rhs_ty = self.air.typeOf(bin_op.rhs);1094 const rhs_ty = self.typeOf(bin_op.rhs);
1093 const result: MCValue = if (self.liveness.isUnused(inst))1095 const result: MCValue = if (self.liveness.isUnused(inst))
1094 .dead1096 .dead
1095 else1097 else
...@@ -1115,7 +1117,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1115,7 +1117,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1115 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);1117 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
11161118
1117 const dest = try self.allocRegOrMem(inst, true);1119 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);
1119 break :result dest;1121 break :result dest;
1120 };1122 };
1121 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1123 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -1203,6 +1205,7 @@ fn airBreakpoint(self: *Self) !void {...@@ -1203,6 +1205,7 @@ fn airBreakpoint(self: *Self) !void {
1203}1205}
12041206
1205fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {1207fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
1208 const mod = self.bin_file.options.module.?;
1206 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1209 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
12071210
1208 // We have hardware byteswapper in SPARCv9, don't let mainstream compilers mislead you.1211 // 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 {...@@ -1217,15 +1220,15 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
1217 // TODO: Fold byteswap+store into a single ST*A and load+byteswap into a single LD*A.1220 // TODO: Fold byteswap+store into a single ST*A and load+byteswap into a single LD*A.
1218 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1221 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1219 const operand = try self.resolveInst(ty_op.operand);1222 const operand = try self.resolveInst(ty_op.operand);
1220 const operand_ty = self.air.typeOf(ty_op.operand);1223 const operand_ty = self.typeOf(ty_op.operand);
1221 switch (operand_ty.zigTypeTag()) {1224 switch (operand_ty.zigTypeTag(mod)) {
1222 .Vector => return self.fail("TODO byteswap for vectors", .{}),1225 .Vector => return self.fail("TODO byteswap for vectors", .{}),
1223 .Int => {1226 .Int => {
1224 const int_info = operand_ty.intInfo(self.target.*);1227 const int_info = operand_ty.intInfo(mod);
1225 if (int_info.bits == 8) break :result operand;1228 if (int_info.bits == 8) break :result operand;
12261229
1227 const abi_size = int_info.bits >> 3;1230 const abi_size = int_info.bits >> 3;
1228 const abi_align = operand_ty.abiAlignment(self.target.*);1231 const abi_align = operand_ty.abiAlignment(mod);
1229 const opposite_endian_asi = switch (self.target.cpu.arch.endian()) {1232 const opposite_endian_asi = switch (self.target.cpu.arch.endian()) {
1230 Endian.Big => ASI.asi_primary_little,1233 Endian.Big => ASI.asi_primary_little,
1231 Endian.Little => ASI.asi_primary,1234 Endian.Little => ASI.asi_primary,
...@@ -1293,10 +1296,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1293,10 +1296,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1293 const callee = pl_op.operand;1296 const callee = pl_op.operand;
1294 const extra = self.air.extraData(Air.Call, pl_op.payload);1297 const extra = self.air.extraData(Air.Call, pl_op.payload);
1295 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end .. extra.end + extra.data.args_len]);1298 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);1299 const ty = self.typeOf(callee);
1297 const fn_ty = switch (ty.zigTypeTag()) {1300 const mod = self.bin_file.options.module.?;
1301 const fn_ty = switch (ty.zigTypeTag(mod)) {
1298 .Fn => ty,1302 .Fn => ty,
1299 .Pointer => ty.childType(),1303 .Pointer => ty.childType(mod),
1300 else => unreachable,1304 else => unreachable,
1301 };1305 };
13021306
...@@ -1316,7 +1320,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1316,7 +1320,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13161320
1317 for (info.args, 0..) |mc_arg, arg_i| {1321 for (info.args, 0..) |mc_arg, arg_i| {
1318 const arg = args[arg_i];1322 const arg = args[arg_i];
1319 const arg_ty = self.air.typeOf(arg);1323 const arg_ty = self.typeOf(arg);
1320 const arg_mcv = try self.resolveInst(arg);1324 const arg_mcv = try self.resolveInst(arg);
13211325
1322 switch (mc_arg) {1326 switch (mc_arg) {
...@@ -1337,10 +1341,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1337,10 +1341,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13371341
1338 // Due to incremental compilation, how function calls are generated depends1342 // Due to incremental compilation, how function calls are generated depends
1339 // on linking.1343 // on linking.
1340 if (self.air.value(callee)) |func_value| {1344 if (try self.air.value(callee, mod)) |func_value| {
1341 if (self.bin_file.tag == link.File.Elf.base_tag) {1345 if (self.bin_file.tag == link.File.Elf.base_tag) {
1342 if (func_value.castTag(.function)) |func_payload| {1346 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1343 const func = func_payload.data;
1344 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {1347 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1345 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1348 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1346 const atom = elf_file.getAtom(atom_index);1349 const atom = elf_file.getAtom(atom_index);
...@@ -1348,7 +1351,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1348,7 +1351,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1348 break :blk @intCast(u32, atom.getOffsetTableAddress(elf_file));1351 break :blk @intCast(u32, atom.getOffsetTableAddress(elf_file));
1349 } else unreachable;1352 } 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
1353 _ = try self.addInst(.{1356 _ = try self.addInst(.{
1354 .tag = .jmpl,1357 .tag = .jmpl,
...@@ -1367,14 +1370,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1367,14 +1370,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1367 .tag = .nop,1370 .tag = .nop,
1368 .data = .{ .nop = {} },1371 .data = .{ .nop = {} },
1369 });1372 });
1370 } else if (func_value.castTag(.extern_fn)) |_| {1373 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1371 return self.fail("TODO implement calling extern functions", .{});1374 return self.fail("TODO implement calling extern functions", .{});
1372 } else {1375 } else {
1373 return self.fail("TODO implement calling bitcasted functions", .{});1376 return self.fail("TODO implement calling bitcasted functions", .{});
1374 }1377 }
1375 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");1378 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
1376 } else {1379 } else {
1377 assert(ty.zigTypeTag() == .Pointer);1380 assert(ty.zigTypeTag(mod) == .Pointer);
1378 const mcv = try self.resolveInst(callee);1381 const mcv = try self.resolveInst(callee);
1379 try self.genSetReg(ty, .o7, mcv);1382 try self.genSetReg(ty, .o7, mcv);
13801383
...@@ -1422,25 +1425,24 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -1422,25 +1425,24 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
14221425
1423fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {1426fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1424 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1427 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1428 const mod = self.bin_file.options.module.?;
1425 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1429 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1426 const lhs = try self.resolveInst(bin_op.lhs);1430 const lhs = try self.resolveInst(bin_op.lhs);
1427 const rhs = try self.resolveInst(bin_op.rhs);1431 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;1434 const int_ty = switch (lhs_ty.zigTypeTag(mod)) {
1431 const int_ty = switch (lhs_ty.zigTypeTag()) {
1432 .Vector => unreachable, // Handled by cmp_vector.1435 .Vector => unreachable, // Handled by cmp_vector.
1433 .Enum => lhs_ty.intTagType(&int_buffer),1436 .Enum => lhs_ty.intTagType(mod),
1434 .Int => lhs_ty,1437 .Int => lhs_ty,
1435 .Bool => Type.initTag(.u1),1438 .Bool => Type.u1,
1436 .Pointer => Type.usize,1439 .Pointer => Type.usize,
1437 .ErrorSet => Type.initTag(.u16),1440 .ErrorSet => Type.u16,
1438 .Optional => blk: {1441 .Optional => blk: {
1439 var opt_buffer: Type.Payload.ElemType = undefined;1442 const payload_ty = lhs_ty.optionalChild(mod);
1440 const payload_ty = lhs_ty.optionalChild(&opt_buffer);1443 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1441 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1444 break :blk Type.u1;
1442 break :blk Type.initTag(.u1);1445 } else if (lhs_ty.isPtrLikeOptional(mod)) {
1443 } else if (lhs_ty.isPtrLikeOptional()) {
1444 break :blk Type.usize;1446 break :blk Type.usize;
1445 } else {1447 } else {
1446 return self.fail("TODO SPARCv9 cmp non-pointer optionals", .{});1448 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 {...@@ -1450,7 +1452,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1450 else => unreachable,1452 else => unreachable,
1451 };1453 };
14521454
1453 const int_info = int_ty.intInfo(self.target.*);1455 const int_info = int_ty.intInfo(mod);
1454 if (int_info.bits <= 64) {1456 if (int_info.bits <= 64) {
1455 _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, BinOpMetadata{1457 _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, BinOpMetadata{
1456 .lhs = bin_op.lhs,1458 .lhs = bin_op.lhs,
...@@ -1512,8 +1514,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1512,8 +1514,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1512 // whether it needs to be spilled in the branches1514 // whether it needs to be spilled in the branches
1513 if (self.liveness.operandDies(inst, 0)) {1515 if (self.liveness.operandDies(inst, 0)) {
1514 const op_int = @enumToInt(pl_op.operand);1516 const op_int = @enumToInt(pl_op.operand);
1515 if (op_int >= Air.Inst.Ref.typed_value_map.len) {1517 if (op_int >= Air.ref_start_index) {
1516 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);1518 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
1517 self.processDeath(op_index);1519 self.processDeath(op_index);
1518 }1520 }
1519 }1521 }
...@@ -1603,7 +1605,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1603,7 +1605,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1603 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });1605 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });
1604 // TODO make sure the destination stack offset / register does not already have something1606 // TODO make sure the destination stack offset / register does not already have something
1605 // going on there.1607 // 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);
1607 // TODO track the new register / stack allocation1609 // TODO track the new register / stack allocation
1608 }1610 }
1609 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count());1611 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 {...@@ -1630,7 +1632,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1630 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });1632 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });
1631 // TODO make sure the destination stack offset / register does not already have something1633 // TODO make sure the destination stack offset / register does not already have something
1632 // going on there.1634 // 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);
1634 // TODO track the new register / stack allocation1636 // TODO track the new register / stack allocation
1635 }1637 }
16361638
...@@ -1656,8 +1658,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -1656,8 +1658,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
1656}1658}
16571659
1658fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1660fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1659 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1661 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1660 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;1662 const mod = self.bin_file.options.module.?;
1663 const function = mod.funcPtr(ty_fn.func);
1661 // TODO emit debug info for function change1664 // TODO emit debug info for function change
1662 _ = function;1665 _ = function;
1663 return self.finishAir(inst, .dead, .{ .none, .none, .none });1666 return self.finishAir(inst, .dead, .{ .none, .none, .none });
...@@ -1752,10 +1755,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1752,10 +1755,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1752 if (self.liveness.isUnused(inst))1755 if (self.liveness.isUnused(inst))
1753 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });1756 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);
1756 const operand = try self.resolveInst(ty_op.operand);1760 const operand = try self.resolveInst(ty_op.operand);
1757 const info_a = operand_ty.intInfo(self.target.*);1761 const info_a = operand_ty.intInfo(mod);
1758 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);1762 const info_b = self.typeOfIndex(inst).intInfo(mod);
1759 if (info_a.signedness != info_b.signedness)1763 if (info_a.signedness != info_b.signedness)
1760 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});1764 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 {...@@ -1777,7 +1781,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
1777 const un_op = self.air.instructions.items(.data)[inst].un_op;1781 const un_op = self.air.instructions.items(.data)[inst].un_op;
1778 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1782 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1779 const operand = try self.resolveInst(un_op);1783 const operand = try self.resolveInst(un_op);
1780 const ty = self.air.typeOf(un_op);1784 const ty = self.typeOf(un_op);
1781 break :result try self.isErr(ty, operand);1785 break :result try self.isErr(ty, operand);
1782 };1786 };
1783 return self.finishAir(inst, result, .{ un_op, .none, .none });1787 return self.finishAir(inst, result, .{ un_op, .none, .none });
...@@ -1787,7 +1791,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1787,7 +1791,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
1787 const un_op = self.air.instructions.items(.data)[inst].un_op;1791 const un_op = self.air.instructions.items(.data)[inst].un_op;
1788 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1792 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1789 const operand = try self.resolveInst(un_op);1793 const operand = try self.resolveInst(un_op);
1790 const ty = self.air.typeOf(un_op);1794 const ty = self.typeOf(un_op);
1791 break :result try self.isNonErr(ty, operand);1795 break :result try self.isNonErr(ty, operand);
1792 };1796 };
1793 return self.finishAir(inst, result, .{ un_op, .none, .none });1797 return self.finishAir(inst, result, .{ un_op, .none, .none });
...@@ -1812,15 +1816,16 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -1812,15 +1816,16 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
1812}1816}
18131817
1814fn airLoad(self: *Self, inst: Air.Inst.Index) !void {1818fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1819 const mod = self.bin_file.options.module.?;
1815 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1820 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1816 const elem_ty = self.air.typeOfIndex(inst);1821 const elem_ty = self.typeOfIndex(inst);
1817 const elem_size = elem_ty.abiSize(self.target.*);1822 const elem_size = elem_ty.abiSize(mod);
1818 const result: MCValue = result: {1823 const result: MCValue = result: {
1819 if (!elem_ty.hasRuntimeBits())1824 if (!elem_ty.hasRuntimeBits(mod))
1820 break :result MCValue.none;1825 break :result MCValue.none;
18211826
1822 const ptr = try self.resolveInst(ty_op.operand);1827 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);
1824 if (self.liveness.isUnused(inst) and !is_volatile)1829 if (self.liveness.isUnused(inst) and !is_volatile)
1825 break :result MCValue.dead;1830 break :result MCValue.dead;
18261831
...@@ -1835,7 +1840,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1835,7 +1840,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1835 break :blk try self.allocRegOrMem(inst, true);1840 break :blk try self.allocRegOrMem(inst, true);
1836 }1841 }
1837 };1842 };
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));
1839 break :result dst_mcv;1844 break :result dst_mcv;
1840 };1845 };
1841 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1846 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -1878,8 +1883,8 @@ fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {...@@ -1878,8 +1883,8 @@ fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {
1878 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1883 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1879 const lhs = try self.resolveInst(bin_op.lhs);1884 const lhs = try self.resolveInst(bin_op.lhs);
1880 const rhs = try self.resolveInst(bin_op.rhs);1885 const rhs = try self.resolveInst(bin_op.rhs);
1881 const lhs_ty = self.air.typeOf(bin_op.lhs);1886 const lhs_ty = self.typeOf(bin_op.lhs);
1882 const rhs_ty = self.air.typeOf(bin_op.rhs);1887 const rhs_ty = self.typeOf(bin_op.rhs);
18831888
1884 const result: MCValue = if (self.liveness.isUnused(inst))1889 const result: MCValue = if (self.liveness.isUnused(inst))
1885 .dead1890 .dead
...@@ -1893,8 +1898,8 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {...@@ -1893,8 +1898,8 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1893 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1898 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1894 const lhs = try self.resolveInst(bin_op.lhs);1899 const lhs = try self.resolveInst(bin_op.lhs);
1895 const rhs = try self.resolveInst(bin_op.rhs);1900 const rhs = try self.resolveInst(bin_op.rhs);
1896 const lhs_ty = self.air.typeOf(bin_op.lhs);1901 const lhs_ty = self.typeOf(bin_op.lhs);
1897 const rhs_ty = self.air.typeOf(bin_op.rhs);1902 const rhs_ty = self.typeOf(bin_op.rhs);
1898 assert(lhs_ty.eql(rhs_ty, self.bin_file.options.module.?));1903 assert(lhs_ty.eql(rhs_ty, self.bin_file.options.module.?));
18991904
1900 if (self.liveness.isUnused(inst))1905 if (self.liveness.isUnused(inst))
...@@ -2037,18 +2042,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2037,18 +2042,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2037 //const tag = self.air.instructions.items(.tag)[inst];2042 //const tag = self.air.instructions.items(.tag)[inst];
2038 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2043 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2039 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2044 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2045 const mod = self.bin_file.options.module.?;
2040 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2046 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2041 const lhs = try self.resolveInst(extra.lhs);2047 const lhs = try self.resolveInst(extra.lhs);
2042 const rhs = try self.resolveInst(extra.rhs);2048 const rhs = try self.resolveInst(extra.rhs);
2043 const lhs_ty = self.air.typeOf(extra.lhs);2049 const lhs_ty = self.typeOf(extra.lhs);
2044 const rhs_ty = self.air.typeOf(extra.rhs);2050 const rhs_ty = self.typeOf(extra.rhs);
20452051
2046 switch (lhs_ty.zigTypeTag()) {2052 switch (lhs_ty.zigTypeTag(mod)) {
2047 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),2053 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
2048 .Int => {2054 .Int => {
2049 const mod = self.bin_file.options.module.?;
2050 assert(lhs_ty.eql(rhs_ty, mod));2055 assert(lhs_ty.eql(rhs_ty, mod));
2051 const int_info = lhs_ty.intInfo(self.target.*);2056 const int_info = lhs_ty.intInfo(mod);
2052 switch (int_info.bits) {2057 switch (int_info.bits) {
2053 1...32 => {2058 1...32 => {
2054 try self.spillConditionFlagsIfOccupied();2059 try self.spillConditionFlagsIfOccupied();
...@@ -2101,9 +2106,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2101,9 +2106,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
21012106
2102fn airNot(self: *Self, inst: Air.Inst.Index) !void {2107fn airNot(self: *Self, inst: Air.Inst.Index) !void {
2103 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2108 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2109 const mod = self.bin_file.options.module.?;
2104 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2110 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2105 const operand = try self.resolveInst(ty_op.operand);2111 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);
2107 switch (operand) {2113 switch (operand) {
2108 .dead => unreachable,2114 .dead => unreachable,
2109 .unreach => unreachable,2115 .unreach => unreachable,
...@@ -2116,7 +2122,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -2116,7 +2122,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
2116 };2122 };
2117 },2123 },
2118 else => {2124 else => {
2119 switch (operand_ty.zigTypeTag()) {2125 switch (operand_ty.zigTypeTag(mod)) {
2120 .Bool => {2126 .Bool => {
2121 const op_reg = switch (operand) {2127 const op_reg = switch (operand) {
2122 .register => |r| r,2128 .register => |r| r,
...@@ -2150,7 +2156,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -2150,7 +2156,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
2150 },2156 },
2151 .Vector => return self.fail("TODO bitwise not for vectors", .{}),2157 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
2152 .Int => {2158 .Int => {
2153 const int_info = operand_ty.intInfo(self.target.*);2159 const int_info = operand_ty.intInfo(mod);
2154 if (int_info.bits <= 64) {2160 if (int_info.bits <= 64) {
2155 const op_reg = switch (operand) {2161 const op_reg = switch (operand) {
2156 .register => |r| r,2162 .register => |r| r,
...@@ -2280,8 +2286,8 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void {...@@ -2280,8 +2286,8 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void {
2280 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2286 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2281 const lhs = try self.resolveInst(bin_op.lhs);2287 const lhs = try self.resolveInst(bin_op.lhs);
2282 const rhs = try self.resolveInst(bin_op.rhs);2288 const rhs = try self.resolveInst(bin_op.rhs);
2283 const lhs_ty = self.air.typeOf(bin_op.lhs);2289 const lhs_ty = self.typeOf(bin_op.lhs);
2284 const rhs_ty = self.air.typeOf(bin_op.rhs);2290 const rhs_ty = self.typeOf(bin_op.rhs);
22852291
2286 // TODO add safety check2292 // TODO add safety check
22872293
...@@ -2332,16 +2338,17 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -2332,16 +2338,17 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
2332fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2338fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2333 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2339 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2334 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2340 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2341 const mod = self.bin_file.options.module.?;
2335 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2342 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2336 const lhs = try self.resolveInst(extra.lhs);2343 const lhs = try self.resolveInst(extra.lhs);
2337 const rhs = try self.resolveInst(extra.rhs);2344 const rhs = try self.resolveInst(extra.rhs);
2338 const lhs_ty = self.air.typeOf(extra.lhs);2345 const lhs_ty = self.typeOf(extra.lhs);
2339 const rhs_ty = self.air.typeOf(extra.rhs);2346 const rhs_ty = self.typeOf(extra.rhs);
23402347
2341 switch (lhs_ty.zigTypeTag()) {2348 switch (lhs_ty.zigTypeTag(mod)) {
2342 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),2349 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
2343 .Int => {2350 .Int => {
2344 const int_info = lhs_ty.intInfo(self.target.*);2351 const int_info = lhs_ty.intInfo(mod);
2345 if (int_info.bits <= 64) {2352 if (int_info.bits <= 64) {
2346 try self.spillConditionFlagsIfOccupied();2353 try self.spillConditionFlagsIfOccupied();
23472354
...@@ -2423,9 +2430,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -2423,9 +2430,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
2423 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2430 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2424 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2431 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2425 const ptr = try self.resolveInst(bin_op.lhs);2432 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);
2427 const len = try self.resolveInst(bin_op.rhs);2434 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
2430 const ptr_bits = self.target.ptrBitWidth();2437 const ptr_bits = self.target.ptrBitWidth();
2431 const ptr_bytes = @divExact(ptr_bits, 8);2438 const ptr_bytes = @divExact(ptr_bits, 8);
...@@ -2439,6 +2446,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -2439,6 +2446,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
2439}2446}
24402447
2441fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {2448fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2449 const mod = self.bin_file.options.module.?;
2442 const is_volatile = false; // TODO2450 const is_volatile = false; // TODO
2443 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2451 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 {...@@ -2447,12 +2455,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2447 const slice_mcv = try self.resolveInst(bin_op.lhs);2455 const slice_mcv = try self.resolveInst(bin_op.lhs);
2448 const index_mcv = try self.resolveInst(bin_op.rhs);2456 const index_mcv = try self.resolveInst(bin_op.rhs);
24492457
2450 const slice_ty = self.air.typeOf(bin_op.lhs);2458 const slice_ty = self.typeOf(bin_op.lhs);
2451 const elem_ty = slice_ty.childType();2459 const elem_ty = slice_ty.childType(mod);
2452 const elem_size = elem_ty.abiSize(self.target.*);2460 const elem_size = elem_ty.abiSize(mod);
24532461
2454 var buf: Type.SlicePtrFieldTypeBuffer = undefined;2462 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
2455 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
24562463
2457 const index_lock: ?RegisterLock = if (index_mcv == .register)2464 const index_lock: ?RegisterLock = if (index_mcv == .register)
2458 self.register_manager.lockRegAssumeUnused(index_mcv.register)2465 self.register_manager.lockRegAssumeUnused(index_mcv.register)
...@@ -2537,8 +2544,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -2537,8 +2544,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
2537 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2544 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2538 const ptr = try self.resolveInst(bin_op.lhs);2545 const ptr = try self.resolveInst(bin_op.lhs);
2539 const value = try self.resolveInst(bin_op.rhs);2546 const value = try self.resolveInst(bin_op.rhs);
2540 const ptr_ty = self.air.typeOf(bin_op.lhs);2547 const ptr_ty = self.typeOf(bin_op.lhs);
2541 const value_ty = self.air.typeOf(bin_op.rhs);2548 const value_ty = self.typeOf(bin_op.rhs);
25422549
2543 try self.store(ptr, value, ptr_ty, value_ty);2550 try self.store(ptr, value, ptr_ty, value_ty);
25442551
...@@ -2564,9 +2571,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2564,9 +2571,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2564 const operand = extra.struct_operand;2571 const operand = extra.struct_operand;
2565 const index = extra.field_index;2572 const index = extra.field_index;
2566 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2573 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2574 const mod = self.bin_file.options.module.?;
2567 const mcv = try self.resolveInst(operand);2575 const mcv = try self.resolveInst(operand);
2568 const struct_ty = self.air.typeOf(operand);2576 const struct_ty = self.typeOf(operand);
2569 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));2577 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
25702578
2571 switch (mcv) {2579 switch (mcv) {
2572 .dead, .unreach => unreachable,2580 .dead, .unreach => unreachable,
...@@ -2651,8 +2659,8 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {...@@ -2651,8 +2659,8 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
2651fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {2659fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2652 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2660 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2653 const operand = try self.resolveInst(ty_op.operand);2661 const operand = try self.resolveInst(ty_op.operand);
2654 const operand_ty = self.air.typeOf(ty_op.operand);2662 const operand_ty = self.typeOf(ty_op.operand);
2655 const dest_ty = self.air.typeOfIndex(inst);2663 const dest_ty = self.typeOfIndex(inst);
26562664
2657 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {2665 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
2658 break :blk try self.trunc(inst, operand, operand_ty, dest_ty);2666 break :blk try self.trunc(inst, operand, operand_ty, dest_ty);
...@@ -2666,7 +2674,7 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {...@@ -2666,7 +2674,7 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
2666 const extra = self.air.extraData(Air.Try, pl_op.payload);2674 const extra = self.air.extraData(Air.Try, pl_op.payload);
2667 const body = self.air.extra[extra.end..][0..extra.data.body_len];2675 const body = self.air.extra[extra.end..][0..extra.data.body_len];
2668 const result: MCValue = result: {2676 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);
2670 const error_union = try self.resolveInst(pl_op.operand);2678 const error_union = try self.resolveInst(pl_op.operand);
2671 const is_err_result = try self.isErr(error_union_ty, error_union);2679 const is_err_result = try self.isErr(error_union_ty, error_union);
2672 const reloc = try self.condBr(is_err_result);2680 const reloc = try self.condBr(is_err_result);
...@@ -2696,12 +2704,13 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -2696,12 +2704,13 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
2696}2704}
26972705
2698fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {2706fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2707 const mod = self.bin_file.options.module.?;
2699 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2708 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2700 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2709 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2701 const error_union_ty = self.air.typeOf(ty_op.operand);2710 const error_union_ty = self.typeOf(ty_op.operand);
2702 const payload_ty = error_union_ty.errorUnionPayload();2711 const payload_ty = error_union_ty.errorUnionPayload(mod);
2703 const mcv = try self.resolveInst(ty_op.operand);2712 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
2706 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});2715 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});
2707 };2716 };
...@@ -2709,11 +2718,12 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2709,11 +2718,12 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2709}2718}
27102719
2711fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {2720fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
2721 const mod = self.bin_file.options.module.?;
2712 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2722 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2713 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2723 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2714 const error_union_ty = self.air.typeOf(ty_op.operand);2724 const error_union_ty = self.typeOf(ty_op.operand);
2715 const payload_ty = error_union_ty.errorUnionPayload();2725 const payload_ty = error_union_ty.errorUnionPayload(mod);
2716 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;2726 if (!payload_ty.hasRuntimeBits(mod)) break :result MCValue.none;
27172727
2718 return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});2728 return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});
2719 };2729 };
...@@ -2722,12 +2732,13 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -2722,12 +2732,13 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
27222732
2723/// E to E!T2733/// E to E!T
2724fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {2734fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2735 const mod = self.bin_file.options.module.?;
2725 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2736 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2726 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2737 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2727 const error_union_ty = self.air.getRefType(ty_op.ty);2738 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);
2729 const mcv = try self.resolveInst(ty_op.operand);2740 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
2732 return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});2743 return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});
2733 };2744 };
...@@ -2742,12 +2753,13 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -2742,12 +2753,13 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2742}2753}
27432754
2744fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {2755fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2756 const mod = self.bin_file.options.module.?;
2745 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2757 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2746 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2758 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
2749 // Optional with a zero-bit payload type is just a boolean true2761 // 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)
2751 break :result MCValue{ .immediate = 1 };2763 break :result MCValue{ .immediate = 1 };
27522764
2753 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});2765 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...@@ -2782,9 +2794,10 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
27822794
2783/// Use a pointer instruction as the basis for allocating stack memory.2795/// Use a pointer instruction as the basis for allocating stack memory.
2784fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {2796fn 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)) {
2788 // As this stack item will never be dereferenced at runtime,2801 // As this stack item will never be dereferenced at runtime,
2789 // return the stack offset 0. Stack offset 0 will be where all2802 // return the stack offset 0. Stack offset 0 will be where all
2790 // zero-sized stack allocations live as non-zero-sized2803 // zero-sized stack allocations live as non-zero-sized
...@@ -2792,22 +2805,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -2792,22 +2805,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
2792 return @as(u32, 0);2805 return @as(u32, 0);
2793 }2806 }
27942807
2795 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {2808 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
2796 const mod = self.bin_file.options.module.?;
2797 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});2809 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
2798 };2810 };
2799 // TODO swap this for inst.ty.ptrAlign2811 // TODO swap this for inst.ty.ptrAlign
2800 const abi_align = elem_ty.abiAlignment(self.target.*);2812 const abi_align = elem_ty.abiAlignment(mod);
2801 return self.allocMem(inst, abi_size, abi_align);2813 return self.allocMem(inst, abi_size, abi_align);
2802}2814}
28032815
2804fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {2816fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
2805 const elem_ty = self.air.typeOfIndex(inst);2817 const mod = self.bin_file.options.module.?;
2806 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {2818 const elem_ty = self.typeOfIndex(inst);
2807 const mod = self.bin_file.options.module.?;2819 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
2808 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});2820 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
2809 };2821 };
2810 const abi_align = elem_ty.abiAlignment(self.target.*);2822 const abi_align = elem_ty.abiAlignment(mod);
2811 if (abi_align > self.stack_align)2823 if (abi_align > self.stack_align)
2812 self.stack_align = abi_align;2824 self.stack_align = abi_align;
28132825
...@@ -2860,12 +2872,12 @@ fn binOp(...@@ -2860,12 +2872,12 @@ fn binOp(
2860 .xor,2872 .xor,
2861 .cmp_eq,2873 .cmp_eq,
2862 => {2874 => {
2863 switch (lhs_ty.zigTypeTag()) {2875 switch (lhs_ty.zigTypeTag(mod)) {
2864 .Float => return self.fail("TODO binary operations on floats", .{}),2876 .Float => return self.fail("TODO binary operations on floats", .{}),
2865 .Vector => return self.fail("TODO binary operations on vectors", .{}),2877 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2866 .Int => {2878 .Int => {
2867 assert(lhs_ty.eql(rhs_ty, mod));2879 assert(lhs_ty.eql(rhs_ty, mod));
2868 const int_info = lhs_ty.intInfo(self.target.*);2880 const int_info = lhs_ty.intInfo(mod);
2869 if (int_info.bits <= 64) {2881 if (int_info.bits <= 64) {
2870 // Only say yes if the operation is2882 // Only say yes if the operation is
2871 // commutative, i.e. we can swap both of the2883 // commutative, i.e. we can swap both of the
...@@ -2934,10 +2946,10 @@ fn binOp(...@@ -2934,10 +2946,10 @@ fn binOp(
2934 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);2946 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
29352947
2936 // Truncate if necessary2948 // Truncate if necessary
2937 switch (lhs_ty.zigTypeTag()) {2949 switch (lhs_ty.zigTypeTag(mod)) {
2938 .Vector => return self.fail("TODO binary operations on vectors", .{}),2950 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2939 .Int => {2951 .Int => {
2940 const int_info = lhs_ty.intInfo(self.target.*);2952 const int_info = lhs_ty.intInfo(mod);
2941 if (int_info.bits <= 64) {2953 if (int_info.bits <= 64) {
2942 const result_reg = result.register;2954 const result_reg = result.register;
2943 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);2955 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
...@@ -2951,11 +2963,11 @@ fn binOp(...@@ -2951,11 +2963,11 @@ fn binOp(
2951 },2963 },
29522964
2953 .div_trunc => {2965 .div_trunc => {
2954 switch (lhs_ty.zigTypeTag()) {2966 switch (lhs_ty.zigTypeTag(mod)) {
2955 .Vector => return self.fail("TODO binary operations on vectors", .{}),2967 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2956 .Int => {2968 .Int => {
2957 assert(lhs_ty.eql(rhs_ty, mod));2969 assert(lhs_ty.eql(rhs_ty, mod));
2958 const int_info = lhs_ty.intInfo(self.target.*);2970 const int_info = lhs_ty.intInfo(mod);
2959 if (int_info.bits <= 64) {2971 if (int_info.bits <= 64) {
2960 const rhs_immediate_ok = switch (tag) {2972 const rhs_immediate_ok = switch (tag) {
2961 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),2973 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
...@@ -2984,14 +2996,14 @@ fn binOp(...@@ -2984,14 +2996,14 @@ fn binOp(
2984 },2996 },
29852997
2986 .ptr_add => {2998 .ptr_add => {
2987 switch (lhs_ty.zigTypeTag()) {2999 switch (lhs_ty.zigTypeTag(mod)) {
2988 .Pointer => {3000 .Pointer => {
2989 const ptr_ty = lhs_ty;3001 const ptr_ty = lhs_ty;
2990 const elem_ty = switch (ptr_ty.ptrSize()) {3002 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
2991 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type3003 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
2992 else => ptr_ty.childType(),3004 else => ptr_ty.childType(mod),
2993 };3005 };
2994 const elem_size = elem_ty.abiSize(self.target.*);3006 const elem_size = elem_ty.abiSize(mod);
29953007
2996 if (elem_size == 1) {3008 if (elem_size == 1) {
2997 const base_tag: Mir.Inst.Tag = switch (tag) {3009 const base_tag: Mir.Inst.Tag = switch (tag) {
...@@ -3005,7 +3017,7 @@ fn binOp(...@@ -3005,7 +3017,7 @@ fn binOp(
3005 // multiplying it with elem_size3017 // multiplying it with elem_size
30063018
3007 const offset = try self.binOp(.mul, rhs, .{ .immediate = elem_size }, Type.usize, Type.usize, null);3019 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);
3009 return addr;3021 return addr;
3010 }3022 }
3011 },3023 },
...@@ -3016,7 +3028,7 @@ fn binOp(...@@ -3016,7 +3028,7 @@ fn binOp(
3016 .bool_and,3028 .bool_and,
3017 .bool_or,3029 .bool_or,
3018 => {3030 => {
3019 switch (lhs_ty.zigTypeTag()) {3031 switch (lhs_ty.zigTypeTag(mod)) {
3020 .Bool => {3032 .Bool => {
3021 assert(lhs != .immediate); // should have been handled by Sema3033 assert(lhs != .immediate); // should have been handled by Sema
3022 assert(rhs != .immediate); // should have been handled by Sema3034 assert(rhs != .immediate); // should have been handled by Sema
...@@ -3046,10 +3058,10 @@ fn binOp(...@@ -3046,10 +3058,10 @@ fn binOp(
3046 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);3058 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
30473059
3048 // Truncate if necessary3060 // Truncate if necessary
3049 switch (lhs_ty.zigTypeTag()) {3061 switch (lhs_ty.zigTypeTag(mod)) {
3050 .Vector => return self.fail("TODO binary operations on vectors", .{}),3062 .Vector => return self.fail("TODO binary operations on vectors", .{}),
3051 .Int => {3063 .Int => {
3052 const int_info = lhs_ty.intInfo(self.target.*);3064 const int_info = lhs_ty.intInfo(mod);
3053 if (int_info.bits <= 64) {3065 if (int_info.bits <= 64) {
3054 // 32 and 64 bit operands doesn't need truncating3066 // 32 and 64 bit operands doesn't need truncating
3055 if (int_info.bits == 32 or int_info.bits == 64) return result;3067 if (int_info.bits == 32 or int_info.bits == 64) return result;
...@@ -3068,10 +3080,10 @@ fn binOp(...@@ -3068,10 +3080,10 @@ fn binOp(
3068 .shl_exact,3080 .shl_exact,
3069 .shr_exact,3081 .shr_exact,
3070 => {3082 => {
3071 switch (lhs_ty.zigTypeTag()) {3083 switch (lhs_ty.zigTypeTag(mod)) {
3072 .Vector => return self.fail("TODO binary operations on vectors", .{}),3084 .Vector => return self.fail("TODO binary operations on vectors", .{}),
3073 .Int => {3085 .Int => {
3074 const int_info = lhs_ty.intInfo(self.target.*);3086 const int_info = lhs_ty.intInfo(mod);
3075 if (int_info.bits <= 64) {3087 if (int_info.bits <= 64) {
3076 const rhs_immediate_ok = rhs == .immediate;3088 const rhs_immediate_ok = rhs == .immediate;
30773089
...@@ -3393,7 +3405,8 @@ fn binOpRegister(...@@ -3393,7 +3405,8 @@ fn binOpRegister(
3393fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {3405fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
3394 const block_data = self.blocks.getPtr(block).?;3406 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)) {
3397 const operand_mcv = try self.resolveInst(operand);3410 const operand_mcv = try self.resolveInst(operand);
3398 const block_mcv = block_data.mcv;3411 const block_mcv = block_data.mcv;
3399 if (block_mcv == .none) {3412 if (block_mcv == .none) {
...@@ -3402,13 +3415,13 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -3402,13 +3415,13 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
3402 .register, .stack_offset, .memory => operand_mcv,3415 .register, .stack_offset, .memory => operand_mcv,
3403 .immediate => blk: {3416 .immediate => blk: {
3404 const new_mcv = try self.allocRegOrMem(block, true);3417 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);
3406 break :blk new_mcv;3419 break :blk new_mcv;
3407 },3420 },
3408 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),3421 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
3409 };3422 };
3410 } else {3423 } else {
3411 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);3424 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
3412 }3425 }
3413 }3426 }
3414 return self.brVoid(block);3427 return self.brVoid(block);
...@@ -3512,16 +3525,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {...@@ -3512,16 +3525,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
35123525
3513/// Given an error union, returns the payload3526/// Given an error union, returns the payload
3514fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {3527fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
3515 const err_ty = error_union_ty.errorUnionSet();3528 const mod = self.bin_file.options.module.?;
3516 const payload_ty = error_union_ty.errorUnionPayload();3529 const err_ty = error_union_ty.errorUnionSet(mod);
3517 if (err_ty.errorSetIsEmpty()) {3530 const payload_ty = error_union_ty.errorUnionPayload(mod);
3531 if (err_ty.errorSetIsEmpty(mod)) {
3518 return error_union_mcv;3532 return error_union_mcv;
3519 }3533 }
3520 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3534 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3521 return MCValue.none;3535 return MCValue.none;
3522 }3536 }
35233537
3524 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));3538 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
3525 switch (error_union_mcv) {3539 switch (error_union_mcv) {
3526 .register => return self.fail("TODO errUnionPayload for registers", .{}),3540 .register => return self.fail("TODO errUnionPayload for registers", .{}),
3527 .stack_offset => |off| {3541 .stack_offset => |off| {
...@@ -3555,8 +3569,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -3555,8 +3569,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
3555 tomb_bits >>= 1;3569 tomb_bits >>= 1;
3556 if (!dies) continue;3570 if (!dies) continue;
3557 const op_int = @enumToInt(op);3571 const op_int = @enumToInt(op);
3558 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;3572 if (op_int < Air.ref_start_index) continue;
3559 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);3573 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
3560 self.processDeath(op_index);3574 self.processDeath(op_index);
3561 }3575 }
3562 const is_used = @truncate(u1, tomb_bits) == 0;3576 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...@@ -3730,6 +3744,7 @@ fn genLoadASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Reg
3730}3744}
37313745
3732fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {3746fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
3747 const mod = self.bin_file.options.module.?;
3733 switch (mcv) {3748 switch (mcv) {
3734 .dead => unreachable,3749 .dead => unreachable,
3735 .unreach, .none => return, // Nothing to do.3750 .unreach, .none => return, // Nothing to do.
...@@ -3928,19 +3943,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3928,19 +3943,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3928 // The value is in memory at a hard-coded address.3943 // The value is in memory at a hard-coded address.
3929 // If the type is a pointer, it means the pointer address is at this memory location.3944 // If the type is a pointer, it means the pointer address is at this memory location.
3930 try self.genSetReg(ty, reg, .{ .immediate = addr });3945 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));
3932 },3947 },
3933 .stack_offset => |off| {3948 .stack_offset => |off| {
3934 const real_offset = realStackOffset(off);3949 const real_offset = realStackOffset(off);
3935 const simm13 = math.cast(i13, real_offset) orelse3950 const simm13 = math.cast(i13, real_offset) orelse
3936 return self.fail("TODO larger stack offsets: {}", .{real_offset});3951 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));
3938 },3953 },
3939 }3954 }
3940}3955}
39413956
3942fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {3957fn 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);
3944 switch (mcv) {3960 switch (mcv) {
3945 .dead => unreachable,3961 .dead => unreachable,
3946 .unreach, .none => return, // Nothing to do.3962 .unreach, .none => return, // Nothing to do.
...@@ -3948,7 +3964,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3948,7 +3964,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3948 if (!self.wantSafety())3964 if (!self.wantSafety())
3949 return; // The already existing value will do just fine.3965 return; // The already existing value will do just fine.
3950 // TODO Upgrade this to a memset call when we have that available.3966 // TODO Upgrade this to a memset call when we have that available.
3951 switch (ty.abiSize(self.target.*)) {3967 switch (ty.abiSize(mod)) {
3952 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),3968 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
3953 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),3969 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
3954 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),3970 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...@@ -3974,11 +3990,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3974 const reg_lock = self.register_manager.lockReg(rwo.reg);3990 const reg_lock = self.register_manager.lockReg(rwo.reg);
3975 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);3991 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);
3978 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });3994 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });
39793995
3980 const overflow_bit_ty = ty.structFieldType(1);3996 const overflow_bit_ty = ty.structFieldType(1, mod);
3981 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));3997 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
3982 const cond_reg = try self.register_manager.allocReg(null, gp);3998 const cond_reg = try self.register_manager.allocReg(null, gp);
39833999
3984 // TODO handle floating point CCRs4000 // TODO handle floating point CCRs
...@@ -4024,11 +4040,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4024,11 +4040,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4024 const reg = try self.copyToTmpRegister(ty, mcv);4040 const reg = try self.copyToTmpRegister(ty, mcv);
4025 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });4041 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
4026 } else {4042 } else {
4027 var ptr_ty_payload: Type.Payload.ElemType = .{4043 const ptr_ty = try mod.singleMutPtrType(ty);
4028 .base = .{ .tag = .single_mut_pointer },
4029 .data = ty,
4030 };
4031 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
40324044
4033 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, gp);4045 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, gp);
4034 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);4046 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
...@@ -4152,13 +4164,14 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -4152,13 +4164,14 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
4152}4164}
41534165
4154fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {4166fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
4155 const error_type = ty.errorUnionSet();4167 const mod = self.bin_file.options.module.?;
4156 const payload_type = ty.errorUnionPayload();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)) {
4159 return MCValue{ .immediate = 0 }; // always false4172 return MCValue{ .immediate = 0 }; // always false
4160 } else if (!payload_type.hasRuntimeBits()) {4173 } else if (!payload_type.hasRuntimeBits(mod)) {
4161 if (error_type.abiSize(self.target.*) <= 8) {4174 if (error_type.abiSize(mod) <= 8) {
4162 const reg_mcv: MCValue = switch (operand) {4175 const reg_mcv: MCValue = switch (operand) {
4163 .register => operand,4176 .register => operand,
4164 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },4177 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },
...@@ -4249,8 +4262,9 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void {...@@ -4249,8 +4262,9 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void {
4249}4262}
42504263
4251fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {4264fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
4252 const elem_ty = ptr_ty.elemType();4265 const mod = self.bin_file.options.module.?;
4253 const elem_size = elem_ty.abiSize(self.target.*);4266 const elem_ty = ptr_ty.childType(mod);
4267 const elem_size = elem_ty.abiSize(mod);
42544268
4255 switch (ptr) {4269 switch (ptr) {
4256 .none => unreachable,4270 .none => unreachable,
...@@ -4321,11 +4335,11 @@ fn minMax(...@@ -4321,11 +4335,11 @@ fn minMax(
4321) InnerError!MCValue {4335) InnerError!MCValue {
4322 const mod = self.bin_file.options.module.?;4336 const mod = self.bin_file.options.module.?;
4323 assert(lhs_ty.eql(rhs_ty, mod));4337 assert(lhs_ty.eql(rhs_ty, mod));
4324 switch (lhs_ty.zigTypeTag()) {4338 switch (lhs_ty.zigTypeTag(mod)) {
4325 .Float => return self.fail("TODO min/max on floats", .{}),4339 .Float => return self.fail("TODO min/max on floats", .{}),
4326 .Vector => return self.fail("TODO min/max on vectors", .{}),4340 .Vector => return self.fail("TODO min/max on vectors", .{}),
4327 .Int => {4341 .Int => {
4328 const int_info = lhs_ty.intInfo(self.target.*);4342 const int_info = lhs_ty.intInfo(mod);
4329 if (int_info.bits <= 64) {4343 if (int_info.bits <= 64) {
4330 // TODO skip register setting when one of the operands4344 // TODO skip register setting when one of the operands
4331 // is a small (fits in i13) immediate.4345 // is a small (fits in i13) immediate.
...@@ -4406,8 +4420,7 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {...@@ -4406,8 +4420,7 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
44064420
4407/// Asserts there is already capacity to insert into top branch inst_table.4421/// Asserts there is already capacity to insert into top branch inst_table.
4408fn processDeath(self: *Self, inst: Air.Inst.Index) void {4422fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4409 const air_tags = self.air.instructions.items(.tag);4423 assert(self.air.instructions.items(.tag)[inst] != .interned);
4410 if (air_tags[inst] == .constant) return; // Constants are immortal.
4411 // When editing this function, note that the logic must synchronize with `reuseOperand`.4424 // When editing this function, note that the logic must synchronize with `reuseOperand`.
4412 const prev_value = self.getResolvedInstValue(inst);4425 const prev_value = self.getResolvedInstValue(inst);
4413 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];4426 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
...@@ -4441,12 +4454,11 @@ fn realStackOffset(off: u32) u32 {...@@ -4441,12 +4454,11 @@ fn realStackOffset(off: u32) u32 {
44414454
4442/// Caller must call `CallMCValues.deinit`.4455/// Caller must call `CallMCValues.deinit`.
4443fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {4456fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
4444 const cc = fn_ty.fnCallingConvention();4457 const mod = self.bin_file.options.module.?;
4445 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());4458 const fn_info = mod.typeToFunc(fn_ty).?;
4446 defer self.gpa.free(param_types);4459 const cc = fn_info.cc;
4447 fn_ty.fnParamTypes(param_types);
4448 var result: CallMCValues = .{4460 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),
4450 // These undefined values must be populated before returning from this function.4462 // These undefined values must be populated before returning from this function.
4451 .return_value = undefined,4463 .return_value = undefined,
4452 .stack_byte_count = undefined,4464 .stack_byte_count = undefined,
...@@ -4454,7 +4466,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4454,7 +4466,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4454 };4466 };
4455 errdefer self.gpa.free(result.args);4467 errdefer self.gpa.free(result.args);
44564468
4457 const ret_ty = fn_ty.fnReturnType();4469 const ret_ty = fn_ty.fnReturnType(mod);
44584470
4459 switch (cc) {4471 switch (cc) {
4460 .Naked => {4472 .Naked => {
...@@ -4477,8 +4489,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4477,8 +4489,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4477 .callee => abi.c_abi_int_param_regs_callee_view,4489 .callee => abi.c_abi_int_param_regs_callee_view,
4478 };4490 };
44794491
4480 for (param_types, 0..) |ty, i| {4492 for (fn_info.param_types, 0..) |ty, i| {
4481 const param_size = @intCast(u32, ty.abiSize(self.target.*));4493 const param_size = @intCast(u32, ty.toType().abiSize(mod));
4482 if (param_size <= 8) {4494 if (param_size <= 8) {
4483 if (next_register < argument_registers.len) {4495 if (next_register < argument_registers.len) {
4484 result.args[i] = .{ .register = argument_registers[next_register] };4496 result.args[i] = .{ .register = argument_registers[next_register] };
...@@ -4505,12 +4517,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4505,12 +4517,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4505 result.stack_byte_count = next_stack_offset;4517 result.stack_byte_count = next_stack_offset;
4506 result.stack_align = 16;4518 result.stack_align = 16;
45074519
4508 if (ret_ty.zigTypeTag() == .NoReturn) {4520 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
4509 result.return_value = .{ .unreach = {} };4521 result.return_value = .{ .unreach = {} };
4510 } else if (!ret_ty.hasRuntimeBits()) {4522 } else if (!ret_ty.hasRuntimeBits(mod)) {
4511 result.return_value = .{ .none = {} };4523 result.return_value = .{ .none = {} };
4512 } else {4524 } else {
4513 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));4525 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
4514 // The callee puts the return values in %i0-%i3, which becomes %o0-%o3 inside the caller.4526 // The callee puts the return values in %i0-%i3, which becomes %o0-%o3 inside the caller.
4515 if (ret_ty_size <= 8) {4527 if (ret_ty_size <= 8) {
4516 result.return_value = switch (role) {4528 result.return_value = switch (role) {
...@@ -4528,44 +4540,41 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4528,44 +4540,41 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4528 return result;4540 return result;
4529}4541}
45304542
4531fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {4543fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
4532 // First section of indexes correspond to a set number of constant values.4544 const mod = self.bin_file.options.module.?;
4533 const ref_int = @enumToInt(inst);4545 const ty = self.typeOf(ref);
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 }
45414546
4542 // If the type has no codegen bits, no need to store it.4547 // If the type has no codegen bits, no need to store it.
4543 const inst_ty = self.air.typeOf(inst);4548 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;
4544 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())4549
4545 return MCValue{ .none = {} };4550 if (Air.refToIndex(ref)) |inst| {
45464551 switch (self.air.instructions.items(.tag)[inst]) {
4547 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);4552 .interned => {
4548 switch (self.air.instructions.items(.tag)[inst_index]) {4553 // Constants have static lifetimes, so they are always memoized in the outer most table.
4549 .constant => {4554 const branch = &self.branch_stack.items[0];
4550 // Constants have static lifetimes, so they are always memoized in the outer most table.4555 const gop = try branch.inst_table.getOrPut(self.gpa, inst);
4551 const branch = &self.branch_stack.items[0];4556 if (!gop.found_existing) {
4552 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);4557 const interned = self.air.instructions.items(.data)[inst].interned;
4553 if (!gop.found_existing) {4558 gop.value_ptr.* = try self.genTypedValue(.{
4554 const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl;4559 .ty = ty,
4555 gop.value_ptr.* = try self.genTypedValue(.{4560 .val = interned.toValue(),
4556 .ty = inst_ty,4561 });
4557 .val = self.air.values[ty_pl.payload],4562 }
4558 });4563 return gop.value_ptr.*;
4559 }4564 },
4560 return gop.value_ptr.*;4565 else => return self.getResolvedInstValue(inst),
4561 },4566 }
4562 .const_ty => unreachable,
4563 else => return self.getResolvedInstValue(inst_index),
4564 }4567 }
4568
4569 return self.genTypedValue(.{
4570 .ty = ty,
4571 .val = (try self.air.value(ref, mod)).?,
4572 });
4565}4573}
45664574
4567fn ret(self: *Self, mcv: MCValue) !void {4575fn 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);
4569 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);4578 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
45704579
4571 // Just add space for a branch instruction, patch this later4580 // Just add space for a branch instruction, patch this later
...@@ -4638,7 +4647,7 @@ fn spillConditionFlagsIfOccupied(self: *Self) !void {...@@ -4638,7 +4647,7 @@ fn spillConditionFlagsIfOccupied(self: *Self) !void {
4638 else => unreachable, // mcv doesn't occupy the compare flags4647 else => unreachable, // mcv doesn't occupy the compare flags
4639 };4648 };
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);
4642 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });4651 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
46434652
4644 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];4653 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...@@ -4662,11 +4671,12 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
4662 assert(reg == reg_mcv.register);4671 assert(reg == reg_mcv.register);
4663 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];4672 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
4664 try branch.inst_table.put(self.gpa, inst, stack_mcv);4673 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);
4666}4675}
46674676
4668fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {4677fn 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
4671 switch (ptr) {4681 switch (ptr) {
4672 .none => unreachable,4682 .none => unreachable,
...@@ -4707,10 +4717,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -4707,10 +4717,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
47074717
4708fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {4718fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
4709 return if (self.liveness.isUnused(inst)) .dead else result: {4719 return if (self.liveness.isUnused(inst)) .dead else result: {
4720 const mod = self.bin_file.options.module.?;
4710 const mcv = try self.resolveInst(operand);4721 const mcv = try self.resolveInst(operand);
4711 const ptr_ty = self.air.typeOf(operand);4722 const ptr_ty = self.typeOf(operand);
4712 const struct_ty = ptr_ty.childType();4723 const struct_ty = ptr_ty.childType(mod);
4713 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));4724 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
4714 switch (mcv) {4725 switch (mcv) {
4715 .ptr_stack_offset => |off| {4726 .ptr_stack_offset => |off| {
4716 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };4727 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };
...@@ -4748,8 +4759,9 @@ fn trunc(...@@ -4748,8 +4759,9 @@ fn trunc(
4748 operand_ty: Type,4759 operand_ty: Type,
4749 dest_ty: Type,4760 dest_ty: Type,
4750) !MCValue {4761) !MCValue {
4751 const info_a = operand_ty.intInfo(self.target.*);4762 const mod = self.bin_file.options.module.?;
4752 const info_b = dest_ty.intInfo(self.target.*);4763 const info_a = operand_ty.intInfo(mod);
4764 const info_b = dest_ty.intInfo(mod);
47534765
4754 if (info_b.bits <= 64) {4766 if (info_b.bits <= 64) {
4755 const operand_reg = switch (operand) {4767 const operand_reg = switch (operand) {
...@@ -4866,3 +4878,13 @@ fn wantSafety(self: *Self) bool {...@@ -4866,3 +4878,13 @@ fn wantSafety(self: *Self) bool {
4866 .ReleaseSmall => false,4878 .ReleaseSmall => false,
4867 };4879 };
4868}4880}
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);...@@ -11,6 +11,7 @@ const log = std.log.scoped(.codegen);
1111
12const codegen = @import("../../codegen.zig");12const codegen = @import("../../codegen.zig");
13const Module = @import("../../Module.zig");13const Module = @import("../../Module.zig");
14const InternPool = @import("../../InternPool.zig");
14const Decl = Module.Decl;15const Decl = Module.Decl;
15const Type = @import("../../type.zig").Type;16const Type = @import("../../type.zig").Type;
16const Value = @import("../../value.zig").Value;17const Value = @import("../../value.zig").Value;
...@@ -764,8 +765,9 @@ pub fn deinit(func: *CodeGen) void {...@@ -764,8 +765,9 @@ pub fn deinit(func: *CodeGen) void {
764765
765/// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig766/// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig
766fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError {767fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError {
768 const mod = func.bin_file.base.options.module.?;
767 const src = LazySrcLoc.nodeOffset(0);769 const src = LazySrcLoc.nodeOffset(0);
768 const src_loc = src.toSrcLoc(func.decl);770 const src_loc = src.toSrcLoc(func.decl, mod);
769 func.err_msg = try Module.ErrorMsg.create(func.gpa, src_loc, fmt, args);771 func.err_msg = try Module.ErrorMsg.create(func.gpa, src_loc, fmt, args);
770 return error.CodegenFail;772 return error.CodegenFail;
771}773}
...@@ -788,9 +790,10 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {...@@ -788,9 +790,10 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
788 const gop = try func.branches.items[0].values.getOrPut(func.gpa, ref);790 const gop = try func.branches.items[0].values.getOrPut(func.gpa, ref);
789 assert(!gop.found_existing);791 assert(!gop.found_existing);
790792
791 const val = func.air.value(ref).?;793 const mod = func.bin_file.base.options.module.?;
792 const ty = func.air.typeOf(ref);794 const val = (try func.air.value(ref, mod)).?;
793 if (!ty.hasRuntimeBitsIgnoreComptime() and !ty.isInt() and !ty.isError()) {795 const ty = func.typeOf(ref);
796 if (!ty.hasRuntimeBitsIgnoreComptime(mod) and !ty.isInt(mod) and !ty.isError(mod)) {
794 gop.value_ptr.* = WValue{ .none = {} };797 gop.value_ptr.* = WValue{ .none = {} };
795 return gop.value_ptr.*;798 return gop.value_ptr.*;
796 }799 }
...@@ -801,7 +804,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {...@@ -801,7 +804,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
801 //804 //
802 // In the other cases, we will simply lower the constant to a value that fits805 // In the other cases, we will simply lower the constant to a value that fits
803 // into a single local (such as a pointer, integer, bool, etc).806 // 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: {
805 const sym_index = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, func.decl_index);808 const sym_index = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, func.decl_index);
806 break :blk WValue{ .memory = sym_index };809 break :blk WValue{ .memory = sym_index };
807 } else try func.lowerConstant(val, ty);810 } else try func.lowerConstant(val, ty);
...@@ -880,7 +883,7 @@ fn iterateBigTomb(func: *CodeGen, inst: Air.Inst.Index, operand_count: usize) !B...@@ -880,7 +883,7 @@ fn iterateBigTomb(func: *CodeGen, inst: Air.Inst.Index, operand_count: usize) !B
880883
881fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void {884fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void {
882 const inst = Air.refToIndex(ref) orelse return;885 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);
884 // Branches are currently only allowed to free locals allocated887 // Branches are currently only allowed to free locals allocated
885 // within their own branch.888 // within their own branch.
886 // TODO: Upon branch consolidation free any locals if needed.889 // TODO: Upon branch consolidation free any locals if needed.
...@@ -987,8 +990,9 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32...@@ -987,8 +990,9 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32
987}990}
988991
989/// Using a given `Type`, returns the corresponding type992/// Using a given `Type`, returns the corresponding type
990fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {993fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {
991 return switch (ty.zigTypeTag()) {994 const target = mod.getTarget();
995 return switch (ty.zigTypeTag(mod)) {
992 .Float => blk: {996 .Float => blk: {
993 const bits = ty.floatBits(target);997 const bits = ty.floatBits(target);
994 if (bits == 16) return wasm.Valtype.i32; // stored/loaded as u16998 if (bits == 16) return wasm.Valtype.i32; // stored/loaded as u16
...@@ -998,30 +1002,26 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {...@@ -998,30 +1002,26 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
998 return wasm.Valtype.i32; // represented as pointer to stack1002 return wasm.Valtype.i32; // represented as pointer to stack
999 },1003 },
1000 .Int, .Enum => blk: {1004 .Int, .Enum => blk: {
1001 const info = ty.intInfo(target);1005 const info = ty.intInfo(mod);
1002 if (info.bits <= 32) break :blk wasm.Valtype.i32;1006 if (info.bits <= 32) break :blk wasm.Valtype.i32;
1003 if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64;1007 if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64;
1004 break :blk wasm.Valtype.i32; // represented as pointer to stack1008 break :blk wasm.Valtype.i32; // represented as pointer to stack
1005 },1009 },
1006 .Struct => switch (ty.containerLayout()) {1010 .Struct => switch (ty.containerLayout(mod)) {
1007 .Packed => {1011 .Packed => {
1008 const struct_obj = ty.castTag(.@"struct").?.data;1012 const struct_obj = mod.typeToStruct(ty).?;
1009 return typeToValtype(struct_obj.backing_int_ty, target);1013 return typeToValtype(struct_obj.backing_int_ty, mod);
1010 },1014 },
1011 else => wasm.Valtype.i32,1015 else => wasm.Valtype.i32,
1012 },1016 },
1013 .Vector => switch (determineSimdStoreStrategy(ty, target)) {1017 .Vector => switch (determineSimdStoreStrategy(ty, mod)) {
1014 .direct => wasm.Valtype.v128,1018 .direct => wasm.Valtype.v128,
1015 .unrolled => wasm.Valtype.i32,1019 .unrolled => wasm.Valtype.i32,
1016 },1020 },
1017 .Union => switch (ty.containerLayout()) {1021 .Union => switch (ty.containerLayout(mod)) {
1018 .Packed => {1022 .Packed => {
1019 var int_ty_payload: Type.Payload.Bits = .{1023 const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory");
1020 .base = .{ .tag = .int_unsigned },1024 return typeToValtype(int_ty, mod);
1021 .data = @intCast(u16, ty.bitSize(target)),
1022 };
1023 const int_ty = Type.initPayload(&int_ty_payload.base);
1024 return typeToValtype(int_ty, target);
1025 },1025 },
1026 else => wasm.Valtype.i32,1026 else => wasm.Valtype.i32,
1027 },1027 },
...@@ -1030,17 +1030,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {...@@ -1030,17 +1030,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
1030}1030}
10311031
1032/// Using a given `Type`, returns the byte representation of its wasm value type1032/// Using a given `Type`, returns the byte representation of its wasm value type
1033fn genValtype(ty: Type, target: std.Target) u8 {1033fn genValtype(ty: Type, mod: *Module) u8 {
1034 return wasm.valtype(typeToValtype(ty, target));1034 return wasm.valtype(typeToValtype(ty, mod));
1035}1035}
10361036
1037/// Using a given `Type`, returns the corresponding wasm value type1037/// Using a given `Type`, returns the corresponding wasm value type
1038/// Differently from `genValtype` this also allows `void` to create a block1038/// Differently from `genValtype` this also allows `void` to create a block
1039/// with no return type1039/// with no return type
1040fn genBlockType(ty: Type, target: std.Target) u8 {1040fn genBlockType(ty: Type, mod: *Module) u8 {
1041 return switch (ty.tag()) {1041 return switch (ty.ip_index) {
1042 .void, .noreturn => wasm.block_empty,1042 .void_type, .noreturn_type => wasm.block_empty,
1043 else => genValtype(ty, target),1043 else => genValtype(ty, mod),
1044 };1044 };
1045}1045}
10461046
...@@ -1101,7 +1101,8 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue {...@@ -1101,7 +1101,8 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue {
1101/// Creates one locals for a given `Type`.1101/// Creates one locals for a given `Type`.
1102/// Returns a corresponding `Wvalue` with `local` as active tag1102/// Returns a corresponding `Wvalue` with `local` as active tag
1103fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {1103fn 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);
1105 switch (valtype) {1106 switch (valtype) {
1106 .i32 => if (func.free_locals_i32.popOrNull()) |index| {1107 .i32 => if (func.free_locals_i32.popOrNull()) |index| {
1107 log.debug("reusing local ({d}) of type {}", .{ index, valtype });1108 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
...@@ -1132,7 +1133,8 @@ fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -1132,7 +1133,8 @@ fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
1132/// Ensures a new local will be created. This is useful when it's useful1133/// Ensures a new local will be created. This is useful when it's useful
1133/// to use a zero-initialized local.1134/// to use a zero-initialized local.
1134fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {1135fn 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));
1136 const initial_index = func.local_index;1138 const initial_index = func.local_index;
1137 func.local_index += 1;1139 func.local_index += 1;
1138 return WValue{ .local = .{ .value = initial_index, .references = 1 } };1140 return WValue{ .local = .{ .value = initial_index, .references = 1 } };
...@@ -1140,48 +1142,55 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -1140,48 +1142,55 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
11401142
1141/// Generates a `wasm.Type` from a given function type.1143/// Generates a `wasm.Type` from a given function type.
1142/// Memory is owned by the caller.1144/// 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 {
1144 var temp_params = std.ArrayList(wasm.Valtype).init(gpa);1152 var temp_params = std.ArrayList(wasm.Valtype).init(gpa);
1145 defer temp_params.deinit();1153 defer temp_params.deinit();
1146 var returns = std.ArrayList(wasm.Valtype).init(gpa);1154 var returns = std.ArrayList(wasm.Valtype).init(gpa);
1147 defer returns.deinit();1155 defer returns.deinit();
11481156
1149 if (firstParamSRet(cc, return_type, target)) {1157 if (firstParamSRet(cc, return_type, mod)) {
1150 try temp_params.append(.i32); // memory address is always a 32-bit handle1158 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)) {
1152 if (cc == .C) {1160 if (cc == .C) {
1153 const res_classes = abi.classifyType(return_type, target);1161 const res_classes = abi.classifyType(return_type, mod);
1154 assert(res_classes[0] == .direct and res_classes[1] == .none);1162 assert(res_classes[0] == .direct and res_classes[1] == .none);
1155 const scalar_type = abi.scalarType(return_type, target);1163 const scalar_type = abi.scalarType(return_type, mod);
1156 try returns.append(typeToValtype(scalar_type, target));1164 try returns.append(typeToValtype(scalar_type, mod));
1157 } else {1165 } else {
1158 try returns.append(typeToValtype(return_type, target));1166 try returns.append(typeToValtype(return_type, mod));
1159 }1167 }
1160 } else if (return_type.isError()) {1168 } else if (return_type.isError(mod)) {
1161 try returns.append(.i32);1169 try returns.append(.i32);
1162 }1170 }
11631171
1164 // param types1172 // param types
1165 for (params) |param_type| {1173 for (params) |param_type_ip| {
1166 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;1174 const param_type = param_type_ip.toType();
1175 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
11671176
1168 switch (cc) {1177 switch (cc) {
1169 .C => {1178 .C => {
1170 const param_classes = abi.classifyType(param_type, target);1179 const param_classes = abi.classifyType(param_type, mod);
1171 for (param_classes) |class| {1180 for (param_classes) |class| {
1172 if (class == .none) continue;1181 if (class == .none) continue;
1173 if (class == .direct) {1182 if (class == .direct) {
1174 const scalar_type = abi.scalarType(param_type, target);1183 const scalar_type = abi.scalarType(param_type, mod);
1175 try temp_params.append(typeToValtype(scalar_type, target));1184 try temp_params.append(typeToValtype(scalar_type, mod));
1176 } else {1185 } else {
1177 try temp_params.append(typeToValtype(param_type, target));1186 try temp_params.append(typeToValtype(param_type, mod));
1178 }1187 }
1179 }1188 }
1180 },1189 },
1181 else => if (isByRef(param_type, target))1190 else => if (isByRef(param_type, mod))
1182 try temp_params.append(.i32)1191 try temp_params.append(.i32)
1183 else1192 else
1184 try temp_params.append(typeToValtype(param_type, target)),1193 try temp_params.append(typeToValtype(param_type, mod)),
1185 }1194 }
1186 }1195 }
11871196
...@@ -1194,20 +1203,22 @@ fn genFunctype(gpa: Allocator, cc: std.builtin.CallingConvention, params: []cons...@@ -1194,20 +1203,22 @@ fn genFunctype(gpa: Allocator, cc: std.builtin.CallingConvention, params: []cons
1194pub fn generate(1203pub fn generate(
1195 bin_file: *link.File,1204 bin_file: *link.File,
1196 src_loc: Module.SrcLoc,1205 src_loc: Module.SrcLoc,
1197 func: *Module.Fn,1206 func_index: Module.Fn.Index,
1198 air: Air,1207 air: Air,
1199 liveness: Liveness,1208 liveness: Liveness,
1200 code: *std.ArrayList(u8),1209 code: *std.ArrayList(u8),
1201 debug_output: codegen.DebugInfoOutput,1210 debug_output: codegen.DebugInfoOutput,
1202) codegen.CodeGenError!codegen.Result {1211) codegen.CodeGenError!codegen.Result {
1203 _ = src_loc;1212 _ = src_loc;
1213 const mod = bin_file.options.module.?;
1214 const func = mod.funcPtr(func_index);
1204 var code_gen: CodeGen = .{1215 var code_gen: CodeGen = .{
1205 .gpa = bin_file.allocator,1216 .gpa = bin_file.allocator,
1206 .air = air,1217 .air = air,
1207 .liveness = liveness,1218 .liveness = liveness,
1208 .code = code,1219 .code = code,
1209 .decl_index = func.owner_decl,1220 .decl_index = func.owner_decl,
1210 .decl = bin_file.options.module.?.declPtr(func.owner_decl),1221 .decl = mod.declPtr(func.owner_decl),
1211 .err_msg = undefined,1222 .err_msg = undefined,
1212 .locals = .{},1223 .locals = .{},
1213 .target = bin_file.options.target,1224 .target = bin_file.options.target,
...@@ -1226,8 +1237,9 @@ pub fn generate(...@@ -1226,8 +1237,9 @@ pub fn generate(
1226}1237}
12271238
1228fn genFunc(func: *CodeGen) InnerError!void {1239fn genFunc(func: *CodeGen) InnerError!void {
1229 const fn_info = func.decl.ty.fnInfo();1240 const mod = func.bin_file.base.options.module.?;
1230 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, func.target);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);
1231 defer func_type.deinit(func.gpa);1243 defer func_type.deinit(func.gpa);
1232 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);1244 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12331245
...@@ -1253,8 +1265,8 @@ fn genFunc(func: *CodeGen) InnerError!void {...@@ -1253,8 +1265,8 @@ fn genFunc(func: *CodeGen) InnerError!void {
1253 // we emit an unreachable instruction to tell the stack validator that part will never be reached.1265 // we emit an unreachable instruction to tell the stack validator that part will never be reached.
1254 if (func_type.returns.len != 0 and func.air.instructions.len > 0) {1266 if (func_type.returns.len != 0 and func.air.instructions.len > 0) {
1255 const inst = @intCast(u32, func.air.instructions.len - 1);1267 const inst = @intCast(u32, func.air.instructions.len - 1);
1256 const last_inst_ty = func.air.typeOfIndex(inst);1268 const last_inst_ty = func.typeOfIndex(inst);
1257 if (!last_inst_ty.hasRuntimeBitsIgnoreComptime() or last_inst_ty.isNoReturn()) {1269 if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(mod) or last_inst_ty.isNoReturn(mod)) {
1258 try func.addTag(.@"unreachable");1270 try func.addTag(.@"unreachable");
1259 }1271 }
1260 }1272 }
...@@ -1335,10 +1347,9 @@ const CallWValues = struct {...@@ -1335,10 +1347,9 @@ const CallWValues = struct {
1335};1347};
13361348
1337fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {1349fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
1338 const cc = fn_ty.fnCallingConvention();1350 const mod = func.bin_file.base.options.module.?;
1339 const param_types = try func.gpa.alloc(Type, fn_ty.fnParamLen());1351 const fn_info = mod.typeToFunc(fn_ty).?;
1340 defer func.gpa.free(param_types);1352 const cc = fn_info.cc;
1341 fn_ty.fnParamTypes(param_types);
1342 var result: CallWValues = .{1353 var result: CallWValues = .{
1343 .args = &.{},1354 .args = &.{},
1344 .return_value = .none,1355 .return_value = .none,
...@@ -1350,8 +1361,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1350,8 +1361,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13501361
1351 // Check if we store the result as a pointer to the stack rather than1362 // Check if we store the result as a pointer to the stack rather than
1352 // by value1363 // by value
1353 const fn_info = fn_ty.fnInfo();1364 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
1354 if (firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) {
1355 // the sret arg will be passed as first argument, therefore we1365 // the sret arg will be passed as first argument, therefore we
1356 // set the `return_value` before allocating locals for regular args.1366 // set the `return_value` before allocating locals for regular args.
1357 result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } };1367 result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } };
...@@ -1360,8 +1370,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1360,8 +1370,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13601370
1361 switch (cc) {1371 switch (cc) {
1362 .Unspecified => {1372 .Unspecified => {
1363 for (param_types) |ty| {1373 for (fn_info.param_types) |ty| {
1364 if (!ty.hasRuntimeBitsIgnoreComptime()) {1374 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
1365 continue;1375 continue;
1366 }1376 }
13671377
...@@ -1370,8 +1380,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1370,8 +1380,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1370 }1380 }
1371 },1381 },
1372 .C => {1382 .C => {
1373 for (param_types) |ty| {1383 for (fn_info.param_types) |ty| {
1374 const ty_classes = abi.classifyType(ty, func.target);1384 const ty_classes = abi.classifyType(ty.toType(), mod);
1375 for (ty_classes) |class| {1385 for (ty_classes) |class| {
1376 if (class == .none) continue;1386 if (class == .none) continue;
1377 try args.append(.{ .local = .{ .value = func.local_index, .references = 1 } });1387 try args.append(.{ .local = .{ .value = func.local_index, .references = 1 } });
...@@ -1385,11 +1395,11 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1385,11 +1395,11 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1385 return result;1395 return result;
1386}1396}
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 {
1389 switch (cc) {1399 switch (cc) {
1390 .Unspecified, .Inline => return isByRef(return_type, target),1400 .Unspecified, .Inline => return isByRef(return_type, mod),
1391 .C => {1401 .C => {
1392 const ty_classes = abi.classifyType(return_type, target);1402 const ty_classes = abi.classifyType(return_type, mod);
1393 if (ty_classes[0] == .indirect) return true;1403 if (ty_classes[0] == .indirect) return true;
1394 if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true;1404 if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true;
1395 return false;1405 return false;
...@@ -1405,16 +1415,17 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:...@@ -1405,16 +1415,17 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:
1405 return func.lowerToStack(value);1415 return func.lowerToStack(value);
1406 }1416 }
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);
1409 assert(ty_classes[0] != .none);1420 assert(ty_classes[0] != .none);
1410 switch (ty.zigTypeTag()) {1421 switch (ty.zigTypeTag(mod)) {
1411 .Struct, .Union => {1422 .Struct, .Union => {
1412 if (ty_classes[0] == .indirect) {1423 if (ty_classes[0] == .indirect) {
1413 return func.lowerToStack(value);1424 return func.lowerToStack(value);
1414 }1425 }
1415 assert(ty_classes[0] == .direct);1426 assert(ty_classes[0] == .direct);
1416 const scalar_type = abi.scalarType(ty, func.target);1427 const scalar_type = abi.scalarType(ty, mod);
1417 const abi_size = scalar_type.abiSize(func.target);1428 const abi_size = scalar_type.abiSize(mod);
1418 try func.emitWValue(value);1429 try func.emitWValue(value);
14191430
1420 // When the value lives in the virtual stack, we must load it onto the actual stack1431 // 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:...@@ -1422,12 +1433,12 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:
1422 const opcode = buildOpcode(.{1433 const opcode = buildOpcode(.{
1423 .op = .load,1434 .op = .load,
1424 .width = @intCast(u8, abi_size),1435 .width = @intCast(u8, abi_size),
1425 .signedness = if (scalar_type.isSignedInt()) .signed else .unsigned,1436 .signedness = if (scalar_type.isSignedInt(mod)) .signed else .unsigned,
1426 .valtype1 = typeToValtype(scalar_type, func.target),1437 .valtype1 = typeToValtype(scalar_type, mod),
1427 });1438 });
1428 try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{1439 try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{
1429 .offset = value.offset(),1440 .offset = value.offset(),
1430 .alignment = scalar_type.abiAlignment(func.target),1441 .alignment = scalar_type.abiAlignment(mod),
1431 });1442 });
1432 }1443 }
1433 },1444 },
...@@ -1436,7 +1447,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:...@@ -1436,7 +1447,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:
1436 return func.lowerToStack(value);1447 return func.lowerToStack(value);
1437 }1448 }
1438 assert(ty_classes[0] == .direct and ty_classes[1] == .direct);1449 assert(ty_classes[0] == .direct and ty_classes[1] == .direct);
1439 assert(ty.abiSize(func.target) == 16);1450 assert(ty.abiSize(mod) == 16);
1440 // in this case we have an integer or float that must be lowered as 2 i64's.1451 // in this case we have an integer or float that must be lowered as 2 i64's.
1441 try func.emitWValue(value);1452 try func.emitWValue(value);
1442 try func.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 8 });1453 try func.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 8 });
...@@ -1503,18 +1514,18 @@ fn restoreStackPointer(func: *CodeGen) !void {...@@ -1503,18 +1514,18 @@ fn restoreStackPointer(func: *CodeGen) !void {
1503///1514///
1504/// Asserts Type has codegenbits1515/// Asserts Type has codegenbits
1505fn allocStack(func: *CodeGen, ty: Type) !WValue {1516fn allocStack(func: *CodeGen, ty: Type) !WValue {
1506 assert(ty.hasRuntimeBitsIgnoreComptime());1517 const mod = func.bin_file.base.options.module.?;
1518 assert(ty.hasRuntimeBitsIgnoreComptime(mod));
1507 if (func.initial_stack_value == .none) {1519 if (func.initial_stack_value == .none) {
1508 try func.initializeStack();1520 try func.initializeStack();
1509 }1521 }
15101522
1511 const abi_size = std.math.cast(u32, ty.abiSize(func.target)) orelse {1523 const abi_size = std.math.cast(u32, ty.abiSize(mod)) orelse {
1512 const module = func.bin_file.base.options.module.?;
1513 return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{1524 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),
1515 });1526 });
1516 };1527 };
1517 const abi_align = ty.abiAlignment(func.target);1528 const abi_align = ty.abiAlignment(mod);
15181529
1519 if (abi_align > func.stack_alignment) {1530 if (abi_align > func.stack_alignment) {
1520 func.stack_alignment = abi_align;1531 func.stack_alignment = abi_align;
...@@ -1531,22 +1542,22 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue {...@@ -1531,22 +1542,22 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue {
1531/// This is different from allocStack where this will use the pointer's alignment1542/// This is different from allocStack where this will use the pointer's alignment
1532/// if it is set, to ensure the stack alignment will be set correctly.1543/// if it is set, to ensure the stack alignment will be set correctly.
1533fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue {1544fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue {
1534 const ptr_ty = func.air.typeOfIndex(inst);1545 const mod = func.bin_file.base.options.module.?;
1535 const pointee_ty = ptr_ty.childType();1546 const ptr_ty = func.typeOfIndex(inst);
1547 const pointee_ty = ptr_ty.childType(mod);
15361548
1537 if (func.initial_stack_value == .none) {1549 if (func.initial_stack_value == .none) {
1538 try func.initializeStack();1550 try func.initializeStack();
1539 }1551 }
15401552
1541 if (!pointee_ty.hasRuntimeBitsIgnoreComptime()) {1553 if (!pointee_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1542 return func.allocStack(Type.usize); // create a value containing just the stack pointer.1554 return func.allocStack(Type.usize); // create a value containing just the stack pointer.
1543 }1555 }
15441556
1545 const abi_alignment = ptr_ty.ptrAlignment(func.target);1557 const abi_alignment = ptr_ty.ptrAlignment(mod);
1546 const abi_size = std.math.cast(u32, pointee_ty.abiSize(func.target)) orelse {1558 const abi_size = std.math.cast(u32, pointee_ty.abiSize(mod)) orelse {
1547 const module = func.bin_file.base.options.module.?;
1548 return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{1559 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),
1550 });1561 });
1551 };1562 };
1552 if (abi_alignment > func.stack_alignment) {1563 if (abi_alignment > func.stack_alignment) {
...@@ -1704,8 +1715,9 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch {...@@ -1704,8 +1715,9 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch {
17041715
1705/// For a given `Type`, will return true when the type will be passed1716/// For a given `Type`, will return true when the type will be passed
1706/// by reference, rather than by value1717/// by reference, rather than by value
1707fn isByRef(ty: Type, target: std.Target) bool {1718fn isByRef(ty: Type, mod: *Module) bool {
1708 switch (ty.zigTypeTag()) {1719 const target = mod.getTarget();
1720 switch (ty.zigTypeTag(mod)) {
1709 .Type,1721 .Type,
1710 .ComptimeInt,1722 .ComptimeInt,
1711 .ComptimeFloat,1723 .ComptimeFloat,
...@@ -1726,44 +1738,42 @@ fn isByRef(ty: Type, target: std.Target) bool {...@@ -1726,44 +1738,42 @@ fn isByRef(ty: Type, target: std.Target) bool {
17261738
1727 .Array,1739 .Array,
1728 .Frame,1740 .Frame,
1729 => return ty.hasRuntimeBitsIgnoreComptime(),1741 => return ty.hasRuntimeBitsIgnoreComptime(mod),
1730 .Union => {1742 .Union => {
1731 if (ty.castTag(.@"union")) |union_ty| {1743 if (mod.typeToUnion(ty)) |union_obj| {
1732 if (union_ty.data.layout == .Packed) {1744 if (union_obj.layout == .Packed) {
1733 return ty.abiSize(target) > 8;1745 return ty.abiSize(mod) > 8;
1734 }1746 }
1735 }1747 }
1736 return ty.hasRuntimeBitsIgnoreComptime();1748 return ty.hasRuntimeBitsIgnoreComptime(mod);
1737 },1749 },
1738 .Struct => {1750 .Struct => {
1739 if (ty.castTag(.@"struct")) |struct_ty| {1751 if (mod.typeToStruct(ty)) |struct_obj| {
1740 const struct_obj = struct_ty.data;
1741 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {1752 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);
1743 }1754 }
1744 }1755 }
1745 return ty.hasRuntimeBitsIgnoreComptime();1756 return ty.hasRuntimeBitsIgnoreComptime(mod);
1746 },1757 },
1747 .Vector => return determineSimdStoreStrategy(ty, target) == .unrolled,1758 .Vector => return determineSimdStoreStrategy(ty, mod) == .unrolled,
1748 .Int => return ty.intInfo(target).bits > 64,1759 .Int => return ty.intInfo(mod).bits > 64,
1749 .Float => return ty.floatBits(target) > 64,1760 .Float => return ty.floatBits(target) > 64,
1750 .ErrorUnion => {1761 .ErrorUnion => {
1751 const pl_ty = ty.errorUnionPayload();1762 const pl_ty = ty.errorUnionPayload(mod);
1752 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {1763 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1753 return false;1764 return false;
1754 }1765 }
1755 return true;1766 return true;
1756 },1767 },
1757 .Optional => {1768 .Optional => {
1758 if (ty.isPtrLikeOptional()) return false;1769 if (ty.isPtrLikeOptional(mod)) return false;
1759 var buf: Type.Payload.ElemType = undefined;1770 const pl_type = ty.optionalChild(mod);
1760 const pl_type = ty.optionalChild(&buf);1771 if (pl_type.zigTypeTag(mod) == .ErrorSet) return false;
1761 if (pl_type.zigTypeTag() == .ErrorSet) return false;1772 return pl_type.hasRuntimeBitsIgnoreComptime(mod);
1762 return pl_type.hasRuntimeBitsIgnoreComptime();
1763 },1773 },
1764 .Pointer => {1774 .Pointer => {
1765 // Slices act like struct and will be passed by reference1775 // Slices act like struct and will be passed by reference
1766 if (ty.isSlice()) return true;1776 if (ty.isSlice(mod)) return true;
1767 return false;1777 return false;
1768 },1778 },
1769 }1779 }
...@@ -1778,10 +1788,11 @@ const SimdStoreStrategy = enum {...@@ -1778,10 +1788,11 @@ const SimdStoreStrategy = enum {
1778/// This means when a given type is 128 bits and either the simd128 or relaxed-simd1788/// This means when a given type is 128 bits and either the simd128 or relaxed-simd
1779/// features are enabled, the function will return `.direct`. This would allow to store1789/// features are enabled, the function will return `.direct`. This would allow to store
1780/// it using a instruction, rather than an unrolled version.1790/// it using a instruction, rather than an unrolled version.
1781fn determineSimdStoreStrategy(ty: Type, target: std.Target) SimdStoreStrategy {1791fn determineSimdStoreStrategy(ty: Type, mod: *Module) SimdStoreStrategy {
1782 std.debug.assert(ty.zigTypeTag() == .Vector);1792 std.debug.assert(ty.zigTypeTag(mod) == .Vector);
1783 if (ty.bitSize(target) != 128) return .unrolled;1793 if (ty.bitSize(mod) != 128) return .unrolled;
1784 const hasFeature = std.Target.wasm.featureSetHas;1794 const hasFeature = std.Target.wasm.featureSetHas;
1795 const target = mod.getTarget();
1785 const features = target.cpu.features;1796 const features = target.cpu.features;
1786 if (hasFeature(features, .relaxed_simd) or hasFeature(features, .simd128)) {1797 if (hasFeature(features, .relaxed_simd) or hasFeature(features, .simd128)) {
1787 return .direct;1798 return .direct;
...@@ -1821,8 +1832,7 @@ fn buildPointerOffset(func: *CodeGen, ptr_value: WValue, offset: u64, action: en...@@ -1821,8 +1832,7 @@ fn buildPointerOffset(func: *CodeGen, ptr_value: WValue, offset: u64, action: en
1821fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {1832fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1822 const air_tags = func.air.instructions.items(.tag);1833 const air_tags = func.air.instructions.items(.tag);
1823 return switch (air_tags[inst]) {1834 return switch (air_tags[inst]) {
1824 .constant => unreachable,1835 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
1825 .const_ty => unreachable,
18261836
1827 .add => func.airBinOp(inst, .add),1837 .add => func.airBinOp(inst, .add),
1828 .add_sat => func.airSatBinOp(inst, .add),1838 .add_sat => func.airSatBinOp(inst, .add),
...@@ -2062,8 +2072,11 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2062,8 +2072,11 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2062}2072}
20632073
2064fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void {2074fn 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
2065 for (body) |inst| {2078 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)) {
2067 continue;2080 continue;
2068 }2081 }
2069 const old_bookkeeping_value = func.air_bookkeeping;2082 const old_bookkeeping_value = func.air_bookkeeping;
...@@ -2080,36 +2093,37 @@ fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2080,36 +2093,37 @@ fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2080}2093}
20812094
2082fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2095fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2096 const mod = func.bin_file.base.options.module.?;
2083 const un_op = func.air.instructions.items(.data)[inst].un_op;2097 const un_op = func.air.instructions.items(.data)[inst].un_op;
2084 const operand = try func.resolveInst(un_op);2098 const operand = try func.resolveInst(un_op);
2085 const fn_info = func.decl.ty.fnInfo();2099 const fn_info = mod.typeToFunc(func.decl.ty).?;
2086 const ret_ty = fn_info.return_type;2100 const ret_ty = fn_info.return_type.toType();
20872101
2088 // result must be stored in the stack and we return a pointer2102 // result must be stored in the stack and we return a pointer
2089 // to the stack instead2103 // to the stack instead
2090 if (func.return_value != .none) {2104 if (func.return_value != .none) {
2091 try func.store(func.return_value, operand, ret_ty, 0);2105 try func.store(func.return_value, operand, ret_ty, 0);
2092 } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime()) {2106 } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2093 switch (ret_ty.zigTypeTag()) {2107 switch (ret_ty.zigTypeTag(mod)) {
2094 // Aggregate types can be lowered as a singular value2108 // Aggregate types can be lowered as a singular value
2095 .Struct, .Union => {2109 .Struct, .Union => {
2096 const scalar_type = abi.scalarType(ret_ty, func.target);2110 const scalar_type = abi.scalarType(ret_ty, mod);
2097 try func.emitWValue(operand);2111 try func.emitWValue(operand);
2098 const opcode = buildOpcode(.{2112 const opcode = buildOpcode(.{
2099 .op = .load,2113 .op = .load,
2100 .width = @intCast(u8, scalar_type.abiSize(func.target) * 8),2114 .width = @intCast(u8, scalar_type.abiSize(mod) * 8),
2101 .signedness = if (scalar_type.isSignedInt()) .signed else .unsigned,2115 .signedness = if (scalar_type.isSignedInt(mod)) .signed else .unsigned,
2102 .valtype1 = typeToValtype(scalar_type, func.target),2116 .valtype1 = typeToValtype(scalar_type, mod),
2103 });2117 });
2104 try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{2118 try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{
2105 .offset = operand.offset(),2119 .offset = operand.offset(),
2106 .alignment = scalar_type.abiAlignment(func.target),2120 .alignment = scalar_type.abiAlignment(mod),
2107 });2121 });
2108 },2122 },
2109 else => try func.emitWValue(operand),2123 else => try func.emitWValue(operand),
2110 }2124 }
2111 } else {2125 } else {
2112 if (!ret_ty.hasRuntimeBitsIgnoreComptime() and ret_ty.isError()) {2126 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and ret_ty.isError(mod)) {
2113 try func.addImm32(0);2127 try func.addImm32(0);
2114 } else {2128 } else {
2115 try func.emitWValue(operand);2129 try func.emitWValue(operand);
...@@ -2122,15 +2136,16 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2122,15 +2136,16 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2122}2136}
21232137
2124fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2138fn 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
2127 var result = result: {2142 var result = result: {
2128 if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime()) {2143 if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
2129 break :result try func.allocStack(Type.usize); // create pointer to void2144 break :result try func.allocStack(Type.usize); // create pointer to void
2130 }2145 }
21312146
2132 const fn_info = func.decl.ty.fnInfo();2147 const fn_info = mod.typeToFunc(func.decl.ty).?;
2133 if (firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) {2148 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
2134 break :result func.return_value;2149 break :result func.return_value;
2135 }2150 }
21362151
...@@ -2141,16 +2156,17 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2141,16 +2156,17 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2141}2156}
21422157
2143fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2158fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2159 const mod = func.bin_file.base.options.module.?;
2144 const un_op = func.air.instructions.items(.data)[inst].un_op;2160 const un_op = func.air.instructions.items(.data)[inst].un_op;
2145 const operand = try func.resolveInst(un_op);2161 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();2164 const fn_info = mod.typeToFunc(func.decl.ty).?;
2149 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {2165 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2150 if (ret_ty.isError()) {2166 if (ret_ty.isError(mod)) {
2151 try func.addImm32(0);2167 try func.addImm32(0);
2152 }2168 }
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)) {
2154 // leave on the stack2170 // leave on the stack
2155 _ = try func.load(operand, ret_ty, 0);2171 _ = try func.load(operand, ret_ty, 0);
2156 }2172 }
...@@ -2165,42 +2181,48 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2165,42 +2181,48 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2165 const pl_op = func.air.instructions.items(.data)[inst].pl_op;2181 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
2166 const extra = func.air.extraData(Air.Call, pl_op.payload);2182 const extra = func.air.extraData(Air.Call, pl_op.payload);
2167 const args = @ptrCast([]const Air.Inst.Ref, func.air.extra[extra.end..][0..extra.data.args_len]);2183 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)) {
2171 .Fn => ty,2188 .Fn => ty,
2172 .Pointer => ty.childType(),2189 .Pointer => ty.childType(mod),
2173 else => unreachable,2190 else => unreachable,
2174 };2191 };
2175 const ret_ty = fn_ty.fnReturnType();2192 const ret_ty = fn_ty.fnReturnType(mod);
2176 const fn_info = fn_ty.fnInfo();2193 const fn_info = mod.typeToFunc(fn_ty).?;
2177 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, func.target);2194 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod);
21782195
2179 const callee: ?Decl.Index = blk: {2196 const callee: ?Decl.Index = blk: {
2180 const func_val = func.air.value(pl_op.operand) orelse break :blk null;2197 const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;
2181 const module = func.bin_file.base.options.module.?;2198
21822199 if (func_val.getFunction(mod)) |function| {
2183 if (func_val.castTag(.function)) |function| {2200 _ = try func.bin_file.getOrCreateAtomForDecl(function.owner_decl);
2184 _ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl);2201 break :blk function.owner_decl;
2185 break :blk function.data.owner_decl;2202 } else if (func_val.getExternFunc(mod)) |extern_func| {
2186 } else if (func_val.castTag(.extern_fn)) |extern_fn| {2203 const ext_decl = mod.declPtr(extern_func.decl);
2187 const ext_decl = module.declPtr(extern_fn.data.owner_decl);2204 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2188 const ext_info = ext_decl.ty.fnInfo();2205 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
2189 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, func.target);
2190 defer func_type.deinit(func.gpa);2206 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);
2192 const atom = func.bin_file.getAtomPtr(atom_index);2208 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);
2194 try func.bin_file.addOrUpdateImport(2210 try func.bin_file.addOrUpdateImport(
2195 mem.sliceTo(ext_decl.name, 0),2211 mod.intern_pool.stringToSlice(ext_decl.name),
2196 atom.getSymbolIndex().?,2212 atom.getSymbolIndex().?,
2197 ext_decl.getExternFn().?.lib_name,2213 mod.intern_pool.stringToSliceUnwrap(ext_decl.getOwnedExternFunc(mod).?.lib_name),
2198 type_index,2214 type_index,
2199 );2215 );
2200 break :blk extern_fn.data.owner_decl;2216 break :blk extern_func.decl;
2201 } else if (func_val.castTag(.decl_ref)) |decl_ref| {2217 } else switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
2202 _ = try func.bin_file.getOrCreateAtomForDecl(decl_ref.data);2218 .ptr => |ptr| switch (ptr.addr) {
2203 break :blk decl_ref.data;2219 .decl => |decl| {
2220 _ = try func.bin_file.getOrCreateAtomForDecl(decl);
2221 break :blk decl;
2222 },
2223 else => {},
2224 },
2225 else => {},
2204 }2226 }
2205 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});2227 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});
2206 };2228 };
...@@ -2214,10 +2236,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2214,10 +2236,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2214 for (args) |arg| {2236 for (args) |arg| {
2215 const arg_val = try func.resolveInst(arg);2237 const arg_val = try func.resolveInst(arg);
22162238
2217 const arg_ty = func.air.typeOf(arg);2239 const arg_ty = func.typeOf(arg);
2218 if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue;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);
2221 }2243 }
22222244
2223 if (callee) |direct| {2245 if (callee) |direct| {
...@@ -2226,11 +2248,11 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2226,11 +2248,11 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2226 } else {2248 } else {
2227 // in this case we call a function pointer2249 // in this case we call a function pointer
2228 // so load its value onto the stack2250 // so load its value onto the stack
2229 std.debug.assert(ty.zigTypeTag() == .Pointer);2251 std.debug.assert(ty.zigTypeTag(mod) == .Pointer);
2230 const operand = try func.resolveInst(pl_op.operand);2252 const operand = try func.resolveInst(pl_op.operand);
2231 try func.emitWValue(operand);2253 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);
2234 defer fn_type.deinit(func.gpa);2256 defer fn_type.deinit(func.gpa);
22352257
2236 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);2258 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...@@ -2238,18 +2260,18 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2238 }2260 }
22392261
2240 const result_value = result_value: {2262 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)) {
2242 break :result_value WValue{ .none = {} };2264 break :result_value WValue{ .none = {} };
2243 } else if (ret_ty.isNoReturn()) {2265 } else if (ret_ty.isNoReturn(mod)) {
2244 try func.addTag(.@"unreachable");2266 try func.addTag(.@"unreachable");
2245 break :result_value WValue{ .none = {} };2267 break :result_value WValue{ .none = {} };
2246 } else if (first_param_sret) {2268 } else if (first_param_sret) {
2247 break :result_value sret;2269 break :result_value sret;
2248 // TODO: Make this less fragile and optimize2270 // 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) {
2250 const result_local = try func.allocLocal(ret_ty);2272 const result_local = try func.allocLocal(ret_ty);
2251 try func.addLabel(.local_set, result_local.local.value);2273 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);
2253 const result = try func.allocStack(scalar_type);2275 const result = try func.allocStack(scalar_type);
2254 try func.store(result, result_local, scalar_type, 0);2276 try func.store(result, result_local, scalar_type, 0);
2255 break :result_value result;2277 break :result_value result;
...@@ -2272,6 +2294,7 @@ fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2272,6 +2294,7 @@ fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2272}2294}
22732295
2274fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {2296fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
2297 const mod = func.bin_file.base.options.module.?;
2275 if (safety) {2298 if (safety) {
2276 // TODO if the value is undef, write 0xaa bytes to dest2299 // TODO if the value is undef, write 0xaa bytes to dest
2277 } else {2300 } else {
...@@ -2281,26 +2304,22 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void...@@ -2281,26 +2304,22 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
22812304
2282 const lhs = try func.resolveInst(bin_op.lhs);2305 const lhs = try func.resolveInst(bin_op.lhs);
2283 const rhs = try func.resolveInst(bin_op.rhs);2306 const rhs = try func.resolveInst(bin_op.rhs);
2284 const ptr_ty = func.air.typeOf(bin_op.lhs);2307 const ptr_ty = func.typeOf(bin_op.lhs);
2285 const ptr_info = ptr_ty.ptrInfo().data;2308 const ptr_info = ptr_ty.ptrInfo(mod);
2286 const ty = ptr_ty.childType();2309 const ty = ptr_ty.childType(mod);
22872310
2288 if (ptr_info.host_size == 0) {2311 if (ptr_info.host_size == 0) {
2289 try func.store(lhs, rhs, ty, 0);2312 try func.store(lhs, rhs, ty, 0);
2290 } else {2313 } else {
2291 // at this point we have a non-natural alignment, we must2314 // at this point we have a non-natural alignment, we must
2292 // load the value, and then shift+or the rhs into the result location.2315 // load the value, and then shift+or the rhs into the result location.
2293 var int_ty_payload: Type.Payload.Bits = .{2316 const int_elem_ty = try mod.intType(.unsigned, ptr_info.host_size * 8);
2294 .base = .{ .tag = .int_unsigned },
2295 .data = ptr_info.host_size * 8,
2296 };
2297 const int_elem_ty = Type.initPayload(&int_ty_payload.base);
22982317
2299 if (isByRef(int_elem_ty, func.target)) {2318 if (isByRef(int_elem_ty, mod)) {
2300 return func.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{});2319 return func.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{});
2301 }2320 }
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);
2304 mask <<= @intCast(u6, ptr_info.bit_offset);2323 mask <<= @intCast(u6, ptr_info.bit_offset);
2305 mask ^= ~@as(u64, 0);2324 mask ^= ~@as(u64, 0);
2306 const shift_val = if (ptr_info.host_size <= 4)2325 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...@@ -2329,11 +2348,12 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
23292348
2330fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {2349fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {
2331 assert(!(lhs != .stack and rhs == .stack));2350 assert(!(lhs != .stack and rhs == .stack));
2332 const abi_size = ty.abiSize(func.target);2351 const mod = func.bin_file.base.options.module.?;
2333 switch (ty.zigTypeTag()) {2352 const abi_size = ty.abiSize(mod);
2353 switch (ty.zigTypeTag(mod)) {
2334 .ErrorUnion => {2354 .ErrorUnion => {
2335 const pl_ty = ty.errorUnionPayload();2355 const pl_ty = ty.errorUnionPayload(mod);
2336 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {2356 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2337 return func.store(lhs, rhs, Type.anyerror, 0);2357 return func.store(lhs, rhs, Type.anyerror, 0);
2338 }2358 }
23392359
...@@ -2341,26 +2361,25 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE...@@ -2341,26 +2361,25 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
2341 return func.memcpy(lhs, rhs, .{ .imm32 = len });2361 return func.memcpy(lhs, rhs, .{ .imm32 = len });
2342 },2362 },
2343 .Optional => {2363 .Optional => {
2344 if (ty.isPtrLikeOptional()) {2364 if (ty.isPtrLikeOptional(mod)) {
2345 return func.store(lhs, rhs, Type.usize, 0);2365 return func.store(lhs, rhs, Type.usize, 0);
2346 }2366 }
2347 var buf: Type.Payload.ElemType = undefined;2367 const pl_ty = ty.optionalChild(mod);
2348 const pl_ty = ty.optionalChild(&buf);2368 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2349 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
2350 return func.store(lhs, rhs, Type.u8, 0);2369 return func.store(lhs, rhs, Type.u8, 0);
2351 }2370 }
2352 if (pl_ty.zigTypeTag() == .ErrorSet) {2371 if (pl_ty.zigTypeTag(mod) == .ErrorSet) {
2353 return func.store(lhs, rhs, Type.anyerror, 0);2372 return func.store(lhs, rhs, Type.anyerror, 0);
2354 }2373 }
23552374
2356 const len = @intCast(u32, abi_size);2375 const len = @intCast(u32, abi_size);
2357 return func.memcpy(lhs, rhs, .{ .imm32 = len });2376 return func.memcpy(lhs, rhs, .{ .imm32 = len });
2358 },2377 },
2359 .Struct, .Array, .Union => if (isByRef(ty, func.target)) {2378 .Struct, .Array, .Union => if (isByRef(ty, mod)) {
2360 const len = @intCast(u32, abi_size);2379 const len = @intCast(u32, abi_size);
2361 return func.memcpy(lhs, rhs, .{ .imm32 = len });2380 return func.memcpy(lhs, rhs, .{ .imm32 = len });
2362 },2381 },
2363 .Vector => switch (determineSimdStoreStrategy(ty, func.target)) {2382 .Vector => switch (determineSimdStoreStrategy(ty, mod)) {
2364 .unrolled => {2383 .unrolled => {
2365 const len = @intCast(u32, abi_size);2384 const len = @intCast(u32, abi_size);
2366 return func.memcpy(lhs, rhs, .{ .imm32 = len });2385 return func.memcpy(lhs, rhs, .{ .imm32 = len });
...@@ -2374,13 +2393,13 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE...@@ -2374,13 +2393,13 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
2374 try func.mir_extra.appendSlice(func.gpa, &[_]u32{2393 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
2375 std.wasm.simdOpcode(.v128_store),2394 std.wasm.simdOpcode(.v128_store),
2376 offset + lhs.offset(),2395 offset + lhs.offset(),
2377 ty.abiAlignment(func.target),2396 ty.abiAlignment(mod),
2378 });2397 });
2379 return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });2398 return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
2380 },2399 },
2381 },2400 },
2382 .Pointer => {2401 .Pointer => {
2383 if (ty.isSlice()) {2402 if (ty.isSlice(mod)) {
2384 // store pointer first2403 // store pointer first
2385 // lower it to the stack so we do not have to store rhs into a local first2404 // lower it to the stack so we do not have to store rhs into a local first
2386 try func.emitWValue(lhs);2405 try func.emitWValue(lhs);
...@@ -2404,7 +2423,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE...@@ -2404,7 +2423,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
2404 try func.store(.{ .stack = {} }, msb, Type.u64, 8 + lhs.offset());2423 try func.store(.{ .stack = {} }, msb, Type.u64, 8 + lhs.offset());
2405 return;2424 return;
2406 } else if (abi_size > 16) {2425 } 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)) });
2408 },2427 },
2409 else => if (abi_size > 8) {2428 else => if (abi_size > 8) {
2410 return func.fail("TODO: `store` for type `{}` with abisize `{d}`", .{2429 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...@@ -2418,7 +2437,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
2418 // into lhs, so we calculate that and emit that instead2437 // into lhs, so we calculate that and emit that instead
2419 try func.lowerToStack(rhs);2438 try func.lowerToStack(rhs);
24202439
2421 const valtype = typeToValtype(ty, func.target);2440 const valtype = typeToValtype(ty, mod);
2422 const opcode = buildOpcode(.{2441 const opcode = buildOpcode(.{
2423 .valtype1 = valtype,2442 .valtype1 = valtype,
2424 .width = @intCast(u8, abi_size * 8),2443 .width = @intCast(u8, abi_size * 8),
...@@ -2428,21 +2447,22 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE...@@ -2428,21 +2447,22 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
2428 // store rhs value at stack pointer's location in memory2447 // store rhs value at stack pointer's location in memory
2429 try func.addMemArg(2448 try func.addMemArg(
2430 Mir.Inst.Tag.fromOpcode(opcode),2449 Mir.Inst.Tag.fromOpcode(opcode),
2431 .{ .offset = offset + lhs.offset(), .alignment = ty.abiAlignment(func.target) },2450 .{ .offset = offset + lhs.offset(), .alignment = ty.abiAlignment(mod) },
2432 );2451 );
2433}2452}
24342453
2435fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2454fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2455 const mod = func.bin_file.base.options.module.?;
2436 const ty_op = func.air.instructions.items(.data)[inst].ty_op;2456 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
2437 const operand = try func.resolveInst(ty_op.operand);2457 const operand = try func.resolveInst(ty_op.operand);
2438 const ty = func.air.getRefType(ty_op.ty);2458 const ty = func.air.getRefType(ty_op.ty);
2439 const ptr_ty = func.air.typeOf(ty_op.operand);2459 const ptr_ty = func.typeOf(ty_op.operand);
2440 const ptr_info = ptr_ty.ptrInfo().data;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
2444 const result = result: {2464 const result = result: {
2445 if (isByRef(ty, func.target)) {2465 if (isByRef(ty, mod)) {
2446 const new_local = try func.allocStack(ty);2466 const new_local = try func.allocStack(ty);
2447 try func.store(new_local, operand, ty, 0);2467 try func.store(new_local, operand, ty, 0);
2448 break :result new_local;2468 break :result new_local;
...@@ -2455,11 +2475,7 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2455,11 +2475,7 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
24552475
2456 // at this point we have a non-natural alignment, we must2476 // at this point we have a non-natural alignment, we must
2457 // shift the value to obtain the correct bit.2477 // shift the value to obtain the correct bit.
2458 var int_ty_payload: Type.Payload.Bits = .{2478 const int_elem_ty = try mod.intType(.unsigned, ptr_info.host_size * 8);
2459 .base = .{ .tag = .int_unsigned },
2460 .data = ptr_info.host_size * 8,
2461 };
2462 const int_elem_ty = Type.initPayload(&int_ty_payload.base);
2463 const shift_val = if (ptr_info.host_size <= 4)2479 const shift_val = if (ptr_info.host_size <= 4)
2464 WValue{ .imm32 = ptr_info.bit_offset }2480 WValue{ .imm32 = ptr_info.bit_offset }
2465 else if (ptr_info.host_size <= 8)2481 else if (ptr_info.host_size <= 8)
...@@ -2479,25 +2495,26 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2479,25 +2495,26 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2479/// Loads an operand from the linear memory section.2495/// Loads an operand from the linear memory section.
2480/// NOTE: Leaves the value on the stack.2496/// NOTE: Leaves the value on the stack.
2481fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue {2497fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
2498 const mod = func.bin_file.base.options.module.?;
2482 // load local's value from memory by its stack position2499 // load local's value from memory by its stack position
2483 try func.emitWValue(operand);2500 try func.emitWValue(operand);
24842501
2485 if (ty.zigTypeTag() == .Vector) {2502 if (ty.zigTypeTag(mod) == .Vector) {
2486 // TODO: Add helper functions for simd opcodes2503 // TODO: Add helper functions for simd opcodes
2487 const extra_index = @intCast(u32, func.mir_extra.items.len);2504 const extra_index = @intCast(u32, func.mir_extra.items.len);
2488 // stores as := opcode, offset, alignment (opcode::memarg)2505 // stores as := opcode, offset, alignment (opcode::memarg)
2489 try func.mir_extra.appendSlice(func.gpa, &[_]u32{2506 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
2490 std.wasm.simdOpcode(.v128_load),2507 std.wasm.simdOpcode(.v128_load),
2491 offset + operand.offset(),2508 offset + operand.offset(),
2492 ty.abiAlignment(func.target),2509 ty.abiAlignment(mod),
2493 });2510 });
2494 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });2511 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
2495 return WValue{ .stack = {} };2512 return WValue{ .stack = {} };
2496 }2513 }
24972514
2498 const abi_size = @intCast(u8, ty.abiSize(func.target));2515 const abi_size = @intCast(u8, ty.abiSize(mod));
2499 const opcode = buildOpcode(.{2516 const opcode = buildOpcode(.{
2500 .valtype1 = typeToValtype(ty, func.target),2517 .valtype1 = typeToValtype(ty, mod),
2501 .width = abi_size * 8,2518 .width = abi_size * 8,
2502 .op = .load,2519 .op = .load,
2503 .signedness = .unsigned,2520 .signedness = .unsigned,
...@@ -2505,19 +2522,20 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu...@@ -2505,19 +2522,20 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
25052522
2506 try func.addMemArg(2523 try func.addMemArg(
2507 Mir.Inst.Tag.fromOpcode(opcode),2524 Mir.Inst.Tag.fromOpcode(opcode),
2508 .{ .offset = offset + operand.offset(), .alignment = ty.abiAlignment(func.target) },2525 .{ .offset = offset + operand.offset(), .alignment = ty.abiAlignment(mod) },
2509 );2526 );
25102527
2511 return WValue{ .stack = {} };2528 return WValue{ .stack = {} };
2512}2529}
25132530
2514fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2531fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2532 const mod = func.bin_file.base.options.module.?;
2515 const arg_index = func.arg_index;2533 const arg_index = func.arg_index;
2516 const arg = func.args[arg_index];2534 const arg = func.args[arg_index];
2517 const cc = func.decl.ty.fnInfo().cc;2535 const cc = mod.typeToFunc(func.decl.ty).?.cc;
2518 const arg_ty = func.air.typeOfIndex(inst);2536 const arg_ty = func.typeOfIndex(inst);
2519 if (cc == .C) {2537 if (cc == .C) {
2520 const arg_classes = abi.classifyType(arg_ty, func.target);2538 const arg_classes = abi.classifyType(arg_ty, mod);
2521 for (arg_classes) |class| {2539 for (arg_classes) |class| {
2522 if (class != .none) {2540 if (class != .none) {
2523 func.arg_index += 1;2541 func.arg_index += 1;
...@@ -2527,7 +2545,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2527,7 +2545,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2527 // When we have an argument that's passed using more than a single parameter,2545 // When we have an argument that's passed using more than a single parameter,
2528 // we combine them into a single stack value2546 // we combine them into a single stack value
2529 if (arg_classes[0] == .direct and arg_classes[1] == .direct) {2547 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) {
2531 return func.fail(2549 return func.fail(
2532 "TODO: Implement C-ABI argument for type '{}'",2550 "TODO: Implement C-ABI argument for type '{}'",
2533 .{arg_ty.fmt(func.bin_file.base.options.module.?)},2551 .{arg_ty.fmt(func.bin_file.base.options.module.?)},
...@@ -2557,11 +2575,12 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2557,11 +2575,12 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2557}2575}
25582576
2559fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {2577fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2578 const mod = func.bin_file.base.options.module.?;
2560 const bin_op = func.air.instructions.items(.data)[inst].bin_op;2579 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
2561 const lhs = try func.resolveInst(bin_op.lhs);2580 const lhs = try func.resolveInst(bin_op.lhs);
2562 const rhs = try func.resolveInst(bin_op.rhs);2581 const rhs = try func.resolveInst(bin_op.rhs);
2563 const lhs_ty = func.air.typeOf(bin_op.lhs);2582 const lhs_ty = func.typeOf(bin_op.lhs);
2564 const rhs_ty = func.air.typeOf(bin_op.rhs);2583 const rhs_ty = func.typeOf(bin_op.rhs);
25652584
2566 // For certain operations, such as shifting, the types are different.2585 // For certain operations, such as shifting, the types are different.
2567 // When converting this to a WebAssembly type, they *must* match to perform2586 // 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 {...@@ -2570,10 +2589,10 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2570 // For big integers we can ignore this as we will call into compiler-rt which handles this.2589 // For big integers we can ignore this as we will call into compiler-rt which handles this.
2571 const result = switch (op) {2590 const result = switch (op) {
2572 .shr, .shl => res: {2591 .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 {
2574 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});2593 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
2575 };2594 };
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))).?;
2577 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {2596 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {
2578 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);2597 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);
2579 break :blk try tmp.toLocal(func, lhs_ty);2598 break :blk try tmp.toLocal(func, lhs_ty);
...@@ -2593,6 +2612,7 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -2593,6 +2612,7 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2593/// Performs a binary operation on the given `WValue`'s2612/// Performs a binary operation on the given `WValue`'s
2594/// NOTE: THis leaves the value on top of the stack.2613/// NOTE: THis leaves the value on top of the stack.
2595fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {2614fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {
2615 const mod = func.bin_file.base.options.module.?;
2596 assert(!(lhs != .stack and rhs == .stack));2616 assert(!(lhs != .stack and rhs == .stack));
25972617
2598 if (ty.isAnyFloat()) {2618 if (ty.isAnyFloat()) {
...@@ -2600,8 +2620,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!...@@ -2600,8 +2620,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
2600 return func.floatOp(float_op, ty, &.{ lhs, rhs });2620 return func.floatOp(float_op, ty, &.{ lhs, rhs });
2601 }2621 }
26022622
2603 if (isByRef(ty, func.target)) {2623 if (isByRef(ty, mod)) {
2604 if (ty.zigTypeTag() == .Int) {2624 if (ty.zigTypeTag(mod) == .Int) {
2605 return func.binOpBigInt(lhs, rhs, ty, op);2625 return func.binOpBigInt(lhs, rhs, ty, op);
2606 } else {2626 } else {
2607 return func.fail(2627 return func.fail(
...@@ -2613,8 +2633,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!...@@ -2613,8 +2633,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
26132633
2614 const opcode: wasm.Opcode = buildOpcode(.{2634 const opcode: wasm.Opcode = buildOpcode(.{
2615 .op = op,2635 .op = op,
2616 .valtype1 = typeToValtype(ty, func.target),2636 .valtype1 = typeToValtype(ty, mod),
2617 .signedness = if (ty.isSignedInt()) .signed else .unsigned,2637 .signedness = if (ty.isSignedInt(mod)) .signed else .unsigned,
2618 });2638 });
2619 try func.emitWValue(lhs);2639 try func.emitWValue(lhs);
2620 try func.emitWValue(rhs);2640 try func.emitWValue(rhs);
...@@ -2625,14 +2645,15 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!...@@ -2625,14 +2645,15 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
2625}2645}
26262646
2627fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {2647fn 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) {
2629 return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{});2650 return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{});
2630 }2651 }
26312652
2632 switch (op) {2653 switch (op) {
2633 .mul => return func.callIntrinsic("__multi3", &.{ ty, ty }, ty, &.{ lhs, rhs }),2654 .mul => return func.callIntrinsic("__multi3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }),
2634 .shr => return func.callIntrinsic("__lshrti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),2655 .shr => return func.callIntrinsic("__lshrti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
2635 .shl => return func.callIntrinsic("__ashlti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),2656 .shl => return func.callIntrinsic("__ashlti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
2636 .xor => {2657 .xor => {
2637 const result = try func.allocStack(ty);2658 const result = try func.allocStack(ty);
2638 try func.emitWValue(result);2659 try func.emitWValue(result);
...@@ -2756,14 +2777,15 @@ const FloatOp = enum {...@@ -2756,14 +2777,15 @@ const FloatOp = enum {
2756fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void {2777fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void {
2757 const un_op = func.air.instructions.items(.data)[inst].un_op;2778 const un_op = func.air.instructions.items(.data)[inst].un_op;
2758 const operand = try func.resolveInst(un_op);2779 const operand = try func.resolveInst(un_op);
2759 const ty = func.air.typeOf(un_op);2780 const ty = func.typeOf(un_op);
27602781
2761 const result = try (try func.floatOp(op, ty, &.{operand})).toLocal(func, ty);2782 const result = try (try func.floatOp(op, ty, &.{operand})).toLocal(func, ty);
2762 func.finishAir(inst, result, &.{un_op});2783 func.finishAir(inst, result, &.{un_op});
2763}2784}
27642785
2765fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) InnerError!WValue {2786fn 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) {
2767 return func.fail("TODO: Implement floatOps for vectors", .{});2789 return func.fail("TODO: Implement floatOps for vectors", .{});
2768 }2790 }
27692791
...@@ -2773,7 +2795,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In...@@ -2773,7 +2795,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
2773 for (args) |operand| {2795 for (args) |operand| {
2774 try func.emitWValue(operand);2796 try func.emitWValue(operand);
2775 }2797 }
2776 const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, func.target) });2798 const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, mod) });
2777 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));2799 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
2778 return .stack;2800 return .stack;
2779 }2801 }
...@@ -2821,20 +2843,21 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In...@@ -2821,20 +2843,21 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
2821 };2843 };
28222844
2823 // fma requires three operands2845 // 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 };
2825 const param_types = param_types_buffer[0..args.len];2847 const param_types = param_types_buffer[0..args.len];
2826 return func.callIntrinsic(fn_name, param_types, ty, args);2848 return func.callIntrinsic(fn_name, param_types, ty, args);
2827}2849}
28282850
2829fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {2851fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2852 const mod = func.bin_file.base.options.module.?;
2830 const bin_op = func.air.instructions.items(.data)[inst].bin_op;2853 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
28312854
2832 const lhs = try func.resolveInst(bin_op.lhs);2855 const lhs = try func.resolveInst(bin_op.lhs);
2833 const rhs = try func.resolveInst(bin_op.rhs);2856 const rhs = try func.resolveInst(bin_op.rhs);
2834 const lhs_ty = func.air.typeOf(bin_op.lhs);2857 const lhs_ty = func.typeOf(bin_op.lhs);
2835 const rhs_ty = func.air.typeOf(bin_op.rhs);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) {
2838 return func.fail("TODO: Implement wrapping arithmetic for vectors", .{});2861 return func.fail("TODO: Implement wrapping arithmetic for vectors", .{});
2839 }2862 }
28402863
...@@ -2845,10 +2868,10 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -2845,10 +2868,10 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2845 // For big integers we can ignore this as we will call into compiler-rt which handles this.2868 // For big integers we can ignore this as we will call into compiler-rt which handles this.
2846 const result = switch (op) {2869 const result = switch (op) {
2847 .shr, .shl => res: {2870 .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 {
2849 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});2872 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
2850 };2873 };
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))).?;
2852 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {2875 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {
2853 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);2876 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);
2854 break :blk try tmp.toLocal(func, lhs_ty);2877 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...@@ -2877,8 +2900,9 @@ fn wrapBinOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr
2877/// Asserts `Type` is <= 128 bits.2900/// Asserts `Type` is <= 128 bits.
2878/// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack.2901/// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack.
2879fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {2902fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {
2880 assert(ty.abiSize(func.target) <= 16);2903 const mod = func.bin_file.base.options.module.?;
2881 const bitsize = @intCast(u16, ty.bitSize(func.target));2904 assert(ty.abiSize(mod) <= 16);
2905 const bitsize = @intCast(u16, ty.bitSize(mod));
2882 const wasm_bits = toWasmBits(bitsize) orelse {2906 const wasm_bits = toWasmBits(bitsize) orelse {
2883 return func.fail("TODO: Implement wrapOperand for bitsize '{d}'", .{bitsize});2907 return func.fail("TODO: Implement wrapOperand for bitsize '{d}'", .{bitsize});
2884 };2908 };
...@@ -2914,43 +2938,67 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {...@@ -2914,43 +2938,67 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {
2914 return WValue{ .stack = {} };2938 return WValue{ .stack = {} };
2915}2939}
29162940
2917fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue {2941fn lowerParentPtr(func: *CodeGen, ptr_val: Value) InnerError!WValue {
2918 switch (ptr_val.tag()) {2942 const mod = func.bin_file.base.options.module.?;
2919 .decl_ref_mut => {2943 const ptr = mod.intern_pool.indexToKey(ptr_val.ip_index).ptr;
2920 const decl_index = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;2944 switch (ptr.addr) {
2921 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);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);
2922 },2951 },
2923 .decl_ref => {2952 .int, .eu_payload => |tag| return func.fail("TODO: Implement lowerParentPtr for {}", .{tag}),
2924 const decl_index = ptr_val.castTag(.decl_ref).?.data;2953 .opt_payload => |base_ptr| {
2925 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);2954 return func.lowerParentPtr(base_ptr.toValue());
2926 },2955 },
2927 .variable => {2956 .comptime_field => unreachable,
2928 const decl_index = ptr_val.castTag(.variable).?.data.owner_decl;2957 .elem => |elem| {
2929 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);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 };
2930 },2978 },
2931 .field_ptr => {2979 .field => |field| {
2932 const field_ptr = ptr_val.castTag(.field_ptr).?.data;2980 const parent_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod);
2933 const parent_ty = field_ptr.container_ty;2981 const parent_ptr = try func.lowerParentPtr(field.base.toValue());
29342982
2935 const field_offset = switch (parent_ty.zigTypeTag()) {2983 const offset = switch (parent_ty.zigTypeTag(mod)) {
2936 .Struct => switch (parent_ty.containerLayout()) {2984 .Struct => switch (parent_ty.containerLayout(mod)) {
2937 .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, func.target),2985 .Packed => parent_ty.packedStructFieldByteOffset(@intCast(usize, field.index), mod),
2938 else => parent_ty.structFieldOffset(field_ptr.field_index, func.target),2986 else => parent_ty.structFieldOffset(@intCast(usize, field.index), mod),
2939 },2987 },
2940 .Union => switch (parent_ty.containerLayout()) {2988 .Union => switch (parent_ty.containerLayout(mod)) {
2941 .Packed => 0,2989 .Packed => 0,
2942 else => blk: {2990 else => blk: {
2943 const layout: Module.Union.Layout = parent_ty.unionGetLayout(func.target);2991 const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod);
2944 if (layout.payload_size == 0) break :blk 0;2992 if (layout.payload_size == 0) break :blk 0;
2945 if (layout.payload_align > layout.tag_align) break :blk 0;2993 if (layout.payload_align > layout.tag_align) break :blk 0;
29462994
2947 // tag is stored first so calculate offset from where payload starts2995 // 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));2996 const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
2949 break :blk field_offset;2997 break :blk offset;
2950 },2998 },
2951 },2999 },
2952 .Pointer => switch (parent_ty.ptrSize()) {3000 .Pointer => switch (parent_ty.ptrSize(mod)) {
2953 .Slice => switch (field_ptr.field_index) {3001 .Slice => switch (field.index) {
2954 0 => 0,3002 0 => 0,
2955 1 => func.ptrSize(),3003 1 => func.ptrSize(),
2956 else => unreachable,3004 else => unreachable,
...@@ -2959,51 +3007,51 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue...@@ -2959,51 +3007,51 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
2959 },3007 },
2960 else => unreachable,3008 else => unreachable,
2961 };3009 };
2962 return func.lowerParentPtr(field_ptr.container_ptr, offset + @intCast(u32, field_offset));3010
2963 },3011 return switch (parent_ptr) {
2964 .elem_ptr => {3012 .memory => |ptr_| WValue{
2965 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;3013 .memory_offset = .{
2966 const index = elem_ptr.index;3014 .pointer = ptr_,
2967 const elem_offset = index * elem_ptr.elem_ty.abiSize(func.target);3015 .offset = @intCast(u32, offset),
2968 return func.lowerParentPtr(elem_ptr.array_ptr, offset + @intCast(u32, elem_offset));3016 },
2969 },3017 },
2970 .opt_payload_ptr => {3018 .memory_offset => |mem_off| WValue{
2971 const payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;3019 .memory_offset = .{
2972 return func.lowerParentPtr(payload_ptr.container_ptr, offset);3020 .pointer = mem_off.pointer,
3021 .offset = @intCast(u32, offset) + mem_off.offset,
3022 },
3023 },
3024 else => unreachable,
3025 };
2973 },3026 },
2974 else => |tag| return func.fail("TODO: Implement lowerParentPtr for tag: {}", .{tag}),
2975 }3027 }
2976}3028}
29773029
2978fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue {3030fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue {
2979 const module = func.bin_file.base.options.module.?;3031 const mod = func.bin_file.base.options.module.?;
2980 const decl = module.declPtr(decl_index);3032 const decl = mod.declPtr(decl_index);
2981 module.markDeclAlive(decl);3033 try mod.markDeclAlive(decl);
2982 var ptr_ty_payload: Type.Payload.ElemType = .{3034 const ptr_ty = try mod.singleMutPtrType(decl.ty);
2983 .base = .{ .tag = .single_mut_pointer },
2984 .data = decl.ty,
2985 };
2986 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2987 return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset);3035 return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset);
2988}3036}
29893037
2990fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue {3038fn 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)) {
2992 return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) };3041 return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) };
2993 }3042 }
29943043
2995 const module = func.bin_file.base.options.module.?;3044 const decl = mod.declPtr(decl_index);
2996 const decl = module.declPtr(decl_index);3045 if (decl.ty.zigTypeTag(mod) != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime(mod)) {
2997 if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) {
2998 return WValue{ .imm32 = 0xaaaaaaaa };3046 return WValue{ .imm32 = 0xaaaaaaaa };
2999 }3047 }
30003048
3001 module.markDeclAlive(decl);3049 try mod.markDeclAlive(decl);
3002 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);3050 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
3003 const atom = func.bin_file.getAtom(atom_index);3051 const atom = func.bin_file.getAtom(atom_index);
30043052
3005 const target_sym_index = atom.sym_index;3053 const target_sym_index = atom.sym_index;
3006 if (decl.ty.zigTypeTag() == .Fn) {3054 if (decl.ty.zigTypeTag(mod) == .Fn) {
3007 try func.bin_file.addTableFunction(target_sym_index);3055 try func.bin_file.addTableFunction(target_sym_index);
3008 return WValue{ .function_index = target_sym_index };3056 return WValue{ .function_index = target_sym_index };
3009 } else if (offset == 0) {3057 } else if (offset == 0) {
...@@ -3028,142 +3076,201 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(...@@ -3028,142 +3076,201 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(
3028}3076}
30293077
3030fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {3078fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3079 const mod = func.bin_file.base.options.module.?;
3031 var val = arg_val;3080 var val = arg_val;
3032 if (val.castTag(.runtime_value)) |rt| {3081 switch (mod.intern_pool.indexToKey(val.ip_index)) {
3033 val = rt.data;3082 .runtime_value => |rt| val = rt.val.toValue(),
3034 }3083 else => {},
3035 if (val.isUndefDeep()) return func.emitUndefined(ty);3084 }
3036 if (val.castTag(.decl_ref)) |decl_ref| {3085 if (val.isUndefDeep(mod)) return func.emitUndefined(ty);
3037 const decl_index = decl_ref.data;3086
3038 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);3087 if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) {
3039 }3088 .Array => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),
3040 if (val.castTag(.decl_ref_mut)) |decl_ref_mut| {3089 .Struct => {
3041 const decl_index = decl_ref_mut.data.decl_index;3090 const struct_obj = mod.typeToStruct(ty).?;
3042 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);3091 assert(struct_obj.layout == .Packed);
3043 }3092 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3044 const target = func.target;3093 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3045 switch (ty.zigTypeTag()) {3094 const int_val = try mod.intValue(
3046 .Void => return WValue{ .none = {} },3095 struct_obj.backing_int_ty,
3047 .Int => {3096 std.mem.readIntLittle(u64, &buf),
3048 const int_info = ty.intInfo(func.target);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);
3049 switch (int_info.signedness) {3174 switch (int_info.signedness) {
3050 .signed => switch (int_info.bits) {3175 .signed => switch (int_info.bits) {
3051 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(3176 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(
3052 val.toSignedInt(target),3177 val.toSignedInt(mod),
3053 @intCast(u6, int_info.bits),3178 @intCast(u6, int_info.bits),
3054 )) },3179 )) },
3055 33...64 => return WValue{ .imm64 = toTwosComplement(3180 33...64 => return WValue{ .imm64 = toTwosComplement(
3056 val.toSignedInt(target),3181 val.toSignedInt(mod),
3057 @intCast(u7, int_info.bits),3182 @intCast(u7, int_info.bits),
3058 ) },3183 ) },
3059 else => unreachable,3184 else => unreachable,
3060 },3185 },
3061 .unsigned => switch (int_info.bits) {3186 .unsigned => switch (int_info.bits) {
3062 0...32 => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) },3187 0...32 => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) },
3063 33...64 => return WValue{ .imm64 = val.toUnsignedInt(target) },3188 33...64 => return WValue{ .imm64 = val.toUnsignedInt(mod) },
3064 else => unreachable,3189 else => unreachable,
3065 },3190 },
3066 }3191 }
3067 },3192 },
3068 .Bool => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) },3193 .err => |err| {
3069 .Float => switch (ty.floatBits(func.target)) {3194 const int = try mod.getErrorValue(err.name);
3070 16 => return WValue{ .imm32 = @bitCast(u16, val.toFloat(f16)) },3195 return WValue{ .imm32 = int };
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()}),
3080 },3196 },
3081 .Enum => {3197 .error_union => |error_union| {
3082 if (val.castTag(.enum_field_index)) |field_index| {3198 const err_tv: TypedValue = switch (error_union.val) {
3083 switch (ty.tag()) {3199 .err_name => |err_name| .{
3084 .enum_simple => return WValue{ .imm32 = field_index.data },3200 .ty = ty.errorUnionSet(mod),
3085 .enum_full, .enum_nonexhaustive => {3201 .val = (try mod.intern(.{ .err = .{
3086 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;3202 .ty = ty.errorUnionSet(mod).toIntern(),
3087 if (enum_full.values.count() != 0) {3203 .name = err_name,
3088 const tag_val = enum_full.values.keys()[field_index.data];3204 } })).toValue(),
3089 return func.lowerConstant(tag_val, enum_full.tag_ty);3205 },
3090 } else {3206 .payload => .{
3091 return WValue{ .imm32 = field_index.data };3207 .ty = Type.err_int,
3092 }3208 .val = try mod.intValue(Type.err_int, 0),
3093 },3209 },
3094 .enum_numbered => {3210 };
3095 const index = field_index.data;3211 const payload_type = ty.errorUnionPayload(mod);
3096 const enum_data = ty.castTag(.enum_numbered).?.data;3212 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
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()) {
3119 // We use the error type directly as the type.3213 // We use the error type directly as the type.
3120 const is_pl = val.errorUnionIsPayload();3214 return func.lowerConstant(err_tv.val, err_tv.ty);
3121 const err_val = if (!is_pl) val else Value.initTag(.zero);
3122 return func.lowerConstant(err_val, error_type);
3123 }3215 }
3216
3124 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});3217 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
3125 },3218 },
3126 .Optional => if (ty.optionalReprIsPayload()) {3219 .enum_tag => |enum_tag| {
3127 var buf: Type.Payload.ElemType = undefined;3220 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
3128 const pl_ty = ty.optionalChild(&buf);3221 return func.lowerConstant(enum_tag.int.toValue(), int_tag_ty.toType());
3129 if (val.castTag(.opt_payload)) |payload| {3222 },
3130 return func.lowerConstant(payload.data, pl_ty);3223 .float => |float| switch (float.storage) {
3131 } else if (val.isNull()) {3224 .f16 => |f16_val| return WValue{ .imm32 = @bitCast(u16, f16_val) },
3132 return WValue{ .imm32 = 0 };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);
3133 } else {3240 } else {
3134 return func.lowerConstant(val, pl_ty);3241 return WValue{ .imm32 = 0 };
3135 }3242 }
3136 } else {3243 } else {
3137 const is_pl = val.tag() == .opt_payload;3244 return WValue{ .imm32 = @boolToInt(!val.isNull(mod)) };
3138 return WValue{ .imm32 = @boolToInt(is_pl) };
3139 },3245 },
3140 .Struct => {3246 .aggregate => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3141 const struct_obj = ty.castTag(.@"struct").?.data;3247 .array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),
3142 assert(struct_obj.layout == .Packed);3248 .vector_type => {
3143 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer3249 assert(determineSimdStoreStrategy(ty, mod) == .direct);
3144 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;3250 var buf: [16]u8 = undefined;
3145 var payload: Value.Payload.U64 = .{3251 val.writeToMemory(ty, mod, &buf) catch unreachable;
3146 .base = .{ .tag = .int_u64 },3252 return func.storeSimdImmd(buf);
3147 .data = std.mem.readIntLittle(u64, &buf),3253 },
3148 };3254 .struct_type, .anon_struct_type => {
3149 const int_val = Value.initPayload(&payload.base);3255 const struct_obj = mod.typeToStruct(ty).?;
3150 return func.lowerConstant(int_val, struct_obj.backing_int_ty);3256 assert(struct_obj.layout == .Packed);
3151 },3257 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3152 .Vector => {3258 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3153 assert(determineSimdStoreStrategy(ty, target) == .direct);3259 const int_val = try mod.intValue(
3154 var buf: [16]u8 = undefined;3260 struct_obj.backing_int_ty,
3155 val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable;3261 std.mem.readIntLittle(u64, &buf),
3156 return func.storeSimdImmd(buf);3262 );
3263 return func.lowerConstant(int_val, struct_obj.backing_int_ty);
3264 },
3265 else => unreachable,
3157 },3266 },
3158 .Union => {3267 .un => |union_obj| {
3159 // in this case we have a packed union which will not be passed by reference.3268 // 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;3269 const field_index = ty.unionTagFieldIndex(union_obj.tag.toValue(), func.bin_file.base.options.module.?).?;
3161 const union_obj = val.castTag(.@"union").?.data;3270 const field_ty = ty.unionFields(mod).values()[field_index].ty;
3162 const field_index = ty.unionTagFieldIndex(union_obj.tag, func.bin_file.base.options.module.?).?;3271 return func.lowerConstant(union_obj.val.toValue(), field_ty);
3163 const field_ty = union_ty.fields.values()[field_index].ty;
3164 return func.lowerConstant(union_obj.val, field_ty);
3165 },3272 },
3166 else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),3273 .memoized_call => unreachable,
3167 }3274 }
3168}3275}
31693276
...@@ -3176,9 +3283,10 @@ fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue {...@@ -3176,9 +3283,10 @@ fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue {
3176}3283}
31773284
3178fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {3285fn 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)) {
3180 .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa },3288 .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa },
3181 .Int, .Enum => switch (ty.intInfo(func.target).bits) {3289 .Int, .Enum => switch (ty.intInfo(mod).bits) {
3182 0...32 => return WValue{ .imm32 = 0xaaaaaaaa },3290 0...32 => return WValue{ .imm32 = 0xaaaaaaaa },
3183 33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },3291 33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },
3184 else => unreachable,3292 else => unreachable,
...@@ -3195,9 +3303,8 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -3195,9 +3303,8 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3195 else => unreachable,3303 else => unreachable,
3196 },3304 },
3197 .Optional => {3305 .Optional => {
3198 var buf: Type.Payload.ElemType = undefined;3306 const pl_ty = ty.optionalChild(mod);
3199 const pl_ty = ty.optionalChild(&buf);3307 if (ty.optionalReprIsPayload(mod)) {
3200 if (ty.optionalReprIsPayload()) {
3201 return func.emitUndefined(pl_ty);3308 return func.emitUndefined(pl_ty);
3202 }3309 }
3203 return WValue{ .imm32 = 0xaaaaaaaa };3310 return WValue{ .imm32 = 0xaaaaaaaa };
...@@ -3206,11 +3313,11 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -3206,11 +3313,11 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3206 return WValue{ .imm32 = 0xaaaaaaaa };3313 return WValue{ .imm32 = 0xaaaaaaaa };
3207 },3314 },
3208 .Struct => {3315 .Struct => {
3209 const struct_obj = ty.castTag(.@"struct").?.data;3316 const struct_obj = mod.typeToStruct(ty).?;
3210 assert(struct_obj.layout == .Packed);3317 assert(struct_obj.layout == .Packed);
3211 return func.emitUndefined(struct_obj.backing_int_ty);3318 return func.emitUndefined(struct_obj.backing_int_ty);
3212 },3319 },
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)}),
3214 }3321 }
3215}3322}
32163323
...@@ -3218,56 +3325,52 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -3218,56 +3325,52 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3218/// It's illegal to provide a value with a type that cannot be represented3325/// It's illegal to provide a value with a type that cannot be represented
3219/// as an integer value.3326/// as an integer value.
3220fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {3327fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
3221 const target = func.target;3328 const mod = func.bin_file.base.options.module.?;
3222 switch (ty.zigTypeTag()) {3329
3223 .Enum => {3330 switch (val.ip_index) {
3224 if (val.castTag(.enum_field_index)) |field_index| {3331 .none => {},
3225 switch (ty.tag()) {3332 .bool_true => return 1,
3226 .enum_simple => return @bitCast(i32, field_index.data),3333 .bool_false => return 0,
3227 .enum_full, .enum_nonexhaustive => {3334 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
3228 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;3335 .enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int, mod),
3229 if (enum_full.values.count() != 0) {3336 .int => |int| intStorageAsI32(int.storage, mod),
3230 const tag_val = enum_full.values.keys()[field_index.data];3337 .ptr => |ptr| intIndexAsI32(&mod.intern_pool, ptr.addr.int, mod),
3231 return func.valueAsI32(tag_val, enum_full.tag_ty);3338 .err => |err| @bitCast(i32, @intCast(Module.ErrorInt, mod.global_error_set.getIndex(err.name).?)),
3232 } else return @bitCast(i32, field_index.data);3339 else => unreachable,
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);
3254 },3340 },
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
3258 }3341 }
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 };
3259}3361}
32603362
3261fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3363fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3364 const mod = func.bin_file.base.options.module.?;
3262 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;3365 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
3263 const block_ty = func.air.getRefType(ty_pl.ty);3366 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);
3265 const extra = func.air.extraData(Air.Block, ty_pl.payload);3368 const extra = func.air.extraData(Air.Block, ty_pl.payload);
3266 const body = func.air.extra[extra.end..][0..extra.data.body_len];3369 const body = func.air.extra[extra.end..][0..extra.data.body_len];
32673370
3268 // if wasm_block_ty is non-empty, we create a register to store the temporary value3371 // if wasm_block_ty is non-empty, we create a register to store the temporary value
3269 const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: {3372 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;
3271 break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten3374 break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten
3272 } else WValue.none;3375 } else WValue.none;
32733376
...@@ -3369,7 +3472,7 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In...@@ -3369,7 +3472,7 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In
33693472
3370 const lhs = try func.resolveInst(bin_op.lhs);3473 const lhs = try func.resolveInst(bin_op.lhs);
3371 const rhs = try func.resolveInst(bin_op.rhs);3474 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);
3373 const result = try (try func.cmp(lhs, rhs, operand_ty, op)).toLocal(func, Type.u32); // comparison result is always 32 bits3476 const result = try (try func.cmp(lhs, rhs, operand_ty, op)).toLocal(func, Type.u32); // comparison result is always 32 bits
3374 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });3477 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
3375}3478}
...@@ -3379,16 +3482,16 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In...@@ -3379,16 +3482,16 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In
3379/// NOTE: This leaves the result on top of the stack, rather than a new local.3482/// NOTE: This leaves the result on top of the stack, rather than a new local.
3380fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOperator) InnerError!WValue {3483fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOperator) InnerError!WValue {
3381 assert(!(lhs != .stack and rhs == .stack));3484 assert(!(lhs != .stack and rhs == .stack));
3382 if (ty.zigTypeTag() == .Optional and !ty.optionalReprIsPayload()) {3485 const mod = func.bin_file.base.options.module.?;
3383 var buf: Type.Payload.ElemType = undefined;3486 if (ty.zigTypeTag(mod) == .Optional and !ty.optionalReprIsPayload(mod)) {
3384 const payload_ty = ty.optionalChild(&buf);3487 const payload_ty = ty.optionalChild(mod);
3385 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {3488 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3386 // When we hit this case, we must check the value of optionals3489 // When we hit this case, we must check the value of optionals
3387 // that are not pointers. This means first checking against non-null for3490 // that are not pointers. This means first checking against non-null for
3388 // both lhs and rhs, as well as checking the payload are matching of lhs and rhs3491 // both lhs and rhs, as well as checking the payload are matching of lhs and rhs
3389 return func.cmpOptionals(lhs, rhs, ty, op);3492 return func.cmpOptionals(lhs, rhs, ty, op);
3390 }3493 }
3391 } else if (isByRef(ty, func.target)) {3494 } else if (isByRef(ty, mod)) {
3392 return func.cmpBigInt(lhs, rhs, ty, op);3495 return func.cmpBigInt(lhs, rhs, ty, op);
3393 } else if (ty.isAnyFloat() and ty.floatBits(func.target) == 16) {3496 } else if (ty.isAnyFloat() and ty.floatBits(func.target) == 16) {
3394 return func.cmpFloat16(lhs, rhs, op);3497 return func.cmpFloat16(lhs, rhs, op);
...@@ -3401,13 +3504,13 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO...@@ -3401,13 +3504,13 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO
34013504
3402 const signedness: std.builtin.Signedness = blk: {3505 const signedness: std.builtin.Signedness = blk: {
3403 // by default we tell the operand type is unsigned (i.e. bools and enum values)3506 // 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
3406 // incase of an actual integer, we emit the correct signedness3509 // 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;
3408 };3511 };
3409 const opcode: wasm.Opcode = buildOpcode(.{3512 const opcode: wasm.Opcode = buildOpcode(.{
3410 .valtype1 = typeToValtype(ty, func.target),3513 .valtype1 = typeToValtype(ty, mod),
3411 .op = switch (op) {3514 .op = switch (op) {
3412 .lt => .lt,3515 .lt => .lt,
3413 .lte => .le,3516 .lte => .le,
...@@ -3464,11 +3567,12 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3464,11 +3567,12 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3464}3567}
34653568
3466fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3569fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3570 const mod = func.bin_file.base.options.module.?;
3467 const br = func.air.instructions.items(.data)[inst].br;3571 const br = func.air.instructions.items(.data)[inst].br;
3468 const block = func.blocks.get(br.block_inst).?;3572 const block = func.blocks.get(br.block_inst).?;
34693573
3470 // if operand has codegen bits we should break with a value3574 // 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)) {
3472 const operand = try func.resolveInst(br.operand);3576 const operand = try func.resolveInst(br.operand);
3473 try func.lowerToStack(operand);3577 try func.lowerToStack(operand);
34743578
...@@ -3489,17 +3593,18 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3489,17 +3593,18 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3489 const ty_op = func.air.instructions.items(.data)[inst].ty_op;3593 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
34903594
3491 const operand = try func.resolveInst(ty_op.operand);3595 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
3494 const result = result: {3599 const result = result: {
3495 if (operand_ty.zigTypeTag() == .Bool) {3600 if (operand_ty.zigTypeTag(mod) == .Bool) {
3496 try func.emitWValue(operand);3601 try func.emitWValue(operand);
3497 try func.addTag(.i32_eqz);3602 try func.addTag(.i32_eqz);
3498 const not_tmp = try func.allocLocal(operand_ty);3603 const not_tmp = try func.allocLocal(operand_ty);
3499 try func.addLabel(.local_set, not_tmp.local.value);3604 try func.addLabel(.local_set, not_tmp.local.value);
3500 break :result not_tmp;3605 break :result not_tmp;
3501 } else {3606 } else {
3502 const operand_bits = operand_ty.intInfo(func.target).bits;3607 const operand_bits = operand_ty.intInfo(mod).bits;
3503 const wasm_bits = toWasmBits(operand_bits) orelse {3608 const wasm_bits = toWasmBits(operand_bits) orelse {
3504 return func.fail("TODO: Implement binary NOT for integer with bitsize '{d}'", .{operand_bits});3609 return func.fail("TODO: Implement binary NOT for integer with bitsize '{d}'", .{operand_bits});
3505 };3610 };
...@@ -3554,8 +3659,8 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3554,8 +3659,8 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3554 const ty_op = func.air.instructions.items(.data)[inst].ty_op;3659 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
3555 const result = result: {3660 const result = result: {
3556 const operand = try func.resolveInst(ty_op.operand);3661 const operand = try func.resolveInst(ty_op.operand);
3557 const wanted_ty = func.air.typeOfIndex(inst);3662 const wanted_ty = func.typeOfIndex(inst);
3558 const given_ty = func.air.typeOf(ty_op.operand);3663 const given_ty = func.typeOf(ty_op.operand);
3559 if (given_ty.isAnyFloat() or wanted_ty.isAnyFloat()) {3664 if (given_ty.isAnyFloat() or wanted_ty.isAnyFloat()) {
3560 const bitcast_result = try func.bitcast(wanted_ty, given_ty, operand);3665 const bitcast_result = try func.bitcast(wanted_ty, given_ty, operand);
3561 break :result try bitcast_result.toLocal(func, wanted_ty);3666 break :result try bitcast_result.toLocal(func, wanted_ty);
...@@ -3566,16 +3671,17 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3566,16 +3671,17 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3566}3671}
35673672
3568fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue {3673fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue {
3674 const mod = func.bin_file.base.options.module.?;
3569 // if we bitcast a float to or from an integer we must use the 'reinterpret' instruction3675 // if we bitcast a float to or from an integer we must use the 'reinterpret' instruction
3570 if (!(wanted_ty.isAnyFloat() or given_ty.isAnyFloat())) return operand;3676 if (!(wanted_ty.isAnyFloat() or given_ty.isAnyFloat())) return operand;
3571 if (wanted_ty.tag() == .f16 or given_ty.tag() == .f16) return operand;3677 if (wanted_ty.ip_index == .f16_type or given_ty.ip_index == .f16_type) return operand;
3572 if (wanted_ty.bitSize(func.target) > 64) return operand;3678 if (wanted_ty.bitSize(mod) > 64) return operand;
3573 assert((wanted_ty.isInt() and given_ty.isAnyFloat()) or (wanted_ty.isAnyFloat() and given_ty.isInt()));3679 assert((wanted_ty.isInt(mod) and given_ty.isAnyFloat()) or (wanted_ty.isAnyFloat() and given_ty.isInt(mod)));
35743680
3575 const opcode = buildOpcode(.{3681 const opcode = buildOpcode(.{
3576 .op = .reinterpret,3682 .op = .reinterpret,
3577 .valtype1 = typeToValtype(wanted_ty, func.target),3683 .valtype1 = typeToValtype(wanted_ty, mod),
3578 .valtype2 = typeToValtype(given_ty, func.target),3684 .valtype2 = typeToValtype(given_ty, mod),
3579 });3685 });
3580 try func.emitWValue(operand);3686 try func.emitWValue(operand);
3581 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));3687 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...@@ -3583,19 +3689,21 @@ fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inn
3583}3689}
35843690
3585fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3691fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3692 const mod = func.bin_file.base.options.module.?;
3586 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;3693 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
3587 const extra = func.air.extraData(Air.StructField, ty_pl.payload);3694 const extra = func.air.extraData(Air.StructField, ty_pl.payload);
35883695
3589 const struct_ptr = try func.resolveInst(extra.data.struct_operand);3696 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);
3591 const result = try func.structFieldPtr(inst, extra.data.struct_operand, struct_ptr, struct_ty, extra.data.field_index);3698 const result = try func.structFieldPtr(inst, extra.data.struct_operand, struct_ptr, struct_ty, extra.data.field_index);
3592 func.finishAir(inst, result, &.{extra.data.struct_operand});3699 func.finishAir(inst, result, &.{extra.data.struct_operand});
3593}3700}
35943701
3595fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) InnerError!void {3702fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) InnerError!void {
3703 const mod = func.bin_file.base.options.module.?;
3596 const ty_op = func.air.instructions.items(.data)[inst].ty_op;3704 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
3597 const struct_ptr = try func.resolveInst(ty_op.operand);3705 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
3600 const result = try func.structFieldPtr(inst, ty_op.operand, struct_ptr, struct_ty, index);3708 const result = try func.structFieldPtr(inst, ty_op.operand, struct_ptr, struct_ty, index);
3601 func.finishAir(inst, result, &.{ty_op.operand});3709 func.finishAir(inst, result, &.{ty_op.operand});
...@@ -3609,19 +3717,20 @@ fn structFieldPtr(...@@ -3609,19 +3717,20 @@ fn structFieldPtr(
3609 struct_ty: Type,3717 struct_ty: Type,
3610 index: u32,3718 index: u32,
3611) InnerError!WValue {3719) InnerError!WValue {
3612 const result_ty = func.air.typeOfIndex(inst);3720 const mod = func.bin_file.base.options.module.?;
3613 const offset = switch (struct_ty.containerLayout()) {3721 const result_ty = func.typeOfIndex(inst);
3614 .Packed => switch (struct_ty.zigTypeTag()) {3722 const offset = switch (struct_ty.containerLayout(mod)) {
3723 .Packed => switch (struct_ty.zigTypeTag(mod)) {
3615 .Struct => offset: {3724 .Struct => offset: {
3616 if (result_ty.ptrInfo().data.host_size != 0) {3725 if (result_ty.ptrInfo(mod).host_size != 0) {
3617 break :offset @as(u32, 0);3726 break :offset @as(u32, 0);
3618 }3727 }
3619 break :offset struct_ty.packedStructFieldByteOffset(index, func.target);3728 break :offset struct_ty.packedStructFieldByteOffset(index, mod);
3620 },3729 },
3621 .Union => 0,3730 .Union => 0,
3622 else => unreachable,3731 else => unreachable,
3623 },3732 },
3624 else => struct_ty.structFieldOffset(index, func.target),3733 else => struct_ty.structFieldOffset(index, mod),
3625 };3734 };
3626 // save a load and store when we can simply reuse the operand3735 // save a load and store when we can simply reuse the operand
3627 if (offset == 0) {3736 if (offset == 0) {
...@@ -3636,22 +3745,23 @@ fn structFieldPtr(...@@ -3636,22 +3745,23 @@ fn structFieldPtr(
3636}3745}
36373746
3638fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3747fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3748 const mod = func.bin_file.base.options.module.?;
3639 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;3749 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
3640 const struct_field = func.air.extraData(Air.StructField, ty_pl.payload).data;3750 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);
3643 const operand = try func.resolveInst(struct_field.struct_operand);3753 const operand = try func.resolveInst(struct_field.struct_operand);
3644 const field_index = struct_field.field_index;3754 const field_index = struct_field.field_index;
3645 const field_ty = struct_ty.structFieldType(field_index);3755 const field_ty = struct_ty.structFieldType(field_index, mod);
3646 if (!field_ty.hasRuntimeBitsIgnoreComptime()) return func.finishAir(inst, .none, &.{struct_field.struct_operand});3756 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{struct_field.struct_operand});
36473757
3648 const result = switch (struct_ty.containerLayout()) {3758 const result = switch (struct_ty.containerLayout(mod)) {
3649 .Packed => switch (struct_ty.zigTypeTag()) {3759 .Packed => switch (struct_ty.zigTypeTag(mod)) {
3650 .Struct => result: {3760 .Struct => result: {
3651 const struct_obj = struct_ty.castTag(.@"struct").?.data;3761 const struct_obj = mod.typeToStruct(struct_ty).?;
3652 const offset = struct_obj.packedFieldBitOffset(func.target, field_index);3762 const offset = struct_obj.packedFieldBitOffset(mod, field_index);
3653 const backing_ty = struct_obj.backing_int_ty;3763 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 {
3655 return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{});3765 return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{});
3656 };3766 };
3657 const const_wvalue = if (wasm_bits == 32)3767 const const_wvalue = if (wasm_bits == 32)
...@@ -3667,25 +3777,17 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3667,25 +3777,17 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3667 else3777 else
3668 try func.binOp(operand, const_wvalue, backing_ty, .shr);3778 try func.binOp(operand, const_wvalue, backing_ty, .shr);
36693779
3670 if (field_ty.zigTypeTag() == .Float) {3780 if (field_ty.zigTypeTag(mod) == .Float) {
3671 var payload: Type.Payload.Bits = .{3781 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
3672 .base = .{ .tag = .int_unsigned },
3673 .data = @intCast(u16, field_ty.bitSize(func.target)),
3674 };
3675 const int_type = Type.initPayload(&payload.base);
3676 const truncated = try func.trunc(shifted_value, int_type, backing_ty);3782 const truncated = try func.trunc(shifted_value, int_type, backing_ty);
3677 const bitcasted = try func.bitcast(field_ty, int_type, truncated);3783 const bitcasted = try func.bitcast(field_ty, int_type, truncated);
3678 break :result try bitcasted.toLocal(func, field_ty);3784 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) {
3680 // In this case we do not have to perform any transformations,3786 // In this case we do not have to perform any transformations,
3681 // we can simply reuse the operand.3787 // we can simply reuse the operand.
3682 break :result func.reuseOperand(struct_field.struct_operand, operand);3788 break :result func.reuseOperand(struct_field.struct_operand, operand);
3683 } else if (field_ty.isPtrAtRuntime()) {3789 } else if (field_ty.isPtrAtRuntime(mod)) {
3684 var payload: Type.Payload.Bits = .{3790 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
3685 .base = .{ .tag = .int_unsigned },
3686 .data = @intCast(u16, field_ty.bitSize(func.target)),
3687 };
3688 const int_type = Type.initPayload(&payload.base);
3689 const truncated = try func.trunc(shifted_value, int_type, backing_ty);3791 const truncated = try func.trunc(shifted_value, int_type, backing_ty);
3690 break :result try truncated.toLocal(func, field_ty);3792 break :result try truncated.toLocal(func, field_ty);
3691 }3793 }
...@@ -3693,8 +3795,8 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3693,8 +3795,8 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3693 break :result try truncated.toLocal(func, field_ty);3795 break :result try truncated.toLocal(func, field_ty);
3694 },3796 },
3695 .Union => result: {3797 .Union => result: {
3696 if (isByRef(struct_ty, func.target)) {3798 if (isByRef(struct_ty, mod)) {
3697 if (!isByRef(field_ty, func.target)) {3799 if (!isByRef(field_ty, mod)) {
3698 const val = try func.load(operand, field_ty, 0);3800 const val = try func.load(operand, field_ty, 0);
3699 break :result try val.toLocal(func, field_ty);3801 break :result try val.toLocal(func, field_ty);
3700 } else {3802 } else {
...@@ -3704,26 +3806,14 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3704,26 +3806,14 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3704 }3806 }
3705 }3807 }
37063808
3707 var payload: Type.Payload.Bits = .{3809 const union_int_type = try mod.intType(.unsigned, @intCast(u16, struct_ty.bitSize(mod)));
3708 .base = .{ .tag = .int_unsigned },3810 if (field_ty.zigTypeTag(mod) == .Float) {
3709 .data = @intCast(u16, struct_ty.bitSize(func.target)),3811 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
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);
3718 const truncated = try func.trunc(operand, int_type, union_int_type);3812 const truncated = try func.trunc(operand, int_type, union_int_type);
3719 const bitcasted = try func.bitcast(field_ty, int_type, truncated);3813 const bitcasted = try func.bitcast(field_ty, int_type, truncated);
3720 break :result try bitcasted.toLocal(func, field_ty);3814 break :result try bitcasted.toLocal(func, field_ty);
3721 } else if (field_ty.isPtrAtRuntime()) {3815 } else if (field_ty.isPtrAtRuntime(mod)) {
3722 var int_payload: Type.Payload.Bits = .{3816 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
3723 .base = .{ .tag = .int_unsigned },
3724 .data = @intCast(u16, field_ty.bitSize(func.target)),
3725 };
3726 const int_type = Type.initPayload(&int_payload.base);
3727 const truncated = try func.trunc(operand, int_type, union_int_type);3817 const truncated = try func.trunc(operand, int_type, union_int_type);
3728 break :result try truncated.toLocal(func, field_ty);3818 break :result try truncated.toLocal(func, field_ty);
3729 }3819 }
...@@ -3733,11 +3823,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3733,11 +3823,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3733 else => unreachable,3823 else => unreachable,
3734 },3824 },
3735 else => result: {3825 else => result: {
3736 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, func.target)) orelse {3826 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, mod)) orelse {
3737 const module = func.bin_file.base.options.module.?;3827 return func.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(mod)});
3738 return func.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(module)});
3739 };3828 };
3740 if (isByRef(field_ty, func.target)) {3829 if (isByRef(field_ty, mod)) {
3741 switch (operand) {3830 switch (operand) {
3742 .stack_offset => |stack_offset| {3831 .stack_offset => |stack_offset| {
3743 break :result WValue{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } };3832 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 {...@@ -3754,11 +3843,12 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3754}3843}
37553844
3756fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3845fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3846 const mod = func.bin_file.base.options.module.?;
3757 // result type is always 'noreturn'3847 // result type is always 'noreturn'
3758 const blocktype = wasm.block_empty;3848 const blocktype = wasm.block_empty;
3759 const pl_op = func.air.instructions.items(.data)[inst].pl_op;3849 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
3760 const target = try func.resolveInst(pl_op.operand);3850 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);
3762 const switch_br = func.air.extraData(Air.SwitchBr, pl_op.payload);3852 const switch_br = func.air.extraData(Air.SwitchBr, pl_op.payload);
3763 const liveness = try func.liveness.getSwitchBr(func.gpa, inst, switch_br.data.cases_len + 1);3853 const liveness = try func.liveness.getSwitchBr(func.gpa, inst, switch_br.data.cases_len + 1);
3764 defer func.gpa.free(liveness.deaths);3854 defer func.gpa.free(liveness.deaths);
...@@ -3787,7 +3877,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3787,7 +3877,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3787 errdefer func.gpa.free(values);3877 errdefer func.gpa.free(values);
37883878
3789 for (items, 0..) |ref, i| {3879 for (items, 0..) |ref, i| {
3790 const item_val = func.air.value(ref).?;3880 const item_val = (try func.air.value(ref, mod)).?;
3791 const int_val = func.valueAsI32(item_val, target_ty);3881 const int_val = func.valueAsI32(item_val, target_ty);
3792 if (lowest_maybe == null or int_val < lowest_maybe.?) {3882 if (lowest_maybe == null or int_val < lowest_maybe.?) {
3793 lowest_maybe = int_val;3883 lowest_maybe = int_val;
...@@ -3810,7 +3900,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3810,7 +3900,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3810 // When the target is an integer size larger than u32, we have no way to use the value3900 // When the target is an integer size larger than u32, we have no way to use the value
3811 // as an index, therefore we also use an if/else-chain for those cases.3901 // as an index, therefore we also use an if/else-chain for those cases.
3812 // TODO: Benchmark this to find a proper value, LLVM seems to draw the line at '40~45'.3902 // 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
3815 const else_body = func.air.extra[extra_index..][0..switch_br.data.else_body_len];3905 const else_body = func.air.extra[extra_index..][0..switch_br.data.else_body_len];
3816 const has_else_body = else_body.len != 0;3906 const has_else_body = else_body.len != 0;
...@@ -3855,7 +3945,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3855,7 +3945,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3855 // for errors that are not present in any branch. This is fine as this default3945 // for errors that are not present in any branch. This is fine as this default
3856 // case will never be hit for those cases but we do save runtime cost and size3946 // case will never be hit for those cases but we do save runtime cost and size
3857 // by using a jump table for this instead of if-else chains.3947 // 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;
3859 };3949 };
3860 func.mir_extra.appendAssumeCapacity(idx);3950 func.mir_extra.appendAssumeCapacity(idx);
3861 } else if (has_else_body) {3951 } else if (has_else_body) {
...@@ -3866,10 +3956,10 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3866,10 +3956,10 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38663956
3867 const signedness: std.builtin.Signedness = blk: {3957 const signedness: std.builtin.Signedness = blk: {
3868 // by default we tell the operand type is unsigned (i.e. bools and enum values)3958 // 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
3871 // incase of an actual integer, we emit the correct signedness3961 // 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;
3873 };3963 };
38743964
3875 try func.branches.ensureUnusedCapacity(func.gpa, case_list.items.len + @boolToInt(has_else_body));3965 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 {...@@ -3882,7 +3972,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3882 const val = try func.lowerConstant(case.values[0].value, target_ty);3972 const val = try func.lowerConstant(case.values[0].value, target_ty);
3883 try func.emitWValue(val);3973 try func.emitWValue(val);
3884 const opcode = buildOpcode(.{3974 const opcode = buildOpcode(.{
3885 .valtype1 = typeToValtype(target_ty, func.target),3975 .valtype1 = typeToValtype(target_ty, mod),
3886 .op = .ne, // not equal, because we want to jump out of this block if it does not match the condition.3976 .op = .ne, // not equal, because we want to jump out of this block if it does not match the condition.
3887 .signedness = signedness,3977 .signedness = signedness,
3888 });3978 });
...@@ -3896,7 +3986,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3896,7 +3986,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3896 const val = try func.lowerConstant(value.value, target_ty);3986 const val = try func.lowerConstant(value.value, target_ty);
3897 try func.emitWValue(val);3987 try func.emitWValue(val);
3898 const opcode = buildOpcode(.{3988 const opcode = buildOpcode(.{
3899 .valtype1 = typeToValtype(target_ty, func.target),3989 .valtype1 = typeToValtype(target_ty, mod),
3900 .op = .eq,3990 .op = .eq,
3901 .signedness = signedness,3991 .signedness = signedness,
3902 });3992 });
...@@ -3933,13 +4023,14 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3933,13 +4023,14 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3933}4023}
39344024
3935fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void {4025fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void {
4026 const mod = func.bin_file.base.options.module.?;
3936 const un_op = func.air.instructions.items(.data)[inst].un_op;4027 const un_op = func.air.instructions.items(.data)[inst].un_op;
3937 const operand = try func.resolveInst(un_op);4028 const operand = try func.resolveInst(un_op);
3938 const err_union_ty = func.air.typeOf(un_op);4029 const err_union_ty = func.typeOf(un_op);
3939 const pl_ty = err_union_ty.errorUnionPayload();4030 const pl_ty = err_union_ty.errorUnionPayload(mod);
39404031
3941 const result = result: {4032 const result = result: {
3942 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {4033 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
3943 switch (opcode) {4034 switch (opcode) {
3944 .i32_ne => break :result WValue{ .imm32 = 0 },4035 .i32_ne => break :result WValue{ .imm32 = 0 },
3945 .i32_eq => break :result WValue{ .imm32 = 1 },4036 .i32_eq => break :result WValue{ .imm32 = 1 },
...@@ -3948,10 +4039,10 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro...@@ -3948,10 +4039,10 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
3948 }4039 }
39494040
3950 try func.emitWValue(operand);4041 try func.emitWValue(operand);
3951 if (pl_ty.hasRuntimeBitsIgnoreComptime()) {4042 if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3952 try func.addMemArg(.i32_load16_u, .{4043 try func.addMemArg(.i32_load16_u, .{
3953 .offset = operand.offset() + @intCast(u32, errUnionErrorOffset(pl_ty, func.target)),4044 .offset = operand.offset() + @intCast(u32, errUnionErrorOffset(pl_ty, mod)),
3954 .alignment = Type.anyerror.abiAlignment(func.target),4045 .alignment = Type.anyerror.abiAlignment(mod),
3955 });4046 });
3956 }4047 }
39574048
...@@ -3967,23 +4058,24 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro...@@ -3967,23 +4058,24 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
3967}4058}
39684059
3969fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {4060fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {
4061 const mod = func.bin_file.base.options.module.?;
3970 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4062 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
39714063
3972 const operand = try func.resolveInst(ty_op.operand);4064 const operand = try func.resolveInst(ty_op.operand);
3973 const op_ty = func.air.typeOf(ty_op.operand);4065 const op_ty = func.typeOf(ty_op.operand);
3974 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;4066 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
3975 const payload_ty = err_ty.errorUnionPayload();4067 const payload_ty = err_ty.errorUnionPayload(mod);
39764068
3977 const result = result: {4069 const result = result: {
3978 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4070 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3979 if (op_is_ptr) {4071 if (op_is_ptr) {
3980 break :result func.reuseOperand(ty_op.operand, operand);4072 break :result func.reuseOperand(ty_op.operand, operand);
3981 }4073 }
3982 break :result WValue{ .none = {} };4074 break :result WValue{ .none = {} };
3983 }4075 }
39844076
3985 const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, func.target));4077 const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
3986 if (op_is_ptr or isByRef(payload_ty, func.target)) {4078 if (op_is_ptr or isByRef(payload_ty, mod)) {
3987 break :result try func.buildPointerOffset(operand, pl_offset, .new);4079 break :result try func.buildPointerOffset(operand, pl_offset, .new);
3988 }4080 }
39894081
...@@ -3994,48 +4086,50 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo...@@ -3994,48 +4086,50 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo
3994}4086}
39954087
3996fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {4088fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {
4089 const mod = func.bin_file.base.options.module.?;
3997 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4090 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
39984091
3999 const operand = try func.resolveInst(ty_op.operand);4092 const operand = try func.resolveInst(ty_op.operand);
4000 const op_ty = func.air.typeOf(ty_op.operand);4093 const op_ty = func.typeOf(ty_op.operand);
4001 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;4094 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
4002 const payload_ty = err_ty.errorUnionPayload();4095 const payload_ty = err_ty.errorUnionPayload(mod);
40034096
4004 const result = result: {4097 const result = result: {
4005 if (err_ty.errorUnionSet().errorSetIsEmpty()) {4098 if (err_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
4006 break :result WValue{ .imm32 = 0 };4099 break :result WValue{ .imm32 = 0 };
4007 }4100 }
40084101
4009 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime()) {4102 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4010 break :result func.reuseOperand(ty_op.operand, operand);4103 break :result func.reuseOperand(ty_op.operand, operand);
4011 }4104 }
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)));
4014 break :result try error_val.toLocal(func, Type.anyerror);4107 break :result try error_val.toLocal(func, Type.anyerror);
4015 };4108 };
4016 func.finishAir(inst, result, &.{ty_op.operand});4109 func.finishAir(inst, result, &.{ty_op.operand});
4017}4110}
40184111
4019fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4112fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4113 const mod = func.bin_file.base.options.module.?;
4020 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4114 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
40214115
4022 const operand = try func.resolveInst(ty_op.operand);4116 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);
4026 const result = result: {4120 const result = result: {
4027 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {4121 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4028 break :result func.reuseOperand(ty_op.operand, operand);4122 break :result func.reuseOperand(ty_op.operand, operand);
4029 }4123 }
40304124
4031 const err_union = try func.allocStack(err_ty);4125 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);
4033 try func.store(payload_ptr, operand, pl_ty, 0);4127 try func.store(payload_ptr, operand, pl_ty, 0);
40344128
4035 // ensure we also write '0' to the error part, so any present stack value gets overwritten by it.4129 // ensure we also write '0' to the error part, so any present stack value gets overwritten by it.
4036 try func.emitWValue(err_union);4130 try func.emitWValue(err_union);
4037 try func.addImm32(0);4131 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));
4039 try func.addMemArg(.i32_store16, .{ .offset = err_union.offset() + err_val_offset, .alignment = 2 });4133 try func.addMemArg(.i32_store16, .{ .offset = err_union.offset() + err_val_offset, .alignment = 2 });
4040 break :result err_union;4134 break :result err_union;
4041 };4135 };
...@@ -4043,24 +4137,25 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void...@@ -4043,24 +4137,25 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void
4043}4137}
40444138
4045fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4139fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4140 const mod = func.bin_file.base.options.module.?;
4046 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4141 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
40474142
4048 const operand = try func.resolveInst(ty_op.operand);4143 const operand = try func.resolveInst(ty_op.operand);
4049 const err_ty = func.air.getRefType(ty_op.ty);4144 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
4052 const result = result: {4147 const result = result: {
4053 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {4148 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4054 break :result func.reuseOperand(ty_op.operand, operand);4149 break :result func.reuseOperand(ty_op.operand, operand);
4055 }4150 }
40564151
4057 const err_union = try func.allocStack(err_ty);4152 const err_union = try func.allocStack(err_ty);
4058 // store error value4153 // 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
4061 // write 'undefined' to the payload4156 // write 'undefined' to the payload
4062 const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, func.target)), .new);4157 const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, mod)), .new);
4063 const len = @intCast(u32, err_ty.errorUnionPayload().abiSize(func.target));4158 const len = @intCast(u32, err_ty.errorUnionPayload(mod).abiSize(mod));
4064 try func.memset(Type.u8, payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaa });4159 try func.memset(Type.u8, payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaa });
40654160
4066 break :result err_union;4161 break :result err_union;
...@@ -4073,16 +4168,17 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4073,16 +4168,17 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
40734168
4074 const ty = func.air.getRefType(ty_op.ty);4169 const ty = func.air.getRefType(ty_op.ty);
4075 const operand = try func.resolveInst(ty_op.operand);4170 const operand = try func.resolveInst(ty_op.operand);
4076 const operand_ty = func.air.typeOf(ty_op.operand);4171 const operand_ty = func.typeOf(ty_op.operand);
4077 if (ty.zigTypeTag() == .Vector or operand_ty.zigTypeTag() == .Vector) {4172 const mod = func.bin_file.base.options.module.?;
4173 if (ty.zigTypeTag(mod) == .Vector or operand_ty.zigTypeTag(mod) == .Vector) {
4078 return func.fail("todo Wasm intcast for vectors", .{});4174 return func.fail("todo Wasm intcast for vectors", .{});
4079 }4175 }
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) {
4081 return func.fail("todo Wasm intcast for bitsize > 128", .{});4177 return func.fail("todo Wasm intcast for bitsize > 128", .{});
4082 }4178 }
40834179
4084 const op_bits = toWasmBits(@intCast(u16, operand_ty.bitSize(func.target))).?;4180 const op_bits = toWasmBits(@intCast(u16, operand_ty.bitSize(mod))).?;
4085 const wanted_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?;4181 const wanted_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?;
4086 const result = if (op_bits == wanted_bits)4182 const result = if (op_bits == wanted_bits)
4087 func.reuseOperand(ty_op.operand, operand)4183 func.reuseOperand(ty_op.operand, operand)
4088 else4184 else
...@@ -4096,8 +4192,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4096,8 +4192,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4096/// Asserts type's bitsize <= 1284192/// Asserts type's bitsize <= 128
4097/// NOTE: May leave the result on the top of the stack.4193/// NOTE: May leave the result on the top of the stack.
4098fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue {4194fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue {
4099 const given_bitsize = @intCast(u16, given.bitSize(func.target));4195 const mod = func.bin_file.base.options.module.?;
4100 const wanted_bitsize = @intCast(u16, wanted.bitSize(func.target));4196 const given_bitsize = @intCast(u16, given.bitSize(mod));
4197 const wanted_bitsize = @intCast(u16, wanted.bitSize(mod));
4101 assert(given_bitsize <= 128);4198 assert(given_bitsize <= 128);
4102 assert(wanted_bitsize <= 128);4199 assert(wanted_bitsize <= 128);
41034200
...@@ -4110,7 +4207,7 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro...@@ -4110,7 +4207,7 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
4110 try func.addTag(.i32_wrap_i64);4207 try func.addTag(.i32_wrap_i64);
4111 } else if (op_bits == 32 and wanted_bits > 32 and wanted_bits <= 64) {4208 } else if (op_bits == 32 and wanted_bits > 32 and wanted_bits <= 64) {
4112 try func.emitWValue(operand);4209 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);
4114 } else if (wanted_bits == 128) {4211 } else if (wanted_bits == 128) {
4115 // for 128bit integers we store the integer in the virtual stack, rather than a local4212 // for 128bit integers we store the integer in the virtual stack, rather than a local
4116 const stack_ptr = try func.allocStack(wanted);4213 const stack_ptr = try func.allocStack(wanted);
...@@ -4119,14 +4216,14 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro...@@ -4119,14 +4216,14 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
4119 // for 32 bit integers, we first coerce the value into a 64 bit integer before storing it4216 // for 32 bit integers, we first coerce the value into a 64 bit integer before storing it
4120 // meaning less store operations are required.4217 // meaning less store operations are required.
4121 const lhs = if (op_bits == 32) blk: {4218 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);
4123 } else operand;4220 } else operand;
41244221
4125 // store msb first4222 // store msb first
4126 try func.store(.{ .stack = {} }, lhs, Type.u64, 0 + stack_ptr.offset());4223 try func.store(.{ .stack = {} }, lhs, Type.u64, 0 + stack_ptr.offset());
41274224
4128 // For signed integers we shift msb by 63 (64bit integer - 1 sign bit) and store remaining value4225 // 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)) {
4130 try func.emitWValue(stack_ptr);4227 try func.emitWValue(stack_ptr);
4131 const shr = try func.binOp(lhs, .{ .imm64 = 63 }, Type.i64, .shr);4228 const shr = try func.binOp(lhs, .{ .imm64 = 63 }, Type.i64, .shr);
4132 try func.store(.{ .stack = {} }, shr, Type.u64, 8 + stack_ptr.offset());4229 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...@@ -4141,11 +4238,12 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
4141}4238}
41424239
4143fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: enum { value, ptr }) InnerError!void {4240fn 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.?;
4144 const un_op = func.air.instructions.items(.data)[inst].un_op;4242 const un_op = func.air.instructions.items(.data)[inst].un_op;
4145 const operand = try func.resolveInst(un_op);4243 const operand = try func.resolveInst(un_op);
41464244
4147 const op_ty = func.air.typeOf(un_op);4245 const op_ty = func.typeOf(un_op);
4148 const optional_ty = if (op_kind == .ptr) op_ty.childType() else op_ty;4246 const optional_ty = if (op_kind == .ptr) op_ty.childType(mod) else op_ty;
4149 const is_null = try func.isNull(operand, optional_ty, opcode);4247 const is_null = try func.isNull(operand, optional_ty, opcode);
4150 const result = try is_null.toLocal(func, optional_ty);4248 const result = try is_null.toLocal(func, optional_ty);
4151 func.finishAir(inst, result, &.{un_op});4249 func.finishAir(inst, result, &.{un_op});
...@@ -4154,20 +4252,19 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind:...@@ -4154,20 +4252,19 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind:
4154/// For a given type and operand, checks if it's considered `null`.4252/// For a given type and operand, checks if it's considered `null`.
4155/// NOTE: Leaves the result on the stack4253/// NOTE: Leaves the result on the stack
4156fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue {4254fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue {
4255 const mod = func.bin_file.base.options.module.?;
4157 try func.emitWValue(operand);4256 try func.emitWValue(operand);
4158 var buf: Type.Payload.ElemType = undefined;4257 const payload_ty = optional_ty.optionalChild(mod);
4159 const payload_ty = optional_ty.optionalChild(&buf);4258 if (!optional_ty.optionalReprIsPayload(mod)) {
4160 if (!optional_ty.optionalReprIsPayload()) {
4161 // When payload is zero-bits, we can treat operand as a value, rather than4259 // When payload is zero-bits, we can treat operand as a value, rather than
4162 // a pointer to the stack value4260 // a pointer to the stack value
4163 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {4261 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4164 const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse {4262 const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse {
4165 const module = func.bin_file.base.options.module.?;4263 return func.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(mod)});
4166 return func.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(module)});
4167 };4264 };
4168 try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });4265 try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });
4169 }4266 }
4170 } else if (payload_ty.isSlice()) {4267 } else if (payload_ty.isSlice(mod)) {
4171 switch (func.arch()) {4268 switch (func.arch()) {
4172 .wasm32 => try func.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }),4269 .wasm32 => try func.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }),
4173 .wasm64 => try func.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = 8 }),4270 .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...@@ -4183,18 +4280,19 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod
4183}4280}
41844281
4185fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4282fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4283 const mod = func.bin_file.base.options.module.?;
4186 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4284 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
4187 const opt_ty = func.air.typeOf(ty_op.operand);4285 const opt_ty = func.typeOf(ty_op.operand);
4188 const payload_ty = func.air.typeOfIndex(inst);4286 const payload_ty = func.typeOfIndex(inst);
4189 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4287 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4190 return func.finishAir(inst, .none, &.{ty_op.operand});4288 return func.finishAir(inst, .none, &.{ty_op.operand});
4191 }4289 }
41924290
4193 const result = result: {4291 const result = result: {
4194 const operand = try func.resolveInst(ty_op.operand);4292 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)) {
4198 break :result try func.buildPointerOffset(operand, 0, .new);4296 break :result try func.buildPointerOffset(operand, 0, .new);
4199 }4297 }
42004298
...@@ -4205,14 +4303,14 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4205,14 +4303,14 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4205}4303}
42064304
4207fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4305fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4306 const mod = func.bin_file.base.options.module.?;
4208 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4307 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
4209 const operand = try func.resolveInst(ty_op.operand);4308 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
4212 const result = result: {4311 const result = result: {
4213 var buf: Type.Payload.ElemType = undefined;4312 const payload_ty = opt_ty.optionalChild(mod);
4214 const payload_ty = opt_ty.optionalChild(&buf);4313 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or opt_ty.optionalReprIsPayload(mod)) {
4215 if (!payload_ty.hasRuntimeBitsIgnoreComptime() or opt_ty.optionalReprIsPayload()) {
4216 break :result func.reuseOperand(ty_op.operand, operand);4314 break :result func.reuseOperand(ty_op.operand, operand);
4217 }4315 }
42184316
...@@ -4222,22 +4320,21 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4222,22 +4320,21 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4222}4320}
42234321
4224fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4322fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4323 const mod = func.bin_file.base.options.module.?;
4225 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4324 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
4226 const operand = try func.resolveInst(ty_op.operand);4325 const operand = try func.resolveInst(ty_op.operand);
4227 const opt_ty = func.air.typeOf(ty_op.operand).childType();4326 const opt_ty = func.typeOf(ty_op.operand).childType(mod);
4228 var buf: Type.Payload.ElemType = undefined;4327 const payload_ty = opt_ty.optionalChild(mod);
4229 const payload_ty = opt_ty.optionalChild(&buf);4328 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4230 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4231 return func.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()});4329 return func.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()});
4232 }4330 }
42334331
4234 if (opt_ty.optionalReprIsPayload()) {4332 if (opt_ty.optionalReprIsPayload(mod)) {
4235 return func.finishAir(inst, operand, &.{ty_op.operand});4333 return func.finishAir(inst, operand, &.{ty_op.operand});
4236 }4334 }
42374335
4238 const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse {4336 const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse {
4239 const module = func.bin_file.base.options.module.?;4337 return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(mod)});
4240 return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(module)});
4241 };4338 };
42424339
4243 try func.emitWValue(operand);4340 try func.emitWValue(operand);
...@@ -4250,11 +4347,12 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi...@@ -4250,11 +4347,12 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi
42504347
4251fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4348fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4252 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4349 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
4255 const result = result: {4353 const result = result: {
4256 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4354 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4257 const non_null_bit = try func.allocStack(Type.initTag(.u1));4355 const non_null_bit = try func.allocStack(Type.u1);
4258 try func.emitWValue(non_null_bit);4356 try func.emitWValue(non_null_bit);
4259 try func.addImm32(1);4357 try func.addImm32(1);
4260 try func.addMemArg(.i32_store8, .{ .offset = non_null_bit.offset(), .alignment = 1 });4358 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 {...@@ -4262,13 +4360,12 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4262 }4360 }
42634361
4264 const operand = try func.resolveInst(ty_op.operand);4362 const operand = try func.resolveInst(ty_op.operand);
4265 const op_ty = func.air.typeOfIndex(inst);4363 const op_ty = func.typeOfIndex(inst);
4266 if (op_ty.optionalReprIsPayload()) {4364 if (op_ty.optionalReprIsPayload(mod)) {
4267 break :result func.reuseOperand(ty_op.operand, operand);4365 break :result func.reuseOperand(ty_op.operand, operand);
4268 }4366 }
4269 const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse {4367 const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse {
4270 const module = func.bin_file.base.options.module.?;4368 return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(mod)});
4271 return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(module)});
4272 };4369 };
42734370
4274 // Create optional type, set the non-null bit, and store the operand inside the optional type4371 // 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 {...@@ -4291,7 +4388,7 @@ fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
42914388
4292 const lhs = try func.resolveInst(bin_op.lhs);4389 const lhs = try func.resolveInst(bin_op.lhs);
4293 const rhs = try func.resolveInst(bin_op.rhs);4390 const rhs = try func.resolveInst(bin_op.rhs);
4294 const slice_ty = func.air.typeOfIndex(inst);4391 const slice_ty = func.typeOfIndex(inst);
42954392
4296 const slice = try func.allocStack(slice_ty);4393 const slice = try func.allocStack(slice_ty);
4297 try func.store(slice, lhs, Type.usize, 0);4394 try func.store(slice, lhs, Type.usize, 0);
...@@ -4308,13 +4405,14 @@ fn airSliceLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4308,13 +4405,14 @@ fn airSliceLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4308}4405}
43094406
4310fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4407fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4408 const mod = func.bin_file.base.options.module.?;
4311 const bin_op = func.air.instructions.items(.data)[inst].bin_op;4409 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);
4314 const slice = try func.resolveInst(bin_op.lhs);4412 const slice = try func.resolveInst(bin_op.lhs);
4315 const index = try func.resolveInst(bin_op.rhs);4413 const index = try func.resolveInst(bin_op.rhs);
4316 const elem_ty = slice_ty.childType();4414 const elem_ty = slice_ty.childType(mod);
4317 const elem_size = elem_ty.abiSize(func.target);4415 const elem_size = elem_ty.abiSize(mod);
43184416
4319 // load pointer onto stack4417 // load pointer onto stack
4320 _ = try func.load(slice, Type.usize, 0);4418 _ = try func.load(slice, Type.usize, 0);
...@@ -4328,7 +4426,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4328,7 +4426,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4328 const result_ptr = try func.allocLocal(Type.usize);4426 const result_ptr = try func.allocLocal(Type.usize);
4329 try func.addLabel(.local_set, result_ptr.local.value);4427 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: {
4332 const elem_val = try func.load(result_ptr, elem_ty, 0);4430 const elem_val = try func.load(result_ptr, elem_ty, 0);
4333 break :result try elem_val.toLocal(func, elem_ty);4431 break :result try elem_val.toLocal(func, elem_ty);
4334 } else result_ptr;4432 } else result_ptr;
...@@ -4337,11 +4435,12 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4337,11 +4435,12 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4337}4435}
43384436
4339fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4437fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4438 const mod = func.bin_file.base.options.module.?;
4340 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;4439 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
4341 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;4440 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
43424441
4343 const elem_ty = func.air.getRefType(ty_pl.ty).childType();4442 const elem_ty = func.air.getRefType(ty_pl.ty).childType(mod);
4344 const elem_size = elem_ty.abiSize(func.target);4443 const elem_size = elem_ty.abiSize(mod);
43454444
4346 const slice = try func.resolveInst(bin_op.lhs);4445 const slice = try func.resolveInst(bin_op.lhs);
4347 const index = try func.resolveInst(bin_op.rhs);4446 const index = try func.resolveInst(bin_op.rhs);
...@@ -4380,7 +4479,7 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4380,7 +4479,7 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43804479
4381 const operand = try func.resolveInst(ty_op.operand);4480 const operand = try func.resolveInst(ty_op.operand);
4382 const wanted_ty = func.air.getRefType(ty_op.ty);4481 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
4385 const result = try func.trunc(operand, wanted_ty, op_ty);4484 const result = try func.trunc(operand, wanted_ty, op_ty);
4386 func.finishAir(inst, try result.toLocal(func, wanted_ty), &.{ty_op.operand});4485 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 {...@@ -4389,13 +4488,14 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4389/// Truncates a given operand to a given type, discarding any overflown bits.4488/// Truncates a given operand to a given type, discarding any overflown bits.
4390/// NOTE: Resulting value is left on the stack.4489/// NOTE: Resulting value is left on the stack.
4391fn trunc(func: *CodeGen, operand: WValue, wanted_ty: Type, given_ty: Type) InnerError!WValue {4490fn 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));
4393 if (toWasmBits(given_bits) == null) {4493 if (toWasmBits(given_bits) == null) {
4394 return func.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{given_bits});4494 return func.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{given_bits});
4395 }4495 }
43964496
4397 var result = try func.intcast(operand, given_ty, wanted_ty);4497 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));
4399 const wasm_bits = toWasmBits(wanted_bits).?;4499 const wasm_bits = toWasmBits(wanted_bits).?;
4400 if (wasm_bits != wanted_bits) {4500 if (wasm_bits != wanted_bits) {
4401 result = try func.wrapOperand(result, wanted_ty);4501 result = try func.wrapOperand(result, wanted_ty);
...@@ -4412,32 +4512,34 @@ fn airBoolToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4412,32 +4512,34 @@ fn airBoolToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4412}4512}
44134513
4414fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4514fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4515 const mod = func.bin_file.base.options.module.?;
4415 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4516 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
44164517
4417 const operand = try func.resolveInst(ty_op.operand);4518 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);
4419 const slice_ty = func.air.getRefType(ty_op.ty);4520 const slice_ty = func.air.getRefType(ty_op.ty);
44204521
4421 // create a slice on the stack4522 // create a slice on the stack
4422 const slice_local = try func.allocStack(slice_ty);4523 const slice_local = try func.allocStack(slice_ty);
44234524
4424 // store the array ptr in the slice4525 // store the array ptr in the slice
4425 if (array_ty.hasRuntimeBitsIgnoreComptime()) {4526 if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4426 try func.store(slice_local, operand, Type.usize, 0);4527 try func.store(slice_local, operand, Type.usize, 0);
4427 }4528 }
44284529
4429 // store the length of the array in the slice4530 // 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)) };
4431 try func.store(slice_local, len, Type.usize, func.ptrSize());4532 try func.store(slice_local, len, Type.usize, func.ptrSize());
44324533
4433 func.finishAir(inst, slice_local, &.{ty_op.operand});4534 func.finishAir(inst, slice_local, &.{ty_op.operand});
4434}4535}
44354536
4436fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4537fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4538 const mod = func.bin_file.base.options.module.?;
4437 const un_op = func.air.instructions.items(.data)[inst].un_op;4539 const un_op = func.air.instructions.items(.data)[inst].un_op;
4438 const operand = try func.resolveInst(un_op);4540 const operand = try func.resolveInst(un_op);
4439 const ptr_ty = func.air.typeOf(un_op);4541 const ptr_ty = func.typeOf(un_op);
4440 const result = if (ptr_ty.isSlice())4542 const result = if (ptr_ty.isSlice(mod))
4441 try func.slicePtr(operand)4543 try func.slicePtr(operand)
4442 else switch (operand) {4544 else switch (operand) {
4443 // for stack offset, return a pointer to this offset.4545 // for stack offset, return a pointer to this offset.
...@@ -4448,16 +4550,17 @@ fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4448,16 +4550,17 @@ fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4448}4550}
44494551
4450fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4552fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4553 const mod = func.bin_file.base.options.module.?;
4451 const bin_op = func.air.instructions.items(.data)[inst].bin_op;4554 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);
4454 const ptr = try func.resolveInst(bin_op.lhs);4557 const ptr = try func.resolveInst(bin_op.lhs);
4455 const index = try func.resolveInst(bin_op.rhs);4558 const index = try func.resolveInst(bin_op.rhs);
4456 const elem_ty = ptr_ty.childType();4559 const elem_ty = ptr_ty.childType(mod);
4457 const elem_size = elem_ty.abiSize(func.target);4560 const elem_size = elem_ty.abiSize(mod);
44584561
4459 // load pointer onto the stack4562 // load pointer onto the stack
4460 if (ptr_ty.isSlice()) {4563 if (ptr_ty.isSlice(mod)) {
4461 _ = try func.load(ptr, Type.usize, 0);4564 _ = try func.load(ptr, Type.usize, 0);
4462 } else {4565 } else {
4463 try func.lowerToStack(ptr);4566 try func.lowerToStack(ptr);
...@@ -4472,7 +4575,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4472,7 +4575,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4472 const elem_result = val: {4575 const elem_result = val: {
4473 var result = try func.allocLocal(Type.usize);4576 var result = try func.allocLocal(Type.usize);
4474 try func.addLabel(.local_set, result.local.value);4577 try func.addLabel(.local_set, result.local.value);
4475 if (isByRef(elem_ty, func.target)) {4578 if (isByRef(elem_ty, mod)) {
4476 break :val result;4579 break :val result;
4477 }4580 }
4478 defer result.free(func); // only free if it's not returned like above4581 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 {...@@ -4484,18 +4587,19 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4484}4587}
44854588
4486fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4589fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4590 const mod = func.bin_file.base.options.module.?;
4487 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;4591 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
4488 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;4592 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
44894593
4490 const ptr_ty = func.air.typeOf(bin_op.lhs);4594 const ptr_ty = func.typeOf(bin_op.lhs);
4491 const elem_ty = func.air.getRefType(ty_pl.ty).childType();4595 const elem_ty = func.air.getRefType(ty_pl.ty).childType(mod);
4492 const elem_size = elem_ty.abiSize(func.target);4596 const elem_size = elem_ty.abiSize(mod);
44934597
4494 const ptr = try func.resolveInst(bin_op.lhs);4598 const ptr = try func.resolveInst(bin_op.lhs);
4495 const index = try func.resolveInst(bin_op.rhs);4599 const index = try func.resolveInst(bin_op.rhs);
44964600
4497 // load pointer onto the stack4601 // load pointer onto the stack
4498 if (ptr_ty.isSlice()) {4602 if (ptr_ty.isSlice(mod)) {
4499 _ = try func.load(ptr, Type.usize, 0);4603 _ = try func.load(ptr, Type.usize, 0);
4500 } else {4604 } else {
4501 try func.lowerToStack(ptr);4605 try func.lowerToStack(ptr);
...@@ -4513,24 +4617,25 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4513,24 +4617,25 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4513}4617}
45144618
4515fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {4619fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
4620 const mod = func.bin_file.base.options.module.?;
4516 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;4621 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
4517 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;4622 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
45184623
4519 const ptr = try func.resolveInst(bin_op.lhs);4624 const ptr = try func.resolveInst(bin_op.lhs);
4520 const offset = try func.resolveInst(bin_op.rhs);4625 const offset = try func.resolveInst(bin_op.rhs);
4521 const ptr_ty = func.air.typeOf(bin_op.lhs);4626 const ptr_ty = func.typeOf(bin_op.lhs);
4522 const pointee_ty = switch (ptr_ty.ptrSize()) {4627 const pointee_ty = switch (ptr_ty.ptrSize(mod)) {
4523 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type4628 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
4524 else => ptr_ty.childType(),4629 else => ptr_ty.childType(mod),
4525 };4630 };
45264631
4527 const valtype = typeToValtype(Type.usize, func.target);4632 const valtype = typeToValtype(Type.usize, mod);
4528 const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul });4633 const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul });
4529 const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op });4634 const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op });
45304635
4531 try func.lowerToStack(ptr);4636 try func.lowerToStack(ptr);
4532 try func.emitWValue(offset);4637 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))));
4534 try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode));4639 try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode));
4535 try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode));4640 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 {...@@ -4540,6 +4645,7 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
4540}4645}
45414646
4542fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {4647fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
4648 const mod = func.bin_file.base.options.module.?;
4543 if (safety) {4649 if (safety) {
4544 // TODO if the value is undef, write 0xaa bytes to dest4650 // TODO if the value is undef, write 0xaa bytes to dest
4545 } else {4651 } else {
...@@ -4548,18 +4654,18 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void...@@ -4548,18 +4654,18 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
4548 const bin_op = func.air.instructions.items(.data)[inst].bin_op;4654 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
45494655
4550 const ptr = try func.resolveInst(bin_op.lhs);4656 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);
4552 const value = try func.resolveInst(bin_op.rhs);4658 const value = try func.resolveInst(bin_op.rhs);
4553 const len = switch (ptr_ty.ptrSize()) {4659 const len = switch (ptr_ty.ptrSize(mod)) {
4554 .Slice => try func.sliceLen(ptr),4660 .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)) }),
4556 .C, .Many => unreachable,4662 .C, .Many => unreachable,
4557 };4663 };
45584664
4559 const elem_ty = if (ptr_ty.ptrSize() == .One)4665 const elem_ty = if (ptr_ty.ptrSize(mod) == .One)
4560 ptr_ty.childType().childType()4666 ptr_ty.childType(mod).childType(mod)
4561 else4667 else
4562 ptr_ty.childType();4668 ptr_ty.childType(mod);
45634669
4564 const dst_ptr = try func.sliceOrArrayPtr(ptr, ptr_ty);4670 const dst_ptr = try func.sliceOrArrayPtr(ptr, ptr_ty);
4565 try func.memset(elem_ty, dst_ptr, len, value);4671 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...@@ -4572,7 +4678,8 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
4572/// this to wasm's memset instruction. When the feature is not present,4678/// this to wasm's memset instruction. When the feature is not present,
4573/// we implement it manually.4679/// we implement it manually.
4574fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) InnerError!void {4680fn 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
4577 // When bulk_memory is enabled, we lower it to wasm's memset instruction.4684 // When bulk_memory is enabled, we lower it to wasm's memset instruction.
4578 // If not, we lower it ourselves.4685 // If not, we lower it ourselves.
...@@ -4660,30 +4767,31 @@ fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue...@@ -4660,30 +4767,31 @@ fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue
4660}4767}
46614768
4662fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4769fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4770 const mod = func.bin_file.base.options.module.?;
4663 const bin_op = func.air.instructions.items(.data)[inst].bin_op;4771 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);
4666 const array = try func.resolveInst(bin_op.lhs);4774 const array = try func.resolveInst(bin_op.lhs);
4667 const index = try func.resolveInst(bin_op.rhs);4775 const index = try func.resolveInst(bin_op.rhs);
4668 const elem_ty = array_ty.childType();4776 const elem_ty = array_ty.childType(mod);
4669 const elem_size = elem_ty.abiSize(func.target);4777 const elem_size = elem_ty.abiSize(mod);
46704778
4671 if (isByRef(array_ty, func.target)) {4779 if (isByRef(array_ty, mod)) {
4672 try func.lowerToStack(array);4780 try func.lowerToStack(array);
4673 try func.emitWValue(index);4781 try func.emitWValue(index);
4674 try func.addImm32(@bitCast(i32, @intCast(u32, elem_size)));4782 try func.addImm32(@bitCast(i32, @intCast(u32, elem_size)));
4675 try func.addTag(.i32_mul);4783 try func.addTag(.i32_mul);
4676 try func.addTag(.i32_add);4784 try func.addTag(.i32_add);
4677 } else {4785 } else {
4678 std.debug.assert(array_ty.zigTypeTag() == .Vector);4786 std.debug.assert(array_ty.zigTypeTag(mod) == .Vector);
46794787
4680 switch (index) {4788 switch (index) {
4681 inline .imm32, .imm64 => |lane| {4789 inline .imm32, .imm64 => |lane| {
4682 const opcode: wasm.SimdOpcode = switch (elem_ty.bitSize(func.target)) {4790 const opcode: wasm.SimdOpcode = switch (elem_ty.bitSize(mod)) {
4683 8 => if (elem_ty.isSignedInt()) .i8x16_extract_lane_s else .i8x16_extract_lane_u,4791 8 => if (elem_ty.isSignedInt(mod)) .i8x16_extract_lane_s else .i8x16_extract_lane_u,
4684 16 => if (elem_ty.isSignedInt()) .i16x8_extract_lane_s else .i16x8_extract_lane_u,4792 16 => if (elem_ty.isSignedInt(mod)) .i16x8_extract_lane_s else .i16x8_extract_lane_u,
4685 32 => if (elem_ty.isInt()) .i32x4_extract_lane else .f32x4_extract_lane,4793 32 => if (elem_ty.isInt(mod)) .i32x4_extract_lane else .f32x4_extract_lane,
4686 64 => if (elem_ty.isInt()) .i64x2_extract_lane else .f64x2_extract_lane,4794 64 => if (elem_ty.isInt(mod)) .i64x2_extract_lane else .f64x2_extract_lane,
4687 else => unreachable,4795 else => unreachable,
4688 };4796 };
46894797
...@@ -4715,7 +4823,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4715,7 +4823,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4715 var result = try func.allocLocal(Type.usize);4823 var result = try func.allocLocal(Type.usize);
4716 try func.addLabel(.local_set, result.local.value);4824 try func.addLabel(.local_set, result.local.value);
47174825
4718 if (isByRef(elem_ty, func.target)) {4826 if (isByRef(elem_ty, mod)) {
4719 break :val result;4827 break :val result;
4720 }4828 }
4721 defer result.free(func); // only free if no longer needed and not returned like above4829 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 {...@@ -4728,22 +4836,23 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4728}4836}
47294837
4730fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4838fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4839 const mod = func.bin_file.base.options.module.?;
4731 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4840 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
47324841
4733 const operand = try func.resolveInst(ty_op.operand);4842 const operand = try func.resolveInst(ty_op.operand);
4734 const dest_ty = func.air.typeOfIndex(inst);4843 const dest_ty = func.typeOfIndex(inst);
4735 const op_ty = func.air.typeOf(ty_op.operand);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) {
4738 return func.fail("TODO: floatToInt for integers/floats with bitsize larger than 64 bits", .{});4847 return func.fail("TODO: floatToInt for integers/floats with bitsize larger than 64 bits", .{});
4739 }4848 }
47404849
4741 try func.emitWValue(operand);4850 try func.emitWValue(operand);
4742 const op = buildOpcode(.{4851 const op = buildOpcode(.{
4743 .op = .trunc,4852 .op = .trunc,
4744 .valtype1 = typeToValtype(dest_ty, func.target),4853 .valtype1 = typeToValtype(dest_ty, mod),
4745 .valtype2 = typeToValtype(op_ty, func.target),4854 .valtype2 = typeToValtype(op_ty, mod),
4746 .signedness = if (dest_ty.isSignedInt()) .signed else .unsigned,4855 .signedness = if (dest_ty.isSignedInt(mod)) .signed else .unsigned,
4747 });4856 });
4748 try func.addTag(Mir.Inst.Tag.fromOpcode(op));4857 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
4749 const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty);4858 const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty);
...@@ -4752,22 +4861,23 @@ fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4752,22 +4861,23 @@ fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4752}4861}
47534862
4754fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4863fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4864 const mod = func.bin_file.base.options.module.?;
4755 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4865 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
47564866
4757 const operand = try func.resolveInst(ty_op.operand);4867 const operand = try func.resolveInst(ty_op.operand);
4758 const dest_ty = func.air.typeOfIndex(inst);4868 const dest_ty = func.typeOfIndex(inst);
4759 const op_ty = func.air.typeOf(ty_op.operand);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) {
4762 return func.fail("TODO: intToFloat for integers/floats with bitsize larger than 64 bits", .{});4872 return func.fail("TODO: intToFloat for integers/floats with bitsize larger than 64 bits", .{});
4763 }4873 }
47644874
4765 try func.emitWValue(operand);4875 try func.emitWValue(operand);
4766 const op = buildOpcode(.{4876 const op = buildOpcode(.{
4767 .op = .convert,4877 .op = .convert,
4768 .valtype1 = typeToValtype(dest_ty, func.target),4878 .valtype1 = typeToValtype(dest_ty, mod),
4769 .valtype2 = typeToValtype(op_ty, func.target),4879 .valtype2 = typeToValtype(op_ty, mod),
4770 .signedness = if (op_ty.isSignedInt()) .signed else .unsigned,4880 .signedness = if (op_ty.isSignedInt(mod)) .signed else .unsigned,
4771 });4881 });
4772 try func.addTag(Mir.Inst.Tag.fromOpcode(op));4882 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
47734883
...@@ -4777,18 +4887,19 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4777,18 +4887,19 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4777}4887}
47784888
4779fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4889fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4890 const mod = func.bin_file.base.options.module.?;
4780 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4891 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
4781 const operand = try func.resolveInst(ty_op.operand);4892 const operand = try func.resolveInst(ty_op.operand);
4782 const ty = func.air.typeOfIndex(inst);4893 const ty = func.typeOfIndex(inst);
4783 const elem_ty = ty.childType();4894 const elem_ty = ty.childType(mod);
47844895
4785 if (determineSimdStoreStrategy(ty, func.target) == .direct) blk: {4896 if (determineSimdStoreStrategy(ty, mod) == .direct) blk: {
4786 switch (operand) {4897 switch (operand) {
4787 // when the operand lives in the linear memory section, we can directly4898 // when the operand lives in the linear memory section, we can directly
4788 // load and splat the value at once. Meaning we do not first have to load4899 // load and splat the value at once. Meaning we do not first have to load
4789 // the scalar value onto the stack.4900 // the scalar value onto the stack.
4790 .stack_offset, .memory, .memory_offset => {4901 .stack_offset, .memory, .memory_offset => {
4791 const opcode = switch (elem_ty.bitSize(func.target)) {4902 const opcode = switch (elem_ty.bitSize(mod)) {
4792 8 => std.wasm.simdOpcode(.v128_load8_splat),4903 8 => std.wasm.simdOpcode(.v128_load8_splat),
4793 16 => std.wasm.simdOpcode(.v128_load16_splat),4904 16 => std.wasm.simdOpcode(.v128_load16_splat),
4794 32 => std.wasm.simdOpcode(.v128_load32_splat),4905 32 => std.wasm.simdOpcode(.v128_load32_splat),
...@@ -4803,18 +4914,18 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4803,18 +4914,18 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4803 try func.mir_extra.appendSlice(func.gpa, &[_]u32{4914 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
4804 opcode,4915 opcode,
4805 operand.offset(),4916 operand.offset(),
4806 elem_ty.abiAlignment(func.target),4917 elem_ty.abiAlignment(mod),
4807 });4918 });
4808 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });4919 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
4809 try func.addLabel(.local_set, result.local.value);4920 try func.addLabel(.local_set, result.local.value);
4810 return func.finishAir(inst, result, &.{ty_op.operand});4921 return func.finishAir(inst, result, &.{ty_op.operand});
4811 },4922 },
4812 .local => {4923 .local => {
4813 const opcode = switch (elem_ty.bitSize(func.target)) {4924 const opcode = switch (elem_ty.bitSize(mod)) {
4814 8 => std.wasm.simdOpcode(.i8x16_splat),4925 8 => std.wasm.simdOpcode(.i8x16_splat),
4815 16 => std.wasm.simdOpcode(.i16x8_splat),4926 16 => std.wasm.simdOpcode(.i16x8_splat),
4816 32 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i32x4_splat) else std.wasm.simdOpcode(.f32x4_splat),4927 32 => if (elem_ty.isInt(mod)) 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),4928 64 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat),
4818 else => break :blk, // Cannot make use of simd-instructions4929 else => break :blk, // Cannot make use of simd-instructions
4819 };4930 };
4820 const result = try func.allocLocal(ty);4931 const result = try func.allocLocal(ty);
...@@ -4828,14 +4939,14 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4828,14 +4939,14 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4828 else => unreachable,4939 else => unreachable,
4829 }4940 }
4830 }4941 }
4831 const elem_size = elem_ty.bitSize(func.target);4942 const elem_size = elem_ty.bitSize(mod);
4832 const vector_len = @intCast(usize, ty.vectorLen());4943 const vector_len = @intCast(usize, ty.vectorLen(mod));
4833 if ((!std.math.isPowerOfTwo(elem_size) or elem_size % 8 != 0) and vector_len > 1) {4944 if ((!std.math.isPowerOfTwo(elem_size) or elem_size % 8 != 0) and vector_len > 1) {
4834 return func.fail("TODO: WebAssembly `@splat` for arbitrary element bitsize {d}", .{elem_size});4945 return func.fail("TODO: WebAssembly `@splat` for arbitrary element bitsize {d}", .{elem_size});
4835 }4946 }
48364947
4837 const result = try func.allocStack(ty);4948 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));
4839 var index: usize = 0;4950 var index: usize = 0;
4840 var offset: u32 = 0;4951 var offset: u32 = 0;
4841 while (index < vector_len) : (index += 1) {4952 while (index < vector_len) : (index += 1) {
...@@ -4855,26 +4966,25 @@ fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4855,26 +4966,25 @@ fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4855}4966}
48564967
4857fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4968fn 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);
4859 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;4971 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
4860 const extra = func.air.extraData(Air.Shuffle, ty_pl.payload).data;4972 const extra = func.air.extraData(Air.Shuffle, ty_pl.payload).data;
48614973
4862 const a = try func.resolveInst(extra.a);4974 const a = try func.resolveInst(extra.a);
4863 const b = try func.resolveInst(extra.b);4975 const b = try func.resolveInst(extra.b);
4864 const mask = func.air.values[extra.mask];4976 const mask = extra.mask.toValue();
4865 const mask_len = extra.mask_len;4977 const mask_len = extra.mask_len;
48664978
4867 const child_ty = inst_ty.childType();4979 const child_ty = inst_ty.childType(mod);
4868 const elem_size = child_ty.abiSize(func.target);4980 const elem_size = child_ty.abiSize(mod);
48694981
4870 const module = func.bin_file.base.options.module.?;
4871 // TODO: One of them could be by ref; handle in loop4982 // 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)) {
4873 const result = try func.allocStack(inst_ty);4984 const result = try func.allocStack(inst_ty);
48744985
4875 for (0..mask_len) |index| {4986 for (0..mask_len) |index| {
4876 var buf: Value.ElemValueBuffer = undefined;4987 const value = (try mask.elemValue(mod, index)).toSignedInt(mod);
4877 const value = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target);
48784988
4879 try func.emitWValue(result);4989 try func.emitWValue(result);
48804990
...@@ -4894,8 +5004,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4894,8 +5004,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48945004
4895 var lanes = std.mem.asBytes(operands[1..]);5005 var lanes = std.mem.asBytes(operands[1..]);
4896 for (0..@intCast(usize, mask_len)) |index| {5006 for (0..@intCast(usize, mask_len)) |index| {
4897 var buf: Value.ElemValueBuffer = undefined;5007 const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod);
4898 const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target);
4899 const base_index = if (mask_elem >= 0)5008 const base_index = if (mask_elem >= 0)
4900 @intCast(u8, @intCast(i64, elem_size) * mask_elem)5009 @intCast(u8, @intCast(i64, elem_size) * mask_elem)
4901 else5010 else
...@@ -4926,25 +5035,26 @@ fn airReduce(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4926,25 +5035,26 @@ fn airReduce(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4926}5035}
49275036
4928fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5037fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5038 const mod = func.bin_file.base.options.module.?;
4929 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;5039 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
4930 const result_ty = func.air.typeOfIndex(inst);5040 const result_ty = func.typeOfIndex(inst);
4931 const len = @intCast(usize, result_ty.arrayLen());5041 const len = @intCast(usize, result_ty.arrayLen(mod));
4932 const elements = @ptrCast([]const Air.Inst.Ref, func.air.extra[ty_pl.payload..][0..len]);5042 const elements = @ptrCast([]const Air.Inst.Ref, func.air.extra[ty_pl.payload..][0..len]);
49335043
4934 const result: WValue = result_value: {5044 const result: WValue = result_value: {
4935 switch (result_ty.zigTypeTag()) {5045 switch (result_ty.zigTypeTag(mod)) {
4936 .Array => {5046 .Array => {
4937 const result = try func.allocStack(result_ty);5047 const result = try func.allocStack(result_ty);
4938 const elem_ty = result_ty.childType();5048 const elem_ty = result_ty.childType(mod);
4939 const elem_size = @intCast(u32, elem_ty.abiSize(func.target));5049 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
4940 const sentinel = if (result_ty.sentinel()) |sent| blk: {5050 const sentinel = if (result_ty.sentinel(mod)) |sent| blk: {
4941 break :blk try func.lowerConstant(sent, elem_ty);5051 break :blk try func.lowerConstant(sent, elem_ty);
4942 } else null;5052 } else null;
49435053
4944 // When the element type is by reference, we must copy the entire5054 // When the element type is by reference, we must copy the entire
4945 // value. It is therefore safer to move the offset pointer and store5055 // value. It is therefore safer to move the offset pointer and store
4946 // each value individually, instead of using store offsets.5056 // each value individually, instead of using store offsets.
4947 if (isByRef(elem_ty, func.target)) {5057 if (isByRef(elem_ty, mod)) {
4948 // copy stack pointer into a temporary local, which is5058 // copy stack pointer into a temporary local, which is
4949 // moved for each element to store each value in the right position.5059 // moved for each element to store each value in the right position.
4950 const offset = try func.buildPointerOffset(result, 0, .new);5060 const offset = try func.buildPointerOffset(result, 0, .new);
...@@ -4972,18 +5082,18 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4972,18 +5082,18 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4972 }5082 }
4973 break :result_value result;5083 break :result_value result;
4974 },5084 },
4975 .Struct => switch (result_ty.containerLayout()) {5085 .Struct => switch (result_ty.containerLayout(mod)) {
4976 .Packed => {5086 .Packed => {
4977 if (isByRef(result_ty, func.target)) {5087 if (isByRef(result_ty, mod)) {
4978 return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{});5088 return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{});
4979 }5089 }
4980 const struct_obj = result_ty.castTag(.@"struct").?.data;5090 const struct_obj = mod.typeToStruct(result_ty).?;
4981 const fields = struct_obj.fields.values();5091 const fields = struct_obj.fields.values();
4982 const backing_type = struct_obj.backing_int_ty;5092 const backing_type = struct_obj.backing_int_ty;
49835093
4984 // ensure the result is zero'd5094 // ensure the result is zero'd
4985 const result = try func.allocLocal(backing_type);5095 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)
4987 try func.addImm32(0)5097 try func.addImm32(0)
4988 else5098 else
4989 try func.addImm64(0);5099 try func.addImm64(0);
...@@ -4992,20 +5102,16 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4992,20 +5102,16 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4992 var current_bit: u16 = 0;5102 var current_bit: u16 = 0;
4993 for (elements, 0..) |elem, elem_index| {5103 for (elements, 0..) |elem, elem_index| {
4994 const field = fields[elem_index];5104 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)
4998 WValue{ .imm32 = current_bit }5108 WValue{ .imm32 = current_bit }
4999 else5109 else
5000 WValue{ .imm64 = current_bit };5110 WValue{ .imm64 = current_bit };
50015111
5002 const value = try func.resolveInst(elem);5112 const value = try func.resolveInst(elem);
5003 const value_bit_size = @intCast(u16, field.ty.bitSize(func.target));5113 const value_bit_size = @intCast(u16, field.ty.bitSize(mod));
5004 var int_ty_payload: Type.Payload.Bits = .{5114 const int_ty = try mod.intType(.unsigned, value_bit_size);
5005 .base = .{ .tag = .int_unsigned },
5006 .data = value_bit_size,
5007 };
5008 const int_ty = Type.initPayload(&int_ty_payload.base);
50095115
5010 // load our current result on stack so we can perform all transformations5116 // load our current result on stack so we can perform all transformations
5011 // using only stack values. Saving the cost of loads and stores.5117 // 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 {...@@ -5027,10 +5133,10 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5027 const result = try func.allocStack(result_ty);5133 const result = try func.allocStack(result_ty);
5028 const offset = try func.buildPointerOffset(result, 0, .new); // pointer to offset5134 const offset = try func.buildPointerOffset(result, 0, .new); // pointer to offset
5029 for (elements, 0..) |elem, elem_index| {5135 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);5138 const elem_ty = result_ty.structFieldType(elem_index, mod);
5033 const elem_size = @intCast(u32, elem_ty.abiSize(func.target));5139 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
5034 const value = try func.resolveInst(elem);5140 const value = try func.resolveInst(elem);
5035 try func.store(offset, value, elem_ty, 0);5141 try func.store(offset, value, elem_ty, 0);
50365142
...@@ -5058,39 +5164,36 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5058,39 +5164,36 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5058}5164}
50595165
5060fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5166fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5167 const mod = func.bin_file.base.options.module.?;
5061 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;5168 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
5062 const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data;5169 const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data;
50635170
5064 const result = result: {5171 const result = result: {
5065 const union_ty = func.air.typeOfIndex(inst);5172 const union_ty = func.typeOfIndex(inst);
5066 const layout = union_ty.unionGetLayout(func.target);5173 const layout = union_ty.unionGetLayout(mod);
5067 const union_obj = union_ty.cast(Type.Payload.Union).?.data;5174 const union_obj = mod.typeToUnion(union_ty).?;
5068 const field = union_obj.fields.values()[extra.field_index];5175 const field = union_obj.fields.values()[extra.field_index];
5069 const field_name = union_obj.fields.keys()[extra.field_index];5176 const field_name = union_obj.fields.keys()[extra.field_index];
50705177
5071 const tag_int = blk: {5178 const tag_int = blk: {
5072 const tag_ty = union_ty.unionTagTypeHypothetical();5179 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
5073 const enum_field_index = tag_ty.enumFieldIndex(field_name).?;5180 const enum_field_index = tag_ty.enumFieldIndex(field_name, mod).?;
5074 var tag_val_payload: Value.Payload.U32 = .{5181 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
5075 .base = .{ .tag = .enum_field_index },
5076 .data = @intCast(u32, enum_field_index),
5077 };
5078 const tag_val = Value.initPayload(&tag_val_payload.base);
5079 break :blk try func.lowerConstant(tag_val, tag_ty);5182 break :blk try func.lowerConstant(tag_val, tag_ty);
5080 };5183 };
5081 if (layout.payload_size == 0) {5184 if (layout.payload_size == 0) {
5082 if (layout.tag_size == 0) {5185 if (layout.tag_size == 0) {
5083 break :result WValue{ .none = {} };5186 break :result WValue{ .none = {} };
5084 }5187 }
5085 assert(!isByRef(union_ty, func.target));5188 assert(!isByRef(union_ty, mod));
5086 break :result tag_int;5189 break :result tag_int;
5087 }5190 }
50885191
5089 if (isByRef(union_ty, func.target)) {5192 if (isByRef(union_ty, mod)) {
5090 const result_ptr = try func.allocStack(union_ty);5193 const result_ptr = try func.allocStack(union_ty);
5091 const payload = try func.resolveInst(extra.init);5194 const payload = try func.resolveInst(extra.init);
5092 if (layout.tag_align >= layout.payload_align) {5195 if (layout.tag_align >= layout.payload_align) {
5093 if (isByRef(field.ty, func.target)) {5196 if (isByRef(field.ty, mod)) {
5094 const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);5197 const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);
5095 try func.store(payload_ptr, payload, field.ty, 0);5198 try func.store(payload_ptr, payload, field.ty, 0);
5096 } else {5199 } else {
...@@ -5114,26 +5217,14 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5114,26 +5217,14 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5114 break :result result_ptr;5217 break :result result_ptr;
5115 } else {5218 } else {
5116 const operand = try func.resolveInst(extra.init);5219 const operand = try func.resolveInst(extra.init);
5117 var payload: Type.Payload.Bits = .{5220 const union_int_type = try mod.intType(.unsigned, @intCast(u16, union_ty.bitSize(mod)));
5118 .base = .{ .tag = .int_unsigned },5221 if (field.ty.zigTypeTag(mod) == .Float) {
5119 .data = @intCast(u16, union_ty.bitSize(func.target)),5222 const int_type = try mod.intType(.unsigned, @intCast(u16, field.ty.bitSize(mod)));
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);
5128 const bitcasted = try func.bitcast(field.ty, int_type, operand);5223 const bitcasted = try func.bitcast(field.ty, int_type, operand);
5129 const casted = try func.trunc(bitcasted, int_type, union_int_type);5224 const casted = try func.trunc(bitcasted, int_type, union_int_type);
5130 break :result try casted.toLocal(func, field.ty);5225 break :result try casted.toLocal(func, field.ty);
5131 } else if (field.ty.isPtrAtRuntime()) {5226 } else if (field.ty.isPtrAtRuntime(mod)) {
5132 var int_payload: Type.Payload.Bits = .{5227 const int_type = try mod.intType(.unsigned, @intCast(u16, field.ty.bitSize(mod)));
5133 .base = .{ .tag = .int_unsigned },
5134 .data = @intCast(u16, field.ty.bitSize(func.target)),
5135 };
5136 const int_type = Type.initPayload(&int_payload.base);
5137 const casted = try func.intcast(operand, int_type, union_int_type);5228 const casted = try func.intcast(operand, int_type, union_int_type);
5138 break :result try casted.toLocal(func, field.ty);5229 break :result try casted.toLocal(func, field.ty);
5139 }5230 }
...@@ -5153,7 +5244,7 @@ fn airPrefetch(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5153,7 +5244,7 @@ fn airPrefetch(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5153fn airWasmMemorySize(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5244fn airWasmMemorySize(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5154 const pl_op = func.air.instructions.items(.data)[inst].pl_op;5245 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));
5157 try func.addLabel(.memory_size, pl_op.payload);5248 try func.addLabel(.memory_size, pl_op.payload);
5158 try func.addLabel(.local_set, result.local.value);5249 try func.addLabel(.local_set, result.local.value);
5159 func.finishAir(inst, result, &.{pl_op.operand});5250 func.finishAir(inst, result, &.{pl_op.operand});
...@@ -5163,7 +5254,7 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5163,7 +5254,7 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {
5163 const pl_op = func.air.instructions.items(.data)[inst].pl_op;5254 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
51645255
5165 const operand = try func.resolveInst(pl_op.operand);5256 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));
5167 try func.emitWValue(operand);5258 try func.emitWValue(operand);
5168 try func.addLabel(.memory_grow, pl_op.payload);5259 try func.addLabel(.memory_grow, pl_op.payload);
5169 try func.addLabel(.local_set, result.local.value);5260 try func.addLabel(.local_set, result.local.value);
...@@ -5171,14 +5262,14 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5171,14 +5262,14 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {
5171}5262}
51725263
5173fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {5264fn 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));
5175 assert(op == .eq or op == .neq);5267 assert(op == .eq or op == .neq);
5176 var buf: Type.Payload.ElemType = undefined;5268 const payload_ty = operand_ty.optionalChild(mod);
5177 const payload_ty = operand_ty.optionalChild(&buf);
51785269
5179 // We store the final result in here that will be validated5270 // We store the final result in here that will be validated
5180 // if the optional is truly equal.5271 // if the optional is truly equal.
5181 var result = try func.ensureAllocLocal(Type.initTag(.i32));5272 var result = try func.ensureAllocLocal(Type.i32);
5182 defer result.free(func);5273 defer result.free(func);
51835274
5184 try func.startBlock(.block, wasm.block_empty);5275 try func.startBlock(.block, wasm.block_empty);
...@@ -5189,7 +5280,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:...@@ -5189,7 +5280,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:
51895280
5190 _ = try func.load(lhs, payload_ty, 0);5281 _ = try func.load(lhs, payload_ty, 0);
5191 _ = try func.load(rhs, payload_ty, 0);5282 _ = 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) });
5193 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));5284 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
5194 try func.addLabel(.br_if, 0);5285 try func.addLabel(.br_if, 0);
51955286
...@@ -5207,10 +5298,11 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:...@@ -5207,10 +5298,11 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:
5207/// NOTE: Leaves the result of the comparison on top of the stack.5298/// NOTE: Leaves the result of the comparison on top of the stack.
5208/// TODO: Lower this to compiler_rt call when bitsize > 1285299/// TODO: Lower this to compiler_rt call when bitsize > 128
5209fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {5300fn 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);
5211 assert(!(lhs != .stack and rhs == .stack));5303 assert(!(lhs != .stack and rhs == .stack));
5212 if (operand_ty.bitSize(func.target) > 128) {5304 if (operand_ty.bitSize(mod) > 128) {
5213 return func.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.bitSize(func.target)});5305 return func.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.bitSize(mod)});
5214 }5306 }
52155307
5216 var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64);5308 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...@@ -5233,7 +5325,7 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std
5233 }5325 }
5234 },5326 },
5235 else => {5327 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;
5237 // leave those value on top of the stack for '.select'5329 // leave those value on top of the stack for '.select'
5238 const lhs_low_bit = try func.load(lhs, Type.u64, 8);5330 const lhs_low_bit = try func.load(lhs, Type.u64, 8);
5239 const rhs_low_bit = try func.load(rhs, Type.u64, 8);5331 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...@@ -5248,10 +5340,11 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std
5248}5340}
52495341
5250fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5342fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5343 const mod = func.bin_file.base.options.module.?;
5251 const bin_op = func.air.instructions.items(.data)[inst].bin_op;5344 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
5252 const un_ty = func.air.typeOf(bin_op.lhs).childType();5345 const un_ty = func.typeOf(bin_op.lhs).childType(mod);
5253 const tag_ty = func.air.typeOf(bin_op.rhs);5346 const tag_ty = func.typeOf(bin_op.rhs);
5254 const layout = un_ty.unionGetLayout(func.target);5347 const layout = un_ty.unionGetLayout(mod);
5255 if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });5348 if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
52565349
5257 const union_ptr = try func.resolveInst(bin_op.lhs);5350 const union_ptr = try func.resolveInst(bin_op.lhs);
...@@ -5271,11 +5364,12 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5271,11 +5364,12 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5271}5364}
52725365
5273fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5366fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5367 const mod = func.bin_file.base.options.module.?;
5274 const ty_op = func.air.instructions.items(.data)[inst].ty_op;5368 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
52755369
5276 const un_ty = func.air.typeOf(ty_op.operand);5370 const un_ty = func.typeOf(ty_op.operand);
5277 const tag_ty = func.air.typeOfIndex(inst);5371 const tag_ty = func.typeOfIndex(inst);
5278 const layout = un_ty.unionGetLayout(func.target);5372 const layout = un_ty.unionGetLayout(mod);
5279 if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ty_op.operand});5373 if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ty_op.operand});
52805374
5281 const operand = try func.resolveInst(ty_op.operand);5375 const operand = try func.resolveInst(ty_op.operand);
...@@ -5292,9 +5386,9 @@ fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5292,9 +5386,9 @@ fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5292fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5386fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5293 const ty_op = func.air.instructions.items(.data)[inst].ty_op;5387 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);
5296 const operand = try func.resolveInst(ty_op.operand);5390 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);
5298 const result = try extended.toLocal(func, dest_ty);5392 const result = try extended.toLocal(func, dest_ty);
5299 func.finishAir(inst, result, &.{ty_op.operand});5393 func.finishAir(inst, result, &.{ty_op.operand});
5300}5394}
...@@ -5313,7 +5407,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!...@@ -5313,7 +5407,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
5313 // call __extendhfsf2(f16) f325407 // call __extendhfsf2(f16) f32
5314 const f32_result = try func.callIntrinsic(5408 const f32_result = try func.callIntrinsic(
5315 "__extendhfsf2",5409 "__extendhfsf2",
5316 &.{Type.f16},5410 &.{.f16_type},
5317 Type.f32,5411 Type.f32,
5318 &.{operand},5412 &.{operand},
5319 );5413 );
...@@ -5331,15 +5425,15 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!...@@ -5331,15 +5425,15 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
5331 target_util.compilerRtFloatAbbrev(wanted_bits),5425 target_util.compilerRtFloatAbbrev(wanted_bits),
5332 }) catch unreachable;5426 }) catch unreachable;
53335427
5334 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});5428 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
5335}5429}
53365430
5337fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5431fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5338 const ty_op = func.air.instructions.items(.data)[inst].ty_op;5432 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);
5341 const operand = try func.resolveInst(ty_op.operand);5435 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);
5343 const result = try truncated.toLocal(func, dest_ty);5437 const result = try truncated.toLocal(func, dest_ty);
5344 func.finishAir(inst, result, &.{ty_op.operand});5438 func.finishAir(inst, result, &.{ty_op.operand});
5345}5439}
...@@ -5362,7 +5456,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro...@@ -5362,7 +5456,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
5362 } else operand;5456 } else operand;
53635457
5364 // call __truncsfhf2(f32) f165458 // call __truncsfhf2(f32) f16
5365 return func.callIntrinsic("__truncsfhf2", &.{Type.f32}, Type.f16, &.{op});5459 return func.callIntrinsic("__truncsfhf2", &.{.f32_type}, Type.f16, &.{op});
5366 }5460 }
53675461
5368 var fn_name_buf: [12]u8 = undefined;5462 var fn_name_buf: [12]u8 = undefined;
...@@ -5371,14 +5465,15 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro...@@ -5371,14 +5465,15 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
5371 target_util.compilerRtFloatAbbrev(wanted_bits),5465 target_util.compilerRtFloatAbbrev(wanted_bits),
5372 }) catch unreachable;5466 }) catch unreachable;
53735467
5374 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});5468 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
5375}5469}
53765470
5377fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5471fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5472 const mod = func.bin_file.base.options.module.?;
5378 const ty_op = func.air.instructions.items(.data)[inst].ty_op;5473 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
53795474
5380 const err_set_ty = func.air.typeOf(ty_op.operand).childType();5475 const err_set_ty = func.typeOf(ty_op.operand).childType(mod);
5381 const payload_ty = err_set_ty.errorUnionPayload();5476 const payload_ty = err_set_ty.errorUnionPayload(mod);
5382 const operand = try func.resolveInst(ty_op.operand);5477 const operand = try func.resolveInst(ty_op.operand);
53835478
5384 // set error-tag to '0' to annotate error union is non-error5479 // 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...@@ -5386,26 +5481,27 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi
5386 operand,5481 operand,
5387 .{ .imm32 = 0 },5482 .{ .imm32 = 0 },
5388 Type.anyerror,5483 Type.anyerror,
5389 @intCast(u32, errUnionErrorOffset(payload_ty, func.target)),5484 @intCast(u32, errUnionErrorOffset(payload_ty, mod)),
5390 );5485 );
53915486
5392 const result = result: {5487 const result = result: {
5393 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {5488 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5394 break :result func.reuseOperand(ty_op.operand, operand);5489 break :result func.reuseOperand(ty_op.operand, operand);
5395 }5490 }
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);
5398 };5493 };
5399 func.finishAir(inst, result, &.{ty_op.operand});5494 func.finishAir(inst, result, &.{ty_op.operand});
5400}5495}
54015496
5402fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5497fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5498 const mod = func.bin_file.base.options.module.?;
5403 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;5499 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
5404 const extra = func.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;5500 const extra = func.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
54055501
5406 const field_ptr = try func.resolveInst(extra.field_ptr);5502 const field_ptr = try func.resolveInst(extra.field_ptr);
5407 const parent_ty = func.air.getRefType(ty_pl.ty).childType();5503 const parent_ty = func.air.getRefType(ty_pl.ty).childType(mod);
5408 const field_offset = parent_ty.structFieldOffset(extra.field_index, func.target);5504 const field_offset = parent_ty.structFieldOffset(extra.field_index, mod);
54095505
5410 const result = if (field_offset != 0) result: {5506 const result = if (field_offset != 0) result: {
5411 const base = try func.buildPointerOffset(field_ptr, 0, .new);5507 const base = try func.buildPointerOffset(field_ptr, 0, .new);
...@@ -5420,7 +5516,8 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5420,7 +5516,8 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5420}5516}
54215517
5422fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue {5518fn 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)) {
5424 return func.slicePtr(ptr);5521 return func.slicePtr(ptr);
5425 } else {5522 } else {
5426 return ptr;5523 return ptr;
...@@ -5428,25 +5525,26 @@ fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue...@@ -5428,25 +5525,26 @@ fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue
5428}5525}
54295526
5430fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5527fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5528 const mod = func.bin_file.base.options.module.?;
5431 const bin_op = func.air.instructions.items(.data)[inst].bin_op;5529 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
5432 const dst = try func.resolveInst(bin_op.lhs);5530 const dst = try func.resolveInst(bin_op.lhs);
5433 const dst_ty = func.air.typeOf(bin_op.lhs);5531 const dst_ty = func.typeOf(bin_op.lhs);
5434 const ptr_elem_ty = dst_ty.childType();5532 const ptr_elem_ty = dst_ty.childType(mod);
5435 const src = try func.resolveInst(bin_op.rhs);5533 const src = try func.resolveInst(bin_op.rhs);
5436 const src_ty = func.air.typeOf(bin_op.rhs);5534 const src_ty = func.typeOf(bin_op.rhs);
5437 const len = switch (dst_ty.ptrSize()) {5535 const len = switch (dst_ty.ptrSize(mod)) {
5438 .Slice => blk: {5536 .Slice => blk: {
5439 const slice_len = try func.sliceLen(dst);5537 const slice_len = try func.sliceLen(dst);
5440 if (ptr_elem_ty.abiSize(func.target) != 1) {5538 if (ptr_elem_ty.abiSize(mod) != 1) {
5441 try func.emitWValue(slice_len);5539 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)) });
5443 try func.addTag(.i32_mul);5541 try func.addTag(.i32_mul);
5444 try func.addLabel(.local_set, slice_len.local.value);5542 try func.addLabel(.local_set, slice_len.local.value);
5445 }5543 }
5446 break :blk slice_len;5544 break :blk slice_len;
5447 },5545 },
5448 .One => @as(WValue, .{5546 .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)),
5450 }),5548 }),
5451 .C, .Many => unreachable,5549 .C, .Many => unreachable,
5452 };5550 };
...@@ -5467,17 +5565,18 @@ fn airRetAddr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5467,17 +5565,18 @@ fn airRetAddr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5467}5565}
54685566
5469fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5567fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5568 const mod = func.bin_file.base.options.module.?;
5470 const ty_op = func.air.instructions.items(.data)[inst].ty_op;5569 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
54715570
5472 const operand = try func.resolveInst(ty_op.operand);5571 const operand = try func.resolveInst(ty_op.operand);
5473 const op_ty = func.air.typeOf(ty_op.operand);5572 const op_ty = func.typeOf(ty_op.operand);
5474 const result_ty = func.air.typeOfIndex(inst);5573 const result_ty = func.typeOfIndex(inst);
54755574
5476 if (op_ty.zigTypeTag() == .Vector) {5575 if (op_ty.zigTypeTag(mod) == .Vector) {
5477 return func.fail("TODO: Implement @popCount for vectors", .{});5576 return func.fail("TODO: Implement @popCount for vectors", .{});
5478 }5577 }
54795578
5480 const int_info = op_ty.intInfo(func.target);5579 const int_info = op_ty.intInfo(mod);
5481 const bits = int_info.bits;5580 const bits = int_info.bits;
5482 const wasm_bits = toWasmBits(bits) orelse {5581 const wasm_bits = toWasmBits(bits) orelse {
5483 return func.fail("TODO: Implement @popCount for integers with bitsize '{d}'", .{bits});5582 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 {...@@ -5526,8 +5625,9 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5526 // As the names are global and the slice elements are constant, we do not have5625 // As the names are global and the slice elements are constant, we do not have
5527 // to make a copy of the ptr+value but can point towards them directly.5626 // to make a copy of the ptr+value but can point towards them directly.
5528 const error_table_symbol = try func.bin_file.getErrorTableSymbol();5627 const error_table_symbol = try func.bin_file.getErrorTableSymbol();
5529 const name_ty = Type.initTag(.const_slice_u8_sentinel_0);5628 const name_ty = Type.slice_const_u8_sentinel_0;
5530 const abi_size = name_ty.abiSize(func.target);5629 const mod = func.bin_file.base.options.module.?;
5630 const abi_size = name_ty.abiSize(mod);
55315631
5532 const error_name_value: WValue = .{ .memory = error_table_symbol }; // emitting this will create a relocation5632 const error_name_value: WValue = .{ .memory = error_table_symbol }; // emitting this will create a relocation
5533 try func.emitWValue(error_name_value);5633 try func.emitWValue(error_name_value);
...@@ -5565,20 +5665,21 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro...@@ -5565,20 +5665,21 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro
55655665
5566 const lhs_op = try func.resolveInst(extra.lhs);5666 const lhs_op = try func.resolveInst(extra.lhs);
5567 const rhs_op = try func.resolveInst(extra.rhs);5667 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) {
5571 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});5672 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});
5572 }5673 }
55735674
5574 const int_info = lhs_ty.intInfo(func.target);5675 const int_info = lhs_ty.intInfo(mod);
5575 const is_signed = int_info.signedness == .signed;5676 const is_signed = int_info.signedness == .signed;
5576 const wasm_bits = toWasmBits(int_info.bits) orelse {5677 const wasm_bits = toWasmBits(int_info.bits) orelse {
5577 return func.fail("TODO: Implement {{add/sub}}_with_overflow for integer bitsize: {d}", .{int_info.bits});5678 return func.fail("TODO: Implement {{add/sub}}_with_overflow for integer bitsize: {d}", .{int_info.bits});
5578 };5679 };
55795680
5580 if (wasm_bits == 128) {5681 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);
5582 return func.finishAir(inst, result, &.{ extra.lhs, extra.rhs });5683 return func.finishAir(inst, result, &.{ extra.lhs, extra.rhs });
5583 }5684 }
55845685
...@@ -5628,17 +5729,18 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro...@@ -5628,17 +5729,18 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro
5628 var overflow_local = try overflow_bit.toLocal(func, Type.u32);5729 var overflow_local = try overflow_bit.toLocal(func, Type.u32);
5629 defer overflow_local.free(func);5730 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));
5632 try func.store(result_ptr, result, lhs_ty, 0);5733 try func.store(result_ptr, result, lhs_ty, 0);
5633 const offset = @intCast(u32, lhs_ty.abiSize(func.target));5734 const offset = @intCast(u32, lhs_ty.abiSize(mod));
5634 try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset);5735 try func.store(result_ptr, overflow_local, Type.u1, offset);
56355736
5636 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });5737 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
5637}5738}
56385739
5639fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, result_ty: Type, op: Op) InnerError!WValue {5740fn 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.?;
5640 assert(op == .add or op == .sub);5742 assert(op == .add or op == .sub);
5641 const int_info = ty.intInfo(func.target);5743 const int_info = ty.intInfo(mod);
5642 const is_signed = int_info.signedness == .signed;5744 const is_signed = int_info.signedness == .signed;
5643 if (int_info.bits != 128) {5745 if (int_info.bits != 128) {
5644 return func.fail("TODO: Implement @{{add/sub}}WithOverflow for integer bitsize '{d}'", .{int_info.bits});5746 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,...@@ -5689,31 +5791,32 @@ fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type,
56895791
5690 break :blk WValue{ .stack = {} };5792 break :blk WValue{ .stack = {} };
5691 };5793 };
5692 var overflow_local = try overflow_bit.toLocal(func, Type.initTag(.u1));5794 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
5693 defer overflow_local.free(func);5795 defer overflow_local.free(func);
56945796
5695 const result_ptr = try func.allocStack(result_ty);5797 const result_ptr = try func.allocStack(result_ty);
5696 try func.store(result_ptr, high_op_res, Type.u64, 0);5798 try func.store(result_ptr, high_op_res, Type.u64, 0);
5697 try func.store(result_ptr, tmp_op, Type.u64, 8);5799 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
5700 return result_ptr;5802 return result_ptr;
5701}5803}
57025804
5703fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5805fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5806 const mod = func.bin_file.base.options.module.?;
5704 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;5807 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
5705 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;5808 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
57065809
5707 const lhs = try func.resolveInst(extra.lhs);5810 const lhs = try func.resolveInst(extra.lhs);
5708 const rhs = try func.resolveInst(extra.rhs);5811 const rhs = try func.resolveInst(extra.rhs);
5709 const lhs_ty = func.air.typeOf(extra.lhs);5812 const lhs_ty = func.typeOf(extra.lhs);
5710 const rhs_ty = func.air.typeOf(extra.rhs);5813 const rhs_ty = func.typeOf(extra.rhs);
57115814
5712 if (lhs_ty.zigTypeTag() == .Vector) {5815 if (lhs_ty.zigTypeTag(mod) == .Vector) {
5713 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});5816 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});
5714 }5817 }
57155818
5716 const int_info = lhs_ty.intInfo(func.target);5819 const int_info = lhs_ty.intInfo(mod);
5717 const is_signed = int_info.signedness == .signed;5820 const is_signed = int_info.signedness == .signed;
5718 const wasm_bits = toWasmBits(int_info.bits) orelse {5821 const wasm_bits = toWasmBits(int_info.bits) orelse {
5719 return func.fail("TODO: Implement shl_with_overflow for integer bitsize: {d}", .{int_info.bits});5822 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 {...@@ -5721,7 +5824,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
57215824
5722 // Ensure rhs is coerced to lhs as they must have the same WebAssembly types5825 // Ensure rhs is coerced to lhs as they must have the same WebAssembly types
5723 // before we can perform any binary operation.5826 // 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).?;
5725 const rhs_final = if (wasm_bits != rhs_wasm_bits) blk: {5828 const rhs_final = if (wasm_bits != rhs_wasm_bits) blk: {
5726 const rhs_casted = try func.intcast(rhs, rhs_ty, lhs_ty);5829 const rhs_casted = try func.intcast(rhs, rhs_ty, lhs_ty);
5727 break :blk try rhs_casted.toLocal(func, lhs_ty);5830 break :blk try rhs_casted.toLocal(func, lhs_ty);
...@@ -5745,13 +5848,13 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5745,13 +5848,13 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5745 const shr = try func.binOp(result, rhs_final, lhs_ty, .shr);5848 const shr = try func.binOp(result, rhs_final, lhs_ty, .shr);
5746 break :blk try func.cmp(.{ .stack = {} }, shr, lhs_ty, .neq);5849 break :blk try func.cmp(.{ .stack = {} }, shr, lhs_ty, .neq);
5747 };5850 };
5748 var overflow_local = try overflow_bit.toLocal(func, Type.initTag(.u1));5851 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
5749 defer overflow_local.free(func);5852 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));
5752 try func.store(result_ptr, result, lhs_ty, 0);5855 try func.store(result_ptr, result, lhs_ty, 0);
5753 const offset = @intCast(u32, lhs_ty.abiSize(func.target));5856 const offset = @intCast(u32, lhs_ty.abiSize(mod));
5754 try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset);5857 try func.store(result_ptr, overflow_local, Type.u1, offset);
57555858
5756 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });5859 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
5757}5860}
...@@ -5762,18 +5865,19 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5762,18 +5865,19 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
57625865
5763 const lhs = try func.resolveInst(extra.lhs);5866 const lhs = try func.resolveInst(extra.lhs);
5764 const rhs = try func.resolveInst(extra.rhs);5867 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) {
5768 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});5872 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});
5769 }5873 }
57705874
5771 // We store the bit if it's overflowed or not in this. As it's zero-initialized5875 // We store the bit if it's overflowed or not in this. As it's zero-initialized
5772 // we only need to update it if an overflow (or underflow) occurred.5876 // 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);
5774 defer overflow_bit.free(func);5878 defer overflow_bit.free(func);
57755879
5776 const int_info = lhs_ty.intInfo(func.target);5880 const int_info = lhs_ty.intInfo(mod);
5777 const wasm_bits = toWasmBits(int_info.bits) orelse {5881 const wasm_bits = toWasmBits(int_info.bits) orelse {
5778 return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits});5882 return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits});
5779 };5883 };
...@@ -5827,7 +5931,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5827,7 +5931,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5827 try func.addLabel(.local_set, overflow_bit.local.value);5931 try func.addLabel(.local_set, overflow_bit.local.value);
5828 break :blk try func.wrapOperand(bin_op, lhs_ty);5932 break :blk try func.wrapOperand(bin_op, lhs_ty);
5829 } else if (int_info.bits == 64 and int_info.signedness == .unsigned) blk: {5933 } 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;
5831 var lhs_upcast = try (try func.intcast(lhs, lhs_ty, new_ty)).toLocal(func, lhs_ty);5935 var lhs_upcast = try (try func.intcast(lhs, lhs_ty, new_ty)).toLocal(func, lhs_ty);
5832 defer lhs_upcast.free(func);5936 defer lhs_upcast.free(func);
5833 var rhs_upcast = try (try func.intcast(rhs, lhs_ty, new_ty)).toLocal(func, lhs_ty);5937 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 {...@@ -5847,8 +5951,8 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58475951
5848 const bin_op = try func.callIntrinsic(5952 const bin_op = try func.callIntrinsic(
5849 "__multi3",5953 "__multi3",
5850 &[_]Type{Type.i64} ** 4,5954 &[_]InternPool.Index{.i64_type} ** 4,
5851 Type.initTag(.i128),5955 Type.i128,
5852 &.{ lhs, lhs_shifted, rhs, rhs_shifted },5956 &.{ lhs, lhs_shifted, rhs, rhs_shifted },
5853 );5957 );
5854 const res = try func.allocLocal(lhs_ty);5958 const res = try func.allocLocal(lhs_ty);
...@@ -5871,20 +5975,20 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5871,20 +5975,20 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58715975
5872 const mul1 = try func.callIntrinsic(5976 const mul1 = try func.callIntrinsic(
5873 "__multi3",5977 "__multi3",
5874 &[_]Type{Type.i64} ** 4,5978 &[_]InternPool.Index{.i64_type} ** 4,
5875 Type.initTag(.i128),5979 Type.i128,
5876 &.{ lhs_lsb, zero, rhs_msb, zero },5980 &.{ lhs_lsb, zero, rhs_msb, zero },
5877 );5981 );
5878 const mul2 = try func.callIntrinsic(5982 const mul2 = try func.callIntrinsic(
5879 "__multi3",5983 "__multi3",
5880 &[_]Type{Type.i64} ** 4,5984 &[_]InternPool.Index{.i64_type} ** 4,
5881 Type.initTag(.i128),5985 Type.i128,
5882 &.{ rhs_lsb, zero, lhs_msb, zero },5986 &.{ rhs_lsb, zero, lhs_msb, zero },
5883 );5987 );
5884 const mul3 = try func.callIntrinsic(5988 const mul3 = try func.callIntrinsic(
5885 "__multi3",5989 "__multi3",
5886 &[_]Type{Type.i64} ** 4,5990 &[_]InternPool.Index{.i64_type} ** 4,
5887 Type.initTag(.i128),5991 Type.i128,
5888 &.{ lhs_msb, zero, rhs_msb, zero },5992 &.{ lhs_msb, zero, rhs_msb, zero },
5889 );5993 );
58905994
...@@ -5912,7 +6016,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5912,7 +6016,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5912 _ = try func.binOp(lsb_or, mul_add_lt, Type.bool, .@"or");6016 _ = try func.binOp(lsb_or, mul_add_lt, Type.bool, .@"or");
5913 try func.addLabel(.local_set, overflow_bit.local.value);6017 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);
5916 try func.emitWValue(tmp_result);6020 try func.emitWValue(tmp_result);
5917 const mul3_msb = try func.load(mul3, Type.u64, 0);6021 const mul3_msb = try func.load(mul3, Type.u64, 0);
5918 try func.store(.stack, mul3_msb, Type.u64, tmp_result.offset());6022 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 {...@@ -5922,23 +6026,24 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5922 var bin_op_local = try bin_op.toLocal(func, lhs_ty);6026 var bin_op_local = try bin_op.toLocal(func, lhs_ty);
5923 defer bin_op_local.free(func);6027 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));
5926 try func.store(result_ptr, bin_op_local, lhs_ty, 0);6030 try func.store(result_ptr, bin_op_local, lhs_ty, 0);
5927 const offset = @intCast(u32, lhs_ty.abiSize(func.target));6031 const offset = @intCast(u32, lhs_ty.abiSize(mod));
5928 try func.store(result_ptr, overflow_bit, Type.initTag(.u1), offset);6032 try func.store(result_ptr, overflow_bit, Type.u1, offset);
59296033
5930 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });6034 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
5931}6035}
59326036
5933fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerError!void {6037fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerError!void {
6038 const mod = func.bin_file.base.options.module.?;
5934 const bin_op = func.air.instructions.items(.data)[inst].bin_op;6039 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
59356040
5936 const ty = func.air.typeOfIndex(inst);6041 const ty = func.typeOfIndex(inst);
5937 if (ty.zigTypeTag() == .Vector) {6042 if (ty.zigTypeTag(mod) == .Vector) {
5938 return func.fail("TODO: `@maximum` and `@minimum` for vectors", .{});6043 return func.fail("TODO: `@maximum` and `@minimum` for vectors", .{});
5939 }6044 }
59406045
5941 if (ty.abiSize(func.target) > 16) {6046 if (ty.abiSize(mod) > 16) {
5942 return func.fail("TODO: `@maximum` and `@minimum` for types larger than 16 bytes", .{});6047 return func.fail("TODO: `@maximum` and `@minimum` for types larger than 16 bytes", .{});
5943 }6048 }
59446049
...@@ -5954,18 +6059,19 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE...@@ -5954,18 +6059,19 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE
5954 try func.addTag(.select);6059 try func.addTag(.select);
59556060
5956 // store result in local6061 // 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;
5958 const result = try func.allocLocal(result_ty);6063 const result = try func.allocLocal(result_ty);
5959 try func.addLabel(.local_set, result.local.value);6064 try func.addLabel(.local_set, result.local.value);
5960 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });6065 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
5961}6066}
59626067
5963fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6068fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6069 const mod = func.bin_file.base.options.module.?;
5964 const pl_op = func.air.instructions.items(.data)[inst].pl_op;6070 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
5965 const bin_op = func.air.extraData(Air.Bin, pl_op.payload).data;6071 const bin_op = func.air.extraData(Air.Bin, pl_op.payload).data;
59666072
5967 const ty = func.air.typeOfIndex(inst);6073 const ty = func.typeOfIndex(inst);
5968 if (ty.zigTypeTag() == .Vector) {6074 if (ty.zigTypeTag(mod) == .Vector) {
5969 return func.fail("TODO: `@mulAdd` for vectors", .{});6075 return func.fail("TODO: `@mulAdd` for vectors", .{});
5970 }6076 }
59716077
...@@ -5980,7 +6086,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5980,7 +6086,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5980 // call to compiler-rt `fn fmaf(f32, f32, f32) f32`6086 // call to compiler-rt `fn fmaf(f32, f32, f32) f32`
5981 var result = try func.callIntrinsic(6087 var result = try func.callIntrinsic(
5982 "fmaf",6088 "fmaf",
5983 &.{ Type.f32, Type.f32, Type.f32 },6089 &.{ .f32_type, .f32_type, .f32_type },
5984 Type.f32,6090 Type.f32,
5985 &.{ rhs_ext, lhs_ext, addend_ext },6091 &.{ rhs_ext, lhs_ext, addend_ext },
5986 );6092 );
...@@ -5994,16 +6100,17 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5994,16 +6100,17 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5994}6100}
59956101
5996fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6102fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6103 const mod = func.bin_file.base.options.module.?;
5997 const ty_op = func.air.instructions.items(.data)[inst].ty_op;6104 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
59986105
5999 const ty = func.air.typeOf(ty_op.operand);6106 const ty = func.typeOf(ty_op.operand);
6000 const result_ty = func.air.typeOfIndex(inst);6107 const result_ty = func.typeOfIndex(inst);
6001 if (ty.zigTypeTag() == .Vector) {6108 if (ty.zigTypeTag(mod) == .Vector) {
6002 return func.fail("TODO: `@clz` for vectors", .{});6109 return func.fail("TODO: `@clz` for vectors", .{});
6003 }6110 }
60046111
6005 const operand = try func.resolveInst(ty_op.operand);6112 const operand = try func.resolveInst(ty_op.operand);
6006 const int_info = ty.intInfo(func.target);6113 const int_info = ty.intInfo(mod);
6007 const wasm_bits = toWasmBits(int_info.bits) orelse {6114 const wasm_bits = toWasmBits(int_info.bits) orelse {
6008 return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits});6115 return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits});
6009 };6116 };
...@@ -6046,17 +6153,18 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6046,17 +6153,18 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6046}6153}
60476154
6048fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6155fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6156 const mod = func.bin_file.base.options.module.?;
6049 const ty_op = func.air.instructions.items(.data)[inst].ty_op;6157 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
60506158
6051 const ty = func.air.typeOf(ty_op.operand);6159 const ty = func.typeOf(ty_op.operand);
6052 const result_ty = func.air.typeOfIndex(inst);6160 const result_ty = func.typeOfIndex(inst);
60536161
6054 if (ty.zigTypeTag() == .Vector) {6162 if (ty.zigTypeTag(mod) == .Vector) {
6055 return func.fail("TODO: `@ctz` for vectors", .{});6163 return func.fail("TODO: `@ctz` for vectors", .{});
6056 }6164 }
60576165
6058 const operand = try func.resolveInst(ty_op.operand);6166 const operand = try func.resolveInst(ty_op.operand);
6059 const int_info = ty.intInfo(func.target);6167 const int_info = ty.intInfo(mod);
6060 const wasm_bits = toWasmBits(int_info.bits) orelse {6168 const wasm_bits = toWasmBits(int_info.bits) orelse {
6061 return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits});6169 return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits});
6062 };6170 };
...@@ -6113,7 +6221,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -6113,7 +6221,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
6113 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});6221 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
61146222
6115 const pl_op = func.air.instructions.items(.data)[inst].pl_op;6223 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);
6117 const operand = try func.resolveInst(pl_op.operand);6225 const operand = try func.resolveInst(pl_op.operand);
61186226
6119 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand });6227 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand });
...@@ -6151,17 +6259,18 @@ fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6151,17 +6259,18 @@ fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6151 const err_union = try func.resolveInst(pl_op.operand);6259 const err_union = try func.resolveInst(pl_op.operand);
6152 const extra = func.air.extraData(Air.Try, pl_op.payload);6260 const extra = func.air.extraData(Air.Try, pl_op.payload);
6153 const body = func.air.extra[extra.end..][0..extra.data.body_len];6261 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);
6155 const result = try lowerTry(func, inst, err_union, body, err_union_ty, false);6263 const result = try lowerTry(func, inst, err_union, body, err_union_ty, false);
6156 func.finishAir(inst, result, &.{pl_op.operand});6264 func.finishAir(inst, result, &.{pl_op.operand});
6157}6265}
61586266
6159fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6267fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6268 const mod = func.bin_file.base.options.module.?;
6160 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;6269 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
6161 const extra = func.air.extraData(Air.TryPtr, ty_pl.payload);6270 const extra = func.air.extraData(Air.TryPtr, ty_pl.payload);
6162 const err_union_ptr = try func.resolveInst(extra.data.ptr);6271 const err_union_ptr = try func.resolveInst(extra.data.ptr);
6163 const body = func.air.extra[extra.end..][0..extra.data.body_len];6272 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);
6165 const result = try lowerTry(func, inst, err_union_ptr, body, err_union_ty, true);6274 const result = try lowerTry(func, inst, err_union_ptr, body, err_union_ty, true);
6166 func.finishAir(inst, result, &.{extra.data.ptr});6275 func.finishAir(inst, result, &.{extra.data.ptr});
6167}6276}
...@@ -6174,24 +6283,25 @@ fn lowerTry(...@@ -6174,24 +6283,25 @@ fn lowerTry(
6174 err_union_ty: Type,6283 err_union_ty: Type,
6175 operand_is_ptr: bool,6284 operand_is_ptr: bool,
6176) InnerError!WValue {6285) InnerError!WValue {
6286 const mod = func.bin_file.base.options.module.?;
6177 if (operand_is_ptr) {6287 if (operand_is_ptr) {
6178 return func.fail("TODO: lowerTry for pointers", .{});6288 return func.fail("TODO: lowerTry for pointers", .{});
6179 }6289 }
61806290
6181 const pl_ty = err_union_ty.errorUnionPayload();6291 const pl_ty = err_union_ty.errorUnionPayload(mod);
6182 const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime();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)) {
6185 // Block we can jump out of when error is not set6295 // Block we can jump out of when error is not set
6186 try func.startBlock(.block, wasm.block_empty);6296 try func.startBlock(.block, wasm.block_empty);
61876297
6188 // check if the error tag is set for the error union.6298 // check if the error tag is set for the error union.
6189 try func.emitWValue(err_union);6299 try func.emitWValue(err_union);
6190 if (pl_has_bits) {6300 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));
6192 try func.addMemArg(.i32_load16_u, .{6302 try func.addMemArg(.i32_load16_u, .{
6193 .offset = err_union.offset() + err_offset,6303 .offset = err_union.offset() + err_offset,
6194 .alignment = Type.anyerror.abiAlignment(func.target),6304 .alignment = Type.anyerror.abiAlignment(mod),
6195 });6305 });
6196 }6306 }
6197 try func.addTag(.i32_eqz);6307 try func.addTag(.i32_eqz);
...@@ -6213,8 +6323,8 @@ fn lowerTry(...@@ -6213,8 +6323,8 @@ fn lowerTry(
6213 return WValue{ .none = {} };6323 return WValue{ .none = {} };
6214 }6324 }
62156325
6216 const pl_offset = @intCast(u32, errUnionPayloadOffset(pl_ty, func.target));6326 const pl_offset = @intCast(u32, errUnionPayloadOffset(pl_ty, mod));
6217 if (isByRef(pl_ty, func.target)) {6327 if (isByRef(pl_ty, mod)) {
6218 return buildPointerOffset(func, err_union, pl_offset, .new);6328 return buildPointerOffset(func, err_union, pl_offset, .new);
6219 }6329 }
6220 const payload = try func.load(err_union, pl_ty, pl_offset);6330 const payload = try func.load(err_union, pl_ty, pl_offset);
...@@ -6222,15 +6332,16 @@ fn lowerTry(...@@ -6222,15 +6332,16 @@ fn lowerTry(
6222}6332}
62236333
6224fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6334fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6335 const mod = func.bin_file.base.options.module.?;
6225 const ty_op = func.air.instructions.items(.data)[inst].ty_op;6336 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);
6228 const operand = try func.resolveInst(ty_op.operand);6339 const operand = try func.resolveInst(ty_op.operand);
62296340
6230 if (ty.zigTypeTag() == .Vector) {6341 if (ty.zigTypeTag(mod) == .Vector) {
6231 return func.fail("TODO: @byteSwap for vectors", .{});6342 return func.fail("TODO: @byteSwap for vectors", .{});
6232 }6343 }
6233 const int_info = ty.intInfo(func.target);6344 const int_info = ty.intInfo(mod);
62346345
6235 // bytes are no-op6346 // bytes are no-op
6236 if (int_info.bits == 8) {6347 if (int_info.bits == 8) {
...@@ -6292,13 +6403,14 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6292,13 +6403,14 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6292}6403}
62936404
6294fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6405fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6406 const mod = func.bin_file.base.options.module.?;
6295 const bin_op = func.air.instructions.items(.data)[inst].bin_op;6407 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);
6298 const lhs = try func.resolveInst(bin_op.lhs);6410 const lhs = try func.resolveInst(bin_op.lhs);
6299 const rhs = try func.resolveInst(bin_op.rhs);6411 const rhs = try func.resolveInst(bin_op.rhs);
63006412
6301 const result = if (ty.isSignedInt())6413 const result = if (ty.isSignedInt(mod))
6302 try func.divSigned(lhs, rhs, ty)6414 try func.divSigned(lhs, rhs, ty)
6303 else6415 else
6304 try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);6416 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 {...@@ -6306,13 +6418,14 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6306}6418}
63076419
6308fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6420fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6421 const mod = func.bin_file.base.options.module.?;
6309 const bin_op = func.air.instructions.items(.data)[inst].bin_op;6422 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);
6312 const lhs = try func.resolveInst(bin_op.lhs);6425 const lhs = try func.resolveInst(bin_op.lhs);
6313 const rhs = try func.resolveInst(bin_op.rhs);6426 const rhs = try func.resolveInst(bin_op.rhs);
63146427
6315 const div_result = if (ty.isSignedInt())6428 const div_result = if (ty.isSignedInt(mod))
6316 try func.divSigned(lhs, rhs, ty)6429 try func.divSigned(lhs, rhs, ty)
6317 else6430 else
6318 try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);6431 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 {...@@ -6328,15 +6441,16 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6328fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6441fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6329 const bin_op = func.air.instructions.items(.data)[inst].bin_op;6442 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);
6332 const lhs = try func.resolveInst(bin_op.lhs);6446 const lhs = try func.resolveInst(bin_op.lhs);
6333 const rhs = try func.resolveInst(bin_op.rhs);6447 const rhs = try func.resolveInst(bin_op.rhs);
63346448
6335 if (ty.isUnsignedInt()) {6449 if (ty.isUnsignedInt(mod)) {
6336 const result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);6450 const result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);
6337 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });6451 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6338 } else if (ty.isSignedInt()) {6452 } else if (ty.isSignedInt(mod)) {
6339 const int_bits = ty.intInfo(func.target).bits;6453 const int_bits = ty.intInfo(mod).bits;
6340 const wasm_bits = toWasmBits(int_bits) orelse {6454 const wasm_bits = toWasmBits(int_bits) orelse {
6341 return func.fail("TODO: `@divFloor` for signed integers larger than '{d}' bits", .{int_bits});6455 return func.fail("TODO: `@divFloor` for signed integers larger than '{d}' bits", .{int_bits});
6342 };6456 };
...@@ -6414,7 +6528,8 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6414,7 +6528,8 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6414}6528}
64156529
6416fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue {6530fn 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;
6418 const wasm_bits = toWasmBits(int_bits) orelse {6533 const wasm_bits = toWasmBits(int_bits) orelse {
6419 return func.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits});6534 return func.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits});
6420 };6535 };
...@@ -6441,7 +6556,8 @@ fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WVal...@@ -6441,7 +6556,8 @@ fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WVal
6441/// Retrieves the absolute value of a signed integer6556/// Retrieves the absolute value of a signed integer
6442/// NOTE: Leaves the result value on the stack.6557/// NOTE: Leaves the result value on the stack.
6443fn signAbsValue(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {6558fn 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;
6445 const wasm_bits = toWasmBits(int_bits) orelse {6561 const wasm_bits = toWasmBits(int_bits) orelse {
6446 return func.fail("TODO: signAbsValue for signed integers larger than '{d}' bits", .{int_bits});6562 return func.fail("TODO: signAbsValue for signed integers larger than '{d}' bits", .{int_bits});
6447 };6563 };
...@@ -6476,11 +6592,12 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -6476,11 +6592,12 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
6476 assert(op == .add or op == .sub);6592 assert(op == .add or op == .sub);
6477 const bin_op = func.air.instructions.items(.data)[inst].bin_op;6593 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);
6480 const lhs = try func.resolveInst(bin_op.lhs);6597 const lhs = try func.resolveInst(bin_op.lhs);
6481 const rhs = try func.resolveInst(bin_op.rhs);6598 const rhs = try func.resolveInst(bin_op.rhs);
64826599
6483 const int_info = ty.intInfo(func.target);6600 const int_info = ty.intInfo(mod);
6484 const is_signed = int_info.signedness == .signed;6601 const is_signed = int_info.signedness == .signed;
64856602
6486 if (int_info.bits > 64) {6603 if (int_info.bits > 64) {
...@@ -6523,7 +6640,8 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -6523,7 +6640,8 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
6523}6640}
65246641
6525fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op: Op) InnerError!WValue {6642fn 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);
6527 const wasm_bits = toWasmBits(int_info.bits).?;6645 const wasm_bits = toWasmBits(int_info.bits).?;
6528 const is_wasm_bits = wasm_bits == int_info.bits;6646 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,...@@ -6588,8 +6706,9 @@ fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type,
6588fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6706fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6589 const bin_op = func.air.instructions.items(.data)[inst].bin_op;6707 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
65906708
6591 const ty = func.air.typeOfIndex(inst);6709 const mod = func.bin_file.base.options.module.?;
6592 const int_info = ty.intInfo(func.target);6710 const ty = func.typeOfIndex(inst);
6711 const int_info = ty.intInfo(mod);
6593 const is_signed = int_info.signedness == .signed;6712 const is_signed = int_info.signedness == .signed;
6594 if (int_info.bits > 64) {6713 if (int_info.bits > 64) {
6595 return func.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits});6714 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 {...@@ -6697,7 +6816,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6697fn callIntrinsic(6816fn callIntrinsic(
6698 func: *CodeGen,6817 func: *CodeGen,
6699 name: []const u8,6818 name: []const u8,
6700 param_types: []const Type,6819 param_types: []const InternPool.Index,
6701 return_type: Type,6820 return_type: Type,
6702 args: []const WValue,6821 args: []const WValue,
6703) InnerError!WValue {6822) InnerError!WValue {
...@@ -6707,12 +6826,13 @@ fn callIntrinsic(...@@ -6707,12 +6826,13 @@ fn callIntrinsic(
6707 };6826 };
67086827
6709 // Always pass over C-ABI6828 // 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);
6711 defer func_type.deinit(func.gpa);6831 defer func_type.deinit(func.gpa);
6712 const func_type_index = try func.bin_file.putOrGetFuncType(func_type);6832 const func_type_index = try func.bin_file.putOrGetFuncType(func_type);
6713 try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index);6833 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);
6716 // if we want return as first param, we allocate a pointer to stack,6836 // if we want return as first param, we allocate a pointer to stack,
6717 // and emit it as our first argument6837 // and emit it as our first argument
6718 const sret = if (want_sret_param) blk: {6838 const sret = if (want_sret_param) blk: {
...@@ -6724,16 +6844,16 @@ fn callIntrinsic(...@@ -6724,16 +6844,16 @@ fn callIntrinsic(
6724 // Lower all arguments to the stack before we call our function6844 // Lower all arguments to the stack before we call our function
6725 for (args, 0..) |arg, arg_i| {6845 for (args, 0..) |arg, arg_i| {
6726 assert(!(want_sret_param and arg == .stack));6846 assert(!(want_sret_param and arg == .stack));
6727 assert(param_types[arg_i].hasRuntimeBitsIgnoreComptime());6847 assert(param_types[arg_i].toType().hasRuntimeBitsIgnoreComptime(mod));
6728 try func.lowerArg(.C, param_types[arg_i], arg);6848 try func.lowerArg(.C, param_types[arg_i].toType(), arg);
6729 }6849 }
67306850
6731 // Actually call our intrinsic6851 // Actually call our intrinsic
6732 try func.addLabel(.call, symbol_index);6852 try func.addLabel(.call, symbol_index);
67336853
6734 if (!return_type.hasRuntimeBitsIgnoreComptime()) {6854 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
6735 return WValue.none;6855 return WValue.none;
6736 } else if (return_type.isNoReturn()) {6856 } else if (return_type.isNoReturn(mod)) {
6737 try func.addTag(.@"unreachable");6857 try func.addTag(.@"unreachable");
6738 return WValue.none;6858 return WValue.none;
6739 } else if (want_sret_param) {6859 } else if (want_sret_param) {
...@@ -6746,11 +6866,11 @@ fn callIntrinsic(...@@ -6746,11 +6866,11 @@ fn callIntrinsic(
6746fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6866fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6747 const un_op = func.air.instructions.items(.data)[inst].un_op;6867 const un_op = func.air.instructions.items(.data)[inst].un_op;
6748 const operand = try func.resolveInst(un_op);6868 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
6751 const func_sym_index = try func.getTagNameFunction(enum_ty);6871 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));
6754 try func.lowerToStack(result_ptr);6874 try func.lowerToStack(result_ptr);
6755 try func.emitWValue(operand);6875 try func.emitWValue(operand);
6756 try func.addLabel(.call, func_sym_index);6876 try func.addLabel(.call, func_sym_index);
...@@ -6759,15 +6879,14 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6759,15 +6879,14 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6759}6879}
67606880
6761fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {6881fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
6762 const enum_decl_index = enum_ty.getOwnerDecl();6882 const mod = func.bin_file.base.options.module.?;
6763 const module = func.bin_file.base.options.module.?;6883 const enum_decl_index = enum_ty.getOwnerDecl(mod);
67646884
6765 var arena_allocator = std.heap.ArenaAllocator.init(func.gpa);6885 var arena_allocator = std.heap.ArenaAllocator.init(func.gpa);
6766 defer arena_allocator.deinit();6886 defer arena_allocator.deinit();
6767 const arena = arena_allocator.allocator();6887 const arena = arena_allocator.allocator();
67686888
6769 const fqn = try module.declPtr(enum_decl_index).getFullyQualifiedName(module);6889 const fqn = mod.intern_pool.stringToSlice(try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod));
6770 defer module.gpa.free(fqn);
6771 const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});6890 const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
67726891
6773 // check if we already generated code for this.6892 // check if we already generated code for this.
...@@ -6775,10 +6894,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -6775,10 +6894,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
6775 return loc.index;6894 return loc.index;
6776 }6895 }
67776896
6778 var int_tag_type_buffer: Type.Payload.Bits = undefined;6897 const int_tag_ty = enum_ty.intTagType(mod);
6779 const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);
67806898
6781 if (int_tag_ty.bitSize(func.target) > 64) {6899 if (int_tag_ty.bitSize(mod) > 64) {
6782 return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{});6900 return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{});
6783 }6901 }
67846902
...@@ -6798,36 +6916,22 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -6798,36 +6916,22 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
67986916
6799 // TODO: Make switch implementation generic so we can use a jump table for this when the tags are not sparse.6917 // TODO: Make switch implementation generic so we can use a jump table for this when the tags are not sparse.
6800 // generate an if-else chain for each tag value as well as constant.6918 // 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);
6802 // for each tag name, create an unnamed const,6922 // for each tag name, create an unnamed const,
6803 // and then get a pointer to its value.6923 // and then get a pointer to its value.
6804 var name_ty_payload: Type.Payload.Len = .{6924 const name_ty = try mod.arrayType(.{
6805 .base = .{ .tag = .array_u8_sentinel_0 },6925 .len = tag_name.len,
6806 .data = @intCast(u64, tag_name.len),6926 .child = .u8_type,
6807 };6927 .sentinel = .zero_u8,
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,
6815 });6928 });
6816 if (!gop.found_existing) {6929 const name_val = try mod.intern(.{ .aggregate = .{
6817 gop.key_ptr.* = .{6930 .ty = name_ty.toIntern(),
6818 .index = @intCast(u32, string_bytes.items.len),6931 .storage = .{ .bytes = tag_name },
6819 .len = @intCast(u32, tag_name.len),6932 } });
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);
6829 const tag_sym_index = try func.bin_file.lowerUnnamedConst(6933 const tag_sym_index = try func.bin_file.lowerUnnamedConst(
6830 .{ .ty = name_ty, .val = name_val },6934 .{ .ty = name_ty, .val = name_val.toValue() },
6831 enum_decl_index,6935 enum_decl_index,
6832 );6936 );
68336937
...@@ -6839,11 +6943,8 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -6839,11 +6943,8 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
6839 try writer.writeByte(std.wasm.opcode(.local_get));6943 try writer.writeByte(std.wasm.opcode(.local_get));
6840 try leb.writeULEB128(writer, @as(u32, 1));6944 try leb.writeULEB128(writer, @as(u32, 1));
68416945
6842 var tag_val_payload: Value.Payload.U32 = .{6946 const tag_val = try mod.enumValueFieldIndex(enum_ty, field_index);
6843 .base = .{ .tag = .enum_field_index },6947 const tag_value = try func.lowerConstant(tag_val, enum_ty);
6844 .data = @intCast(u32, field_index),
6845 };
6846 const tag_value = try func.lowerConstant(Value.initPayload(&tag_val_payload.base), enum_ty);
68476948
6848 switch (tag_value) {6949 switch (tag_value) {
6849 .imm32 => |value| {6950 .imm32 => |value| {
...@@ -6928,27 +7029,27 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -6928,27 +7029,27 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
6928 // finish function body7029 // finish function body
6929 try writer.writeByte(std.wasm.opcode(.end));7030 try writer.writeByte(std.wasm.opcode(.end));
69307031
6931 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);7032 const slice_ty = Type.slice_const_u8_sentinel_0;
6932 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty}, slice_ty, func.target);7033 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);
6933 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);7034 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
6934}7035}
69357036
6936fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7037fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7038 const mod = func.bin_file.base.options.module.?;
6937 const ty_op = func.air.instructions.items(.data)[inst].ty_op;7039 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
69387040
6939 const operand = try func.resolveInst(ty_op.operand);7041 const operand = try func.resolveInst(ty_op.operand);
6940 const error_set_ty = func.air.getRefType(ty_op.ty);7042 const error_set_ty = func.air.getRefType(ty_op.ty);
6941 const result = try func.allocLocal(Type.bool);7043 const result = try func.allocLocal(Type.bool);
69427044
6943 const names = error_set_ty.errorSetNames();7045 const names = error_set_ty.errorSetNames(mod);
6944 var values = try std.ArrayList(u32).initCapacity(func.gpa, names.len);7046 var values = try std.ArrayList(u32).initCapacity(func.gpa, names.len);
6945 defer values.deinit();7047 defer values.deinit();
69467048
6947 const module = func.bin_file.base.options.module.?;
6948 var lowest: ?u32 = null;7049 var lowest: ?u32 = null;
6949 var highest: ?u32 = null;7050 var highest: ?u32 = null;
6950 for (names) |name| {7051 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).?);
6952 if (lowest) |*l| {7053 if (lowest) |*l| {
6953 if (err_int < l.*) {7054 if (err_int < l.*) {
6954 l.* = err_int;7055 l.* = err_int;
...@@ -7019,12 +7120,13 @@ inline fn useAtomicFeature(func: *const CodeGen) bool {...@@ -7019,12 +7120,13 @@ inline fn useAtomicFeature(func: *const CodeGen) bool {
7019}7120}
70207121
7021fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7122fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7123 const mod = func.bin_file.base.options.module.?;
7022 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;7124 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
7023 const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data;7125 const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
70247126
7025 const ptr_ty = func.air.typeOf(extra.ptr);7127 const ptr_ty = func.typeOf(extra.ptr);
7026 const ty = ptr_ty.childType();7128 const ty = ptr_ty.childType(mod);
7027 const result_ty = func.air.typeOfIndex(inst);7129 const result_ty = func.typeOfIndex(inst);
70287130
7029 const ptr_operand = try func.resolveInst(extra.ptr);7131 const ptr_operand = try func.resolveInst(extra.ptr);
7030 const expected_val = try func.resolveInst(extra.expected_value);7132 const expected_val = try func.resolveInst(extra.expected_value);
...@@ -7037,7 +7139,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7037,7 +7139,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7037 try func.emitWValue(ptr_operand);7139 try func.emitWValue(ptr_operand);
7038 try func.lowerToStack(expected_val);7140 try func.lowerToStack(expected_val);
7039 try func.lowerToStack(new_val);7141 try func.lowerToStack(new_val);
7040 try func.addAtomicMemArg(switch (ty.abiSize(func.target)) {7142 try func.addAtomicMemArg(switch (ty.abiSize(mod)) {
7041 1 => .i32_atomic_rmw8_cmpxchg_u,7143 1 => .i32_atomic_rmw8_cmpxchg_u,
7042 2 => .i32_atomic_rmw16_cmpxchg_u,7144 2 => .i32_atomic_rmw16_cmpxchg_u,
7043 4 => .i32_atomic_rmw_cmpxchg,7145 4 => .i32_atomic_rmw_cmpxchg,
...@@ -7045,14 +7147,14 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7045,14 +7147,14 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7045 else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}),7147 else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}),
7046 }, .{7148 }, .{
7047 .offset = ptr_operand.offset(),7149 .offset = ptr_operand.offset(),
7048 .alignment = ty.abiAlignment(func.target),7150 .alignment = ty.abiAlignment(mod),
7049 });7151 });
7050 try func.addLabel(.local_tee, val_local.local.value);7152 try func.addLabel(.local_tee, val_local.local.value);
7051 _ = try func.cmp(.stack, expected_val, ty, .eq);7153 _ = try func.cmp(.stack, expected_val, ty, .eq);
7052 try func.addLabel(.local_set, cmp_result.local.value);7154 try func.addLabel(.local_set, cmp_result.local.value);
7053 break :val val_local;7155 break :val val_local;
7054 } else val: {7156 } else val: {
7055 if (ty.abiSize(func.target) > 8) {7157 if (ty.abiSize(mod) > 8) {
7056 return func.fail("TODO: Implement `@cmpxchg` for types larger than abi size of 8 bytes", .{});7158 return func.fail("TODO: Implement `@cmpxchg` for types larger than abi size of 8 bytes", .{});
7057 }7159 }
7058 const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty);7160 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 {...@@ -7068,7 +7170,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7068 break :val ptr_val;7170 break :val ptr_val;
7069 };7171 };
70707172
7071 const result_ptr = if (isByRef(result_ty, func.target)) val: {7173 const result_ptr = if (isByRef(result_ty, mod)) val: {
7072 try func.emitWValue(cmp_result);7174 try func.emitWValue(cmp_result);
7073 try func.addImm32(-1);7175 try func.addImm32(-1);
7074 try func.addTag(.i32_xor);7176 try func.addTag(.i32_xor);
...@@ -7076,7 +7178,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7076,7 +7178,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7076 try func.addTag(.i32_and);7178 try func.addTag(.i32_and);
7077 const and_result = try WValue.toLocal(.stack, func, Type.bool);7179 const and_result = try WValue.toLocal(.stack, func, Type.bool);
7078 const result_ptr = try func.allocStack(result_ty);7180 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)));
7080 try func.store(result_ptr, ptr_val, ty, 0);7182 try func.store(result_ptr, ptr_val, ty, 0);
7081 break :val result_ptr;7183 break :val result_ptr;
7082 } else val: {7184 } else val: {
...@@ -7087,16 +7189,17 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7087,16 +7189,17 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7087 break :val try WValue.toLocal(.stack, func, result_ty);7189 break :val try WValue.toLocal(.stack, func, result_ty);
7088 };7190 };
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 });
7091}7193}
70927194
7093fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7195fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7196 const mod = func.bin_file.base.options.module.?;
7094 const atomic_load = func.air.instructions.items(.data)[inst].atomic_load;7197 const atomic_load = func.air.instructions.items(.data)[inst].atomic_load;
7095 const ptr = try func.resolveInst(atomic_load.ptr);7198 const ptr = try func.resolveInst(atomic_load.ptr);
7096 const ty = func.air.typeOfIndex(inst);7199 const ty = func.typeOfIndex(inst);
70977200
7098 if (func.useAtomicFeature()) {7201 if (func.useAtomicFeature()) {
7099 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) {7202 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) {
7100 1 => .i32_atomic_load8_u,7203 1 => .i32_atomic_load8_u,
7101 2 => .i32_atomic_load16_u,7204 2 => .i32_atomic_load16_u,
7102 4 => .i32_atomic_load,7205 4 => .i32_atomic_load,
...@@ -7106,7 +7209,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7106,7 +7209,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7106 try func.emitWValue(ptr);7209 try func.emitWValue(ptr);
7107 try func.addAtomicMemArg(tag, .{7210 try func.addAtomicMemArg(tag, .{
7108 .offset = ptr.offset(),7211 .offset = ptr.offset(),
7109 .alignment = ty.abiAlignment(func.target),7212 .alignment = ty.abiAlignment(mod),
7110 });7213 });
7111 } else {7214 } else {
7112 _ = try func.load(ptr, ty, 0);7215 _ = try func.load(ptr, ty, 0);
...@@ -7117,12 +7220,13 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7117,12 +7220,13 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7117}7220}
71187221
7119fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7222fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7223 const mod = func.bin_file.base.options.module.?;
7120 const pl_op = func.air.instructions.items(.data)[inst].pl_op;7224 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
7121 const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data;7225 const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data;
71227226
7123 const ptr = try func.resolveInst(pl_op.operand);7227 const ptr = try func.resolveInst(pl_op.operand);
7124 const operand = try func.resolveInst(extra.operand);7228 const operand = try func.resolveInst(extra.operand);
7125 const ty = func.air.typeOfIndex(inst);7229 const ty = func.typeOfIndex(inst);
7126 const op: std.builtin.AtomicRmwOp = extra.op();7230 const op: std.builtin.AtomicRmwOp = extra.op();
71277231
7128 if (func.useAtomicFeature()) {7232 if (func.useAtomicFeature()) {
...@@ -7140,7 +7244,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7140,7 +7244,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7140 try func.emitWValue(ptr);7244 try func.emitWValue(ptr);
7141 try func.emitWValue(value);7245 try func.emitWValue(value);
7142 if (op == .Nand) {7246 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
7145 const and_res = try func.binOp(value, operand, ty, .@"and");7249 const and_res = try func.binOp(value, operand, ty, .@"and");
7146 if (wasm_bits == 32)7250 if (wasm_bits == 32)
...@@ -7157,7 +7261,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7157,7 +7261,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7157 try func.addTag(.select);7261 try func.addTag(.select);
7158 }7262 }
7159 try func.addAtomicMemArg(7263 try func.addAtomicMemArg(
7160 switch (ty.abiSize(func.target)) {7264 switch (ty.abiSize(mod)) {
7161 1 => .i32_atomic_rmw8_cmpxchg_u,7265 1 => .i32_atomic_rmw8_cmpxchg_u,
7162 2 => .i32_atomic_rmw16_cmpxchg_u,7266 2 => .i32_atomic_rmw16_cmpxchg_u,
7163 4 => .i32_atomic_rmw_cmpxchg,7267 4 => .i32_atomic_rmw_cmpxchg,
...@@ -7166,7 +7270,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7166,7 +7270,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7166 },7270 },
7167 .{7271 .{
7168 .offset = ptr.offset(),7272 .offset = ptr.offset(),
7169 .alignment = ty.abiAlignment(func.target),7273 .alignment = ty.abiAlignment(mod),
7170 },7274 },
7171 );7275 );
7172 const select_res = try func.allocLocal(ty);7276 const select_res = try func.allocLocal(ty);
...@@ -7185,7 +7289,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7185,7 +7289,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7185 else => {7289 else => {
7186 try func.emitWValue(ptr);7290 try func.emitWValue(ptr);
7187 try func.emitWValue(operand);7291 try func.emitWValue(operand);
7188 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) {7292 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) {
7189 1 => switch (op) {7293 1 => switch (op) {
7190 .Xchg => .i32_atomic_rmw8_xchg_u,7294 .Xchg => .i32_atomic_rmw8_xchg_u,
7191 .Add => .i32_atomic_rmw8_add_u,7295 .Add => .i32_atomic_rmw8_add_u,
...@@ -7226,7 +7330,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7226,7 +7330,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7226 };7330 };
7227 try func.addAtomicMemArg(tag, .{7331 try func.addAtomicMemArg(tag, .{
7228 .offset = ptr.offset(),7332 .offset = ptr.offset(),
7229 .alignment = ty.abiAlignment(func.target),7333 .alignment = ty.abiAlignment(mod),
7230 });7334 });
7231 const result = try WValue.toLocal(.stack, func, ty);7335 const result = try WValue.toLocal(.stack, func, ty);
7232 return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand });7336 return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand });
...@@ -7255,7 +7359,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7255,7 +7359,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7255 .Xor => .xor,7359 .Xor => .xor,
7256 else => unreachable,7360 else => unreachable,
7257 });7361 });
7258 if (ty.isInt() and (op == .Add or op == .Sub)) {7362 if (ty.isInt(mod) and (op == .Add or op == .Sub)) {
7259 _ = try func.wrapOperand(.stack, ty);7363 _ = try func.wrapOperand(.stack, ty);
7260 }7364 }
7261 try func.store(.stack, .stack, ty, ptr.offset());7365 try func.store(.stack, .stack, ty, ptr.offset());
...@@ -7271,7 +7375,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7271,7 +7375,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7271 try func.store(.stack, .stack, ty, ptr.offset());7375 try func.store(.stack, .stack, ty, ptr.offset());
7272 },7376 },
7273 .Nand => {7377 .Nand => {
7274 const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?;7378 const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?;
72757379
7276 try func.emitWValue(ptr);7380 try func.emitWValue(ptr);
7277 const and_res = try func.binOp(result, operand, ty, .@"and");7381 const and_res = try func.binOp(result, operand, ty, .@"and");
...@@ -7302,15 +7406,16 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7302,15 +7406,16 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7302}7406}
73037407
7304fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7408fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7409 const mod = func.bin_file.base.options.module.?;
7305 const bin_op = func.air.instructions.items(.data)[inst].bin_op;7410 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
73067411
7307 const ptr = try func.resolveInst(bin_op.lhs);7412 const ptr = try func.resolveInst(bin_op.lhs);
7308 const operand = try func.resolveInst(bin_op.rhs);7413 const operand = try func.resolveInst(bin_op.rhs);
7309 const ptr_ty = func.air.typeOf(bin_op.lhs);7414 const ptr_ty = func.typeOf(bin_op.lhs);
7310 const ty = ptr_ty.childType();7415 const ty = ptr_ty.childType(mod);
73117416
7312 if (func.useAtomicFeature()) {7417 if (func.useAtomicFeature()) {
7313 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) {7418 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) {
7314 1 => .i32_atomic_store8,7419 1 => .i32_atomic_store8,
7315 2 => .i32_atomic_store16,7420 2 => .i32_atomic_store16,
7316 4 => .i32_atomic_store,7421 4 => .i32_atomic_store,
...@@ -7321,7 +7426,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7321,7 +7426,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7321 try func.lowerToStack(operand);7426 try func.lowerToStack(operand);
7322 try func.addAtomicMemArg(tag, .{7427 try func.addAtomicMemArg(tag, .{
7323 .offset = ptr.offset(),7428 .offset = ptr.offset(),
7324 .alignment = ty.abiAlignment(func.target),7429 .alignment = ty.abiAlignment(mod),
7325 });7430 });
7326 } else {7431 } else {
7327 try func.store(ptr, operand, ty, 0);7432 try func.store(ptr, operand, ty, 0);
...@@ -7338,3 +7443,13 @@ fn airFrameAddress(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7338,3 +7443,13 @@ fn airFrameAddress(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7338 const result = try WValue.toLocal(.stack, func, Type.usize);7443 const result = try WValue.toLocal(.stack, func, Type.usize);
7339 return func.finishAir(inst, result, &.{});7444 return func.finishAir(inst, result, &.{});
7340}7445}
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 {...@@ -254,7 +254,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
254 @setCold(true);254 @setCold(true);
255 std.debug.assert(emit.error_msg == null);255 std.debug.assert(emit.error_msg == null);
256 const mod = emit.bin_file.base.options.module.?;256 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);
258 return error.EmitFail;258 return error.EmitFail;
259}259}
260260
src/arch/wasm/abi.zig+33-30
...@@ -5,9 +5,11 @@...@@ -5,9 +5,11 @@
5//! Note: Above mentioned document is not an official specification, therefore called a convention.5//! Note: Above mentioned document is not an official specification, therefore called a convention.
66
7const std = @import("std");7const std = @import("std");
8const Type = @import("../../type.zig").Type;
9const Target = std.Target;8const Target = std.Target;
109
10const Type = @import("../../type.zig").Type;
11const Module = @import("../../Module.zig");
12
11/// Defines how to pass a type as part of a function signature,13/// Defines how to pass a type as part of a function signature,
12/// both for parameters as well as return values.14/// both for parameters as well as return values.
13pub const Class = enum { direct, indirect, none };15pub const Class = enum { direct, indirect, none };
...@@ -19,27 +21,28 @@ const direct: [2]Class = .{ .direct, .none };...@@ -19,27 +21,28 @@ const direct: [2]Class = .{ .direct, .none };
19/// Classifies a given Zig type to determine how they must be passed21/// Classifies a given Zig type to determine how they must be passed
20/// or returned as value within a wasm function.22/// or returned as value within a wasm function.
21/// When all elements result in `.none`, no value must be passed in or returned.23/// When all elements result in `.none`, no value must be passed in or returned.
22pub fn classifyType(ty: Type, target: Target) [2]Class {24pub fn classifyType(ty: Type, mod: *Module) [2]Class {
23 if (!ty.hasRuntimeBitsIgnoreComptime()) return none;25 const target = mod.getTarget();
24 switch (ty.zigTypeTag()) {26 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none;
27 switch (ty.zigTypeTag(mod)) {
25 .Struct => {28 .Struct => {
26 if (ty.containerLayout() == .Packed) {29 if (ty.containerLayout(mod) == .Packed) {
27 if (ty.bitSize(target) <= 64) return direct;30 if (ty.bitSize(mod) <= 64) return direct;
28 return .{ .direct, .direct };31 return .{ .direct, .direct };
29 }32 }
30 // When the struct type is non-scalar33 // When the struct type is non-scalar
31 if (ty.structFieldCount() > 1) return memory;34 if (ty.structFieldCount(mod) > 1) return memory;
32 // When the struct's alignment is non-natural35 // When the struct's alignment is non-natural
33 const field = ty.structFields().values()[0];36 const field = ty.structFields(mod).values()[0];
34 if (field.abi_align != 0) {37 if (field.abi_align != 0) {
35 if (field.abi_align > field.ty.abiAlignment(target)) {38 if (field.abi_align > field.ty.abiAlignment(mod)) {
36 return memory;39 return memory;
37 }40 }
38 }41 }
39 return classifyType(field.ty, target);42 return classifyType(field.ty, mod);
40 },43 },
41 .Int, .Enum, .ErrorSet, .Vector => {44 .Int, .Enum, .ErrorSet, .Vector => {
42 const int_bits = ty.intInfo(target).bits;45 const int_bits = ty.intInfo(mod).bits;
43 if (int_bits <= 64) return direct;46 if (int_bits <= 64) return direct;
44 if (int_bits <= 128) return .{ .direct, .direct };47 if (int_bits <= 128) return .{ .direct, .direct };
45 return memory;48 return memory;
...@@ -53,22 +56,22 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {...@@ -53,22 +56,22 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
53 .Bool => return direct,56 .Bool => return direct,
54 .Array => return memory,57 .Array => return memory,
55 .Optional => {58 .Optional => {
56 std.debug.assert(ty.isPtrLikeOptional());59 std.debug.assert(ty.isPtrLikeOptional(mod));
57 return direct;60 return direct;
58 },61 },
59 .Pointer => {62 .Pointer => {
60 std.debug.assert(!ty.isSlice());63 std.debug.assert(!ty.isSlice(mod));
61 return direct;64 return direct;
62 },65 },
63 .Union => {66 .Union => {
64 if (ty.containerLayout() == .Packed) {67 if (ty.containerLayout(mod) == .Packed) {
65 if (ty.bitSize(target) <= 64) return direct;68 if (ty.bitSize(mod) <= 64) return direct;
66 return .{ .direct, .direct };69 return .{ .direct, .direct };
67 }70 }
68 const layout = ty.unionGetLayout(target);71 const layout = ty.unionGetLayout(mod);
69 std.debug.assert(layout.tag_size == 0);72 std.debug.assert(layout.tag_size == 0);
70 if (ty.unionFields().count() > 1) return memory;73 if (ty.unionFields(mod).count() > 1) return memory;
71 return classifyType(ty.unionFields().values()[0].ty, target);74 return classifyType(ty.unionFields(mod).values()[0].ty, mod);
72 },75 },
73 .ErrorUnion,76 .ErrorUnion,
74 .Frame,77 .Frame,
...@@ -90,29 +93,29 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {...@@ -90,29 +93,29 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
90/// Returns the scalar type a given type can represent.93/// Returns the scalar type a given type can represent.
91/// Asserts given type can be represented as scalar, such as94/// Asserts given type can be represented as scalar, such as
92/// a struct with a single scalar field.95/// a struct with a single scalar field.
93pub fn scalarType(ty: Type, target: std.Target) Type {96pub fn scalarType(ty: Type, mod: *Module) Type {
94 switch (ty.zigTypeTag()) {97 switch (ty.zigTypeTag(mod)) {
95 .Struct => {98 .Struct => {
96 switch (ty.containerLayout()) {99 switch (ty.containerLayout(mod)) {
97 .Packed => {100 .Packed => {
98 const struct_obj = ty.castTag(.@"struct").?.data;101 const struct_obj = mod.typeToStruct(ty).?;
99 return scalarType(struct_obj.backing_int_ty, target);102 return scalarType(struct_obj.backing_int_ty, mod);
100 },103 },
101 else => {104 else => {
102 std.debug.assert(ty.structFieldCount() == 1);105 std.debug.assert(ty.structFieldCount(mod) == 1);
103 return scalarType(ty.structFieldType(0), target);106 return scalarType(ty.structFieldType(0, mod), mod);
104 },107 },
105 }108 }
106 },109 },
107 .Union => {110 .Union => {
108 if (ty.containerLayout() != .Packed) {111 if (ty.containerLayout(mod) != .Packed) {
109 const layout = ty.unionGetLayout(target);112 const layout = ty.unionGetLayout(mod);
110 if (layout.payload_size == 0 and layout.tag_size != 0) {113 if (layout.payload_size == 0 and layout.tag_size != 0) {
111 return scalarType(ty.unionTagTypeSafety().?, target);114 return scalarType(ty.unionTagTypeSafety(mod).?, mod);
112 }115 }
113 std.debug.assert(ty.unionFields().count() == 1);116 std.debug.assert(ty.unionFields(mod).count() == 1);
114 }117 }
115 return scalarType(ty.unionFields().values()[0].ty, target);118 return scalarType(ty.unionFields(mod).values()[0].ty, mod);
116 },119 },
117 else => return ty,120 else => return ty,
118 }121 }
src/arch/x86_64/CodeGen.zig+784-772
...@@ -26,6 +26,7 @@ const Liveness = @import("../../Liveness.zig");...@@ -26,6 +26,7 @@ const Liveness = @import("../../Liveness.zig");
26const Lower = @import("Lower.zig");26const Lower = @import("Lower.zig");
27const Mir = @import("Mir.zig");27const Mir = @import("Mir.zig");
28const Module = @import("../../Module.zig");28const Module = @import("../../Module.zig");
29const InternPool = @import("../../InternPool.zig");
29const Target = std.Target;30const Target = std.Target;
30const Type = @import("../../type.zig").Type;31const Type = @import("../../type.zig").Type;
31const TypedValue = @import("../../TypedValue.zig");32const TypedValue = @import("../../TypedValue.zig");
...@@ -112,10 +113,10 @@ const Owner = union(enum) {...@@ -112,10 +113,10 @@ const Owner = union(enum) {
112 mod_fn: *const Module.Fn,113 mod_fn: *const Module.Fn,
113 lazy_sym: link.File.LazySymbol,114 lazy_sym: link.File.LazySymbol,
114115
115 fn getDecl(owner: Owner) Module.Decl.Index {116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
116 return switch (owner) {117 return switch (owner) {
117 .mod_fn => |mod_fn| mod_fn.owner_decl,118 .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),
119 };120 };
120 }121 }
121122
...@@ -447,7 +448,7 @@ const InstTracking = struct {...@@ -447,7 +448,7 @@ const InstTracking = struct {
447 else => unreachable,448 else => unreachable,
448 }449 }
449 tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long });450 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);
451 }452 }
452453
453 fn reuseFrame(self: *InstTracking) void {454 fn reuseFrame(self: *InstTracking) void {
...@@ -537,7 +538,7 @@ const InstTracking = struct {...@@ -537,7 +538,7 @@ const InstTracking = struct {
537 inst: Air.Inst.Index,538 inst: Air.Inst.Index,
538 target: InstTracking,539 target: InstTracking,
539 ) !void {540 ) !void {
540 const ty = function.air.typeOfIndex(inst);541 const ty = function.typeOfIndex(inst);
541 if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame)542 if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame)
542 try function.genCopy(ty, target.long, self.short);543 try function.genCopy(ty, target.long, self.short);
543 try function.genCopy(ty, target.short, self.short);544 try function.genCopy(ty, target.short, self.short);
...@@ -605,14 +606,14 @@ const FrameAlloc = struct {...@@ -605,14 +606,14 @@ const FrameAlloc = struct {
605 .ref_count = 0,606 .ref_count = 0,
606 };607 };
607 }608 }
608 fn initType(ty: Type, target: Target) FrameAlloc {609 fn initType(ty: Type, mod: *Module) FrameAlloc {
609 return init(.{ .size = ty.abiSize(target), .alignment = ty.abiAlignment(target) });610 return init(.{ .size = ty.abiSize(mod), .alignment = ty.abiAlignment(mod) });
610 }611 }
611};612};
612613
613const StackAllocation = struct {614const StackAllocation = struct {
614 inst: ?Air.Inst.Index,615 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)
616 size: u32,617 size: u32,
617};618};
618619
...@@ -631,7 +632,7 @@ const Self = @This();...@@ -631,7 +632,7 @@ const Self = @This();
631pub fn generate(632pub fn generate(
632 bin_file: *link.File,633 bin_file: *link.File,
633 src_loc: Module.SrcLoc,634 src_loc: Module.SrcLoc,
634 module_fn: *Module.Fn,635 module_fn_index: Module.Fn.Index,
635 air: Air,636 air: Air,
636 liveness: Liveness,637 liveness: Liveness,
637 code: *std.ArrayList(u8),638 code: *std.ArrayList(u8),
...@@ -642,6 +643,7 @@ pub fn generate(...@@ -642,6 +643,7 @@ pub fn generate(
642 }643 }
643644
644 const mod = bin_file.options.module.?;645 const mod = bin_file.options.module.?;
646 const module_fn = mod.funcPtr(module_fn_index);
645 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);647 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
646 assert(fn_owner_decl.has_tv);648 assert(fn_owner_decl.has_tv);
647 const fn_type = fn_owner_decl.ty;649 const fn_type = fn_owner_decl.ty;
...@@ -686,7 +688,7 @@ pub fn generate(...@@ -686,7 +688,7 @@ pub fn generate(
686 @enumToInt(FrameIndex.stack_frame),688 @enumToInt(FrameIndex.stack_frame),
687 FrameAlloc.init(.{689 FrameAlloc.init(.{
688 .size = 0,690 .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|
690 set_align_stack.alignment692 set_align_stack.alignment
691 else693 else
692 1,694 1,
...@@ -697,7 +699,8 @@ pub fn generate(...@@ -697,7 +699,8 @@ pub fn generate(
697 FrameAlloc.init(.{ .size = 0, .alignment = 1 }),699 FrameAlloc.init(.{ .size = 0, .alignment = 1 }),
698 );700 );
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) {
701 error.CodegenFail => return Result{ .fail = function.err_msg.? },704 error.CodegenFail => return Result{ .fail = function.err_msg.? },
702 error.OutOfRegisters => return Result{705 error.OutOfRegisters => return Result{
703 .fail = try ErrorMsg.create(706 .fail = try ErrorMsg.create(
...@@ -714,12 +717,12 @@ pub fn generate(...@@ -714,12 +717,12 @@ pub fn generate(
714 function.args = call_info.args;717 function.args = call_info.args;
715 function.ret_mcv = call_info.return_value;718 function.ret_mcv = call_info.return_value;
716 function.frame_allocs.set(@enumToInt(FrameIndex.ret_addr), FrameAlloc.init(.{719 function.frame_allocs.set(@enumToInt(FrameIndex.ret_addr), FrameAlloc.init(.{
717 .size = Type.usize.abiSize(function.target.*),720 .size = Type.usize.abiSize(mod),
718 .alignment = @min(Type.usize.abiAlignment(function.target.*), call_info.stack_align),721 .alignment = @min(Type.usize.abiAlignment(mod), call_info.stack_align),
719 }));722 }));
720 function.frame_allocs.set(@enumToInt(FrameIndex.base_ptr), FrameAlloc.init(.{723 function.frame_allocs.set(@enumToInt(FrameIndex.base_ptr), FrameAlloc.init(.{
721 .size = Type.usize.abiSize(function.target.*),724 .size = Type.usize.abiSize(mod),
722 .alignment = @min(Type.usize.abiAlignment(function.target.*) * 2, call_info.stack_align),725 .alignment = @min(Type.usize.abiAlignment(mod) * 2, call_info.stack_align),
723 }));726 }));
724 function.frame_allocs.set(727 function.frame_allocs.set(
725 @enumToInt(FrameIndex.args_frame),728 @enumToInt(FrameIndex.args_frame),
...@@ -1565,7 +1568,8 @@ fn asmMemoryRegisterImmediate(...@@ -1565,7 +1568,8 @@ fn asmMemoryRegisterImmediate(
1565}1568}
15661569
1567fn gen(self: *Self) InnerError!void {1570fn 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);
1569 if (cc != .Naked) {1573 if (cc != .Naked) {
1570 try self.asmRegister(.{ ._, .push }, .rbp);1574 try self.asmRegister(.{ ._, .push }, .rbp);
1571 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();1575 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
...@@ -1582,7 +1586,7 @@ fn gen(self: *Self) InnerError!void {...@@ -1582,7 +1586,7 @@ fn gen(self: *Self) InnerError!void {
1582 // register which the callee is free to clobber. Therefore, we purposely1586 // register which the callee is free to clobber. Therefore, we purposely
1583 // spill it to stack immediately.1587 // spill it to stack immediately.
1584 const frame_index =1588 const frame_index =
1585 try self.allocFrameIndex(FrameAlloc.initType(Type.usize, self.target.*));1589 try self.allocFrameIndex(FrameAlloc.initType(Type.usize, mod));
1586 try self.genSetMem(1590 try self.genSetMem(
1587 .{ .frame = frame_index },1591 .{ .frame = frame_index },
1588 0,1592 0,
...@@ -1724,6 +1728,8 @@ fn gen(self: *Self) InnerError!void {...@@ -1724,6 +1728,8 @@ fn gen(self: *Self) InnerError!void {
1724}1728}
17251729
1726fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {1730fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1731 const mod = self.bin_file.options.module.?;
1732 const ip = &mod.intern_pool;
1727 const air_tags = self.air.instructions.items(.tag);1733 const air_tags = self.air.instructions.items(.tag);
17281734
1729 for (body) |inst| {1735 for (body) |inst| {
...@@ -1732,7 +1738,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1732,7 +1738,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1732 try self.mir_to_air_map.put(self.gpa, mir_inst, inst);1738 try self.mir_to_air_map.put(self.gpa, mir_inst, inst);
1733 }1739 }
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;
1736 wip_mir_log.debug("{}", .{self.fmtAir(inst)});1742 wip_mir_log.debug("{}", .{self.fmtAir(inst)});
1737 verbose_tracking_log.debug("{}", .{self.fmtTracking()});1743 verbose_tracking_log.debug("{}", .{self.fmtTracking()});
17381744
...@@ -1916,8 +1922,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1916,8 +1922,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1916 .ptr_elem_val => try self.airPtrElemVal(inst),1922 .ptr_elem_val => try self.airPtrElemVal(inst),
1917 .ptr_elem_ptr => try self.airPtrElemPtr(inst),1923 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
19181924
1919 .constant => unreachable, // excluded from function bodies1925 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
1920 .const_ty => unreachable, // excluded from function bodies
1921 .unreach => if (self.wantSafety()) try self.airTrap() else self.finishAirBookkeeping(),1926 .unreach => if (self.wantSafety()) try self.airTrap() else self.finishAirBookkeeping(),
19221927
1923 .optional_payload => try self.airOptionalPayload(inst),1928 .optional_payload => try self.airOptionalPayload(inst),
...@@ -1999,7 +2004,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1999,7 +2004,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1999}2004}
20002005
2001fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {2006fn 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)) {
2003 .Enum => {2009 .Enum => {
2004 const enum_ty = lazy_sym.ty;2010 const enum_ty = lazy_sym.ty;
2005 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(self.bin_file.options.module.?)});2011 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 {...@@ -2011,7 +2017,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2011 const ret_reg = param_regs[0];2017 const ret_reg = param_regs[0];
2012 const enum_mcv = MCValue{ .register = param_regs[1] };2018 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));
2015 defer self.gpa.free(exitlude_jump_relocs);2021 defer self.gpa.free(exitlude_jump_relocs);
20162022
2017 const data_reg = try self.register_manager.allocReg(null, gp);2023 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 {...@@ -2020,16 +2026,10 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2020 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });2026 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
20212027
2022 var data_off: i32 = 0;2028 var data_off: i32 = 0;
2023 for (2029 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| {
2024 exitlude_jump_relocs,2030 const index = @intCast(u32, index_usize);
2025 enum_ty.enumFields().keys(),2031 const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]);
2026 0..,2032 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
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);
2033 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });2033 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
2034 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);2034 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
2035 const skip_reloc = try self.asmJccReloc(undefined, .ne);2035 const skip_reloc = try self.asmJccReloc(undefined, .ne);
...@@ -2092,10 +2092,8 @@ fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) void {...@@ -2092,10 +2092,8 @@ fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) void {
20922092
2093/// Asserts there is already capacity to insert into top branch inst_table.2093/// Asserts there is already capacity to insert into top branch inst_table.
2094fn processDeath(self: *Self, inst: Air.Inst.Index) void {2094fn processDeath(self: *Self, inst: Air.Inst.Index) void {
2095 switch (self.air.instructions.items(.tag)[inst]) {2095 assert(self.air.instructions.items(.tag)[inst] != .interned);
2096 .constant, .const_ty => unreachable,2096 self.inst_tracking.getPtr(inst).?.die(self, inst);
2097 else => self.inst_tracking.getPtr(inst).?.die(self, inst),
2098 }
2099}2097}
21002098
2101/// Called when there are no operands, and the instruction is always unreferenced.2099/// 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...@@ -2126,10 +2124,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
2126 const dies = @truncate(u1, tomb_bits) != 0;2124 const dies = @truncate(u1, tomb_bits) != 0;
2127 tomb_bits >>= 1;2125 tomb_bits >>= 1;
2128 if (!dies) continue;2126 if (!dies) continue;
2129 const op_int = @enumToInt(op);2127 self.processDeath(Air.refToIndexAllowNone(op) orelse continue);
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);
2133 }2128 }
2134 self.finishAirResult(inst, result);2129 self.finishAirResult(inst, result);
2135}2130}
...@@ -2252,19 +2247,19 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex {...@@ -2252,19 +2247,19 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex {
22522247
2253/// Use a pointer instruction as the basis for allocating stack memory.2248/// Use a pointer instruction as the basis for allocating stack memory.
2254fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex {2249fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex {
2255 const ptr_ty = self.air.typeOfIndex(inst);2250 const mod = self.bin_file.options.module.?;
2256 const val_ty = ptr_ty.childType();2251 const ptr_ty = self.typeOfIndex(inst);
2252 const val_ty = ptr_ty.childType(mod);
2257 return self.allocFrameIndex(FrameAlloc.init(.{2253 return self.allocFrameIndex(FrameAlloc.init(.{
2258 .size = math.cast(u32, val_ty.abiSize(self.target.*)) orelse {2254 .size = math.cast(u32, val_ty.abiSize(mod)) orelse {
2259 const mod = self.bin_file.options.module.?;
2260 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(mod)});2255 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(mod)});
2261 },2256 },
2262 .alignment = @max(ptr_ty.ptrAlignment(self.target.*), 1),2257 .alignment = @max(ptr_ty.ptrAlignment(mod), 1),
2263 }));2258 }));
2264}2259}
22652260
2266fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {2261fn 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);
2268}2263}
22692264
2270fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue {2265fn 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 {...@@ -2272,20 +2267,20 @@ fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue {
2272}2267}
22732268
2274fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue {2269fn 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 {2270 const mod = self.bin_file.options.module.?;
2276 const mod = self.bin_file.options.module.?;2271 const abi_size = math.cast(u32, ty.abiSize(mod)) orelse {
2277 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});2272 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
2278 };2273 };
22792274
2280 if (reg_ok) need_mem: {2275 if (reg_ok) need_mem: {
2281 if (abi_size <= @as(u32, switch (ty.zigTypeTag()) {2276 if (abi_size <= @as(u32, switch (ty.zigTypeTag(mod)) {
2282 .Float => switch (ty.floatBits(self.target.*)) {2277 .Float => switch (ty.floatBits(self.target.*)) {
2283 16, 32, 64, 128 => 16,2278 16, 32, 64, 128 => 16,
2284 80 => break :need_mem,2279 80 => break :need_mem,
2285 else => unreachable,2280 else => unreachable,
2286 },2281 },
2287 .Vector => switch (ty.childType().zigTypeTag()) {2282 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
2288 .Float => switch (ty.childType().floatBits(self.target.*)) {2283 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
2289 16, 32, 64, 128 => if (self.hasFeature(.avx)) 32 else 16,2284 16, 32, 64, 128 => if (self.hasFeature(.avx)) 32 else 16,
2290 80 => break :need_mem,2285 80 => break :need_mem,
2291 else => unreachable,2286 else => unreachable,
...@@ -2294,18 +2289,18 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b...@@ -2294,18 +2289,18 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b
2294 },2289 },
2295 else => 8,2290 else => 8,
2296 })) {2291 })) {
2297 if (self.register_manager.tryAllocReg(inst, regClassForType(ty))) |reg| {2292 if (self.register_manager.tryAllocReg(inst, regClassForType(ty, mod))) |reg| {
2298 return MCValue{ .register = registerAlias(reg, abi_size) };2293 return MCValue{ .register = registerAlias(reg, abi_size) };
2299 }2294 }
2300 }2295 }
2301 }2296 }
23022297
2303 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, self.target.*));2298 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, mod));
2304 return .{ .load_frame = .{ .index = frame_index } };2299 return .{ .load_frame = .{ .index = frame_index } };
2305}2300}
23062301
2307fn regClassForType(ty: Type) RegisterManager.RegisterBitSet {2302fn regClassForType(ty: Type, mod: *Module) RegisterManager.RegisterBitSet {
2308 return switch (ty.zigTypeTag()) {2303 return switch (ty.zigTypeTag(mod)) {
2309 .Float, .Vector => sse,2304 .Float, .Vector => sse,
2310 else => gp,2305 else => gp,
2311 };2306 };
...@@ -2449,7 +2444,8 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void {...@@ -2449,7 +2444,8 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void {
2449/// allocated. A second call to `copyToTmpRegister` may return the same register.2444/// allocated. A second call to `copyToTmpRegister` may return the same register.
2450/// This can have a side effect of spilling instructions to the stack to free up a register.2445/// This can have a side effect of spilling instructions to the stack to free up a register.
2451fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {2446fn 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));
2453 try self.genSetReg(reg, ty, mcv);2449 try self.genSetReg(reg, ty, mcv);
2454 return reg;2450 return reg;
2455}2451}
...@@ -2464,7 +2460,8 @@ fn copyToRegisterWithInstTracking(...@@ -2464,7 +2460,8 @@ fn copyToRegisterWithInstTracking(
2464 ty: Type,2460 ty: Type,
2465 mcv: MCValue,2461 mcv: MCValue,
2466) !MCValue {2462) !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));
2468 try self.genSetReg(reg, ty, mcv);2465 try self.genSetReg(reg, ty, mcv);
2469 return MCValue{ .register = reg };2466 return MCValue{ .register = reg };
2470}2467}
...@@ -2481,7 +2478,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2481,7 +2478,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
2481 .load_frame => .{ .register_offset = .{2478 .load_frame => .{ .register_offset = .{
2482 .reg = (try self.copyToRegisterWithInstTracking(2479 .reg = (try self.copyToRegisterWithInstTracking(
2483 inst,2480 inst,
2484 self.air.typeOfIndex(inst),2481 self.typeOfIndex(inst),
2485 self.ret_mcv.long,2482 self.ret_mcv.long,
2486 )).register,2483 )).register,
2487 .off = self.ret_mcv.short.indirect.off,2484 .off = self.ret_mcv.short.indirect.off,
...@@ -2492,9 +2489,9 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2492,9 +2489,9 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
24922489
2493fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {2490fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
2494 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2491 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);
2496 const dst_bits = dst_ty.floatBits(self.target.*);2493 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);
2498 const src_bits = src_ty.floatBits(self.target.*);2495 const src_bits = src_ty.floatBits(self.target.*);
24992496
2500 const src_mcv = try self.resolveInst(ty_op.operand);2497 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -2558,9 +2555,9 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2558,9 +2555,9 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
25582555
2559fn airFpext(self: *Self, inst: Air.Inst.Index) !void {2556fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
2560 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2557 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);
2562 const dst_bits = dst_ty.floatBits(self.target.*);2559 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);
2564 const src_bits = src_ty.floatBits(self.target.*);2561 const src_bits = src_ty.floatBits(self.target.*);
25652562
2566 const src_mcv = try self.resolveInst(ty_op.operand);2563 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -2618,14 +2615,15 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {...@@ -2618,14 +2615,15 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
2618}2615}
26192616
2620fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {2617fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
2618 const mod = self.bin_file.options.module.?;
2621 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2619 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2622 const result: MCValue = result: {2620 const result: MCValue = result: {
2623 const src_ty = self.air.typeOf(ty_op.operand);2621 const src_ty = self.typeOf(ty_op.operand);
2624 const src_int_info = src_ty.intInfo(self.target.*);2622 const src_int_info = src_ty.intInfo(mod);
26252623
2626 const dst_ty = self.air.typeOfIndex(inst);2624 const dst_ty = self.typeOfIndex(inst);
2627 const dst_int_info = dst_ty.intInfo(self.target.*);2625 const dst_int_info = dst_ty.intInfo(mod);
2628 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));2626 const abi_size = @intCast(u32, dst_ty.abiSize(mod));
26292627
2630 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;2628 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;
2631 const extend = switch (src_int_info.signedness) {2629 const extend = switch (src_int_info.signedness) {
...@@ -2670,14 +2668,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -2670,14 +2668,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
26702668
2671 const high_bits = src_int_info.bits % 64;2669 const high_bits = src_int_info.bits % 64;
2672 if (high_bits > 0) {2670 if (high_bits > 0) {
2673 var high_pl = Type.Payload.Bits{2671 const high_ty = try mod.intType(extend, high_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);
2681 try self.truncateRegister(high_ty, high_reg);2672 try self.truncateRegister(high_ty, high_reg);
2682 try self.genCopy(Type.usize, high_mcv, .{ .register = high_reg });2673 try self.genCopy(Type.usize, high_mcv, .{ .register = high_reg });
2683 }2674 }
...@@ -2706,12 +2697,13 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -2706,12 +2697,13 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
2706}2697}
27072698
2708fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {2699fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2700 const mod = self.bin_file.options.module.?;
2709 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2701 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
27102702
2711 const dst_ty = self.air.typeOfIndex(inst);2703 const dst_ty = self.typeOfIndex(inst);
2712 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));2704 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
2713 const src_ty = self.air.typeOf(ty_op.operand);2705 const src_ty = self.typeOf(ty_op.operand);
2714 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));2706 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
27152707
2716 const result = result: {2708 const result = result: {
2717 const src_mcv = try self.resolveInst(ty_op.operand);2709 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -2724,13 +2716,13 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2724,13 +2716,13 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2724 else2716 else
2725 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);2717 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
27262718
2727 if (dst_ty.zigTypeTag() == .Vector) {2719 if (dst_ty.zigTypeTag(mod) == .Vector) {
2728 assert(src_ty.zigTypeTag() == .Vector and dst_ty.vectorLen() == src_ty.vectorLen());2720 assert(src_ty.zigTypeTag(mod) == .Vector and dst_ty.vectorLen(mod) == src_ty.vectorLen(mod));
2729 const dst_info = dst_ty.childType().intInfo(self.target.*);2721 const dst_info = dst_ty.childType(mod).intInfo(mod);
2730 const src_info = src_ty.childType().intInfo(self.target.*);2722 const src_info = src_ty.childType(mod).intInfo(mod);
2731 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_info.bits) {2723 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_info.bits) {
2732 8 => switch (src_info.bits) {2724 8 => switch (src_info.bits) {
2733 16 => switch (dst_ty.vectorLen()) {2725 16 => switch (dst_ty.vectorLen(mod)) {
2734 1...8 => if (self.hasFeature(.avx)) .{ .vp_b, .ackusw } else .{ .p_b, .ackusw },2726 1...8 => if (self.hasFeature(.avx)) .{ .vp_b, .ackusw } else .{ .p_b, .ackusw },
2735 9...16 => if (self.hasFeature(.avx2)) .{ .vp_b, .ackusw } else null,2727 9...16 => if (self.hasFeature(.avx2)) .{ .vp_b, .ackusw } else null,
2736 else => null,2728 else => null,
...@@ -2738,7 +2730,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2738,7 +2730,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2738 else => null,2730 else => null,
2739 },2731 },
2740 16 => switch (src_info.bits) {2732 16 => switch (src_info.bits) {
2741 32 => switch (dst_ty.vectorLen()) {2733 32 => switch (dst_ty.vectorLen(mod)) {
2742 1...4 => if (self.hasFeature(.avx))2734 1...4 => if (self.hasFeature(.avx))
2743 .{ .vp_w, .ackusd }2735 .{ .vp_w, .ackusd }
2744 else if (self.hasFeature(.sse4_1))2736 else if (self.hasFeature(.sse4_1))
...@@ -2755,29 +2747,21 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2755,29 +2747,21 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2755 dst_ty.fmt(self.bin_file.options.module.?),2747 dst_ty.fmt(self.bin_file.options.module.?),
2756 });2748 });
27572749
2758 var mask_pl = Value.Payload.U64{2750 const elem_ty = src_ty.childType(mod);
2759 .base = .{ .tag = .int_u64 },2751 const mask_val = try mod.intValue(elem_ty, @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - dst_info.bits));
2760 .data = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - dst_info.bits),
2761 };
2762 const mask_val = Value.initPayload(&mask_pl.base);
27632752
2764 var splat_pl = Value.Payload.SubValue{2753 const splat_ty = try mod.vectorType(.{
2765 .base = .{ .tag = .repeated },2754 .len = @intCast(u32, @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),
2766 .data = mask_val,2755 .child = elem_ty.ip_index,
2767 };2756 });
2768 const splat_val = Value.initPayload(&splat_pl.base);2757 const splat_abi_size = @intCast(u32, splat_ty.abiSize(mod));
27692758
2770 var full_pl = Type.Payload.Array{2759 const splat_val = try mod.intern(.{ .aggregate = .{
2771 .base = .{ .tag = .vector },2760 .ty = splat_ty.ip_index,
2772 .data = .{2761 .storage = .{ .repeated_elem = mask_val.ip_index },
2773 .len = @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits),2762 } });
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.*));
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() });
2781 const splat_addr_mcv: MCValue = switch (splat_mcv) {2765 const splat_addr_mcv: MCValue = switch (splat_mcv) {
2782 .memory, .indirect, .load_frame => splat_mcv.address(),2766 .memory, .indirect, .load_frame => splat_mcv.address(),
2783 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },2767 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },
...@@ -2789,14 +2773,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2789,14 +2773,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2789 .{ .vp_, .@"and" },2773 .{ .vp_, .@"and" },
2790 dst_reg,2774 dst_reg,
2791 dst_reg,2775 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)),
2793 );2777 );
2794 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);2778 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);
2795 } else {2779 } else {
2796 try self.asmRegisterMemory(2780 try self.asmRegisterMemory(
2797 .{ .p_, .@"and" },2781 .{ .p_, .@"and" },
2798 dst_reg,2782 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)),
2800 );2784 );
2801 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);2785 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);
2802 }2786 }
...@@ -2819,7 +2803,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2819,7 +2803,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
28192803
2820fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {2804fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
2821 const un_op = self.air.instructions.items(.data)[inst].un_op;2805 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
2824 const operand = try self.resolveInst(un_op);2808 const operand = try self.resolveInst(un_op);
2825 const dst_mcv = if (self.reuseOperand(inst, un_op, 0, operand))2809 const dst_mcv = if (self.reuseOperand(inst, un_op, 0, operand))
...@@ -2831,20 +2815,21 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -2831,20 +2815,21 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
2831}2815}
28322816
2833fn airSlice(self: *Self, inst: Air.Inst.Index) !void {2817fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
2818 const mod = self.bin_file.options.module.?;
2834 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2819 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2835 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2820 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);
2838 const ptr = try self.resolveInst(bin_op.lhs);2823 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);
2840 const len = try self.resolveInst(bin_op.rhs);2825 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));
2844 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);2829 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
2845 try self.genSetMem(2830 try self.genSetMem(
2846 .{ .frame = frame_index },2831 .{ .frame = frame_index },
2847 @intCast(i32, ptr_ty.abiSize(self.target.*)),2832 @intCast(i32, ptr_ty.abiSize(mod)),
2848 len_ty,2833 len_ty,
2849 len,2834 len,
2850 );2835 );
...@@ -2873,23 +2858,24 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void...@@ -2873,23 +2858,24 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
2873}2858}
28742859
2875fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {2860fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
2861 const mod = self.bin_file.options.module.?;
2876 const air_tag = self.air.instructions.items(.tag);2862 const air_tag = self.air.instructions.items(.tag);
2877 const air_data = self.air.instructions.items(.data);2863 const air_data = self.air.instructions.items(.data);
28782864
2879 const dst_ty = self.air.typeOf(dst_air);2865 const dst_ty = self.typeOf(dst_air);
2880 const dst_info = dst_ty.intInfo(self.target.*);2866 const dst_info = dst_ty.intInfo(mod);
2881 if (Air.refToIndex(dst_air)) |inst| {2867 if (Air.refToIndex(dst_air)) |inst| {
2882 switch (air_tag[inst]) {2868 switch (air_tag[inst]) {
2883 .constant => {2869 .interned => {
2884 const src_val = self.air.values[air_data[inst].ty_pl.payload];2870 const src_val = air_data[inst].interned.toValue();
2885 var space: Value.BigIntSpace = undefined;2871 var space: Value.BigIntSpace = undefined;
2886 const src_int = src_val.toBigInt(&space, self.target.*);2872 const src_int = src_val.toBigInt(&space, mod);
2887 return @intCast(u16, src_int.bitCountTwosComp()) +2873 return @intCast(u16, src_int.bitCountTwosComp()) +
2888 @boolToInt(src_int.positive and dst_info.signedness == .signed);2874 @boolToInt(src_int.positive and dst_info.signedness == .signed);
2889 },2875 },
2890 .intcast => {2876 .intcast => {
2891 const src_ty = self.air.typeOf(air_data[inst].ty_op.operand);2877 const src_ty = self.typeOf(air_data[inst].ty_op.operand);
2892 const src_info = src_ty.intInfo(self.target.*);2878 const src_info = src_ty.intInfo(mod);
2893 return @min(switch (src_info.signedness) {2879 return @min(switch (src_info.signedness) {
2894 .signed => switch (dst_info.signedness) {2880 .signed => switch (dst_info.signedness) {
2895 .signed => src_info.bits,2881 .signed => src_info.bits,
...@@ -2908,20 +2894,18 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {...@@ -2908,20 +2894,18 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
2908}2894}
29092895
2910fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {2896fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
2897 const mod = self.bin_file.options.module.?;
2911 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2898 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2912 const result = result: {2899 const result = result: {
2913 const tag = self.air.instructions.items(.tag)[inst];2900 const tag = self.air.instructions.items(.tag)[inst];
2914 const dst_ty = self.air.typeOfIndex(inst);2901 const dst_ty = self.typeOfIndex(inst);
2915 switch (dst_ty.zigTypeTag()) {2902 switch (dst_ty.zigTypeTag(mod)) {
2916 .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs),2903 .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs),
2917 else => {},2904 else => {},
2918 }2905 }
29192906
2920 const dst_info = dst_ty.intInfo(self.target.*);2907 const dst_info = dst_ty.intInfo(mod);
2921 var src_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dst_info.signedness) {2908 const src_ty = try mod.intType(dst_info.signedness, switch (tag) {
2922 .signed => .int_signed,
2923 .unsigned => .int_unsigned,
2924 } }, .data = switch (tag) {
2925 else => unreachable,2909 else => unreachable,
2926 .mul, .mulwrap => math.max3(2910 .mul, .mulwrap => math.max3(
2927 self.activeIntBits(bin_op.lhs),2911 self.activeIntBits(bin_op.lhs),
...@@ -2929,8 +2913,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -2929,8 +2913,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
2929 dst_info.bits / 2,2913 dst_info.bits / 2,
2930 ),2914 ),
2931 .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_info.bits,2915 .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_info.bits,
2932 } };2916 });
2933 const src_ty = Type.initPayload(&src_pl.base);
29342917
2935 try self.spillEflagsIfOccupied();2918 try self.spillEflagsIfOccupied();
2936 try self.spillRegisters(&.{ .rax, .rdx });2919 try self.spillRegisters(&.{ .rax, .rdx });
...@@ -2942,8 +2925,9 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -2942,8 +2925,9 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
2942}2925}
29432926
2944fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {2927fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
2928 const mod = self.bin_file.options.module.?;
2945 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2929 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
2948 const lhs_mcv = try self.resolveInst(bin_op.lhs);2932 const lhs_mcv = try self.resolveInst(bin_op.lhs);
2949 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))2933 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 {...@@ -2968,7 +2952,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
29682952
2969 const reg_bits = self.regBitSize(ty);2953 const reg_bits = self.regBitSize(ty);
2970 const reg_extra_bits = self.regExtraBits(ty);2954 const reg_extra_bits = self.regExtraBits(ty);
2971 const cc: Condition = if (ty.isSignedInt()) cc: {2955 const cc: Condition = if (ty.isSignedInt(mod)) cc: {
2972 if (reg_extra_bits > 0) {2956 if (reg_extra_bits > 0) {
2973 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });2957 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
2974 }2958 }
...@@ -2994,7 +2978,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -2994,7 +2978,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
2994 break :cc .o;2978 break :cc .o;
2995 } else cc: {2979 } else cc: {
2996 try self.genSetReg(limit_reg, ty, .{2980 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)),
2998 });2982 });
29992983
3000 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);2984 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);
...@@ -3005,14 +2989,14 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3005,14 +2989,14 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
3005 break :cc .c;2989 break :cc .c;
3006 };2990 };
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);
3009 try self.asmCmovccRegisterRegister(2993 try self.asmCmovccRegisterRegister(
3010 registerAlias(dst_reg, cmov_abi_size),2994 registerAlias(dst_reg, cmov_abi_size),
3011 registerAlias(limit_reg, cmov_abi_size),2995 registerAlias(limit_reg, cmov_abi_size),
3012 cc,2996 cc,
3013 );2997 );
30142998
3015 if (reg_extra_bits > 0 and ty.isSignedInt()) {2999 if (reg_extra_bits > 0 and ty.isSignedInt(mod)) {
3016 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });3000 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
3017 }3001 }
30183002
...@@ -3020,8 +3004,9 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3020,8 +3004,9 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
3020}3004}
30213005
3022fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {3006fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
3007 const mod = self.bin_file.options.module.?;
3023 const bin_op = self.air.instructions.items(.data)[inst].bin_op;3008 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
3026 const lhs_mcv = try self.resolveInst(bin_op.lhs);3011 const lhs_mcv = try self.resolveInst(bin_op.lhs);
3027 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))3012 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 {...@@ -3046,7 +3031,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
30463031
3047 const reg_bits = self.regBitSize(ty);3032 const reg_bits = self.regBitSize(ty);
3048 const reg_extra_bits = self.regExtraBits(ty);3033 const reg_extra_bits = self.regExtraBits(ty);
3049 const cc: Condition = if (ty.isSignedInt()) cc: {3034 const cc: Condition = if (ty.isSignedInt(mod)) cc: {
3050 if (reg_extra_bits > 0) {3035 if (reg_extra_bits > 0) {
3051 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });3036 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
3052 }3037 }
...@@ -3076,14 +3061,14 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3076,14 +3061,14 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
3076 break :cc .c;3061 break :cc .c;
3077 };3062 };
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);
3080 try self.asmCmovccRegisterRegister(3065 try self.asmCmovccRegisterRegister(
3081 registerAlias(dst_reg, cmov_abi_size),3066 registerAlias(dst_reg, cmov_abi_size),
3082 registerAlias(limit_reg, cmov_abi_size),3067 registerAlias(limit_reg, cmov_abi_size),
3083 cc,3068 cc,
3084 );3069 );
30853070
3086 if (reg_extra_bits > 0 and ty.isSignedInt()) {3071 if (reg_extra_bits > 0 and ty.isSignedInt(mod)) {
3087 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });3072 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
3088 }3073 }
30893074
...@@ -3091,8 +3076,9 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3091,8 +3076,9 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
3091}3076}
30923077
3093fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {3078fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
3079 const mod = self.bin_file.options.module.?;
3094 const bin_op = self.air.instructions.items(.data)[inst].bin_op;3080 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
3097 try self.spillRegisters(&.{ .rax, .rdx });3083 try self.spillRegisters(&.{ .rax, .rdx });
3098 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });3084 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });
...@@ -3118,7 +3104,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3118,7 +3104,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
3118 defer self.register_manager.unlockReg(limit_lock);3104 defer self.register_manager.unlockReg(limit_lock);
31193105
3120 const reg_bits = self.regBitSize(ty);3106 const reg_bits = self.regBitSize(ty);
3121 const cc: Condition = if (ty.isSignedInt()) cc: {3107 const cc: Condition = if (ty.isSignedInt(mod)) cc: {
3122 try self.genSetReg(limit_reg, ty, lhs_mcv);3108 try self.genSetReg(limit_reg, ty, lhs_mcv);
3123 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);3109 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);
3124 try self.genShiftBinOpMir(.{ ._, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });3110 try self.genShiftBinOpMir(.{ ._, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
...@@ -3134,7 +3120,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3134,7 +3120,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
3134 };3120 };
31353121
3136 const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv);3122 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);
3138 try self.asmCmovccRegisterRegister(3124 try self.asmCmovccRegisterRegister(
3139 registerAlias(dst_mcv.register, cmov_abi_size),3125 registerAlias(dst_mcv.register, cmov_abi_size),
3140 registerAlias(limit_reg, cmov_abi_size),3126 registerAlias(limit_reg, cmov_abi_size),
...@@ -3145,12 +3131,13 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3145,12 +3131,13 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
3145}3131}
31463132
3147fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {3133fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3134 const mod = self.bin_file.options.module.?;
3148 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;3135 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3149 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;3136 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3150 const result: MCValue = result: {3137 const result: MCValue = result: {
3151 const tag = self.air.instructions.items(.tag)[inst];3138 const tag = self.air.instructions.items(.tag)[inst];
3152 const ty = self.air.typeOf(bin_op.lhs);3139 const ty = self.typeOf(bin_op.lhs);
3153 switch (ty.zigTypeTag()) {3140 switch (ty.zigTypeTag(mod)) {
3154 .Vector => return self.fail("TODO implement add/sub with overflow for Vector type", .{}),3141 .Vector => return self.fail("TODO implement add/sub with overflow for Vector type", .{}),
3155 .Int => {3142 .Int => {
3156 try self.spillEflagsIfOccupied();3143 try self.spillEflagsIfOccupied();
...@@ -3160,13 +3147,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3160,13 +3147,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3160 .sub_with_overflow => .sub,3147 .sub_with_overflow => .sub,
3161 else => unreachable,3148 else => unreachable,
3162 }, bin_op.lhs, bin_op.rhs);3149 }, bin_op.lhs, bin_op.rhs);
3163 const int_info = ty.intInfo(self.target.*);3150 const int_info = ty.intInfo(mod);
3164 const cc: Condition = switch (int_info.signedness) {3151 const cc: Condition = switch (int_info.signedness) {
3165 .unsigned => .c,3152 .unsigned => .c,
3166 .signed => .o,3153 .signed => .o,
3167 };3154 };
31683155
3169 const tuple_ty = self.air.typeOfIndex(inst);3156 const tuple_ty = self.typeOfIndex(inst);
3170 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {3157 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
3171 switch (partial_mcv) {3158 switch (partial_mcv) {
3172 .register => |reg| {3159 .register => |reg| {
...@@ -3177,16 +3164,16 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3177,16 +3164,16 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3177 }3164 }
31783165
3179 const frame_index =3166 const frame_index =
3180 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));3167 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3181 try self.genSetMem(3168 try self.genSetMem(
3182 .{ .frame = frame_index },3169 .{ .frame = frame_index },
3183 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),3170 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3184 Type.u1,3171 Type.u1,
3185 .{ .eflags = cc },3172 .{ .eflags = cc },
3186 );3173 );
3187 try self.genSetMem(3174 try self.genSetMem(
3188 .{ .frame = frame_index },3175 .{ .frame = frame_index },
3189 @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)),3176 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3190 ty,3177 ty,
3191 partial_mcv,3178 partial_mcv,
3192 );3179 );
...@@ -3194,7 +3181,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3194,7 +3181,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3194 }3181 }
31953182
3196 const frame_index =3183 const frame_index =
3197 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));3184 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3198 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);3185 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
3199 break :result .{ .load_frame = .{ .index = frame_index } };3186 break :result .{ .load_frame = .{ .index = frame_index } };
3200 },3187 },
...@@ -3205,12 +3192,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3205,12 +3192,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3205}3192}
32063193
3207fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {3194fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3195 const mod = self.bin_file.options.module.?;
3208 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;3196 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3209 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;3197 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3210 const result: MCValue = result: {3198 const result: MCValue = result: {
3211 const lhs_ty = self.air.typeOf(bin_op.lhs);3199 const lhs_ty = self.typeOf(bin_op.lhs);
3212 const rhs_ty = self.air.typeOf(bin_op.rhs);3200 const rhs_ty = self.typeOf(bin_op.rhs);
3213 switch (lhs_ty.zigTypeTag()) {3201 switch (lhs_ty.zigTypeTag(mod)) {
3214 .Vector => return self.fail("TODO implement shl with overflow for Vector type", .{}),3202 .Vector => return self.fail("TODO implement shl with overflow for Vector type", .{}),
3215 .Int => {3203 .Int => {
3216 try self.spillEflagsIfOccupied();3204 try self.spillEflagsIfOccupied();
...@@ -3219,7 +3207,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3219,7 +3207,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3219 const lhs = try self.resolveInst(bin_op.lhs);3207 const lhs = try self.resolveInst(bin_op.lhs);
3220 const rhs = try self.resolveInst(bin_op.rhs);3208 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
3224 const partial_mcv = try self.genShiftBinOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty);3212 const partial_mcv = try self.genShiftBinOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty);
3225 const partial_lock = switch (partial_mcv) {3213 const partial_lock = switch (partial_mcv) {
...@@ -3238,7 +3226,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3238,7 +3226,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3238 try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, tmp_mcv, lhs);3226 try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, tmp_mcv, lhs);
3239 const cc = Condition.ne;3227 const cc = Condition.ne;
32403228
3241 const tuple_ty = self.air.typeOfIndex(inst);3229 const tuple_ty = self.typeOfIndex(inst);
3242 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {3230 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
3243 switch (partial_mcv) {3231 switch (partial_mcv) {
3244 .register => |reg| {3232 .register => |reg| {
...@@ -3249,24 +3237,24 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3249,24 +3237,24 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3249 }3237 }
32503238
3251 const frame_index =3239 const frame_index =
3252 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));3240 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3253 try self.genSetMem(3241 try self.genSetMem(
3254 .{ .frame = frame_index },3242 .{ .frame = frame_index },
3255 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),3243 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3256 tuple_ty.structFieldType(1),3244 tuple_ty.structFieldType(1, mod),
3257 .{ .eflags = cc },3245 .{ .eflags = cc },
3258 );3246 );
3259 try self.genSetMem(3247 try self.genSetMem(
3260 .{ .frame = frame_index },3248 .{ .frame = frame_index },
3261 @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)),3249 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3262 tuple_ty.structFieldType(0),3250 tuple_ty.structFieldType(0, mod),
3263 partial_mcv,3251 partial_mcv,
3264 );3252 );
3265 break :result .{ .load_frame = .{ .index = frame_index } };3253 break :result .{ .load_frame = .{ .index = frame_index } };
3266 }3254 }
32673255
3268 const frame_index =3256 const frame_index =
3269 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));3257 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3270 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);3258 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
3271 break :result .{ .load_frame = .{ .index = frame_index } };3259 break :result .{ .load_frame = .{ .index = frame_index } };
3272 },3260 },
...@@ -3283,29 +3271,20 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3283,29 +3271,20 @@ fn genSetFrameTruncatedOverflowCompare(
3283 src_mcv: MCValue,3271 src_mcv: MCValue,
3284 overflow_cc: ?Condition,3272 overflow_cc: ?Condition,
3285) !void {3273) !void {
3274 const mod = self.bin_file.options.module.?;
3286 const src_lock = switch (src_mcv) {3275 const src_lock = switch (src_mcv) {
3287 .register => |reg| self.register_manager.lockReg(reg),3276 .register => |reg| self.register_manager.lockReg(reg),
3288 else => null,3277 else => null,
3289 };3278 };
3290 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);3279 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
32913280
3292 const ty = tuple_ty.structFieldType(0);3281 const ty = tuple_ty.structFieldType(0, mod);
3293 const int_info = ty.intInfo(self.target.*);3282 const int_info = ty.intInfo(mod);
32943283
3295 var hi_limb_pl = Type.Payload.Bits{3284 const hi_limb_bits = (int_info.bits - 1) % 64 + 1;
3296 .base = .{ .tag = switch (int_info.signedness) {3285 const hi_limb_ty = try mod.intType(int_info.signedness, hi_limb_bits);
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);
33033286
3304 var rest_pl = Type.Payload.Bits{3287 const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_limb_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);
33093288
3310 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, gp);3289 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, gp);
3311 const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);3290 const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);
...@@ -3335,7 +3314,7 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3335,7 +3314,7 @@ fn genSetFrameTruncatedOverflowCompare(
3335 );3314 );
3336 }3315 }
33373316
3338 const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*));3317 const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, mod));
3339 if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv);3318 if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv);
3340 try self.genSetMem(3319 try self.genSetMem(
3341 .{ .frame = frame_index },3320 .{ .frame = frame_index },
...@@ -3345,23 +3324,24 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3345,23 +3324,24 @@ fn genSetFrameTruncatedOverflowCompare(
3345 );3324 );
3346 try self.genSetMem(3325 try self.genSetMem(
3347 .{ .frame = frame_index },3326 .{ .frame = frame_index },
3348 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),3327 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3349 tuple_ty.structFieldType(1),3328 tuple_ty.structFieldType(1, mod),
3350 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },3329 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },
3351 );3330 );
3352}3331}
33533332
3354fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {3333fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3334 const mod = self.bin_file.options.module.?;
3355 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;3335 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3356 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;3336 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3357 const dst_ty = self.air.typeOf(bin_op.lhs);3337 const dst_ty = self.typeOf(bin_op.lhs);
3358 const result: MCValue = switch (dst_ty.zigTypeTag()) {3338 const result: MCValue = switch (dst_ty.zigTypeTag(mod)) {
3359 .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}),3339 .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}),
3360 .Int => result: {3340 .Int => result: {
3361 try self.spillEflagsIfOccupied();3341 try self.spillEflagsIfOccupied();
3362 try self.spillRegisters(&.{ .rax, .rdx });3342 try self.spillRegisters(&.{ .rax, .rdx });
33633343
3364 const dst_info = dst_ty.intInfo(self.target.*);3344 const dst_info = dst_ty.intInfo(mod);
3365 const cc: Condition = switch (dst_info.signedness) {3345 const cc: Condition = switch (dst_info.signedness) {
3366 .unsigned => .c,3346 .unsigned => .c,
3367 .signed => .o,3347 .signed => .o,
...@@ -3369,16 +3349,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3369,16 +3349,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
33693349
3370 const lhs_active_bits = self.activeIntBits(bin_op.lhs);3350 const lhs_active_bits = self.activeIntBits(bin_op.lhs);
3371 const rhs_active_bits = self.activeIntBits(bin_op.rhs);3351 const rhs_active_bits = self.activeIntBits(bin_op.rhs);
3372 var src_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dst_info.signedness) {3352 const src_bits = math.max3(lhs_active_bits, rhs_active_bits, dst_info.bits / 2);
3373 .signed => .int_signed,3353 const src_ty = try mod.intType(dst_info.signedness, src_bits);
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);
33773354
3378 const lhs = try self.resolveInst(bin_op.lhs);3355 const lhs = try self.resolveInst(bin_op.lhs);
3379 const rhs = try self.resolveInst(bin_op.rhs);3356 const rhs = try self.resolveInst(bin_op.rhs);
33803357
3381 const tuple_ty = self.air.typeOfIndex(inst);3358 const tuple_ty = self.typeOfIndex(inst);
3382 const extra_bits = if (dst_info.bits <= 64)3359 const extra_bits = if (dst_info.bits <= 64)
3383 self.regExtraBits(dst_ty)3360 self.regExtraBits(dst_ty)
3384 else3361 else
...@@ -3391,27 +3368,27 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3391,27 +3368,27 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3391 break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } };3368 break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } };
3392 } else {3369 } else {
3393 const frame_index =3370 const frame_index =
3394 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));3371 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3395 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);3372 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
3396 break :result .{ .load_frame = .{ .index = frame_index } };3373 break :result .{ .load_frame = .{ .index = frame_index } };
3397 },3374 },
3398 else => {3375 else => {
3399 // For now, this is the only supported multiply that doesn't fit in a register.3376 // 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
3402 const frame_index =3379 const frame_index =
3403 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));3380 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3404 if (dst_info.bits >= lhs_active_bits + rhs_active_bits) {3381 if (dst_info.bits >= lhs_active_bits + rhs_active_bits) {
3405 try self.genSetMem(3382 try self.genSetMem(
3406 .{ .frame = frame_index },3383 .{ .frame = frame_index },
3407 @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)),3384 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3408 tuple_ty.structFieldType(0),3385 tuple_ty.structFieldType(0, mod),
3409 partial_mcv,3386 partial_mcv,
3410 );3387 );
3411 try self.genSetMem(3388 try self.genSetMem(
3412 .{ .frame = frame_index },3389 .{ .frame = frame_index },
3413 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),3390 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3414 tuple_ty.structFieldType(1),3391 tuple_ty.structFieldType(1, mod),
3415 .{ .immediate = 0 }, // cc being set is impossible3392 .{ .immediate = 0 }, // cc being set is impossible
3416 );3393 );
3417 } else try self.genSetFrameTruncatedOverflowCompare(3394 } else try self.genSetFrameTruncatedOverflowCompare(
...@@ -3433,7 +3410,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3433,7 +3410,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3433/// Clobbers .rax and .rdx registers.3410/// Clobbers .rax and .rdx registers.
3434/// Quotient is saved in .rax and remainder in .rdx.3411/// Quotient is saved in .rax and remainder in .rdx.
3435fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void {3412fn 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));
3437 if (abi_size > 8) {3415 if (abi_size > 8) {
3438 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});3416 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});
3439 }3417 }
...@@ -3472,8 +3450,9 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue...@@ -3472,8 +3450,9 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue
3472/// Always returns a register.3450/// Always returns a register.
3473/// Clobbers .rax and .rdx registers.3451/// Clobbers .rax and .rdx registers.
3474fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue {3452fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue {
3475 const abi_size = @intCast(u32, ty.abiSize(self.target.*));3453 const mod = self.bin_file.options.module.?;
3476 const int_info = ty.intInfo(self.target.*);3454 const abi_size = @intCast(u32, ty.abiSize(mod));
3455 const int_info = ty.intInfo(mod);
3477 const dividend: Register = switch (lhs) {3456 const dividend: Register = switch (lhs) {
3478 .register => |reg| reg,3457 .register => |reg| reg,
3479 else => try self.copyToTmpRegister(ty, lhs),3458 else => try self.copyToTmpRegister(ty, lhs),
...@@ -3531,8 +3510,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -3531,8 +3510,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
3531 try self.register_manager.getReg(.rcx, null);3510 try self.register_manager.getReg(.rcx, null);
3532 const lhs = try self.resolveInst(bin_op.lhs);3511 const lhs = try self.resolveInst(bin_op.lhs);
3533 const rhs = try self.resolveInst(bin_op.rhs);3512 const rhs = try self.resolveInst(bin_op.rhs);
3534 const lhs_ty = self.air.typeOf(bin_op.lhs);3513 const lhs_ty = self.typeOf(bin_op.lhs);
3535 const rhs_ty = self.air.typeOf(bin_op.rhs);3514 const rhs_ty = self.typeOf(bin_op.rhs);
35363515
3537 const result = try self.genShiftBinOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);3516 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 {...@@ -3549,7 +3528,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
3549fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {3528fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
3550 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3529 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3551 const result: MCValue = result: {3530 const result: MCValue = result: {
3552 const pl_ty = self.air.typeOfIndex(inst);3531 const pl_ty = self.typeOfIndex(inst);
3553 const opt_mcv = try self.resolveInst(ty_op.operand);3532 const opt_mcv = try self.resolveInst(ty_op.operand);
35543533
3555 if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) {3534 if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) {
...@@ -3574,7 +3553,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -3574,7 +3553,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
3574fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {3553fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3575 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3554 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);
3578 const opt_mcv = try self.resolveInst(ty_op.operand);3557 const opt_mcv = try self.resolveInst(ty_op.operand);
35793558
3580 const dst_mcv = if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))3559 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 {...@@ -3585,14 +3564,15 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3585}3564}
35863565
3587fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {3566fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3567 const mod = self.bin_file.options.module.?;
3588 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3568 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3589 const result = result: {3569 const result = result: {
3590 const dst_ty = self.air.typeOfIndex(inst);3570 const dst_ty = self.typeOfIndex(inst);
3591 const src_ty = self.air.typeOf(ty_op.operand);3571 const src_ty = self.typeOf(ty_op.operand);
3592 const opt_ty = src_ty.childType();3572 const opt_ty = src_ty.childType(mod);
3593 const src_mcv = try self.resolveInst(ty_op.operand);3573 const src_mcv = try self.resolveInst(ty_op.operand);
35943574
3595 if (opt_ty.optionalReprIsPayload()) {3575 if (opt_ty.optionalReprIsPayload(mod)) {
3596 break :result if (self.liveness.isUnused(inst))3576 break :result if (self.liveness.isUnused(inst))
3597 .unreach3577 .unreach
3598 else if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))3578 else if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
...@@ -3609,8 +3589,8 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3609,8 +3589,8 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3609 else3589 else
3610 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);3590 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
36113591
3612 const pl_ty = dst_ty.childType();3592 const pl_ty = dst_ty.childType(mod);
3613 const pl_abi_size = @intCast(i32, pl_ty.abiSize(self.target.*));3593 const pl_abi_size = @intCast(i32, pl_ty.abiSize(mod));
3614 try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 });3594 try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 });
3615 break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv;3595 break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv;
3616 };3596 };
...@@ -3618,22 +3598,23 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3618,22 +3598,23 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3618}3598}
36193599
3620fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {3600fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
3601 const mod = self.bin_file.options.module.?;
3621 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3602 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3622 const err_union_ty = self.air.typeOf(ty_op.operand);3603 const err_union_ty = self.typeOf(ty_op.operand);
3623 const err_ty = err_union_ty.errorUnionSet();3604 const err_ty = err_union_ty.errorUnionSet(mod);
3624 const payload_ty = err_union_ty.errorUnionPayload();3605 const payload_ty = err_union_ty.errorUnionPayload(mod);
3625 const operand = try self.resolveInst(ty_op.operand);3606 const operand = try self.resolveInst(ty_op.operand);
36263607
3627 const result: MCValue = result: {3608 const result: MCValue = result: {
3628 if (err_ty.errorSetIsEmpty()) {3609 if (err_ty.errorSetIsEmpty(mod)) {
3629 break :result MCValue{ .immediate = 0 };3610 break :result MCValue{ .immediate = 0 };
3630 }3611 }
36313612
3632 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3613 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3633 break :result operand;3614 break :result operand;
3634 }3615 }
36353616
3636 const err_off = errUnionErrorOffset(payload_ty, self.target.*);3617 const err_off = errUnionErrorOffset(payload_ty, mod);
3637 switch (operand) {3618 switch (operand) {
3638 .register => |reg| {3619 .register => |reg| {
3639 // TODO reuse operand3620 // TODO reuse operand
...@@ -3666,7 +3647,7 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3666,7 +3647,7 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
36663647
3667fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {3648fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
3668 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3649 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);
3670 const operand = try self.resolveInst(ty_op.operand);3651 const operand = try self.resolveInst(ty_op.operand);
3671 const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, operand);3652 const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, operand);
3672 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3653 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -3678,12 +3659,13 @@ fn genUnwrapErrorUnionPayloadMir(...@@ -3678,12 +3659,13 @@ fn genUnwrapErrorUnionPayloadMir(
3678 err_union_ty: Type,3659 err_union_ty: Type,
3679 err_union: MCValue,3660 err_union: MCValue,
3680) !MCValue {3661) !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
3683 const result: MCValue = result: {3665 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);
3687 switch (err_union) {3669 switch (err_union) {
3688 .load_frame => |frame_addr| break :result .{ .load_frame = .{3670 .load_frame => |frame_addr| break :result .{ .load_frame = .{
3689 .index = frame_addr.index,3671 .index = frame_addr.index,
...@@ -3720,9 +3702,10 @@ fn genUnwrapErrorUnionPayloadMir(...@@ -3720,9 +3702,10 @@ fn genUnwrapErrorUnionPayloadMir(
37203702
3721// *(E!T) -> E3703// *(E!T) -> E
3722fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {3704fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
3705 const mod = self.bin_file.options.module.?;
3723 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3706 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);
3726 const src_mcv = try self.resolveInst(ty_op.operand);3709 const src_mcv = try self.resolveInst(ty_op.operand);
3727 const src_reg = switch (src_mcv) {3710 const src_reg = switch (src_mcv) {
3728 .register => |reg| reg,3711 .register => |reg| reg,
...@@ -3736,11 +3719,11 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3736,11 +3719,11 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
3736 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);3719 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
3737 defer self.register_manager.unlockReg(dst_lock);3720 defer self.register_manager.unlockReg(dst_lock);
37383721
3739 const eu_ty = src_ty.childType();3722 const eu_ty = src_ty.childType(mod);
3740 const pl_ty = eu_ty.errorUnionPayload();3723 const pl_ty = eu_ty.errorUnionPayload(mod);
3741 const err_ty = eu_ty.errorUnionSet();3724 const err_ty = eu_ty.errorUnionSet(mod);
3742 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));3725 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
3743 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));3726 const err_abi_size = @intCast(u32, err_ty.abiSize(mod));
3744 try self.asmRegisterMemory(3727 try self.asmRegisterMemory(
3745 .{ ._, .mov },3728 .{ ._, .mov },
3746 registerAlias(dst_reg, err_abi_size),3729 registerAlias(dst_reg, err_abi_size),
...@@ -3755,9 +3738,10 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3755,9 +3738,10 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
37553738
3756// *(E!T) -> *T3739// *(E!T) -> *T
3757fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {3740fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3741 const mod = self.bin_file.options.module.?;
3758 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3742 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);
3761 const src_mcv = try self.resolveInst(ty_op.operand);3745 const src_mcv = try self.resolveInst(ty_op.operand);
3762 const src_reg = switch (src_mcv) {3746 const src_reg = switch (src_mcv) {
3763 .register => |reg| reg,3747 .register => |reg| reg,
...@@ -3766,7 +3750,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3766,7 +3750,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3766 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);3750 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
3767 defer self.register_manager.unlockReg(src_lock);3751 defer self.register_manager.unlockReg(src_lock);
37683752
3769 const dst_ty = self.air.typeOfIndex(inst);3753 const dst_ty = self.typeOfIndex(inst);
3770 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))3754 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
3771 src_reg3755 src_reg
3772 else3756 else
...@@ -3775,10 +3759,10 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3775,10 +3759,10 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3775 const dst_lock = self.register_manager.lockReg(dst_reg);3759 const dst_lock = self.register_manager.lockReg(dst_reg);
3776 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3760 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
37773761
3778 const eu_ty = src_ty.childType();3762 const eu_ty = src_ty.childType(mod);
3779 const pl_ty = eu_ty.errorUnionPayload();3763 const pl_ty = eu_ty.errorUnionPayload(mod);
3780 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));3764 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3781 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));3765 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
3782 try self.asmRegisterMemory(3766 try self.asmRegisterMemory(
3783 .{ ._, .lea },3767 .{ ._, .lea },
3784 registerAlias(dst_reg, dst_abi_size),3768 registerAlias(dst_reg, dst_abi_size),
...@@ -3789,9 +3773,10 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3789,9 +3773,10 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3789}3773}
37903774
3791fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {3775fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3776 const mod = self.bin_file.options.module.?;
3792 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3777 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3793 const result: MCValue = result: {3778 const result: MCValue = result: {
3794 const src_ty = self.air.typeOf(ty_op.operand);3779 const src_ty = self.typeOf(ty_op.operand);
3795 const src_mcv = try self.resolveInst(ty_op.operand);3780 const src_mcv = try self.resolveInst(ty_op.operand);
3796 const src_reg = switch (src_mcv) {3781 const src_reg = switch (src_mcv) {
3797 .register => |reg| reg,3782 .register => |reg| reg,
...@@ -3800,11 +3785,11 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3800,11 +3785,11 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3800 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);3785 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
3801 defer self.register_manager.unlockReg(src_lock);3786 defer self.register_manager.unlockReg(src_lock);
38023787
3803 const eu_ty = src_ty.childType();3788 const eu_ty = src_ty.childType(mod);
3804 const pl_ty = eu_ty.errorUnionPayload();3789 const pl_ty = eu_ty.errorUnionPayload(mod);
3805 const err_ty = eu_ty.errorUnionSet();3790 const err_ty = eu_ty.errorUnionSet(mod);
3806 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));3791 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
3807 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));3792 const err_abi_size = @intCast(u32, err_ty.abiSize(mod));
3808 try self.asmMemoryImmediate(3793 try self.asmMemoryImmediate(
3809 .{ ._, .mov },3794 .{ ._, .mov },
3810 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{3795 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{
...@@ -3816,7 +3801,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3816,7 +3801,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
38163801
3817 if (self.liveness.isUnused(inst)) break :result .unreach;3802 if (self.liveness.isUnused(inst)) break :result .unreach;
38183803
3819 const dst_ty = self.air.typeOfIndex(inst);3804 const dst_ty = self.typeOfIndex(inst);
3820 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))3805 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
3821 src_reg3806 src_reg
3822 else3807 else
...@@ -3824,8 +3809,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3824,8 +3809,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3824 const dst_lock = self.register_manager.lockReg(dst_reg);3809 const dst_lock = self.register_manager.lockReg(dst_reg);
3825 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3810 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
38263811
3827 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));3812 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3828 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));3813 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
3829 try self.asmRegisterMemory(3814 try self.asmRegisterMemory(
3830 .{ ._, .lea },3815 .{ ._, .lea },
3831 registerAlias(dst_reg, dst_abi_size),3816 registerAlias(dst_reg, dst_abi_size),
...@@ -3853,14 +3838,15 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {...@@ -3853,14 +3838,15 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
3853}3838}
38543839
3855fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {3840fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3841 const mod = self.bin_file.options.module.?;
3856 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3842 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3857 const result: MCValue = result: {3843 const result: MCValue = result: {
3858 const pl_ty = self.air.typeOf(ty_op.operand);3844 const pl_ty = self.typeOf(ty_op.operand);
3859 if (!pl_ty.hasRuntimeBits()) break :result .{ .immediate = 1 };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);
3862 const pl_mcv = try self.resolveInst(ty_op.operand);3848 const pl_mcv = try self.resolveInst(ty_op.operand);
3863 const same_repr = opt_ty.optionalReprIsPayload();3849 const same_repr = opt_ty.optionalReprIsPayload(mod);
3864 if (same_repr and self.reuseOperand(inst, ty_op.operand, 0, pl_mcv)) break :result pl_mcv;3850 if (same_repr and self.reuseOperand(inst, ty_op.operand, 0, pl_mcv)) break :result pl_mcv;
38653851
3866 const pl_lock: ?RegisterLock = switch (pl_mcv) {3852 const pl_lock: ?RegisterLock = switch (pl_mcv) {
...@@ -3873,7 +3859,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -3873,7 +3859,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3873 try self.genCopy(pl_ty, opt_mcv, pl_mcv);3859 try self.genCopy(pl_ty, opt_mcv, pl_mcv);
38743860
3875 if (!same_repr) {3861 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));
3877 switch (opt_mcv) {3863 switch (opt_mcv) {
3878 else => unreachable,3864 else => unreachable,
38793865
...@@ -3900,19 +3886,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -3900,19 +3886,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
39003886
3901/// T to E!T3887/// T to E!T
3902fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {3888fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
3889 const mod = self.bin_file.options.module.?;
3903 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3890 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
39043891
3905 const eu_ty = self.air.getRefType(ty_op.ty);3892 const eu_ty = self.air.getRefType(ty_op.ty);
3906 const pl_ty = eu_ty.errorUnionPayload();3893 const pl_ty = eu_ty.errorUnionPayload(mod);
3907 const err_ty = eu_ty.errorUnionSet();3894 const err_ty = eu_ty.errorUnionSet(mod);
3908 const operand = try self.resolveInst(ty_op.operand);3895 const operand = try self.resolveInst(ty_op.operand);
39093896
3910 const result: MCValue = result: {3897 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.*));3900 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
3914 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));3901 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3915 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));3902 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
3916 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);3903 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);
3917 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });3904 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });
3918 break :result .{ .load_frame = .{ .index = frame_index } };3905 break :result .{ .load_frame = .{ .index = frame_index } };
...@@ -3922,18 +3909,19 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -3922,18 +3909,19 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
39223909
3923/// E to E!T3910/// E to E!T
3924fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {3911fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
3912 const mod = self.bin_file.options.module.?;
3925 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3913 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
39263914
3927 const eu_ty = self.air.getRefType(ty_op.ty);3915 const eu_ty = self.air.getRefType(ty_op.ty);
3928 const pl_ty = eu_ty.errorUnionPayload();3916 const pl_ty = eu_ty.errorUnionPayload(mod);
3929 const err_ty = eu_ty.errorUnionSet();3917 const err_ty = eu_ty.errorUnionSet(mod);
39303918
3931 const result: MCValue = result: {3919 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.*));3922 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
3935 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));3923 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3936 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));3924 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
3937 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);3925 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);
3938 const operand = try self.resolveInst(ty_op.operand);3926 const operand = try self.resolveInst(ty_op.operand);
3939 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand);3927 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand);
...@@ -3949,7 +3937,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3949,7 +3937,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
3949 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;3937 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
39503938
3951 const dst_mcv = try self.allocRegOrMem(inst, true);3939 const dst_mcv = try self.allocRegOrMem(inst, true);
3952 const dst_ty = self.air.typeOfIndex(inst);3940 const dst_ty = self.typeOfIndex(inst);
3953 try self.genCopy(dst_ty, dst_mcv, src_mcv);3941 try self.genCopy(dst_ty, dst_mcv, src_mcv);
3954 break :result dst_mcv;3942 break :result dst_mcv;
3955 };3943 };
...@@ -3974,9 +3962,10 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -3974,9 +3962,10 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
3974}3962}
39753963
3976fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {3964fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
3965 const mod = self.bin_file.options.module.?;
3977 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3966 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);
3980 const src_mcv = try self.resolveInst(ty_op.operand);3969 const src_mcv = try self.resolveInst(ty_op.operand);
3981 const src_reg = switch (src_mcv) {3970 const src_reg = switch (src_mcv) {
3982 .register => |reg| reg,3971 .register => |reg| reg,
...@@ -3985,7 +3974,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3985,7 +3974,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
3985 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);3974 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
3986 defer self.register_manager.unlockReg(src_lock);3975 defer self.register_manager.unlockReg(src_lock);
39873976
3988 const dst_ty = self.air.typeOfIndex(inst);3977 const dst_ty = self.typeOfIndex(inst);
3989 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))3978 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
3990 src_reg3979 src_reg
3991 else3980 else
...@@ -3994,7 +3983,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3994,7 +3983,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
3994 const dst_lock = self.register_manager.lockReg(dst_reg);3983 const dst_lock = self.register_manager.lockReg(dst_reg);
3995 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3984 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));
3998 try self.asmRegisterMemory(3987 try self.asmRegisterMemory(
3999 .{ ._, .lea },3988 .{ ._, .lea },
4000 registerAlias(dst_reg, dst_abi_size),3989 registerAlias(dst_reg, dst_abi_size),
...@@ -4010,7 +3999,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4010,7 +3999,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
4010fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {3999fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
4011 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4000 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);
4014 const opt_mcv = try self.resolveInst(ty_op.operand);4003 const opt_mcv = try self.resolveInst(ty_op.operand);
40154004
4016 const dst_mcv = if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))4005 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...@@ -4041,7 +4030,8 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi
4041}4030}
40424031
4043fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {4032fn 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);
4045 const slice_mcv = try self.resolveInst(lhs);4035 const slice_mcv = try self.resolveInst(lhs);
4046 const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) {4036 const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) {
4047 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),4037 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -4049,12 +4039,11 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -4049,12 +4039,11 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
4049 };4039 };
4050 defer if (slice_mcv_lock) |lock| self.register_manager.unlockReg(lock);4040 defer if (slice_mcv_lock) |lock| self.register_manager.unlockReg(lock);
40514041
4052 const elem_ty = slice_ty.childType();4042 const elem_ty = slice_ty.childType(mod);
4053 const elem_size = elem_ty.abiSize(self.target.*);4043 const elem_size = elem_ty.abiSize(mod);
4054 var buf: Type.SlicePtrFieldTypeBuffer = undefined;4044 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
4055 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
40564045
4057 const index_ty = self.air.typeOf(rhs);4046 const index_ty = self.typeOf(rhs);
4058 const index_mcv = try self.resolveInst(rhs);4047 const index_mcv = try self.resolveInst(rhs);
4059 const index_mcv_lock: ?RegisterLock = switch (index_mcv) {4048 const index_mcv_lock: ?RegisterLock = switch (index_mcv) {
4060 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),4049 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -4077,11 +4066,11 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -4077,11 +4066,11 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
4077}4066}
40784067
4079fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {4068fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
4069 const mod = self.bin_file.options.module.?;
4080 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4070 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;4073 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
4084 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
4085 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);4074 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
4086 const dst_mcv = try self.allocRegOrMem(inst, false);4075 const dst_mcv = try self.allocRegOrMem(inst, false);
4087 try self.load(dst_mcv, slice_ptr_field_type, elem_ptr);4076 try self.load(dst_mcv, slice_ptr_field_type, elem_ptr);
...@@ -4097,9 +4086,10 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4097,9 +4086,10 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
4097}4086}
40984087
4099fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {4088fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
4089 const mod = self.bin_file.options.module.?;
4100 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4090 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);
4103 const array = try self.resolveInst(bin_op.lhs);4093 const array = try self.resolveInst(bin_op.lhs);
4104 const array_lock: ?RegisterLock = switch (array) {4094 const array_lock: ?RegisterLock = switch (array) {
4105 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),4095 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -4107,10 +4097,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4107,10 +4097,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
4107 };4097 };
4108 defer if (array_lock) |lock| self.register_manager.unlockReg(lock);4098 defer if (array_lock) |lock| self.register_manager.unlockReg(lock);
41094099
4110 const elem_ty = array_ty.childType();4100 const elem_ty = array_ty.childType(mod);
4111 const elem_abi_size = elem_ty.abiSize(self.target.*);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);
4114 const index = try self.resolveInst(bin_op.rhs);4104 const index = try self.resolveInst(bin_op.rhs);
4115 const index_lock: ?RegisterLock = switch (index) {4105 const index_lock: ?RegisterLock = switch (index) {
4116 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),4106 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -4125,7 +4115,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4125,7 +4115,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
4125 const addr_reg = try self.register_manager.allocReg(null, gp);4115 const addr_reg = try self.register_manager.allocReg(null, gp);
4126 switch (array) {4116 switch (array) {
4127 .register => {4117 .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));
4129 try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array);4119 try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array);
4130 try self.asmRegisterMemory(4120 try self.asmRegisterMemory(
4131 .{ ._, .lea },4121 .{ ._, .lea },
...@@ -4162,15 +4152,16 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4162,15 +4152,16 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
4162}4152}
41634153
4164fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {4154fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
4155 const mod = self.bin_file.options.module.?;
4165 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4156 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
4168 // this is identical to the `airPtrElemPtr` codegen expect here an4159 // this is identical to the `airPtrElemPtr` codegen expect here an
4169 // additional `mov` is needed at the end to get the actual value4160 // additional `mov` is needed at the end to get the actual value
41704161
4171 const elem_ty = ptr_ty.elemType2();4162 const elem_ty = ptr_ty.elemType2(mod);
4172 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));4163 const elem_abi_size = @intCast(u32, elem_ty.abiSize(mod));
4173 const index_ty = self.air.typeOf(bin_op.rhs);4164 const index_ty = self.typeOf(bin_op.rhs);
4174 const index_mcv = try self.resolveInst(bin_op.rhs);4165 const index_mcv = try self.resolveInst(bin_op.rhs);
4175 const index_lock = switch (index_mcv) {4166 const index_lock = switch (index_mcv) {
4176 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),4167 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -4207,10 +4198,11 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4207,10 +4198,11 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
4207}4198}
42084199
4209fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {4200fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
4201 const mod = self.bin_file.options.module.?;
4210 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4202 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4211 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;4203 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);
4214 const ptr = try self.resolveInst(extra.lhs);4206 const ptr = try self.resolveInst(extra.lhs);
4215 const ptr_lock: ?RegisterLock = switch (ptr) {4207 const ptr_lock: ?RegisterLock = switch (ptr) {
4216 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),4208 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -4218,9 +4210,9 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4218,9 +4210,9 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
4218 };4210 };
4219 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);4211 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
42204212
4221 const elem_ty = ptr_ty.elemType2();4213 const elem_ty = ptr_ty.elemType2(mod);
4222 const elem_abi_size = elem_ty.abiSize(self.target.*);4214 const elem_abi_size = elem_ty.abiSize(mod);
4223 const index_ty = self.air.typeOf(extra.rhs);4215 const index_ty = self.typeOf(extra.rhs);
4224 const index = try self.resolveInst(extra.rhs);4216 const index = try self.resolveInst(extra.rhs);
4225 const index_lock: ?RegisterLock = switch (index) {4217 const index_lock: ?RegisterLock = switch (index) {
4226 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),4218 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -4239,11 +4231,12 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4239,11 +4231,12 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
4239}4231}
42404232
4241fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {4233fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
4234 const mod = self.bin_file.options.module.?;
4242 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4235 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4243 const ptr_union_ty = self.air.typeOf(bin_op.lhs);4236 const ptr_union_ty = self.typeOf(bin_op.lhs);
4244 const union_ty = ptr_union_ty.childType();4237 const union_ty = ptr_union_ty.childType(mod);
4245 const tag_ty = self.air.typeOf(bin_op.rhs);4238 const tag_ty = self.typeOf(bin_op.rhs);
4246 const layout = union_ty.unionGetLayout(self.target.*);4239 const layout = union_ty.unionGetLayout(mod);
42474240
4248 if (layout.tag_size == 0) {4241 if (layout.tag_size == 0) {
4249 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });4242 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 {...@@ -4275,20 +4268,19 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
4275 break :blk MCValue{ .register = reg };4268 break :blk MCValue{ .register = reg };
4276 } else ptr;4269 } else ptr;
42774270
4278 var ptr_tag_pl = ptr_union_ty.ptrInfo();4271 const ptr_tag_ty = try mod.adjustPtrTypeChild(ptr_union_ty, tag_ty);
4279 ptr_tag_pl.data.pointee_type = tag_ty;
4280 const ptr_tag_ty = Type.initPayload(&ptr_tag_pl.base);
4281 try self.store(ptr_tag_ty, adjusted_ptr, tag);4272 try self.store(ptr_tag_ty, adjusted_ptr, tag);
42824273
4283 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });4274 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
4284}4275}
42854276
4286fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {4277fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
4278 const mod = self.bin_file.options.module.?;
4287 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4279 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
42884280
4289 const tag_ty = self.air.typeOfIndex(inst);4281 const tag_ty = self.typeOfIndex(inst);
4290 const union_ty = self.air.typeOf(ty_op.operand);4282 const union_ty = self.typeOf(ty_op.operand);
4291 const layout = union_ty.unionGetLayout(self.target.*);4283 const layout = union_ty.unionGetLayout(mod);
42924284
4293 if (layout.tag_size == 0) {4285 if (layout.tag_size == 0) {
4294 return self.finishAir(inst, .none, .{ ty_op.operand, .none, .none });4286 return self.finishAir(inst, .none, .{ ty_op.operand, .none, .none });
...@@ -4302,7 +4294,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -4302,7 +4294,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
4302 };4294 };
4303 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);4295 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);
4306 const dst_mcv: MCValue = blk: {4298 const dst_mcv: MCValue = blk: {
4307 switch (operand) {4299 switch (operand) {
4308 .load_frame => |frame_addr| {4300 .load_frame => |frame_addr| {
...@@ -4337,10 +4329,11 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -4337,10 +4329,11 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
4337}4329}
43384330
4339fn airClz(self: *Self, inst: Air.Inst.Index) !void {4331fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4332 const mod = self.bin_file.options.module.?;
4340 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4333 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4341 const result = result: {4334 const result = result: {
4342 const dst_ty = self.air.typeOfIndex(inst);4335 const dst_ty = self.typeOfIndex(inst);
4343 const src_ty = self.air.typeOf(ty_op.operand);4336 const src_ty = self.typeOf(ty_op.operand);
43444337
4345 const src_mcv = try self.resolveInst(ty_op.operand);4338 const src_mcv = try self.resolveInst(ty_op.operand);
4346 const mat_src_mcv = switch (src_mcv) {4339 const mat_src_mcv = switch (src_mcv) {
...@@ -4358,7 +4351,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4358,7 +4351,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4358 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);4351 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
4359 defer self.register_manager.unlockReg(dst_lock);4352 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);
4362 if (self.hasFeature(.lzcnt)) {4355 if (self.hasFeature(.lzcnt)) {
4363 if (src_bits <= 8) {4356 if (src_bits <= 8) {
4364 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);4357 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
...@@ -4405,7 +4398,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4405,7 +4398,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4405 }4398 }
44064399
4407 if (src_bits > 64)4400 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)});
4409 if (math.isPowerOfTwo(src_bits)) {4402 if (math.isPowerOfTwo(src_bits)) {
4410 const imm_reg = try self.copyToTmpRegister(dst_ty, .{4403 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
4411 .immediate = src_bits ^ (src_bits - 1),4404 .immediate = src_bits ^ (src_bits - 1),
...@@ -4422,7 +4415,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4422,7 +4415,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4422 try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg });4415 try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg });
4423 } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);4416 } 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);
4426 try self.asmCmovccRegisterRegister(4419 try self.asmCmovccRegisterRegister(
4427 registerAlias(dst_reg, cmov_abi_size),4420 registerAlias(dst_reg, cmov_abi_size),
4428 registerAlias(imm_reg, cmov_abi_size),4421 registerAlias(imm_reg, cmov_abi_size),
...@@ -4449,7 +4442,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4449,7 +4442,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4449 .{ .register = wide_reg },4442 .{ .register = wide_reg },
4450 );4443 );
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);
4453 try self.asmCmovccRegisterRegister(4446 try self.asmCmovccRegisterRegister(
4454 registerAlias(imm_reg, cmov_abi_size),4447 registerAlias(imm_reg, cmov_abi_size),
4455 registerAlias(dst_reg, cmov_abi_size),4448 registerAlias(dst_reg, cmov_abi_size),
...@@ -4465,11 +4458,12 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4465,11 +4458,12 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4465}4458}
44664459
4467fn airCtz(self: *Self, inst: Air.Inst.Index) !void {4460fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
4461 const mod = self.bin_file.options.module.?;
4468 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4462 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4469 const result = result: {4463 const result = result: {
4470 const dst_ty = self.air.typeOfIndex(inst);4464 const dst_ty = self.typeOfIndex(inst);
4471 const src_ty = self.air.typeOf(ty_op.operand);4465 const src_ty = self.typeOf(ty_op.operand);
4472 const src_bits = src_ty.bitSize(self.target.*);4466 const src_bits = src_ty.bitSize(mod);
44734467
4474 const src_mcv = try self.resolveInst(ty_op.operand);4468 const src_mcv = try self.resolveInst(ty_op.operand);
4475 const mat_src_mcv = switch (src_mcv) {4469 const mat_src_mcv = switch (src_mcv) {
...@@ -4548,7 +4542,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4548,7 +4542,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
4548 try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg });4542 try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg });
4549 } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv);4543 } 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);
4552 try self.asmCmovccRegisterRegister(4546 try self.asmCmovccRegisterRegister(
4553 registerAlias(dst_reg, cmov_abi_size),4547 registerAlias(dst_reg, cmov_abi_size),
4554 registerAlias(width_reg, cmov_abi_size),4548 registerAlias(width_reg, cmov_abi_size),
...@@ -4560,10 +4554,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4560,10 +4554,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
4560}4554}
45614555
4562fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {4556fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
4557 const mod = self.bin_file.options.module.?;
4563 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4558 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4564 const result: MCValue = result: {4559 const result: MCValue = result: {
4565 const src_ty = self.air.typeOf(ty_op.operand);4560 const src_ty = self.typeOf(ty_op.operand);
4566 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));4561 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
4567 const src_mcv = try self.resolveInst(ty_op.operand);4562 const src_mcv = try self.resolveInst(ty_op.operand);
45684563
4569 if (self.hasFeature(.popcnt)) {4564 if (self.hasFeature(.popcnt)) {
...@@ -4729,16 +4724,17 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m...@@ -4729,16 +4724,17 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
4729}4724}
47304725
4731fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {4726fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
4727 const mod = self.bin_file.options.module.?;
4732 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4728 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);
4735 const src_mcv = try self.resolveInst(ty_op.operand);4731 const src_mcv = try self.resolveInst(ty_op.operand);
47364732
4737 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, true);4733 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, true);
4738 switch (self.regExtraBits(src_ty)) {4734 switch (self.regExtraBits(src_ty)) {
4739 0 => {},4735 0 => {},
4740 else => |extra| try self.genBinOpMir(4736 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 },
4742 src_ty,4738 src_ty,
4743 dst_mcv,4739 dst_mcv,
4744 .{ .immediate = extra },4740 .{ .immediate = extra },
...@@ -4749,10 +4745,11 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {...@@ -4749,10 +4745,11 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
4749}4745}
47504746
4751fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {4747fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
4748 const mod = self.bin_file.options.module.?;
4752 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4749 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
47534750
4754 const src_ty = self.air.typeOf(ty_op.operand);4751 const src_ty = self.typeOf(ty_op.operand);
4755 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));4752 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
4756 const src_mcv = try self.resolveInst(ty_op.operand);4753 const src_mcv = try self.resolveInst(ty_op.operand);
47574754
4758 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, false);4755 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 {...@@ -4847,7 +4844,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
4847 switch (self.regExtraBits(src_ty)) {4844 switch (self.regExtraBits(src_ty)) {
4848 0 => {},4845 0 => {},
4849 else => |extra| try self.genBinOpMir(4846 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 },
4851 src_ty,4848 src_ty,
4852 dst_mcv,4849 dst_mcv,
4853 .{ .immediate = extra },4850 .{ .immediate = extra },
...@@ -4858,17 +4855,18 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {...@@ -4858,17 +4855,18 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
4858}4855}
48594856
4860fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {4857fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4858 const mod = self.bin_file.options.module.?;
4861 const tag = self.air.instructions.items(.tag)[inst];4859 const tag = self.air.instructions.items(.tag)[inst];
4862 const un_op = self.air.instructions.items(.data)[inst].un_op;4860 const un_op = self.air.instructions.items(.data)[inst].un_op;
4863 const ty = self.air.typeOf(un_op);4861 const ty = self.typeOf(un_op);
4864 const abi_size: u32 = switch (ty.abiSize(self.target.*)) {4862 const abi_size: u32 = switch (ty.abiSize(mod)) {
4865 1...16 => 16,4863 1...16 => 16,
4866 17...32 => 32,4864 17...32 => 32,
4867 else => return self.fail("TODO implement airFloatSign for {}", .{4865 else => return self.fail("TODO implement airFloatSign for {}", .{
4868 ty.fmt(self.bin_file.options.module.?),4866 ty.fmt(mod),
4869 }),4867 }),
4870 };4868 };
4871 const scalar_bits = ty.scalarType().floatBits(self.target.*);4869 const scalar_bits = ty.scalarType(mod).floatBits(self.target.*);
48724870
4873 const src_mcv = try self.resolveInst(un_op);4871 const src_mcv = try self.resolveInst(un_op);
4874 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;4872 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 {...@@ -4884,42 +4882,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4884 const dst_lock = self.register_manager.lockReg(dst_reg);4882 const dst_lock = self.register_manager.lockReg(dst_reg);
4885 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);4883 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
48864884
4887 var arena = std.heap.ArenaAllocator.init(self.gpa);4885 const vec_ty = try mod.vectorType(.{
4888 defer arena.deinit();4886 .len = @divExact(abi_size * 8, scalar_bits),
48894887 .child = (try mod.intType(.signed, scalar_bits)).ip_index,
4890 const ExpectedContents = struct {4888 });
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());
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);
4920 const sign_val = switch (tag) {4890 const sign_val = switch (tag) {
4921 .neg => try vec_ty.minInt(stack.get(), self.target.*),4891 .neg => try vec_ty.minInt(mod, vec_ty),
4922 .fabs => try vec_ty.maxInt(stack.get(), self.target.*),4892 .fabs => try vec_ty.maxInt(mod, vec_ty),
4923 else => unreachable,4893 else => unreachable,
4924 };4894 };
49254895
...@@ -4993,7 +4963,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {...@@ -4993,7 +4963,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
49934963
4994fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {4964fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
4995 const un_op = self.air.instructions.items(.data)[inst].un_op;4965 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
4998 const src_mcv = try self.resolveInst(un_op);4968 const src_mcv = try self.resolveInst(un_op);
4999 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))4969 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 {...@@ -5008,25 +4978,26 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
5008}4978}
50094979
5010fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4) !void {4980fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4) !void {
4981 const mod = self.bin_file.options.module.?;
5011 if (!self.hasFeature(.sse4_1))4982 if (!self.hasFeature(.sse4_1))
5012 return self.fail("TODO implement genRound without sse4_1 feature", .{});4983 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)) {
5015 .Float => switch (ty.floatBits(self.target.*)) {4986 .Float => switch (ty.floatBits(self.target.*)) {
5016 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },4987 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },
5017 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },4988 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },
5018 16, 80, 128 => null,4989 16, 80, 128 => null,
5019 else => unreachable,4990 else => unreachable,
5020 },4991 },
5021 .Vector => switch (ty.childType().zigTypeTag()) {4992 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
5022 .Float => switch (ty.childType().floatBits(self.target.*)) {4993 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
5023 32 => switch (ty.vectorLen()) {4994 32 => switch (ty.vectorLen(mod)) {
5024 1 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },4995 1 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },
5025 2...4 => if (self.hasFeature(.avx)) .{ .v_ps, .round } else .{ ._ps, .round },4996 2...4 => if (self.hasFeature(.avx)) .{ .v_ps, .round } else .{ ._ps, .round },
5026 5...8 => if (self.hasFeature(.avx)) .{ .v_ps, .round } else null,4997 5...8 => if (self.hasFeature(.avx)) .{ .v_ps, .round } else null,
5027 else => null,4998 else => null,
5028 },4999 },
5029 64 => switch (ty.vectorLen()) {5000 64 => switch (ty.vectorLen(mod)) {
5030 1 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },5001 1 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },
5031 2 => if (self.hasFeature(.avx)) .{ .v_pd, .round } else .{ ._pd, .round },5002 2 => if (self.hasFeature(.avx)) .{ .v_pd, .round } else .{ ._pd, .round },
5032 3...4 => if (self.hasFeature(.avx)) .{ .v_pd, .round } else null,5003 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...@@ -5041,7 +5012,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
5041 })) |tag| tag else return self.fail("TODO implement genRound for {}", .{5012 })) |tag| tag else return self.fail("TODO implement genRound for {}", .{
5042 ty.fmt(self.bin_file.options.module.?),5013 ty.fmt(self.bin_file.options.module.?),
5043 });5014 });
5044 const abi_size = @intCast(u32, ty.abiSize(self.target.*));5015 const abi_size = @intCast(u32, ty.abiSize(mod));
5045 const dst_alias = registerAlias(dst_reg, abi_size);5016 const dst_alias = registerAlias(dst_reg, abi_size);
5046 switch (mir_tag[0]) {5017 switch (mir_tag[0]) {
5047 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(5018 .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...@@ -5078,9 +5049,10 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
5078}5049}
50795050
5080fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {5051fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5052 const mod = self.bin_file.options.module.?;
5081 const un_op = self.air.instructions.items(.data)[inst].un_op;5053 const un_op = self.air.instructions.items(.data)[inst].un_op;
5082 const ty = self.air.typeOf(un_op);5054 const ty = self.typeOf(un_op);
5083 const abi_size = @intCast(u32, ty.abiSize(self.target.*));5055 const abi_size = @intCast(u32, ty.abiSize(mod));
50845056
5085 const src_mcv = try self.resolveInst(un_op);5057 const src_mcv = try self.resolveInst(un_op);
5086 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))5058 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 {...@@ -5092,7 +5064,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5092 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);5064 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
50935065
5094 const result: MCValue = result: {5066 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)) {
5096 .Float => switch (ty.floatBits(self.target.*)) {5068 .Float => switch (ty.floatBits(self.target.*)) {
5097 16 => if (self.hasFeature(.f16c)) {5069 16 => if (self.hasFeature(.f16c)) {
5098 const mat_src_reg = if (src_mcv.isRegister())5070 const mat_src_reg = if (src_mcv.isRegister())
...@@ -5114,9 +5086,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5114,9 +5086,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5114 80, 128 => null,5086 80, 128 => null,
5115 else => unreachable,5087 else => unreachable,
5116 },5088 },
5117 .Vector => switch (ty.childType().zigTypeTag()) {5089 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
5118 .Float => switch (ty.childType().floatBits(self.target.*)) {5090 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
5119 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {5091 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen(mod)) {
5120 1 => {5092 1 => {
5121 try self.asmRegisterRegister(5093 try self.asmRegisterRegister(
5122 .{ .v_ps, .cvtph2 },5094 .{ .v_ps, .cvtph2 },
...@@ -5167,13 +5139,13 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5167,13 +5139,13 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5167 },5139 },
5168 else => null,5140 else => null,
5169 } else null,5141 } else null,
5170 32 => switch (ty.vectorLen()) {5142 32 => switch (ty.vectorLen(mod)) {
5171 1 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt },5143 1 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt },
5172 2...4 => if (self.hasFeature(.avx)) .{ .v_ps, .sqrt } else .{ ._ps, .sqrt },5144 2...4 => if (self.hasFeature(.avx)) .{ .v_ps, .sqrt } else .{ ._ps, .sqrt },
5173 5...8 => if (self.hasFeature(.avx)) .{ .v_ps, .sqrt } else null,5145 5...8 => if (self.hasFeature(.avx)) .{ .v_ps, .sqrt } else null,
5174 else => null,5146 else => null,
5175 },5147 },
5176 64 => switch (ty.vectorLen()) {5148 64 => switch (ty.vectorLen(mod)) {
5177 1 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt },5149 1 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt },
5178 2 => if (self.hasFeature(.avx)) .{ .v_pd, .sqrt } else .{ ._pd, .sqrt },5150 2 => if (self.hasFeature(.avx)) .{ .v_pd, .sqrt } else .{ ._pd, .sqrt },
5179 3...4 => if (self.hasFeature(.avx)) .{ .v_pd, .sqrt } else null,5151 3...4 => if (self.hasFeature(.avx)) .{ .v_pd, .sqrt } else null,
...@@ -5186,7 +5158,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5186,7 +5158,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5186 },5158 },
5187 else => unreachable,5159 else => unreachable,
5188 })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{5160 })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{
5189 ty.fmt(self.bin_file.options.module.?),5161 ty.fmt(mod),
5190 });5162 });
5191 switch (mir_tag[0]) {5163 switch (mir_tag[0]) {
5192 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(5164 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
...@@ -5274,10 +5246,11 @@ fn reuseOperandAdvanced(...@@ -5274,10 +5246,11 @@ fn reuseOperandAdvanced(
5274}5246}
52755247
5276fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void {5248fn 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
5279 const val_ty = ptr_info.pointee_type;5252 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));
5281 const limb_abi_size: u32 = @min(val_abi_size, 8);5254 const limb_abi_size: u32 = @min(val_abi_size, 8);
5282 const limb_abi_bits = limb_abi_size * 8;5255 const limb_abi_bits = limb_abi_size * 8;
5283 const val_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size);5256 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...@@ -5347,7 +5320,8 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
5347}5320}
53485321
5349fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void {5322fn 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);
5351 switch (ptr_mcv) {5325 switch (ptr_mcv) {
5352 .none,5326 .none,
5353 .unreach,5327 .unreach,
...@@ -5382,20 +5356,21 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro...@@ -5382,20 +5356,21 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
5382}5356}
53835357
5384fn airLoad(self: *Self, inst: Air.Inst.Index) !void {5358fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
5359 const mod = self.bin_file.options.module.?;
5385 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5360 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);
5387 const result: MCValue = result: {5362 const result: MCValue = result: {
5388 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) break :result .none;5363 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
53895364
5390 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });5365 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
5391 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });5366 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
5392 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);5367 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
53935368
5394 const ptr_ty = self.air.typeOf(ty_op.operand);5369 const ptr_ty = self.typeOf(ty_op.operand);
5395 const elem_size = elem_ty.abiSize(self.target.*);5370 const elem_size = elem_ty.abiSize(mod);
53965371
5397 const elem_rc = regClassForType(elem_ty);5372 const elem_rc = regClassForType(elem_ty, mod);
5398 const ptr_rc = regClassForType(ptr_ty);5373 const ptr_rc = regClassForType(ptr_ty, mod);
53995374
5400 const ptr_mcv = try self.resolveInst(ty_op.operand);5375 const ptr_mcv = try self.resolveInst(ty_op.operand);
5401 const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and5376 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 {...@@ -5405,7 +5380,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
5405 else5380 else
5406 try self.allocRegOrMem(inst, true);5381 try self.allocRegOrMem(inst, true);
54075382
5408 if (ptr_ty.ptrInfo().data.host_size > 0) {5383 if (ptr_ty.ptrInfo(mod).host_size > 0) {
5409 try self.packedLoad(dst_mcv, ptr_ty, ptr_mcv);5384 try self.packedLoad(dst_mcv, ptr_ty, ptr_mcv);
5410 } else {5385 } else {
5411 try self.load(dst_mcv, ptr_ty, ptr_mcv);5386 try self.load(dst_mcv, ptr_ty, ptr_mcv);
...@@ -5416,13 +5391,14 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -5416,13 +5391,14 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
5416}5391}
54175392
5418fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void {5393fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void {
5419 const ptr_info = ptr_ty.ptrInfo().data;5394 const mod = self.bin_file.options.module.?;
5420 const src_ty = ptr_ty.childType();5395 const ptr_info = ptr_ty.ptrInfo(mod);
5396 const src_ty = ptr_ty.childType(mod);
54215397
5422 const limb_abi_size: u16 = @min(ptr_info.host_size, 8);5398 const limb_abi_size: u16 = @min(ptr_info.host_size, 8);
5423 const limb_abi_bits = limb_abi_size * 8;5399 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);
5426 const src_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size);5402 const src_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size);
5427 const src_bit_off = ptr_info.bit_offset % limb_abi_bits;5403 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...@@ -5489,7 +5465,8 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
5489}5465}
54905466
5491fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void {5467fn 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);
5493 switch (ptr_mcv) {5470 switch (ptr_mcv) {
5494 .none,5471 .none,
5495 .unreach,5472 .unreach,
...@@ -5524,6 +5501,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr...@@ -5524,6 +5501,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
5524}5501}
55255502
5526fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {5503fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
5504 const mod = self.bin_file.options.module.?;
5527 if (safety) {5505 if (safety) {
5528 // TODO if the value is undef, write 0xaa bytes to dest5506 // TODO if the value is undef, write 0xaa bytes to dest
5529 } else {5507 } else {
...@@ -5531,9 +5509,9 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -5531,9 +5509,9 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
5531 }5509 }
5532 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5510 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5533 const ptr_mcv = try self.resolveInst(bin_op.lhs);5511 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);
5535 const src_mcv = try self.resolveInst(bin_op.rhs);5513 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) {
5537 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);5515 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);
5538 } else {5516 } else {
5539 try self.store(ptr_ty, ptr_mcv, src_mcv);5517 try self.store(ptr_ty, ptr_mcv, src_mcv);
...@@ -5555,14 +5533,15 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {...@@ -5555,14 +5533,15 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
5555}5533}
55565534
5557fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {5535fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
5558 const ptr_field_ty = self.air.typeOfIndex(inst);5536 const mod = self.bin_file.options.module.?;
5559 const ptr_container_ty = self.air.typeOf(operand);5537 const ptr_field_ty = self.typeOfIndex(inst);
5560 const container_ty = ptr_container_ty.childType();5538 const ptr_container_ty = self.typeOf(operand);
5561 const field_offset = @intCast(i32, switch (container_ty.containerLayout()) {5539 const container_ty = ptr_container_ty.childType(mod);
5562 .Auto, .Extern => container_ty.structFieldOffset(index, self.target.*),5540 const field_offset = @intCast(i32, switch (container_ty.containerLayout(mod)) {
5563 .Packed => if (container_ty.zigTypeTag() == .Struct and5541 .Auto, .Extern => container_ty.structFieldOffset(index, mod),
5564 ptr_field_ty.ptrInfo().data.host_size == 0)5542 .Packed => if (container_ty.zigTypeTag(mod) == .Struct and
5565 container_ty.packedStructFieldByteOffset(index, self.target.*)5543 ptr_field_ty.ptrInfo(mod).host_size == 0)
5544 container_ty.packedStructFieldByteOffset(index, mod)
5566 else5545 else
5567 0,5546 0,
5568 });5547 });
...@@ -5577,24 +5556,25 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32...@@ -5577,24 +5556,25 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
5577}5556}
55785557
5579fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {5558fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5559 const mod = self.bin_file.options.module.?;
5580 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5560 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5581 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;5561 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
5582 const result: MCValue = result: {5562 const result: MCValue = result: {
5583 const operand = extra.struct_operand;5563 const operand = extra.struct_operand;
5584 const index = extra.field_index;5564 const index = extra.field_index;
55855565
5586 const container_ty = self.air.typeOf(operand);5566 const container_ty = self.typeOf(operand);
5587 const container_rc = regClassForType(container_ty);5567 const container_rc = regClassForType(container_ty, mod);
5588 const field_ty = container_ty.structFieldType(index);5568 const field_ty = container_ty.structFieldType(index, mod);
5589 if (!field_ty.hasRuntimeBitsIgnoreComptime()) break :result .none;5569 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
5590 const field_rc = regClassForType(field_ty);5570 const field_rc = regClassForType(field_ty, mod);
5591 const field_is_gp = field_rc.supersetOf(gp);5571 const field_is_gp = field_rc.supersetOf(gp);
55925572
5593 const src_mcv = try self.resolveInst(operand);5573 const src_mcv = try self.resolveInst(operand);
5594 const field_off = switch (container_ty.containerLayout()) {5574 const field_off = switch (container_ty.containerLayout(mod)) {
5595 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*) * 8),5575 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8),
5596 .Packed => if (container_ty.castTag(.@"struct")) |struct_obj|5576 .Packed => if (mod.typeToStruct(container_ty)) |struct_obj|
5597 struct_obj.data.packedFieldBitOffset(self.target.*, index)5577 struct_obj.packedFieldBitOffset(mod, index)
5598 else5578 else
5599 0,5579 0,
5600 };5580 };
...@@ -5611,7 +5591,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5611,7 +5591,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5611 break :result dst_mcv;5591 break :result dst_mcv;
5612 }5592 }
56135593
5614 const field_abi_size = @intCast(u32, field_ty.abiSize(self.target.*));5594 const field_abi_size = @intCast(u32, field_ty.abiSize(mod));
5615 const limb_abi_size: u32 = @min(field_abi_size, 8);5595 const limb_abi_size: u32 = @min(field_abi_size, 8);
5616 const limb_abi_bits = limb_abi_size * 8;5596 const limb_abi_bits = limb_abi_size * 8;
5617 const field_byte_off = @intCast(i32, field_off / limb_abi_bits * limb_abi_size);5597 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 {...@@ -5733,12 +5713,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5733}5713}
57345714
5735fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {5715fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
5716 const mod = self.bin_file.options.module.?;
5736 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5717 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5737 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;5718 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
57385719
5739 const inst_ty = self.air.typeOfIndex(inst);5720 const inst_ty = self.typeOfIndex(inst);
5740 const parent_ty = inst_ty.childType();5721 const parent_ty = inst_ty.childType(mod);
5741 const field_offset = @intCast(i32, parent_ty.structFieldOffset(extra.field_index, self.target.*));5722 const field_offset = @intCast(i32, parent_ty.structFieldOffset(extra.field_index, mod));
57425723
5743 const src_mcv = try self.resolveInst(extra.field_ptr);5724 const src_mcv = try self.resolveInst(extra.field_ptr);
5744 const dst_mcv = if (src_mcv.isRegisterOffset() and5725 const dst_mcv = if (src_mcv.isRegisterOffset() and
...@@ -5751,9 +5732,10 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -5751,9 +5732,10 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
5751}5732}
57525733
5753fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {5734fn 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);
5755 const src_mcv = try self.resolveInst(src_air);5737 const src_mcv = try self.resolveInst(src_air);
5756 if (src_ty.zigTypeTag() == .Vector) {5738 if (src_ty.zigTypeTag(mod) == .Vector) {
5757 return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(self.bin_file.options.module.?)});5739 return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(self.bin_file.options.module.?)});
5758 }5740 }
57595741
...@@ -5786,28 +5768,22 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:...@@ -5786,28 +5768,22 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
57865768
5787 switch (tag) {5769 switch (tag) {
5788 .not => {5770 .not => {
5789 const limb_abi_size = @intCast(u16, @min(src_ty.abiSize(self.target.*), 8));5771 const limb_abi_size = @intCast(u16, @min(src_ty.abiSize(mod), 8));
5790 const int_info = if (src_ty.tag() == .bool)5772 const int_info = if (src_ty.ip_index == .bool_type)
5791 std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 }5773 std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 }
5792 else5774 else
5793 src_ty.intInfo(self.target.*);5775 src_ty.intInfo(mod);
5794 var byte_off: i32 = 0;5776 var byte_off: i32 = 0;
5795 while (byte_off * 8 < int_info.bits) : (byte_off += limb_abi_size) {5777 while (byte_off * 8 < int_info.bits) : (byte_off += limb_abi_size) {
5796 var limb_pl = Type.Payload.Bits{5778 const limb_bits = @intCast(u16, @min(int_info.bits - byte_off * 8, limb_abi_size * 8));
5797 .base = .{ .tag = switch (int_info.signedness) {5779 const limb_ty = try mod.intType(int_info.signedness, limb_bits);
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);
5804 const limb_mcv = switch (byte_off) {5780 const limb_mcv = switch (byte_off) {
5805 0 => dst_mcv,5781 0 => dst_mcv,
5806 else => dst_mcv.address().offset(byte_off).deref(),5782 else => dst_mcv.address().offset(byte_off).deref(),
5807 };5783 };
58085784
5809 if (limb_pl.base.tag == .int_unsigned and self.regExtraBits(limb_ty) > 0) {5785 if (int_info.signedness == .unsigned and self.regExtraBits(limb_ty) > 0) {
5810 const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_pl.data);5786 const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_bits);
5811 try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask });5787 try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask });
5812 } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);5788 } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);
5813 }5789 }
...@@ -5819,7 +5795,8 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:...@@ -5819,7 +5795,8 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
5819}5795}
58205796
5821fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {5797fn 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));
5823 if (abi_size > 8) return self.fail("TODO implement {} for {}", .{5800 if (abi_size > 8) return self.fail("TODO implement {} for {}", .{
5824 mir_tag,5801 mir_tag,
5825 dst_ty.fmt(self.bin_file.options.module.?),5802 dst_ty.fmt(self.bin_file.options.module.?),
...@@ -5866,6 +5843,7 @@ fn genShiftBinOpMir(...@@ -5866,6 +5843,7 @@ fn genShiftBinOpMir(
5866 lhs_mcv: MCValue,5843 lhs_mcv: MCValue,
5867 shift_mcv: MCValue,5844 shift_mcv: MCValue,
5868) !void {5845) !void {
5846 const mod = self.bin_file.options.module.?;
5869 const rhs_mcv: MCValue = rhs: {5847 const rhs_mcv: MCValue = rhs: {
5870 switch (shift_mcv) {5848 switch (shift_mcv) {
5871 .immediate => |imm| switch (imm) {5849 .immediate => |imm| switch (imm) {
...@@ -5880,7 +5858,7 @@ fn genShiftBinOpMir(...@@ -5880,7 +5858,7 @@ fn genShiftBinOpMir(
5880 break :rhs .{ .register = .rcx };5858 break :rhs .{ .register = .rcx };
5881 };5859 };
58825860
5883 const abi_size = @intCast(u32, ty.abiSize(self.target.*));5861 const abi_size = @intCast(u32, ty.abiSize(mod));
5884 if (abi_size <= 8) {5862 if (abi_size <= 8) {
5885 switch (lhs_mcv) {5863 switch (lhs_mcv) {
5886 .register => |lhs_reg| switch (rhs_mcv) {5864 .register => |lhs_reg| switch (rhs_mcv) {
...@@ -6099,13 +6077,14 @@ fn genShiftBinOp(...@@ -6099,13 +6077,14 @@ fn genShiftBinOp(
6099 lhs_ty: Type,6077 lhs_ty: Type,
6100 rhs_ty: Type,6078 rhs_ty: Type,
6101) !MCValue {6079) !MCValue {
6102 if (lhs_ty.zigTypeTag() == .Vector) {6080 const mod = self.bin_file.options.module.?;
6081 if (lhs_ty.zigTypeTag(mod) == .Vector) {
6103 return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});6082 return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});
6104 }6083 }
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);
6109 if (lhs_abi_size > 16) {6088 if (lhs_abi_size > 16) {
6110 return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});6089 return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});
6111 }6090 }
...@@ -6136,7 +6115,7 @@ fn genShiftBinOp(...@@ -6136,7 +6115,7 @@ fn genShiftBinOp(
6136 break :dst dst_mcv;6115 break :dst dst_mcv;
6137 };6116 };
61386117
6139 const signedness = lhs_ty.intInfo(self.target.*).signedness;6118 const signedness = lhs_ty.intInfo(mod).signedness;
6140 try self.genShiftBinOpMir(switch (air_tag) {6119 try self.genShiftBinOpMir(switch (air_tag) {
6141 .shl, .shl_exact => switch (signedness) {6120 .shl, .shl_exact => switch (signedness) {
6142 .signed => .{ ._l, .sa },6121 .signed => .{ ._l, .sa },
...@@ -6163,11 +6142,12 @@ fn genMulDivBinOp(...@@ -6163,11 +6142,12 @@ fn genMulDivBinOp(
6163 lhs: MCValue,6142 lhs: MCValue,
6164 rhs: MCValue,6143 rhs: MCValue,
6165) !MCValue {6144) !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) {
6167 return self.fail("TODO implement genMulDivBinOp for {}", .{dst_ty.fmtDebug()});6147 return self.fail("TODO implement genMulDivBinOp for {}", .{dst_ty.fmtDebug()});
6168 }6148 }
6169 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));6149 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
6170 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));6150 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
6171 if (switch (tag) {6151 if (switch (tag) {
6172 else => unreachable,6152 else => unreachable,
6173 .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2,6153 .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2,
...@@ -6184,7 +6164,7 @@ fn genMulDivBinOp(...@@ -6184,7 +6164,7 @@ fn genMulDivBinOp(
6184 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });6164 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });
6185 defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);6165 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;
6188 switch (tag) {6168 switch (tag) {
6189 .mul,6169 .mul,
6190 .mulwrap,6170 .mulwrap,
...@@ -6338,13 +6318,14 @@ fn genBinOp(...@@ -6338,13 +6318,14 @@ fn genBinOp(
6338 lhs_air: Air.Inst.Ref,6318 lhs_air: Air.Inst.Ref,
6339 rhs_air: Air.Inst.Ref,6319 rhs_air: Air.Inst.Ref,
6340) !MCValue {6320) !MCValue {
6341 const lhs_ty = self.air.typeOf(lhs_air);6321 const mod = self.bin_file.options.module.?;
6342 const rhs_ty = self.air.typeOf(rhs_air);6322 const lhs_ty = self.typeOf(lhs_air);
6343 const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*));6323 const rhs_ty = self.typeOf(rhs_air);
6324 const abi_size = @intCast(u32, lhs_ty.abiSize(mod));
63446325
6345 const maybe_mask_reg = switch (air_tag) {6326 const maybe_mask_reg = switch (air_tag) {
6346 else => null,6327 else => null,
6347 .max, .min => if (lhs_ty.scalarType().isRuntimeFloat()) registerAlias(6328 .max, .min => if (lhs_ty.scalarType(mod).isRuntimeFloat()) registerAlias(
6348 if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: {6329 if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: {
6349 try self.register_manager.getReg(.xmm0, null);6330 try self.register_manager.getReg(.xmm0, null);
6350 break :mask .xmm0;6331 break :mask .xmm0;
...@@ -6384,7 +6365,7 @@ fn genBinOp(...@@ -6384,7 +6365,7 @@ fn genBinOp(
63846365
6385 else => false,6366 else => false,
6386 };6367 };
6387 const vec_op = switch (lhs_ty.zigTypeTag()) {6368 const vec_op = switch (lhs_ty.zigTypeTag(mod)) {
6388 else => false,6369 else => false,
6389 .Float, .Vector => true,6370 .Float, .Vector => true,
6390 };6371 };
...@@ -6456,7 +6437,7 @@ fn genBinOp(...@@ -6456,7 +6437,7 @@ fn genBinOp(
6456 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6437 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6457 defer self.register_manager.unlockReg(tmp_lock);6438 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);
6460 try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size });6441 try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size });
6461 try self.genBinOpMir(6442 try self.genBinOpMir(
6462 switch (air_tag) {6443 switch (air_tag) {
...@@ -6506,7 +6487,7 @@ fn genBinOp(...@@ -6506,7 +6487,7 @@ fn genBinOp(
65066487
6507 try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, dst_mcv, mat_src_mcv);6488 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);
6510 const cc: Condition = switch (int_info.signedness) {6491 const cc: Condition = switch (int_info.signedness) {
6511 .unsigned => switch (air_tag) {6492 .unsigned => switch (air_tag) {
6512 .min => .a,6493 .min => .a,
...@@ -6520,7 +6501,7 @@ fn genBinOp(...@@ -6520,7 +6501,7 @@ fn genBinOp(
6520 },6501 },
6521 };6502 };
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);
6524 const tmp_reg = switch (dst_mcv) {6505 const tmp_reg = switch (dst_mcv) {
6525 .register => |reg| reg,6506 .register => |reg| reg,
6526 else => try self.copyToTmpRegister(lhs_ty, dst_mcv),6507 else => try self.copyToTmpRegister(lhs_ty, dst_mcv),
...@@ -6581,7 +6562,7 @@ fn genBinOp(...@@ -6581,7 +6562,7 @@ fn genBinOp(
6581 }6562 }
65826563
6583 const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size);6564 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)) {
6585 else => unreachable,6566 else => unreachable,
6586 .Float => switch (lhs_ty.floatBits(self.target.*)) {6567 .Float => switch (lhs_ty.floatBits(self.target.*)) {
6587 16 => if (self.hasFeature(.f16c)) {6568 16 => if (self.hasFeature(.f16c)) {
...@@ -6657,10 +6638,10 @@ fn genBinOp(...@@ -6657,10 +6638,10 @@ fn genBinOp(
6657 80, 128 => null,6638 80, 128 => null,
6658 else => unreachable,6639 else => unreachable,
6659 },6640 },
6660 .Vector => switch (lhs_ty.childType().zigTypeTag()) {6641 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
6661 else => null,6642 else => null,
6662 .Int => switch (lhs_ty.childType().intInfo(self.target.*).bits) {6643 .Int => switch (lhs_ty.childType(mod).intInfo(mod).bits) {
6663 8 => switch (lhs_ty.vectorLen()) {6644 8 => switch (lhs_ty.vectorLen(mod)) {
6664 1...16 => switch (air_tag) {6645 1...16 => switch (air_tag) {
6665 .add,6646 .add,
6666 .addwrap,6647 .addwrap,
...@@ -6671,7 +6652,7 @@ fn genBinOp(...@@ -6671,7 +6652,7 @@ fn genBinOp(
6671 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },6652 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
6672 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },6653 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
6673 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },6654 .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) {
6675 .signed => if (self.hasFeature(.avx))6656 .signed => if (self.hasFeature(.avx))
6676 .{ .vp_b, .mins }6657 .{ .vp_b, .mins }
6677 else if (self.hasFeature(.sse4_1))6658 else if (self.hasFeature(.sse4_1))
...@@ -6685,7 +6666,7 @@ fn genBinOp(...@@ -6685,7 +6666,7 @@ fn genBinOp(
6685 else6666 else
6686 null,6667 null,
6687 },6668 },
6688 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {6669 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
6689 .signed => if (self.hasFeature(.avx))6670 .signed => if (self.hasFeature(.avx))
6690 .{ .vp_b, .maxs }6671 .{ .vp_b, .maxs }
6691 else if (self.hasFeature(.sse4_1))6672 else if (self.hasFeature(.sse4_1))
...@@ -6711,11 +6692,11 @@ fn genBinOp(...@@ -6711,11 +6692,11 @@ fn genBinOp(
6711 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,6692 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
6712 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,6693 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
6713 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,6694 .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) {
6715 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .mins } else null,6696 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .mins } else null,
6716 .unsigned => if (self.hasFeature(.avx)) .{ .vp_b, .minu } else null,6697 .unsigned => if (self.hasFeature(.avx)) .{ .vp_b, .minu } else null,
6717 },6698 },
6718 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {6699 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
6719 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .maxs } else null,6700 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .maxs } else null,
6720 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_b, .maxu } else null,6701 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_b, .maxu } else null,
6721 },6702 },
...@@ -6723,7 +6704,7 @@ fn genBinOp(...@@ -6723,7 +6704,7 @@ fn genBinOp(
6723 },6704 },
6724 else => null,6705 else => null,
6725 },6706 },
6726 16 => switch (lhs_ty.vectorLen()) {6707 16 => switch (lhs_ty.vectorLen(mod)) {
6727 1...8 => switch (air_tag) {6708 1...8 => switch (air_tag) {
6728 .add,6709 .add,
6729 .addwrap,6710 .addwrap,
...@@ -6737,7 +6718,7 @@ fn genBinOp(...@@ -6737,7 +6718,7 @@ fn genBinOp(
6737 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },6718 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
6738 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },6719 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
6739 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },6720 .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) {
6741 .signed => if (self.hasFeature(.avx))6722 .signed => if (self.hasFeature(.avx))
6742 .{ .vp_w, .mins }6723 .{ .vp_w, .mins }
6743 else6724 else
...@@ -6747,7 +6728,7 @@ fn genBinOp(...@@ -6747,7 +6728,7 @@ fn genBinOp(
6747 else6728 else
6748 .{ .p_w, .minu },6729 .{ .p_w, .minu },
6749 },6730 },
6750 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {6731 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
6751 .signed => if (self.hasFeature(.avx))6732 .signed => if (self.hasFeature(.avx))
6752 .{ .vp_w, .maxs }6733 .{ .vp_w, .maxs }
6753 else6734 else
...@@ -6772,11 +6753,11 @@ fn genBinOp(...@@ -6772,11 +6753,11 @@ fn genBinOp(
6772 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,6753 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
6773 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,6754 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
6774 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,6755 .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) {
6776 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .mins } else null,6757 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .mins } else null,
6777 .unsigned => if (self.hasFeature(.avx)) .{ .vp_w, .minu } else null,6758 .unsigned => if (self.hasFeature(.avx)) .{ .vp_w, .minu } else null,
6778 },6759 },
6779 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {6760 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
6780 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .maxs } else null,6761 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .maxs } else null,
6781 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .maxu } else null,6762 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .maxu } else null,
6782 },6763 },
...@@ -6784,7 +6765,7 @@ fn genBinOp(...@@ -6784,7 +6765,7 @@ fn genBinOp(
6784 },6765 },
6785 else => null,6766 else => null,
6786 },6767 },
6787 32 => switch (lhs_ty.vectorLen()) {6768 32 => switch (lhs_ty.vectorLen(mod)) {
6788 1...4 => switch (air_tag) {6769 1...4 => switch (air_tag) {
6789 .add,6770 .add,
6790 .addwrap,6771 .addwrap,
...@@ -6803,7 +6784,7 @@ fn genBinOp(...@@ -6803,7 +6784,7 @@ fn genBinOp(
6803 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },6784 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
6804 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },6785 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
6805 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },6786 .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) {
6807 .signed => if (self.hasFeature(.avx))6788 .signed => if (self.hasFeature(.avx))
6808 .{ .vp_d, .mins }6789 .{ .vp_d, .mins }
6809 else if (self.hasFeature(.sse4_1))6790 else if (self.hasFeature(.sse4_1))
...@@ -6817,7 +6798,7 @@ fn genBinOp(...@@ -6817,7 +6798,7 @@ fn genBinOp(
6817 else6798 else
6818 null,6799 null,
6819 },6800 },
6820 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {6801 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
6821 .signed => if (self.hasFeature(.avx))6802 .signed => if (self.hasFeature(.avx))
6822 .{ .vp_d, .maxs }6803 .{ .vp_d, .maxs }
6823 else if (self.hasFeature(.sse4_1))6804 else if (self.hasFeature(.sse4_1))
...@@ -6846,11 +6827,11 @@ fn genBinOp(...@@ -6846,11 +6827,11 @@ fn genBinOp(
6846 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,6827 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
6847 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,6828 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
6848 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,6829 .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) {
6850 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .mins } else null,6831 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .mins } else null,
6851 .unsigned => if (self.hasFeature(.avx)) .{ .vp_d, .minu } else null,6832 .unsigned => if (self.hasFeature(.avx)) .{ .vp_d, .minu } else null,
6852 },6833 },
6853 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {6834 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
6854 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .maxs } else null,6835 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .maxs } else null,
6855 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .maxu } else null,6836 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .maxu } else null,
6856 },6837 },
...@@ -6858,7 +6839,7 @@ fn genBinOp(...@@ -6858,7 +6839,7 @@ fn genBinOp(
6858 },6839 },
6859 else => null,6840 else => null,
6860 },6841 },
6861 64 => switch (lhs_ty.vectorLen()) {6842 64 => switch (lhs_ty.vectorLen(mod)) {
6862 1...2 => switch (air_tag) {6843 1...2 => switch (air_tag) {
6863 .add,6844 .add,
6864 .addwrap,6845 .addwrap,
...@@ -6887,8 +6868,8 @@ fn genBinOp(...@@ -6887,8 +6868,8 @@ fn genBinOp(
6887 },6868 },
6888 else => null,6869 else => null,
6889 },6870 },
6890 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {6871 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
6891 16 => if (self.hasFeature(.f16c)) switch (lhs_ty.vectorLen()) {6872 16 => if (self.hasFeature(.f16c)) switch (lhs_ty.vectorLen(mod)) {
6892 1 => {6873 1 => {
6893 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();6874 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
6894 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6875 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
...@@ -7063,7 +7044,7 @@ fn genBinOp(...@@ -7063,7 +7044,7 @@ fn genBinOp(
7063 },7044 },
7064 else => null,7045 else => null,
7065 } else null,7046 } else null,
7066 32 => switch (lhs_ty.vectorLen()) {7047 32 => switch (lhs_ty.vectorLen(mod)) {
7067 1 => switch (air_tag) {7048 1 => switch (air_tag) {
7068 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },7049 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },
7069 .sub => if (self.hasFeature(.avx)) .{ .v_ss, .sub } else .{ ._ss, .sub },7050 .sub => if (self.hasFeature(.avx)) .{ .v_ss, .sub } else .{ ._ss, .sub },
...@@ -7101,7 +7082,7 @@ fn genBinOp(...@@ -7101,7 +7082,7 @@ fn genBinOp(
7101 } else null,7082 } else null,
7102 else => null,7083 else => null,
7103 },7084 },
7104 64 => switch (lhs_ty.vectorLen()) {7085 64 => switch (lhs_ty.vectorLen(mod)) {
7105 1 => switch (air_tag) {7086 1 => switch (air_tag) {
7106 .add => if (self.hasFeature(.avx)) .{ .v_sd, .add } else .{ ._sd, .add },7087 .add => if (self.hasFeature(.avx)) .{ .v_sd, .add } else .{ ._sd, .add },
7107 .sub => if (self.hasFeature(.avx)) .{ .v_sd, .sub } else .{ ._sd, .sub },7088 .sub => if (self.hasFeature(.avx)) .{ .v_sd, .sub } else .{ ._sd, .sub },
...@@ -7206,21 +7187,21 @@ fn genBinOp(...@@ -7206,21 +7187,21 @@ fn genBinOp(
7206 const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size);7187 const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size);
72077188
7208 try self.asmRegisterRegisterRegisterImmediate(7189 try self.asmRegisterRegisterRegisterImmediate(
7209 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {7190 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
7210 .Float => switch (lhs_ty.floatBits(self.target.*)) {7191 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7211 32 => .{ .v_ss, .cmp },7192 32 => .{ .v_ss, .cmp },
7212 64 => .{ .v_sd, .cmp },7193 64 => .{ .v_sd, .cmp },
7213 16, 80, 128 => null,7194 16, 80, 128 => null,
7214 else => unreachable,7195 else => unreachable,
7215 },7196 },
7216 .Vector => switch (lhs_ty.childType().zigTypeTag()) {7197 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7217 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {7198 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7218 32 => switch (lhs_ty.vectorLen()) {7199 32 => switch (lhs_ty.vectorLen(mod)) {
7219 1 => .{ .v_ss, .cmp },7200 1 => .{ .v_ss, .cmp },
7220 2...8 => .{ .v_ps, .cmp },7201 2...8 => .{ .v_ps, .cmp },
7221 else => null,7202 else => null,
7222 },7203 },
7223 64 => switch (lhs_ty.vectorLen()) {7204 64 => switch (lhs_ty.vectorLen(mod)) {
7224 1 => .{ .v_sd, .cmp },7205 1 => .{ .v_sd, .cmp },
7225 2...4 => .{ .v_pd, .cmp },7206 2...4 => .{ .v_pd, .cmp },
7226 else => null,7207 else => null,
...@@ -7240,20 +7221,20 @@ fn genBinOp(...@@ -7240,20 +7221,20 @@ fn genBinOp(
7240 Immediate.u(3), // unord7221 Immediate.u(3), // unord
7241 );7222 );
7242 try self.asmRegisterRegisterRegisterRegister(7223 try self.asmRegisterRegisterRegisterRegister(
7243 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {7224 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
7244 .Float => switch (lhs_ty.floatBits(self.target.*)) {7225 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7245 32 => .{ .v_ps, .blendv },7226 32 => .{ .v_ps, .blendv },
7246 64 => .{ .v_pd, .blendv },7227 64 => .{ .v_pd, .blendv },
7247 16, 80, 128 => null,7228 16, 80, 128 => null,
7248 else => unreachable,7229 else => unreachable,
7249 },7230 },
7250 .Vector => switch (lhs_ty.childType().zigTypeTag()) {7231 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7251 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {7232 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7252 32 => switch (lhs_ty.vectorLen()) {7233 32 => switch (lhs_ty.vectorLen(mod)) {
7253 1...8 => .{ .v_ps, .blendv },7234 1...8 => .{ .v_ps, .blendv },
7254 else => null,7235 else => null,
7255 },7236 },
7256 64 => switch (lhs_ty.vectorLen()) {7237 64 => switch (lhs_ty.vectorLen(mod)) {
7257 1...4 => .{ .v_pd, .blendv },7238 1...4 => .{ .v_pd, .blendv },
7258 else => null,7239 else => null,
7259 },7240 },
...@@ -7274,21 +7255,21 @@ fn genBinOp(...@@ -7274,21 +7255,21 @@ fn genBinOp(
7274 } else {7255 } else {
7275 const has_blend = self.hasFeature(.sse4_1);7256 const has_blend = self.hasFeature(.sse4_1);
7276 try self.asmRegisterRegisterImmediate(7257 try self.asmRegisterRegisterImmediate(
7277 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {7258 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
7278 .Float => switch (lhs_ty.floatBits(self.target.*)) {7259 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7279 32 => .{ ._ss, .cmp },7260 32 => .{ ._ss, .cmp },
7280 64 => .{ ._sd, .cmp },7261 64 => .{ ._sd, .cmp },
7281 16, 80, 128 => null,7262 16, 80, 128 => null,
7282 else => unreachable,7263 else => unreachable,
7283 },7264 },
7284 .Vector => switch (lhs_ty.childType().zigTypeTag()) {7265 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7285 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {7266 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7286 32 => switch (lhs_ty.vectorLen()) {7267 32 => switch (lhs_ty.vectorLen(mod)) {
7287 1 => .{ ._ss, .cmp },7268 1 => .{ ._ss, .cmp },
7288 2...4 => .{ ._ps, .cmp },7269 2...4 => .{ ._ps, .cmp },
7289 else => null,7270 else => null,
7290 },7271 },
7291 64 => switch (lhs_ty.vectorLen()) {7272 64 => switch (lhs_ty.vectorLen(mod)) {
7292 1 => .{ ._sd, .cmp },7273 1 => .{ ._sd, .cmp },
7293 2 => .{ ._pd, .cmp },7274 2 => .{ ._pd, .cmp },
7294 else => null,7275 else => null,
...@@ -7307,20 +7288,20 @@ fn genBinOp(...@@ -7307,20 +7288,20 @@ fn genBinOp(
7307 Immediate.u(if (has_blend) 3 else 7), // unord, ord7288 Immediate.u(if (has_blend) 3 else 7), // unord, ord
7308 );7289 );
7309 if (has_blend) try self.asmRegisterRegisterRegister(7290 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)) {
7311 .Float => switch (lhs_ty.floatBits(self.target.*)) {7292 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7312 32 => .{ ._ps, .blendv },7293 32 => .{ ._ps, .blendv },
7313 64 => .{ ._pd, .blendv },7294 64 => .{ ._pd, .blendv },
7314 16, 80, 128 => null,7295 16, 80, 128 => null,
7315 else => unreachable,7296 else => unreachable,
7316 },7297 },
7317 .Vector => switch (lhs_ty.childType().zigTypeTag()) {7298 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7318 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {7299 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7319 32 => switch (lhs_ty.vectorLen()) {7300 32 => switch (lhs_ty.vectorLen(mod)) {
7320 1...4 => .{ ._ps, .blendv },7301 1...4 => .{ ._ps, .blendv },
7321 else => null,7302 else => null,
7322 },7303 },
7323 64 => switch (lhs_ty.vectorLen()) {7304 64 => switch (lhs_ty.vectorLen(mod)) {
7324 1...2 => .{ ._pd, .blendv },7305 1...2 => .{ ._pd, .blendv },
7325 else => null,7306 else => null,
7326 },7307 },
...@@ -7338,20 +7319,20 @@ fn genBinOp(...@@ -7338,20 +7319,20 @@ fn genBinOp(
7338 mask_reg,7319 mask_reg,
7339 ) else {7320 ) else {
7340 try self.asmRegisterRegister(7321 try self.asmRegisterRegister(
7341 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {7322 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
7342 .Float => switch (lhs_ty.floatBits(self.target.*)) {7323 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7343 32 => .{ ._ps, .@"and" },7324 32 => .{ ._ps, .@"and" },
7344 64 => .{ ._pd, .@"and" },7325 64 => .{ ._pd, .@"and" },
7345 16, 80, 128 => null,7326 16, 80, 128 => null,
7346 else => unreachable,7327 else => unreachable,
7347 },7328 },
7348 .Vector => switch (lhs_ty.childType().zigTypeTag()) {7329 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7349 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {7330 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7350 32 => switch (lhs_ty.vectorLen()) {7331 32 => switch (lhs_ty.vectorLen(mod)) {
7351 1...4 => .{ ._ps, .@"and" },7332 1...4 => .{ ._ps, .@"and" },
7352 else => null,7333 else => null,
7353 },7334 },
7354 64 => switch (lhs_ty.vectorLen()) {7335 64 => switch (lhs_ty.vectorLen(mod)) {
7355 1...2 => .{ ._pd, .@"and" },7336 1...2 => .{ ._pd, .@"and" },
7356 else => null,7337 else => null,
7357 },7338 },
...@@ -7368,20 +7349,20 @@ fn genBinOp(...@@ -7368,20 +7349,20 @@ fn genBinOp(
7368 mask_reg,7349 mask_reg,
7369 );7350 );
7370 try self.asmRegisterRegister(7351 try self.asmRegisterRegister(
7371 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {7352 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
7372 .Float => switch (lhs_ty.floatBits(self.target.*)) {7353 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7373 32 => .{ ._ps, .andn },7354 32 => .{ ._ps, .andn },
7374 64 => .{ ._pd, .andn },7355 64 => .{ ._pd, .andn },
7375 16, 80, 128 => null,7356 16, 80, 128 => null,
7376 else => unreachable,7357 else => unreachable,
7377 },7358 },
7378 .Vector => switch (lhs_ty.childType().zigTypeTag()) {7359 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7379 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {7360 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7380 32 => switch (lhs_ty.vectorLen()) {7361 32 => switch (lhs_ty.vectorLen(mod)) {
7381 1...4 => .{ ._ps, .andn },7362 1...4 => .{ ._ps, .andn },
7382 else => null,7363 else => null,
7383 },7364 },
7384 64 => switch (lhs_ty.vectorLen()) {7365 64 => switch (lhs_ty.vectorLen(mod)) {
7385 1...2 => .{ ._pd, .andn },7366 1...2 => .{ ._pd, .andn },
7386 else => null,7367 else => null,
7387 },7368 },
...@@ -7398,20 +7379,20 @@ fn genBinOp(...@@ -7398,20 +7379,20 @@ fn genBinOp(
7398 lhs_copy_reg.?,7379 lhs_copy_reg.?,
7399 );7380 );
7400 try self.asmRegisterRegister(7381 try self.asmRegisterRegister(
7401 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {7382 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
7402 .Float => switch (lhs_ty.floatBits(self.target.*)) {7383 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7403 32 => .{ ._ps, .@"or" },7384 32 => .{ ._ps, .@"or" },
7404 64 => .{ ._pd, .@"or" },7385 64 => .{ ._pd, .@"or" },
7405 16, 80, 128 => null,7386 16, 80, 128 => null,
7406 else => unreachable,7387 else => unreachable,
7407 },7388 },
7408 .Vector => switch (lhs_ty.childType().zigTypeTag()) {7389 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7409 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {7390 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7410 32 => switch (lhs_ty.vectorLen()) {7391 32 => switch (lhs_ty.vectorLen(mod)) {
7411 1...4 => .{ ._ps, .@"or" },7392 1...4 => .{ ._ps, .@"or" },
7412 else => null,7393 else => null,
7413 },7394 },
7414 64 => switch (lhs_ty.vectorLen()) {7395 64 => switch (lhs_ty.vectorLen(mod)) {
7415 1...2 => .{ ._pd, .@"or" },7396 1...2 => .{ ._pd, .@"or" },
7416 else => null,7397 else => null,
7417 },7398 },
...@@ -7442,7 +7423,8 @@ fn genBinOpMir(...@@ -7442,7 +7423,8 @@ fn genBinOpMir(
7442 dst_mcv: MCValue,7423 dst_mcv: MCValue,
7443 src_mcv: MCValue,7424 src_mcv: MCValue,
7444) !void {7425) !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));
7446 switch (dst_mcv) {7428 switch (dst_mcv) {
7447 .none,7429 .none,
7448 .unreach,7430 .unreach,
...@@ -7562,11 +7544,7 @@ fn genBinOpMir(...@@ -7562,11 +7544,7 @@ fn genBinOpMir(
7562 .load_got,7544 .load_got,
7563 .load_tlv,7545 .load_tlv,
7564 => {7546 => {
7565 var ptr_pl = Type.Payload.ElemType{7547 const ptr_ty = try mod.singleConstPtrType(ty);
7566 .base = .{ .tag = .single_const_pointer },
7567 .data = ty,
7568 };
7569 const ptr_ty = Type.initPayload(&ptr_pl.base);
7570 const addr_reg = try self.copyToTmpRegister(ptr_ty, src_mcv.address());7548 const addr_reg = try self.copyToTmpRegister(ptr_ty, src_mcv.address());
7571 return self.genBinOpMir(mir_tag, ty, dst_mcv, .{7549 return self.genBinOpMir(mir_tag, ty, dst_mcv, .{
7572 .indirect = .{ .reg = addr_reg },7550 .indirect = .{ .reg = addr_reg },
...@@ -7640,7 +7618,7 @@ fn genBinOpMir(...@@ -7640,7 +7618,7 @@ fn genBinOpMir(
7640 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);7618 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
76417619
7642 const ty_signedness =7620 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;
7644 const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) {7622 const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) {
7645 .signed => Type.usize,7623 .signed => Type.usize,
7646 .unsigned => Type.isize,7624 .unsigned => Type.isize,
...@@ -7796,7 +7774,8 @@ fn genBinOpMir(...@@ -7796,7 +7774,8 @@ fn genBinOpMir(
7796/// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv.7774/// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv.
7797/// Does not support byte-size operands.7775/// Does not support byte-size operands.
7798fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {7776fn 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));
7800 switch (dst_mcv) {7779 switch (dst_mcv) {
7801 .none,7780 .none,
7802 .unreach,7781 .unreach,
...@@ -7896,6 +7875,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -7896,6 +7875,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
7896}7875}
78977876
7898fn airArg(self: *Self, inst: Air.Inst.Index) !void {7877fn airArg(self: *Self, inst: Air.Inst.Index) !void {
7878 const mod = self.bin_file.options.module.?;
7899 // skip zero-bit arguments as they don't have a corresponding arg instruction7879 // skip zero-bit arguments as they don't have a corresponding arg instruction
7900 var arg_index = self.arg_index;7880 var arg_index = self.arg_index;
7901 while (self.args[arg_index] == .none) arg_index += 1;7881 while (self.args[arg_index] == .none) arg_index += 1;
...@@ -7909,9 +7889,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -7909,9 +7889,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
7909 else => return self.fail("TODO implement arg for {}", .{dst_mcv}),7889 else => return self.fail("TODO implement arg for {}", .{dst_mcv}),
7910 }7890 }
79117891
7912 const ty = self.air.typeOfIndex(inst);7892 const ty = self.typeOfIndex(inst);
7913 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;7893 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);
7915 try self.genArgDbgInfo(ty, name, dst_mcv);7895 try self.genArgDbgInfo(ty, name, dst_mcv);
79167896
7917 break :result dst_mcv;7897 break :result dst_mcv;
...@@ -7920,6 +7900,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -7920,6 +7900,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
7920}7900}
79217901
7922fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {7902fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
7903 const mod = self.bin_file.options.module.?;
7923 switch (self.debug_output) {7904 switch (self.debug_output) {
7924 .dwarf => |dw| {7905 .dwarf => |dw| {
7925 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {7906 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 {...@@ -7938,7 +7919,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
7938 // TODO: this might need adjusting like the linkers do.7919 // TODO: this might need adjusting like the linkers do.
7939 // Instead of flattening the owner and passing Decl.Index here we may7920 // Instead of flattening the owner and passing Decl.Index here we may
7940 // want to special case LazySymbol in DWARF linker too.7921 // 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);
7942 },7923 },
7943 .plan9 => {},7924 .plan9 => {},
7944 .none => {},7925 .none => {},
...@@ -7952,6 +7933,7 @@ fn genVarDbgInfo(...@@ -7952,6 +7933,7 @@ fn genVarDbgInfo(
7952 mcv: MCValue,7933 mcv: MCValue,
7953 name: [:0]const u8,7934 name: [:0]const u8,
7954) !void {7935) !void {
7936 const mod = self.bin_file.options.module.?;
7955 const is_ptr = switch (tag) {7937 const is_ptr = switch (tag) {
7956 .dbg_var_ptr => true,7938 .dbg_var_ptr => true,
7957 .dbg_var_val => false,7939 .dbg_var_val => false,
...@@ -7982,7 +7964,7 @@ fn genVarDbgInfo(...@@ -7982,7 +7964,7 @@ fn genVarDbgInfo(
7982 // TODO: this might need adjusting like the linkers do.7964 // TODO: this might need adjusting like the linkers do.
7983 // Instead of flattening the owner and passing Decl.Index here we may7965 // Instead of flattening the owner and passing Decl.Index here we may
7984 // want to special case LazySymbol in DWARF linker too.7966 // 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);
7986 },7968 },
7987 .plan9 => {},7969 .plan9 => {},
7988 .none => {},7970 .none => {},
...@@ -8022,20 +8004,23 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {...@@ -8022,20 +8004,23 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {
8022}8004}
80238005
8024fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {8006fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
8007 const mod = self.bin_file.options.module.?;
8025 if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{});8008 if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{});
8026 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8009 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8027 const callee = pl_op.operand;8010 const callee = pl_op.operand;
8028 const extra = self.air.extraData(Air.Call, pl_op.payload);8011 const extra = self.air.extraData(Air.Call, pl_op.payload);
8029 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);8012 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)) {
8033 .Fn => ty,8016 .Fn => ty,
8034 .Pointer => ty.childType(),8017 .Pointer => ty.childType(mod),
8035 else => unreachable,8018 else => unreachable,
8036 };8019 };
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);
8039 defer info.deinit(self);8024 defer info.deinit(self);
80408025
8041 // We need a properly aligned and sized call frame to be able to call this function.8026 // 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...@@ -8062,7 +8047,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8062 else => unreachable,8047 else => unreachable,
8063 }8048 }
8064 for (args, info.args) |arg, mc_arg| {8049 for (args, info.args) |arg, mc_arg| {
8065 const arg_ty = self.air.typeOf(arg);8050 const arg_ty = self.typeOf(arg);
8066 const arg_mcv = try self.resolveInst(arg);8051 const arg_mcv = try self.resolveInst(arg);
8067 switch (mc_arg) {8052 switch (mc_arg) {
8068 .none => {},8053 .none => {},
...@@ -8076,8 +8061,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8076,8 +8061,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8076 const ret_lock = switch (info.return_value.long) {8061 const ret_lock = switch (info.return_value.long) {
8077 .none, .unreach => null,8062 .none, .unreach => null,
8078 .indirect => |reg_off| lock: {8063 .indirect => |reg_off| lock: {
8079 const ret_ty = fn_ty.fnReturnType();8064 const ret_ty = fn_info.return_type.toType();
8080 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, self.target.*));8065 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
8081 try self.genSetReg(reg_off.reg, Type.usize, .{8066 try self.genSetReg(reg_off.reg, Type.usize, .{
8082 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },8067 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
8083 });8068 });
...@@ -8089,7 +8074,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8089,7 +8074,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8089 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);8074 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);
80908075
8091 for (args, info.args) |arg, mc_arg| {8076 for (args, info.args) |arg, mc_arg| {
8092 const arg_ty = self.air.typeOf(arg);8077 const arg_ty = self.typeOf(arg);
8093 const arg_mcv = try self.resolveInst(arg);8078 const arg_mcv = try self.resolveInst(arg);
8094 switch (mc_arg) {8079 switch (mc_arg) {
8095 .none, .load_frame => {},8080 .none, .load_frame => {},
...@@ -8100,15 +8085,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8100,15 +8085,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81008085
8101 // Due to incremental compilation, how function calls are generated depends8086 // Due to incremental compilation, how function calls are generated depends
8102 // on linking.8087 // on linking.
8103 const mod = self.bin_file.options.module.?;8088 if (try self.air.value(callee, mod)) |func_value| {
8104 if (self.air.value(callee)) |func_value| {8089 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8105 if (if (func_value.castTag(.function)) |func_payload|8090 if (switch (func_key) {
8106 func_payload.data.owner_decl8091 .func => |func| mod.funcPtr(func.index).owner_decl,
8107 else if (func_value.castTag(.decl_ref)) |decl_ref_payload|8092 .ptr => |ptr| switch (ptr.addr) {
8108 decl_ref_payload.data8093 .decl => |decl| decl,
8109 else8094 else => null,
8110 null) |owner_decl|8095 },
8111 {8096 else => null,
8097 }) |owner_decl| {
8112 if (self.bin_file.cast(link.File.Elf)) |elf_file| {8098 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8113 const atom_index = try elf_file.getOrCreateAtomForDecl(owner_decl);8099 const atom_index = try elf_file.getOrCreateAtomForDecl(owner_decl);
8114 const atom = elf_file.getAtom(atom_index);8100 const atom = elf_file.getAtom(atom_index);
...@@ -8141,10 +8127,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8141,10 +8127,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8141 .disp = @intCast(i32, fn_got_addr),8127 .disp = @intCast(i32, fn_got_addr),
8142 }));8128 }));
8143 } else unreachable;8129 } else unreachable;
8144 } else if (func_value.castTag(.extern_fn)) |func_payload| {8130 } else if (func_value.getExternFunc(mod)) |extern_func| {
8145 const extern_fn = func_payload.data;8131 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
8146 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);8132 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
8147 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
8148 if (self.bin_file.cast(link.File.Coff)) |coff_file| {8133 if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8149 const atom_index = try self.owner.getSymbolIndex(self);8134 const atom_index = try self.owner.getSymbolIndex(self);
8150 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);8135 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...@@ -8178,7 +8163,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8178 return self.fail("TODO implement calling bitcasted functions", .{});8163 return self.fail("TODO implement calling bitcasted functions", .{});
8179 }8164 }
8180 } else {8165 } else {
8181 assert(ty.zigTypeTag() == .Pointer);8166 assert(ty.zigTypeTag(mod) == .Pointer);
8182 const mcv = try self.resolveInst(callee);8167 const mcv = try self.resolveInst(callee);
8183 try self.genSetReg(.rax, Type.usize, mcv);8168 try self.genSetReg(.rax, Type.usize, mcv);
8184 try self.asmRegister(.{ ._, .call }, .rax);8169 try self.asmRegister(.{ ._, .call }, .rax);
...@@ -8193,9 +8178,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8193,9 +8178,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8193}8178}
81948179
8195fn airRet(self: *Self, inst: Air.Inst.Index) !void {8180fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8181 const mod = self.bin_file.options.module.?;
8196 const un_op = self.air.instructions.items(.data)[inst].un_op;8182 const un_op = self.air.instructions.items(.data)[inst].un_op;
8197 const operand = try self.resolveInst(un_op);8183 const operand = try self.resolveInst(un_op);
8198 const ret_ty = self.fn_type.fnReturnType();8184 const ret_ty = self.fn_type.fnReturnType(mod);
8199 switch (self.ret_mcv.short) {8185 switch (self.ret_mcv.short) {
8200 .none => {},8186 .none => {},
8201 .register => try self.genCopy(ret_ty, self.ret_mcv.short, operand),8187 .register => try self.genCopy(ret_ty, self.ret_mcv.short, operand),
...@@ -8219,7 +8205,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -8219,7 +8205,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8219fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {8205fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
8220 const un_op = self.air.instructions.items(.data)[inst].un_op;8206 const un_op = self.air.instructions.items(.data)[inst].un_op;
8221 const ptr = try self.resolveInst(un_op);8207 const ptr = try self.resolveInst(un_op);
8222 const ptr_ty = self.air.typeOf(un_op);8208 const ptr_ty = self.typeOf(un_op);
8223 switch (self.ret_mcv.short) {8209 switch (self.ret_mcv.short) {
8224 .none => {},8210 .none => {},
8225 .register => try self.load(self.ret_mcv.short, ptr_ty, ptr),8211 .register => try self.load(self.ret_mcv.short, ptr_ty, ptr),
...@@ -8234,8 +8220,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -8234,8 +8220,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
8234}8220}
82358221
8236fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {8222fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8223 const mod = self.bin_file.options.module.?;
8237 const bin_op = self.air.instructions.items(.data)[inst].bin_op;8224 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
8240 try self.spillEflagsIfOccupied();8227 try self.spillEflagsIfOccupied();
8241 self.eflags_inst = inst;8228 self.eflags_inst = inst;
...@@ -8255,9 +8242,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8255,9 +8242,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8255 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);8242 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
82568243
8257 const result = MCValue{8244 const result = MCValue{
8258 .eflags = switch (ty.zigTypeTag()) {8245 .eflags = switch (ty.zigTypeTag(mod)) {
8259 else => result: {8246 else => result: {
8260 const abi_size = @intCast(u16, ty.abiSize(self.target.*));8247 const abi_size = @intCast(u16, ty.abiSize(mod));
8261 const may_flip: enum {8248 const may_flip: enum {
8262 may_flip,8249 may_flip,
8263 must_flip,8250 must_flip,
...@@ -8290,7 +8277,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8290,7 +8277,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8290 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);8277 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
82918278
8292 break :result Condition.fromCompareOperator(8279 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,
8294 result_op: {8281 result_op: {
8295 const flipped_op = if (flipped) op.reverse() else op;8282 const flipped_op = if (flipped) op.reverse() else op;
8296 if (abi_size > 8) switch (flipped_op) {8283 if (abi_size > 8) switch (flipped_op) {
...@@ -8404,7 +8391,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8404,7 +8391,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8404 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);8391 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);
8405 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);8392 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);
8406 } else return self.fail("TODO implement airCmp for {}", .{8393 } else return self.fail("TODO implement airCmp for {}", .{
8407 ty.fmt(self.bin_file.options.module.?),8394 ty.fmt(mod),
8408 }),8395 }),
8409 32 => try self.genBinOpMir(8396 32 => try self.genBinOpMir(
8410 .{ ._ss, .ucomi },8397 .{ ._ss, .ucomi },
...@@ -8419,7 +8406,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8419,7 +8406,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8419 src_mcv,8406 src_mcv,
8420 ),8407 ),
8421 else => return self.fail("TODO implement airCmp for {}", .{8408 else => return self.fail("TODO implement airCmp for {}", .{
8422 ty.fmt(self.bin_file.options.module.?),8409 ty.fmt(mod),
8423 }),8410 }),
8424 }8411 }
84258412
...@@ -8453,8 +8440,8 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -8453,8 +8440,8 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
8453 try self.spillEflagsIfOccupied();8440 try self.spillEflagsIfOccupied();
8454 self.eflags_inst = inst;8441 self.eflags_inst = inst;
84558442
8456 const op_ty = self.air.typeOf(un_op);8443 const op_ty = self.typeOf(un_op);
8457 const op_abi_size = @intCast(u32, op_ty.abiSize(self.target.*));8444 const op_abi_size = @intCast(u32, op_ty.abiSize(mod));
8458 const op_mcv = try self.resolveInst(un_op);8445 const op_mcv = try self.resolveInst(un_op);
8459 const dst_reg = switch (op_mcv) {8446 const dst_reg = switch (op_mcv) {
8460 .register => |reg| reg,8447 .register => |reg| reg,
...@@ -8473,16 +8460,17 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {...@@ -8473,16 +8460,17 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
8473 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8460 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8474 const extra = self.air.extraData(Air.Try, pl_op.payload);8461 const extra = self.air.extraData(Air.Try, pl_op.payload);
8475 const body = self.air.extra[extra.end..][0..extra.data.body_len];8462 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);
8477 const result = try self.genTry(inst, pl_op.operand, body, err_union_ty, false);8464 const result = try self.genTry(inst, pl_op.operand, body, err_union_ty, false);
8478 return self.finishAir(inst, result, .{ .none, .none, .none });8465 return self.finishAir(inst, result, .{ .none, .none, .none });
8479}8466}
84808467
8481fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {8468fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
8469 const mod = self.bin_file.options.module.?;
8482 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8470 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
8483 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);8471 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
8484 const body = self.air.extra[extra.end..][0..extra.data.body_len];8472 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);
8486 const result = try self.genTry(inst, extra.data.ptr, body, err_union_ty, true);8474 const result = try self.genTry(inst, extra.data.ptr, body, err_union_ty, true);
8487 return self.finishAir(inst, result, .{ .none, .none, .none });8475 return self.finishAir(inst, result, .{ .none, .none, .none });
8488}8476}
...@@ -8546,8 +8534,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -8546,8 +8534,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
8546}8534}
85478535
8548fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {8536fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
8549 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8537 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
8550 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;8538 const mod = self.bin_file.options.module.?;
8539 const function = mod.funcPtr(ty_fn.func);
8551 // TODO emit debug info for function change8540 // TODO emit debug info for function change
8552 _ = function;8541 _ = function;
8553 return self.finishAir(inst, .unreach, .{ .none, .none, .none });8542 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
...@@ -8561,7 +8550,7 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -8561,7 +8550,7 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
8561fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {8550fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
8562 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8551 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8563 const operand = pl_op.operand;8552 const operand = pl_op.operand;
8564 const ty = self.air.typeOf(operand);8553 const ty = self.typeOf(operand);
8565 const mcv = try self.resolveInst(operand);8554 const mcv = try self.resolveInst(operand);
85668555
8567 const name = self.air.nullTerminatedString(pl_op.payload);8556 const name = self.air.nullTerminatedString(pl_op.payload);
...@@ -8573,7 +8562,8 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -8573,7 +8562,8 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
8573}8562}
85748563
8575fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {8564fn 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);
8577 switch (mcv) {8567 switch (mcv) {
8578 .eflags => |cc| {8568 .eflags => |cc| {
8579 // Here we map the opposites since the jump is to the false branch.8569 // 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 {...@@ -8602,7 +8592,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
8602fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {8592fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
8603 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8593 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8604 const cond = try self.resolveInst(pl_op.operand);8594 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);
8606 const extra = self.air.extraData(Air.CondBr, pl_op.payload);8596 const extra = self.air.extraData(Air.CondBr, pl_op.payload);
8607 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];8597 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
8608 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];8598 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 {...@@ -8646,6 +8636,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
8646}8636}
86478637
8648fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue {8638fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue {
8639 const mod = self.bin_file.options.module.?;
8649 switch (opt_mcv) {8640 switch (opt_mcv) {
8650 .register_overflow => |ro| return .{ .eflags = ro.eflags.negate() },8641 .register_overflow => |ro| return .{ .eflags = ro.eflags.negate() },
8651 else => {},8642 else => {},
...@@ -8654,14 +8645,12 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -8654,14 +8645,12 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8654 try self.spillEflagsIfOccupied();8645 try self.spillEflagsIfOccupied();
8655 self.eflags_inst = inst;8646 self.eflags_inst = inst;
86568647
8657 var pl_buf: Type.Payload.ElemType = undefined;8648 const pl_ty = opt_ty.optionalChild(mod);
8658 const pl_ty = opt_ty.optionalChild(&pl_buf);
86598649
8660 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;8650 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod))
8661 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload())8651 .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty }
8662 .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
8663 else8652 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
8666 switch (opt_mcv) {8655 switch (opt_mcv) {
8667 .none,8656 .none,
...@@ -8681,14 +8670,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -8681,14 +8670,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
86818670
8682 .register => |opt_reg| {8671 .register => |opt_reg| {
8683 if (some_info.off == 0) {8672 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));
8685 const alias_reg = registerAlias(opt_reg, some_abi_size);8674 const alias_reg = registerAlias(opt_reg, some_abi_size);
8686 assert(some_abi_size * 8 == alias_reg.bitSize());8675 assert(some_abi_size * 8 == alias_reg.bitSize());
8687 try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg);8676 try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg);
8688 return .{ .eflags = .z };8677 return .{ .eflags = .z };
8689 }8678 }
8690 assert(some_info.ty.tag() == .bool);8679 assert(some_info.ty.ip_index == .bool_type);
8691 const opt_abi_size = @intCast(u32, opt_ty.abiSize(self.target.*));8680 const opt_abi_size = @intCast(u32, opt_ty.abiSize(mod));
8692 try self.asmRegisterImmediate(8681 try self.asmRegisterImmediate(
8693 .{ ._, .bt },8682 .{ ._, .bt },
8694 registerAlias(opt_reg, opt_abi_size),8683 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...@@ -8707,7 +8696,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8707 defer self.register_manager.unlockReg(addr_reg_lock);8696 defer self.register_manager.unlockReg(addr_reg_lock);
87088697
8709 try self.genSetReg(addr_reg, Type.usize, opt_mcv.address());8698 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));
8711 try self.asmMemoryImmediate(8700 try self.asmMemoryImmediate(
8712 .{ ._, .cmp },8701 .{ ._, .cmp },
8713 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{8702 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...@@ -8720,7 +8709,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8720 },8709 },
87218710
8722 .indirect, .load_frame => {8711 .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));
8724 try self.asmMemoryImmediate(8713 try self.asmMemoryImmediate(
8725 .{ ._, .cmp },8714 .{ ._, .cmp },
8726 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), switch (opt_mcv) {8715 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...@@ -8742,18 +8731,17 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8742}8731}
87438732
8744fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {8733fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {
8734 const mod = self.bin_file.options.module.?;
8745 try self.spillEflagsIfOccupied();8735 try self.spillEflagsIfOccupied();
8746 self.eflags_inst = inst;8736 self.eflags_inst = inst;
87478737
8748 const opt_ty = ptr_ty.childType();8738 const opt_ty = ptr_ty.childType(mod);
8749 var pl_buf: Type.Payload.ElemType = undefined;8739 const pl_ty = opt_ty.optionalChild(mod);
8750 const pl_ty = opt_ty.optionalChild(&pl_buf);
87518740
8752 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;8741 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod))
8753 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload())8742 .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty }
8754 .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
8755 else8743 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
8758 const ptr_reg = switch (ptr_mcv) {8746 const ptr_reg = switch (ptr_mcv) {
8759 .register => |reg| reg,8747 .register => |reg| reg,
...@@ -8762,7 +8750,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)...@@ -8762,7 +8750,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
8762 const ptr_lock = self.register_manager.lockReg(ptr_reg);8750 const ptr_lock = self.register_manager.lockReg(ptr_reg);
8763 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);8751 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));
8766 try self.asmMemoryImmediate(8754 try self.asmMemoryImmediate(
8767 .{ ._, .cmp },8755 .{ ._, .cmp },
8768 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{8756 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)...@@ -8775,9 +8763,10 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
8775}8763}
87768764
8777fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {8765fn 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)) {
8781 return MCValue{ .immediate = 0 }; // always false8770 return MCValue{ .immediate = 0 }; // always false
8782 }8771 }
87838772
...@@ -8786,7 +8775,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !...@@ -8786,7 +8775,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
8786 self.eflags_inst = inst;8775 self.eflags_inst = inst;
8787 }8776 }
87888777
8789 const err_off = errUnionErrorOffset(ty.errorUnionPayload(), self.target.*);8778 const err_off = errUnionErrorOffset(ty.errorUnionPayload(mod), mod);
8790 switch (operand) {8779 switch (operand) {
8791 .register => |reg| {8780 .register => |reg| {
8792 const eu_lock = self.register_manager.lockReg(reg);8781 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...@@ -8844,7 +8833,7 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCVa
8844fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {8833fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
8845 const un_op = self.air.instructions.items(.data)[inst].un_op;8834 const un_op = self.air.instructions.items(.data)[inst].un_op;
8846 const operand = try self.resolveInst(un_op);8835 const operand = try self.resolveInst(un_op);
8847 const ty = self.air.typeOf(un_op);8836 const ty = self.typeOf(un_op);
8848 const result = try self.isNull(inst, ty, operand);8837 const result = try self.isNull(inst, ty, operand);
8849 return self.finishAir(inst, result, .{ un_op, .none, .none });8838 return self.finishAir(inst, result, .{ un_op, .none, .none });
8850}8839}
...@@ -8852,7 +8841,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -8852,7 +8841,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
8852fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {8841fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
8853 const un_op = self.air.instructions.items(.data)[inst].un_op;8842 const un_op = self.air.instructions.items(.data)[inst].un_op;
8854 const operand = try self.resolveInst(un_op);8843 const operand = try self.resolveInst(un_op);
8855 const ty = self.air.typeOf(un_op);8844 const ty = self.typeOf(un_op);
8856 const result = try self.isNullPtr(inst, ty, operand);8845 const result = try self.isNullPtr(inst, ty, operand);
8857 return self.finishAir(inst, result, .{ un_op, .none, .none });8846 return self.finishAir(inst, result, .{ un_op, .none, .none });
8858}8847}
...@@ -8860,7 +8849,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -8860,7 +8849,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
8860fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {8849fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
8861 const un_op = self.air.instructions.items(.data)[inst].un_op;8850 const un_op = self.air.instructions.items(.data)[inst].un_op;
8862 const operand = try self.resolveInst(un_op);8851 const operand = try self.resolveInst(un_op);
8863 const ty = self.air.typeOf(un_op);8852 const ty = self.typeOf(un_op);
8864 const result = switch (try self.isNull(inst, ty, operand)) {8853 const result = switch (try self.isNull(inst, ty, operand)) {
8865 .eflags => |cc| .{ .eflags = cc.negate() },8854 .eflags => |cc| .{ .eflags = cc.negate() },
8866 else => unreachable,8855 else => unreachable,
...@@ -8871,7 +8860,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -8871,7 +8860,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
8871fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {8860fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
8872 const un_op = self.air.instructions.items(.data)[inst].un_op;8861 const un_op = self.air.instructions.items(.data)[inst].un_op;
8873 const operand = try self.resolveInst(un_op);8862 const operand = try self.resolveInst(un_op);
8874 const ty = self.air.typeOf(un_op);8863 const ty = self.typeOf(un_op);
8875 const result = switch (try self.isNullPtr(inst, ty, operand)) {8864 const result = switch (try self.isNullPtr(inst, ty, operand)) {
8876 .eflags => |cc| .{ .eflags = cc.negate() },8865 .eflags => |cc| .{ .eflags = cc.negate() },
8877 else => unreachable,8866 else => unreachable,
...@@ -8882,12 +8871,13 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -8882,12 +8871,13 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
8882fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {8871fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
8883 const un_op = self.air.instructions.items(.data)[inst].un_op;8872 const un_op = self.air.instructions.items(.data)[inst].un_op;
8884 const operand = try self.resolveInst(un_op);8873 const operand = try self.resolveInst(un_op);
8885 const ty = self.air.typeOf(un_op);8874 const ty = self.typeOf(un_op);
8886 const result = try self.isErr(inst, ty, operand);8875 const result = try self.isErr(inst, ty, operand);
8887 return self.finishAir(inst, result, .{ un_op, .none, .none });8876 return self.finishAir(inst, result, .{ un_op, .none, .none });
8888}8877}
88898878
8890fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {8879fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
8880 const mod = self.bin_file.options.module.?;
8891 const un_op = self.air.instructions.items(.data)[inst].un_op;8881 const un_op = self.air.instructions.items(.data)[inst].un_op;
88928882
8893 const operand_ptr = try self.resolveInst(un_op);8883 const operand_ptr = try self.resolveInst(un_op);
...@@ -8905,10 +8895,10 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -8905,10 +8895,10 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
8905 break :blk try self.allocRegOrMem(inst, true);8895 break :blk try self.allocRegOrMem(inst, true);
8906 }8896 }
8907 };8897 };
8908 const ptr_ty = self.air.typeOf(un_op);8898 const ptr_ty = self.typeOf(un_op);
8909 try self.load(operand, ptr_ty, operand_ptr);8899 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
8913 return self.finishAir(inst, result, .{ un_op, .none, .none });8903 return self.finishAir(inst, result, .{ un_op, .none, .none });
8914}8904}
...@@ -8916,12 +8906,13 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -8916,12 +8906,13 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
8916fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {8906fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
8917 const un_op = self.air.instructions.items(.data)[inst].un_op;8907 const un_op = self.air.instructions.items(.data)[inst].un_op;
8918 const operand = try self.resolveInst(un_op);8908 const operand = try self.resolveInst(un_op);
8919 const ty = self.air.typeOf(un_op);8909 const ty = self.typeOf(un_op);
8920 const result = try self.isNonErr(inst, ty, operand);8910 const result = try self.isNonErr(inst, ty, operand);
8921 return self.finishAir(inst, result, .{ un_op, .none, .none });8911 return self.finishAir(inst, result, .{ un_op, .none, .none });
8922}8912}
89238913
8924fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {8914fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
8915 const mod = self.bin_file.options.module.?;
8925 const un_op = self.air.instructions.items(.data)[inst].un_op;8916 const un_op = self.air.instructions.items(.data)[inst].un_op;
89268917
8927 const operand_ptr = try self.resolveInst(un_op);8918 const operand_ptr = try self.resolveInst(un_op);
...@@ -8939,10 +8930,10 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -8939,10 +8930,10 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
8939 break :blk try self.allocRegOrMem(inst, true);8930 break :blk try self.allocRegOrMem(inst, true);
8940 }8931 }
8941 };8932 };
8942 const ptr_ty = self.air.typeOf(un_op);8933 const ptr_ty = self.typeOf(un_op);
8943 try self.load(operand, ptr_ty, operand_ptr);8934 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
8947 return self.finishAir(inst, result, .{ un_op, .none, .none });8938 return self.finishAir(inst, result, .{ un_op, .none, .none });
8948}8939}
...@@ -9005,7 +8996,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -9005,7 +8996,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
9005fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {8996fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
9006 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8997 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
9007 const condition = try self.resolveInst(pl_op.operand);8998 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);
9009 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);9000 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
9010 var extra_index: usize = switch_br.end;9001 var extra_index: usize = switch_br.end;
9011 var case_i: u32 = 0;9002 var case_i: u32 = 0;
...@@ -9088,12 +9079,13 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {...@@ -9088,12 +9079,13 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {
9088}9079}
90899080
9090fn airBr(self: *Self, inst: Air.Inst.Index) !void {9081fn airBr(self: *Self, inst: Air.Inst.Index) !void {
9082 const mod = self.bin_file.options.module.?;
9091 const br = self.air.instructions.items(.data)[inst].br;9083 const br = self.air.instructions.items(.data)[inst].br;
9092 const src_mcv = try self.resolveInst(br.operand);9084 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);
9095 const block_unused =9087 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);
9097 const block_tracking = self.inst_tracking.getPtr(br.block_inst).?;9089 const block_tracking = self.inst_tracking.getPtr(br.block_inst).?;
9098 const block_data = self.blocks.getPtr(br.block_inst).?;9090 const block_data = self.blocks.getPtr(br.block_inst).?;
9099 const first_br = block_data.relocs.items.len == 0;9091 const first_br = block_data.relocs.items.len == 0;
...@@ -9216,7 +9208,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9216,7 +9208,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
92169208
9217 const arg_mcv = try self.resolveInst(input);9209 const arg_mcv = try self.resolveInst(input);
9218 try self.register_manager.getReg(reg, null);9210 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);
9220 }9212 }
92219213
9222 {9214 {
...@@ -9402,7 +9394,8 @@ const MoveStrategy = union(enum) {...@@ -9402,7 +9394,8 @@ const MoveStrategy = union(enum) {
9402 };9394 };
9403};9395};
9404fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {9396fn 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)) {
9406 else => return .{ .move = .{ ._, .mov } },9399 else => return .{ .move = .{ ._, .mov } },
9407 .Float => switch (ty.floatBits(self.target.*)) {9400 .Float => switch (ty.floatBits(self.target.*)) {
9408 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{9401 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
...@@ -9419,9 +9412,9 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9419,9 +9412,9 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9419 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },9412 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
9420 else => {},9413 else => {},
9421 },9414 },
9422 .Vector => switch (ty.childType().zigTypeTag()) {9415 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
9423 .Int => switch (ty.childType().intInfo(self.target.*).bits) {9416 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
9424 8 => switch (ty.vectorLen()) {9417 8 => switch (ty.vectorLen(mod)) {
9425 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{9418 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
9426 .insert = .{ .vp_b, .insr },9419 .insert = .{ .vp_b, .insr },
9427 .extract = .{ .vp_b, .extr },9420 .extract = .{ .vp_b, .extr },
...@@ -9451,7 +9444,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9451,7 +9444,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9451 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },9444 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9452 else => {},9445 else => {},
9453 },9446 },
9454 16 => switch (ty.vectorLen()) {9447 16 => switch (ty.vectorLen(mod)) {
9455 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{9448 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
9456 .insert = .{ .vp_w, .insr },9449 .insert = .{ .vp_w, .insr },
9457 .extract = .{ .vp_w, .extr },9450 .extract = .{ .vp_w, .extr },
...@@ -9474,7 +9467,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9474,7 +9467,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9474 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },9467 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9475 else => {},9468 else => {},
9476 },9469 },
9477 32 => switch (ty.vectorLen()) {9470 32 => switch (ty.vectorLen(mod)) {
9478 1 => return .{ .move = if (self.hasFeature(.avx))9471 1 => return .{ .move = if (self.hasFeature(.avx))
9479 .{ .v_d, .mov }9472 .{ .v_d, .mov }
9480 else9473 else
...@@ -9490,7 +9483,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9490,7 +9483,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9490 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },9483 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9491 else => {},9484 else => {},
9492 },9485 },
9493 64 => switch (ty.vectorLen()) {9486 64 => switch (ty.vectorLen(mod)) {
9494 1 => return .{ .move = if (self.hasFeature(.avx))9487 1 => return .{ .move = if (self.hasFeature(.avx))
9495 .{ .v_q, .mov }9488 .{ .v_q, .mov }
9496 else9489 else
...@@ -9502,7 +9495,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9502,7 +9495,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9502 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },9495 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9503 else => {},9496 else => {},
9504 },9497 },
9505 128 => switch (ty.vectorLen()) {9498 128 => switch (ty.vectorLen(mod)) {
9506 1 => return .{ .move = if (self.hasFeature(.avx))9499 1 => return .{ .move = if (self.hasFeature(.avx))
9507 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }9500 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9508 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },9501 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
...@@ -9510,15 +9503,15 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9510,15 +9503,15 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9510 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },9503 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9511 else => {},9504 else => {},
9512 },9505 },
9513 256 => switch (ty.vectorLen()) {9506 256 => switch (ty.vectorLen(mod)) {
9514 1 => if (self.hasFeature(.avx))9507 1 => if (self.hasFeature(.avx))
9515 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },9508 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9516 else => {},9509 else => {},
9517 },9510 },
9518 else => {},9511 else => {},
9519 },9512 },
9520 .Float => switch (ty.childType().floatBits(self.target.*)) {9513 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
9521 16 => switch (ty.vectorLen()) {9514 16 => switch (ty.vectorLen(mod)) {
9522 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{9515 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
9523 .insert = .{ .vp_w, .insr },9516 .insert = .{ .vp_w, .insr },
9524 .extract = .{ .vp_w, .extr },9517 .extract = .{ .vp_w, .extr },
...@@ -9541,7 +9534,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9541,7 +9534,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9541 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },9534 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9542 else => {},9535 else => {},
9543 },9536 },
9544 32 => switch (ty.vectorLen()) {9537 32 => switch (ty.vectorLen(mod)) {
9545 1 => return .{ .move = if (self.hasFeature(.avx))9538 1 => return .{ .move = if (self.hasFeature(.avx))
9546 .{ .v_ss, .mov }9539 .{ .v_ss, .mov }
9547 else9540 else
...@@ -9557,7 +9550,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9557,7 +9550,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9557 return .{ .move = if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } },9550 return .{ .move = if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } },
9558 else => {},9551 else => {},
9559 },9552 },
9560 64 => switch (ty.vectorLen()) {9553 64 => switch (ty.vectorLen(mod)) {
9561 1 => return .{ .move = if (self.hasFeature(.avx))9554 1 => return .{ .move = if (self.hasFeature(.avx))
9562 .{ .v_sd, .mov }9555 .{ .v_sd, .mov }
9563 else9556 else
...@@ -9569,7 +9562,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {...@@ -9569,7 +9562,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9569 return .{ .move = if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } },9562 return .{ .move = if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } },
9570 else => {},9563 else => {},
9571 },9564 },
9572 128 => switch (ty.vectorLen()) {9565 128 => switch (ty.vectorLen(mod)) {
9573 1 => return .{ .move = if (self.hasFeature(.avx))9566 1 => return .{ .move = if (self.hasFeature(.avx))
9574 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }9567 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9575 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },9568 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
...@@ -9647,7 +9640,8 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError...@@ -9647,7 +9640,8 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
9647}9640}
96489641
9649fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void {9642fn 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));
9651 if (abi_size * 8 > dst_reg.bitSize())9645 if (abi_size * 8 > dst_reg.bitSize())
9652 return self.fail("genSetReg called with a value larger than dst_reg", .{});9646 return self.fail("genSetReg called with a value larger than dst_reg", .{});
9653 switch (src_mcv) {9647 switch (src_mcv) {
...@@ -9730,7 +9724,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -9730,7 +9724,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
9730 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },9724 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
9731 ),9725 ),
9732 .sse => try self.asmRegisterRegister(9726 .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)) {
9734 else => switch (abi_size) {9728 else => switch (abi_size) {
9735 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },9729 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
9736 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },9730 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...@@ -9738,7 +9732,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
9738 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null,9732 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null,
9739 else => null,9733 else => null,
9740 },9734 },
9741 .Float => switch (ty.scalarType().floatBits(self.target.*)) {9735 .Float => switch (ty.scalarType(mod).floatBits(self.target.*)) {
9742 16, 128 => switch (abi_size) {9736 16, 128 => switch (abi_size) {
9743 2...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },9737 2...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
9744 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },9738 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...@@ -9789,7 +9783,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
9789 .indirect => try self.moveStrategy(ty, false),9783 .indirect => try self.moveStrategy(ty, false),
9790 .load_frame => |frame_addr| try self.moveStrategy(9784 .load_frame => |frame_addr| try self.moveStrategy(
9791 ty,9785 ty,
9792 self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(self.target.*),9786 self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(mod),
9793 ),9787 ),
9794 .lea_frame => .{ .move = .{ ._, .lea } },9788 .lea_frame => .{ .move = .{ ._, .lea } },
9795 else => unreachable,9789 else => unreachable,
...@@ -9821,7 +9815,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -9821,7 +9815,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
9821 switch (try self.moveStrategy(ty, mem.isAlignedGeneric(9815 switch (try self.moveStrategy(ty, mem.isAlignedGeneric(
9822 u32,9816 u32,
9823 @bitCast(u32, small_addr),9817 @bitCast(u32, small_addr),
9824 ty.abiAlignment(self.target.*),9818 ty.abiAlignment(mod),
9825 ))) {9819 ))) {
9826 .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem),9820 .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem),
9827 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(9821 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
...@@ -9839,7 +9833,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -9839,7 +9833,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
9839 ),9833 ),
9840 }9834 }
9841 },9835 },
9842 .load_direct => |sym_index| switch (ty.zigTypeTag()) {9836 .load_direct => |sym_index| switch (ty.zigTypeTag(mod)) {
9843 else => {9837 else => {
9844 const atom_index = try self.owner.getSymbolIndex(self);9838 const atom_index = try self.owner.getSymbolIndex(self);
9845 _ = try self.addInst(.{9839 _ = try self.addInst(.{
...@@ -9933,7 +9927,8 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -9933,7 +9927,8 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
9933}9927}
99349928
9935fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void {9929fn 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));
9937 const dst_ptr_mcv: MCValue = switch (base) {9932 const dst_ptr_mcv: MCValue = switch (base) {
9938 .none => .{ .immediate = @bitCast(u64, @as(i64, disp)) },9933 .none => .{ .immediate = @bitCast(u64, @as(i64, disp)) },
9939 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },9934 .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...@@ -9945,7 +9940,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
9945 try self.genInlineMemset(dst_ptr_mcv, .{ .immediate = 0xaa }, .{ .immediate = abi_size }),9940 try self.genInlineMemset(dst_ptr_mcv, .{ .immediate = 0xaa }, .{ .immediate = abi_size }),
9946 .immediate => |imm| switch (abi_size) {9941 .immediate => |imm| switch (abi_size) {
9947 1, 2, 4 => {9942 1, 2, 4 => {
9948 const immediate = if (ty.isSignedInt())9943 const immediate = if (ty.isSignedInt(mod))
9949 Immediate.s(@truncate(i32, @bitCast(i64, imm)))9944 Immediate.s(@truncate(i32, @bitCast(i64, imm)))
9950 else9945 else
9951 Immediate.u(@intCast(u32, imm));9946 Immediate.u(@intCast(u32, imm));
...@@ -9967,7 +9962,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -9967,7 +9962,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
9967 while (offset < abi_size) : (offset += 4) try self.asmMemoryImmediate(9962 while (offset < abi_size) : (offset += 4) try self.asmMemoryImmediate(
9968 .{ ._, .mov },9963 .{ ._, .mov },
9969 Memory.sib(.dword, .{ .base = base, .disp = disp + offset }),9964 Memory.sib(.dword, .{ .base = base, .disp = disp + offset }),
9970 if (ty.isSignedInt())9965 if (ty.isSignedInt(mod))
9971 Immediate.s(@truncate(9966 Immediate.s(@truncate(
9972 i32,9967 i32,
9973 @bitCast(i64, imm) >> (math.cast(u6, offset * 8) orelse 63),9968 @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...@@ -9991,19 +9986,19 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
9991 .none => mem.isAlignedGeneric(9986 .none => mem.isAlignedGeneric(
9992 u32,9987 u32,
9993 @bitCast(u32, disp),9988 @bitCast(u32, disp),
9994 ty.abiAlignment(self.target.*),9989 ty.abiAlignment(mod),
9995 ),9990 ),
9996 .reg => |reg| switch (reg) {9991 .reg => |reg| switch (reg) {
9997 .es, .cs, .ss, .ds => mem.isAlignedGeneric(9992 .es, .cs, .ss, .ds => mem.isAlignedGeneric(
9998 u32,9993 u32,
9999 @bitCast(u32, disp),9994 @bitCast(u32, disp),
10000 ty.abiAlignment(self.target.*),9995 ty.abiAlignment(mod),
10001 ),9996 ),
10002 else => false,9997 else => false,
10003 },9998 },
10004 .frame => |frame_index| self.getFrameAddrAlignment(9999 .frame => |frame_index| self.getFrameAddrAlignment(
10005 .{ .index = frame_index, .off = disp },10000 .{ .index = frame_index, .off = disp },
10006 ) >= ty.abiAlignment(self.target.*),10001 ) >= ty.abiAlignment(mod),
10007 })) {10002 })) {
10008 .move => |tag| try self.asmMemoryRegister(tag, dst_mem, src_alias),10003 .move => |tag| try self.asmMemoryRegister(tag, dst_mem, src_alias),
10009 .insert_extract, .vex_insert_extract => |ie| try self.asmMemoryRegisterImmediate(10004 .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...@@ -10017,14 +10012,14 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
10017 .register_overflow => |ro| {10012 .register_overflow => |ro| {
10018 try self.genSetMem(10013 try self.genSetMem(
10019 base,10014 base,
10020 disp + @intCast(i32, ty.structFieldOffset(0, self.target.*)),10015 disp + @intCast(i32, ty.structFieldOffset(0, mod)),
10021 ty.structFieldType(0),10016 ty.structFieldType(0, mod),
10022 .{ .register = ro.reg },10017 .{ .register = ro.reg },
10023 );10018 );
10024 try self.genSetMem(10019 try self.genSetMem(
10025 base,10020 base,
10026 disp + @intCast(i32, ty.structFieldOffset(1, self.target.*)),10021 disp + @intCast(i32, ty.structFieldOffset(1, mod)),
10027 ty.structFieldType(1),10022 ty.structFieldType(1, mod),
10028 .{ .eflags = ro.eflags },10023 .{ .eflags = ro.eflags },
10029 );10024 );
10030 },10025 },
...@@ -10138,7 +10133,7 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -10138,7 +10133,7 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
10138 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;10133 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
1013910134
10140 const dst_mcv = try self.allocRegOrMem(inst, true);10135 const dst_mcv = try self.allocRegOrMem(inst, true);
10141 const dst_ty = self.air.typeOfIndex(inst);10136 const dst_ty = self.typeOfIndex(inst);
10142 try self.genCopy(dst_ty, dst_mcv, src_mcv);10137 try self.genCopy(dst_ty, dst_mcv, src_mcv);
10143 break :result dst_mcv;10138 break :result dst_mcv;
10144 };10139 };
...@@ -10146,13 +10141,14 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -10146,13 +10141,14 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
10146}10141}
1014710142
10148fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {10143fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
10144 const mod = self.bin_file.options.module.?;
10149 const ty_op = self.air.instructions.items(.data)[inst].ty_op;10145 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
10150 const dst_ty = self.air.typeOfIndex(inst);10146 const dst_ty = self.typeOfIndex(inst);
10151 const src_ty = self.air.typeOf(ty_op.operand);10147 const src_ty = self.typeOf(ty_op.operand);
1015210148
10153 const result = result: {10149 const result = result: {
10154 const dst_rc = regClassForType(dst_ty);10150 const dst_rc = regClassForType(dst_ty, mod);
10155 const src_rc = regClassForType(src_ty);10151 const src_rc = regClassForType(src_ty, mod);
10156 const src_mcv = try self.resolveInst(ty_op.operand);10152 const src_mcv = try self.resolveInst(ty_op.operand);
1015710153
10158 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;10154 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 {...@@ -10172,13 +10168,13 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
10172 };10168 };
1017310169
10174 const dst_signedness =10170 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;
10176 const src_signedness =10172 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;
10178 if (dst_signedness == src_signedness) break :result dst_mcv;10174 if (dst_signedness == src_signedness) break :result dst_mcv;
1017910175
10180 const abi_size = @intCast(u16, dst_ty.abiSize(self.target.*));10176 const abi_size = @intCast(u16, dst_ty.abiSize(mod));
10181 const bit_size = @intCast(u16, dst_ty.bitSize(self.target.*));10177 const bit_size = @intCast(u16, dst_ty.bitSize(mod));
10182 if (abi_size * 8 <= bit_size) break :result dst_mcv;10178 if (abi_size * 8 <= bit_size) break :result dst_mcv;
1018310179
10184 const dst_limbs_len = math.divCeil(i32, bit_size, 64) catch unreachable;10180 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 {...@@ -10192,14 +10188,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
10192 const high_lock = self.register_manager.lockReg(high_reg);10188 const high_lock = self.register_manager.lockReg(high_reg);
10193 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);10189 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);
1019410190
10195 var high_pl = Type.Payload.Bits{10191 const high_ty = try mod.intType(dst_signedness, bit_size % 64);
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);
1020310192
10204 try self.truncateRegister(high_ty, high_reg);10193 try self.truncateRegister(high_ty, high_reg);
10205 if (!dst_mcv.isRegister()) try self.genCopy(10194 if (!dst_mcv.isRegister()) try self.genCopy(
...@@ -10213,19 +10202,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -10213,19 +10202,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
10213}10202}
1021410203
10215fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {10204fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
10205 const mod = self.bin_file.options.module.?;
10216 const ty_op = self.air.instructions.items(.data)[inst].ty_op;10206 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1021710207
10218 const slice_ty = self.air.typeOfIndex(inst);10208 const slice_ty = self.typeOfIndex(inst);
10219 const ptr_ty = self.air.typeOf(ty_op.operand);10209 const ptr_ty = self.typeOf(ty_op.operand);
10220 const ptr = try self.resolveInst(ty_op.operand);10210 const ptr = try self.resolveInst(ty_op.operand);
10221 const array_ty = ptr_ty.childType();10211 const array_ty = ptr_ty.childType(mod);
10222 const array_len = array_ty.arrayLen();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));
10225 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);10215 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
10226 try self.genSetMem(10216 try self.genSetMem(
10227 .{ .frame = frame_index },10217 .{ .frame = frame_index },
10228 @intCast(i32, ptr_ty.abiSize(self.target.*)),10218 @intCast(i32, ptr_ty.abiSize(mod)),
10229 Type.usize,10219 Type.usize,
10230 .{ .immediate = array_len },10220 .{ .immediate = array_len },
10231 );10221 );
...@@ -10235,20 +10225,21 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -10235,20 +10225,21 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
10235}10225}
1023610226
10237fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {10227fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
10228 const mod = self.bin_file.options.module.?;
10238 const ty_op = self.air.instructions.items(.data)[inst].ty_op;10229 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1023910230
10240 const src_ty = self.air.typeOf(ty_op.operand);10231 const src_ty = self.typeOf(ty_op.operand);
10241 const src_bits = @intCast(u32, src_ty.bitSize(self.target.*));10232 const src_bits = @intCast(u32, src_ty.bitSize(mod));
10242 const src_signedness =10233 const src_signedness =
10243 if (src_ty.isAbiInt()) src_ty.intInfo(self.target.*).signedness else .unsigned;10234 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
10244 const dst_ty = self.air.typeOfIndex(inst);10235 const dst_ty = self.typeOfIndex(inst);
1024510236
10246 const src_size = math.divCeil(u32, @max(switch (src_signedness) {10237 const src_size = math.divCeil(u32, @max(switch (src_signedness) {
10247 .signed => src_bits,10238 .signed => src_bits,
10248 .unsigned => src_bits + 1,10239 .unsigned => src_bits + 1,
10249 }, 32), 8) catch unreachable;10240 }, 32), 8) catch unreachable;
10250 if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{10241 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),
10252 });10243 });
1025310244
10254 const src_mcv = try self.resolveInst(ty_op.operand);10245 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -10261,12 +10252,12 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -10261,12 +10252,12 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
1026110252
10262 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);10253 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));
10265 const dst_mcv = MCValue{ .register = dst_reg };10256 const dst_mcv = MCValue{ .register = dst_reg };
10266 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);10257 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
10267 defer self.register_manager.unlockReg(dst_lock);10258 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)) {
10270 .Float => switch (dst_ty.floatBits(self.target.*)) {10261 .Float => switch (dst_ty.floatBits(self.target.*)) {
10271 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },10262 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },
10272 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },10263 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },
...@@ -10275,7 +10266,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -10275,7 +10266,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
10275 },10266 },
10276 else => null,10267 else => null,
10277 })) |tag| tag else return self.fail("TODO implement airIntToFloat from {} to {}", .{10268 })) |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),
10279 });10270 });
10280 const dst_alias = dst_reg.to128();10271 const dst_alias = dst_reg.to128();
10281 const src_alias = registerAlias(src_reg, src_size);10272 const src_alias = registerAlias(src_reg, src_size);
...@@ -10288,13 +10279,14 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -10288,13 +10279,14 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
10288}10279}
1028910280
10290fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {10281fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
10282 const mod = self.bin_file.options.module.?;
10291 const ty_op = self.air.instructions.items(.data)[inst].ty_op;10283 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1029210284
10293 const src_ty = self.air.typeOf(ty_op.operand);10285 const src_ty = self.typeOf(ty_op.operand);
10294 const dst_ty = self.air.typeOfIndex(inst);10286 const dst_ty = self.typeOfIndex(inst);
10295 const dst_bits = @intCast(u32, dst_ty.bitSize(self.target.*));10287 const dst_bits = @intCast(u32, dst_ty.bitSize(mod));
10296 const dst_signedness =10288 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
10299 const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {10291 const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {
10300 .signed => dst_bits,10292 .signed => dst_bits,
...@@ -10312,13 +10304,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -10312,13 +10304,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
10312 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);10304 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
10313 defer self.register_manager.unlockReg(src_lock);10305 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));
10316 const dst_mcv = MCValue{ .register = dst_reg };10308 const dst_mcv = MCValue{ .register = dst_reg };
10317 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);10309 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
10318 defer self.register_manager.unlockReg(dst_lock);10310 defer self.register_manager.unlockReg(dst_lock);
1031910311
10320 try self.asmRegisterRegister(10312 try self.asmRegisterRegister(
10321 if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag()) {10313 if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag(mod)) {
10322 .Float => switch (src_ty.floatBits(self.target.*)) {10314 .Float => switch (src_ty.floatBits(self.target.*)) {
10323 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },10315 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },
10324 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },10316 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },
...@@ -10339,12 +10331,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -10339,12 +10331,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
10339}10331}
1034010332
10341fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {10333fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
10334 const mod = self.bin_file.options.module.?;
10342 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;10335 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
10343 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;10336 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
1034410337
10345 const ptr_ty = self.air.typeOf(extra.ptr);10338 const ptr_ty = self.typeOf(extra.ptr);
10346 const val_ty = self.air.typeOf(extra.expected_value);10339 const val_ty = self.typeOf(extra.expected_value);
10347 const val_abi_size = @intCast(u32, val_ty.abiSize(self.target.*));10340 const val_abi_size = @intCast(u32, val_ty.abiSize(mod));
1034810341
10349 try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx });10342 try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx });
10350 const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx });10343 const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx });
...@@ -10433,6 +10426,7 @@ fn atomicOp(...@@ -10433,6 +10426,7 @@ fn atomicOp(
10433 rmw_op: ?std.builtin.AtomicRmwOp,10426 rmw_op: ?std.builtin.AtomicRmwOp,
10434 order: std.builtin.AtomicOrder,10427 order: std.builtin.AtomicOrder,
10435) InnerError!MCValue {10428) InnerError!MCValue {
10429 const mod = self.bin_file.options.module.?;
10436 const ptr_lock = switch (ptr_mcv) {10430 const ptr_lock = switch (ptr_mcv) {
10437 .register => |reg| self.register_manager.lockReg(reg),10431 .register => |reg| self.register_manager.lockReg(reg),
10438 else => null,10432 else => null,
...@@ -10445,7 +10439,7 @@ fn atomicOp(...@@ -10445,7 +10439,7 @@ fn atomicOp(
10445 };10439 };
10446 defer if (val_lock) |lock| self.register_manager.unlockReg(lock);10440 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));
10449 const ptr_size = Memory.PtrSize.fromSize(val_abi_size);10443 const ptr_size = Memory.PtrSize.fromSize(val_abi_size);
10450 const ptr_mem = switch (ptr_mcv) {10444 const ptr_mem = switch (ptr_mcv) {
10451 .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(ptr_size),10445 .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(ptr_size),
...@@ -10539,8 +10533,8 @@ fn atomicOp(...@@ -10539,8 +10533,8 @@ fn atomicOp(
10539 .Or => try self.genBinOpMir(.{ ._, .@"or" }, val_ty, tmp_mcv, val_mcv),10533 .Or => try self.genBinOpMir(.{ ._, .@"or" }, val_ty, tmp_mcv, val_mcv),
10540 .Xor => try self.genBinOpMir(.{ ._, .xor }, val_ty, tmp_mcv, val_mcv),10534 .Xor => try self.genBinOpMir(.{ ._, .xor }, val_ty, tmp_mcv, val_mcv),
10541 .Min, .Max => {10535 .Min, .Max => {
10542 const cc: Condition = switch (if (val_ty.isAbiInt())10536 const cc: Condition = switch (if (val_ty.isAbiInt(mod))
10543 val_ty.intInfo(self.target.*).signedness10537 val_ty.intInfo(mod).signedness
10544 else10538 else
10545 .unsigned) {10539 .unsigned) {
10546 .unsigned => switch (op) {10540 .unsigned => switch (op) {
...@@ -10682,10 +10676,10 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {...@@ -10682,10 +10676,10 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {
1068210676
10683 const unused = self.liveness.isUnused(inst);10677 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);
10686 const ptr_mcv = try self.resolveInst(pl_op.operand);10680 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);
10689 const val_mcv = try self.resolveInst(extra.operand);10683 const val_mcv = try self.resolveInst(extra.operand);
1069010684
10691 const result =10685 const result =
...@@ -10696,7 +10690,7 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {...@@ -10696,7 +10690,7 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {
10696fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {10690fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {
10697 const atomic_load = self.air.instructions.items(.data)[inst].atomic_load;10691 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);
10700 const ptr_mcv = try self.resolveInst(atomic_load.ptr);10694 const ptr_mcv = try self.resolveInst(atomic_load.ptr);
10701 const ptr_lock = switch (ptr_mcv) {10695 const ptr_lock = switch (ptr_mcv) {
10702 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),10696 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -10717,10 +10711,10 @@ fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -10717,10 +10711,10 @@ fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {
10717fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {10711fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {
10718 const bin_op = self.air.instructions.items(.data)[inst].bin_op;10712 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);
10721 const ptr_mcv = try self.resolveInst(bin_op.lhs);10715 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);
10724 const val_mcv = try self.resolveInst(bin_op.rhs);10718 const val_mcv = try self.resolveInst(bin_op.rhs);
1072510719
10726 const result = try self.atomicOp(ptr_mcv, val_mcv, ptr_ty, val_ty, true, null, order);10720 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...@@ -10728,6 +10722,7 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr
10728}10722}
1072910723
10730fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {10724fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
10725 const mod = self.bin_file.options.module.?;
10731 if (safety) {10726 if (safety) {
10732 // TODO if the value is undef, write 0xaa bytes to dest10727 // TODO if the value is undef, write 0xaa bytes to dest
10733 } else {10728 } else {
...@@ -10737,7 +10732,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -10737,7 +10732,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
10737 const bin_op = self.air.instructions.items(.data)[inst].bin_op;10732 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1073810733
10739 const dst_ptr = try self.resolveInst(bin_op.lhs);10734 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);
10741 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {10736 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
10742 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),10737 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
10743 else => null,10738 else => null,
...@@ -10745,26 +10740,26 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -10745,26 +10740,26 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
10745 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);10740 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
1074610741
10747 const src_val = try self.resolveInst(bin_op.rhs);10742 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);
10749 const src_val_lock: ?RegisterLock = switch (src_val) {10744 const src_val_lock: ?RegisterLock = switch (src_val) {
10750 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),10745 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
10751 else => null,10746 else => null,
10752 };10747 };
10753 defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock);10748 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
10757 if (elem_abi_size == 1) {10752 if (elem_abi_size == 1) {
10758 const ptr: MCValue = switch (dst_ptr_ty.ptrSize()) {10753 const ptr: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
10759 // TODO: this only handles slices stored in the stack10754 // TODO: this only handles slices stored in the stack
10760 .Slice => dst_ptr,10755 .Slice => dst_ptr,
10761 .One => dst_ptr,10756 .One => dst_ptr,
10762 .C, .Many => unreachable,10757 .C, .Many => unreachable,
10763 };10758 };
10764 const len: MCValue = switch (dst_ptr_ty.ptrSize()) {10759 const len: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
10765 // TODO: this only handles slices stored in the stack10760 // TODO: this only handles slices stored in the stack
10766 .Slice => dst_ptr.address().offset(8).deref(),10761 .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) },
10768 .C, .Many => unreachable,10763 .C, .Many => unreachable,
10769 };10764 };
10770 const len_lock: ?RegisterLock = switch (len) {10765 const len_lock: ?RegisterLock = switch (len) {
...@@ -10780,10 +10775,9 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -10780,10 +10775,9 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
10780 // Store the first element, and then rely on memcpy copying forwards.10775 // Store the first element, and then rely on memcpy copying forwards.
10781 // Length zero requires a runtime check - so we handle arrays specially10776 // Length zero requires a runtime check - so we handle arrays specially
10782 // here to elide it.10777 // here to elide it.
10783 switch (dst_ptr_ty.ptrSize()) {10778 switch (dst_ptr_ty.ptrSize(mod)) {
10784 .Slice => {10779 .Slice => {
10785 var buf: Type.SlicePtrFieldTypeBuffer = undefined;10780 const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(mod);
10786 const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(&buf);
1078710781
10788 // TODO: this only handles slices stored in the stack10782 // TODO: this only handles slices stored in the stack
10789 const ptr = dst_ptr;10783 const ptr = dst_ptr;
...@@ -10823,13 +10817,9 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -10823,13 +10817,9 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
10823 try self.performReloc(skip_reloc);10817 try self.performReloc(skip_reloc);
10824 },10818 },
10825 .One => {10819 .One => {
10826 var elem_ptr_pl = Type.Payload.ElemType{10820 const elem_ptr_ty = try mod.singleMutPtrType(elem_ty);
10827 .base = .{ .tag = .single_mut_pointer },
10828 .data = elem_ty,
10829 };
10830 const elem_ptr_ty = Type.initPayload(&elem_ptr_pl.base);
1083110821
10832 const len = dst_ptr_ty.childType().arrayLen();10822 const len = dst_ptr_ty.childType(mod).arrayLen(mod);
1083310823
10834 assert(len != 0); // prevented by Sema10824 assert(len != 0); // prevented by Sema
10835 try self.store(elem_ptr_ty, dst_ptr, src_val);10825 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 {...@@ -10854,10 +10844,11 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
10854}10844}
1085510845
10856fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {10846fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
10847 const mod = self.bin_file.options.module.?;
10857 const bin_op = self.air.instructions.items(.data)[inst].bin_op;10848 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1085810849
10859 const dst_ptr = try self.resolveInst(bin_op.lhs);10850 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);
10861 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {10852 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
10862 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),10853 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
10863 else => null,10854 else => null,
...@@ -10871,9 +10862,9 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {...@@ -10871,9 +10862,9 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
10871 };10862 };
10872 defer if (src_ptr_lock) |lock| self.register_manager.unlockReg(lock);10863 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)) {
10875 .Slice => dst_ptr.address().offset(8).deref(),10866 .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) },
10877 .C, .Many => unreachable,10868 .C, .Many => unreachable,
10878 };10869 };
10879 const len_lock: ?RegisterLock = switch (len) {10870 const len_lock: ?RegisterLock = switch (len) {
...@@ -10891,14 +10882,14 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {...@@ -10891,14 +10882,14 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
10891fn airTagName(self: *Self, inst: Air.Inst.Index) !void {10882fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
10892 const mod = self.bin_file.options.module.?;10883 const mod = self.bin_file.options.module.?;
10893 const un_op = self.air.instructions.items(.data)[inst].un_op;10884 const un_op = self.air.instructions.items(.data)[inst].un_op;
10894 const inst_ty = self.air.typeOfIndex(inst);10885 const inst_ty = self.typeOfIndex(inst);
10895 const enum_ty = self.air.typeOf(un_op);10886 const enum_ty = self.typeOf(un_op);
1089610887
10897 // We need a properly aligned and sized call frame to be able to call this function.10888 // We need a properly aligned and sized call frame to be able to call this function.
10898 {10889 {
10899 const needed_call_frame = FrameAlloc.init(.{10890 const needed_call_frame = FrameAlloc.init(.{
10900 .size = inst_ty.abiSize(self.target.*),10891 .size = inst_ty.abiSize(mod),
10901 .alignment = inst_ty.abiAlignment(self.target.*),10892 .alignment = inst_ty.abiAlignment(mod),
10902 });10893 });
10903 const frame_allocs_slice = self.frame_allocs.slice();10894 const frame_allocs_slice = self.frame_allocs.slice();
10904 const stack_frame_size =10895 const stack_frame_size =
...@@ -10923,7 +10914,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {...@@ -10923,7 +10914,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
10923 try self.genLazySymbolRef(10914 try self.genLazySymbolRef(
10924 .call,10915 .call,
10925 .rax,10916 .rax,
10926 link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(), mod),10917 link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(mod), mod),
10927 );10918 );
1092810919
10929 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });10920 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
...@@ -10933,7 +10924,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -10933,7 +10924,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
10933 const mod = self.bin_file.options.module.?;10924 const mod = self.bin_file.options.module.?;
10934 const un_op = self.air.instructions.items(.data)[inst].un_op;10925 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);
10937 const err_mcv = try self.resolveInst(un_op);10928 const err_mcv = try self.resolveInst(un_op);
10938 const err_reg = try self.copyToTmpRegister(err_ty, err_mcv);10929 const err_reg = try self.copyToTmpRegister(err_ty, err_mcv);
10939 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);10930 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);
...@@ -11013,17 +11004,18 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -11013,17 +11004,18 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
11013}11004}
1101411005
11015fn airSplat(self: *Self, inst: Air.Inst.Index) !void {11006fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
11007 const mod = self.bin_file.options.module.?;
11016 const ty_op = self.air.instructions.items(.data)[inst].ty_op;11008 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
11017 const vector_ty = self.air.typeOfIndex(inst);11009 const vector_ty = self.typeOfIndex(inst);
11018 const dst_rc = regClassForType(vector_ty);11010 const dst_rc = regClassForType(vector_ty, mod);
11019 const scalar_ty = vector_ty.scalarType();11011 const scalar_ty = vector_ty.scalarType(mod);
1102011012
11021 const src_mcv = try self.resolveInst(ty_op.operand);11013 const src_mcv = try self.resolveInst(ty_op.operand);
11022 const result: MCValue = result: {11014 const result: MCValue = result: {
11023 switch (scalar_ty.zigTypeTag()) {11015 switch (scalar_ty.zigTypeTag(mod)) {
11024 else => {},11016 else => {},
11025 .Float => switch (scalar_ty.floatBits(self.target.*)) {11017 .Float => switch (scalar_ty.floatBits(self.target.*)) {
11026 32 => switch (vector_ty.vectorLen()) {11018 32 => switch (vector_ty.vectorLen(mod)) {
11027 1 => {11019 1 => {
11028 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;11020 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
11029 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);11021 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
...@@ -11103,7 +11095,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {...@@ -11103,7 +11095,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
11103 },11095 },
11104 else => {},11096 else => {},
11105 },11097 },
11106 64 => switch (vector_ty.vectorLen()) {11098 64 => switch (vector_ty.vectorLen(mod)) {
11107 1 => {11099 1 => {
11108 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;11100 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
11109 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);11101 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
...@@ -11169,7 +11161,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {...@@ -11169,7 +11161,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
11169 },11161 },
11170 else => {},11162 else => {},
11171 },11163 },
11172 128 => switch (vector_ty.vectorLen()) {11164 128 => switch (vector_ty.vectorLen(mod)) {
11173 1 => {11165 1 => {
11174 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;11166 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
11175 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);11167 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
...@@ -11233,36 +11225,37 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {...@@ -11233,36 +11225,37 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
11233}11225}
1123411226
11235fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {11227fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11236 const result_ty = self.air.typeOfIndex(inst);11228 const mod = self.bin_file.options.module.?;
11237 const len = @intCast(usize, result_ty.arrayLen());11229 const result_ty = self.typeOfIndex(inst);
11230 const len = @intCast(usize, result_ty.arrayLen(mod));
11238 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;11231 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
11239 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);11232 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
11240 const result: MCValue = result: {11233 const result: MCValue = result: {
11241 switch (result_ty.zigTypeTag()) {11234 switch (result_ty.zigTypeTag(mod)) {
11242 .Struct => {11235 .Struct => {
11243 const frame_index =11236 const frame_index =
11244 try self.allocFrameIndex(FrameAlloc.initType(result_ty, self.target.*));11237 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
11245 if (result_ty.containerLayout() == .Packed) {11238 if (result_ty.containerLayout(mod) == .Packed) {
11246 const struct_obj = result_ty.castTag(.@"struct").?.data;11239 const struct_obj = mod.typeToStruct(result_ty).?;
11247 try self.genInlineMemset(11240 try self.genInlineMemset(
11248 .{ .lea_frame = .{ .index = frame_index } },11241 .{ .lea_frame = .{ .index = frame_index } },
11249 .{ .immediate = 0 },11242 .{ .immediate = 0 },
11250 .{ .immediate = result_ty.abiSize(self.target.*) },11243 .{ .immediate = result_ty.abiSize(mod) },
11251 );11244 );
11252 for (elements, 0..) |elem, elem_i| {11245 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);11248 const elem_ty = result_ty.structFieldType(elem_i, mod);
11256 const elem_bit_size = @intCast(u32, elem_ty.bitSize(self.target.*));11249 const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod));
11257 if (elem_bit_size > 64) {11250 if (elem_bit_size > 64) {
11258 return self.fail(11251 return self.fail(
11259 "TODO airAggregateInit implement packed structs with large fields",11252 "TODO airAggregateInit implement packed structs with large fields",
11260 .{},11253 .{},
11261 );11254 );
11262 }11255 }
11263 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));11256 const elem_abi_size = @intCast(u32, elem_ty.abiSize(mod));
11264 const elem_abi_bits = elem_abi_size * 8;11257 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);
11266 const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size);11259 const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size);
11267 const elem_bit_off = elem_off % elem_abi_bits;11260 const elem_bit_off = elem_off % elem_abi_bits;
11268 const elem_mcv = try self.resolveInst(elem);11261 const elem_mcv = try self.resolveInst(elem);
...@@ -11322,10 +11315,10 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11322,10 +11315,10 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11322 }11315 }
11323 }11316 }
11324 } else for (elements, 0..) |elem, elem_i| {11317 } 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);11320 const elem_ty = result_ty.structFieldType(elem_i, mod);
11328 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*));11321 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod));
11329 const elem_mcv = try self.resolveInst(elem);11322 const elem_mcv = try self.resolveInst(elem);
11330 const mat_elem_mcv = switch (elem_mcv) {11323 const mat_elem_mcv = switch (elem_mcv) {
11331 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },11324 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
...@@ -11337,9 +11330,9 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11337,9 +11330,9 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11337 },11330 },
11338 .Array => {11331 .Array => {
11339 const frame_index =11332 const frame_index =
11340 try self.allocFrameIndex(FrameAlloc.initType(result_ty, self.target.*));11333 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
11341 const elem_ty = result_ty.childType();11334 const elem_ty = result_ty.childType(mod);
11342 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));11335 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
1134311336
11344 for (elements, 0..) |elem, elem_i| {11337 for (elements, 0..) |elem, elem_i| {
11345 const elem_mcv = try self.resolveInst(elem);11338 const elem_mcv = try self.resolveInst(elem);
...@@ -11350,7 +11343,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11350,7 +11343,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11350 const elem_off = @intCast(i32, elem_size * elem_i);11343 const elem_off = @intCast(i32, elem_size * elem_i);
11351 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv);11344 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv);
11352 }11345 }
11353 if (result_ty.sentinel()) |sentinel| try self.genSetMem(11346 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(
11354 .{ .frame = frame_index },11347 .{ .frame = frame_index },
11355 @intCast(i32, elem_size * elements.len),11348 @intCast(i32, elem_size * elements.len),
11356 elem_ty,11349 elem_ty,
...@@ -11374,13 +11367,14 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11374,13 +11367,14 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11374}11367}
1137511368
11376fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {11369fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
11370 const mod = self.bin_file.options.module.?;
11377 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;11371 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
11378 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;11372 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
11379 const result: MCValue = result: {11373 const result: MCValue = result: {
11380 const union_ty = self.air.typeOfIndex(inst);11374 const union_ty = self.typeOfIndex(inst);
11381 const layout = union_ty.unionGetLayout(self.target.*);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);
11384 const src_mcv = try self.resolveInst(extra.init);11378 const src_mcv = try self.resolveInst(extra.init);
11385 if (layout.tag_size == 0) {11379 if (layout.tag_size == 0) {
11386 if (self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv;11380 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 {...@@ -11392,15 +11386,13 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
1139211386
11393 const dst_mcv = try self.allocRegOrMem(inst, false);11387 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).?;
11396 const field_name = union_obj.fields.keys()[extra.field_index];11390 const field_name = union_obj.fields.keys()[extra.field_index];
11397 const tag_ty = union_ty.unionTagTypeSafety().?;11391 const tag_ty = union_obj.tag_ty;
11398 const field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);11392 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
11399 var tag_pl = Value.Payload.U32{ .base = .{ .tag = .enum_field_index }, .data = field_index };11393 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
11400 const tag_val = Value.initPayload(&tag_pl.base);11394 const tag_int_val = try tag_val.enumToInt(tag_ty, mod);
11401 var tag_int_pl: Value.Payload.U64 = undefined;11395 const tag_int = tag_int_val.toUnsignedInt(mod);
11402 const tag_int_val = tag_val.enumToInt(tag_ty, &tag_int_pl);
11403 const tag_int = tag_int_val.toUnsignedInt(self.target.*);
11404 const tag_off = if (layout.tag_align < layout.payload_align)11396 const tag_off = if (layout.tag_align < layout.payload_align)
11405 @intCast(i32, layout.payload_size)11397 @intCast(i32, layout.payload_size)
11406 else11398 else
...@@ -11424,9 +11416,10 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {...@@ -11424,9 +11416,10 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
11424}11416}
1142511417
11426fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {11418fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
11419 const mod = self.bin_file.options.module.?;
11427 const pl_op = self.air.instructions.items(.data)[inst].pl_op;11420 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
11428 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;11421 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
11431 if (!self.hasFeature(.fma)) return self.fail("TODO implement airMulAdd for {}", .{11424 if (!self.hasFeature(.fma)) return self.fail("TODO implement airMulAdd for {}", .{
11432 ty.fmt(self.bin_file.options.module.?),11425 ty.fmt(self.bin_file.options.module.?),
...@@ -11466,21 +11459,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {...@@ -11466,21 +11459,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
11466 const mir_tag = if (@as(11459 const mir_tag = if (@as(
11467 ?Mir.Inst.FixedTag,11460 ?Mir.Inst.FixedTag,
11468 if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or mem.eql(u2, &order, &.{ 3, 1, 2 }))11461 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)) {
11470 .Float => switch (ty.floatBits(self.target.*)) {11463 .Float => switch (ty.floatBits(self.target.*)) {
11471 32 => .{ .v_ss, .fmadd132 },11464 32 => .{ .v_ss, .fmadd132 },
11472 64 => .{ .v_sd, .fmadd132 },11465 64 => .{ .v_sd, .fmadd132 },
11473 16, 80, 128 => null,11466 16, 80, 128 => null,
11474 else => unreachable,11467 else => unreachable,
11475 },11468 },
11476 .Vector => switch (ty.childType().zigTypeTag()) {11469 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11477 .Float => switch (ty.childType().floatBits(self.target.*)) {11470 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11478 32 => switch (ty.vectorLen()) {11471 32 => switch (ty.vectorLen(mod)) {
11479 1 => .{ .v_ss, .fmadd132 },11472 1 => .{ .v_ss, .fmadd132 },
11480 2...8 => .{ .v_ps, .fmadd132 },11473 2...8 => .{ .v_ps, .fmadd132 },
11481 else => null,11474 else => null,
11482 },11475 },
11483 64 => switch (ty.vectorLen()) {11476 64 => switch (ty.vectorLen(mod)) {
11484 1 => .{ .v_sd, .fmadd132 },11477 1 => .{ .v_sd, .fmadd132 },
11485 2...4 => .{ .v_pd, .fmadd132 },11478 2...4 => .{ .v_pd, .fmadd132 },
11486 else => null,11479 else => null,
...@@ -11493,21 +11486,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {...@@ -11493,21 +11486,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
11493 else => unreachable,11486 else => unreachable,
11494 }11487 }
11495 else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 }))11488 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)) {
11497 .Float => switch (ty.floatBits(self.target.*)) {11490 .Float => switch (ty.floatBits(self.target.*)) {
11498 32 => .{ .v_ss, .fmadd213 },11491 32 => .{ .v_ss, .fmadd213 },
11499 64 => .{ .v_sd, .fmadd213 },11492 64 => .{ .v_sd, .fmadd213 },
11500 16, 80, 128 => null,11493 16, 80, 128 => null,
11501 else => unreachable,11494 else => unreachable,
11502 },11495 },
11503 .Vector => switch (ty.childType().zigTypeTag()) {11496 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11504 .Float => switch (ty.childType().floatBits(self.target.*)) {11497 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11505 32 => switch (ty.vectorLen()) {11498 32 => switch (ty.vectorLen(mod)) {
11506 1 => .{ .v_ss, .fmadd213 },11499 1 => .{ .v_ss, .fmadd213 },
11507 2...8 => .{ .v_ps, .fmadd213 },11500 2...8 => .{ .v_ps, .fmadd213 },
11508 else => null,11501 else => null,
11509 },11502 },
11510 64 => switch (ty.vectorLen()) {11503 64 => switch (ty.vectorLen(mod)) {
11511 1 => .{ .v_sd, .fmadd213 },11504 1 => .{ .v_sd, .fmadd213 },
11512 2...4 => .{ .v_pd, .fmadd213 },11505 2...4 => .{ .v_pd, .fmadd213 },
11513 else => null,11506 else => null,
...@@ -11520,21 +11513,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {...@@ -11520,21 +11513,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
11520 else => unreachable,11513 else => unreachable,
11521 }11514 }
11522 else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 }))11515 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)) {
11524 .Float => switch (ty.floatBits(self.target.*)) {11517 .Float => switch (ty.floatBits(self.target.*)) {
11525 32 => .{ .v_ss, .fmadd231 },11518 32 => .{ .v_ss, .fmadd231 },
11526 64 => .{ .v_sd, .fmadd231 },11519 64 => .{ .v_sd, .fmadd231 },
11527 16, 80, 128 => null,11520 16, 80, 128 => null,
11528 else => unreachable,11521 else => unreachable,
11529 },11522 },
11530 .Vector => switch (ty.childType().zigTypeTag()) {11523 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11531 .Float => switch (ty.childType().floatBits(self.target.*)) {11524 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11532 32 => switch (ty.vectorLen()) {11525 32 => switch (ty.vectorLen(mod)) {
11533 1 => .{ .v_ss, .fmadd231 },11526 1 => .{ .v_ss, .fmadd231 },
11534 2...8 => .{ .v_ps, .fmadd231 },11527 2...8 => .{ .v_ps, .fmadd231 },
11535 else => null,11528 else => null,
11536 },11529 },
11537 64 => switch (ty.vectorLen()) {11530 64 => switch (ty.vectorLen(mod)) {
11538 1 => .{ .v_sd, .fmadd231 },11531 1 => .{ .v_sd, .fmadd231 },
11539 2...4 => .{ .v_pd, .fmadd231 },11532 2...4 => .{ .v_pd, .fmadd231 },
11540 else => null,11533 else => null,
...@@ -11555,7 +11548,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {...@@ -11555,7 +11548,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
11555 var mops: [3]MCValue = undefined;11548 var mops: [3]MCValue = undefined;
11556 for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv;11549 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));
11559 const mop1_reg = registerAlias(mops[0].getReg().?, abi_size);11552 const mop1_reg = registerAlias(mops[0].getReg().?, abi_size);
11560 const mop2_reg = registerAlias(mops[1].getReg().?, abi_size);11553 const mop2_reg = registerAlias(mops[1].getReg().?, abi_size);
11561 if (mops[2].isRegister()) try self.asmRegisterRegisterRegister(11554 if (mops[2].isRegister()) try self.asmRegisterRegisterRegister(
...@@ -11573,22 +11566,22 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {...@@ -11573,22 +11566,22 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
11573}11566}
1157411567
11575fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {11568fn 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
11578 // If the type has no codegen bits, no need to store it.11572 // 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
11581 if (Air.refToIndex(ref)) |inst| {11575 if (Air.refToIndex(ref)) |inst| {
11582 const mcv = switch (self.air.instructions.items(.tag)[inst]) {11576 const mcv = switch (self.air.instructions.items(.tag)[inst]) {
11583 .constant => tracking: {11577 .interned => tracking: {
11584 const gop = try self.const_tracking.getOrPut(self.gpa, inst);11578 const gop = try self.const_tracking.getOrPut(self.gpa, inst);
11585 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{11579 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{
11586 .ty = ty,11580 .ty = ty,
11587 .val = self.air.value(ref).?,11581 .val = self.air.instructions.items(.data)[inst].interned.toValue(),
11588 }));11582 }));
11589 break :tracking gop.value_ptr;11583 break :tracking gop.value_ptr;
11590 },11584 },
11591 .const_ty => unreachable,
11592 else => self.inst_tracking.getPtr(inst).?,11585 else => self.inst_tracking.getPtr(inst).?,
11593 }.short;11586 }.short;
11594 switch (mcv) {11587 switch (mcv) {
...@@ -11597,13 +11590,12 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -11597,13 +11590,12 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
11597 }11590 }
11598 }11591 }
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)).? });
11601}11594}
1160211595
11603fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {11596fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {
11604 const tracking = switch (self.air.instructions.items(.tag)[inst]) {11597 const tracking = switch (self.air.instructions.items(.tag)[inst]) {
11605 .constant => &self.const_tracking,11598 .interned => &self.const_tracking,
11606 .const_ty => unreachable,
11607 else => &self.inst_tracking,11599 else => &self.inst_tracking,
11608 }.getPtr(inst).?;11600 }.getPtr(inst).?;
11609 return switch (tracking.short) {11601 return switch (tracking.short) {
...@@ -11634,7 +11626,8 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV...@@ -11634,7 +11626,8 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
11634}11626}
1163511627
11636fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {11628fn 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))) {
11638 .mcv => |mcv| switch (mcv) {11631 .mcv => |mcv| switch (mcv) {
11639 .none => .none,11632 .none => .none,
11640 .undef => .undef,11633 .undef => .undef,
...@@ -11666,17 +11659,23 @@ const CallMCValues = struct {...@@ -11666,17 +11659,23 @@ const CallMCValues = struct {
11666/// Caller must call `CallMCValues.deinit`.11659/// Caller must call `CallMCValues.deinit`.
11667fn resolveCallingConventionValues(11660fn resolveCallingConventionValues(
11668 self: *Self,11661 self: *Self,
11669 fn_ty: Type,11662 fn_info: InternPool.Key.FuncType,
11670 var_args: []const Air.Inst.Ref,11663 var_args: []const Air.Inst.Ref,
11671 stack_frame_base: FrameIndex,11664 stack_frame_base: FrameIndex,
11672) !CallMCValues {11665) !CallMCValues {
11673 const cc = fn_ty.fnCallingConvention();11666 const mod = self.bin_file.options.module.?;
11674 const param_len = fn_ty.fnParamLen();11667 const cc = fn_info.cc;
11675 const param_types = try self.gpa.alloc(Type, param_len + var_args.len);11668 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
11676 defer self.gpa.free(param_types);11669 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 }
11678 // TODO: promote var arg types11674 // 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
11680 var result: CallMCValues = .{11679 var result: CallMCValues = .{
11681 .args = try self.gpa.alloc(MCValue, param_types.len),11680 .args = try self.gpa.alloc(MCValue, param_types.len),
11682 // These undefined values must be populated before returning from this function.11681 // These undefined values must be populated before returning from this function.
...@@ -11686,7 +11685,7 @@ fn resolveCallingConventionValues(...@@ -11686,7 +11685,7 @@ fn resolveCallingConventionValues(
11686 };11685 };
11687 errdefer self.gpa.free(result.args);11686 errdefer self.gpa.free(result.args);
1168811687
11689 const ret_ty = fn_ty.fnReturnType();11688 const ret_ty = fn_info.return_type.toType();
1169011689
11691 switch (cc) {11690 switch (cc) {
11692 .Naked => {11691 .Naked => {
...@@ -11702,21 +11701,21 @@ fn resolveCallingConventionValues(...@@ -11702,21 +11701,21 @@ fn resolveCallingConventionValues(
11702 switch (self.target.os.tag) {11701 switch (self.target.os.tag) {
11703 .windows => {11702 .windows => {
11704 // Align the stack to 16bytes before allocating shadow stack space (if any).11703 // 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));
11706 },11705 },
11707 else => {},11706 else => {},
11708 }11707 }
1170911708
11710 // Return values11709 // Return values
11711 if (ret_ty.zigTypeTag() == .NoReturn) {11710 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
11712 result.return_value = InstTracking.init(.unreach);11711 result.return_value = InstTracking.init(.unreach);
11713 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {11712 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
11714 // TODO: is this even possible for C calling convention?11713 // TODO: is this even possible for C calling convention?
11715 result.return_value = InstTracking.init(.none);11714 result.return_value = InstTracking.init(.none);
11716 } else {11715 } else {
11717 const classes = switch (self.target.os.tag) {11716 const classes = switch (self.target.os.tag) {
11718 .windows => &[1]abi.Class{abi.classifyWindows(ret_ty, self.target.*)},11717 .windows => &[1]abi.Class{abi.classifyWindows(ret_ty, mod)},
11719 else => mem.sliceTo(&abi.classifySystemV(ret_ty, self.target.*, .ret), .none),11718 else => mem.sliceTo(&abi.classifySystemV(ret_ty, mod, .ret), .none),
11720 };11719 };
11721 if (classes.len > 1) {11720 if (classes.len > 1) {
11722 return self.fail("TODO handle multiple classes per type", .{});11721 return self.fail("TODO handle multiple classes per type", .{});
...@@ -11725,7 +11724,7 @@ fn resolveCallingConventionValues(...@@ -11725,7 +11724,7 @@ fn resolveCallingConventionValues(
11725 result.return_value = switch (classes[0]) {11724 result.return_value = switch (classes[0]) {
11726 .integer => InstTracking.init(.{ .register = registerAlias(11725 .integer => InstTracking.init(.{ .register = registerAlias(
11727 ret_reg,11726 ret_reg,
11728 @intCast(u32, ret_ty.abiSize(self.target.*)),11727 @intCast(u32, ret_ty.abiSize(mod)),
11729 ) }),11728 ) }),
11730 .float, .sse => InstTracking.init(.{ .register = .xmm0 }),11729 .float, .sse => InstTracking.init(.{ .register = .xmm0 }),
11731 .memory => ret: {11730 .memory => ret: {
...@@ -11744,11 +11743,11 @@ fn resolveCallingConventionValues(...@@ -11744,11 +11743,11 @@ fn resolveCallingConventionValues(
1174411743
11745 // Input params11744 // Input params
11746 for (param_types, result.args) |ty, *arg| {11745 for (param_types, result.args) |ty, *arg| {
11747 assert(ty.hasRuntimeBitsIgnoreComptime());11746 assert(ty.hasRuntimeBitsIgnoreComptime(mod));
1174811747
11749 const classes = switch (self.target.os.tag) {11748 const classes = switch (self.target.os.tag) {
11750 .windows => &[1]abi.Class{abi.classifyWindows(ty, self.target.*)},11749 .windows => &[1]abi.Class{abi.classifyWindows(ty, mod)},
11751 else => mem.sliceTo(&abi.classifySystemV(ty, self.target.*, .arg), .none),11750 else => mem.sliceTo(&abi.classifySystemV(ty, mod, .arg), .none),
11752 };11751 };
11753 if (classes.len > 1) {11752 if (classes.len > 1) {
11754 return self.fail("TODO handle multiple classes per type", .{});11753 return self.fail("TODO handle multiple classes per type", .{});
...@@ -11783,8 +11782,8 @@ fn resolveCallingConventionValues(...@@ -11783,8 +11782,8 @@ fn resolveCallingConventionValues(
11783 }),11782 }),
11784 }11783 }
1178511784
11786 const param_size = @intCast(u31, ty.abiSize(self.target.*));11785 const param_size = @intCast(u31, ty.abiSize(mod));
11787 const param_align = @intCast(u31, ty.abiAlignment(self.target.*));11786 const param_align = @intCast(u31, ty.abiAlignment(mod));
11788 result.stack_byte_count =11787 result.stack_byte_count =
11789 mem.alignForwardGeneric(u31, result.stack_byte_count, param_align);11788 mem.alignForwardGeneric(u31, result.stack_byte_count, param_align);
11790 arg.* = .{ .load_frame = .{11789 arg.* = .{ .load_frame = .{
...@@ -11798,13 +11797,13 @@ fn resolveCallingConventionValues(...@@ -11798,13 +11797,13 @@ fn resolveCallingConventionValues(
11798 result.stack_align = 16;11797 result.stack_align = 16;
1179911798
11800 // Return values11799 // Return values
11801 if (ret_ty.zigTypeTag() == .NoReturn) {11800 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
11802 result.return_value = InstTracking.init(.unreach);11801 result.return_value = InstTracking.init(.unreach);
11803 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {11802 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
11804 result.return_value = InstTracking.init(.none);11803 result.return_value = InstTracking.init(.none);
11805 } else {11804 } else {
11806 const ret_reg = abi.getCAbiIntReturnRegs(self.target.*)[0];11805 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));
11808 if (ret_ty_size <= 8 and !ret_ty.isRuntimeFloat()) {11807 if (ret_ty_size <= 8 and !ret_ty.isRuntimeFloat()) {
11809 const aliased_reg = registerAlias(ret_reg, ret_ty_size);11808 const aliased_reg = registerAlias(ret_reg, ret_ty_size);
11810 result.return_value = .{ .short = .{ .register = aliased_reg }, .long = .none };11809 result.return_value = .{ .short = .{ .register = aliased_reg }, .long = .none };
...@@ -11819,12 +11818,12 @@ fn resolveCallingConventionValues(...@@ -11819,12 +11818,12 @@ fn resolveCallingConventionValues(
1181911818
11820 // Input params11819 // Input params
11821 for (param_types, result.args) |ty, *arg| {11820 for (param_types, result.args) |ty, *arg| {
11822 if (!ty.hasRuntimeBitsIgnoreComptime()) {11821 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
11823 arg.* = .none;11822 arg.* = .none;
11824 continue;11823 continue;
11825 }11824 }
11826 const param_size = @intCast(u31, ty.abiSize(self.target.*));11825 const param_size = @intCast(u31, ty.abiSize(mod));
11827 const param_align = @intCast(u31, ty.abiAlignment(self.target.*));11826 const param_align = @intCast(u31, ty.abiAlignment(mod));
11828 result.stack_byte_count =11827 result.stack_byte_count =
11829 mem.alignForwardGeneric(u31, result.stack_byte_count, param_align);11828 mem.alignForwardGeneric(u31, result.stack_byte_count, param_align);
11830 arg.* = .{ .load_frame = .{11829 arg.* = .{ .load_frame = .{
...@@ -11908,9 +11907,10 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {...@@ -11908,9 +11907,10 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
11908/// Truncates the value in the register in place.11907/// Truncates the value in the register in place.
11909/// Clobbers any remaining bits.11908/// Clobbers any remaining bits.
11910fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {11909fn 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{
11912 .signedness = .unsigned,11912 .signedness = .unsigned,
11913 .bits = @intCast(u16, ty.bitSize(self.target.*)),11913 .bits = @intCast(u16, ty.bitSize(mod)),
11914 };11914 };
11915 const max_reg_bit_width = Register.rax.bitSize();11915 const max_reg_bit_width = Register.rax.bitSize();
11916 switch (int_info.signedness) {11916 switch (int_info.signedness) {
...@@ -11953,8 +11953,9 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {...@@ -11953,8 +11953,9 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
11953}11953}
1195411954
11955fn regBitSize(self: *Self, ty: Type) u64 {11955fn regBitSize(self: *Self, ty: Type) u64 {
11956 const abi_size = ty.abiSize(self.target.*);11956 const mod = self.bin_file.options.module.?;
11957 return switch (ty.zigTypeTag()) {11957 const abi_size = ty.abiSize(mod);
11958 return switch (ty.zigTypeTag(mod)) {
11958 else => switch (abi_size) {11959 else => switch (abi_size) {
11959 1 => 8,11960 1 => 8,
11960 2 => 16,11961 2 => 16,
...@@ -11971,7 +11972,8 @@ fn regBitSize(self: *Self, ty: Type) u64 {...@@ -11971,7 +11972,8 @@ fn regBitSize(self: *Self, ty: Type) u64 {
11971}11972}
1197211973
11973fn regExtraBits(self: *Self, ty: Type) u64 {11974fn 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);
11975}11977}
1197611978
11977fn hasFeature(self: *Self, feature: Target.x86.Feature) bool {11979fn hasFeature(self: *Self, feature: Target.x86.Feature) bool {
...@@ -11983,3 +11985,13 @@ fn hasAnyFeatures(self: *Self, features: anytype) bool {...@@ -11983,3 +11985,13 @@ fn hasAnyFeatures(self: *Self, features: anytype) bool {
11983fn hasAllFeatures(self: *Self, features: anytype) bool {11985fn hasAllFeatures(self: *Self, features: anytype) bool {
11984 return Target.x86.featureSetHasAll(self.target.cpu.features, features);11986 return Target.x86.featureSetHasAll(self.target.cpu.features, features);
11985}11987}
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 @@...@@ -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
8pub const Class = enum {1pub const Class = enum {
9 integer,2 integer,
10 sse,3 sse,
...@@ -19,7 +12,7 @@ pub const Class = enum {...@@ -19,7 +12,7 @@ pub const Class = enum {
19 float_combine,12 float_combine,
20};13};
2114
22pub fn classifyWindows(ty: Type, target: Target) Class {15pub fn classifyWindows(ty: Type, mod: *Module) Class {
23 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-201716 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
24 // "There's a strict one-to-one correspondence between a function call's arguments17 // "There's a strict one-to-one correspondence between a function call's arguments
25 // and the registers used for those arguments. Any argument that doesn't fit in 818 // 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 {...@@ -28,7 +21,7 @@ pub fn classifyWindows(ty: Type, target: Target) Class {
28 // "All floating point operations are done using the 16 XMM registers."21 // "All floating point operations are done using the 16 XMM registers."
29 // "Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed22 // "Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed
30 // as if they were integers of the same size."23 // as if they were integers of the same size."
31 switch (ty.zigTypeTag()) {24 switch (ty.zigTypeTag(mod)) {
32 .Pointer,25 .Pointer,
33 .Int,26 .Int,
34 .Bool,27 .Bool,
...@@ -43,12 +36,12 @@ pub fn classifyWindows(ty: Type, target: Target) Class {...@@ -43,12 +36,12 @@ pub fn classifyWindows(ty: Type, target: Target) Class {
43 .ErrorUnion,36 .ErrorUnion,
44 .AnyFrame,37 .AnyFrame,
45 .Frame,38 .Frame,
46 => switch (ty.abiSize(target)) {39 => switch (ty.abiSize(mod)) {
47 0 => unreachable,40 0 => unreachable,
48 1, 2, 4, 8 => return .integer,41 1, 2, 4, 8 => return .integer,
49 else => switch (ty.zigTypeTag()) {42 else => switch (ty.zigTypeTag(mod)) {
50 .Int => return .win_i128,43 .Int => return .win_i128,
51 .Struct, .Union => if (ty.containerLayout() == .Packed) {44 .Struct, .Union => if (ty.containerLayout(mod) == .Packed) {
52 return .win_i128;45 return .win_i128;
53 } else {46 } else {
54 return .memory;47 return .memory;
...@@ -75,14 +68,15 @@ pub const Context = enum { ret, arg, other };...@@ -75,14 +68,15 @@ pub const Context = enum { ret, arg, other };
7568
76/// There are a maximum of 8 possible return slots. Returned values are in69/// There are a maximum of 8 possible return slots. Returned values are in
77/// the beginning of the array; unused slots are filled with .none.70/// 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();
79 const memory_class = [_]Class{73 const memory_class = [_]Class{
80 .memory, .none, .none, .none,74 .memory, .none, .none, .none,
81 .none, .none, .none, .none,75 .none, .none, .none, .none,
82 };76 };
83 var result = [1]Class{.none} ** 8;77 var result = [1]Class{.none} ** 8;
84 switch (ty.zigTypeTag()) {78 switch (ty.zigTypeTag(mod)) {
85 .Pointer => switch (ty.ptrSize()) {79 .Pointer => switch (ty.ptrSize(mod)) {
86 .Slice => {80 .Slice => {
87 result[0] = .integer;81 result[0] = .integer;
88 result[1] = .integer;82 result[1] = .integer;
...@@ -94,7 +88,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -94,7 +88,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
94 },88 },
95 },89 },
96 .Int, .Enum, .ErrorSet => {90 .Int, .Enum, .ErrorSet => {
97 const bits = ty.intInfo(target).bits;91 const bits = ty.intInfo(mod).bits;
98 if (bits <= 64) {92 if (bits <= 64) {
99 result[0] = .integer;93 result[0] = .integer;
100 return result;94 return result;
...@@ -164,8 +158,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -164,8 +158,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
164 else => unreachable,158 else => unreachable,
165 },159 },
166 .Vector => {160 .Vector => {
167 const elem_ty = ty.childType();161 const elem_ty = ty.childType(mod);
168 const bits = elem_ty.bitSize(target) * ty.arrayLen();162 const bits = elem_ty.bitSize(mod) * ty.arrayLen(mod);
169 if (bits <= 64) return .{163 if (bits <= 64) return .{
170 .sse, .none, .none, .none,164 .sse, .none, .none, .none,
171 .none, .none, .none, .none,165 .none, .none, .none, .none,
...@@ -204,7 +198,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -204,7 +198,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
204 return memory_class;198 return memory_class;
205 },199 },
206 .Optional => {200 .Optional => {
207 if (ty.isPtrLikeOptional()) {201 if (ty.isPtrLikeOptional(mod)) {
208 result[0] = .integer;202 result[0] = .integer;
209 return result;203 return result;
210 }204 }
...@@ -215,8 +209,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -215,8 +209,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
215 // it contains unaligned fields, it has class MEMORY"209 // it contains unaligned fields, it has class MEMORY"
216 // "If the size of the aggregate exceeds a single eightbyte, each is classified210 // "If the size of the aggregate exceeds a single eightbyte, each is classified
217 // separately.".211 // separately.".
218 const ty_size = ty.abiSize(target);212 const ty_size = ty.abiSize(mod);
219 if (ty.containerLayout() == .Packed) {213 if (ty.containerLayout(mod) == .Packed) {
220 assert(ty_size <= 128);214 assert(ty_size <= 128);
221 result[0] = .integer;215 result[0] = .integer;
222 if (ty_size > 64) result[1] = .integer;216 if (ty_size > 64) result[1] = .integer;
...@@ -227,15 +221,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -227,15 +221,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
227221
228 var result_i: usize = 0; // out of 8222 var result_i: usize = 0; // out of 8
229 var byte_i: usize = 0; // out of 8223 var byte_i: usize = 0; // out of 8
230 const fields = ty.structFields();224 const fields = ty.structFields(mod);
231 for (fields.values()) |field| {225 for (fields.values()) |field| {
232 if (field.abi_align != 0) {226 if (field.abi_align != 0) {
233 if (field.abi_align < field.ty.abiAlignment(target)) {227 if (field.abi_align < field.ty.abiAlignment(mod)) {
234 return memory_class;228 return memory_class;
235 }229 }
236 }230 }
237 const field_size = field.ty.abiSize(target);231 const field_size = field.ty.abiSize(mod);
238 const field_class_array = classifySystemV(field.ty, target, .other);232 const field_class_array = classifySystemV(field.ty, mod, .other);
239 const field_class = std.mem.sliceTo(&field_class_array, .none);233 const field_class = std.mem.sliceTo(&field_class_array, .none);
240 if (byte_i + field_size <= 8) {234 if (byte_i + field_size <= 8) {
241 // Combine this field with the previous one.235 // Combine this field with the previous one.
...@@ -334,8 +328,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -334,8 +328,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
334 // it contains unaligned fields, it has class MEMORY"328 // it contains unaligned fields, it has class MEMORY"
335 // "If the size of the aggregate exceeds a single eightbyte, each is classified329 // "If the size of the aggregate exceeds a single eightbyte, each is classified
336 // separately.".330 // separately.".
337 const ty_size = ty.abiSize(target);331 const ty_size = ty.abiSize(mod);
338 if (ty.containerLayout() == .Packed) {332 if (ty.containerLayout(mod) == .Packed) {
339 assert(ty_size <= 128);333 assert(ty_size <= 128);
340 result[0] = .integer;334 result[0] = .integer;
341 if (ty_size > 64) result[1] = .integer;335 if (ty_size > 64) result[1] = .integer;
...@@ -344,15 +338,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {...@@ -344,15 +338,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
344 if (ty_size > 64)338 if (ty_size > 64)
345 return memory_class;339 return memory_class;
346340
347 const fields = ty.unionFields();341 const fields = ty.unionFields(mod);
348 for (fields.values()) |field| {342 for (fields.values()) |field| {
349 if (field.abi_align != 0) {343 if (field.abi_align != 0) {
350 if (field.abi_align < field.ty.abiAlignment(target)) {344 if (field.abi_align < field.ty.abiAlignment(mod)) {
351 return memory_class;345 return memory_class;
352 }346 }
353 }347 }
354 // Combine this field with the previous one.348 // 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);
356 for (&result, 0..) |*result_item, i| {350 for (&result, 0..) |*result_item, i| {
357 const field_item = field_class[i];351 const field_item = field_class[i];
358 // "If both classes are equal, this is the resulting class."352 // "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 {...@@ -426,7 +420,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
426 return result;420 return result;
427 },421 },
428 .Array => {422 .Array => {
429 const ty_size = ty.abiSize(target);423 const ty_size = ty.abiSize(mod);
430 if (ty_size <= 64) {424 if (ty_size <= 64) {
431 result[0] = .integer;425 result[0] = .integer;
432 return result;426 return result;
...@@ -527,10 +521,17 @@ pub const RegisterClass = struct {...@@ -527,10 +521,17 @@ pub const RegisterClass = struct {
527 };521 };
528};522};
529523
524const builtin = @import("builtin");
525const std = @import("std");
526const Target = std.Target;
527const assert = std.debug.assert;
530const testing = std.testing;528const testing = std.testing;
529
531const Module = @import("../../Module.zig");530const Module = @import("../../Module.zig");
531const Register = @import("bits.zig").Register;
532const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
533const Type = @import("../../type.zig").Type;
532const Value = @import("../../value.zig").Value;534const Value = @import("../../value.zig").Value;
533const builtin = @import("builtin");
534535
535fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field {536fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field {
536 return .{537 return .{
...@@ -541,34 +542,3 @@ fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field {...@@ -541,34 +542,3 @@ fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field {
541 .is_comptime = false,542 .is_comptime = false,
542 };543 };
543}544}
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");...@@ -14,6 +14,7 @@ const Air = @import("Air.zig");
14const Allocator = mem.Allocator;14const Allocator = mem.Allocator;
15const Compilation = @import("Compilation.zig");15const Compilation = @import("Compilation.zig");
16const ErrorMsg = Module.ErrorMsg;16const ErrorMsg = Module.ErrorMsg;
17const InternPool = @import("InternPool.zig");
17const Liveness = @import("Liveness.zig");18const Liveness = @import("Liveness.zig");
18const Module = @import("Module.zig");19const Module = @import("Module.zig");
19const Target = std.Target;20const Target = std.Target;
...@@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {...@@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
66pub fn generateFunction(67pub fn generateFunction(
67 bin_file: *link.File,68 bin_file: *link.File,
68 src_loc: Module.SrcLoc,69 src_loc: Module.SrcLoc,
69 func: *Module.Fn,70 func_index: Module.Fn.Index,
70 air: Air,71 air: Air,
71 liveness: Liveness,72 liveness: Liveness,
72 code: *std.ArrayList(u8),73 code: *std.ArrayList(u8),
...@@ -75,17 +76,17 @@ pub fn generateFunction(...@@ -75,17 +76,17 @@ pub fn generateFunction(
75 switch (bin_file.options.target.cpu.arch) {76 switch (bin_file.options.target.cpu.arch) {
76 .arm,77 .arm,
77 .armeb,78 .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),
79 .aarch64,80 .aarch64,
80 .aarch64_be,81 .aarch64_be,
81 .aarch64_32,82 .aarch64_32,
82 => return @import("arch/aarch64/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),
83 .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func, 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),
84 .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func, 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),
85 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func, 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),
86 .wasm32,87 .wasm32,
87 .wasm64,88 .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),
89 else => unreachable,90 else => unreachable,
90 }91 }
91}92}
...@@ -139,13 +140,14 @@ pub fn generateLazySymbol(...@@ -139,13 +140,14 @@ pub fn generateLazySymbol(
139 return generateLazyFunction(bin_file, src_loc, lazy_sym, code, debug_output);140 return generateLazyFunction(bin_file, src_loc, lazy_sym, code, debug_output);
140 }141 }
141142
142 if (lazy_sym.ty.isAnyError()) {143 if (lazy_sym.ty.isAnyError(mod)) {
143 alignment.* = 4;144 alignment.* = 4;
144 const err_names = mod.error_name_list.items;145 const err_names = mod.global_error_set.keys();
145 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, err_names.len), endian);146 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, err_names.len), endian);
146 var offset = code.items.len;147 var offset = code.items.len;
147 try code.resize((1 + err_names.len + 1) * 4);148 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);
149 mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian);151 mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian);
150 offset += 4;152 offset += 4;
151 try code.ensureUnusedCapacity(err_name.len + 1);153 try code.ensureUnusedCapacity(err_name.len + 1);
...@@ -154,9 +156,10 @@ pub fn generateLazySymbol(...@@ -154,9 +156,10 @@ pub fn generateLazySymbol(
154 }156 }
155 mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian);157 mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian);
156 return Result.ok;158 return Result.ok;
157 } else if (lazy_sym.ty.zigTypeTag() == .Enum) {159 } else if (lazy_sym.ty.zigTypeTag(mod) == .Enum) {
158 alignment.* = 1;160 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);
160 try code.ensureUnusedCapacity(tag_name.len + 1);163 try code.ensureUnusedCapacity(tag_name.len + 1);
161 code.appendSliceAssumeCapacity(tag_name);164 code.appendSliceAssumeCapacity(tag_name);
162 code.appendAssumeCapacity(0);165 code.appendAssumeCapacity(0);
...@@ -181,749 +184,512 @@ pub fn generateSymbol(...@@ -181,749 +184,512 @@ pub fn generateSymbol(
181 const tracy = trace(@src());184 const tracy = trace(@src());
182 defer tracy.end();185 defer tracy.end();
183186
187 const mod = bin_file.options.module.?;
184 var typed_value = arg_tv;188 var typed_value = arg_tv;
185 if (arg_tv.val.castTag(.runtime_value)) |rt| {189 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
186 typed_value.val = rt.data;190 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
191 else => {},
187 }192 }
188193
189 const target = bin_file.options.target;194 const target = mod.getTarget();
190 const endian = target.cpu.arch.endian();195 const endian = target.cpu.arch.endian();
191196
192 const mod = bin_file.options.module.?;
193 log.debug("generateSymbol: ty = {}, val = {}", .{197 log.debug("generateSymbol: ty = {}, val = {}", .{
194 typed_value.ty.fmt(mod),198 typed_value.ty.fmt(mod),
195 typed_value.val.fmtValue(typed_value.ty, mod),199 typed_value.val.fmtValue(typed_value.ty, mod),
196 });200 });
197201
198 if (typed_value.val.isUndefDeep()) {202 if (typed_value.val.isUndefDeep(mod)) {
199 const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow;203 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
200 try code.appendNTimes(0xaa, abi_size);204 try code.appendNTimes(0xaa, abi_size);
201 return Result.ok;205 return .ok;
202 }206 }
203207
204 switch (typed_value.ty.zigTypeTag()) {208 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
205 .Fn => {209 .int_type,
206 return Result{210 .ptr_type,
207 .fail = try ErrorMsg.create(211 .array_type,
208 bin_file.allocator,212 .vector_type,
209 src_loc,213 .opt_type,
210 "TODO implement generateSymbol function pointers",214 .anyframe_type,
211 .{},215 .error_union_type,
212 ),216 .simple_type,
213 };217 .struct_type,
214 },218 .anon_struct_type,
215 .Float => {219 .union_type,
216 switch (typed_value.ty.floatBits(target)) {220 .opaque_type,
217 16 => writeFloat(f16, typed_value.val.toFloat(f16), target, endian, try code.addManyAsArray(2)),221 .enum_type,
218 32 => writeFloat(f32, typed_value.val.toFloat(f32), target, endian, try code.addManyAsArray(4)),222 .func_type,
219 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)),223 .error_set_type,
220 80 => {224 .inferred_error_set_type,
221 writeFloat(f80, typed_value.val.toFloat(f80), target, endian, try code.addManyAsArray(10));225 => unreachable, // types, not values
222 const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow;226
223 try code.appendNTimes(0, abi_size - 10);227 .undef, .runtime_value => unreachable, // handled above
224 },228 .simple_value => |simple_value| switch (simple_value) {
225 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)),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,
226 else => unreachable,239 else => unreachable,
227 }240 }),
228 return Result.ok;
229 },241 },
230 .Array => switch (typed_value.val.tag()) {242 .variable,
231 .bytes => {243 .extern_func,
232 const bytes = typed_value.val.castTag(.bytes).?.data;244 .func,
233 const len = @intCast(usize, typed_value.ty.arrayLenIncludingSentinel());245 .enum_literal,
234 // The bytes payload already includes the sentinel, if any246 .empty_enum_value,
235 try code.ensureUnusedCapacity(len);247 => unreachable, // non-runtime values
236 code.appendSliceAssumeCapacity(bytes[0..len]);248 .int => {
237 return Result.ok;249 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
238 },250 var space: Value.BigIntSpace = undefined;
239 .str_lit => {251 const val = typed_value.val.toBigInt(&space, mod);
240 const str_lit = typed_value.val.castTag(.str_lit).?.data;252 val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);
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 },
314 },253 },
315 .Pointer => switch (typed_value.val.tag()) {254 .err => |err| {
316 .null_value => {255 const int = try mod.getErrorValue(err.name);
317 switch (target.ptrBitWidth()) {256 try code.writer().writeInt(u16, @intCast(u16, int), endian);
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 },
400 },257 },
401 .Int => {258 .error_union => |error_union| {
402 const info = typed_value.ty.intInfo(target);259 const payload_ty = typed_value.ty.errorUnionPayload(mod);
403 if (info.bits <= 8) {260 const err_val = switch (error_union.val) {
404 const x: u8 = switch (info.signedness) {261 .err_name => |err_name| @intCast(u16, try mod.getErrorValue(err_name)),
405 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)),262 .payload => @as(u16, 0),
406 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(target))),263 };
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 }
531264
532 return Result.ok;265 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
266 try code.writer().writeInt(u16, err_val, endian);
267 return .ok;
533 }268 }
534269
535 const struct_begin = code.items.len;270 const payload_align = payload_ty.abiAlignment(mod);
536 const field_vals = typed_value.val.castTag(.aggregate).?.data;271 const error_align = Type.anyerror.abiAlignment(mod);
537 for (field_vals, 0..) |field_val, index| {272 const abi_align = typed_value.ty.abiAlignment(mod);
538 const field_ty = typed_value.ty.structFieldType(index);
539 if (!field_ty.hasRuntimeBits()) continue;
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;
541 switch (try generateSymbol(bin_file, src_loc, .{282 switch (try generateSymbol(bin_file, src_loc, .{
542 .ty = field_ty,283 .ty = payload_ty,
543 .val = field_val,284 .val = switch (error_union.val) {
285 .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),
286 .payload => |payload| payload,
287 }.toValue(),
544 }, code, debug_output, reloc_info)) {288 }, code, debug_output, reloc_info)) {
545 .ok => {},289 .ok => {},
546 .fail => |em| return Result{ .fail = em },290 .fail => |em| return .{ .fail = em },
547 }291 }
548 const unpadded_field_end = code.items.len - struct_begin;292 const unpadded_end = code.items.len - begin;
549293 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
550 // Pad struct members if required294 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
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;
553295
554 if (padding > 0) {296 if (padding > 0) {
555 try code.writer().writeByteNTimes(0, padding);297 try code.writer().writeByteNTimes(0, padding);
556 }298 }
557 }299 }
558300
559 return Result.ok;301 // Payload size is larger than error set, so emit our error set last
560 },302 if (error_align <= payload_align) {
561 .Union => {303 const begin = code.items.len;
562 const union_obj = typed_value.val.castTag(.@"union").?.data;304 try code.writer().writeInt(u16, err_val, endian);
563 const layout = typed_value.ty.unionGetLayout(target);305 const unpadded_end = code.items.len - begin;
564306 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
565 if (layout.payload_size == 0) {307 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
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 }
597308
598 const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(target)) orelse return error.Overflow;
599 if (padding > 0) {309 if (padding > 0) {
600 try code.writer().writeByteNTimes(0, padding);310 try code.writer().writeByteNTimes(0, padding);
601 }311 }
602 }312 }
603313 },
604 if (layout.tag_size > 0) {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
605 switch (try generateSymbol(bin_file, src_loc, .{346 switch (try generateSymbol(bin_file, src_loc, .{
606 .ty = union_ty.tag_ty,347 .ty = Type.usize,
607 .val = union_obj.tag,348 .val = ptr.len.toValue(),
608 }, code, debug_output, reloc_info)) {349 }, code, debug_output, reloc_info)) {
609 .ok => {},350 .ok => {},
610 .fail => |em| return Result{ .fail = em },351 .fail => |em| return Result{ .fail = em },
611 }352 }
612 }353 }
613
614 if (layout.padding > 0) {
615 try code.writer().writeByteNTimes(0, layout.padding);
616 }
617
618 return Result.ok;
619 },354 },
620 .Optional => {355 .opt => {
621 var opt_buf: Type.Payload.ElemType = undefined;356 const payload_type = typed_value.ty.optionalChild(mod);
622 const payload_type = typed_value.ty.optionalChild(&opt_buf);357 const payload_val = typed_value.val.optionalValue(mod);
623 const is_pl = !typed_value.val.isNull();358 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
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 }
630359
631 if (typed_value.ty.optionalReprIsPayload()) {360 if (typed_value.ty.optionalReprIsPayload(mod)) {
632 if (typed_value.val.castTag(.opt_payload)) |payload| {361 if (payload_val) |value| {
633 switch (try generateSymbol(bin_file, src_loc, .{362 switch (try generateSymbol(bin_file, src_loc, .{
634 .ty = payload_type,363 .ty = payload_type,
635 .val = payload.data,364 .val = value,
636 }, code, debug_output, reloc_info)) {365 }, code, debug_output, reloc_info)) {
637 .ok => {},366 .ok => {},
638 .fail => |em| return Result{ .fail = em },367 .fail => |em| return Result{ .fail = em },
639 }368 }
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();
641 switch (try generateSymbol(bin_file, src_loc, .{376 switch (try generateSymbol(bin_file, src_loc, .{
642 .ty = payload_type,377 .ty = payload_type,
643 .val = typed_value.val,378 .val = value,
644 }, code, debug_output, reloc_info)) {379 }, code, debug_output, reloc_info)) {
645 .ok => {},380 .ok => {},
646 .fail => |em| return Result{ .fail = em },381 .fail => |em| return Result{ .fail = em },
647 }382 }
648 } else {
649 try code.writer().writeByteNTimes(0, abi_size);
650 }383 }
651384 try code.writer().writeByte(@boolToInt(payload_val != null));
652 return Result.ok;385 try code.writer().writeByteNTimes(0, padding);
653 }386 }
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;431 const padding = math.cast(usize, typed_value.ty.abiSize(mod) -
656 const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef);432 (math.divCeil(u64, vector_type.child.toType().bitSize(mod) * vector_type.len, 8) catch |err| switch (err) {
657 switch (try generateSymbol(bin_file, src_loc, .{433 error.DivisionByZero => unreachable,
658 .ty = payload_type,434 else => |e| return e,
659 .val = value,435 })) orelse return error.Overflow;
660 }, code, debug_output, reloc_info)) {436 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
661 .ok => {},437 },
662 .fail => |em| return Result{ .fail = em },438 .anon_struct_type => |tuple| {
663 }439 const struct_begin = code.items.len;
664 try code.writer().writeByte(@boolToInt(is_pl));440 for (tuple.types, tuple.values, 0..) |field_ty, comptime_val, index| {
665 try code.writer().writeByteNTimes(0, padding);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,
668 },549 },
669 .ErrorUnion => {550 .un => |un| {
670 const error_ty = typed_value.ty.errorUnionSet();551 const layout = typed_value.ty.unionGetLayout(mod);
671 const payload_ty = typed_value.ty.errorUnionPayload();
672 const is_payload = typed_value.val.errorUnionIsPayload();
673552
674 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {553 if (layout.payload_size == 0) {
675 const err_val = if (is_payload) Value.initTag(.zero) else typed_value.val;
676 return generateSymbol(bin_file, src_loc, .{554 return generateSymbol(bin_file, src_loc, .{
677 .ty = error_ty,555 .ty = typed_value.ty.unionTagType(mod).?,
678 .val = err_val,556 .val = un.tag.toValue(),
679 }, code, debug_output, reloc_info);557 }, code, debug_output, reloc_info);
680 }558 }
681559
682 const payload_align = payload_ty.abiAlignment(target);560 // Check if we should store the tag first.
683 const error_align = Type.anyerror.abiAlignment(target);561 if (layout.tag_align >= layout.payload_align) {
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) {
688 switch (try generateSymbol(bin_file, src_loc, .{562 switch (try generateSymbol(bin_file, src_loc, .{
689 .ty = error_ty,563 .ty = typed_value.ty.unionTagType(mod).?,
690 .val = if (is_payload) Value.initTag(.zero) else typed_value.val,564 .val = un.tag.toValue(),
691 }, code, debug_output, reloc_info)) {565 }, code, debug_output, reloc_info)) {
692 .ok => {},566 .ok => {},
693 .fail => |em| return Result{ .fail = em },567 .fail => |em| return Result{ .fail = em },
694 }568 }
695 }569 }
696570
697 // emit payload part of the error union571 const union_ty = mod.typeToUnion(typed_value.ty).?;
698 {572 const field_index = typed_value.ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
699 const begin = code.items.len;573 assert(union_ty.haveFieldTypes());
700 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);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 {
701 switch (try generateSymbol(bin_file, src_loc, .{578 switch (try generateSymbol(bin_file, src_loc, .{
702 .ty = payload_ty,579 .ty = field_ty,
703 .val = payload_val,580 .val = un.val.toValue(),
704 }, code, debug_output, reloc_info)) {581 }, code, debug_output, reloc_info)) {
705 .ok => {},582 .ok => {},
706 .fail => |em| return Result{ .fail = em },583 .fail => |em| return Result{ .fail = em },
707 }584 }
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;
712 if (padding > 0) {587 if (padding > 0) {
713 try code.writer().writeByteNTimes(0, padding);588 try code.writer().writeByteNTimes(0, padding);
714 }589 }
715 }590 }
716591
717 // Payload size is larger than error set, so emit our error set last592 if (layout.tag_size > 0) {
718 if (error_align <= payload_align) {
719 const begin = code.items.len;
720 switch (try generateSymbol(bin_file, src_loc, .{593 switch (try generateSymbol(bin_file, src_loc, .{
721 .ty = error_ty,594 .ty = union_ty.tag_ty,
722 .val = if (is_payload) Value.initTag(.zero) else typed_value.val,595 .val = un.tag.toValue(),
723 }, code, debug_output, reloc_info)) {596 }, code, debug_output, reloc_info)) {
724 .ok => {},597 .ok => {},
725 .fail => |em| return Result{ .fail = em },598 .fail => |em| return Result{ .fail = em },
726 }599 }
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 },
748 }600 }
749 return Result.ok;
750 },601 },
751 .Vector => switch (typed_value.val.tag()) {602 .memoized_call => unreachable,
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 ) },
823 }603 }
604 return .ok;
824}605}
825606
826fn lowerParentPtr(607fn lowerParentPtr(
827 bin_file: *link.File,608 bin_file: *link.File,
828 src_loc: Module.SrcLoc,609 src_loc: Module.SrcLoc,
829 typed_value: TypedValue,610 parent_ptr: InternPool.Index,
830 parent_ptr: Value,
831 code: *std.ArrayList(u8),611 code: *std.ArrayList(u8),
832 debug_output: DebugInfoOutput,612 debug_output: DebugInfoOutput,
833 reloc_info: RelocInfo,613 reloc_info: RelocInfo,
834) CodeGenError!Result {614) CodeGenError!Result {
835 const target = bin_file.options.target;615 const mod = bin_file.options.module.?;
836 switch (parent_ptr.tag()) {616 const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr;
837 .field_ptr => {617 assert(ptr.len == .none);
838 const field_ptr = parent_ptr.castTag(.field_ptr).?.data;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;
839 return lowerParentPtr(665 return lowerParentPtr(
840 bin_file,666 bin_file,
841 src_loc,667 src_loc,
842 typed_value,668 field.base,
843 field_ptr.container_ptr,
844 code,669 code,
845 debug_output,670 debug_output,
846 reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag()) {671 reloc_info.offset(switch (mod.intern_pool.indexToKey(base_type)) {
847 .Pointer => offset: {672 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
848 assert(field_ptr.container_ty.isSlice());673 .One, .Many, .C => unreachable,
849 var buf: Type.SlicePtrFieldTypeBuffer = undefined;674 .Slice => switch (field.index) {
850 break :offset switch (field_ptr.field_index) {
851 0 => 0,675 0 => 0,
852 1 => field_ptr.container_ty.slicePtrFieldType(&buf).abiSize(target),676 1 => @divExact(mod.getTarget().ptrBitWidth(), 8),
853 else => unreachable,677 else => unreachable,
854 };678 },
855 },679 },
856 .Struct, .Union => field_ptr.container_ty.structFieldOffset(680 .struct_type,
857 field_ptr.field_index,681 .anon_struct_type,
858 target,682 .union_type,
859 ),683 => @intCast(u32, base_type.toType().structFieldOffset(
860 else => return Result{ .fail = try ErrorMsg.create(684 @intCast(u32, field.index),
861 bin_file.allocator,685 mod,
862 src_loc,686 )),
863 "TODO implement lowerParentPtr for field_ptr with a container of type {}",687 else => unreachable,
864 .{field_ptr.container_ty.fmt(bin_file.options.module.?)},688 }),
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))),
904 );689 );
905 },690 },
906 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(691 .comptime_field => unreachable,
907 bin_file,692 };
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 }
927}693}
928694
929const RelocInfo = struct {695const RelocInfo = struct {
...@@ -938,51 +704,25 @@ const RelocInfo = struct {...@@ -938,51 +704,25 @@ const RelocInfo = struct {
938fn lowerDeclRef(704fn lowerDeclRef(
939 bin_file: *link.File,705 bin_file: *link.File,
940 src_loc: Module.SrcLoc,706 src_loc: Module.SrcLoc,
941 typed_value: TypedValue,
942 decl_index: Module.Decl.Index,707 decl_index: Module.Decl.Index,
943 code: *std.ArrayList(u8),708 code: *std.ArrayList(u8),
944 debug_output: DebugInfoOutput,709 debug_output: DebugInfoOutput,
945 reloc_info: RelocInfo,710 reloc_info: RelocInfo,
946) CodeGenError!Result {711) CodeGenError!Result {
712 _ = src_loc;
713 _ = debug_output;
947 const target = bin_file.options.target;714 const target = bin_file.options.target;
948 const module = bin_file.options.module.?;715 const mod = 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 }
976716
977 const ptr_width = target.ptrBitWidth();717 const ptr_width = target.ptrBitWidth();
978 const decl = module.declPtr(decl_index);718 const decl = mod.declPtr(decl_index);
979 const is_fn_body = decl.ty.zigTypeTag() == .Fn;719 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;
980 if (!is_fn_body and !decl.ty.hasRuntimeBits()) {720 if (!is_fn_body and !decl.ty.hasRuntimeBits(mod)) {
981 try code.writer().writeByteNTimes(0xaa, @divExact(ptr_width, 8));721 try code.writer().writeByteNTimes(0xaa, @divExact(ptr_width, 8));
982 return Result.ok;722 return Result.ok;
983 }723 }
984724
985 module.markDeclAlive(decl);725 try mod.markDeclAlive(decl);
986726
987 const vaddr = try bin_file.getDeclVAddr(decl_index, .{727 const vaddr = try bin_file.getDeclVAddr(decl_index, .{
988 .parent_atom_index = reloc_info.parent_atom_index,728 .parent_atom_index = reloc_info.parent_atom_index,
...@@ -1059,16 +799,16 @@ fn genDeclRef(...@@ -1059,16 +799,16 @@ fn genDeclRef(
1059 tv: TypedValue,799 tv: TypedValue,
1060 decl_index: Module.Decl.Index,800 decl_index: Module.Decl.Index,
1061) CodeGenError!GenResult {801) CodeGenError!GenResult {
1062 const module = bin_file.options.module.?;802 const mod = bin_file.options.module.?;
1063 log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(module), tv.val.fmtValue(tv.ty, module) });803 log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) });
1064804
1065 const target = bin_file.options.target;805 const target = bin_file.options.target;
1066 const ptr_bits = target.ptrBitWidth();806 const ptr_bits = target.ptrBitWidth();
1067 const ptr_bytes: u64 = @divExact(ptr_bits, 8);807 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)) {
1072 const imm: u64 = switch (ptr_bytes) {812 const imm: u64 = switch (ptr_bytes) {
1073 1 => 0xaa,813 1 => 0xaa,
1074 2 => 0xaaaa,814 2 => 0xaaaa,
...@@ -1080,20 +820,20 @@ fn genDeclRef(...@@ -1080,20 +820,20 @@ fn genDeclRef(
1080 }820 }
1081821
1082 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?822 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
1083 if (tv.ty.castPtrToFn()) |fn_ty| {823 if (tv.ty.castPtrToFn(mod)) |fn_ty| {
1084 if (fn_ty.fnInfo().is_generic) {824 if (mod.typeToFunc(fn_ty).?.is_generic) {
1085 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(target) });825 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod) });
1086 }826 }
1087 } else if (tv.ty.zigTypeTag() == .Pointer) {827 } else if (tv.ty.zigTypeTag(mod) == .Pointer) {
1088 const elem_ty = tv.ty.elemType2();828 const elem_ty = tv.ty.elemType2(mod);
1089 if (!elem_ty.hasRuntimeBits()) {829 if (!elem_ty.hasRuntimeBits(mod)) {
1090 return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(target) });830 return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(mod) });
1091 }831 }
1092 }832 }
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
1098 if (bin_file.cast(link.File.Elf)) |elf_file| {838 if (bin_file.cast(link.File.Elf)) |elf_file| {
1099 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);839 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
...@@ -1157,57 +897,56 @@ pub fn genTypedValue(...@@ -1157,57 +897,56 @@ pub fn genTypedValue(
1157 arg_tv: TypedValue,897 arg_tv: TypedValue,
1158 owner_decl_index: Module.Decl.Index,898 owner_decl_index: Module.Decl.Index,
1159) CodeGenError!GenResult {899) CodeGenError!GenResult {
900 const mod = bin_file.options.module.?;
1160 var typed_value = arg_tv;901 var typed_value = arg_tv;
1161 if (typed_value.val.castTag(.runtime_value)) |rt| {902 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
1162 typed_value.val = rt.data;903 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
904 else => {},
1163 }905 }
1164906
1165 const mod = bin_file.options.module.?;
1166 log.debug("genTypedValue: ty = {}, val = {}", .{907 log.debug("genTypedValue: ty = {}, val = {}", .{
1167 typed_value.ty.fmt(mod),908 typed_value.ty.fmt(mod),
1168 typed_value.val.fmtValue(typed_value.ty, mod),909 typed_value.val.fmtValue(typed_value.ty, mod),
1169 });910 });
1170911
1171 if (typed_value.val.isUndef())912 if (typed_value.val.isUndef(mod))
1172 return GenResult.mcv(.undef);913 return GenResult.mcv(.undef);
1173914
1174 const target = bin_file.options.target;915 const target = bin_file.options.target;
1175 const ptr_bits = target.ptrBitWidth();916 const ptr_bits = target.ptrBitWidth();
1176917
1177 if (!typed_value.ty.isSlice()) {918 if (!typed_value.ty.isSlice(mod)) switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
1178 if (typed_value.val.castTag(.variable)) |payload| {919 .ptr => |ptr| switch (ptr.addr) {
1179 return genDeclRef(bin_file, src_loc, typed_value, payload.data.owner_decl);920 .decl => |decl| return genDeclRef(bin_file, src_loc, typed_value, decl),
1180 }921 .mut_decl => |mut_decl| return genDeclRef(bin_file, src_loc, typed_value, mut_decl.decl),
1181 if (typed_value.val.castTag(.decl_ref)) |payload| {922 else => {},
1182 return genDeclRef(bin_file, src_loc, typed_value, payload.data);923 },
1183 }924 else => {},
1184 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {925 };
1185 return genDeclRef(bin_file, src_loc, typed_value, payload.data.decl_index);
1186 }
1187 }
1188926
1189 switch (typed_value.ty.zigTypeTag()) {927 switch (typed_value.ty.zigTypeTag(mod)) {
1190 .Void => return GenResult.mcv(.none),928 .Void => return GenResult.mcv(.none),
1191 .Pointer => switch (typed_value.ty.ptrSize()) {929 .Pointer => switch (typed_value.ty.ptrSize(mod)) {
1192 .Slice => {},930 .Slice => {},
1193 else => {931 else => switch (typed_value.val.toIntern()) {
1194 switch (typed_value.val.tag()) {932 .null_value => {
1195 .null_value => {933 return GenResult.mcv(.{ .immediate = 0 });
1196 return GenResult.mcv(.{ .immediate = 0 });934 },
1197 },935 .none => {},
1198 .int_u64 => {936 else => switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
1199 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(target) });937 .int => {
938 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) });
1200 },939 },
1201 else => {},940 else => {},
1202 }941 },
1203 },942 },
1204 },943 },
1205 .Int => {944 .Int => {
1206 const info = typed_value.ty.intInfo(target);945 const info = typed_value.ty.intInfo(mod);
1207 if (info.bits <= ptr_bits) {946 if (info.bits <= ptr_bits) {
1208 const unsigned = switch (info.signedness) {947 const unsigned = switch (info.signedness) {
1209 .signed => @bitCast(u64, typed_value.val.toSignedInt(target)),948 .signed => @bitCast(u64, typed_value.val.toSignedInt(mod)),
1210 .unsigned => typed_value.val.toUnsignedInt(target),949 .unsigned => typed_value.val.toUnsignedInt(mod),
1211 };950 };
1212 return GenResult.mcv(.{ .immediate = unsigned });951 return GenResult.mcv(.{ .immediate = unsigned });
1213 }952 }
...@@ -1216,78 +955,46 @@ pub fn genTypedValue(...@@ -1216,78 +955,46 @@ pub fn genTypedValue(
1216 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) });955 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) });
1217 },956 },
1218 .Optional => {957 .Optional => {
1219 if (typed_value.ty.isPtrLikeOptional()) {958 if (typed_value.ty.isPtrLikeOptional(mod)) {
1220 if (typed_value.val.tag() == .null_value) return GenResult.mcv(.{ .immediate = 0 });
1221
1222 var buf: Type.Payload.ElemType = undefined;
1223 return genTypedValue(bin_file, src_loc, .{959 return genTypedValue(bin_file, src_loc, .{
1224 .ty = typed_value.ty.optionalChild(&buf),960 .ty = typed_value.ty.optionalChild(mod),
1225 .val = if (typed_value.val.castTag(.opt_payload)) |pl| pl.data else typed_value.val,961 .val = typed_value.val.optionalValue(mod) orelse return GenResult.mcv(.{ .immediate = 0 }),
1226 }, owner_decl_index);962 }, owner_decl_index);
1227 } else if (typed_value.ty.abiSize(target) == 1) {963 } else if (typed_value.ty.abiSize(mod) == 1) {
1228 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull()) });964 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull(mod)) });
1229 }965 }
1230 },966 },
1231 .Enum => {967 .Enum => {
1232 if (typed_value.val.castTag(.enum_field_index)) |field_index| {968 const enum_tag = mod.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag;
1233 switch (typed_value.ty.tag()) {969 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
1234 .enum_simple => {970 return genTypedValue(bin_file, src_loc, .{
1235 return GenResult.mcv(.{ .immediate = field_index.data });971 .ty = int_tag_ty.toType(),
1236 },972 .val = enum_tag.int.toValue(),
1237 .enum_numbered, .enum_full, .enum_nonexhaustive => {973 }, owner_decl_index);
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 }
1263 },974 },
1264 .ErrorSet => {975 .ErrorSet => {
1265 switch (typed_value.val.tag()) {976 const err_name = mod.intern_pool.indexToKey(typed_value.val.toIntern()).err.name;
1266 .@"error" => {977 const error_index = mod.global_error_set.getIndex(err_name).?;
1267 const err_name = typed_value.val.castTag(.@"error").?.data.name;978 return GenResult.mcv(.{ .immediate = error_index });
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 }
1278 },979 },
1279 .ErrorUnion => {980 .ErrorUnion => {
1280 const error_type = typed_value.ty.errorUnionSet();981 const err_type = typed_value.ty.errorUnionSet(mod);
1281 const payload_type = typed_value.ty.errorUnionPayload();982 const payload_type = typed_value.ty.errorUnionPayload(mod);
1282 const is_pl = typed_value.val.errorUnionIsPayload();983 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
1283
1284 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
1285 // We use the error type directly as the type.984 // We use the error type directly as the type.
1286 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);985 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {
1287 return genTypedValue(bin_file, src_loc, .{986 .err_name => |err_name| return genTypedValue(bin_file, src_loc, .{
1288 .ty = error_type,987 .ty = err_type,
1289 .val = err_val,988 .val = (try mod.intern(.{ .err = .{
1290 }, owner_decl_index);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 }
1291 }998 }
1292 },999 },
12931000
...@@ -1306,23 +1013,23 @@ pub fn genTypedValue(...@@ -1306,23 +1013,23 @@ pub fn genTypedValue(
1306 return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index);1013 return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index);
1307}1014}
13081015
1309pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {1016pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 {
1310 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;1017 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0;
1311 const payload_align = payload_ty.abiAlignment(target);1018 const payload_align = payload_ty.abiAlignment(mod);
1312 const error_align = Type.anyerror.abiAlignment(target);1019 const error_align = Type.anyerror.abiAlignment(mod);
1313 if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime()) {1020 if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1314 return 0;1021 return 0;
1315 } else {1022 } else {
1316 return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(target), payload_align);1023 return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(mod), payload_align);
1317 }1024 }
1318}1025}
13191026
1320pub fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u64 {1027pub fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u64 {
1321 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;1028 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0;
1322 const payload_align = payload_ty.abiAlignment(target);1029 const payload_align = payload_ty.abiAlignment(mod);
1323 const error_align = Type.anyerror.abiAlignment(target);1030 const error_align = Type.anyerror.abiAlignment(mod);
1324 if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime()) {1031 if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1325 return mem.alignForwardGeneric(u64, payload_ty.abiSize(target), error_align);1032 return mem.alignForwardGeneric(u64, payload_ty.abiSize(mod), error_align);
1326 } else {1033 } else {
1327 return 0;1034 return 0;
1328 }1035 }
src/codegen/c.zig+1341-1369
...@@ -16,6 +16,7 @@ const trace = @import("../tracy.zig").trace;...@@ -16,6 +16,7 @@ const trace = @import("../tracy.zig").trace;
16const LazySrcLoc = Module.LazySrcLoc;16const LazySrcLoc = Module.LazySrcLoc;
17const Air = @import("../Air.zig");17const Air = @import("../Air.zig");
18const Liveness = @import("../Liveness.zig");18const Liveness = @import("../Liveness.zig");
19const InternPool = @import("../InternPool.zig");
1920
20const BigIntLimb = std.math.big.Limb;21const BigIntLimb = std.math.big.Limb;
21const BigInt = std.math.big.int;22const BigInt = std.math.big.int;
...@@ -256,7 +257,7 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {...@@ -256,7 +257,7 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
256 return .{ .data = ident };257 return .{ .data = ident };
257}258}
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`.
260/// It is not available when generating .h file.261/// It is not available when generating .h file.
261pub const Function = struct {262pub const Function = struct {
262 air: Air,263 air: Air,
...@@ -267,7 +268,7 @@ pub const Function = struct {...@@ -267,7 +268,7 @@ pub const Function = struct {
267 next_block_index: usize = 0,268 next_block_index: usize = 0,
268 object: Object,269 object: Object,
269 lazy_fns: LazyFnMap,270 lazy_fns: LazyFnMap,
270 func: *Module.Fn,271 func_index: Module.Fn.Index,
271 /// All the locals, to be emitted at the top of the function.272 /// All the locals, to be emitted at the top of the function.
272 locals: std.ArrayListUnmanaged(Local) = .{},273 locals: std.ArrayListUnmanaged(Local) = .{},
273 /// Which locals are available for reuse, based on Type.274 /// Which locals are available for reuse, based on Type.
...@@ -285,10 +286,11 @@ pub const Function = struct {...@@ -285,10 +286,11 @@ pub const Function = struct {
285 const gop = try f.value_map.getOrPut(inst);286 const gop = try f.value_map.getOrPut(inst);
286 if (gop.found_existing) return gop.value_ptr.*;287 if (gop.found_existing) return gop.value_ptr.*;
287288
288 const val = f.air.value(ref).?;289 const mod = f.object.dg.module;
289 const ty = f.air.typeOf(ref);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: {
292 const writer = f.object.code_header.writer();294 const writer = f.object.code_header.writer();
293 const alignment = 0;295 const alignment = 0;
294 const decl_c_value = try f.allocLocalValue(ty, alignment);296 const decl_c_value = try f.allocLocalValue(ty, alignment);
...@@ -318,11 +320,11 @@ pub const Function = struct {...@@ -318,11 +320,11 @@ pub const Function = struct {
318 /// those which go into `allocs`. This function does not add the resulting local into `allocs`;320 /// those which go into `allocs`. This function does not add the resulting local into `allocs`;
319 /// that responsibility lies with the caller.321 /// that responsibility lies with the caller.
320 fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue {322 fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue {
323 const mod = f.object.dg.module;
321 const gpa = f.object.dg.gpa;324 const gpa = f.object.dg.gpa;
322 const target = f.object.dg.module.getTarget();
323 try f.locals.append(gpa, .{325 try f.locals.append(gpa, .{
324 .cty_idx = try f.typeToIndex(ty, .complete),326 .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)),
326 });328 });
327 return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) };329 return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) };
328 }330 }
...@@ -336,10 +338,10 @@ pub const Function = struct {...@@ -336,10 +338,10 @@ pub const Function = struct {
336 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should338 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should
337 /// not be used for persistent locals (i.e. those in `allocs`).339 /// not be used for persistent locals (i.e. those in `allocs`).
338 fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue {340 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;
340 if (f.free_locals_map.getPtr(.{342 if (f.free_locals_map.getPtr(.{
341 .cty_idx = try f.typeToIndex(ty, .complete),343 .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)),
343 })) |locals_list| {345 })) |locals_list| {
344 if (locals_list.popOrNull()) |local_entry| {346 if (locals_list.popOrNull()) |local_entry| {
345 return .{ .new_local = local_entry.key };347 return .{ .new_local = local_entry.key };
...@@ -352,8 +354,9 @@ pub const Function = struct {...@@ -352,8 +354,9 @@ pub const Function = struct {
352 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {354 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
353 switch (c_value) {355 switch (c_value) {
354 .constant => |inst| {356 .constant => |inst| {
355 const ty = f.air.typeOf(inst);357 const mod = f.object.dg.module;
356 const val = f.air.value(inst).?;358 const ty = f.typeOf(inst);
359 const val = (try f.air.value(inst, mod)).?;
357 return f.object.dg.renderValue(w, ty, val, location);360 return f.object.dg.renderValue(w, ty, val, location);
358 },361 },
359 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),362 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
...@@ -364,8 +367,9 @@ pub const Function = struct {...@@ -364,8 +367,9 @@ pub const Function = struct {
364 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {367 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
365 switch (c_value) {368 switch (c_value) {
366 .constant => |inst| {369 .constant => |inst| {
367 const ty = f.air.typeOf(inst);370 const mod = f.object.dg.module;
368 const val = f.air.value(inst).?;371 const ty = f.typeOf(inst);
372 const val = (try f.air.value(inst, mod)).?;
369 try w.writeAll("(*");373 try w.writeAll("(*");
370 try f.object.dg.renderValue(w, ty, val, .Other);374 try f.object.dg.renderValue(w, ty, val, .Other);
371 return w.writeByte(')');375 return w.writeByte(')');
...@@ -377,8 +381,9 @@ pub const Function = struct {...@@ -377,8 +381,9 @@ pub const Function = struct {
377 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {381 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
378 switch (c_value) {382 switch (c_value) {
379 .constant => |inst| {383 .constant => |inst| {
380 const ty = f.air.typeOf(inst);384 const mod = f.object.dg.module;
381 const val = f.air.value(inst).?;385 const ty = f.typeOf(inst);
386 const val = (try f.air.value(inst, mod)).?;
382 try f.object.dg.renderValue(w, ty, val, .Other);387 try f.object.dg.renderValue(w, ty, val, .Other);
383 try w.writeByte('.');388 try w.writeByte('.');
384 return f.writeCValue(w, member, .Other);389 return f.writeCValue(w, member, .Other);
...@@ -390,8 +395,9 @@ pub const Function = struct {...@@ -390,8 +395,9 @@ pub const Function = struct {
390 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {395 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
391 switch (c_value) {396 switch (c_value) {
392 .constant => |inst| {397 .constant => |inst| {
393 const ty = f.air.typeOf(inst);398 const mod = f.object.dg.module;
394 const val = f.air.value(inst).?;399 const ty = f.typeOf(inst);
400 const val = (try f.air.value(inst, mod)).?;
395 try w.writeByte('(');401 try w.writeByte('(');
396 try f.object.dg.renderValue(w, ty, val, .Other);402 try f.object.dg.renderValue(w, ty, val, .Other);
397 try w.writeAll(")->");403 try w.writeAll(")->");
...@@ -446,6 +452,7 @@ pub const Function = struct {...@@ -446,6 +452,7 @@ pub const Function = struct {
446 var promoted = f.object.dg.ctypes.promote(gpa);452 var promoted = f.object.dg.ctypes.promote(gpa);
447 defer f.object.dg.ctypes.demote(promoted);453 defer f.object.dg.ctypes.demote(promoted);
448 const arena = promoted.arena.allocator();454 const arena = promoted.arena.allocator();
455 const mod = f.object.dg.module;
449456
450 gop.value_ptr.* = .{457 gop.value_ptr.* = .{
451 .fn_name = switch (key) {458 .fn_name = switch (key) {
...@@ -454,12 +461,12 @@ pub const Function = struct {...@@ -454,12 +461,12 @@ pub const Function = struct {
454 .never_inline,461 .never_inline,
455 => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{462 => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{
456 @tagName(key),463 @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)),
458 @enumToInt(owner_decl),465 @enumToInt(owner_decl),
459 }),466 }),
460 },467 },
461 .data = switch (key) {468 .data = switch (key) {
462 .tag_name => .{ .tag_name = try data.tag_name.copy(arena) },469 .tag_name => .{ .tag_name = data.tag_name },
463 .never_tail => .{ .never_tail = data.never_tail },470 .never_tail => .{ .never_tail = data.never_tail },
464 .never_inline => .{ .never_inline = data.never_inline },471 .never_inline => .{ .never_inline = data.never_inline },
465 },472 },
...@@ -480,6 +487,16 @@ pub const Function = struct {...@@ -480,6 +487,16 @@ pub const Function = struct {
480 f.object.dg.ctypes.deinit(gpa);487 f.object.dg.ctypes.deinit(gpa);
481 f.object.dg.fwd_decl.deinit();488 f.object.dg.fwd_decl.deinit();
482 }489 }
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 }
483};500};
484501
485/// This data is available when outputting .c code for a `Module`.502/// This data is available when outputting .c code for a `Module`.
...@@ -508,8 +525,9 @@ pub const DeclGen = struct {...@@ -508,8 +525,9 @@ pub const DeclGen = struct {
508525
509 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {526 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
510 @setCold(true);527 @setCold(true);
528 const mod = dg.module;
511 const src = LazySrcLoc.nodeOffset(0);529 const src = LazySrcLoc.nodeOffset(0);
512 const src_loc = src.toSrcLoc(dg.decl.?);530 const src_loc = src.toSrcLoc(dg.decl.?, mod);
513 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);531 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
514 return error.AnalysisFail;532 return error.AnalysisFail;
515 }533 }
...@@ -522,53 +540,28 @@ pub const DeclGen = struct {...@@ -522,53 +540,28 @@ pub const DeclGen = struct {
522 decl_index: Decl.Index,540 decl_index: Decl.Index,
523 location: ValueRenderLocation,541 location: ValueRenderLocation,
524 ) error{ OutOfMemory, AnalysisFail }!void {542 ) error{ OutOfMemory, AnalysisFail }!void {
525 const decl = dg.module.declPtr(decl_index);543 const mod = dg.module;
544 const decl = mod.declPtr(decl_index);
526 assert(decl.has_tv);545 assert(decl.has_tv);
527546
528 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.547 // 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)) {
530 return dg.writeCValue(writer, .{ .undef = ty });549 return dg.writeCValue(writer, .{ .undef = ty });
531 }550 }
532551
533 // Chase function values in order to be able to reference the original function.552 // Chase function values in order to be able to reference the original function.
534 inline for (.{ .function, .extern_fn }) |tag|553 if (decl.val.getFunction(mod)) |func| if (func.owner_decl != decl_index)
535 if (decl.val.castTag(tag)) |func|554 return dg.renderDeclValue(writer, ty, val, func.owner_decl, location);
536 if (func.data.owner_decl != decl_index)555 if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
537 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location);556 return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);
538557
539 if (decl.val.castTag(.variable)) |var_payload|558 if (decl.val.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable);
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 }
566559
567 // We shouldn't cast C function pointers as this is UB (when you call560 // We shouldn't cast C function pointers as this is UB (when you call
568 // them). The analysis until now should ensure that the C function561 // them). The analysis until now should ensure that the C function
569 // pointers are compatible. If they are not, then there is a bug562 // pointers are compatible. If they are not, then there is a bug
570 // somewhere and we should let the C compiler tell us about it.563 // 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);
572 if (need_typecast) {565 if (need_typecast) {
573 try writer.writeAll("((");566 try writer.writeAll("((");
574 try dg.renderType(writer, ty);567 try dg.renderType(writer, ty);
...@@ -579,127 +572,124 @@ pub const DeclGen = struct {...@@ -579,127 +572,124 @@ pub const DeclGen = struct {
579 if (need_typecast) try writer.writeByte(')');572 if (need_typecast) try writer.writeByte(')');
580 }573 }
581574
582 // Renders a "parent" pointer by recursing to the root decl/variable575 /// Renders a "parent" pointer by recursing to the root decl/variable
583 // that its contents are defined with respect to.576 /// that its contents are defined with respect to.
584 //577 fn renderParentPtr(
585 // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr578 dg: *DeclGen,
586 fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void {579 writer: anytype,
587 if (!ptr_ty.isSlice()) {580 ptr_val: InternPool.Index,
588 try writer.writeByte('(');581 location: ValueRenderLocation,
589 try dg.renderType(writer, ptr_ty);582 ) error{ OutOfMemory, AnalysisFail }!void {
590 try writer.writeByte(')');583 const mod = dg.module;
591 }584 const ptr_ty = mod.intern_pool.typeOf(ptr_val).toType();
592 switch (ptr_val.tag()) {585 const ptr_cty = try dg.typeToIndex(ptr_ty, .complete);
593 .int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val, .Other)}),586 const ptr = mod.intern_pool.indexToKey(ptr_val).ptr;
594 .decl_ref_mut, .decl_ref, .variable => {587 switch (ptr.addr) {
595 const decl_index = switch (ptr_val.tag()) {588 .decl, .mut_decl => try dg.renderDeclValue(
596 .decl_ref => ptr_val.castTag(.decl_ref).?.data,589 writer,
597 .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index,590 ptr_ty,
598 .variable => ptr_val.castTag(.variable).?.data.owner_decl,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),
599 else => unreachable,610 else => unreachable,
600 };611 };
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");
602 },622 },
603 .field_ptr => {623 .elem => |elem| {
604 const target = dg.module.getTarget();624 const ptr_base_ty = mod.intern_pool.typeOf(elem.base).toType();
605 const field_ptr = ptr_val.castTag(.field_ptr).?.data;625 const elem_ty = ptr_base_ty.elemType2(mod);
606626 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);
607 // Ensure complete type definition is visible before accessing fields.642 // Ensure complete type definition is visible before accessing fields.
608 _ = try dg.typeToIndex(field_ptr.container_ty, .complete);643 _ = try dg.typeToIndex(base_ty, .complete);
609644 const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) {
610 var container_ptr_pl = ptr_ty.ptrInfo();645 .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(@intCast(usize, field.index), mod),
611 container_ptr_pl.data.pointee_type = field_ptr.container_ty;646 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
612 const container_ptr_ty = Type.initPayload(&container_ptr_pl.base);647 .One, .Many, .C => unreachable,
613648 .Slice => switch (field.index) {
614 switch (fieldLocation(649 Value.slice_ptr_index => base_ty.slicePtrFieldType(mod),
615 field_ptr.container_ty,650 Value.slice_len_index => Type.usize,
616 ptr_ty,651 else => unreachable,
617 @intCast(u32, field_ptr.field_index),652 },
618 target,653 },
619 )) {654 else => unreachable,
620 .begin => try dg.renderParentPtr(655 };
621 writer,656 const ptr_field_ty = try mod.adjustPtrTypeChild(ptr_base_ty, field_ty);
622 field_ptr.container_ptr,657 const ptr_field_cty = try dg.typeToIndex(ptr_field_ty, .complete);
623 container_ptr_ty,658 if (ptr_cty != ptr_field_cty) {
624 location,659 try writer.writeByte('(');
625 ),660 try dg.renderCType(writer, ptr_cty);
626 .field => |field| {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| {
627 try writer.writeAll("&(");666 try writer.writeAll("&(");
628 try dg.renderParentPtr(667 try dg.renderParentPtr(writer, field.base, location);
629 writer,
630 field_ptr.container_ptr,
631 container_ptr_ty,
632 location,
633 );
634 try writer.writeAll(")->");668 try writer.writeAll(")->");
635 try dg.writeCValue(writer, field);669 try dg.writeCValue(writer, name);
636 },670 },
637 .byte_offset => |byte_offset| {671 .byte_offset => |byte_offset| {
638 var u8_ptr_pl = ptr_ty.ptrInfo();672 const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8);
639 u8_ptr_pl.data.pointee_type = Type.u8;673 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
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);
647674
648 try writer.writeAll("((");675 try writer.writeAll("((");
649 try dg.renderType(writer, u8_ptr_ty);676 try dg.renderType(writer, u8_ptr_ty);
650 try writer.writeByte(')');677 try writer.writeByte(')');
651 try dg.renderParentPtr(678 try dg.renderParentPtr(writer, field.base, location);
652 writer,
653 field_ptr.container_ptr,
654 container_ptr_ty,
655 location,
656 );
657 try writer.print(" + {})", .{679 try writer.print(" + {})", .{
658 try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),680 try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),
659 });681 });
660 },682 },
661 .end => {683 .end => {
662 try writer.writeAll("((");684 try writer.writeAll("((");
663 try dg.renderParentPtr(685 try dg.renderParentPtr(writer, field.base, location);
664 writer,
665 field_ptr.container_ptr,
666 container_ptr_ty,
667 location,
668 );
669 try writer.print(") + {})", .{686 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),
671 });688 });
672 },689 },
673 }690 }
674 },691 },
675 .elem_ptr => {692 .comptime_field => unreachable,
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,
703 }693 }
704 }694 }
705695
...@@ -710,23 +700,25 @@ pub const DeclGen = struct {...@@ -710,23 +700,25 @@ pub const DeclGen = struct {
710 arg_val: Value,700 arg_val: Value,
711 location: ValueRenderLocation,701 location: ValueRenderLocation,
712 ) error{ OutOfMemory, AnalysisFail }!void {702 ) error{ OutOfMemory, AnalysisFail }!void {
703 const mod = dg.module;
713 var val = arg_val;704 var val = arg_val;
714 if (val.castTag(.runtime_value)) |rt| {705 switch (mod.intern_pool.indexToKey(val.ip_index)) {
715 val = rt.data;706 .runtime_value => |rt| val = rt.val.toValue(),
707 else => {},
716 }708 }
717 const target = dg.module.getTarget();709 const target = mod.getTarget();
718 const initializer_type: ValueRenderLocation = switch (location) {710 const initializer_type: ValueRenderLocation = switch (location) {
719 .StaticInitializer => .StaticInitializer,711 .StaticInitializer => .StaticInitializer,
720 else => .Initializer,712 else => .Initializer,
721 };713 };
722714
723 const safety_on = switch (dg.module.optimizeMode()) {715 const safety_on = switch (mod.optimizeMode()) {
724 .Debug, .ReleaseSafe => true,716 .Debug, .ReleaseSafe => true,
725 .ReleaseFast, .ReleaseSmall => false,717 .ReleaseFast, .ReleaseSmall => false,
726 };718 };
727719
728 if (val.isUndefDeep()) {720 if (val.isUndefDeep(mod)) {
729 switch (ty.zigTypeTag()) {721 switch (ty.zigTypeTag(mod)) {
730 .Bool => {722 .Bool => {
731 if (safety_on) {723 if (safety_on) {
732 return writer.writeAll("0xaa");724 return writer.writeAll("0xaa");
...@@ -737,8 +729,8 @@ pub const DeclGen = struct {...@@ -737,8 +729,8 @@ pub const DeclGen = struct {
737 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}),729 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}),
738 .Float => {730 .Float => {
739 const bits = ty.floatBits(target);731 const bits = ty.floatBits(target);
740 var repr_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = bits };732 // All unsigned ints matching float types are pre-allocated.
741 const repr_ty = Type.initPayload(&repr_pl.base);733 const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
742734
743 try writer.writeAll("zig_cast_");735 try writer.writeAll("zig_cast_");
744 try dg.renderTypeForBuiltinFnName(writer, ty);736 try dg.renderTypeForBuiltinFnName(writer, ty);
...@@ -757,7 +749,7 @@ pub const DeclGen = struct {...@@ -757,7 +749,7 @@ pub const DeclGen = struct {
757 try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument);749 try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument);
758 return writer.writeByte(')');750 return writer.writeByte(')');
759 },751 },
760 .Pointer => if (ty.isSlice()) {752 .Pointer => if (ty.isSlice(mod)) {
761 if (!location.isInitializer()) {753 if (!location.isInitializer()) {
762 try writer.writeByte('(');754 try writer.writeByte('(');
763 try dg.renderType(writer, ty);755 try dg.renderType(writer, ty);
...@@ -765,8 +757,7 @@ pub const DeclGen = struct {...@@ -765,8 +757,7 @@ pub const DeclGen = struct {
765 }757 }
766758
767 try writer.writeAll("{(");759 try writer.writeAll("{(");
768 var buf: Type.SlicePtrFieldTypeBuffer = undefined;760 const ptr_ty = ty.slicePtrFieldType(mod);
769 const ptr_ty = ty.slicePtrFieldType(&buf);
770 try dg.renderType(writer, ptr_ty);761 try dg.renderType(writer, ptr_ty);
771 return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});762 return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
772 } else {763 } else {
...@@ -775,14 +766,13 @@ pub const DeclGen = struct {...@@ -775,14 +766,13 @@ pub const DeclGen = struct {
775 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});766 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
776 },767 },
777 .Optional => {768 .Optional => {
778 var opt_buf: Type.Payload.ElemType = undefined;769 const payload_ty = ty.optionalChild(mod);
779 const payload_ty = ty.optionalChild(&opt_buf);
780770
781 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {771 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
782 return dg.renderValue(writer, Type.bool, val, location);772 return dg.renderValue(writer, Type.bool, val, location);
783 }773 }
784774
785 if (ty.optionalReprIsPayload()) {775 if (ty.optionalReprIsPayload(mod)) {
786 return dg.renderValue(writer, payload_ty, val, location);776 return dg.renderValue(writer, payload_ty, val, location);
787 }777 }
788778
...@@ -798,7 +788,7 @@ pub const DeclGen = struct {...@@ -798,7 +788,7 @@ pub const DeclGen = struct {
798 try dg.renderValue(writer, Type.bool, val, initializer_type);788 try dg.renderValue(writer, Type.bool, val, initializer_type);
799 return writer.writeAll(" }");789 return writer.writeAll(" }");
800 },790 },
801 .Struct => switch (ty.containerLayout()) {791 .Struct => switch (ty.containerLayout(mod)) {
802 .Auto, .Extern => {792 .Auto, .Extern => {
803 if (!location.isInitializer()) {793 if (!location.isInitializer()) {
804 try writer.writeByte('(');794 try writer.writeByte('(');
...@@ -808,10 +798,10 @@ pub const DeclGen = struct {...@@ -808,10 +798,10 @@ pub const DeclGen = struct {
808798
809 try writer.writeByte('{');799 try writer.writeByte('{');
810 var empty = true;800 var empty = true;
811 for (0..ty.structFieldCount()) |field_i| {801 for (0..ty.structFieldCount(mod)) |field_i| {
812 if (ty.structFieldIsComptime(field_i)) continue;802 if (ty.structFieldIsComptime(field_i, mod)) continue;
813 const field_ty = ty.structFieldType(field_i);803 const field_ty = ty.structFieldType(field_i, mod);
814 if (!field_ty.hasRuntimeBits()) continue;804 if (!field_ty.hasRuntimeBits(mod)) continue;
815805
816 if (!empty) try writer.writeByte(',');806 if (!empty) try writer.writeByte(',');
817 try dg.renderValue(writer, field_ty, val, initializer_type);807 try dg.renderValue(writer, field_ty, val, initializer_type);
...@@ -831,29 +821,29 @@ pub const DeclGen = struct {...@@ -831,29 +821,29 @@ pub const DeclGen = struct {
831 }821 }
832822
833 try writer.writeByte('{');823 try writer.writeByte('{');
834 if (ty.unionTagTypeSafety()) |tag_ty| {824 if (ty.unionTagTypeSafety(mod)) |tag_ty| {
835 const layout = ty.unionGetLayout(target);825 const layout = ty.unionGetLayout(mod);
836 if (layout.tag_size != 0) {826 if (layout.tag_size != 0) {
837 try writer.writeAll(" .tag = ");827 try writer.writeAll(" .tag = ");
838 try dg.renderValue(writer, tag_ty, val, initializer_type);828 try dg.renderValue(writer, tag_ty, val, initializer_type);
839 }829 }
840 if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}');830 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
841 if (layout.tag_size != 0) try writer.writeByte(',');831 if (layout.tag_size != 0) try writer.writeByte(',');
842 try writer.writeAll(" .payload = {");832 try writer.writeAll(" .payload = {");
843 }833 }
844 for (ty.unionFields().values()) |field| {834 for (ty.unionFields(mod).values()) |field| {
845 if (!field.ty.hasRuntimeBits()) continue;835 if (!field.ty.hasRuntimeBits(mod)) continue;
846 try dg.renderValue(writer, field.ty, val, initializer_type);836 try dg.renderValue(writer, field.ty, val, initializer_type);
847 break;837 break;
848 }838 }
849 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');839 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
850 return writer.writeByte('}');840 return writer.writeByte('}');
851 },841 },
852 .ErrorUnion => {842 .ErrorUnion => {
853 const payload_ty = ty.errorUnionPayload();843 const payload_ty = ty.errorUnionPayload(mod);
854 const error_ty = ty.errorUnionSet();844 const error_ty = ty.errorUnionSet(mod);
855845
856 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {846 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
857 return dg.renderValue(writer, error_ty, val, location);847 return dg.renderValue(writer, error_ty, val, location);
858 }848 }
859849
...@@ -870,11 +860,11 @@ pub const DeclGen = struct {...@@ -870,11 +860,11 @@ pub const DeclGen = struct {
870 return writer.writeAll(" }");860 return writer.writeAll(" }");
871 },861 },
872 .Array, .Vector => {862 .Array, .Vector => {
873 const ai = ty.arrayInfo();863 const ai = ty.arrayInfo(mod);
874 if (ai.elem_type.eql(Type.u8, dg.module)) {864 if (ai.elem_type.eql(Type.u8, mod)) {
875 var literal = stringLiteral(writer);865 var literal = stringLiteral(writer);
876 try literal.start();866 try literal.start();
877 const c_len = ty.arrayLenIncludingSentinel();867 const c_len = ty.arrayLenIncludingSentinel(mod);
878 var index: u64 = 0;868 var index: u64 = 0;
879 while (index < c_len) : (index += 1)869 while (index < c_len) : (index += 1)
880 try literal.writeChar(0xaa);870 try literal.writeChar(0xaa);
...@@ -887,11 +877,11 @@ pub const DeclGen = struct {...@@ -887,11 +877,11 @@ pub const DeclGen = struct {
887 }877 }
888878
889 try writer.writeByte('{');879 try writer.writeByte('{');
890 const c_len = ty.arrayLenIncludingSentinel();880 const c_len = ty.arrayLenIncludingSentinel(mod);
891 var index: u64 = 0;881 var index: u64 = 0;
892 while (index < c_len) : (index += 1) {882 while (index < c_len) : (index += 1) {
893 if (index > 0) try writer.writeAll(", ");883 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);
895 }885 }
896 return writer.writeByte('}');886 return writer.writeByte('}');
897 }887 }
...@@ -916,23 +906,129 @@ pub const DeclGen = struct {...@@ -916,23 +906,129 @@ pub const DeclGen = struct {
916 }906 }
917 unreachable;907 unreachable;
918 }908 }
919 switch (ty.zigTypeTag()) {909
920 .Int => switch (val.tag()) {910 switch (mod.intern_pool.indexToKey(val.ip_index)) {
921 .field_ptr,911 // types, not values
922 .elem_ptr,912 .int_type,
923 .opt_payload_ptr,913 .ptr_type,
924 .eu_payload_ptr,914 .array_type,
925 .decl_ref_mut,915 .vector_type,
926 .decl_ref,916 .opt_type,
927 => try dg.renderParentPtr(writer, val, ty, location),917 .anyframe_type,
928 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),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"),
929 },944 },
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 => {
931 const bits = ty.floatBits(target);1027 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 };1030 // All unsigned ints matching float types are pre-allocated.
935 const repr_ty = Type.initPayload(&repr_ty_pl.base);1031 const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
9361032
937 assert(bits <= 128);1033 assert(bits <= 128);
938 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;1034 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
...@@ -943,21 +1039,15 @@ pub const DeclGen = struct {...@@ -943,21 +1039,15 @@ pub const DeclGen = struct {
943 };1039 };
9441040
945 switch (bits) {1041 switch (bits) {
946 16 => repr_val_big.set(@bitCast(u16, val.toFloat(f16))),1042 16 => repr_val_big.set(@bitCast(u16, val.toFloat(f16, mod))),
947 32 => repr_val_big.set(@bitCast(u32, val.toFloat(f32))),1043 32 => repr_val_big.set(@bitCast(u32, val.toFloat(f32, mod))),
948 64 => repr_val_big.set(@bitCast(u64, val.toFloat(f64))),1044 64 => repr_val_big.set(@bitCast(u64, val.toFloat(f64, mod))),
949 80 => repr_val_big.set(@bitCast(u80, val.toFloat(f80))),1045 80 => repr_val_big.set(@bitCast(u80, val.toFloat(f80, mod))),
950 128 => repr_val_big.set(@bitCast(u128, f128_val)),1046 128 => repr_val_big.set(@bitCast(u128, f128_val)),
951 else => unreachable,1047 else => unreachable,
952 }1048 }
9531049
954 var repr_val_pl = Value.Payload.BigInt{1050 const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst());
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);
9611051
962 try writer.writeAll("zig_cast_");1052 try writer.writeAll("zig_cast_");
963 try dg.renderTypeForBuiltinFnName(writer, ty);1053 try dg.renderTypeForBuiltinFnName(writer, ty);
...@@ -968,10 +1058,10 @@ pub const DeclGen = struct {...@@ -968,10 +1058,10 @@ pub const DeclGen = struct {
968 try dg.renderTypeForBuiltinFnName(writer, ty);1058 try dg.renderTypeForBuiltinFnName(writer, ty);
969 try writer.writeByte('(');1059 try writer.writeByte('(');
970 switch (bits) {1060 switch (bits) {
971 16 => try writer.print("{x}", .{val.toFloat(f16)}),1061 16 => try writer.print("{x}", .{val.toFloat(f16, mod)}),
972 32 => try writer.print("{x}", .{val.toFloat(f32)}),1062 32 => try writer.print("{x}", .{val.toFloat(f32, mod)}),
973 64 => try writer.print("{x}", .{val.toFloat(f64)}),1063 64 => try writer.print("{x}", .{val.toFloat(f64, mod)}),
974 80 => try writer.print("{x}", .{val.toFloat(f80)}),1064 80 => try writer.print("{x}", .{val.toFloat(f80, mod)}),
975 128 => try writer.print("{x}", .{f128_val}),1065 128 => try writer.print("{x}", .{f128_val}),
976 else => unreachable,1066 else => unreachable,
977 }1067 }
...@@ -1011,10 +1101,10 @@ pub const DeclGen = struct {...@@ -1011,10 +1101,10 @@ pub const DeclGen = struct {
1011 if (std.math.isNan(f128_val)) switch (bits) {1101 if (std.math.isNan(f128_val)) switch (bits) {
1012 // We only actually need to pass the significand, but it will get1102 // We only actually need to pass the significand, but it will get
1013 // properly masked anyway, so just pass the whole value.1103 // properly masked anyway, so just pass the whole value.
1014 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}),1104 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16, mod))}),
1015 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}),1105 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32, mod))}),
1016 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}),1106 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64, mod))}),
1017 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}),1107 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80, mod))}),
1018 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),1108 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
1019 else => unreachable,1109 else => unreachable,
1020 };1110 };
...@@ -1023,173 +1113,80 @@ pub const DeclGen = struct {...@@ -1023,173 +1113,80 @@ pub const DeclGen = struct {
1023 }1113 }
1024 try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)});1114 try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)});
1025 if (!empty) try writer.writeByte(')');1115 if (!empty) try writer.writeByte(')');
1026 return;
1027 },1116 },
1028 .Pointer => switch (val.tag()) {1117 .ptr => |ptr| {
1029 .null_value, .zero => if (ty.isSlice()) {1118 if (ptr.len != .none) {
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 => {
1047 if (!location.isInitializer()) {1119 if (!location.isInitializer()) {
1048 try writer.writeByte('(');1120 try writer.writeByte('(');
1049 try dg.renderType(writer, ty);1121 try dg.renderType(writer, ty);
1050 try writer.writeByte(')');1122 try writer.writeByte(')');
1051 }1123 }
1052
1053 const slice = val.castTag(.slice).?.data;
1054 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1055
1056 try writer.writeByte('{');1124 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(')');
1089 }1125 }
10901126 const ptr_location = switch (ptr.len) {
1091 // First try specific tag representations for more efficiency.1127 .none => location,
1092 switch (val.tag()) {1128 else => initializer_type,
1093 .undef, .empty_struct_value, .empty_array => {1129 };
1094 const ai = ty.arrayInfo();1130 const ptr_ty = switch (ptr.len) {
1095 try writer.writeByte('{');1131 .none => ty,
1096 if (ai.sentinel) |s| {1132 else => ty.slicePtrFieldType(mod),
1097 try dg.renderValue(writer, ai.elem_type, s, initializer_type);1133 };
1098 } else {1134 const ptr_val = switch (ptr.len) {
1099 try writer.writeByte('0');1135 .none => val,
1100 }1136 else => val.slicePtr(mod),
1101 try writer.writeByte('}');1137 };
1102 },1138 switch (ptr.addr) {
1103 .bytes, .str_lit => |t| {1139 .decl, .mut_decl => try dg.renderDeclValue(
1104 const bytes = switch (t) {1140 writer,
1105 .bytes => val.castTag(.bytes).?.data,1141 ptr_ty,
1106 .str_lit => bytes: {1142 ptr_val,
1107 const str_lit = val.castTag(.str_lit).?.data;1143 switch (ptr.addr) {
1108 break :bytes dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];1144 .decl => |decl| decl,
1109 },1145 .mut_decl => |mut_decl| mut_decl.decl,
1110 else => unreachable,1146 else => unreachable,
1111 };1147 },
1112 const sentinel = if (ty.sentinel()) |sentinel| @intCast(u8, sentinel.toUnsignedInt(target)) else null;1148 ptr_location,
1113 try writer.print("{s}", .{1149 ),
1114 fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen())], sentinel),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),
1115 });1155 });
1116 },1156 },
1117 else => {1157 .eu_payload,
1118 // Fall back to generic implementation.1158 .opt_payload,
1119 var arena = std.heap.ArenaAllocator.init(dg.gpa);1159 .elem,
1120 defer arena.deinit();1160 .field,
1121 const arena_allocator = arena.allocator();1161 => try dg.renderParentPtr(writer, ptr_val.ip_index, ptr_location),
11221162 .comptime_field => unreachable,
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 },
1172 }1163 }
1173 },1164 if (ptr.len != .none) {
1174 .Bool => {1165 try writer.writeAll(", ");
1175 if (val.toBool()) {1166 try dg.renderValue(writer, Type.usize, ptr.len.toValue(), initializer_type);
1176 return writer.writeAll("true");1167 try writer.writeByte('}');
1177 } else {
1178 return writer.writeAll("false");
1179 }1168 }
1180 },1169 },
1181 .Optional => {1170 .opt => |opt| {
1182 var opt_buf: Type.Payload.ElemType = undefined;1171 const payload_ty = ty.optionalChild(mod);
1183 const payload_ty = ty.optionalChild(&opt_buf);
11841172
1185 const is_null_val = Value.makeBool(val.tag() == .null_value);1173 const is_null_val = Value.makeBool(opt.val == .none);
1186 if (!payload_ty.hasRuntimeBitsIgnoreComptime())1174 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
1187 return dg.renderValue(writer, Type.bool, is_null_val, location);1175 return dg.renderValue(writer, Type.bool, is_null_val, location);
11881176
1189 if (ty.optionalReprIsPayload()) {1177 if (ty.optionalReprIsPayload(mod)) return dg.renderValue(
1190 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val;1178 writer,
1191 return dg.renderValue(writer, payload_ty, payload_val, location);1179 payload_ty,
1192 }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
1194 if (!location.isInitializer()) {1191 if (!location.isInitializer()) {
1195 try writer.writeByte('(');1192 try writer.writeByte('(');
...@@ -1197,93 +1194,74 @@ pub const DeclGen = struct {...@@ -1197,93 +1194,74 @@ pub const DeclGen = struct {
1197 try writer.writeByte(')');1194 try writer.writeByte(')');
1198 }1195 }
11991196
1200 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef;
1201
1202 try writer.writeAll("{ .payload = ");1197 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);
1204 try writer.writeAll(", .is_null = ");1202 try writer.writeAll(", .is_null = ");
1205 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);1203 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
1206 try writer.writeAll(" }");1204 try writer.writeAll(" }");
1207 },1205 },
1208 .ErrorSet => {1206 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1209 if (val.castTag(.@"error")) |error_pl| {1207 .array_type, .vector_type => {
1210 // Error values are already defined by genErrDecls.1208 if (location == .FunctionArgument) {
1211 try writer.print("zig_error_{}", .{fmtIdent(error_pl.data.name)});1209 try writer.writeByte('(');
1212 } else {1210 try dg.renderType(writer, ty);
1213 try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, .Other)});1211 try writer.writeByte(')');
1214 }1212 }
1215 },1213 // Fall back to generic implementation.
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;
12201214
1221 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1215 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal
1222 return dg.renderValue(writer, error_ty, error_val, location);1216 const max_string_initializer_len = 65535;
1223 }
12241217
1225 if (!location.isInitializer()) {1218 const ai = ty.arrayInfo(mod);
1226 try writer.writeByte('(');1219 if (ai.elem_type.eql(Type.u8, mod)) {
1227 try dg.renderType(writer, ty);1220 if (ai.len <= max_string_initializer_len) {
1228 try writer.writeByte(')');1221 var literal = stringLiteral(writer);
1229 }1222 try literal.start();
12301223 var index: usize = 0;
1231 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;1224 while (index < ai.len) : (index += 1) {
1232 try writer.writeAll("{ .payload = ");1225 const elem_val = try val.elemValue(mod, index);
1233 try dg.renderValue(writer, payload_ty, payload_val, initializer_type);1226 const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod));
1234 try writer.writeAll(", .error = ");1227 try literal.writeChar(elem_val_u8);
1235 try dg.renderValue(writer, error_ty, error_val, initializer_type);1228 }
1236 try writer.writeAll(" }");1229 if (ai.sentinel) |s| {
1237 },1230 const s_u8 = @intCast(u8, s.toUnsignedInt(mod));
1238 .Enum => {1231 if (s_u8 != 0) try literal.writeChar(s_u8);
1239 switch (val.tag()) {1232 }
1240 .enum_field_index => {1233 try literal.end();
1241 const field_index = val.castTag(.enum_field_index).?.data;1234 } else {
1242 switch (ty.tag()) {1235 try writer.writeByte('{');
1243 .enum_simple => return writer.print("{d}", .{field_index}),1236 var index: usize = 0;
1244 .enum_full, .enum_nonexhaustive => {1237 while (index < ai.len) : (index += 1) {
1245 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;1238 if (index != 0) try writer.writeByte(',');
1246 if (enum_full.values.count() != 0) {1239 const elem_val = try val.elemValue(mod, index);
1247 const tag_val = enum_full.values.keys()[field_index];1240 const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod));
1248 return dg.renderValue(writer, enum_full.tag_ty, tag_val, location);1241 try writer.print("'\\x{x}'", .{elem_val_u8});
1249 } else {1242 }
1250 return writer.print("{d}", .{field_index});1243 if (ai.sentinel) |s| {
1251 }1244 if (index != 0) try writer.writeByte(',');
1252 },1245 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1253 .enum_numbered => {1246 }
1254 const enum_obj = ty.castTag(.enum_numbered).?.data;1247 try writer.writeByte('}');
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,
1263 }1248 }
1264 },1249 } else {
1265 else => {1250 try writer.writeByte('{');
1266 var int_tag_ty_buffer: Type.Payload.Bits = undefined;1251 var index: usize = 0;
1267 const int_tag_ty = ty.intTagType(&int_tag_ty_buffer);1252 while (index < ai.len) : (index += 1) {
1268 return dg.renderValue(writer, int_tag_ty, val, location);1253 if (index != 0) try writer.writeByte(',');
1269 },1254 const elem_val = try val.elemValue(mod, index);
1270 }1255 try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type);
1271 },1256 }
1272 .Fn => switch (val.tag()) {1257 if (ai.sentinel) |s| {
1273 .function => {1258 if (index != 0) try writer.writeByte(',');
1274 const decl = val.castTag(.function).?.data.owner_decl;1259 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1275 return dg.renderDeclValue(writer, ty, val, decl, location);1260 }
1276 },1261 try writer.writeByte('}');
1277 .extern_fn => {1262 }
1278 const decl = val.castTag(.extern_fn).?.data.owner_decl;
1279 return dg.renderDeclValue(writer, ty, val, decl, location);
1280 },1263 },
1281 else => unreachable,1264 .anon_struct_type => |tuple| {
1282 },
1283 .Struct => switch (ty.containerLayout()) {
1284 .Auto, .Extern => {
1285 const field_vals = val.castTag(.aggregate).?.data;
1286
1287 if (!location.isInitializer()) {1265 if (!location.isInitializer()) {
1288 try writer.writeByte('(');1266 try writer.writeByte('(');
1289 try dg.renderType(writer, ty);1267 try dg.renderType(writer, ty);
...@@ -1292,133 +1270,184 @@ pub const DeclGen = struct {...@@ -1292,133 +1270,184 @@ pub const DeclGen = struct {
12921270
1293 try writer.writeByte('{');1271 try writer.writeByte('{');
1294 var empty = true;1272 var empty = true;
1295 for (field_vals, 0..) |field_val, field_i| {1273 for (tuple.types, tuple.values, 0..) |field_ty, comptime_ty, field_i| {
1296 if (ty.structFieldIsComptime(field_i)) continue;1274 if (comptime_ty != .none) continue;
1297 const field_ty = ty.structFieldType(field_i);1275 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
1298 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
12991276
1300 if (!empty) try writer.writeByte(',');1277 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
1303 empty = false;1289 empty = false;
1304 }1290 }
1305 try writer.writeByte('}');1291 try writer.writeByte('}');
1306 },1292 },
1307 .Packed => {1293 .struct_type => |struct_type| {
1308 const field_vals = val.castTag(.aggregate).?.data;1294 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1309 const int_info = ty.intInfo(target);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{1303 try writer.writeByte('{');
1312 .base = .{ .tag = .int_unsigned },1304 var empty = true;
1313 .data = Type.smallestUnsignedBits(int_info.bits - 1),1305 for (struct_obj.fields.values(), 0..) |field, field_i| {
1314 };1306 if (field.is_comptime) continue;
1315 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);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 };1327 const bits = Type.smallestUnsignedBits(int_info.bits - 1);
1318 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);1328 const bit_offset_ty = try mod.intType(.unsigned, bits);
13191329
1320 var eff_num_fields: usize = 0;1330 var bit_offset: u64 = 0;
1321 for (0..field_vals.len) |field_i| {1331 var eff_num_fields: usize = 0;
1322 if (ty.structFieldIsComptime(field_i)) continue;
1323 const field_ty = ty.structFieldType(field_i);
1324 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
13251332
1326 eff_num_fields += 1;1333 for (struct_obj.fields.values()) |field| {
1327 }1334 if (field.is_comptime) continue;
1335 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13281336
1329 if (eff_num_fields == 0) {1337 eff_num_fields += 1;
1330 try writer.writeByte('(');1338 }
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 }
13411339
1342 var eff_index: usize = 0;1340 if (eff_num_fields == 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);
1353 try writer.writeByte('(');1341 try writer.writeByte('(');
1354 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);1342 try dg.renderValue(writer, ty, Value.undef, initializer_type);
1355 try writer.writeAll(", ");
1356 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1357 try writer.writeByte(')');1343 try writer.writeByte(')');
1358 } else {1344 } else if (ty.bitSize(mod) > 64) {
1359 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);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))
1360 }1346 var num_or = eff_num_fields - 1;
13611347 while (num_or > 0) : (num_or -= 1) {
1362 if (needs_closing_paren) try writer.writeByte(')');1348 try writer.writeAll("zig_or_");
1363 if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");1349 try dg.renderTypeForBuiltinFnName(writer, ty);
13641350 try writer.writeByte('(');
1365 bit_offset_val_pl.data += field_ty.bitSize(target);1351 }
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(')');
13821352
1383 if (bit_offset_val_pl.data != 0) {1353 var eff_index: usize = 0;
1384 try dg.renderValue(writer, field_ty, field_val, .Other);1354 var needs_closing_paren = false;
1385 try writer.writeAll(" << ");1355 for (struct_obj.fields.values(), 0..) |field, field_i| {
1386 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);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 }
1387 } else {1388 } 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(')');
1389 }1423 }
13901424 },
1391 bit_offset_val_pl.data += field_ty.bitSize(target);
1392 empty = false;
1393 }
1394 try writer.writeByte(')');
1395 }1425 }
1396 },1426 },
1427 else => unreachable,
1397 },1428 },
1398 .Union => {1429 .un => |un| {
1399 const union_obj = val.castTag(.@"union").?.data;
1400
1401 if (!location.isInitializer()) {1430 if (!location.isInitializer()) {
1402 try writer.writeByte('(');1431 try writer.writeByte('(');
1403 try dg.renderType(writer, ty);1432 try dg.renderType(writer, ty);
1404 try writer.writeByte(')');1433 try writer.writeByte(')');
1405 }1434 }
14061435
1407 const field_i = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;1436 const field_i = ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
1408 const field_ty = ty.unionFields().values()[field_i].ty;1437 const field_ty = ty.unionFields(mod).values()[field_i].ty;
1409 const field_name = ty.unionFields().keys()[field_i];1438 const field_name = ty.unionFields(mod).keys()[field_i];
1410 if (ty.containerLayout() == .Packed) {1439 if (ty.containerLayout(mod) == .Packed) {
1411 if (field_ty.hasRuntimeBits()) {1440 if (field_ty.hasRuntimeBits(mod)) {
1412 if (field_ty.isPtrAtRuntime()) {1441 if (field_ty.isPtrAtRuntime(mod)) {
1413 try writer.writeByte('(');1442 try writer.writeByte('(');
1414 try dg.renderType(writer, ty);1443 try dg.renderType(writer, ty);
1415 try writer.writeByte(')');1444 try writer.writeByte(')');
1416 } else if (field_ty.zigTypeTag() == .Float) {1445 } else if (field_ty.zigTypeTag(mod) == .Float) {
1417 try writer.writeByte('(');1446 try writer.writeByte('(');
1418 try dg.renderType(writer, ty);1447 try dg.renderType(writer, ty);
1419 try writer.writeByte(')');1448 try writer.writeByte(')');
1420 }1449 }
1421 try dg.renderValue(writer, field_ty, union_obj.val, initializer_type);1450 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
1422 } else {1451 } else {
1423 try writer.writeAll("0");1452 try writer.writeAll("0");
1424 }1453 }
...@@ -1426,44 +1455,28 @@ pub const DeclGen = struct {...@@ -1426,44 +1455,28 @@ pub const DeclGen = struct {
1426 }1455 }
14271456
1428 try writer.writeByte('{');1457 try writer.writeByte('{');
1429 if (ty.unionTagTypeSafety()) |tag_ty| {1458 if (ty.unionTagTypeSafety(mod)) |tag_ty| {
1430 const layout = ty.unionGetLayout(target);1459 const layout = ty.unionGetLayout(mod);
1431 if (layout.tag_size != 0) {1460 if (layout.tag_size != 0) {
1432 try writer.writeAll(" .tag = ");1461 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);
1434 }1463 }
1435 if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}');1464 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
1436 if (layout.tag_size != 0) try writer.writeByte(',');1465 if (layout.tag_size != 0) try writer.writeByte(',');
1437 try writer.writeAll(" .payload = {");1466 try writer.writeAll(" .payload = {");
1438 }1467 }
1439 if (field_ty.hasRuntimeBits()) {1468 if (field_ty.hasRuntimeBits(mod)) {
1440 try writer.print(" .{ } = ", .{fmtIdent(field_name)});1469 try writer.print(" .{ } = ", .{fmtIdent(mod.intern_pool.stringToSlice(field_name))});
1441 try dg.renderValue(writer, field_ty, union_obj.val, initializer_type);1470 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
1442 try writer.writeByte(' ');1471 try writer.writeByte(' ');
1443 } else for (ty.unionFields().values()) |field| {1472 } else for (ty.unionFields(mod).values()) |field| {
1444 if (!field.ty.hasRuntimeBits()) continue;1473 if (!field.ty.hasRuntimeBits(mod)) continue;
1445 try dg.renderValue(writer, field.ty, Value.undef, initializer_type);1474 try dg.renderValue(writer, field.ty, Value.undef, initializer_type);
1446 break;1475 break;
1447 }1476 }
1448 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');1477 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
1449 try writer.writeByte('}');1478 try writer.writeByte('}');
1450 },1479 },
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 }),
1467 }1480 }
1468 }1481 }
14691482
...@@ -1478,12 +1491,12 @@ pub const DeclGen = struct {...@@ -1478,12 +1491,12 @@ pub const DeclGen = struct {
1478 },1491 },
1479 ) !void {1492 ) !void {
1480 const store = &dg.ctypes.set;1493 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);
1484 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);1497 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).?;
1487 if (fn_info.cc == .Naked) {1500 if (fn_info.cc == .Naked) {
1488 switch (kind) {1501 switch (kind) {
1489 .forward => try w.writeAll("zig_naked_decl "),1502 .forward => try w.writeAll("zig_naked_decl "),
...@@ -1491,14 +1504,13 @@ pub const DeclGen = struct {...@@ -1491,14 +1504,13 @@ pub const DeclGen = struct {
1491 else => unreachable,1504 else => unreachable,
1492 }1505 }
1493 }1506 }
1494 if (fn_decl.val.castTag(.function)) |func_payload|1507 if (fn_decl.val.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");
1495 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");1508 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
1496 if (fn_info.return_type.tag() == .noreturn) try w.writeAll("zig_noreturn ");
14971509
1498 const trailing = try renderTypePrefix(1510 const trailing = try renderTypePrefix(
1499 dg.decl_index,1511 dg.decl_index,
1500 store.*,1512 store.*,
1501 module,1513 mod,
1502 w,1514 w,
1503 fn_cty_idx,1515 fn_cty_idx,
1504 .suffix,1516 .suffix,
...@@ -1512,8 +1524,8 @@ pub const DeclGen = struct {...@@ -1512,8 +1524,8 @@ pub const DeclGen = struct {
15121524
1513 switch (kind) {1525 switch (kind) {
1514 .forward => {},1526 .forward => {},
1515 .complete => if (fn_info.alignment > 0)1527 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a|
1516 try w.print(" zig_align_fn({})", .{fn_info.alignment}),1528 try w.print(" zig_align_fn({})", .{a}),
1517 else => unreachable,1529 else => unreachable,
1518 }1530 }
15191531
...@@ -1525,7 +1537,7 @@ pub const DeclGen = struct {...@@ -1525,7 +1537,7 @@ pub const DeclGen = struct {
1525 try renderTypeSuffix(1537 try renderTypeSuffix(
1526 dg.decl_index,1538 dg.decl_index,
1527 store.*,1539 store.*,
1528 module,1540 mod,
1529 w,1541 w,
1530 fn_cty_idx,1542 fn_cty_idx,
1531 .suffix,1543 .suffix,
...@@ -1537,8 +1549,8 @@ pub const DeclGen = struct {...@@ -1537,8 +1549,8 @@ pub const DeclGen = struct {
1537 );1549 );
15381550
1539 switch (kind) {1551 switch (kind) {
1540 .forward => if (fn_info.alignment > 0)1552 .forward => if (fn_info.alignment.toByteUnitsOptional()) |a|
1541 try w.print(" zig_align_fn({})", .{fn_info.alignment}),1553 try w.print(" zig_align_fn({})", .{a}),
1542 .complete => {},1554 .complete => {},
1543 else => unreachable,1555 else => unreachable,
1544 }1556 }
...@@ -1577,9 +1589,9 @@ pub const DeclGen = struct {...@@ -1577,9 +1589,9 @@ pub const DeclGen = struct {
15771589
1578 fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {1590 fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {
1579 const store = &dg.ctypes.set;1591 const store = &dg.ctypes.set;
1580 const module = dg.module;1592 const mod = dg.module;
1581 _ = try renderTypePrefix(dg.decl_index, store.*, module, w, idx, .suffix, .{});1593 _ = try renderTypePrefix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
1582 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix, .{});1594 try renderTypeSuffix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
1583 }1595 }
15841596
1585 const IntCastContext = union(enum) {1597 const IntCastContext = union(enum) {
...@@ -1619,18 +1631,18 @@ pub const DeclGen = struct {...@@ -1619,18 +1631,18 @@ pub const DeclGen = struct {
1619 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)1631 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
1620 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))1632 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
1621 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {1633 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {
1622 const target = dg.module.getTarget();1634 const mod = dg.module;
1623 const dest_bits = dest_ty.bitSize(target);1635 const dest_bits = dest_ty.bitSize(mod);
1624 const dest_int_info = dest_ty.intInfo(target);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);
1627 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {1639 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
1628 .unsigned => Type.usize,1640 .unsigned => Type.usize,
1629 .signed => Type.isize,1641 .signed => Type.isize,
1630 } else src_ty;1642 } else src_ty;
16311643
1632 const src_bits = src_eff_ty.bitSize(target);1644 const src_bits = src_eff_ty.bitSize(mod);
1633 const src_int_info = if (src_eff_ty.isAbiInt()) src_eff_ty.intInfo(target) else null;1645 const src_int_info = if (src_eff_ty.isAbiInt(mod)) src_eff_ty.intInfo(mod) else null;
1634 if (dest_bits <= 64 and src_bits <= 64) {1646 if (dest_bits <= 64 and src_bits <= 64) {
1635 const needs_cast = src_int_info == null or1647 const needs_cast = src_int_info == null or
1636 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or1648 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
...@@ -1703,8 +1715,8 @@ pub const DeclGen = struct {...@@ -1703,8 +1715,8 @@ pub const DeclGen = struct {
1703 alignment: u32,1715 alignment: u32,
1704 kind: CType.Kind,1716 kind: CType.Kind,
1705 ) error{ OutOfMemory, AnalysisFail }!void {1717 ) error{ OutOfMemory, AnalysisFail }!void {
1706 const target = dg.module.getTarget();1718 const mod = dg.module;
1707 const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target));1719 const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod));
1708 try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas);1720 try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas);
1709 }1721 }
17101722
...@@ -1717,7 +1729,7 @@ pub const DeclGen = struct {...@@ -1717,7 +1729,7 @@ pub const DeclGen = struct {
1717 alignas: CType.AlignAs,1729 alignas: CType.AlignAs,
1718 ) error{ OutOfMemory, AnalysisFail }!void {1730 ) error{ OutOfMemory, AnalysisFail }!void {
1719 const store = &dg.ctypes.set;1731 const store = &dg.ctypes.set;
1720 const module = dg.module;1732 const mod = dg.module;
17211733
1722 switch (std.math.order(alignas.@"align", alignas.abi)) {1734 switch (std.math.order(alignas.@"align", alignas.abi)) {
1723 .lt => try w.print("zig_under_align({}) ", .{alignas.getAlign()}),1735 .lt => try w.print("zig_under_align({}) ", .{alignas.getAlign()}),
...@@ -1726,25 +1738,20 @@ pub const DeclGen = struct {...@@ -1726,25 +1738,20 @@ pub const DeclGen = struct {
1726 }1738 }
17271739
1728 const trailing =1740 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);
1730 try w.print("{}", .{trailing});1742 try w.print("{}", .{trailing});
1731 try dg.writeCValue(w, name);1743 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, .{});
1733 }1745 }
17341746
1735 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {1747 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
1736 switch (tv.val.tag()) {1748 const mod = dg.module;
1737 .extern_fn => return true,1749 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1738 .function => {1750 .variable => |variable| mod.decl_exports.contains(variable.decl),
1739 const func = tv.val.castTag(.function).?.data;1751 .extern_func => true,
1740 return dg.module.decl_exports.contains(func.owner_decl);1752 .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),
1741 },
1742 .variable => {
1743 const variable = tv.val.castTag(.variable).?.data;
1744 return dg.module.decl_exports.contains(variable.owner_decl);
1745 },
1746 else => unreachable,1753 else => unreachable,
1747 }1754 };
1748 }1755 }
17491756
1750 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {1757 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
...@@ -1819,7 +1826,7 @@ pub const DeclGen = struct {...@@ -1819,7 +1826,7 @@ pub const DeclGen = struct {
1819 try dg.writeCValue(writer, member);1826 try dg.writeCValue(writer, member);
1820 }1827 }
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 {
1823 const decl = dg.module.declPtr(decl_index);1830 const decl = dg.module.declPtr(decl_index);
1824 const fwd_decl_writer = dg.fwd_decl.writer();1831 const fwd_decl_writer = dg.fwd_decl.writer();
1825 const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;1832 const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;
...@@ -1830,7 +1837,7 @@ pub const DeclGen = struct {...@@ -1830,7 +1837,7 @@ pub const DeclGen = struct {
1830 fwd_decl_writer,1837 fwd_decl_writer,
1831 decl.ty,1838 decl.ty,
1832 .{ .decl = decl_index },1839 .{ .decl = decl_index },
1833 CQualifiers.init(.{ .@"const" = !variable.is_mutable }),1840 CQualifiers.init(.{ .@"const" = variable.is_const }),
1834 decl.@"align",1841 decl.@"align",
1835 .complete,1842 .complete,
1836 );1843 );
...@@ -1838,19 +1845,20 @@ pub const DeclGen = struct {...@@ -1838,19 +1845,20 @@ pub const DeclGen = struct {
1838 }1845 }
18391846
1840 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {1847 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
1841 const decl = dg.module.declPtr(decl_index);1848 const mod = dg.module;
1842 dg.module.markDeclAlive(decl);1849 const decl = mod.declPtr(decl_index);
18431850 try mod.markDeclAlive(decl);
1844 if (dg.module.decl_exports.get(decl_index)) |exports| {1851
1845 try writer.writeAll(exports.items[export_index].options.name);1852 if (mod.decl_exports.get(decl_index)) |exports| {
1846 } else if (decl.isExtern()) {1853 try writer.print("{}", .{exports.items[export_index].opts.name.fmt(&mod.intern_pool)});
1847 try writer.writeAll(mem.span(decl.name));1854 } else if (decl.isExtern(mod)) {
1855 try writer.print("{}", .{decl.name.fmt(&mod.intern_pool)});
1848 } else {1856 } else {
1849 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),1857 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
1850 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.1858 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
1851 var name: [100]u8 = undefined;1859 var name: [100]u8 = undefined;
1852 var name_stream = std.io.fixedBufferStream(&name);1860 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) {
1854 error.NoSpaceLeft => {},1862 error.NoSpaceLeft => {},
1855 };1863 };
1856 try writer.print("{}__{d}", .{1864 try writer.print("{}__{d}", .{
...@@ -1894,18 +1902,18 @@ pub const DeclGen = struct {...@@ -1894,18 +1902,18 @@ pub const DeclGen = struct {
1894 .bits => {},1902 .bits => {},
1895 }1903 }
18961904
1897 const target = dg.module.getTarget();1905 const mod = dg.module;
1898 const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{1906 const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{
1899 .signedness = .unsigned,1907 .signedness = .unsigned,
1900 .bits = @intCast(u16, ty.bitSize(target)),1908 .bits = @intCast(u16, ty.bitSize(mod)),
1901 };1909 };
19021910
1903 if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});1911 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;
1906 try writer.print(", {}", .{try dg.fmtIntLiteral(1914 try writer.print(", {}", .{try dg.fmtIntLiteral(
1907 if (is_big) Type.u16 else Type.u8,1915 bits_ty,
1908 Value.initPayload(&bits_pl.base),1916 try mod.intValue(bits_ty, int_info.bits),
1909 .FunctionArgument,1917 .FunctionArgument,
1910 )});1918 )});
1911 }1919 }
...@@ -1916,6 +1924,7 @@ pub const DeclGen = struct {...@@ -1916,6 +1924,7 @@ pub const DeclGen = struct {
1916 val: Value,1924 val: Value,
1917 loc: ValueRenderLocation,1925 loc: ValueRenderLocation,
1918 ) !std.fmt.Formatter(formatIntLiteral) {1926 ) !std.fmt.Formatter(formatIntLiteral) {
1927 const mod = dg.module;
1919 const kind: CType.Kind = switch (loc) {1928 const kind: CType.Kind = switch (loc) {
1920 .FunctionArgument => .parameter,1929 .FunctionArgument => .parameter,
1921 .Initializer, .Other => .complete,1930 .Initializer, .Other => .complete,
...@@ -1923,7 +1932,7 @@ pub const DeclGen = struct {...@@ -1923,7 +1932,7 @@ pub const DeclGen = struct {
1923 };1932 };
1924 return std.fmt.Formatter(formatIntLiteral){ .data = .{1933 return std.fmt.Formatter(formatIntLiteral){ .data = .{
1925 .dg = dg,1934 .dg = dg,
1926 .int_info = ty.intInfo(dg.module.getTarget()),1935 .int_info = ty.intInfo(mod),
1927 .kind = kind,1936 .kind = kind,
1928 .cty = try dg.typeToCType(ty, kind),1937 .cty = try dg.typeToCType(ty, kind),
1929 .val = val,1938 .val = val,
...@@ -1979,7 +1988,7 @@ fn renderTypeName(...@@ -1979,7 +1988,7 @@ fn renderTypeName(
1979 try w.print("{s} {s}{}__{d}", .{1988 try w.print("{s} {s}{}__{d}", .{
1980 @tagName(tag)["fwd_".len..],1989 @tagName(tag)["fwd_".len..],
1981 attributes,1990 attributes,
1982 fmtIdent(mem.span(mod.declPtr(owner_decl).name)),1991 fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)),
1983 @enumToInt(owner_decl),1992 @enumToInt(owner_decl),
1984 });1993 });
1985 },1994 },
...@@ -2392,15 +2401,20 @@ pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {...@@ -2392,15 +2401,20 @@ pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {
2392}2401}
23932402
2394pub fn genErrDecls(o: *Object) !void {2403pub fn genErrDecls(o: *Object) !void {
2404 const mod = o.dg.module;
2395 const writer = o.writer();2405 const writer = o.writer();
23962406
2397 try writer.writeAll("enum {\n");2407 try writer.writeAll("enum {\n");
2398 o.indent_writer.pushIndent();2408 o.indent_writer.pushIndent();
2399 var max_name_len: usize = 0;2409 var max_name_len: usize = 0;
2400 for (o.dg.module.error_name_list.items, 0..) |name, value| {2410 for (mod.global_error_set.keys()[1..], 1..) |name_nts, value| {
2401 max_name_len = std.math.max(name.len, max_name_len);2411 const name = mod.intern_pool.stringToSlice(name_nts);
2402 var err_pl = Value.Payload.Error{ .data = .{ .name = name } };2412 max_name_len = @max(name.len, max_name_len);
2403 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_pl.base), .Other);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);
2404 try writer.print(" = {d}u,\n", .{value});2418 try writer.print(" = {d}u,\n", .{value});
2405 }2419 }
2406 o.indent_writer.popIndent();2420 o.indent_writer.popIndent();
...@@ -2412,40 +2426,44 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2412,40 +2426,44 @@ pub fn genErrDecls(o: *Object) !void {
2412 defer o.dg.gpa.free(name_buf);2426 defer o.dg.gpa.free(name_buf);
24132427
2414 @memcpy(name_buf[0..name_prefix.len], name_prefix);2428 @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);
2416 @memcpy(name_buf[name_prefix.len..][0..name.len], name);2431 @memcpy(name_buf[name_prefix.len..][0..name.len], name);
2417 const identifier = name_buf[0 .. name_prefix.len + name.len];2432 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 };2434 const name_ty = try mod.arrayType(.{
2420 const name_ty = Type.initPayload(&name_ty_pl.base);2435 .len = name.len,
24212436 .child = .u8_type,
2422 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name };2437 .sentinel = .zero_u8,
2423 const name_val = Value.initPayload(&name_pl.base);2438 });
2439 const name_val = try mod.intern(.{ .aggregate = .{
2440 .ty = name_ty.toIntern(),
2441 .storage = .{ .bytes = name },
2442 } });
24242443
2425 try writer.writeAll("static ");2444 try writer.writeAll("static ");
2426 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, 0, .complete);2445 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, 0, .complete);
2427 try writer.writeAll(" = ");2446 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);
2429 try writer.writeAll(";\n");2448 try writer.writeAll(";\n");
2430 }2449 }
24312450
2432 var name_array_ty_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{2451 const name_array_ty = try mod.arrayType(.{
2433 .len = o.dg.module.error_name_list.items.len,2452 .len = mod.global_error_set.count(),
2434 .elem_type = Type.initTag(.const_slice_u8_sentinel_0),2453 .child = .slice_const_u8_sentinel_0_type,
2435 } };2454 });
2436 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
24372455
2438 try writer.writeAll("static ");2456 try writer.writeAll("static ");
2439 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, 0, .complete);2457 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, 0, .complete);
2440 try writer.writeAll(" = {");2458 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);
2442 if (value != 0) try writer.writeByte(',');2461 if (value != 0) try writer.writeByte(',');
24432462
2444 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };2463 const len_val = try mod.intValue(Type.usize, name.len);
2445 const len_val = Value.initPayload(&len_pl.base);
24462464
2447 try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{2465 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),
2449 });2467 });
2450 }2468 }
2451 try writer.writeAll("};\n");2469 try writer.writeAll("};\n");
...@@ -2455,20 +2473,23 @@ fn genExports(o: *Object) !void {...@@ -2455,20 +2473,23 @@ fn genExports(o: *Object) !void {
2455 const tracy = trace(@src());2473 const tracy = trace(@src());
2456 defer tracy.end();2474 defer tracy.end();
24572475
2476 const mod = o.dg.module;
2477 const ip = &mod.intern_pool;
2458 const fwd_decl_writer = o.dg.fwd_decl.writer();2478 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| {
2460 for (exports.items[1..], 1..) |@"export", i| {2480 for (exports.items[1..], 1..) |@"export", i| {
2461 try fwd_decl_writer.writeAll("zig_export(");2481 try fwd_decl_writer.writeAll("zig_export(");
2462 try o.dg.renderFunctionSignature(fwd_decl_writer, o.dg.decl_index.unwrap().?, .forward, .{ .export_index = @intCast(u32, i) });2482 try o.dg.renderFunctionSignature(fwd_decl_writer, o.dg.decl_index.unwrap().?, .forward, .{ .export_index = @intCast(u32, i) });
2463 try fwd_decl_writer.print(", {s}, {s});\n", .{2483 try fwd_decl_writer.print(", {s}, {s});\n", .{
2464 fmtStringLiteral(exports.items[0].options.name, null),2484 fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
2465 fmtStringLiteral(@"export".options.name, null),2485 fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null),
2466 });2486 });
2467 }2487 }
2468 }2488 }
2469}2489}
24702490
2471pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {2491pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2492 const mod = o.dg.module;
2472 const w = o.writer();2493 const w = o.writer();
2473 const key = lazy_fn.key_ptr.*;2494 const key = lazy_fn.key_ptr.*;
2474 const val = lazy_fn.value_ptr;2495 const val = lazy_fn.value_ptr;
...@@ -2477,7 +2498,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {...@@ -2477,7 +2498,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2477 .tag_name => {2498 .tag_name => {
2478 const enum_ty = val.data.tag_name;2499 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
2482 try w.writeAll("static ");2503 try w.writeAll("static ");
2483 try o.dg.renderType(w, name_slice_ty);2504 try o.dg.renderType(w, name_slice_ty);
...@@ -2486,34 +2507,30 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {...@@ -2486,34 +2507,30 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2486 try w.writeByte('(');2507 try w.writeByte('(');
2487 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, 0, .complete);2508 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, 0, .complete);
2488 try w.writeAll(") {\n switch (tag) {\n");2509 try w.writeAll(") {\n switch (tag) {\n");
2489 for (enum_ty.enumFields().keys(), 0..) |name, index| {2510 for (enum_ty.enumFields(mod), 0..) |name_ip, index_usize| {
2490 var tag_pl: Value.Payload.U32 = .{2511 const index = @intCast(u32, index_usize);
2491 .base = .{ .tag = .enum_field_index },2512 const name = mod.intern_pool.stringToSlice(name_ip);
2492 .data = @intCast(u32, index),2513 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
2493 };
2494 const tag_val = Value.initPayload(&tag_pl.base);
24952514
2496 var int_pl: Value.Payload.U64 = undefined;2515 const int_val = try tag_val.enumToInt(enum_ty, mod);
2497 const int_val = tag_val.enumToInt(enum_ty, &int_pl);
24982516
2499 var name_ty_pl = Type.Payload.Len{2517 const name_ty = try mod.arrayType(.{
2500 .base = .{ .tag = .array_u8_sentinel_0 },2518 .len = name.len,
2501 .data = name.len,2519 .child = .u8_type,
2502 };2520 .sentinel = .zero_u8,
2503 const name_ty = Type.initPayload(&name_ty_pl.base);2521 });
25042522 const name_val = try mod.intern(.{ .aggregate = .{
2505 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name };2523 .ty = name_ty.toIntern(),
2506 const name_val = Value.initPayload(&name_pl.base);2524 .storage = .{ .bytes = name },
25072525 } });
2508 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };2526 const len_val = try mod.intValue(Type.usize, name.len);
2509 const len_val = Value.initPayload(&len_pl.base);
25102527
2511 try w.print(" case {}: {{\n static ", .{2528 try w.print(" case {}: {{\n static ", .{
2512 try o.dg.fmtIntLiteral(enum_ty, int_val, .Other),2529 try o.dg.fmtIntLiteral(enum_ty, int_val, .Other),
2513 });2530 });
2514 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete);2531 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete);
2515 try w.writeAll(" = ");2532 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);
2517 try w.writeAll(";\n return (");2534 try w.writeAll(";\n return (");
2518 try o.dg.renderType(w, name_slice_ty);2535 try o.dg.renderType(w, name_slice_ty);
2519 try w.print("){{{}, {}}};\n", .{2536 try w.print("){{{}, {}}};\n", .{
...@@ -2529,7 +2546,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {...@@ -2529,7 +2546,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2529 try w.writeAll("}\n");2546 try w.writeAll("}\n");
2530 },2547 },
2531 .never_tail, .never_inline => |fn_decl_index| {2548 .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);
2533 const fn_cty = try o.dg.typeToCType(fn_decl.ty, .complete);2550 const fn_cty = try o.dg.typeToCType(fn_decl.ty, .complete);
2534 const fn_info = fn_cty.cast(CType.Payload.Function).?.data;2551 const fn_info = fn_cty.cast(CType.Payload.Function).?.data;
25352552
...@@ -2646,19 +2663,19 @@ pub fn genDecl(o: *Object) !void {...@@ -2646,19 +2663,19 @@ pub fn genDecl(o: *Object) !void {
2646 const tracy = trace(@src());2663 const tracy = trace(@src());
2647 defer tracy.end();2664 defer tracy.end();
26482665
2666 const mod = o.dg.module;
2649 const decl = o.dg.decl.?;2667 const decl = o.dg.decl.?;
2650 const decl_c_value = .{ .decl = o.dg.decl_index.unwrap().? };2668 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;2671 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
2654 if (tv.val.tag() == .extern_fn) {2672 if (tv.val.getExternFunc(mod)) |_| {
2655 const fwd_decl_writer = o.dg.fwd_decl.writer();2673 const fwd_decl_writer = o.dg.fwd_decl.writer();
2656 try fwd_decl_writer.writeAll("zig_extern ");2674 try fwd_decl_writer.writeAll("zig_extern ");
2657 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 });2675 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 });
2658 try fwd_decl_writer.writeAll(";\n");2676 try fwd_decl_writer.writeAll(";\n");
2659 try genExports(o);2677 try genExports(o);
2660 } else if (tv.val.castTag(.variable)) |var_payload| {2678 } else if (tv.val.getVariable(mod)) |variable| {
2661 const variable: *Module.Var = var_payload.data;
2662 try o.dg.renderFwdDecl(decl_c_value.decl, variable);2679 try o.dg.renderFwdDecl(decl_c_value.decl, variable);
2663 try genExports(o);2680 try genExports(o);
26642681
...@@ -2669,11 +2686,12 @@ pub fn genDecl(o: *Object) !void {...@@ -2669,11 +2686,12 @@ pub fn genDecl(o: *Object) !void {
2669 if (!is_global) try w.writeAll("static ");2686 if (!is_global) try w.writeAll("static ");
2670 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");2687 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
2671 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");2688 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});
2673 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete);2691 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)");
2675 try w.writeAll(" = ");2693 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);
2677 try w.writeByte(';');2695 try w.writeByte(';');
2678 try o.indent_writer.insertNewline();2696 try o.indent_writer.insertNewline();
2679 } else {2697 } else {
...@@ -2686,9 +2704,10 @@ pub fn genDecl(o: *Object) !void {...@@ -2686,9 +2704,10 @@ pub fn genDecl(o: *Object) !void {
26862704
2687 const w = o.writer();2705 const w = o.writer();
2688 if (!is_global) try w.writeAll("static ");2706 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});
2690 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, Const, decl.@"align", .complete);2709 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)");
2692 try w.writeAll(" = ");2711 try w.writeAll(" = ");
2693 try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer);2712 try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer);
2694 try w.writeAll(";\n");2713 try w.writeAll(";\n");
...@@ -2704,8 +2723,9 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -2704,8 +2723,9 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
2704 .val = dg.decl.?.val,2723 .val = dg.decl.?.val,
2705 };2724 };
2706 const writer = dg.fwd_decl.writer();2725 const writer = dg.fwd_decl.writer();
2726 const mod = dg.module;
27072727
2708 switch (tv.ty.zigTypeTag()) {2728 switch (tv.ty.zigTypeTag(mod)) {
2709 .Fn => {2729 .Fn => {
2710 const is_global = dg.declIsGlobal(tv);2730 const is_global = dg.declIsGlobal(tv);
2711 if (is_global) {2731 if (is_global) {
...@@ -2791,17 +2811,18 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con...@@ -2791,17 +2811,18 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
2791}2811}
27922812
2793fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {2813fn 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;
2794 const air_tags = f.air.instructions.items(.tag);2816 const air_tags = f.air.instructions.items(.tag);
27952817
2796 for (body) |inst| {2818 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))
2798 continue;2820 continue;
2799 }
28002821
2801 const result_value = switch (air_tags[inst]) {2822 const result_value = switch (air_tags[inst]) {
2802 // zig fmt: off2823 // zig fmt: off
2803 .constant => unreachable, // excluded from function bodies2824 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
2804 .const_ty => unreachable, // excluded from function bodies2825
2805 .arg => try airArg(f, inst),2826 .arg => try airArg(f, inst),
28062827
2807 .trap => try airTrap(f.object.writer()),2828 .trap => try airTrap(f.object.writer()),
...@@ -2826,10 +2847,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2826,10 +2847,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
2826 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),2847 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
2827 .rem => blk: {2848 .rem => blk: {
2828 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2849 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);
2830 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),2851 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2831 // so we only check one.2852 // so we only check one.
2832 break :blk if (lhs_scalar_ty.isInt())2853 break :blk if (lhs_scalar_ty.isInt(mod))
2833 try airBinOp(f, inst, "%", "rem", .none)2854 try airBinOp(f, inst, "%", "rem", .none)
2834 else2855 else
2835 try airBinFloatOp(f, inst, "fmod");2856 try airBinFloatOp(f, inst, "fmod");
...@@ -3077,7 +3098,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3077,7 +3098,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3077fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue {3098fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue {
3078 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3099 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);
3081 const operand = try f.resolveInst(ty_op.operand);3102 const operand = try f.resolveInst(ty_op.operand);
3082 try reap(f, inst, &.{ty_op.operand});3103 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: [...@@ -3095,9 +3116,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
3095}3116}
30963117
3097fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {3118fn 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);
3099 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3121 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3100 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {3122 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3101 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3123 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3102 return .none;3124 return .none;
3103 }3125 }
...@@ -3120,13 +3142,14 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3120,13 +3142,14 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3120}3142}
31213143
3122fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {3144fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3145 const mod = f.object.dg.module;
3123 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;3146 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3124 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;3147 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
31253148
3126 const inst_ty = f.air.typeOfIndex(inst);3149 const inst_ty = f.typeOfIndex(inst);
3127 const ptr_ty = f.air.typeOf(bin_op.lhs);3150 const ptr_ty = f.typeOf(bin_op.lhs);
3128 const elem_ty = ptr_ty.childType();3151 const elem_ty = ptr_ty.childType(mod);
3129 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime();3152 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
31303153
3131 const ptr = try f.resolveInst(bin_op.lhs);3154 const ptr = try f.resolveInst(bin_op.lhs);
3132 const index = try f.resolveInst(bin_op.rhs);3155 const index = try f.resolveInst(bin_op.rhs);
...@@ -3141,7 +3164,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3141,7 +3164,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3141 try f.renderType(writer, inst_ty);3164 try f.renderType(writer, inst_ty);
3142 try writer.writeByte(')');3165 try writer.writeByte(')');
3143 if (elem_has_bits) try writer.writeByte('&');3166 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) {
3145 // It's a pointer to an array, so we need to de-reference.3168 // It's a pointer to an array, so we need to de-reference.
3146 try f.writeCValueDeref(writer, ptr);3169 try f.writeCValueDeref(writer, ptr);
3147 } else try f.writeCValue(writer, ptr, .Other);3170 } else try f.writeCValue(writer, ptr, .Other);
...@@ -3155,9 +3178,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3155,9 +3178,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3155}3178}
31563179
3157fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {3180fn 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);
3159 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3183 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3160 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {3184 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3161 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3185 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3162 return .none;3186 return .none;
3163 }3187 }
...@@ -3180,13 +3204,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3180,13 +3204,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3180}3204}
31813205
3182fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {3206fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3207 const mod = f.object.dg.module;
3183 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;3208 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3184 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;3209 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
31853210
3186 const inst_ty = f.air.typeOfIndex(inst);3211 const inst_ty = f.typeOfIndex(inst);
3187 const slice_ty = f.air.typeOf(bin_op.lhs);3212 const slice_ty = f.typeOf(bin_op.lhs);
3188 const elem_ty = slice_ty.elemType2();3213 const elem_ty = slice_ty.elemType2(mod);
3189 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime();3214 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
31903215
3191 const slice = try f.resolveInst(bin_op.lhs);3216 const slice = try f.resolveInst(bin_op.lhs);
3192 const index = try f.resolveInst(bin_op.rhs);3217 const index = try f.resolveInst(bin_op.rhs);
...@@ -3209,9 +3234,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3209,9 +3234,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3209}3234}
32103235
3211fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {3236fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3237 const mod = f.object.dg.module;
3212 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3238 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3213 const inst_ty = f.air.typeOfIndex(inst);3239 const inst_ty = f.typeOfIndex(inst);
3214 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {3240 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3215 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3241 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3216 return .none;3242 return .none;
3217 }3243 }
...@@ -3234,14 +3260,14 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3234,14 +3260,14 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3234}3260}
32353261
3236fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {3262fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
3237 const inst_ty = f.air.typeOfIndex(inst);3263 const mod = f.object.dg.module;
3238 const elem_type = inst_ty.elemType();3264 const inst_ty = f.typeOfIndex(inst);
3239 if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty };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();
3242 const local = try f.allocLocalValue(3268 const local = try f.allocLocalValue(
3243 elem_type,3269 elem_type,
3244 inst_ty.ptrAlignment(target),3270 inst_ty.ptrAlignment(mod),
3245 );3271 );
3246 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });3272 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
3247 const gpa = f.object.dg.module.gpa;3273 const gpa = f.object.dg.module.gpa;
...@@ -3250,14 +3276,14 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3250,14 +3276,14 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
3250}3276}
32513277
3252fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {3278fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3253 const inst_ty = f.air.typeOfIndex(inst);3279 const mod = f.object.dg.module;
3254 const elem_ty = inst_ty.elemType();3280 const inst_ty = f.typeOfIndex(inst);
3255 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty };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();
3258 const local = try f.allocLocalValue(3284 const local = try f.allocLocalValue(
3259 elem_ty,3285 elem_ty,
3260 inst_ty.ptrAlignment(target),3286 inst_ty.ptrAlignment(mod),
3261 );3287 );
3262 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });3288 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
3263 const gpa = f.object.dg.module.gpa;3289 const gpa = f.object.dg.module.gpa;
...@@ -3266,7 +3292,7 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3266,7 +3292,7 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3266}3292}
32673293
3268fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {3294fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
3269 const inst_ty = f.air.typeOfIndex(inst);3295 const inst_ty = f.typeOfIndex(inst);
3270 const inst_cty = try f.typeToIndex(inst_ty, .parameter);3296 const inst_cty = try f.typeToIndex(inst_ty, .parameter);
32713297
3272 const i = f.next_arg_index;3298 const i = f.next_arg_index;
...@@ -3290,14 +3316,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3290,14 +3316,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
3290}3316}
32913317
3292fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {3318fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3319 const mod = f.object.dg.module;
3293 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3320 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
32943321
3295 const ptr_ty = f.air.typeOf(ty_op.operand);3322 const ptr_ty = f.typeOf(ty_op.operand);
3296 const ptr_scalar_ty = ptr_ty.scalarType();3323 const ptr_scalar_ty = ptr_ty.scalarType(mod);
3297 const ptr_info = ptr_scalar_ty.ptrInfo().data;3324 const ptr_info = ptr_scalar_ty.ptrInfo(mod);
3298 const src_ty = ptr_info.pointee_type;3325 const src_ty = ptr_info.pointee_type;
32993326
3300 if (!src_ty.hasRuntimeBitsIgnoreComptime()) {3327 if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3301 try reap(f, inst, &.{ty_op.operand});3328 try reap(f, inst, &.{ty_op.operand});
3302 return .none;3329 return .none;
3303 }3330 }
...@@ -3306,9 +3333,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3306,9 +3333,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33063333
3307 try reap(f, inst, &.{ty_op.operand});3334 try reap(f, inst, &.{ty_op.operand});
33083335
3309 const target = f.object.dg.module.getTarget();3336 const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(mod);
3310 const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(target);3337 const is_array = lowersToArray(src_ty, mod);
3311 const is_array = lowersToArray(src_ty, target);
3312 const need_memcpy = !is_aligned or is_array;3338 const need_memcpy = !is_aligned or is_array;
33133339
3314 const writer = f.object.writer();3340 const writer = f.object.writer();
...@@ -3327,29 +3353,13 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3327,29 +3353,13 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3327 try f.renderType(writer, src_ty);3353 try f.renderType(writer, src_ty);
3328 try writer.writeAll("))");3354 try writer.writeAll("))");
3329 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {3355 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {
3330 var host_pl = Type.Payload.Bits{3356 const host_bits: u16 = ptr_info.host_size * 8;
3331 .base = .{ .tag = .int_unsigned },3357 const host_ty = try mod.intType(.unsigned, host_bits);
3332 .data = ptr_info.host_size * 8,
3333 };
3334 const host_ty = Type.initPayload(&host_pl.base);
33353358
3336 var bit_offset_ty_pl = Type.Payload.Bits{3359 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
3337 .base = .{ .tag = .int_unsigned },3360 const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.bit_offset);
3338 .data = Type.smallestUnsignedBits(host_pl.data - 1),
3339 };
3340 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
33413361
3342 var bit_offset_val_pl: Value.Payload.U64 = .{3362 const field_ty = try mod.intType(.unsigned, @intCast(u16, src_ty.bitSize(mod)));
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);
33533363
3354 try f.writeCValue(writer, local, .Other);3364 try f.writeCValue(writer, local, .Other);
3355 try v.elem(f, writer);3365 try v.elem(f, writer);
...@@ -3360,9 +3370,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3360,9 +3370,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3360 try writer.writeAll("((");3370 try writer.writeAll("((");
3361 try f.renderType(writer, field_ty);3371 try f.renderType(writer, field_ty);
3362 try writer.writeByte(')');3372 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;
3364 if (cant_cast) {3374 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", .{});
3366 try writer.writeAll("zig_lo_");3376 try writer.writeAll("zig_lo_");
3367 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);3377 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
3368 try writer.writeByte('(');3378 try writer.writeByte('(');
...@@ -3390,23 +3400,22 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3390,23 +3400,22 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3390}3400}
33913401
3392fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {3402fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3403 const mod = f.object.dg.module;
3393 const un_op = f.air.instructions.items(.data)[inst].un_op;3404 const un_op = f.air.instructions.items(.data)[inst].un_op;
3394 const writer = f.object.writer();3405 const writer = f.object.writer();
3395 const target = f.object.dg.module.getTarget();
3396 const op_inst = Air.refToIndex(un_op);3406 const op_inst = Air.refToIndex(un_op);
3397 const op_ty = f.air.typeOf(un_op);3407 const op_ty = f.typeOf(un_op);
3398 const ret_ty = if (is_ptr) op_ty.childType() else op_ty;3408 const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty;
3399 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;3409 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
3400 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
34013410
3402 if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) {3411 if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) {
3403 try reap(f, inst, &.{un_op});3412 try reap(f, inst, &.{un_op});
3404 _ = try airCall(f, op_inst.?, .always_tail);3413 _ = try airCall(f, op_inst.?, .always_tail);
3405 } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) {3414 } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3406 const operand = try f.resolveInst(un_op);3415 const operand = try f.resolveInst(un_op);
3407 try reap(f, inst, &.{un_op});3416 try reap(f, inst, &.{un_op});
3408 var deref = is_ptr;3417 var deref = is_ptr;
3409 const is_array = lowersToArray(ret_ty, target);3418 const is_array = lowersToArray(ret_ty, mod);
3410 const ret_val = if (is_array) ret_val: {3419 const ret_val = if (is_array) ret_val: {
3411 const array_local = try f.allocLocal(inst, lowered_ret_ty);3420 const array_local = try f.allocLocal(inst, lowered_ret_ty);
3412 try writer.writeAll("memcpy(");3421 try writer.writeAll("memcpy(");
...@@ -3435,22 +3444,23 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -3435,22 +3444,23 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3435 } else {3444 } else {
3436 try reap(f, inst, &.{un_op});3445 try reap(f, inst, &.{un_op});
3437 // Not even allowed to return void in a naked function.3446 // 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)
3439 try writer.writeAll("return;\n");3448 try writer.writeAll("return;\n");
3440 }3449 }
3441 return .none;3450 return .none;
3442}3451}
34433452
3444fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {3453fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
3454 const mod = f.object.dg.module;
3445 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3455 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
34463456
3447 const operand = try f.resolveInst(ty_op.operand);3457 const operand = try f.resolveInst(ty_op.operand);
3448 try reap(f, inst, &.{ty_op.operand});3458 try reap(f, inst, &.{ty_op.operand});
34493459
3450 const inst_ty = f.air.typeOfIndex(inst);3460 const inst_ty = f.typeOfIndex(inst);
3451 const inst_scalar_ty = inst_ty.scalarType();3461 const inst_scalar_ty = inst_ty.scalarType(mod);
3452 const operand_ty = f.air.typeOf(ty_op.operand);3462 const operand_ty = f.typeOf(ty_op.operand);
3453 const scalar_ty = operand_ty.scalarType();3463 const scalar_ty = operand_ty.scalarType(mod);
34543464
3455 const writer = f.object.writer();3465 const writer = f.object.writer();
3456 const local = try f.allocLocal(inst, inst_ty);3466 const local = try f.allocLocal(inst, inst_ty);
...@@ -3467,20 +3477,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3467,20 +3477,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
3467}3477}
34683478
3469fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {3479fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3480 const mod = f.object.dg.module;
3470 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3481 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
34713482
3472 const operand = try f.resolveInst(ty_op.operand);3483 const operand = try f.resolveInst(ty_op.operand);
3473 try reap(f, inst, &.{ty_op.operand});3484 try reap(f, inst, &.{ty_op.operand});
3474 const inst_ty = f.air.typeOfIndex(inst);3485 const inst_ty = f.typeOfIndex(inst);
3475 const inst_scalar_ty = inst_ty.scalarType();3486 const inst_scalar_ty = inst_ty.scalarType(mod);
3476 const target = f.object.dg.module.getTarget();3487 const dest_int_info = inst_scalar_ty.intInfo(mod);
3477 const dest_int_info = inst_scalar_ty.intInfo(target);
3478 const dest_bits = dest_int_info.bits;3488 const dest_bits = dest_int_info.bits;
3479 const dest_c_bits = toCIntBits(dest_int_info.bits) orelse3489 const dest_c_bits = toCIntBits(dest_int_info.bits) orelse
3480 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});3490 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3481 const operand_ty = f.air.typeOf(ty_op.operand);3491 const operand_ty = f.typeOf(ty_op.operand);
3482 const scalar_ty = operand_ty.scalarType();3492 const scalar_ty = operand_ty.scalarType(mod);
3483 const scalar_int_info = scalar_ty.intInfo(target);3493 const scalar_int_info = scalar_ty.intInfo(mod);
34843494
3485 const writer = f.object.writer();3495 const writer = f.object.writer();
3486 const local = try f.allocLocal(inst, inst_ty);3496 const local = try f.allocLocal(inst, inst_ty);
...@@ -3508,14 +3518,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3508,14 +3518,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3508 try v.elem(f, writer);3518 try v.elem(f, writer);
3509 } else switch (dest_int_info.signedness) {3519 } else switch (dest_int_info.signedness) {
3510 .unsigned => {3520 .unsigned => {
3511 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);3521 const mask_val = try inst_scalar_ty.maxIntScalar(mod, scalar_ty);
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);
3519 try writer.writeAll("zig_and_");3522 try writer.writeAll("zig_and_");
3520 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);3523 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
3521 try writer.writeByte('(');3524 try writer.writeByte('(');
...@@ -3526,11 +3529,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3526,11 +3529,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3526 .signed => {3529 .signed => {
3527 const c_bits = toCIntBits(scalar_int_info.bits) orelse3530 const c_bits = toCIntBits(scalar_int_info.bits) orelse
3528 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});3531 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3529 var shift_pl = Value.Payload.U64{3532 const shift_val = try mod.intValue(Type.u8, c_bits - dest_bits);
3530 .base = .{ .tag = .int_u64 },
3531 .data = c_bits - dest_bits,
3532 };
3533 const shift_val = Value.initPayload(&shift_pl.base);
35343533
3535 try writer.writeAll("zig_shr_");3534 try writer.writeAll("zig_shr_");
3536 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);3535 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
...@@ -3566,7 +3565,7 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3566,7 +3565,7 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
3566 const operand = try f.resolveInst(un_op);3565 const operand = try f.resolveInst(un_op);
3567 try reap(f, inst, &.{un_op});3566 try reap(f, inst, &.{un_op});
3568 const writer = f.object.writer();3567 const writer = f.object.writer();
3569 const inst_ty = f.air.typeOfIndex(inst);3568 const inst_ty = f.typeOfIndex(inst);
3570 const local = try f.allocLocal(inst, inst_ty);3569 const local = try f.allocLocal(inst, inst_ty);
3571 const a = try Assignment.start(f, writer, inst_ty);3570 const a = try Assignment.start(f, writer, inst_ty);
3572 try f.writeCValue(writer, local, .Other);3571 try f.writeCValue(writer, local, .Other);
...@@ -3577,17 +3576,18 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3577,17 +3576,18 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
3577}3576}
35783577
3579fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {3578fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3579 const mod = f.object.dg.module;
3580 // *a = b;3580 // *a = b;
3581 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3581 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
35823582
3583 const ptr_ty = f.air.typeOf(bin_op.lhs);3583 const ptr_ty = f.typeOf(bin_op.lhs);
3584 const ptr_scalar_ty = ptr_ty.scalarType();3584 const ptr_scalar_ty = ptr_ty.scalarType(mod);
3585 const ptr_info = ptr_scalar_ty.ptrInfo().data;3585 const ptr_info = ptr_scalar_ty.ptrInfo(mod);
35863586
3587 const ptr_val = try f.resolveInst(bin_op.lhs);3587 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
3592 if (val_is_undef) {3592 if (val_is_undef) {
3593 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3593 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 {...@@ -3602,10 +3602,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3602 return .none;3602 return .none;
3603 }3603 }
36043604
3605 const target = f.object.dg.module.getTarget();
3606 const is_aligned = ptr_info.@"align" == 0 or3605 const is_aligned = ptr_info.@"align" == 0 or
3607 ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(target);3606 ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(mod);
3608 const is_array = lowersToArray(ptr_info.pointee_type, target);3607 const is_array = lowersToArray(ptr_info.pointee_type, mod);
3609 const need_memcpy = !is_aligned or is_array;3608 const need_memcpy = !is_aligned or is_array;
36103609
3611 const src_val = try f.resolveInst(bin_op.rhs);3610 const src_val = try f.resolveInst(bin_op.rhs);
...@@ -3647,22 +3646,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -3647,22 +3646,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3647 }3646 }
3648 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {3647 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {
3649 const host_bits = ptr_info.host_size * 8;3648 const host_bits = ptr_info.host_size * 8;
3650 var host_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = host_bits };3649 const host_ty = try mod.intType(.unsigned, host_bits);
3651 const host_ty = Type.initPayload(&host_pl.base);
36523650
3653 var bit_offset_ty_pl = Type.Payload.Bits{3651 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
3654 .base = .{ .tag = .int_unsigned },3652 const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.bit_offset);
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);
36643653
3665 const src_bits = src_ty.bitSize(target);3654 const src_bits = src_ty.bitSize(mod);
36663655
3667 const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb;3656 const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb;
3668 var stack align(@alignOf(ExpectedContents)) =3657 var stack align(@alignOf(ExpectedContents)) =
...@@ -3675,11 +3664,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -3675,11 +3664,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3675 try mask.shiftLeft(&mask, ptr_info.bit_offset);3664 try mask.shiftLeft(&mask, ptr_info.bit_offset);
3676 try mask.bitNotWrap(&mask, .unsigned, host_bits);3665 try mask.bitNotWrap(&mask, .unsigned, host_bits);
36773666
3678 var mask_pl = Value.Payload.BigInt{3667 const mask_val = try mod.intValue_big(host_ty, mask.toConst());
3679 .base = .{ .tag = .int_big_positive },
3680 .data = mask.limbs[0..mask.len()],
3681 };
3682 const mask_val = Value.initPayload(&mask_pl.base);
36833668
3684 try f.writeCValueDeref(writer, ptr_val);3669 try f.writeCValueDeref(writer, ptr_val);
3685 try v.elem(f, writer);3670 try v.elem(f, writer);
...@@ -3693,9 +3678,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -3693,9 +3678,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3693 try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});3678 try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});
3694 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);3679 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
3695 try writer.writeByte('(');3680 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;
3697 if (cant_cast) {3682 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", .{});
3699 try writer.writeAll("zig_make_");3684 try writer.writeAll("zig_make_");
3700 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);3685 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
3701 try writer.writeAll("(0, ");3686 try writer.writeAll("(0, ");
...@@ -3705,7 +3690,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -3705,7 +3690,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3705 try writer.writeByte(')');3690 try writer.writeByte(')');
3706 }3691 }
37073692
3708 if (src_ty.isPtrAtRuntime()) {3693 if (src_ty.isPtrAtRuntime(mod)) {
3709 try writer.writeByte('(');3694 try writer.writeByte('(');
3710 try f.renderType(writer, Type.usize);3695 try f.renderType(writer, Type.usize);
3711 try writer.writeByte(')');3696 try writer.writeByte(')');
...@@ -3728,6 +3713,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -3728,6 +3713,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3728}3713}
37293714
3730fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {3715fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
3716 const mod = f.object.dg.module;
3731 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;3717 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3732 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;3718 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:...@@ -3735,9 +3721,9 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3735 const rhs = try f.resolveInst(bin_op.rhs);3721 const rhs = try f.resolveInst(bin_op.rhs);
3736 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3722 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37373723
3738 const inst_ty = f.air.typeOfIndex(inst);3724 const inst_ty = f.typeOfIndex(inst);
3739 const operand_ty = f.air.typeOf(bin_op.lhs);3725 const operand_ty = f.typeOf(bin_op.lhs);
3740 const scalar_ty = operand_ty.scalarType();3726 const scalar_ty = operand_ty.scalarType(mod);
37413727
3742 const w = f.object.writer();3728 const w = f.object.writer();
3743 const local = try f.allocLocal(inst, inst_ty);3729 const local = try f.allocLocal(inst, inst_ty);
...@@ -3765,15 +3751,16 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3765,15 +3751,16 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3765}3751}
37663752
3767fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {3753fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
3754 const mod = f.object.dg.module;
3768 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3755 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3769 const operand_ty = f.air.typeOf(ty_op.operand);3756 const operand_ty = f.typeOf(ty_op.operand);
3770 const scalar_ty = operand_ty.scalarType();3757 const scalar_ty = operand_ty.scalarType(mod);
3771 if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits);3758 if (scalar_ty.ip_index != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);
37723759
3773 const op = try f.resolveInst(ty_op.operand);3760 const op = try f.resolveInst(ty_op.operand);
3774 try reap(f, inst, &.{ty_op.operand});3761 try reap(f, inst, &.{ty_op.operand});
37753762
3776 const inst_ty = f.air.typeOfIndex(inst);3763 const inst_ty = f.typeOfIndex(inst);
37773764
3778 const writer = f.object.writer();3765 const writer = f.object.writer();
3779 const local = try f.allocLocal(inst, inst_ty);3766 const local = try f.allocLocal(inst, inst_ty);
...@@ -3797,18 +3784,18 @@ fn airBinOp(...@@ -3797,18 +3784,18 @@ fn airBinOp(
3797 operation: []const u8,3784 operation: []const u8,
3798 info: BuiltinInfo,3785 info: BuiltinInfo,
3799) !CValue {3786) !CValue {
3787 const mod = f.object.dg.module;
3800 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3788 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3801 const operand_ty = f.air.typeOf(bin_op.lhs);3789 const operand_ty = f.typeOf(bin_op.lhs);
3802 const scalar_ty = operand_ty.scalarType();3790 const scalar_ty = operand_ty.scalarType(mod);
3803 const target = f.object.dg.module.getTarget();3791 if ((scalar_ty.isInt(mod) and scalar_ty.bitSize(mod) > 64) or scalar_ty.isRuntimeFloat())
3804 if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat())
3805 return try airBinBuiltinCall(f, inst, operation, info);3792 return try airBinBuiltinCall(f, inst, operation, info);
38063793
3807 const lhs = try f.resolveInst(bin_op.lhs);3794 const lhs = try f.resolveInst(bin_op.lhs);
3808 const rhs = try f.resolveInst(bin_op.rhs);3795 const rhs = try f.resolveInst(bin_op.rhs);
3809 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3796 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
3813 const writer = f.object.writer();3800 const writer = f.object.writer();
3814 const local = try f.allocLocal(inst, inst_ty);3801 const local = try f.allocLocal(inst, inst_ty);
...@@ -3835,12 +3822,12 @@ fn airCmpOp(...@@ -3835,12 +3822,12 @@ fn airCmpOp(
3835 data: anytype,3822 data: anytype,
3836 operator: std.math.CompareOperator,3823 operator: std.math.CompareOperator,
3837) !CValue {3824) !CValue {
3838 const lhs_ty = f.air.typeOf(data.lhs);3825 const mod = f.object.dg.module;
3839 const scalar_ty = lhs_ty.scalarType();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();3829 const scalar_bits = scalar_ty.bitSize(mod);
3842 const scalar_bits = scalar_ty.bitSize(target);3830 if (scalar_ty.isInt(mod) and scalar_bits > 64)
3843 if (scalar_ty.isInt() and scalar_bits > 64)
3844 return airCmpBuiltinCall(3831 return airCmpBuiltinCall(
3845 f,3832 f,
3846 inst,3833 inst,
...@@ -3852,13 +3839,13 @@ fn airCmpOp(...@@ -3852,13 +3839,13 @@ fn airCmpOp(
3852 if (scalar_ty.isRuntimeFloat())3839 if (scalar_ty.isRuntimeFloat())
3853 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);3840 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
38543841
3855 const inst_ty = f.air.typeOfIndex(inst);3842 const inst_ty = f.typeOfIndex(inst);
3856 const lhs = try f.resolveInst(data.lhs);3843 const lhs = try f.resolveInst(data.lhs);
3857 const rhs = try f.resolveInst(data.rhs);3844 const rhs = try f.resolveInst(data.rhs);
3858 try reap(f, inst, &.{ data.lhs, data.rhs });3845 try reap(f, inst, &.{ data.lhs, data.rhs });
38593846
3860 const rhs_ty = f.air.typeOf(data.rhs);3847 const rhs_ty = f.typeOf(data.rhs);
3861 const need_cast = lhs_ty.isSinglePointer() or rhs_ty.isSinglePointer();3848 const need_cast = lhs_ty.isSinglePointer(mod) or rhs_ty.isSinglePointer(mod);
3862 const writer = f.object.writer();3849 const writer = f.object.writer();
3863 const local = try f.allocLocal(inst, inst_ty);3850 const local = try f.allocLocal(inst, inst_ty);
3864 const v = try Vectorize.start(f, inst, writer, lhs_ty);3851 const v = try Vectorize.start(f, inst, writer, lhs_ty);
...@@ -3885,12 +3872,12 @@ fn airEquality(...@@ -3885,12 +3872,12 @@ fn airEquality(
3885 inst: Air.Inst.Index,3872 inst: Air.Inst.Index,
3886 operator: std.math.CompareOperator,3873 operator: std.math.CompareOperator,
3887) !CValue {3874) !CValue {
3875 const mod = f.object.dg.module;
3888 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3876 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
38893877
3890 const operand_ty = f.air.typeOf(bin_op.lhs);3878 const operand_ty = f.typeOf(bin_op.lhs);
3891 const target = f.object.dg.module.getTarget();3879 const operand_bits = operand_ty.bitSize(mod);
3892 const operand_bits = operand_ty.bitSize(target);3880 if (operand_ty.isInt(mod) and operand_bits > 64)
3893 if (operand_ty.isInt() and operand_bits > 64)
3894 return airCmpBuiltinCall(3881 return airCmpBuiltinCall(
3895 f,3882 f,
3896 inst,3883 inst,
...@@ -3907,12 +3894,12 @@ fn airEquality(...@@ -3907,12 +3894,12 @@ fn airEquality(
3907 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3894 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
39083895
3909 const writer = f.object.writer();3896 const writer = f.object.writer();
3910 const inst_ty = f.air.typeOfIndex(inst);3897 const inst_ty = f.typeOfIndex(inst);
3911 const local = try f.allocLocal(inst, inst_ty);3898 const local = try f.allocLocal(inst, inst_ty);
3912 try f.writeCValue(writer, local, .Other);3899 try f.writeCValue(writer, local, .Other);
3913 try writer.writeAll(" = ");3900 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)) {
3916 // (A && B) || (C && (A == B))3903 // (A && B) || (C && (A == B))
3917 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload3904 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
39183905
...@@ -3951,7 +3938,7 @@ fn airEquality(...@@ -3951,7 +3938,7 @@ fn airEquality(
3951fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {3938fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
3952 const un_op = f.air.instructions.items(.data)[inst].un_op;3939 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);
3955 const operand = try f.resolveInst(un_op);3942 const operand = try f.resolveInst(un_op);
3956 try reap(f, inst, &.{un_op});3943 try reap(f, inst, &.{un_op});
39573944
...@@ -3965,6 +3952,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3965,6 +3952,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
3965}3952}
39663953
3967fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {3954fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
3955 const mod = f.object.dg.module;
3968 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;3956 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3969 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;3957 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 {...@@ -3972,9 +3960,9 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
3972 const rhs = try f.resolveInst(bin_op.rhs);3960 const rhs = try f.resolveInst(bin_op.rhs);
3973 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3961 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
39743962
3975 const inst_ty = f.air.typeOfIndex(inst);3963 const inst_ty = f.typeOfIndex(inst);
3976 const inst_scalar_ty = inst_ty.scalarType();3964 const inst_scalar_ty = inst_ty.scalarType(mod);
3977 const elem_ty = inst_scalar_ty.elemType2();3965 const elem_ty = inst_scalar_ty.elemType2(mod);
39783966
3979 const local = try f.allocLocal(inst, inst_ty);3967 const local = try f.allocLocal(inst, inst_ty);
3980 const writer = f.object.writer();3968 const writer = f.object.writer();
...@@ -3983,7 +3971,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {...@@ -3983,7 +3971,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
3983 try v.elem(f, writer);3971 try v.elem(f, writer);
3984 try writer.writeAll(" = ");3972 try writer.writeAll(" = ");
39853973
3986 if (elem_ty.hasRuntimeBitsIgnoreComptime()) {3974 if (elem_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3987 // We must convert to and from integer types to prevent UB if the operation3975 // We must convert to and from integer types to prevent UB if the operation
3988 // results in a NULL pointer, or if LHS is NULL. The operation is only UB3976 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
3989 // if the result is NULL and then dereferenced.3977 // if the result is NULL and then dereferenced.
...@@ -4012,13 +4000,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {...@@ -4012,13 +4000,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
4012}4000}
40134001
4014fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {4002fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {
4003 const mod = f.object.dg.module;
4015 const bin_op = f.air.instructions.items(.data)[inst].bin_op;4004 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
40164005
4017 const inst_ty = f.air.typeOfIndex(inst);4006 const inst_ty = f.typeOfIndex(inst);
4018 const inst_scalar_ty = inst_ty.scalarType();4007 const inst_scalar_ty = inst_ty.scalarType(mod);
40194008
4020 const target = f.object.dg.module.getTarget();4009 if (inst_scalar_ty.isInt(mod) and inst_scalar_ty.bitSize(mod) > 64)
4021 if (inst_scalar_ty.isInt() and inst_scalar_ty.bitSize(target) > 64)
4022 return try airBinBuiltinCall(f, inst, operation[1..], .none);4010 return try airBinBuiltinCall(f, inst, operation[1..], .none);
4023 if (inst_scalar_ty.isRuntimeFloat())4011 if (inst_scalar_ty.isRuntimeFloat())
4024 return try airBinFloatOp(f, inst, operation);4012 return try airBinFloatOp(f, inst, operation);
...@@ -4054,6 +4042,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -4054,6 +4042,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
4054}4042}
40554043
4056fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {4044fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
4045 const mod = f.object.dg.module;
4057 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;4046 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4058 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;4047 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 {...@@ -4061,9 +4050,8 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
4061 const len = try f.resolveInst(bin_op.rhs);4050 const len = try f.resolveInst(bin_op.rhs);
4062 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4051 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
40634052
4064 const inst_ty = f.air.typeOfIndex(inst);4053 const inst_ty = f.typeOfIndex(inst);
4065 var buf: Type.SlicePtrFieldTypeBuffer = undefined;4054 const ptr_ty = inst_ty.slicePtrFieldType(mod);
4066 const ptr_ty = inst_ty.slicePtrFieldType(&buf);
40674055
4068 const writer = f.object.writer();4056 const writer = f.object.writer();
4069 const local = try f.allocLocal(inst, inst_ty);4057 const local = try f.allocLocal(inst, inst_ty);
...@@ -4092,12 +4080,11 @@ fn airCall(...@@ -4092,12 +4080,11 @@ fn airCall(
4092 inst: Air.Inst.Index,4080 inst: Air.Inst.Index,
4093 modifier: std.builtin.CallModifier,4081 modifier: std.builtin.CallModifier,
4094) !CValue {4082) !CValue {
4083 const mod = f.object.dg.module;
4095 // Not even allowed to call panic in a naked function.4084 // 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
4098 const gpa = f.object.dg.gpa;4087 const gpa = f.object.dg.gpa;
4099 const module = f.object.dg.module;
4100 const target = module.getTarget();
4101 const writer = f.object.writer();4088 const writer = f.object.writer();
41024089
4103 const pl_op = f.air.instructions.items(.data)[inst].pl_op;4090 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
...@@ -4107,7 +4094,7 @@ fn airCall(...@@ -4107,7 +4094,7 @@ fn airCall(
4107 const resolved_args = try gpa.alloc(CValue, args.len);4094 const resolved_args = try gpa.alloc(CValue, args.len);
4108 defer gpa.free(resolved_args);4095 defer gpa.free(resolved_args);
4109 for (resolved_args, args) |*resolved_arg, arg| {4096 for (resolved_args, args) |*resolved_arg, arg| {
4110 const arg_ty = f.air.typeOf(arg);4097 const arg_ty = f.typeOf(arg);
4111 const arg_cty = try f.typeToIndex(arg_ty, .parameter);4098 const arg_cty = try f.typeToIndex(arg_ty, .parameter);
4112 if (f.indexToCType(arg_cty).tag() == .void) {4099 if (f.indexToCType(arg_cty).tag() == .void) {
4113 resolved_arg.* = .none;4100 resolved_arg.* = .none;
...@@ -4115,8 +4102,7 @@ fn airCall(...@@ -4115,8 +4102,7 @@ fn airCall(
4115 }4102 }
4116 resolved_arg.* = try f.resolveInst(arg);4103 resolved_arg.* = try f.resolveInst(arg);
4117 if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {4104 if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {
4118 var lowered_arg_buf: LowerFnRetTyBuffer = undefined;4105 const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod);
4119 const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, target);
41204106
4121 const array_local = try f.allocLocal(inst, lowered_arg_ty);4107 const array_local = try f.allocLocal(inst, lowered_arg_ty);
4122 try writer.writeAll("memcpy(");4108 try writer.writeAll("memcpy(");
...@@ -4138,22 +4124,21 @@ fn airCall(...@@ -4138,22 +4124,21 @@ fn airCall(
4138 for (args) |arg| try bt.feed(arg);4124 for (args) |arg| try bt.feed(arg);
4139 }4125 }
41404126
4141 const callee_ty = f.air.typeOf(pl_op.operand);4127 const callee_ty = f.typeOf(pl_op.operand);
4142 const fn_ty = switch (callee_ty.zigTypeTag()) {4128 const fn_ty = switch (callee_ty.zigTypeTag(mod)) {
4143 .Fn => callee_ty,4129 .Fn => callee_ty,
4144 .Pointer => callee_ty.childType(),4130 .Pointer => callee_ty.childType(mod),
4145 else => unreachable,4131 else => unreachable,
4146 };4132 };
41474133
4148 const ret_ty = fn_ty.fnReturnType();4134 const ret_ty = fn_ty.fnReturnType(mod);
4149 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;4135 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
4150 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
41514136
4152 const result_local = result: {4137 const result_local = result: {
4153 if (modifier == .always_tail) {4138 if (modifier == .always_tail) {
4154 try writer.writeAll("zig_always_tail return ");4139 try writer.writeAll("zig_always_tail return ");
4155 break :result .none;4140 break :result .none;
4156 } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) {4141 } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4157 break :result .none;4142 break :result .none;
4158 } else if (f.liveness.isUnused(inst)) {4143 } else if (f.liveness.isUnused(inst)) {
4159 try writer.writeByte('(');4144 try writer.writeByte('(');
...@@ -4171,19 +4156,22 @@ fn airCall(...@@ -4171,19 +4156,22 @@ fn airCall(
4171 callee: {4156 callee: {
4172 known: {4157 known: {
4173 const fn_decl = fn_decl: {4158 const fn_decl = fn_decl: {
4174 const callee_val = f.air.value(pl_op.operand) orelse break :known;4159 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
4175 break :fn_decl switch (callee_val.tag()) {4160 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
4176 .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,4161 .extern_func => |extern_func| extern_func.decl,
4177 .function => callee_val.castTag(.function).?.data.owner_decl,4162 .func => |func| mod.funcPtr(func.index).owner_decl,
4178 .decl_ref => callee_val.castTag(.decl_ref).?.data,4163 .ptr => |ptr| switch (ptr.addr) {
4164 .decl => |decl| decl,
4165 else => break :known,
4166 },
4179 else => break :known,4167 else => break :known,
4180 };4168 };
4181 };4169 };
4182 switch (modifier) {4170 switch (modifier) {
4183 .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl, 0),4171 .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(4172 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(
4185 @unionInit(LazyFnKey, @tagName(mod), fn_decl),4173 @unionInit(LazyFnKey, @tagName(m), fn_decl),
4186 @unionInit(LazyFnValue.Data, @tagName(mod), {}),4174 @unionInit(LazyFnValue.Data, @tagName(m), {}),
4187 )),4175 )),
4188 else => unreachable,4176 else => unreachable,
4189 }4177 }
...@@ -4211,7 +4199,7 @@ fn airCall(...@@ -4211,7 +4199,7 @@ fn airCall(
4211 try writer.writeAll(");\n");4199 try writer.writeAll(");\n");
42124200
4213 const result = result: {4201 const result = result: {
4214 if (result_local == .none or !lowersToArray(ret_ty, target))4202 if (result_local == .none or !lowersToArray(ret_ty, mod))
4215 break :result result_local;4203 break :result result_local;
42164204
4217 const array_local = try f.allocLocal(inst, ret_ty);4205 const array_local = try f.allocLocal(inst, ret_ty);
...@@ -4245,18 +4233,21 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4245,18 +4233,21 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
4245}4233}
42464234
4247fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {4235fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
4248 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;4236 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
4249 const writer = f.object.writer();
4250 const function = f.air.values[ty_pl.payload].castTag(.function).?.data;
4251 const mod = f.object.dg.module;4237 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 });
4253 return .none;4243 return .none;
4254}4244}
42554245
4256fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {4246fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
4247 const mod = f.object.dg.module;
4257 const pl_op = f.air.instructions.items(.data)[inst].pl_op;4248 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
4258 const name = f.air.nullTerminatedString(pl_op.payload);4249 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;
4260 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);4251 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
42614252
4262 try reap(f, inst, &.{pl_op.operand});4253 try reap(f, inst, &.{pl_op.operand});
...@@ -4266,6 +4257,7 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4266,6 +4257,7 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
4266}4257}
42674258
4268fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {4259fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4260 const mod = f.object.dg.module;
4269 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;4261 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4270 const extra = f.air.extraData(Air.Block, ty_pl.payload);4262 const extra = f.air.extraData(Air.Block, ty_pl.payload);
4271 const body = f.air.extra[extra.end..][0..extra.data.body_len];4263 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 {...@@ -4275,8 +4267,8 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4275 f.next_block_index += 1;4267 f.next_block_index += 1;
4276 const writer = f.object.writer();4268 const writer = f.object.writer();
42774269
4278 const inst_ty = f.air.typeOfIndex(inst);4270 const inst_ty = f.typeOfIndex(inst);
4279 const result = if (inst_ty.tag() != .void and !f.liveness.isUnused(inst))4271 const result = if (inst_ty.ip_index != .void_type and !f.liveness.isUnused(inst))
4280 try f.allocLocal(inst, inst_ty)4272 try f.allocLocal(inst, inst_ty)
4281 else4273 else
4282 .none;4274 .none;
...@@ -4298,7 +4290,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4298,7 +4290,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4298 try f.object.indent_writer.insertNewline();4290 try f.object.indent_writer.insertNewline();
42994291
4300 // noreturn blocks have no `br` instructions reaching them, so we don't want a label4292 // 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)) {
4302 // label must be followed by an expression, include an empty one.4294 // label must be followed by an expression, include an empty one.
4303 try writer.print("zig_block_{d}:;\n", .{block_id});4295 try writer.print("zig_block_{d}:;\n", .{block_id});
4304 }4296 }
...@@ -4310,15 +4302,16 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4310,15 +4302,16 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {
4310 const pl_op = f.air.instructions.items(.data)[inst].pl_op;4302 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
4311 const extra = f.air.extraData(Air.Try, pl_op.payload);4303 const extra = f.air.extraData(Air.Try, pl_op.payload);
4312 const body = f.air.extra[extra.end..][0..extra.data.body_len];4304 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);
4314 return lowerTry(f, inst, pl_op.operand, body, err_union_ty, false);4306 return lowerTry(f, inst, pl_op.operand, body, err_union_ty, false);
4315}4307}
43164308
4317fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {4309fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {
4310 const mod = f.object.dg.module;
4318 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;4311 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4319 const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);4312 const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);
4320 const body = f.air.extra[extra.end..][0..extra.data.body_len];4313 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);
4322 return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true);4315 return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true);
4323}4316}
43244317
...@@ -4330,14 +4323,15 @@ fn lowerTry(...@@ -4330,14 +4323,15 @@ fn lowerTry(
4330 err_union_ty: Type,4323 err_union_ty: Type,
4331 is_ptr: bool,4324 is_ptr: bool,
4332) !CValue {4325) !CValue {
4326 const mod = f.object.dg.module;
4333 const err_union = try f.resolveInst(operand);4327 const err_union = try f.resolveInst(operand);
4334 const inst_ty = f.air.typeOfIndex(inst);4328 const inst_ty = f.typeOfIndex(inst);
4335 const liveness_condbr = f.liveness.getCondBr(inst);4329 const liveness_condbr = f.liveness.getCondBr(inst);
4336 const writer = f.object.writer();4330 const writer = f.object.writer();
4337 const payload_ty = err_union_ty.errorUnionPayload();4331 const payload_ty = err_union_ty.errorUnionPayload(mod);
4338 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();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)) {
4341 try writer.writeAll("if (");4335 try writer.writeAll("if (");
4342 if (!payload_has_bits) {4336 if (!payload_has_bits) {
4343 if (is_ptr)4337 if (is_ptr)
...@@ -4399,7 +4393,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4399,7 +4393,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
43994393
4400 // If result is .none then the value of the block is unused.4394 // If result is .none then the value of the block is unused.
4401 if (result != .none) {4395 if (result != .none) {
4402 const operand_ty = f.air.typeOf(branch.operand);4396 const operand_ty = f.typeOf(branch.operand);
4403 const operand = try f.resolveInst(branch.operand);4397 const operand = try f.resolveInst(branch.operand);
4404 try reap(f, inst, &.{branch.operand});4398 try reap(f, inst, &.{branch.operand});
44054399
...@@ -4416,10 +4410,10 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4416,10 +4410,10 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
44164410
4417fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {4411fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
4418 const ty_op = f.air.instructions.items(.data)[inst].ty_op;4412 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
4421 const operand = try f.resolveInst(ty_op.operand);4415 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
4424 const bitcasted = try bitcast(f, dest_ty, operand, operand_ty);4418 const bitcasted = try bitcast(f, dest_ty, operand, operand_ty);
4425 try reap(f, inst, &.{ty_op.operand});4419 try reap(f, inst, &.{ty_op.operand});
...@@ -4431,6 +4425,8 @@ const LocalResult = struct {...@@ -4431,6 +4425,8 @@ const LocalResult = struct {
4431 need_free: bool,4425 need_free: bool,
44324426
4433 fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue {4427 fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue {
4428 const mod = f.object.dg.module;
4429
4434 if (lr.need_free) {4430 if (lr.need_free) {
4435 // Move the freshly allocated local to be owned by this instruction,4431 // Move the freshly allocated local to be owned by this instruction,
4436 // by returning it here instead of freeing it.4432 // by returning it here instead of freeing it.
...@@ -4441,7 +4437,7 @@ const LocalResult = struct {...@@ -4441,7 +4437,7 @@ const LocalResult = struct {
4441 try lr.free(f);4437 try lr.free(f);
4442 const writer = f.object.writer();4438 const writer = f.object.writer();
4443 try f.writeCValue(writer, local, .Other);4439 try f.writeCValue(writer, local, .Other);
4444 if (dest_ty.isAbiInt()) {4440 if (dest_ty.isAbiInt(mod)) {
4445 try writer.writeAll(" = ");4441 try writer.writeAll(" = ");
4446 } else {4442 } else {
4447 try writer.writeAll(" = (");4443 try writer.writeAll(" = (");
...@@ -4461,12 +4457,13 @@ const LocalResult = struct {...@@ -4461,12 +4457,13 @@ const LocalResult = struct {
4461};4457};
44624458
4463fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult {4459fn 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();
4465 const writer = f.object.writer();4462 const writer = f.object.writer();
44664463
4467 if (operand_ty.isAbiInt() and dest_ty.isAbiInt()) {4464 if (operand_ty.isAbiInt(mod) and dest_ty.isAbiInt(mod)) {
4468 const src_info = dest_ty.intInfo(target);4465 const src_info = dest_ty.intInfo(mod);
4469 const dest_info = operand_ty.intInfo(target);4466 const dest_info = operand_ty.intInfo(mod);
4470 if (src_info.signedness == dest_info.signedness and4467 if (src_info.signedness == dest_info.signedness and
4471 src_info.bits == dest_info.bits)4468 src_info.bits == dest_info.bits)
4472 {4469 {
...@@ -4477,7 +4474,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca...@@ -4477,7 +4474,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
4477 }4474 }
4478 }4475 }
44794476
4480 if (dest_ty.isPtrAtRuntime() and operand_ty.isPtrAtRuntime()) {4477 if (dest_ty.isPtrAtRuntime(mod) and operand_ty.isPtrAtRuntime(mod)) {
4481 const local = try f.allocLocal(0, dest_ty);4478 const local = try f.allocLocal(0, dest_ty);
4482 try f.writeCValue(writer, local, .Other);4479 try f.writeCValue(writer, local, .Other);
4483 try writer.writeAll(" = (");4480 try writer.writeAll(" = (");
...@@ -4494,7 +4491,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca...@@ -4494,7 +4491,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
4494 const operand_lval = if (operand == .constant) blk: {4491 const operand_lval = if (operand == .constant) blk: {
4495 const operand_local = try f.allocLocal(0, operand_ty);4492 const operand_local = try f.allocLocal(0, operand_ty);
4496 try f.writeCValue(writer, operand_local, .Other);4493 try f.writeCValue(writer, operand_local, .Other);
4497 if (operand_ty.isAbiInt()) {4494 if (operand_ty.isAbiInt(mod)) {
4498 try writer.writeAll(" = ");4495 try writer.writeAll(" = ");
4499 } else {4496 } else {
4500 try writer.writeAll(" = (");4497 try writer.writeAll(" = (");
...@@ -4516,13 +4513,10 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca...@@ -4516,13 +4513,10 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
4516 try writer.writeAll("));\n");4513 try writer.writeAll("));\n");
45174514
4518 // Ensure padding bits have the expected value.4515 // Ensure padding bits have the expected value.
4519 if (dest_ty.isAbiInt()) {4516 if (dest_ty.isAbiInt(mod)) {
4520 const dest_cty = try f.typeToCType(dest_ty, .complete);4517 const dest_cty = try f.typeToCType(dest_ty, .complete);
4521 const dest_info = dest_ty.intInfo(target);4518 const dest_info = dest_ty.intInfo(mod);
4522 var info_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) {4519 var bits: u16 = dest_info.bits;
4523 .unsigned => .int_unsigned,
4524 .signed => .int_signed,
4525 } }, .data = dest_info.bits };
4526 var wrap_cty: ?CType = null;4520 var wrap_cty: ?CType = null;
4527 var need_bitcasts = false;4521 var need_bitcasts = false;
45284522
...@@ -4535,9 +4529,9 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca...@@ -4535,9 +4529,9 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
4535 const elem_cty = f.indexToCType(pl.data.elem_type);4529 const elem_cty = f.indexToCType(pl.data.elem_type);
4536 wrap_cty = elem_cty.toSignedness(dest_info.signedness);4530 wrap_cty = elem_cty.toSignedness(dest_info.signedness);
4537 need_bitcasts = wrap_cty.?.tag() == .zig_i128;4531 need_bitcasts = wrap_cty.?.tag() == .zig_i128;
4538 info_ty_pl.data -= 1;4532 bits -= 1;
4539 info_ty_pl.data %= @intCast(u16, f.byteSize(elem_cty) * 8);4533 bits %= @intCast(u16, f.byteSize(elem_cty) * 8);
4540 info_ty_pl.data += 1;4534 bits += 1;
4541 }4535 }
4542 try writer.writeAll(" = ");4536 try writer.writeAll(" = ");
4543 if (need_bitcasts) {4537 if (need_bitcasts) {
...@@ -4546,7 +4540,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca...@@ -4546,7 +4540,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
4546 try writer.writeByte('(');4540 try writer.writeByte('(');
4547 }4541 }
4548 try writer.writeAll("zig_wrap_");4542 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);
4550 if (wrap_cty) |cty|4544 if (wrap_cty) |cty|
4551 try f.object.dg.renderCTypeForBuiltinFnName(writer, cty)4545 try f.object.dg.renderCTypeForBuiltinFnName(writer, cty)
4552 else4546 else
...@@ -4622,8 +4616,9 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4622,8 +4616,9 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
4622}4616}
46234617
4624fn airUnreach(f: *Function) !CValue {4618fn airUnreach(f: *Function) !CValue {
4619 const mod = f.object.dg.module;
4625 // Not even allowed to call unreachable in a naked function.4620 // 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
4628 try f.object.writer().writeAll("zig_unreachable();\n");4623 try f.object.writer().writeAll("zig_unreachable();\n");
4629 return .none;4624 return .none;
...@@ -4657,6 +4652,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4657,6 +4652,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4657 try writer.writeAll(") ");4652 try writer.writeAll(") ");
46584653
4659 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);4654 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);
4655 try writer.writeByte('\n');
46604656
4661 // We don't need to use `genBodyResolveState` for the else block, because this instruction is4657 // We don't need to use `genBodyResolveState` for the else block, because this instruction is
4662 // noreturn so must terminate a body, therefore we don't need to leave `value_map` or4658 // 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 {...@@ -4675,19 +4671,20 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4675}4671}
46764672
4677fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {4673fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4674 const mod = f.object.dg.module;
4678 const pl_op = f.air.instructions.items(.data)[inst].pl_op;4675 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
4679 const condition = try f.resolveInst(pl_op.operand);4676 const condition = try f.resolveInst(pl_op.operand);
4680 try reap(f, inst, &.{pl_op.operand});4677 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);
4682 const switch_br = f.air.extraData(Air.SwitchBr, pl_op.payload);4679 const switch_br = f.air.extraData(Air.SwitchBr, pl_op.payload);
4683 const writer = f.object.writer();4680 const writer = f.object.writer();
46844681
4685 try writer.writeAll("switch (");4682 try writer.writeAll("switch (");
4686 if (condition_ty.zigTypeTag() == .Bool) {4683 if (condition_ty.zigTypeTag(mod) == .Bool) {
4687 try writer.writeByte('(');4684 try writer.writeByte('(');
4688 try f.renderType(writer, Type.u1);4685 try f.renderType(writer, Type.u1);
4689 try writer.writeByte(')');4686 try writer.writeByte(')');
4690 } else if (condition_ty.isPtrAtRuntime()) {4687 } else if (condition_ty.isPtrAtRuntime(mod)) {
4691 try writer.writeByte('(');4688 try writer.writeByte('(');
4692 try f.renderType(writer, Type.usize);4689 try f.renderType(writer, Type.usize);
4693 try writer.writeByte(')');4690 try writer.writeByte(')');
...@@ -4714,12 +4711,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4714,12 +4711,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4714 for (items) |item| {4711 for (items) |item| {
4715 try f.object.indent_writer.insertNewline();4712 try f.object.indent_writer.insertNewline();
4716 try writer.writeAll("case ");4713 try writer.writeAll("case ");
4717 if (condition_ty.isPtrAtRuntime()) {4714 if (condition_ty.isPtrAtRuntime(mod)) {
4718 try writer.writeByte('(');4715 try writer.writeByte('(');
4719 try f.renderType(writer, Type.usize);4716 try f.renderType(writer, Type.usize);
4720 try writer.writeByte(')');4717 try writer.writeByte(')');
4721 }4718 }
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);
4723 try writer.writeByte(':');4720 try writer.writeByte(':');
4724 }4721 }
4725 try writer.writeByte(' ');4722 try writer.writeByte(' ');
...@@ -4764,6 +4761,7 @@ fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool {...@@ -4764,6 +4761,7 @@ fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool {
4764}4761}
47654762
4766fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {4763fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4764 const mod = f.object.dg.module;
4767 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;4765 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4768 const extra = f.air.extraData(Air.Asm, ty_pl.payload);4766 const extra = f.air.extraData(Air.Asm, ty_pl.payload);
4769 const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0;4767 const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0;
...@@ -4777,8 +4775,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4777,8 +4775,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
47774775
4778 const result = result: {4776 const result = result: {
4779 const writer = f.object.writer();4777 const writer = f.object.writer();
4780 const inst_ty = f.air.typeOfIndex(inst);4778 const inst_ty = f.typeOfIndex(inst);
4781 const local = if (inst_ty.hasRuntimeBitsIgnoreComptime()) local: {4779 const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod)) local: {
4782 const local = try f.allocLocal(inst, inst_ty);4780 const local = try f.allocLocal(inst, inst_ty);
4783 if (f.wantSafety()) {4781 if (f.wantSafety()) {
4784 try f.writeCValue(writer, local, .Other);4782 try f.writeCValue(writer, local, .Other);
...@@ -4807,7 +4805,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4807,7 +4805,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
48074805
4808 const is_reg = constraint[1] == '{';4806 const is_reg = constraint[1] == '{';
4809 if (is_reg) {4807 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);
4811 try writer.writeAll("register ");4809 try writer.writeAll("register ");
4812 const alignment = 0;4810 const alignment = 0;
4813 const local_value = try f.allocLocalValue(output_ty, alignment);4811 const local_value = try f.allocLocalValue(output_ty, alignment);
...@@ -4840,7 +4838,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4840,7 +4838,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4840 const is_reg = constraint[0] == '{';4838 const is_reg = constraint[0] == '{';
4841 const input_val = try f.resolveInst(input);4839 const input_val = try f.resolveInst(input);
4842 if (asmInputNeedsLocal(constraint, input_val)) {4840 if (asmInputNeedsLocal(constraint, input_val)) {
4843 const input_ty = f.air.typeOf(input);4841 const input_ty = f.typeOf(input);
4844 if (is_reg) try writer.writeAll("register ");4842 if (is_reg) try writer.writeAll("register ");
4845 const alignment = 0;4843 const alignment = 0;
4846 const local_value = try f.allocLocalValue(input_ty, alignment);4844 const local_value = try f.allocLocalValue(input_ty, alignment);
...@@ -5025,6 +5023,7 @@ fn airIsNull(...@@ -5025,6 +5023,7 @@ fn airIsNull(
5025 operator: []const u8,5023 operator: []const u8,
5026 is_ptr: bool,5024 is_ptr: bool,
5027) !CValue {5025) !CValue {
5026 const mod = f.object.dg.module;
5028 const un_op = f.air.instructions.items(.data)[inst].un_op;5027 const un_op = f.air.instructions.items(.data)[inst].un_op;
50295028
5030 const writer = f.object.writer();5029 const writer = f.object.writer();
...@@ -5040,23 +5039,22 @@ fn airIsNull(...@@ -5040,23 +5039,22 @@ fn airIsNull(
5040 try f.writeCValue(writer, operand, .Other);5039 try f.writeCValue(writer, operand, .Other);
5041 }5040 }
50425041
5043 const operand_ty = f.air.typeOf(un_op);5042 const operand_ty = f.typeOf(un_op);
5044 const optional_ty = if (is_ptr) operand_ty.childType() else operand_ty;5043 const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
5045 var payload_buf: Type.Payload.ElemType = undefined;5044 const payload_ty = optional_ty.optionalChild(mod);
5046 const payload_ty = optional_ty.optionalChild(&payload_buf);
5047 var slice_ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
50485045
5049 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime())5046 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
5050 TypedValue{ .ty = Type.bool, .val = Value.true }5047 TypedValue{ .ty = Type.bool, .val = Value.true }
5051 else if (optional_ty.isPtrLikeOptional())5048 else if (optional_ty.isPtrLikeOptional(mod))
5052 // operand is a regular pointer, test `operand !=/== NULL`5049 // operand is a regular pointer, test `operand !=/== NULL`
5053 TypedValue{ .ty = optional_ty, .val = Value.null }5050 TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) }
5054 else if (payload_ty.zigTypeTag() == .ErrorSet)5051 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
5055 TypedValue{ .ty = payload_ty, .val = Value.zero }5052 TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) }
5056 else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload()) rhs: {5053 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
5057 try writer.writeAll(".ptr");5054 try writer.writeAll(".ptr");
5058 const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf);5055 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
5059 break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.null };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) };
5060 } else rhs: {5058 } else rhs: {
5061 try writer.writeAll(".is_null");5059 try writer.writeAll(".is_null");
5062 break :rhs TypedValue{ .ty = Type.bool, .val = Value.true };5060 break :rhs TypedValue{ .ty = Type.bool, .val = Value.true };
...@@ -5070,24 +5068,24 @@ fn airIsNull(...@@ -5070,24 +5068,24 @@ fn airIsNull(
5070}5068}
50715069
5072fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {5070fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
5071 const mod = f.object.dg.module;
5073 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5072 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
50745073
5075 const operand = try f.resolveInst(ty_op.operand);5074 const operand = try f.resolveInst(ty_op.operand);
5076 try reap(f, inst, &.{ty_op.operand});5075 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;5078 const payload_ty = opt_ty.optionalChild(mod);
5080 const payload_ty = opt_ty.optionalChild(&buf);
50815079
5082 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {5080 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5083 return .none;5081 return .none;
5084 }5082 }
50855083
5086 const inst_ty = f.air.typeOfIndex(inst);5084 const inst_ty = f.typeOfIndex(inst);
5087 const writer = f.object.writer();5085 const writer = f.object.writer();
5088 const local = try f.allocLocal(inst, inst_ty);5086 const local = try f.allocLocal(inst, inst_ty);
50895087
5090 if (opt_ty.optionalReprIsPayload()) {5088 if (opt_ty.optionalReprIsPayload(mod)) {
5091 try f.writeCValue(writer, local, .Other);5089 try f.writeCValue(writer, local, .Other);
5092 try writer.writeAll(" = ");5090 try writer.writeAll(" = ");
5093 try f.writeCValue(writer, operand, .Other);5091 try f.writeCValue(writer, operand, .Other);
...@@ -5104,23 +5102,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5104,23 +5102,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
5104}5102}
51055103
5106fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {5104fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5105 const mod = f.object.dg.module;
5107 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5106 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
51085107
5109 const writer = f.object.writer();5108 const writer = f.object.writer();
5110 const operand = try f.resolveInst(ty_op.operand);5109 const operand = try f.resolveInst(ty_op.operand);
5111 try reap(f, inst, &.{ty_op.operand});5110 try reap(f, inst, &.{ty_op.operand});
5112 const ptr_ty = f.air.typeOf(ty_op.operand);5111 const ptr_ty = f.typeOf(ty_op.operand);
5113 const opt_ty = ptr_ty.childType();5112 const opt_ty = ptr_ty.childType(mod);
5114 const inst_ty = f.air.typeOfIndex(inst);5113 const inst_ty = f.typeOfIndex(inst);
51155114
5116 if (!inst_ty.childType().hasRuntimeBitsIgnoreComptime()) {5115 if (!inst_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod)) {
5117 return .{ .undef = inst_ty };5116 return .{ .undef = inst_ty };
5118 }5117 }
51195118
5120 const local = try f.allocLocal(inst, inst_ty);5119 const local = try f.allocLocal(inst, inst_ty);
5121 try f.writeCValue(writer, local, .Other);5120 try f.writeCValue(writer, local, .Other);
51225121
5123 if (opt_ty.optionalReprIsPayload()) {5122 if (opt_ty.optionalReprIsPayload(mod)) {
5124 // the operand is just a regular pointer, no need to do anything special.5123 // the operand is just a regular pointer, no need to do anything special.
5125 // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C5124 // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C
5126 try writer.writeAll(" = ");5125 try writer.writeAll(" = ");
...@@ -5134,17 +5133,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5134,17 +5133,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5134}5133}
51355134
5136fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {5135fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5136 const mod = f.object.dg.module;
5137 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5137 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
5138 const writer = f.object.writer();5138 const writer = f.object.writer();
5139 const operand = try f.resolveInst(ty_op.operand);5139 const operand = try f.resolveInst(ty_op.operand);
5140 try reap(f, inst, &.{ty_op.operand});5140 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)) {
5148 if (f.liveness.isUnused(inst)) {5148 if (f.liveness.isUnused(inst)) {
5149 return .none;5149 return .none;
5150 }5150 }
...@@ -5179,48 +5179,49 @@ fn fieldLocation(...@@ -5179,48 +5179,49 @@ fn fieldLocation(
5179 container_ty: Type,5179 container_ty: Type,
5180 field_ptr_ty: Type,5180 field_ptr_ty: Type,
5181 field_index: u32,5181 field_index: u32,
5182 target: std.Target,5182 mod: *Module,
5183) union(enum) {5183) union(enum) {
5184 begin: void,5184 begin: void,
5185 field: CValue,5185 field: CValue,
5186 byte_offset: u32,5186 byte_offset: u32,
5187 end: void,5187 end: void,
5188} {5188} {
5189 return switch (container_ty.zigTypeTag()) {5189 const ip = &mod.intern_pool;
5190 .Struct => switch (container_ty.containerLayout()) {5190 return switch (container_ty.zigTypeTag(mod)) {
5191 .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| {5191 .Struct => switch (container_ty.containerLayout(mod)) {
5192 if (container_ty.structFieldIsComptime(next_field_index)) continue;5192 .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| {
5193 const field_ty = container_ty.structFieldType(next_field_index);5193 if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
5194 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;5194 const field_ty = container_ty.structFieldType(next_field_index, mod);
51955195 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
5196 break .{ .field = if (container_ty.isSimpleTuple())5196
5197 break .{ .field = if (container_ty.isSimpleTuple(mod))
5197 .{ .field = next_field_index }5198 .{ .field = next_field_index }
5198 else5199 else
5199 .{ .identifier = container_ty.structFieldName(next_field_index) } };5200 .{ .identifier = ip.stringToSlice(container_ty.structFieldName(next_field_index, mod)) } };
5200 } else if (container_ty.hasRuntimeBitsIgnoreComptime()) .end else .begin,5201 } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin,
5201 .Packed => if (field_ptr_ty.ptrInfo().data.host_size == 0)5202 .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0)
5202 .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, target) }5203 .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) }
5203 else5204 else
5204 .begin,5205 .begin,
5205 },5206 },
5206 .Union => switch (container_ty.containerLayout()) {5207 .Union => switch (container_ty.containerLayout(mod)) {
5207 .Auto, .Extern => {5208 .Auto, .Extern => {
5208 const field_ty = container_ty.structFieldType(field_index);5209 const field_ty = container_ty.structFieldType(field_index, mod);
5209 if (!field_ty.hasRuntimeBitsIgnoreComptime())5210 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod))
5210 return if (container_ty.unionTagTypeSafety() != null and5211 return if (container_ty.unionTagTypeSafety(mod) != null and
5211 !container_ty.unionHasAllZeroBitFieldTypes())5212 !container_ty.unionHasAllZeroBitFieldTypes(mod))
5212 .{ .field = .{ .identifier = "payload" } }5213 .{ .field = .{ .identifier = "payload" } }
5213 else5214 else
5214 .begin;5215 .begin;
5215 const field_name = container_ty.unionFields().keys()[field_index];5216 const field_name = container_ty.unionFields(mod).keys()[field_index];
5216 return .{ .field = if (container_ty.unionTagTypeSafety()) |_|5217 return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_|
5217 .{ .payload_identifier = field_name }5218 .{ .payload_identifier = ip.stringToSlice(field_name) }
5218 else5219 else
5219 .{ .identifier = field_name } };5220 .{ .identifier = ip.stringToSlice(field_name) } };
5220 },5221 },
5221 .Packed => .begin,5222 .Packed => .begin,
5222 },5223 },
5223 .Pointer => switch (container_ty.ptrSize()) {5224 .Pointer => switch (container_ty.ptrSize(mod)) {
5224 .Slice => switch (field_index) {5225 .Slice => switch (field_index) {
5225 0 => .{ .field = .{ .identifier = "ptr" } },5226 0 => .{ .field = .{ .identifier = "ptr" } },
5226 1 => .{ .field = .{ .identifier = "len" } },5227 1 => .{ .field = .{ .identifier = "len" } },
...@@ -5238,7 +5239,7 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5238,7 +5239,7 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue {
52385239
5239 const container_ptr_val = try f.resolveInst(extra.struct_operand);5240 const container_ptr_val = try f.resolveInst(extra.struct_operand);
5240 try reap(f, inst, &.{extra.struct_operand});5241 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);
5242 return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, extra.field_index);5243 return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, extra.field_index);
5243}5244}
52445245
...@@ -5247,19 +5248,19 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue...@@ -5247,19 +5248,19 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue
52475248
5248 const container_ptr_val = try f.resolveInst(ty_op.operand);5249 const container_ptr_val = try f.resolveInst(ty_op.operand);
5249 try reap(f, inst, &.{ty_op.operand});5250 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);
5251 return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, index);5252 return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, index);
5252}5253}
52535254
5254fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {5255fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5256 const mod = f.object.dg.module;
5255 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;5257 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
5256 const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;5258 const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
52575259
5258 const target = f.object.dg.module.getTarget();5260 const container_ptr_ty = f.typeOfIndex(inst);
5259 const container_ptr_ty = f.air.typeOfIndex(inst);5261 const container_ty = container_ptr_ty.childType(mod);
5260 const container_ty = container_ptr_ty.childType();
52615262
5262 const field_ptr_ty = f.air.typeOf(extra.field_ptr);5263 const field_ptr_ty = f.typeOf(extra.field_ptr);
5263 const field_ptr_val = try f.resolveInst(extra.field_ptr);5264 const field_ptr_val = try f.resolveInst(extra.field_ptr);
5264 try reap(f, inst, &.{extra.field_ptr});5265 try reap(f, inst, &.{extra.field_ptr});
52655266
...@@ -5270,12 +5271,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5270,12 +5271,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5270 try f.renderType(writer, container_ptr_ty);5271 try f.renderType(writer, container_ptr_ty);
5271 try writer.writeByte(')');5272 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)) {
5274 .begin => try f.writeCValue(writer, field_ptr_val, .Initializer),5275 .begin => try f.writeCValue(writer, field_ptr_val, .Initializer),
5275 .field => |field| {5276 .field => |field| {
5276 var u8_ptr_pl = field_ptr_ty.ptrInfo();5277 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
5277 u8_ptr_pl.data.pointee_type = Type.u8;
5278 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
52795278
5280 try writer.writeAll("((");5279 try writer.writeAll("((");
5281 try f.renderType(writer, u8_ptr_ty);5280 try f.renderType(writer, u8_ptr_ty);
...@@ -5288,15 +5287,9 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5288,15 +5287,9 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5288 try writer.writeAll("))");5287 try writer.writeAll("))");
5289 },5288 },
5290 .byte_offset => |byte_offset| {5289 .byte_offset => |byte_offset| {
5291 var u8_ptr_pl = field_ptr_ty.ptrInfo();5290 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
5292 u8_ptr_pl.data.pointee_type = Type.u8;
5293 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
52945291
5295 var byte_offset_pl = Value.Payload.U64{5292 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
5296 .base = .{ .tag = .int_u64 },
5297 .data = byte_offset,
5298 };
5299 const byte_offset_val = Value.initPayload(&byte_offset_pl.base);
53005293
5301 try writer.writeAll("((");5294 try writer.writeAll("((");
5302 try f.renderType(writer, u8_ptr_ty);5295 try f.renderType(writer, u8_ptr_ty);
...@@ -5306,7 +5299,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5306,7 +5299,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5306 },5299 },
5307 .end => {5300 .end => {
5308 try f.writeCValue(writer, field_ptr_val, .Other);5301 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))});
5310 },5303 },
5311 }5304 }
53125305
...@@ -5321,9 +5314,9 @@ fn fieldPtr(...@@ -5321,9 +5314,9 @@ fn fieldPtr(
5321 container_ptr_val: CValue,5314 container_ptr_val: CValue,
5322 field_index: u32,5315 field_index: u32,
5323) !CValue {5316) !CValue {
5324 const target = f.object.dg.module.getTarget();5317 const mod = f.object.dg.module;
5325 const container_ty = container_ptr_ty.elemType();5318 const container_ty = container_ptr_ty.childType(mod);
5326 const field_ptr_ty = f.air.typeOfIndex(inst);5319 const field_ptr_ty = f.typeOfIndex(inst);
53275320
5328 // Ensure complete type definition is visible before accessing fields.5321 // Ensure complete type definition is visible before accessing fields.
5329 _ = try f.typeToIndex(container_ty, .complete);5322 _ = try f.typeToIndex(container_ty, .complete);
...@@ -5335,22 +5328,16 @@ fn fieldPtr(...@@ -5335,22 +5328,16 @@ fn fieldPtr(
5335 try f.renderType(writer, field_ptr_ty);5328 try f.renderType(writer, field_ptr_ty);
5336 try writer.writeByte(')');5329 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)) {
5339 .begin => try f.writeCValue(writer, container_ptr_val, .Initializer),5332 .begin => try f.writeCValue(writer, container_ptr_val, .Initializer),
5340 .field => |field| {5333 .field => |field| {
5341 try writer.writeByte('&');5334 try writer.writeByte('&');
5342 try f.writeCValueDerefMember(writer, container_ptr_val, field);5335 try f.writeCValueDerefMember(writer, container_ptr_val, field);
5343 },5336 },
5344 .byte_offset => |byte_offset| {5337 .byte_offset => |byte_offset| {
5345 var u8_ptr_pl = field_ptr_ty.ptrInfo();5338 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
5346 u8_ptr_pl.data.pointee_type = Type.u8;
5347 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
53485339
5349 var byte_offset_pl = Value.Payload.U64{5340 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
5350 .base = .{ .tag = .int_u64 },
5351 .data = byte_offset,
5352 };
5353 const byte_offset_val = Value.initPayload(&byte_offset_pl.base);
53545341
5355 try writer.writeAll("((");5342 try writer.writeAll("((");
5356 try f.renderType(writer, u8_ptr_ty);5343 try f.renderType(writer, u8_ptr_ty);
...@@ -5361,7 +5348,7 @@ fn fieldPtr(...@@ -5361,7 +5348,7 @@ fn fieldPtr(
5361 .end => {5348 .end => {
5362 try writer.writeByte('(');5349 try writer.writeByte('(');
5363 try f.writeCValue(writer, container_ptr_val, .Other);5350 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))});
5365 },5352 },
5366 }5353 }
53675354
...@@ -5370,58 +5357,45 @@ fn fieldPtr(...@@ -5370,58 +5357,45 @@ fn fieldPtr(
5370}5357}
53715358
5372fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {5359fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5360 const mod = f.object.dg.module;
5361 const ip = &mod.intern_pool;
5373 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;5362 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
5374 const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;5363 const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;
53755364
5376 const inst_ty = f.air.typeOfIndex(inst);5365 const inst_ty = f.typeOfIndex(inst);
5377 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {5366 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5378 try reap(f, inst, &.{extra.struct_operand});5367 try reap(f, inst, &.{extra.struct_operand});
5379 return .none;5368 return .none;
5380 }5369 }
53815370
5382 const target = f.object.dg.module.getTarget();
5383 const struct_byval = try f.resolveInst(extra.struct_operand);5371 const struct_byval = try f.resolveInst(extra.struct_operand);
5384 try reap(f, inst, &.{extra.struct_operand});5372 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);
5386 const writer = f.object.writer();5374 const writer = f.object.writer();
53875375
5388 // Ensure complete type definition is visible before accessing fields.5376 // Ensure complete type definition is visible before accessing fields.
5389 _ = try f.typeToIndex(struct_ty, .complete);5377 _ = try f.typeToIndex(struct_ty, .complete);
53905378
5391 const field_name: CValue = switch (struct_ty.tag()) {5379 const field_name: CValue = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
5392 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {5380 .struct_type => switch (struct_ty.containerLayout(mod)) {
5393 .Auto, .Extern => if (struct_ty.isSimpleTuple())5381 .Auto, .Extern => if (struct_ty.isSimpleTuple(mod))
5394 .{ .field = extra.field_index }5382 .{ .field = extra.field_index }
5395 else5383 else
5396 .{ .identifier = struct_ty.structFieldName(extra.field_index) },5384 .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) },
5397 .Packed => {5385 .Packed => {
5398 const struct_obj = struct_ty.castTag(.@"struct").?.data;5386 const struct_obj = mod.typeToStruct(struct_ty).?;
5399 const int_info = struct_ty.intInfo(target);5387 const int_info = struct_ty.intInfo(mod);
54005388
5401 var bit_offset_ty_pl = Type.Payload.Bits{5389 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
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);
54065390
5407 var bit_offset_val_pl: Value.Payload.U64 = .{5391 const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index);
5408 .base = .{ .tag = .int_u64 },5392 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
5409 .data = struct_obj.packedFieldBitOffset(target, extra.field_index),
5410 };
5411 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
54125393
5413 const field_int_signedness = if (inst_ty.isAbiInt())5394 const field_int_signedness = if (inst_ty.isAbiInt(mod))
5414 inst_ty.intInfo(target).signedness5395 inst_ty.intInfo(mod).signedness
5415 else5396 else
5416 .unsigned;5397 .unsigned;
5417 var field_int_pl = Type.Payload.Bits{5398 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));
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);
54255399
5426 const temp_local = try f.allocLocal(inst, field_int_ty);5400 const temp_local = try f.allocLocal(inst, field_int_ty);
5427 try f.writeCValue(writer, temp_local, .Other);5401 try f.writeCValue(writer, temp_local, .Other);
...@@ -5432,18 +5406,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5432,18 +5406,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5432 try writer.writeByte(')');5406 try writer.writeByte(')');
5433 const cant_cast = int_info.bits > 64;5407 const cant_cast = int_info.bits > 64;
5434 if (cant_cast) {5408 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", .{});
5436 try writer.writeAll("zig_lo_");5410 try writer.writeAll("zig_lo_");
5437 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);5411 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5438 try writer.writeByte('(');5412 try writer.writeByte('(');
5439 }5413 }
5440 if (bit_offset_val_pl.data > 0) {5414 if (bit_offset > 0) {
5441 try writer.writeAll("zig_shr_");5415 try writer.writeAll("zig_shr_");
5442 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);5416 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5443 try writer.writeByte('(');5417 try writer.writeByte('(');
5444 }5418 }
5445 try f.writeCValue(writer, struct_byval, .Other);5419 try f.writeCValue(writer, struct_byval, .Other);
5446 if (bit_offset_val_pl.data > 0) {5420 if (bit_offset > 0) {
5447 try writer.writeAll(", ");5421 try writer.writeAll(", ");
5448 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);5422 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
5449 try writer.writeByte(')');5423 try writer.writeByte(')');
...@@ -5465,36 +5439,46 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5465,36 +5439,46 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5465 return local;5439 return local;
5466 },5440 },
5467 },5441 },
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);5443 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)
5479 try writer.writeAll("memcpy(&");5444 .{ .field = extra.field_index }
5480 try f.writeCValue(writer, local, .Other);5445 else
5481 try writer.writeAll(", &");5446 .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) },
5482 try f.writeCValue(writer, operand_lval, .Other);5447
5483 try writer.writeAll(", sizeof(");5448 .union_type => |union_type| field_name: {
5484 try f.renderType(writer, inst_ty);5449 const union_obj = mod.unionPtr(union_type.index);
5485 try writer.writeAll("));\n");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) {5460 const local = try f.allocLocal(inst, inst_ty);
5488 try freeLocal(f, inst, operand_lval.new_local, 0);5461 try writer.writeAll("memcpy(&");
5489 }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;5469 if (struct_byval == .constant) {
5492 } else field_name: {5470 try freeLocal(f, inst, operand_lval.new_local, 0);
5493 const name = struct_ty.unionFields().keys()[extra.field_index];5471 }
5494 break :field_name if (struct_ty.unionTagTypeSafety()) |_|5472
5495 .{ .payload_identifier = name }5473 return local;
5496 else5474 } else {
5497 .{ .identifier = name };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 }
5498 },5482 },
5499 else => unreachable,5483 else => unreachable,
5500 };5484 };
...@@ -5511,20 +5495,21 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5511,20 +5495,21 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5511/// *(E!T) -> E5495/// *(E!T) -> E
5512/// Note that the result is never a pointer.5496/// Note that the result is never a pointer.
5513fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {5497fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5498 const mod = f.object.dg.module;
5514 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5499 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);
5517 const operand = try f.resolveInst(ty_op.operand);5502 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);
5519 try reap(f, inst, &.{ty_op.operand});5504 try reap(f, inst, &.{ty_op.operand});
55205505
5521 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;5506 const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer;
5522 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;5507 const error_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
5523 const error_ty = error_union_ty.errorUnionSet();5508 const error_ty = error_union_ty.errorUnionSet(mod);
5524 const payload_ty = error_union_ty.errorUnionPayload();5509 const payload_ty = error_union_ty.errorUnionPayload(mod);
5525 const local = try f.allocLocal(inst, inst_ty);5510 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) {
5528 // The store will be 'x = x'; elide it.5513 // The store will be 'x = x'; elide it.
5529 return local;5514 return local;
5530 }5515 }
...@@ -5533,32 +5518,33 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5533,32 +5518,33 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5533 try f.writeCValue(writer, local, .Other);5518 try f.writeCValue(writer, local, .Other);
5534 try writer.writeAll(" = ");5519 try writer.writeAll(" = ");
55355520
5536 if (!payload_ty.hasRuntimeBits()) {5521 if (!payload_ty.hasRuntimeBits(mod)) {
5537 try f.writeCValue(writer, operand, .Other);5522 try f.writeCValue(writer, operand, .Other);
5538 } else {5523 } else {
5539 if (!error_ty.errorSetIsEmpty())5524 if (!error_ty.errorSetIsEmpty(mod))
5540 if (operand_is_ptr)5525 if (operand_is_ptr)
5541 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })5526 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
5542 else5527 else
5543 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })5528 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
5544 else5529 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);
5546 }5531 }
5547 try writer.writeAll(";\n");5532 try writer.writeAll(";\n");
5548 return local;5533 return local;
5549}5534}
55505535
5551fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {5536fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
5537 const mod = f.object.dg.module;
5552 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5538 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);
5555 const operand = try f.resolveInst(ty_op.operand);5541 const operand = try f.resolveInst(ty_op.operand);
5556 try reap(f, inst, &.{ty_op.operand});5542 try reap(f, inst, &.{ty_op.operand});
5557 const operand_ty = f.air.typeOf(ty_op.operand);5543 const operand_ty = f.typeOf(ty_op.operand);
5558 const error_union_ty = if (is_ptr) operand_ty.childType() else operand_ty;5544 const error_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
55595545
5560 const writer = f.object.writer();5546 const writer = f.object.writer();
5561 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {5547 if (!error_union_ty.errorUnionPayload(mod).hasRuntimeBits(mod)) {
5562 if (!is_ptr) return .none;5548 if (!is_ptr) return .none;
55635549
5564 const local = try f.allocLocal(inst, inst_ty);5550 const local = try f.allocLocal(inst, inst_ty);
...@@ -5584,11 +5570,12 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -5584,11 +5570,12 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
5584}5570}
55855571
5586fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {5572fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
5573 const mod = f.object.dg.module;
5587 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5574 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
55885575
5589 const inst_ty = f.air.typeOfIndex(inst);5576 const inst_ty = f.typeOfIndex(inst);
5590 const repr_is_payload = inst_ty.optionalReprIsPayload();5577 const repr_is_payload = inst_ty.optionalReprIsPayload(mod);
5591 const payload_ty = f.air.typeOf(ty_op.operand);5578 const payload_ty = f.typeOf(ty_op.operand);
5592 const payload = try f.resolveInst(ty_op.operand);5579 const payload = try f.resolveInst(ty_op.operand);
5593 try reap(f, inst, &.{ty_op.operand});5580 try reap(f, inst, &.{ty_op.operand});
55945581
...@@ -5615,12 +5602,13 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5615,12 +5602,13 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
5615}5602}
56165603
5617fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {5604fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5605 const mod = f.object.dg.module;
5618 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5606 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
56195607
5620 const inst_ty = f.air.typeOfIndex(inst);5608 const inst_ty = f.typeOfIndex(inst);
5621 const payload_ty = inst_ty.errorUnionPayload();5609 const payload_ty = inst_ty.errorUnionPayload(mod);
5622 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime();5610 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5623 const err_ty = inst_ty.errorUnionSet();5611 const err_ty = inst_ty.errorUnionSet(mod);
5624 const err = try f.resolveInst(ty_op.operand);5612 const err = try f.resolveInst(ty_op.operand);
5625 try reap(f, inst, &.{ty_op.operand});5613 try reap(f, inst, &.{ty_op.operand});
56265614
...@@ -5653,19 +5641,20 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5653,19 +5641,20 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5653}5641}
56545642
5655fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {5643fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5644 const mod = f.object.dg.module;
5656 const writer = f.object.writer();5645 const writer = f.object.writer();
5657 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5646 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
5658 const operand = try f.resolveInst(ty_op.operand);5647 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();5650 const error_ty = error_union_ty.errorUnionSet(mod);
5662 const payload_ty = error_union_ty.errorUnionPayload();5651 const payload_ty = error_union_ty.errorUnionPayload(mod);
56635652
5664 // First, set the non-error value.5653 // First, set the non-error value.
5665 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {5654 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5666 try f.writeCValueDeref(writer, operand);5655 try f.writeCValueDeref(writer, operand);
5667 try writer.writeAll(" = ");5656 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);
5669 try writer.writeAll(";\n ");5658 try writer.writeAll(";\n ");
56705659
5671 return operand;5660 return operand;
...@@ -5673,13 +5662,13 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5673,13 +5662,13 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5673 try reap(f, inst, &.{ty_op.operand});5662 try reap(f, inst, &.{ty_op.operand});
5674 try f.writeCValueDeref(writer, operand);5663 try f.writeCValueDeref(writer, operand);
5675 try writer.writeAll(".error = ");5664 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);
5677 try writer.writeAll(";\n");5666 try writer.writeAll(";\n");
56785667
5679 // Then return the payload pointer (only if it is used)5668 // Then return the payload pointer (only if it is used)
5680 if (f.liveness.isUnused(inst)) return .none;5669 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));
5683 try f.writeCValue(writer, local, .Other);5672 try f.writeCValue(writer, local, .Other);
5684 try writer.writeAll(" = &(");5673 try writer.writeAll(" = &(");
5685 try f.writeCValueDeref(writer, operand);5674 try f.writeCValueDeref(writer, operand);
...@@ -5703,13 +5692,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5703,13 +5692,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
5703}5692}
57045693
5705fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {5694fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
5695 const mod = f.object.dg.module;
5706 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5696 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
57075697
5708 const inst_ty = f.air.typeOfIndex(inst);5698 const inst_ty = f.typeOfIndex(inst);
5709 const payload_ty = inst_ty.errorUnionPayload();5699 const payload_ty = inst_ty.errorUnionPayload(mod);
5710 const payload = try f.resolveInst(ty_op.operand);5700 const payload = try f.resolveInst(ty_op.operand);
5711 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime();5701 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5712 const err_ty = inst_ty.errorUnionSet();5702 const err_ty = inst_ty.errorUnionSet(mod);
5713 try reap(f, inst, &.{ty_op.operand});5703 try reap(f, inst, &.{ty_op.operand});
57145704
5715 const writer = f.object.writer();5705 const writer = f.object.writer();
...@@ -5728,29 +5718,30 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5728,29 +5718,30 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
5728 else5718 else
5729 try f.writeCValueMember(writer, local, .{ .identifier = "error" });5719 try f.writeCValueMember(writer, local, .{ .identifier = "error" });
5730 try a.assign(f, writer);5720 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);
5732 try a.end(f, writer);5722 try a.end(f, writer);
5733 }5723 }
5734 return local;5724 return local;
5735}5725}
57365726
5737fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {5727fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {
5728 const mod = f.object.dg.module;
5738 const un_op = f.air.instructions.items(.data)[inst].un_op;5729 const un_op = f.air.instructions.items(.data)[inst].un_op;
57395730
5740 const writer = f.object.writer();5731 const writer = f.object.writer();
5741 const operand = try f.resolveInst(un_op);5732 const operand = try f.resolveInst(un_op);
5742 try reap(f, inst, &.{un_op});5733 try reap(f, inst, &.{un_op});
5743 const operand_ty = f.air.typeOf(un_op);5734 const operand_ty = f.typeOf(un_op);
5744 const local = try f.allocLocal(inst, Type.bool);5735 const local = try f.allocLocal(inst, Type.bool);
5745 const err_union_ty = if (is_ptr) operand_ty.childType() else operand_ty;5736 const err_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
5746 const payload_ty = err_union_ty.errorUnionPayload();5737 const payload_ty = err_union_ty.errorUnionPayload(mod);
5747 const error_ty = err_union_ty.errorUnionSet();5738 const error_ty = err_union_ty.errorUnionSet(mod);
57485739
5749 try f.writeCValue(writer, local, .Other);5740 try f.writeCValue(writer, local, .Other);
5750 try writer.writeAll(" = ");5741 try writer.writeAll(" = ");
57515742
5752 if (!error_ty.errorSetIsEmpty())5743 if (!error_ty.errorSetIsEmpty(mod))
5753 if (payload_ty.hasRuntimeBits())5744 if (payload_ty.hasRuntimeBits(mod))
5754 if (is_ptr)5745 if (is_ptr)
5755 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })5746 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
5756 else5747 else
...@@ -5758,42 +5749,40 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const...@@ -5758,42 +5749,40 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
5758 else5749 else
5759 try f.writeCValue(writer, operand, .Other)5750 try f.writeCValue(writer, operand, .Other)
5760 else5751 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);
5762 try writer.writeByte(' ');5753 try writer.writeByte(' ');
5763 try writer.writeAll(operator);5754 try writer.writeAll(operator);
5764 try writer.writeByte(' ');5755 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);
5766 try writer.writeAll(";\n");5757 try writer.writeAll(";\n");
5767 return local;5758 return local;
5768}5759}
57695760
5770fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {5761fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
5762 const mod = f.object.dg.module;
5771 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5763 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
57725764
5773 const operand = try f.resolveInst(ty_op.operand);5765 const operand = try f.resolveInst(ty_op.operand);
5774 try reap(f, inst, &.{ty_op.operand});5766 try reap(f, inst, &.{ty_op.operand});
5775 const inst_ty = f.air.typeOfIndex(inst);5767 const inst_ty = f.typeOfIndex(inst);
5776 const writer = f.object.writer();5768 const writer = f.object.writer();
5777 const local = try f.allocLocal(inst, inst_ty);5769 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
5780 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });5772 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
5781 try writer.writeAll(" = ");5773 try writer.writeAll(" = ");
5782 // Unfortunately, C does not support any equivalent to5774 // Unfortunately, C does not support any equivalent to
5783 // &(*(void *)p)[0], although LLVM does via GetElementPtr5775 // &(*(void *)p)[0], although LLVM does via GetElementPtr
5784 if (operand == .undef) {5776 if (operand == .undef) {
5785 var buf: Type.SlicePtrFieldTypeBuffer = undefined;5777 try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(mod) }, .Initializer);
5786 try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer);5778 } else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5787 } else if (array_ty.hasRuntimeBitsIgnoreComptime()) {
5788 try writer.writeAll("&(");5779 try writer.writeAll("&(");
5789 try f.writeCValueDeref(writer, operand);5780 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))});
5791 } else try f.writeCValue(writer, operand, .Initializer);5782 } else try f.writeCValue(writer, operand, .Initializer);
5792 try writer.writeAll("; ");5783 try writer.writeAll("; ");
57935784
5794 const array_len = array_ty.arrayLen();5785 const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod));
5795 var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len };
5796 const len_val = Value.initPayload(&len_pl.base);
5797 try f.writeCValueMember(writer, local, .{ .identifier = "len" });5786 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
5798 try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});5787 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 {...@@ -5801,19 +5790,20 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
5801}5790}
58025791
5803fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {5792fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
5793 const mod = f.object.dg.module;
5804 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5794 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);
5807 const operand = try f.resolveInst(ty_op.operand);5797 const operand = try f.resolveInst(ty_op.operand);
5808 try reap(f, inst, &.{ty_op.operand});5798 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);
5810 const target = f.object.dg.module.getTarget();5800 const target = f.object.dg.module.getTarget();
5811 const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat())5801 const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat())
5812 if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend"5802 if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend"
5813 else if (inst_ty.isInt() and operand_ty.isRuntimeFloat())5803 else if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat())
5814 if (inst_ty.isSignedInt()) "fix" else "fixuns"5804 if (inst_ty.isSignedInt(mod)) "fix" else "fixuns"
5815 else if (inst_ty.isRuntimeFloat() and operand_ty.isInt())5805 else if (inst_ty.isRuntimeFloat() and operand_ty.isInt(mod))
5816 if (operand_ty.isSignedInt()) "float" else "floatun"5806 if (operand_ty.isSignedInt(mod)) "float" else "floatun"
5817 else5807 else
5818 unreachable;5808 unreachable;
58195809
...@@ -5822,19 +5812,19 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5822,19 +5812,19 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
5822 try f.writeCValue(writer, local, .Other);5812 try f.writeCValue(writer, local, .Other);
58235813
5824 try writer.writeAll(" = ");5814 try writer.writeAll(" = ");
5825 if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) {5815 if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat()) {
5826 try writer.writeAll("zig_wrap_");5816 try writer.writeAll("zig_wrap_");
5827 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);5817 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5828 try writer.writeByte('(');5818 try writer.writeByte('(');
5829 }5819 }
5830 try writer.writeAll("zig_");5820 try writer.writeAll("zig_");
5831 try writer.writeAll(operation);5821 try writer.writeAll(operation);
5832 try writer.writeAll(compilerRtAbbrev(operand_ty, target));5822 try writer.writeAll(compilerRtAbbrev(operand_ty, mod));
5833 try writer.writeAll(compilerRtAbbrev(inst_ty, target));5823 try writer.writeAll(compilerRtAbbrev(inst_ty, mod));
5834 try writer.writeByte('(');5824 try writer.writeByte('(');
5835 try f.writeCValue(writer, operand, .FunctionArgument);5825 try f.writeCValue(writer, operand, .FunctionArgument);
5836 try writer.writeByte(')');5826 try writer.writeByte(')');
5837 if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) {5827 if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat()) {
5838 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);5828 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
5839 try writer.writeByte(')');5829 try writer.writeByte(')');
5840 }5830 }
...@@ -5843,12 +5833,13 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5843,12 +5833,13 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
5843}5833}
58445834
5845fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {5835fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
5836 const mod = f.object.dg.module;
5846 const un_op = f.air.instructions.items(.data)[inst].un_op;5837 const un_op = f.air.instructions.items(.data)[inst].un_op;
58475838
5848 const operand = try f.resolveInst(un_op);5839 const operand = try f.resolveInst(un_op);
5849 const operand_ty = f.air.typeOf(un_op);5840 const operand_ty = f.typeOf(un_op);
5850 try reap(f, inst, &.{un_op});5841 try reap(f, inst, &.{un_op});
5851 const inst_ty = f.air.typeOfIndex(inst);5842 const inst_ty = f.typeOfIndex(inst);
5852 const writer = f.object.writer();5843 const writer = f.object.writer();
5853 const local = try f.allocLocal(inst, inst_ty);5844 const local = try f.allocLocal(inst, inst_ty);
5854 try f.writeCValue(writer, local, .Other);5845 try f.writeCValue(writer, local, .Other);
...@@ -5856,7 +5847,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5856,7 +5847,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
5856 try writer.writeAll(" = (");5847 try writer.writeAll(" = (");
5857 try f.renderType(writer, inst_ty);5848 try f.renderType(writer, inst_ty);
5858 try writer.writeByte(')');5849 try writer.writeByte(')');
5859 if (operand_ty.isSlice()) {5850 if (operand_ty.isSlice(mod)) {
5860 try f.writeCValueMember(writer, operand, .{ .identifier = "len" });5851 try f.writeCValueMember(writer, operand, .{ .identifier = "len" });
5861 } else {5852 } else {
5862 try f.writeCValue(writer, operand, .Other);5853 try f.writeCValue(writer, operand, .Other);
...@@ -5871,14 +5862,15 @@ fn airUnBuiltinCall(...@@ -5871,14 +5862,15 @@ fn airUnBuiltinCall(
5871 operation: []const u8,5862 operation: []const u8,
5872 info: BuiltinInfo,5863 info: BuiltinInfo,
5873) !CValue {5864) !CValue {
5865 const mod = f.object.dg.module;
5874 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5866 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
58755867
5876 const operand = try f.resolveInst(ty_op.operand);5868 const operand = try f.resolveInst(ty_op.operand);
5877 try reap(f, inst, &.{ty_op.operand});5869 try reap(f, inst, &.{ty_op.operand});
5878 const inst_ty = f.air.typeOfIndex(inst);5870 const inst_ty = f.typeOfIndex(inst);
5879 const inst_scalar_ty = inst_ty.scalarType();5871 const inst_scalar_ty = inst_ty.scalarType(mod);
5880 const operand_ty = f.air.typeOf(ty_op.operand);5872 const operand_ty = f.typeOf(ty_op.operand);
5881 const scalar_ty = operand_ty.scalarType();5873 const scalar_ty = operand_ty.scalarType(mod);
58825874
5883 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);5875 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
5884 const ref_ret = inst_scalar_cty.tag() == .array;5876 const ref_ret = inst_scalar_cty.tag() == .array;
...@@ -5914,9 +5906,10 @@ fn airBinBuiltinCall(...@@ -5914,9 +5906,10 @@ fn airBinBuiltinCall(
5914 operation: []const u8,5906 operation: []const u8,
5915 info: BuiltinInfo,5907 info: BuiltinInfo,
5916) !CValue {5908) !CValue {
5909 const mod = f.object.dg.module;
5917 const bin_op = f.air.instructions.items(.data)[inst].bin_op;5910 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);
5920 const operand_cty = try f.typeToCType(operand_ty, .complete);5913 const operand_cty = try f.typeToCType(operand_ty, .complete);
5921 const is_big = operand_cty.tag() == .array;5914 const is_big = operand_cty.tag() == .array;
59225915
...@@ -5924,9 +5917,9 @@ fn airBinBuiltinCall(...@@ -5924,9 +5917,9 @@ fn airBinBuiltinCall(
5924 const rhs = try f.resolveInst(bin_op.rhs);5917 const rhs = try f.resolveInst(bin_op.rhs);
5925 if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });5918 if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
59265919
5927 const inst_ty = f.air.typeOfIndex(inst);5920 const inst_ty = f.typeOfIndex(inst);
5928 const inst_scalar_ty = inst_ty.scalarType();5921 const inst_scalar_ty = inst_ty.scalarType(mod);
5929 const scalar_ty = operand_ty.scalarType();5922 const scalar_ty = operand_ty.scalarType(mod);
59305923
5931 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);5924 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
5932 const ref_ret = inst_scalar_cty.tag() == .array;5925 const ref_ret = inst_scalar_cty.tag() == .array;
...@@ -5968,14 +5961,15 @@ fn airCmpBuiltinCall(...@@ -5968,14 +5961,15 @@ fn airCmpBuiltinCall(
5968 operation: enum { cmp, operator },5961 operation: enum { cmp, operator },
5969 info: BuiltinInfo,5962 info: BuiltinInfo,
5970) !CValue {5963) !CValue {
5964 const mod = f.object.dg.module;
5971 const lhs = try f.resolveInst(data.lhs);5965 const lhs = try f.resolveInst(data.lhs);
5972 const rhs = try f.resolveInst(data.rhs);5966 const rhs = try f.resolveInst(data.rhs);
5973 try reap(f, inst, &.{ data.lhs, data.rhs });5967 try reap(f, inst, &.{ data.lhs, data.rhs });
59745968
5975 const inst_ty = f.air.typeOfIndex(inst);5969 const inst_ty = f.typeOfIndex(inst);
5976 const inst_scalar_ty = inst_ty.scalarType();5970 const inst_scalar_ty = inst_ty.scalarType(mod);
5977 const operand_ty = f.air.typeOf(data.lhs);5971 const operand_ty = f.typeOf(data.lhs);
5978 const scalar_ty = operand_ty.scalarType();5972 const scalar_ty = operand_ty.scalarType(mod);
59795973
5980 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);5974 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
5981 const ref_ret = inst_scalar_cty.tag() == .array;5975 const ref_ret = inst_scalar_cty.tag() == .array;
...@@ -6008,7 +6002,7 @@ fn airCmpBuiltinCall(...@@ -6008,7 +6002,7 @@ fn airCmpBuiltinCall(
6008 try writer.writeByte(')');6002 try writer.writeByte(')');
6009 if (!ref_ret) try writer.print(" {s} {}", .{6003 if (!ref_ret) try writer.print(" {s} {}", .{
6010 compareOperatorC(operator),6004 compareOperatorC(operator),
6011 try f.fmtIntLiteral(Type.initTag(.i32), Value.zero),6005 try f.fmtIntLiteral(Type.i32, try mod.intValue(Type.i32, 0)),
6012 });6006 });
6013 try writer.writeAll(";\n");6007 try writer.writeAll(";\n");
6014 try v.end(f, inst, writer);6008 try v.end(f, inst, writer);
...@@ -6017,28 +6011,27 @@ fn airCmpBuiltinCall(...@@ -6017,28 +6011,27 @@ fn airCmpBuiltinCall(
6017}6011}
60186012
6019fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {6013fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {
6014 const mod = f.object.dg.module;
6020 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;6015 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
6021 const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data;6016 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);
6023 const ptr = try f.resolveInst(extra.ptr);6018 const ptr = try f.resolveInst(extra.ptr);
6024 const expected_value = try f.resolveInst(extra.expected_value);6019 const expected_value = try f.resolveInst(extra.expected_value);
6025 const new_value = try f.resolveInst(extra.new_value);6020 const new_value = try f.resolveInst(extra.new_value);
6026 const ptr_ty = f.air.typeOf(extra.ptr);6021 const ptr_ty = f.typeOf(extra.ptr);
6027 const ty = ptr_ty.childType();6022 const ty = ptr_ty.childType(mod);
60286023
6029 const writer = f.object.writer();6024 const writer = f.object.writer();
6030 const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value);6025 const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value);
6031 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });6026 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
60326027
6033 const target = f.object.dg.module.getTarget();6028 const repr_ty = if (ty.isRuntimeFloat())
6034 var repr_pl = Type.Payload.Bits{6029 mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable
6035 .base = .{ .tag = .int_unsigned },6030 else
6036 .data = @intCast(u16, ty.abiSize(target) * 8),6031 ty;
6037 };
6038 const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty;
60396032
6040 const local = try f.allocLocal(inst, inst_ty);6033 const local = try f.allocLocal(inst, inst_ty);
6041 if (inst_ty.isPtrLikeOptional()) {6034 if (inst_ty.isPtrLikeOptional(mod)) {
6042 {6035 {
6043 const a = try Assignment.start(f, writer, ty);6036 const a = try Assignment.start(f, writer, ty);
6044 try f.writeCValue(writer, local, .Other);6037 try f.writeCValue(writer, local, .Other);
...@@ -6051,7 +6044,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6051,7 +6044,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6051 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});6044 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
6052 try f.renderType(writer, ty);6045 try f.renderType(writer, ty);
6053 try writer.writeByte(')');6046 try writer.writeByte(')');
6054 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");6047 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6055 try writer.writeAll(" *)");6048 try writer.writeAll(" *)");
6056 try f.writeCValue(writer, ptr, .Other);6049 try f.writeCValue(writer, ptr, .Other);
6057 try writer.writeAll(", ");6050 try writer.writeAll(", ");
...@@ -6093,7 +6086,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6093,7 +6086,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6093 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});6086 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
6094 try f.renderType(writer, ty);6087 try f.renderType(writer, ty);
6095 try writer.writeByte(')');6088 try writer.writeByte(')');
6096 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");6089 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6097 try writer.writeAll(" *)");6090 try writer.writeAll(" *)");
6098 try f.writeCValue(writer, ptr, .Other);6091 try f.writeCValue(writer, ptr, .Other);
6099 try writer.writeAll(", ");6092 try writer.writeAll(", ");
...@@ -6123,11 +6116,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6123,11 +6116,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6123}6116}
61246117
6125fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {6118fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6119 const mod = f.object.dg.module;
6126 const pl_op = f.air.instructions.items(.data)[inst].pl_op;6120 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
6127 const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data;6121 const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data;
6128 const inst_ty = f.air.typeOfIndex(inst);6122 const inst_ty = f.typeOfIndex(inst);
6129 const ptr_ty = f.air.typeOf(pl_op.operand);6123 const ptr_ty = f.typeOf(pl_op.operand);
6130 const ty = ptr_ty.childType();6124 const ty = ptr_ty.childType(mod);
6131 const ptr = try f.resolveInst(pl_op.operand);6125 const ptr = try f.resolveInst(pl_op.operand);
6132 const operand = try f.resolveInst(extra.operand);6126 const operand = try f.resolveInst(extra.operand);
61336127
...@@ -6135,14 +6129,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6135,14 +6129,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6135 const operand_mat = try Materialize.start(f, inst, writer, ty, operand);6129 const operand_mat = try Materialize.start(f, inst, writer, ty, operand);
6136 try reap(f, inst, &.{ pl_op.operand, extra.operand });6130 try reap(f, inst, &.{ pl_op.operand, extra.operand });
61376131
6138 const target = f.object.dg.module.getTarget();6132 const repr_bits = @intCast(u16, ty.abiSize(mod) * 8);
6139 var repr_pl = Type.Payload.Bits{
6140 .base = .{ .tag = .int_unsigned },
6141 .data = @intCast(u16, ty.abiSize(target) * 8),
6142 };
6143 const is_float = ty.isRuntimeFloat();6133 const is_float = ty.isRuntimeFloat();
6144 const is_128 = repr_pl.data == 128;6134 const is_128 = repr_bits == 128;
6145 const repr_ty = if (is_float) Type.initPayload(&repr_pl.base) else ty;6135 const repr_ty = if (is_float) mod.intType(.unsigned, repr_bits) catch unreachable else ty;
61466136
6147 const local = try f.allocLocal(inst, inst_ty);6137 const local = try f.allocLocal(inst, inst_ty);
6148 try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});6138 try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});
...@@ -6158,7 +6148,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6158,7 +6148,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6158 if (use_atomic) try writer.writeAll("zig_atomic(");6148 if (use_atomic) try writer.writeAll("zig_atomic(");
6159 try f.renderType(writer, ty);6149 try f.renderType(writer, ty);
6160 if (use_atomic) try writer.writeByte(')');6150 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");
6162 try writer.writeAll(" *)");6152 try writer.writeAll(" *)");
6163 try f.writeCValue(writer, ptr, .Other);6153 try f.writeCValue(writer, ptr, .Other);
6164 try writer.writeAll(", ");6154 try writer.writeAll(", ");
...@@ -6181,20 +6171,19 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6181,20 +6171,19 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6181}6171}
61826172
6183fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {6173fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6174 const mod = f.object.dg.module;
6184 const atomic_load = f.air.instructions.items(.data)[inst].atomic_load;6175 const atomic_load = f.air.instructions.items(.data)[inst].atomic_load;
6185 const ptr = try f.resolveInst(atomic_load.ptr);6176 const ptr = try f.resolveInst(atomic_load.ptr);
6186 try reap(f, inst, &.{atomic_load.ptr});6177 try reap(f, inst, &.{atomic_load.ptr});
6187 const ptr_ty = f.air.typeOf(atomic_load.ptr);6178 const ptr_ty = f.typeOf(atomic_load.ptr);
6188 const ty = ptr_ty.childType();6179 const ty = ptr_ty.childType(mod);
61896180
6190 const target = f.object.dg.module.getTarget();6181 const repr_ty = if (ty.isRuntimeFloat())
6191 var repr_pl = Type.Payload.Bits{6182 mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable
6192 .base = .{ .tag = .int_unsigned },6183 else
6193 .data = @intCast(u16, ty.abiSize(target) * 8),6184 ty;
6194 };
6195 const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty;
61966185
6197 const inst_ty = f.air.typeOfIndex(inst);6186 const inst_ty = f.typeOfIndex(inst);
6198 const writer = f.object.writer();6187 const writer = f.object.writer();
6199 const local = try f.allocLocal(inst, inst_ty);6188 const local = try f.allocLocal(inst, inst_ty);
62006189
...@@ -6203,7 +6192,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6203,7 +6192,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6203 try writer.writeAll(", (zig_atomic(");6192 try writer.writeAll(", (zig_atomic(");
6204 try f.renderType(writer, ty);6193 try f.renderType(writer, ty);
6205 try writer.writeByte(')');6194 try writer.writeByte(')');
6206 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");6195 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6207 try writer.writeAll(" *)");6196 try writer.writeAll(" *)");
6208 try f.writeCValue(writer, ptr, .Other);6197 try f.writeCValue(writer, ptr, .Other);
6209 try writer.writeAll(", ");6198 try writer.writeAll(", ");
...@@ -6218,9 +6207,10 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6218,9 +6207,10 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6218}6207}
62196208
6220fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue {6209fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue {
6210 const mod = f.object.dg.module;
6221 const bin_op = f.air.instructions.items(.data)[inst].bin_op;6211 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
6222 const ptr_ty = f.air.typeOf(bin_op.lhs);6212 const ptr_ty = f.typeOf(bin_op.lhs);
6223 const ty = ptr_ty.childType();6213 const ty = ptr_ty.childType(mod);
6224 const ptr = try f.resolveInst(bin_op.lhs);6214 const ptr = try f.resolveInst(bin_op.lhs);
6225 const element = try f.resolveInst(bin_op.rhs);6215 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...@@ -6228,17 +6218,15 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
6228 const element_mat = try Materialize.start(f, inst, writer, ty, element);6218 const element_mat = try Materialize.start(f, inst, writer, ty, element);
6229 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });6219 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
62306220
6231 const target = f.object.dg.module.getTarget();6221 const repr_ty = if (ty.isRuntimeFloat())
6232 var repr_pl = Type.Payload.Bits{6222 mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable
6233 .base = .{ .tag = .int_unsigned },6223 else
6234 .data = @intCast(u16, ty.abiSize(target) * 8),6224 ty;
6235 };
6236 const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty;
62376225
6238 try writer.writeAll("zig_atomic_store((zig_atomic(");6226 try writer.writeAll("zig_atomic_store((zig_atomic(");
6239 try f.renderType(writer, ty);6227 try f.renderType(writer, ty);
6240 try writer.writeByte(')');6228 try writer.writeByte(')');
6241 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");6229 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6242 try writer.writeAll(" *)");6230 try writer.writeAll(" *)");
6243 try f.writeCValue(writer, ptr, .Other);6231 try f.writeCValue(writer, ptr, .Other);
6244 try writer.writeAll(", ");6232 try writer.writeAll(", ");
...@@ -6254,7 +6242,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa...@@ -6254,7 +6242,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
6254}6242}
62556243
6256fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {6244fn 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)) {
6258 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });6247 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });
6259 } else {6248 } else {
6260 try f.writeCValue(writer, ptr, .FunctionArgument);6249 try f.writeCValue(writer, ptr, .FunctionArgument);
...@@ -6262,14 +6251,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo...@@ -6262,14 +6251,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo
6262}6251}
62636252
6264fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {6253fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6254 const mod = f.object.dg.module;
6265 const bin_op = f.air.instructions.items(.data)[inst].bin_op;6255 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);
6267 const dest_slice = try f.resolveInst(bin_op.lhs);6257 const dest_slice = try f.resolveInst(bin_op.lhs);
6268 const value = try f.resolveInst(bin_op.rhs);6258 const value = try f.resolveInst(bin_op.rhs);
6269 const elem_ty = f.air.typeOf(bin_op.rhs);6259 const elem_ty = f.typeOf(bin_op.rhs);
6270 const target = f.object.dg.module.getTarget();6260 const elem_abi_size = elem_ty.abiSize(mod);
6271 const elem_abi_size = elem_ty.abiSize(target);6261 const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
6272 const val_is_undef = if (f.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
6273 const writer = f.object.writer();6262 const writer = f.object.writer();
62746263
6275 if (val_is_undef) {6264 if (val_is_undef) {
...@@ -6279,7 +6268,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6279,7 +6268,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6279 }6268 }
62806269
6281 try writer.writeAll("memset(");6270 try writer.writeAll("memset(");
6282 switch (dest_ty.ptrSize()) {6271 switch (dest_ty.ptrSize(mod)) {
6283 .Slice => {6272 .Slice => {
6284 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });6273 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
6285 try writer.writeAll(", 0xaa, ");6274 try writer.writeAll(", 0xaa, ");
...@@ -6291,8 +6280,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6291,8 +6280,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6291 }6280 }
6292 },6281 },
6293 .One => {6282 .One => {
6294 const array_ty = dest_ty.childType();6283 const array_ty = dest_ty.childType(mod);
6295 const len = array_ty.arrayLen() * elem_abi_size;6284 const len = array_ty.arrayLen(mod) * elem_abi_size;
62966285
6297 try f.writeCValue(writer, dest_slice, .FunctionArgument);6286 try f.writeCValue(writer, dest_slice, .FunctionArgument);
6298 try writer.print(", 0xaa, {d});\n", .{len});6287 try writer.print(", 0xaa, {d});\n", .{len});
...@@ -6303,32 +6292,33 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6303,32 +6292,33 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6303 return .none;6292 return .none;
6304 }6293 }
63056294
6306 if (elem_abi_size > 1 or dest_ty.isVolatilePtr()) {6295 if (elem_abi_size > 1 or dest_ty.isVolatilePtr(mod)) {
6307 // For the assignment in this loop, the array pointer needs to get6296 // For the assignment in this loop, the array pointer needs to get
6308 // casted to a regular pointer, otherwise an error like this occurs:6297 // casted to a regular pointer, otherwise an error like this occurs:
6309 // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable6298 // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable
6310 var elem_ptr_ty_pl: Type.Payload.ElemType = .{6299 const elem_ptr_ty = try mod.ptrType(.{
6311 .base = .{ .tag = .c_mut_pointer },6300 .child = elem_ty.ip_index,
6312 .data = elem_ty,6301 .flags = .{
6313 };6302 .size = .C,
6314 const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);6303 },
6304 });
63156305
6316 const index = try f.allocLocal(inst, Type.usize);6306 const index = try f.allocLocal(inst, Type.usize);
63176307
6318 try writer.writeAll("for (");6308 try writer.writeAll("for (");
6319 try f.writeCValue(writer, index, .Other);6309 try f.writeCValue(writer, index, .Other);
6320 try writer.writeAll(" = ");6310 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);
6322 try writer.writeAll("; ");6312 try writer.writeAll("; ");
6323 try f.writeCValue(writer, index, .Other);6313 try f.writeCValue(writer, index, .Other);
6324 try writer.writeAll(" != ");6314 try writer.writeAll(" != ");
6325 switch (dest_ty.ptrSize()) {6315 switch (dest_ty.ptrSize(mod)) {
6326 .Slice => {6316 .Slice => {
6327 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });6317 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
6328 },6318 },
6329 .One => {6319 .One => {
6330 const array_ty = dest_ty.childType();6320 const array_ty = dest_ty.childType(mod);
6331 try writer.print("{d}", .{array_ty.arrayLen()});6321 try writer.print("{d}", .{array_ty.arrayLen(mod)});
6332 },6322 },
6333 .Many, .C => unreachable,6323 .Many, .C => unreachable,
6334 }6324 }
...@@ -6357,7 +6347,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6357,7 +6347,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6357 const bitcasted = try bitcast(f, Type.u8, value, elem_ty);6347 const bitcasted = try bitcast(f, Type.u8, value, elem_ty);
63586348
6359 try writer.writeAll("memset(");6349 try writer.writeAll("memset(");
6360 switch (dest_ty.ptrSize()) {6350 switch (dest_ty.ptrSize(mod)) {
6361 .Slice => {6351 .Slice => {
6362 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });6352 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
6363 try writer.writeAll(", ");6353 try writer.writeAll(", ");
...@@ -6367,8 +6357,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6367,8 +6357,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6367 try writer.writeAll(");\n");6357 try writer.writeAll(");\n");
6368 },6358 },
6369 .One => {6359 .One => {
6370 const array_ty = dest_ty.childType();6360 const array_ty = dest_ty.childType(mod);
6371 const len = array_ty.arrayLen() * elem_abi_size;6361 const len = array_ty.arrayLen(mod) * elem_abi_size;
63726362
6373 try f.writeCValue(writer, dest_slice, .FunctionArgument);6363 try f.writeCValue(writer, dest_slice, .FunctionArgument);
6374 try writer.writeAll(", ");6364 try writer.writeAll(", ");
...@@ -6383,12 +6373,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6383,12 +6373,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6383}6373}
63846374
6385fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {6375fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
6376 const mod = f.object.dg.module;
6386 const bin_op = f.air.instructions.items(.data)[inst].bin_op;6377 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
6387 const dest_ptr = try f.resolveInst(bin_op.lhs);6378 const dest_ptr = try f.resolveInst(bin_op.lhs);
6388 const src_ptr = try f.resolveInst(bin_op.rhs);6379 const src_ptr = try f.resolveInst(bin_op.rhs);
6389 const dest_ty = f.air.typeOf(bin_op.lhs);6380 const dest_ty = f.typeOf(bin_op.lhs);
6390 const src_ty = f.air.typeOf(bin_op.rhs);6381 const src_ty = f.typeOf(bin_op.rhs);
6391 const target = f.object.dg.module.getTarget();
6392 const writer = f.object.writer();6382 const writer = f.object.writer();
63936383
6394 try writer.writeAll("memcpy(");6384 try writer.writeAll("memcpy(");
...@@ -6396,10 +6386,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6396,10 +6386,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
6396 try writer.writeAll(", ");6386 try writer.writeAll(", ");
6397 try writeSliceOrPtr(f, writer, src_ptr, src_ty);6387 try writeSliceOrPtr(f, writer, src_ptr, src_ty);
6398 try writer.writeAll(", ");6388 try writer.writeAll(", ");
6399 switch (dest_ty.ptrSize()) {6389 switch (dest_ty.ptrSize(mod)) {
6400 .Slice => {6390 .Slice => {
6401 const elem_ty = dest_ty.childType();6391 const elem_ty = dest_ty.childType(mod);
6402 const elem_abi_size = elem_ty.abiSize(target);6392 const elem_abi_size = elem_ty.abiSize(mod);
6403 try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" });6393 try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" });
6404 if (elem_abi_size > 1) {6394 if (elem_abi_size > 1) {
6405 try writer.print(" * {d});\n", .{elem_abi_size});6395 try writer.print(" * {d});\n", .{elem_abi_size});
...@@ -6408,10 +6398,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6408,10 +6398,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
6408 }6398 }
6409 },6399 },
6410 .One => {6400 .One => {
6411 const array_ty = dest_ty.childType();6401 const array_ty = dest_ty.childType(mod);
6412 const elem_ty = array_ty.childType();6402 const elem_ty = array_ty.childType(mod);
6413 const elem_abi_size = elem_ty.abiSize(target);6403 const elem_abi_size = elem_ty.abiSize(mod);
6414 const len = array_ty.arrayLen() * elem_abi_size;6404 const len = array_ty.arrayLen(mod) * elem_abi_size;
6415 try writer.print("{d});\n", .{len});6405 try writer.print("{d});\n", .{len});
6416 },6406 },
6417 .Many, .C => unreachable,6407 .Many, .C => unreachable,
...@@ -6422,16 +6412,16 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6422,16 +6412,16 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
6422}6412}
64236413
6424fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {6414fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6415 const mod = f.object.dg.module;
6425 const bin_op = f.air.instructions.items(.data)[inst].bin_op;6416 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
6426 const union_ptr = try f.resolveInst(bin_op.lhs);6417 const union_ptr = try f.resolveInst(bin_op.lhs);
6427 const new_tag = try f.resolveInst(bin_op.rhs);6418 const new_tag = try f.resolveInst(bin_op.rhs);
6428 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });6419 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
64296420
6430 const target = f.object.dg.module.getTarget();6421 const union_ty = f.typeOf(bin_op.lhs).childType(mod);
6431 const union_ty = f.air.typeOf(bin_op.lhs).childType();6422 const layout = union_ty.unionGetLayout(mod);
6432 const layout = union_ty.unionGetLayout(target);
6433 if (layout.tag_size == 0) return .none;6423 if (layout.tag_size == 0) return .none;
6434 const tag_ty = union_ty.unionTagTypeSafety().?;6424 const tag_ty = union_ty.unionTagTypeSafety(mod).?;
64356425
6436 const writer = f.object.writer();6426 const writer = f.object.writer();
6437 const a = try Assignment.start(f, writer, tag_ty);6427 const a = try Assignment.start(f, writer, tag_ty);
...@@ -6443,17 +6433,17 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6443,17 +6433,17 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6443}6433}
64446434
6445fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {6435fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6436 const mod = f.object.dg.module;
6446 const ty_op = f.air.instructions.items(.data)[inst].ty_op;6437 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
64476438
6448 const operand = try f.resolveInst(ty_op.operand);6439 const operand = try f.resolveInst(ty_op.operand);
6449 try reap(f, inst, &.{ty_op.operand});6440 try reap(f, inst, &.{ty_op.operand});
64506441
6451 const union_ty = f.air.typeOf(ty_op.operand);6442 const union_ty = f.typeOf(ty_op.operand);
6452 const target = f.object.dg.module.getTarget();6443 const layout = union_ty.unionGetLayout(mod);
6453 const layout = union_ty.unionGetLayout(target);
6454 if (layout.tag_size == 0) return .none;6444 if (layout.tag_size == 0) return .none;
64556445
6456 const inst_ty = f.air.typeOfIndex(inst);6446 const inst_ty = f.typeOfIndex(inst);
6457 const writer = f.object.writer();6447 const writer = f.object.writer();
6458 const local = try f.allocLocal(inst, inst_ty);6448 const local = try f.allocLocal(inst, inst_ty);
6459 const a = try Assignment.start(f, writer, inst_ty);6449 const a = try Assignment.start(f, writer, inst_ty);
...@@ -6465,10 +6455,11 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6465,10 +6455,11 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6465}6455}
64666456
6467fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {6457fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
6458 const mod = f.object.dg.module;
6468 const un_op = f.air.instructions.items(.data)[inst].un_op;6459 const un_op = f.air.instructions.items(.data)[inst].un_op;
64696460
6470 const inst_ty = f.air.typeOfIndex(inst);6461 const inst_ty = f.typeOfIndex(inst);
6471 const enum_ty = f.air.typeOf(un_op);6462 const enum_ty = f.typeOf(un_op);
6472 const operand = try f.resolveInst(un_op);6463 const operand = try f.resolveInst(un_op);
6473 try reap(f, inst, &.{un_op});6464 try reap(f, inst, &.{un_op});
64746465
...@@ -6476,7 +6467,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6476,7 +6467,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
6476 const local = try f.allocLocal(inst, inst_ty);6467 const local = try f.allocLocal(inst, inst_ty);
6477 try f.writeCValue(writer, local, .Other);6468 try f.writeCValue(writer, local, .Other);
6478 try writer.print(" = {s}(", .{6469 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 }),
6480 });6471 });
6481 try f.writeCValue(writer, operand, .Other);6472 try f.writeCValue(writer, operand, .Other);
6482 try writer.writeAll(");\n");6473 try writer.writeAll(");\n");
...@@ -6488,7 +6479,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6488,7 +6479,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
6488 const un_op = f.air.instructions.items(.data)[inst].un_op;6479 const un_op = f.air.instructions.items(.data)[inst].un_op;
64896480
6490 const writer = f.object.writer();6481 const writer = f.object.writer();
6491 const inst_ty = f.air.typeOfIndex(inst);6482 const inst_ty = f.typeOfIndex(inst);
6492 const operand = try f.resolveInst(un_op);6483 const operand = try f.resolveInst(un_op);
6493 try reap(f, inst, &.{un_op});6484 try reap(f, inst, &.{un_op});
6494 const local = try f.allocLocal(inst, inst_ty);6485 const local = try f.allocLocal(inst, inst_ty);
...@@ -6501,13 +6492,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6501,13 +6492,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
6501}6492}
65026493
6503fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {6494fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
6495 const mod = f.object.dg.module;
6504 const ty_op = f.air.instructions.items(.data)[inst].ty_op;6496 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
65056497
6506 const operand = try f.resolveInst(ty_op.operand);6498 const operand = try f.resolveInst(ty_op.operand);
6507 try reap(f, inst, &.{ty_op.operand});6499 try reap(f, inst, &.{ty_op.operand});
65086500
6509 const inst_ty = f.air.typeOfIndex(inst);6501 const inst_ty = f.typeOfIndex(inst);
6510 const inst_scalar_ty = inst_ty.scalarType();6502 const inst_scalar_ty = inst_ty.scalarType(mod);
65116503
6512 const writer = f.object.writer();6504 const writer = f.object.writer();
6513 const local = try f.allocLocal(inst, inst_ty);6505 const local = try f.allocLocal(inst, inst_ty);
...@@ -6532,7 +6524,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6532,7 +6524,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
6532 const rhs = try f.resolveInst(extra.rhs);6524 const rhs = try f.resolveInst(extra.rhs);
6533 try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs });6525 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
6537 const writer = f.object.writer();6529 const writer = f.object.writer();
6538 const local = try f.allocLocal(inst, inst_ty);6530 const local = try f.allocLocal(inst, inst_ty);
...@@ -6555,41 +6547,31 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6555,41 +6547,31 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
6555}6547}
65566548
6557fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {6549fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
6550 const mod = f.object.dg.module;
6558 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;6551 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
6559 const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data;6552 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();
6562 const lhs = try f.resolveInst(extra.a);6555 const lhs = try f.resolveInst(extra.a);
6563 const rhs = try f.resolveInst(extra.b);6556 const rhs = try f.resolveInst(extra.b);
65646557
6565 const module = f.object.dg.module;6558 const inst_ty = f.typeOfIndex(inst);
6566 const target = module.getTarget();
6567 const inst_ty = f.air.typeOfIndex(inst);
65686559
6569 const writer = f.object.writer();6560 const writer = f.object.writer();
6570 const local = try f.allocLocal(inst, inst_ty);6561 const local = try f.allocLocal(inst, inst_ty);
6571 try reap(f, inst, &.{ extra.a, extra.b }); // local cannot alias operands6562 try reap(f, inst, &.{ extra.a, extra.b }); // local cannot alias operands
6572 for (0..extra.mask_len) |index| {6563 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
6578 try f.writeCValue(writer, local, .Other);6564 try f.writeCValue(writer, local, .Other);
6579 try writer.writeByte('[');6565 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);
6581 try writer.writeAll("] = ");6567 try writer.writeAll("] = ");
65826568
6583 var buf: Value.ElemValueBuffer = undefined;6569 const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod);
6584 const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(target);6570 const src_val = try mod.intValue(Type.usize, @intCast(u64, mask_elem ^ mask_elem >> 63));
6585 var src_pl = Value.Payload.U64{
6586 .base = .{ .tag = .int_u64 },
6587 .data = @intCast(u64, mask_elem ^ mask_elem >> 63),
6588 };
65896571
6590 try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other);6572 try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other);
6591 try writer.writeByte('[');6573 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);
6593 try writer.writeAll("];\n");6575 try writer.writeAll("];\n");
6594 }6576 }
65956577
...@@ -6597,16 +6579,16 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6597,16 +6579,16 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
6597}6579}
65986580
6599fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {6581fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6582 const mod = f.object.dg.module;
6600 const reduce = f.air.instructions.items(.data)[inst].reduce;6583 const reduce = f.air.instructions.items(.data)[inst].reduce;
66016584
6602 const target = f.object.dg.module.getTarget();6585 const scalar_ty = f.typeOfIndex(inst);
6603 const scalar_ty = f.air.typeOfIndex(inst);
6604 const operand = try f.resolveInst(reduce.operand);6586 const operand = try f.resolveInst(reduce.operand);
6605 try reap(f, inst, &.{reduce.operand});6587 try reap(f, inst, &.{reduce.operand});
6606 const operand_ty = f.air.typeOf(reduce.operand);6588 const operand_ty = f.typeOf(reduce.operand);
6607 const writer = f.object.writer();6589 const writer = f.object.writer();
66086590
6609 const use_operator = scalar_ty.bitSize(target) <= 64;6591 const use_operator = scalar_ty.bitSize(mod) <= 64;
6610 const op: union(enum) {6592 const op: union(enum) {
6611 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };6593 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
6612 float_op: Func,6594 float_op: Func,
...@@ -6617,28 +6599,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6617,28 +6599,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6617 .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } },6599 .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } },
6618 .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },6600 .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },
6619 .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },6601 .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },
6620 .Min => switch (scalar_ty.zigTypeTag()) {6602 .Min => switch (scalar_ty.zigTypeTag(mod)) {
6621 .Int => if (use_operator) .{ .ternary = " < " } else .{6603 .Int => if (use_operator) .{ .ternary = " < " } else .{
6622 .builtin = .{ .operation = "min" },6604 .builtin = .{ .operation = "min" },
6623 },6605 },
6624 .Float => .{ .float_op = .{ .operation = "fmin" } },6606 .Float => .{ .float_op = .{ .operation = "fmin" } },
6625 else => unreachable,6607 else => unreachable,
6626 },6608 },
6627 .Max => switch (scalar_ty.zigTypeTag()) {6609 .Max => switch (scalar_ty.zigTypeTag(mod)) {
6628 .Int => if (use_operator) .{ .ternary = " > " } else .{6610 .Int => if (use_operator) .{ .ternary = " > " } else .{
6629 .builtin = .{ .operation = "max" },6611 .builtin = .{ .operation = "max" },
6630 },6612 },
6631 .Float => .{ .float_op = .{ .operation = "fmax" } },6613 .Float => .{ .float_op = .{ .operation = "fmax" } },
6632 else => unreachable,6614 else => unreachable,
6633 },6615 },
6634 .Add => switch (scalar_ty.zigTypeTag()) {6616 .Add => switch (scalar_ty.zigTypeTag(mod)) {
6635 .Int => if (use_operator) .{ .infix = " += " } else .{6617 .Int => if (use_operator) .{ .infix = " += " } else .{
6636 .builtin = .{ .operation = "addw", .info = .bits },6618 .builtin = .{ .operation = "addw", .info = .bits },
6637 },6619 },
6638 .Float => .{ .builtin = .{ .operation = "add" } },6620 .Float => .{ .builtin = .{ .operation = "add" } },
6639 else => unreachable,6621 else => unreachable,
6640 },6622 },
6641 .Mul => switch (scalar_ty.zigTypeTag()) {6623 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
6642 .Int => if (use_operator) .{ .infix = " *= " } else .{6624 .Int => if (use_operator) .{ .infix = " *= " } else .{
6643 .builtin = .{ .operation = "mulw", .info = .bits },6625 .builtin = .{ .operation = "mulw", .info = .bits },
6644 },6626 },
...@@ -6663,43 +6645,42 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6663,43 +6645,42 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6663 try f.writeCValue(writer, accum, .Other);6645 try f.writeCValue(writer, accum, .Other);
6664 try writer.writeAll(" = ");6646 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
6681 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {6648 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
6682 .Or, .Xor, .Add => Value.zero,6649 .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) {
6683 .And => switch (scalar_ty.zigTypeTag()) {6650 .Bool => Value.false,
6684 .Bool => Value.one,6651 .Int => try mod.intValue(scalar_ty, 0),
6685 else => switch (scalar_ty.intInfo(target).signedness) {6652 else => unreachable,
6686 .unsigned => try scalar_ty.maxInt(stack.get(), target),6653 },
6687 .signed => Value.negative_one,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),
6688 },6659 },
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,
6689 },6666 },
6690 .Min => switch (scalar_ty.zigTypeTag()) {6667 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
6691 .Bool => Value.one,6668 .Int => try mod.intValue(scalar_ty, 1),
6692 .Int => try scalar_ty.maxInt(stack.get(), target),6669 .Float => try mod.floatValue(scalar_ty, 1.0),
6693 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
6694 else => unreachable,6670 else => unreachable,
6695 },6671 },
6696 .Max => switch (scalar_ty.zigTypeTag()) {6672 .Min => switch (scalar_ty.zigTypeTag(mod)) {
6697 .Bool => Value.zero,6673 .Bool => Value.true,
6698 .Int => try scalar_ty.minInt(stack.get(), target),6674 .Int => try scalar_ty.maxIntScalar(mod, scalar_ty),
6699 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),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),
6700 else => unreachable,6682 else => unreachable,
6701 },6683 },
6702 .Mul => Value.one,
6703 }, .Initializer);6684 }, .Initializer);
6704 try writer.writeAll(";\n");6685 try writer.writeAll(";\n");
67056686
...@@ -6753,9 +6734,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6753,9 +6734,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6753}6734}
67546735
6755fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {6736fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6737 const mod = f.object.dg.module;
6738 const ip = &mod.intern_pool;
6756 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;6739 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
6757 const inst_ty = f.air.typeOfIndex(inst);6740 const inst_ty = f.typeOfIndex(inst);
6758 const len = @intCast(usize, inst_ty.arrayLen());6741 const len = @intCast(usize, inst_ty.arrayLen(mod));
6759 const elements = @ptrCast([]const Air.Inst.Ref, f.air.extra[ty_pl.payload..][0..len]);6742 const elements = @ptrCast([]const Air.Inst.Ref, f.air.extra[ty_pl.payload..][0..len]);
6760 const gpa = f.object.dg.gpa;6743 const gpa = f.object.dg.gpa;
6761 const resolved_elements = try gpa.alloc(CValue, elements.len);6744 const resolved_elements = try gpa.alloc(CValue, elements.len);
...@@ -6770,13 +6753,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6770,13 +6753,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6770 }6753 }
6771 }6754 }
67726755
6773 const target = f.object.dg.module.getTarget();
6774
6775 const writer = f.object.writer();6756 const writer = f.object.writer();
6776 const local = try f.allocLocal(inst, inst_ty);6757 const local = try f.allocLocal(inst, inst_ty);
6777 switch (inst_ty.zigTypeTag()) {6758 switch (inst_ty.zigTypeTag(mod)) {
6778 .Array, .Vector => {6759 .Array, .Vector => {
6779 const elem_ty = inst_ty.childType();6760 const elem_ty = inst_ty.childType(mod);
6780 const a = try Assignment.init(f, elem_ty);6761 const a = try Assignment.init(f, elem_ty);
6781 for (resolved_elements, 0..) |element, i| {6762 for (resolved_elements, 0..) |element, i| {
6782 try a.restart(f, writer);6763 try a.restart(f, writer);
...@@ -6786,7 +6767,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6786,7 +6767,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6786 try f.writeCValue(writer, element, .Other);6767 try f.writeCValue(writer, element, .Other);
6787 try a.end(f, writer);6768 try a.end(f, writer);
6788 }6769 }
6789 if (inst_ty.sentinel()) |sentinel| {6770 if (inst_ty.sentinel(mod)) |sentinel| {
6790 try a.restart(f, writer);6771 try a.restart(f, writer);
6791 try f.writeCValue(writer, local, .Other);6772 try f.writeCValue(writer, local, .Other);
6792 try writer.print("[{d}]", .{resolved_elements.len});6773 try writer.print("[{d}]", .{resolved_elements.len});
...@@ -6795,17 +6776,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6795,17 +6776,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6795 try a.end(f, writer);6776 try a.end(f, writer);
6796 }6777 }
6797 },6778 },
6798 .Struct => switch (inst_ty.containerLayout()) {6779 .Struct => switch (inst_ty.containerLayout(mod)) {
6799 .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {6780 .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {
6800 if (inst_ty.structFieldIsComptime(field_i)) continue;6781 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6801 const field_ty = inst_ty.structFieldType(field_i);6782 const field_ty = inst_ty.structFieldType(field_i, mod);
6802 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;6783 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68036784
6804 const a = try Assignment.start(f, writer, field_ty);6785 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))
6806 .{ .field = field_i }6787 .{ .field = field_i }
6807 else6788 else
6808 .{ .identifier = inst_ty.structFieldName(field_i) });6789 .{ .identifier = ip.stringToSlice(inst_ty.structFieldName(field_i, mod)) });
6809 try a.assign(f, writer);6790 try a.assign(f, writer);
6810 try f.writeCValue(writer, element, .Other);6791 try f.writeCValue(writer, element, .Other);
6811 try a.end(f, writer);6792 try a.end(f, writer);
...@@ -6813,22 +6794,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6813,22 +6794,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6813 .Packed => {6794 .Packed => {
6814 try f.writeCValue(writer, local, .Other);6795 try f.writeCValue(writer, local, .Other);
6815 try writer.writeAll(" = ");6796 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{6799 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
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);
68236800
6824 var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 };6801 var bit_offset: u64 = 0;
6825 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
68266802
6827 var empty = true;6803 var empty = true;
6828 for (0..elements.len) |field_i| {6804 for (0..elements.len) |field_i| {
6829 if (inst_ty.structFieldIsComptime(field_i)) continue;6805 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6830 const field_ty = inst_ty.structFieldType(field_i);6806 const field_ty = inst_ty.structFieldType(field_i, mod);
6831 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;6807 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68326808
6833 if (!empty) {6809 if (!empty) {
6834 try writer.writeAll("zig_or_");6810 try writer.writeAll("zig_or_");
...@@ -6839,9 +6815,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6839,9 +6815,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6839 }6815 }
6840 empty = true;6816 empty = true;
6841 for (resolved_elements, 0..) |element, field_i| {6817 for (resolved_elements, 0..) |element, field_i| {
6842 if (inst_ty.structFieldIsComptime(field_i)) continue;6818 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6843 const field_ty = inst_ty.structFieldType(field_i);6819 const field_ty = inst_ty.structFieldType(field_i, mod);
6844 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;6820 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68456821
6846 if (!empty) try writer.writeAll(", ");6822 if (!empty) try writer.writeAll(", ");
6847 // TODO: Skip this entire shift if val is 0?6823 // TODO: Skip this entire shift if val is 0?
...@@ -6849,13 +6825,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6849,13 +6825,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6849 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);6825 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
6850 try writer.writeByte('(');6826 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))) {
6853 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);6829 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
6854 } else {6830 } else {
6855 try writer.writeByte('(');6831 try writer.writeByte('(');
6856 try f.renderType(writer, inst_ty);6832 try f.renderType(writer, inst_ty);
6857 try writer.writeByte(')');6833 try writer.writeByte(')');
6858 if (field_ty.isPtrAtRuntime()) {6834 if (field_ty.isPtrAtRuntime(mod)) {
6859 try writer.writeByte('(');6835 try writer.writeByte('(');
6860 try f.renderType(writer, switch (int_info.signedness) {6836 try f.renderType(writer, switch (int_info.signedness) {
6861 .unsigned => Type.usize,6837 .unsigned => Type.usize,
...@@ -6867,12 +6843,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6867,12 +6843,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6867 }6843 }
68686844
6869 try writer.writeAll(", ");6845 try writer.writeAll(", ");
6846 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
6870 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);6847 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
6871 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);6848 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
6872 try writer.writeByte(')');6849 try writer.writeByte(')');
6873 if (!empty) try writer.writeByte(')');6850 if (!empty) try writer.writeByte(')');
68746851
6875 bit_offset_val_pl.data += field_ty.bitSize(target);6852 bit_offset += field_ty.bitSize(mod);
6876 empty = false;6853 empty = false;
6877 }6854 }
68786855
...@@ -6886,14 +6863,15 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6886,14 +6863,15 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6886}6863}
68876864
6888fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {6865fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
6866 const mod = f.object.dg.module;
6867 const ip = &mod.intern_pool;
6889 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;6868 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
6890 const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data;6869 const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data;
68916870
6892 const union_ty = f.air.typeOfIndex(inst);6871 const union_ty = f.typeOfIndex(inst);
6893 const target = f.object.dg.module.getTarget();6872 const union_obj = mod.typeToUnion(union_ty).?;
6894 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
6895 const field_name = union_obj.fields.keys()[extra.field_index];6873 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);
6897 const payload = try f.resolveInst(extra.init);6875 const payload = try f.resolveInst(extra.init);
6898 try reap(f, inst, &.{extra.init});6876 try reap(f, inst, &.{extra.init});
68996877
...@@ -6907,19 +6885,14 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6907,19 +6885,14 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
6907 return local;6885 return local;
6908 }6886 }
69096887
6910 const field: CValue = if (union_ty.unionTagTypeSafety()) |tag_ty| field: {6888 const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: {
6911 const layout = union_ty.unionGetLayout(target);6889 const layout = union_ty.unionGetLayout(mod);
6912 if (layout.tag_size != 0) {6890 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 = .{6893 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
6916 .base = .{ .tag = .enum_field_index },
6917 .data = @intCast(u32, field_index),
6918 };
6919 const tag_val = Value.initPayload(&tag_pl.base);
69206894
6921 var int_pl: Value.Payload.U64 = undefined;6895 const int_val = try tag_val.enumToInt(tag_ty, mod);
6922 const int_val = tag_val.enumToInt(tag_ty, &int_pl);
69236896
6924 const a = try Assignment.start(f, writer, tag_ty);6897 const a = try Assignment.start(f, writer, tag_ty);
6925 try f.writeCValueMember(writer, local, .{ .identifier = "tag" });6898 try f.writeCValueMember(writer, local, .{ .identifier = "tag" });
...@@ -6927,8 +6900,8 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6927,8 +6900,8 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
6927 try writer.print("{}", .{try f.fmtIntLiteral(tag_ty, int_val)});6900 try writer.print("{}", .{try f.fmtIntLiteral(tag_ty, int_val)});
6928 try a.end(f, writer);6901 try a.end(f, writer);
6929 }6902 }
6930 break :field .{ .payload_identifier = field_name };6903 break :field .{ .payload_identifier = ip.stringToSlice(field_name) };
6931 } else .{ .identifier = field_name };6904 } else .{ .identifier = ip.stringToSlice(field_name) };
69326905
6933 const a = try Assignment.start(f, writer, payload_ty);6906 const a = try Assignment.start(f, writer, payload_ty);
6934 try f.writeCValueMember(writer, local, field);6907 try f.writeCValueMember(writer, local, field);
...@@ -6963,7 +6936,7 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6963,7 +6936,7 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
6963 const pl_op = f.air.instructions.items(.data)[inst].pl_op;6936 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
69646937
6965 const writer = f.object.writer();6938 const writer = f.object.writer();
6966 const inst_ty = f.air.typeOfIndex(inst);6939 const inst_ty = f.typeOfIndex(inst);
6967 const local = try f.allocLocal(inst, inst_ty);6940 const local = try f.allocLocal(inst, inst_ty);
6968 try f.writeCValue(writer, local, .Other);6941 try f.writeCValue(writer, local, .Other);
69696942
...@@ -6977,7 +6950,7 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6977,7 +6950,7 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
6977 const pl_op = f.air.instructions.items(.data)[inst].pl_op;6950 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
69786951
6979 const writer = f.object.writer();6952 const writer = f.object.writer();
6980 const inst_ty = f.air.typeOfIndex(inst);6953 const inst_ty = f.typeOfIndex(inst);
6981 const operand = try f.resolveInst(pl_op.operand);6954 const operand = try f.resolveInst(pl_op.operand);
6982 try reap(f, inst, &.{pl_op.operand});6955 try reap(f, inst, &.{pl_op.operand});
6983 const local = try f.allocLocal(inst, inst_ty);6956 const local = try f.allocLocal(inst, inst_ty);
...@@ -6991,13 +6964,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6991,13 +6964,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
6991}6964}
69926965
6993fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {6966fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
6967 const mod = f.object.dg.module;
6994 const un_op = f.air.instructions.items(.data)[inst].un_op;6968 const un_op = f.air.instructions.items(.data)[inst].un_op;
69956969
6996 const operand = try f.resolveInst(un_op);6970 const operand = try f.resolveInst(un_op);
6997 try reap(f, inst, &.{un_op});6971 try reap(f, inst, &.{un_op});
69986972
6999 const operand_ty = f.air.typeOf(un_op);6973 const operand_ty = f.typeOf(un_op);
7000 const scalar_ty = operand_ty.scalarType();6974 const scalar_ty = operand_ty.scalarType(mod);
70016975
7002 const writer = f.object.writer();6976 const writer = f.object.writer();
7003 const local = try f.allocLocal(inst, operand_ty);6977 const local = try f.allocLocal(inst, operand_ty);
...@@ -7016,13 +6990,14 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7016,13 +6990,14 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
7016}6990}
70176991
7018fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {6992fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
6993 const mod = f.object.dg.module;
7019 const un_op = f.air.instructions.items(.data)[inst].un_op;6994 const un_op = f.air.instructions.items(.data)[inst].un_op;
70206995
7021 const operand = try f.resolveInst(un_op);6996 const operand = try f.resolveInst(un_op);
7022 try reap(f, inst, &.{un_op});6997 try reap(f, inst, &.{un_op});
70236998
7024 const inst_ty = f.air.typeOfIndex(inst);6999 const inst_ty = f.typeOfIndex(inst);
7025 const inst_scalar_ty = inst_ty.scalarType();7000 const inst_scalar_ty = inst_ty.scalarType(mod);
70267001
7027 const writer = f.object.writer();7002 const writer = f.object.writer();
7028 const local = try f.allocLocal(inst, inst_ty);7003 const local = try f.allocLocal(inst, inst_ty);
...@@ -7043,14 +7018,15 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal...@@ -7043,14 +7018,15 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
7043}7018}
70447019
7045fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {7020fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
7021 const mod = f.object.dg.module;
7046 const bin_op = f.air.instructions.items(.data)[inst].bin_op;7022 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
70477023
7048 const lhs = try f.resolveInst(bin_op.lhs);7024 const lhs = try f.resolveInst(bin_op.lhs);
7049 const rhs = try f.resolveInst(bin_op.rhs);7025 const rhs = try f.resolveInst(bin_op.rhs);
7050 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });7026 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
70517027
7052 const inst_ty = f.air.typeOfIndex(inst);7028 const inst_ty = f.typeOfIndex(inst);
7053 const inst_scalar_ty = inst_ty.scalarType();7029 const inst_scalar_ty = inst_ty.scalarType(mod);
70547030
7055 const writer = f.object.writer();7031 const writer = f.object.writer();
7056 const local = try f.allocLocal(inst, inst_ty);7032 const local = try f.allocLocal(inst, inst_ty);
...@@ -7074,6 +7050,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa...@@ -7074,6 +7050,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
7074}7050}
70757051
7076fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {7052fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7053 const mod = f.object.dg.module;
7077 const pl_op = f.air.instructions.items(.data)[inst].pl_op;7054 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
7078 const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data;7055 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 {...@@ -7082,8 +7059,8 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7082 const addend = try f.resolveInst(pl_op.operand);7059 const addend = try f.resolveInst(pl_op.operand);
7083 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });7060 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
70847061
7085 const inst_ty = f.air.typeOfIndex(inst);7062 const inst_ty = f.typeOfIndex(inst);
7086 const inst_scalar_ty = inst_ty.scalarType();7063 const inst_scalar_ty = inst_ty.scalarType(mod);
70877064
7088 const writer = f.object.writer();7065 const writer = f.object.writer();
7089 const local = try f.allocLocal(inst, inst_ty);7066 const local = try f.allocLocal(inst, inst_ty);
...@@ -7108,7 +7085,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7108,7 +7085,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7108}7085}
71097086
7110fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {7087fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7111 const inst_ty = f.air.typeOfIndex(inst);7088 const inst_ty = f.typeOfIndex(inst);
7112 const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete);7089 const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete);
7113 const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;7090 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 {...@@ -7127,7 +7104,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7127fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {7104fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
7128 const ty_op = f.air.instructions.items(.data)[inst].ty_op;7105 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);
7131 const va_list = try f.resolveInst(ty_op.operand);7108 const va_list = try f.resolveInst(ty_op.operand);
7132 try reap(f, inst, &.{ty_op.operand});7109 try reap(f, inst, &.{ty_op.operand});
71337110
...@@ -7158,7 +7135,7 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7158,7 +7135,7 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
7158fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {7135fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
7159 const ty_op = f.air.instructions.items(.data)[inst].ty_op;7136 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);
7162 const va_list = try f.resolveInst(ty_op.operand);7139 const va_list = try f.resolveInst(ty_op.operand);
7163 try reap(f, inst, &.{ty_op.operand});7140 try reap(f, inst, &.{ty_op.operand});
71647141
...@@ -7279,8 +7256,9 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {...@@ -7279,8 +7256,9 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {
7279 };7256 };
7280}7257}
72817258
7282fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 {7259fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 {
7283 return if (ty.isInt()) switch (ty.intInfo(target).bits) {7260 const target = mod.getTarget();
7261 return if (ty.isInt(mod)) switch (ty.intInfo(mod).bits) {
7284 1...32 => "si",7262 1...32 => "si",
7285 33...64 => "di",7263 33...64 => "di",
7286 65...128 => "ti",7264 65...128 => "ti",
...@@ -7407,7 +7385,7 @@ fn undefPattern(comptime IntType: type) IntType {...@@ -7407,7 +7385,7 @@ fn undefPattern(comptime IntType: type) IntType {
74077385
7408const FormatIntLiteralContext = struct {7386const FormatIntLiteralContext = struct {
7409 dg: *DeclGen,7387 dg: *DeclGen,
7410 int_info: std.builtin.Type.Int,7388 int_info: InternPool.Key.IntType,
7411 kind: CType.Kind,7389 kind: CType.Kind,
7412 cty: CType,7390 cty: CType,
7413 val: Value,7391 val: Value,
...@@ -7418,7 +7396,8 @@ fn formatIntLiteral(...@@ -7418,7 +7396,8 @@ fn formatIntLiteral(
7418 options: std.fmt.FormatOptions,7396 options: std.fmt.FormatOptions,
7419 writer: anytype,7397 writer: anytype,
7420) @TypeOf(writer).Error!void {7398) @TypeOf(writer).Error!void {
7421 const target = data.dg.module.getTarget();7399 const mod = data.dg.module;
7400 const target = mod.getTarget();
74227401
7423 const ExpectedContents = struct {7402 const ExpectedContents = struct {
7424 const base = 10;7403 const base = 10;
...@@ -7438,7 +7417,7 @@ fn formatIntLiteral(...@@ -7438,7 +7417,7 @@ fn formatIntLiteral(
7438 defer allocator.free(undef_limbs);7417 defer allocator.free(undef_limbs);
74397418
7440 var int_buf: Value.BigIntSpace = undefined;7419 var int_buf: Value.BigIntSpace = undefined;
7441 const int = if (data.val.isUndefDeep()) blk: {7420 const int = if (data.val.isUndefDeep(mod)) blk: {
7442 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));7421 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
7443 @memset(undef_limbs, undefPattern(BigIntLimb));7422 @memset(undef_limbs, undefPattern(BigIntLimb));
74447423
...@@ -7449,7 +7428,7 @@ fn formatIntLiteral(...@@ -7449,7 +7428,7 @@ fn formatIntLiteral(
7449 };7428 };
7450 undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits);7429 undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits);
7451 break :blk undef_int.toConst();7430 break :blk undef_int.toConst();
7452 } else data.val.toBigInt(&int_buf, target);7431 } else data.val.toBigInt(&int_buf, mod);
7453 assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));7432 assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));
74547433
7455 const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8);7434 const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8);
...@@ -7576,10 +7555,6 @@ fn formatIntLiteral(...@@ -7576,10 +7555,6 @@ fn formatIntLiteral(
7576 c_limb_int_info.signedness = .unsigned;7555 c_limb_int_info.signedness = .unsigned;
7577 c_limb_cty = c_limb_info.cty;7556 c_limb_cty = c_limb_info.cty;
7578 }7557 }
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
7584 if (limb_offset > 0) try writer.writeAll(", ");7559 if (limb_offset > 0) try writer.writeAll(", ");
7585 try formatIntLiteral(.{7560 try formatIntLiteral(.{
...@@ -7587,7 +7562,7 @@ fn formatIntLiteral(...@@ -7587,7 +7562,7 @@ fn formatIntLiteral(
7587 .int_info = c_limb_int_info,7562 .int_info = c_limb_int_info,
7588 .kind = data.kind,7563 .kind = data.kind,
7589 .cty = c_limb_cty,7564 .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()),
7591 }, fmt, options, writer);7566 }, fmt, options, writer);
7592 }7567 }
7593 }7568 }
...@@ -7684,20 +7659,21 @@ const Vectorize = struct {...@@ -7684,20 +7659,21 @@ const Vectorize = struct {
7684 index: CValue = .none,7659 index: CValue = .none,
76857660
7686 pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {7661 pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {
7687 return if (ty.zigTypeTag() == .Vector) index: {7662 const mod = f.object.dg.module;
7688 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = ty.vectorLen() };7663 return if (ty.zigTypeTag(mod) == .Vector) index: {
7664 const len_val = try mod.intValue(Type.usize, ty.vectorLen(mod));
76897665
7690 const local = try f.allocLocal(inst, Type.usize);7666 const local = try f.allocLocal(inst, Type.usize);
76917667
7692 try writer.writeAll("for (");7668 try writer.writeAll("for (");
7693 try f.writeCValue(writer, local, .Other);7669 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))});
7695 try f.writeCValue(writer, local, .Other);7671 try f.writeCValue(writer, local, .Other);
7696 try writer.print(" < {d}; ", .{7672 try writer.print(" < {d}; ", .{
7697 try f.fmtIntLiteral(Type.usize, Value.initPayload(&len_pl.base)),7673 try f.fmtIntLiteral(Type.usize, len_val),
7698 });7674 });
7699 try f.writeCValue(writer, local, .Other);7675 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))});
7701 f.object.indent_writer.pushIndent();7677 f.object.indent_writer.pushIndent();
77027678
7703 break :index .{ .index = local };7679 break :index .{ .index = local };
...@@ -7721,34 +7697,30 @@ const Vectorize = struct {...@@ -7721,34 +7697,30 @@ const Vectorize = struct {
7721 }7697 }
7722};7698};
77237699
7724const LowerFnRetTyBuffer = struct {7700fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
7725 names: [1][]const u8,7701 if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;
7726 types: [1]Type,7702
7727 values: [1]Value,7703 if (lowersToArray(ret_ty, mod)) {
7728 payload: Type.Payload.AnonStruct,7704 const names = [1]InternPool.NullTerminatedString{
7729};7705 try mod.intern_pool.getOrPutString(mod.gpa, "array"),
7730fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {7706 };
7731 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);7707 const types = [1]InternPool.Index{ret_ty.ip_index};
77327708 const values = [1]InternPool.Index{.none};
7733 if (lowersToArray(ret_ty, target)) {7709 const interned = try mod.intern(.{ .anon_struct_type = .{
7734 buffer.names = [1][]const u8{"array"};7710 .names = &names,
7735 buffer.types = [1]Type{ret_ty};7711 .types = &types,
7736 buffer.values = [1]Value{Value.initTag(.unreachable_value)};7712 .values = &values,
7737 buffer.payload = .{ .data = .{7713 } });
7738 .names = &buffer.names,7714 return interned.toType();
7739 .types = &buffer.types,
7740 .values = &buffer.values,
7741 } };
7742 return Type.initPayload(&buffer.payload.base);
7743 }7715 }
77447716
7745 return if (ret_ty.hasRuntimeBitsIgnoreComptime()) ret_ty else Type.void;7717 return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void;
7746}7718}
77477719
7748fn lowersToArray(ty: Type, target: std.Target) bool {7720fn lowersToArray(ty: Type, mod: *Module) bool {
7749 return switch (ty.zigTypeTag()) {7721 return switch (ty.zigTypeTag(mod)) {
7750 .Array, .Vector => return true,7722 .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,
7752 };7724 };
7753}7725}
77547726
...@@ -7765,8 +7737,8 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi...@@ -7765,8 +7737,8 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi
77657737
7766fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {7738fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
7767 const ref_inst = Air.refToIndex(ref) orelse return;7739 const ref_inst = Air.refToIndex(ref) orelse return;
7740 assert(f.air.instructions.items(.tag)[ref_inst] != .interned);
7768 const c_value = (f.value_map.fetchRemove(ref_inst) orelse return).value;7741 const c_value = (f.value_map.fetchRemove(ref_inst) orelse return).value;
7769 if (f.air.instructions.items(.tag)[ref_inst] == .constant) return;
7770 const local_index = switch (c_value) {7742 const local_index = switch (c_value) {
7771 .local, .new_local => |l| l,7743 .local, .new_local => |l| l,
7772 else => return,7744 else => return,
src/codegen/c/type.zig+165-167
...@@ -292,19 +292,19 @@ pub const CType = extern union {...@@ -292,19 +292,19 @@ pub const CType = extern union {
292 .abi = std.math.log2_int(u32, abi_alignment),292 .abi = std.math.log2_int(u32, abi_alignment),
293 };293 };
294 }294 }
295 pub fn abiAlign(ty: Type, target: Target) AlignAs {295 pub fn abiAlign(ty: Type, mod: *Module) AlignAs {
296 const abi_align = ty.abiAlignment(target);296 const abi_align = ty.abiAlignment(mod);
297 return init(abi_align, abi_align);297 return init(abi_align, abi_align);
298 }298 }
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 {
300 return init(300 return init(
301 struct_ty.structFieldAlign(field_i, target),301 struct_ty.structFieldAlign(field_i, mod),
302 struct_ty.structFieldType(field_i).abiAlignment(target),302 struct_ty.structFieldType(field_i, mod).abiAlignment(mod),
303 );303 );
304 }304 }
305 pub fn unionPayloadAlign(union_ty: Type, target: Target) AlignAs {305 pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs {
306 const union_obj = union_ty.cast(Type.Payload.Union).?.data;306 const union_obj = mod.typeToUnion(union_ty).?;
307 const union_payload_align = union_obj.abiAlignment(target, false);307 const union_payload_align = union_obj.abiAlignment(mod, false);
308 return init(union_payload_align, union_payload_align);308 return init(union_payload_align, union_payload_align);
309 }309 }
310310
...@@ -344,8 +344,8 @@ pub const CType = extern union {...@@ -344,8 +344,8 @@ pub const CType = extern union {
344 return self.map.entries.items(.hash)[index - Tag.no_payload_count];344 return self.map.entries.items(.hash)[index - Tag.no_payload_count];
345 }345 }
346346
347 pub fn typeToIndex(self: Set, ty: Type, target: Target, kind: Kind) ?Index {347 pub fn typeToIndex(self: Set, ty: Type, mod: *Module, kind: Kind) ?Index {
348 const lookup = Convert.Lookup{ .imm = .{ .set = &self, .target = target } };348 const lookup = Convert.Lookup{ .imm = .{ .set = &self, .mod = mod } };
349349
350 var convert: Convert = undefined;350 var convert: Convert = undefined;
351 convert.initType(ty, kind, lookup) catch unreachable;351 convert.initType(ty, kind, lookup) catch unreachable;
...@@ -405,7 +405,7 @@ pub const CType = extern union {...@@ -405,7 +405,7 @@ pub const CType = extern union {
405 );405 );
406 if (!gop.found_existing) {406 if (!gop.found_existing) {
407 errdefer _ = self.set.map.pop();407 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);
409 }409 }
410 if (std.debug.runtime_safety) {410 if (std.debug.runtime_safety) {
411 const adapter = TypeAdapter64{411 const adapter = TypeAdapter64{
...@@ -1236,10 +1236,10 @@ pub const CType = extern union {...@@ -1236,10 +1236,10 @@ pub const CType = extern union {
1236 }1236 }
12371237
1238 pub const Lookup = union(enum) {1238 pub const Lookup = union(enum) {
1239 fail: Target,1239 fail: *Module,
1240 imm: struct {1240 imm: struct {
1241 set: *const Store.Set,1241 set: *const Store.Set,
1242 target: Target,1242 mod: *Module,
1243 },1243 },
1244 mut: struct {1244 mut: struct {
1245 promoted: *Store.Promoted,1245 promoted: *Store.Promoted,
...@@ -1254,10 +1254,14 @@ pub const CType = extern union {...@@ -1254,10 +1254,14 @@ pub const CType = extern union {
1254 }1254 }
12551255
1256 pub fn getTarget(self: @This()) Target {1256 pub fn getTarget(self: @This()) Target {
1257 return self.getModule().getTarget();
1258 }
1259
1260 pub fn getModule(self: @This()) *Module {
1257 return switch (self) {1261 return switch (self) {
1258 .fail => |target| target,1262 .fail => |mod| mod,
1259 .imm => |imm| imm.target,1263 .imm => |imm| imm.mod,
1260 .mut => |mut| mut.mod.getTarget(),1264 .mut => |mut| mut.mod,
1261 };1265 };
1262 }1266 }
12631267
...@@ -1272,7 +1276,7 @@ pub const CType = extern union {...@@ -1272,7 +1276,7 @@ pub const CType = extern union {
1272 pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index {1276 pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index {
1273 return switch (self) {1277 return switch (self) {
1274 .fail => null,1278 .fail => null,
1275 .imm => |imm| imm.set.typeToIndex(ty, imm.target, kind),1279 .imm => |imm| imm.set.typeToIndex(ty, imm.mod, kind),
1276 .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind),1280 .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind),
1277 };1281 };
1278 }1282 }
...@@ -1284,7 +1288,7 @@ pub const CType = extern union {...@@ -1284,7 +1288,7 @@ pub const CType = extern union {
1284 pub fn freeze(self: @This()) @This() {1288 pub fn freeze(self: @This()) @This() {
1285 return switch (self) {1289 return switch (self) {
1286 .fail, .imm => self,1290 .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 } },
1288 };1292 };
1289 }1293 }
1290 };1294 };
...@@ -1338,7 +1342,7 @@ pub const CType = extern union {...@@ -1338,7 +1342,7 @@ pub const CType = extern union {
1338 self.storage.anon.fields[0] = .{1342 self.storage.anon.fields[0] = .{
1339 .name = "array",1343 .name = "array",
1340 .type = array_idx,1344 .type = array_idx,
1341 .alignas = AlignAs.abiAlign(ty, lookup.getTarget()),1345 .alignas = AlignAs.abiAlign(ty, lookup.getModule()),
1342 };1346 };
1343 self.initAnon(kind, fwd_idx, 1);1347 self.initAnon(kind, fwd_idx, 1);
1344 } else self.init(switch (kind) {1348 } else self.init(switch (kind) {
...@@ -1350,30 +1354,30 @@ pub const CType = extern union {...@@ -1350,30 +1354,30 @@ pub const CType = extern union {
1350 }1354 }
13511355
1352 pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void {1356 pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void {
1353 const target = lookup.getTarget();1357 const mod = lookup.getModule();
13541358
1355 self.* = undefined;1359 self.* = undefined;
1356 if (!ty.isFnOrHasRuntimeBitsIgnoreComptime())1360 if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(mod))
1357 self.init(.void)1361 self.init(.void)
1358 else if (ty.isAbiInt()) switch (ty.tag()) {1362 else if (ty.isAbiInt(mod)) switch (ty.ip_index) {
1359 .usize => self.init(.uintptr_t),1363 .usize_type => self.init(.uintptr_t),
1360 .isize => self.init(.intptr_t),1364 .isize_type => self.init(.intptr_t),
1361 .c_char => self.init(.char),1365 .c_char_type => self.init(.char),
1362 .c_short => self.init(.short),1366 .c_short_type => self.init(.short),
1363 .c_ushort => self.init(.@"unsigned short"),1367 .c_ushort_type => self.init(.@"unsigned short"),
1364 .c_int => self.init(.int),1368 .c_int_type => self.init(.int),
1365 .c_uint => self.init(.@"unsigned int"),1369 .c_uint_type => self.init(.@"unsigned int"),
1366 .c_long => self.init(.long),1370 .c_long_type => self.init(.long),
1367 .c_ulong => self.init(.@"unsigned long"),1371 .c_ulong_type => self.init(.@"unsigned long"),
1368 .c_longlong => self.init(.@"long long"),1372 .c_longlong_type => self.init(.@"long long"),
1369 .c_ulonglong => self.init(.@"unsigned long long"),1373 .c_ulonglong_type => self.init(.@"unsigned long long"),
1370 else => switch (tagFromIntInfo(ty.intInfo(target))) {1374 else => switch (tagFromIntInfo(ty.intInfo(mod))) {
1371 .void => unreachable,1375 .void => unreachable,
1372 else => |t| self.init(t),1376 else => |t| self.init(t),
1373 .array => switch (kind) {1377 .array => switch (kind) {
1374 .forward, .complete, .global => {1378 .forward, .complete, .global => {
1375 const abi_size = ty.abiSize(target);1379 const abi_size = ty.abiSize(mod);
1376 const abi_align = ty.abiAlignment(target);1380 const abi_align = ty.abiAlignment(mod);
1377 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{1381 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
1378 .len = @divExact(abi_size, abi_align),1382 .len = @divExact(abi_size, abi_align),
1379 .elem_type = tagFromIntInfo(.{1383 .elem_type = tagFromIntInfo(.{
...@@ -1389,7 +1393,7 @@ pub const CType = extern union {...@@ -1389,7 +1393,7 @@ pub const CType = extern union {
1389 .payload => unreachable,1393 .payload => unreachable,
1390 },1394 },
1391 },1395 },
1392 } else switch (ty.zigTypeTag()) {1396 } else switch (ty.zigTypeTag(mod)) {
1393 .Frame => unreachable,1397 .Frame => unreachable,
1394 .AnyFrame => unreachable,1398 .AnyFrame => unreachable,
13951399
...@@ -1408,18 +1412,18 @@ pub const CType = extern union {...@@ -1408,18 +1412,18 @@ pub const CType = extern union {
14081412
1409 .Bool => self.init(.bool),1413 .Bool => self.init(.bool),
14101414
1411 .Float => self.init(switch (ty.tag()) {1415 .Float => self.init(switch (ty.ip_index) {
1412 .f16 => .zig_f16,1416 .f16_type => .zig_f16,
1413 .f32 => .zig_f32,1417 .f32_type => .zig_f32,
1414 .f64 => .zig_f64,1418 .f64_type => .zig_f64,
1415 .f80 => .zig_f80,1419 .f80_type => .zig_f80,
1416 .f128 => .zig_f128,1420 .f128_type => .zig_f128,
1417 .c_longdouble => .zig_c_longdouble,1421 .c_longdouble_type => .zig_c_longdouble,
1418 else => unreachable,1422 else => unreachable,
1419 }),1423 }),
14201424
1421 .Pointer => {1425 .Pointer => {
1422 const info = ty.ptrInfo().data;1426 const info = ty.ptrInfo(mod);
1423 switch (info.size) {1427 switch (info.size) {
1424 .Slice => {1428 .Slice => {
1425 if (switch (kind) {1429 if (switch (kind) {
...@@ -1427,19 +1431,18 @@ pub const CType = extern union {...@@ -1427,19 +1431,18 @@ pub const CType = extern union {
1427 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),1431 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
1428 .payload => unreachable,1432 .payload => unreachable,
1429 }) |fwd_idx| {1433 }) |fwd_idx| {
1430 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1434 const ptr_ty = ty.slicePtrFieldType(mod);
1431 const ptr_ty = ty.slicePtrFieldType(&buf);
1432 if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| {1435 if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| {
1433 self.storage = .{ .anon = undefined };1436 self.storage = .{ .anon = undefined };
1434 self.storage.anon.fields[0] = .{1437 self.storage.anon.fields[0] = .{
1435 .name = "ptr",1438 .name = "ptr",
1436 .type = ptr_idx,1439 .type = ptr_idx,
1437 .alignas = AlignAs.abiAlign(ptr_ty, target),1440 .alignas = AlignAs.abiAlign(ptr_ty, mod),
1438 };1441 };
1439 self.storage.anon.fields[1] = .{1442 self.storage.anon.fields[1] = .{
1440 .name = "len",1443 .name = "len",
1441 .type = Tag.uintptr_t.toIndex(),1444 .type = Tag.uintptr_t.toIndex(),
1442 .alignas = AlignAs.abiAlign(Type.usize, target),1445 .alignas = AlignAs.abiAlign(Type.usize, mod),
1443 };1446 };
1444 self.initAnon(kind, fwd_idx, 2);1447 self.initAnon(kind, fwd_idx, 2);
1445 } else self.init(switch (kind) {1448 } else self.init(switch (kind) {
...@@ -1462,16 +1465,12 @@ pub const CType = extern union {...@@ -1462,16 +1465,12 @@ pub const CType = extern union {
1462 },1465 },
1463 };1466 };
14641467
1465 var host_int_pl = Type.Payload.Bits{
1466 .base = .{ .tag = .int_unsigned },
1467 .data = info.host_size * 8,
1468 };
1469 const pointee_ty = if (info.host_size > 0 and info.vector_index == .none)1468 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)
1471 else1470 else
1472 info.pointee_type;1471 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)
1475 Tag.char.toIndex()1474 Tag.char.toIndex()
1476 else1475 else
1477 try lookup.typeToIndex(pointee_ty, .forward)) |child_idx|1476 try lookup.typeToIndex(pointee_ty, .forward)) |child_idx|
...@@ -1486,26 +1485,24 @@ pub const CType = extern union {...@@ -1486,26 +1485,24 @@ pub const CType = extern union {
1486 }1485 }
1487 },1486 },
14881487
1489 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout() == .Packed) {1488 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .Packed) {
1490 if (ty.castTag(.@"struct")) |struct_obj| {1489 if (mod.typeToStruct(ty)) |struct_obj| {
1491 try self.initType(struct_obj.data.backing_int_ty, kind, lookup);1490 try self.initType(struct_obj.backing_int_ty, kind, lookup);
1492 } else {1491 } else {
1493 var buf: Type.Payload.Bits = .{1492 const bits = @intCast(u16, ty.bitSize(mod));
1494 .base = .{ .tag = .int_unsigned },1493 const int_ty = try mod.intType(.unsigned, bits);
1495 .data = @intCast(u16, ty.bitSize(target)),1494 try self.initType(int_ty, kind, lookup);
1496 };
1497 try self.initType(Type.initPayload(&buf.base), kind, lookup);
1498 }1495 }
1499 } else if (ty.isTupleOrAnonStruct()) {1496 } else if (ty.isTupleOrAnonStruct(mod)) {
1500 if (lookup.isMutable()) {1497 if (lookup.isMutable()) {
1501 for (0..switch (zig_ty_tag) {1498 for (0..switch (zig_ty_tag) {
1502 .Struct => ty.structFieldCount(),1499 .Struct => ty.structFieldCount(mod),
1503 .Union => ty.unionFields().count(),1500 .Union => ty.unionFields(mod).count(),
1504 else => unreachable,1501 else => unreachable,
1505 }) |field_i| {1502 }) |field_i| {
1506 const field_ty = ty.structFieldType(field_i);1503 const field_ty = ty.structFieldType(field_i, mod);
1507 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or1504 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1508 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;1505 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1509 _ = try lookup.typeToIndex(field_ty, switch (kind) {1506 _ = try lookup.typeToIndex(field_ty, switch (kind) {
1510 .forward, .forward_parameter => .forward,1507 .forward, .forward_parameter => .forward,
1511 .complete, .parameter => .complete,1508 .complete, .parameter => .complete,
...@@ -1533,14 +1530,14 @@ pub const CType = extern union {...@@ -1533,14 +1530,14 @@ pub const CType = extern union {
1533 .payload => unreachable,1530 .payload => unreachable,
1534 });1531 });
1535 } else {1532 } else {
1536 const tag_ty = ty.unionTagTypeSafety();1533 const tag_ty = ty.unionTagTypeSafety(mod);
1537 const is_tagged_union_wrapper = kind != .payload and tag_ty != null;1534 const is_tagged_union_wrapper = kind != .payload and tag_ty != null;
1538 const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper;1535 const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper;
1539 switch (kind) {1536 switch (kind) {
1540 .forward, .forward_parameter => {1537 .forward, .forward_parameter => {
1541 self.storage = .{ .fwd = .{1538 self.storage = .{ .fwd = .{
1542 .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union },1539 .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union },
1543 .data = ty.getOwnerDecl(),1540 .data = ty.getOwnerDecl(mod),
1544 } };1541 } };
1545 self.value = .{ .cty = initPayload(&self.storage.fwd) };1542 self.value = .{ .cty = initPayload(&self.storage.fwd) };
1546 },1543 },
...@@ -1555,7 +1552,7 @@ pub const CType = extern union {...@@ -1555,7 +1552,7 @@ pub const CType = extern union {
1555 self.storage.anon.fields[field_count] = .{1552 self.storage.anon.fields[field_count] = .{
1556 .name = "payload",1553 .name = "payload",
1557 .type = payload_idx.?,1554 .type = payload_idx.?,
1558 .alignas = AlignAs.unionPayloadAlign(ty, target),1555 .alignas = AlignAs.unionPayloadAlign(ty, mod),
1559 };1556 };
1560 field_count += 1;1557 field_count += 1;
1561 }1558 }
...@@ -1563,7 +1560,7 @@ pub const CType = extern union {...@@ -1563,7 +1560,7 @@ pub const CType = extern union {
1563 self.storage.anon.fields[field_count] = .{1560 self.storage.anon.fields[field_count] = .{
1564 .name = "tag",1561 .name = "tag",
1565 .type = tag_idx.?,1562 .type = tag_idx.?,
1566 .alignas = AlignAs.abiAlign(tag_ty.?, target),1563 .alignas = AlignAs.abiAlign(tag_ty.?, mod),
1567 };1564 };
1568 field_count += 1;1565 field_count += 1;
1569 }1566 }
...@@ -1576,19 +1573,19 @@ pub const CType = extern union {...@@ -1576,19 +1573,19 @@ pub const CType = extern union {
1576 } };1573 } };
1577 self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) };1574 self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) };
1578 } else self.init(.@"struct");1575 } else self.init(.@"struct");
1579 } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes()) {1576 } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(mod)) {
1580 self.init(.void);1577 self.init(.void);
1581 } else {1578 } else {
1582 var is_packed = false;1579 var is_packed = false;
1583 for (0..switch (zig_ty_tag) {1580 for (0..switch (zig_ty_tag) {
1584 .Struct => ty.structFieldCount(),1581 .Struct => ty.structFieldCount(mod),
1585 .Union => ty.unionFields().count(),1582 .Union => ty.unionFields(mod).count(),
1586 else => unreachable,1583 else => unreachable,
1587 }) |field_i| {1584 }) |field_i| {
1588 const field_ty = ty.structFieldType(field_i);1585 const field_ty = ty.structFieldType(field_i, mod);
1589 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;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);
1592 if (field_align.@"align" < field_align.abi) {1589 if (field_align.@"align" < field_align.abi) {
1593 is_packed = true;1590 is_packed = true;
1594 if (!lookup.isMutable()) break;1591 if (!lookup.isMutable()) break;
...@@ -1627,9 +1624,9 @@ pub const CType = extern union {...@@ -1627,9 +1624,9 @@ pub const CType = extern union {
1627 .Vector => .vector,1624 .Vector => .vector,
1628 else => unreachable,1625 else => unreachable,
1629 };1626 };
1630 if (try lookup.typeToIndex(ty.childType(), kind)) |child_idx| {1627 if (try lookup.typeToIndex(ty.childType(mod), kind)) |child_idx| {
1631 self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{1628 self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{
1632 .len = ty.arrayLenIncludingSentinel(),1629 .len = ty.arrayLenIncludingSentinel(mod),
1633 .elem_type = child_idx,1630 .elem_type = child_idx,
1634 } } };1631 } } };
1635 self.value = .{ .cty = initPayload(&self.storage.seq) };1632 self.value = .{ .cty = initPayload(&self.storage.seq) };
...@@ -1641,10 +1638,9 @@ pub const CType = extern union {...@@ -1641,10 +1638,9 @@ pub const CType = extern union {
1641 },1638 },
16421639
1643 .Optional => {1640 .Optional => {
1644 var buf: Type.Payload.ElemType = undefined;1641 const payload_ty = ty.optionalChild(mod);
1645 const payload_ty = ty.optionalChild(&buf);1642 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1646 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {1643 if (ty.optionalReprIsPayload(mod)) {
1647 if (ty.optionalReprIsPayload()) {
1648 try self.initType(payload_ty, kind, lookup);1644 try self.initType(payload_ty, kind, lookup);
1649 } else if (switch (kind) {1645 } else if (switch (kind) {
1650 .forward, .forward_parameter => @as(Index, undefined),1646 .forward, .forward_parameter => @as(Index, undefined),
...@@ -1661,12 +1657,12 @@ pub const CType = extern union {...@@ -1661,12 +1657,12 @@ pub const CType = extern union {
1661 self.storage.anon.fields[0] = .{1657 self.storage.anon.fields[0] = .{
1662 .name = "payload",1658 .name = "payload",
1663 .type = payload_idx,1659 .type = payload_idx,
1664 .alignas = AlignAs.abiAlign(payload_ty, target),1660 .alignas = AlignAs.abiAlign(payload_ty, mod),
1665 };1661 };
1666 self.storage.anon.fields[1] = .{1662 self.storage.anon.fields[1] = .{
1667 .name = "is_null",1663 .name = "is_null",
1668 .type = Tag.bool.toIndex(),1664 .type = Tag.bool.toIndex(),
1669 .alignas = AlignAs.abiAlign(Type.bool, target),1665 .alignas = AlignAs.abiAlign(Type.bool, mod),
1670 };1666 };
1671 self.initAnon(kind, fwd_idx, 2);1667 self.initAnon(kind, fwd_idx, 2);
1672 } else self.init(switch (kind) {1668 } else self.init(switch (kind) {
...@@ -1684,14 +1680,14 @@ pub const CType = extern union {...@@ -1684,14 +1680,14 @@ pub const CType = extern union {
1684 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),1680 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
1685 .payload => unreachable,1681 .payload => unreachable,
1686 }) |fwd_idx| {1682 }) |fwd_idx| {
1687 const payload_ty = ty.errorUnionPayload();1683 const payload_ty = ty.errorUnionPayload(mod);
1688 if (try lookup.typeToIndex(payload_ty, switch (kind) {1684 if (try lookup.typeToIndex(payload_ty, switch (kind) {
1689 .forward, .forward_parameter => .forward,1685 .forward, .forward_parameter => .forward,
1690 .complete, .parameter => .complete,1686 .complete, .parameter => .complete,
1691 .global => .global,1687 .global => .global,
1692 .payload => unreachable,1688 .payload => unreachable,
1693 })) |payload_idx| {1689 })) |payload_idx| {
1694 const error_ty = ty.errorUnionSet();1690 const error_ty = ty.errorUnionSet(mod);
1695 if (payload_idx == Tag.void.toIndex()) {1691 if (payload_idx == Tag.void.toIndex()) {
1696 try self.initType(error_ty, kind, lookup);1692 try self.initType(error_ty, kind, lookup);
1697 } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| {1693 } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| {
...@@ -1699,12 +1695,12 @@ pub const CType = extern union {...@@ -1699,12 +1695,12 @@ pub const CType = extern union {
1699 self.storage.anon.fields[0] = .{1695 self.storage.anon.fields[0] = .{
1700 .name = "payload",1696 .name = "payload",
1701 .type = payload_idx,1697 .type = payload_idx,
1702 .alignas = AlignAs.abiAlign(payload_ty, target),1698 .alignas = AlignAs.abiAlign(payload_ty, mod),
1703 };1699 };
1704 self.storage.anon.fields[1] = .{1700 self.storage.anon.fields[1] = .{
1705 .name = "error",1701 .name = "error",
1706 .type = error_idx,1702 .type = error_idx,
1707 .alignas = AlignAs.abiAlign(error_ty, target),1703 .alignas = AlignAs.abiAlign(error_ty, mod),
1708 };1704 };
1709 self.initAnon(kind, fwd_idx, 2);1705 self.initAnon(kind, fwd_idx, 2);
1710 } else self.init(switch (kind) {1706 } else self.init(switch (kind) {
...@@ -1723,7 +1719,7 @@ pub const CType = extern union {...@@ -1723,7 +1719,7 @@ pub const CType = extern union {
1723 .Opaque => self.init(.void),1719 .Opaque => self.init(.void),
17241720
1725 .Fn => {1721 .Fn => {
1726 const info = ty.fnInfo();1722 const info = mod.typeToFunc(ty).?;
1727 if (!info.is_generic) {1723 if (!info.is_generic) {
1728 if (lookup.isMutable()) {1724 if (lookup.isMutable()) {
1729 const param_kind: Kind = switch (kind) {1725 const param_kind: Kind = switch (kind) {
...@@ -1731,10 +1727,10 @@ pub const CType = extern union {...@@ -1731,10 +1727,10 @@ pub const CType = extern union {
1731 .complete, .parameter, .global => .parameter,1727 .complete, .parameter, .global => .parameter,
1732 .payload => unreachable,1728 .payload => unreachable,
1733 };1729 };
1734 _ = try lookup.typeToIndex(info.return_type, param_kind);1730 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
1735 for (info.param_types) |param_type| {1731 for (info.param_types) |param_type| {
1736 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;1732 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
1737 _ = try lookup.typeToIndex(param_type, param_kind);1733 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
1738 }1734 }
1739 }1735 }
1740 self.init(if (info.is_var_args) .varargs_function else .function);1736 self.init(if (info.is_var_args) .varargs_function else .function);
...@@ -1900,16 +1896,16 @@ pub const CType = extern union {...@@ -1900,16 +1896,16 @@ pub const CType = extern union {
1900 }1896 }
1901 }1897 }
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 {
1904 var convert: Convert = undefined;1900 var convert: Convert = undefined;
1905 try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .target = target } });1901 try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .mod = mod } });
1906 return createFromConvert(store, ty, target, kind, &convert);1902 return createFromConvert(store, ty, mod, kind, &convert);
1907 }1903 }
19081904
1909 fn createFromConvert(1905 fn createFromConvert(
1910 store: *Store.Promoted,1906 store: *Store.Promoted,
1911 ty: Type,1907 ty: Type,
1912 target: Target,1908 mod: *Module,
1913 kind: Kind,1909 kind: Kind,
1914 convert: Convert,1910 convert: Convert,
1915 ) !CType {1911 ) !CType {
...@@ -1930,44 +1926,44 @@ pub const CType = extern union {...@@ -1930,44 +1926,44 @@ pub const CType = extern union {
1930 .packed_struct,1926 .packed_struct,
1931 .packed_union,1927 .packed_union,
1932 => {1928 => {
1933 const zig_ty_tag = ty.zigTypeTag();1929 const zig_ty_tag = ty.zigTypeTag(mod);
1934 const fields_len = switch (zig_ty_tag) {1930 const fields_len = switch (zig_ty_tag) {
1935 .Struct => ty.structFieldCount(),1931 .Struct => ty.structFieldCount(mod),
1936 .Union => ty.unionFields().count(),1932 .Union => ty.unionFields(mod).count(),
1937 else => unreachable,1933 else => unreachable,
1938 };1934 };
19391935
1940 var c_fields_len: usize = 0;1936 var c_fields_len: usize = 0;
1941 for (0..fields_len) |field_i| {1937 for (0..fields_len) |field_i| {
1942 const field_ty = ty.structFieldType(field_i);1938 const field_ty = ty.structFieldType(field_i, mod);
1943 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or1939 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1944 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;1940 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1945 c_fields_len += 1;1941 c_fields_len += 1;
1946 }1942 }
19471943
1948 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);1944 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);
1949 var c_field_i: usize = 0;1945 var c_field_i: usize = 0;
1950 for (0..fields_len) |field_i| {1946 for (0..fields_len) |field_i| {
1951 const field_ty = ty.structFieldType(field_i);1947 const field_ty = ty.structFieldType(field_i, mod);
1952 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or1948 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1953 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;1949 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
19541950
1955 defer c_field_i += 1;1951 defer c_field_i += 1;
1956 fields_pl[c_field_i] = .{1952 fields_pl[c_field_i] = .{
1957 .name = try if (ty.isSimpleTuple())1953 .name = try if (ty.isSimpleTuple(mod))
1958 std.fmt.allocPrintZ(arena, "f{}", .{field_i})1954 std.fmt.allocPrintZ(arena, "f{}", .{field_i})
1959 else1955 else
1960 arena.dupeZ(u8, switch (zig_ty_tag) {1956 arena.dupeZ(u8, mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
1961 .Struct => ty.structFieldName(field_i),1957 .Struct => ty.structFieldName(field_i, mod),
1962 .Union => ty.unionFields().keys()[field_i],1958 .Union => ty.unionFields(mod).keys()[field_i],
1963 else => unreachable,1959 else => unreachable,
1964 }),1960 })),
1965 .type = store.set.typeToIndex(field_ty, target, switch (kind) {1961 .type = store.set.typeToIndex(field_ty, mod, switch (kind) {
1966 .forward, .forward_parameter => .forward,1962 .forward, .forward_parameter => .forward,
1967 .complete, .parameter, .payload => .complete,1963 .complete, .parameter, .payload => .complete,
1968 .global => .global,1964 .global => .global,
1969 }).?,1965 }).?,
1970 .alignas = AlignAs.fieldAlign(ty, field_i, target),1966 .alignas = AlignAs.fieldAlign(ty, field_i, mod),
1971 };1967 };
1972 }1968 }
19731969
...@@ -1988,8 +1984,8 @@ pub const CType = extern union {...@@ -1988,8 +1984,8 @@ pub const CType = extern union {
1988 const unnamed_pl = try arena.create(Payload.Unnamed);1984 const unnamed_pl = try arena.create(Payload.Unnamed);
1989 unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{1985 unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{
1990 .fields = fields_pl,1986 .fields = fields_pl,
1991 .owner_decl = ty.getOwnerDecl(),1987 .owner_decl = ty.getOwnerDecl(mod),
1992 .id = if (ty.unionTagTypeSafety()) |_| 0 else unreachable,1988 .id = if (ty.unionTagTypeSafety(mod)) |_| 0 else unreachable,
1993 } };1989 } };
1994 return initPayload(unnamed_pl);1990 return initPayload(unnamed_pl);
1995 },1991 },
...@@ -2004,7 +2000,7 @@ pub const CType = extern union {...@@ -2004,7 +2000,7 @@ pub const CType = extern union {
2004 const struct_pl = try arena.create(Payload.Aggregate);2000 const struct_pl = try arena.create(Payload.Aggregate);
2005 struct_pl.* = .{ .base = .{ .tag = t }, .data = .{2001 struct_pl.* = .{ .base = .{ .tag = t }, .data = .{
2006 .fields = fields_pl,2002 .fields = fields_pl,
2007 .fwd_decl = store.set.typeToIndex(ty, target, .forward).?,2003 .fwd_decl = store.set.typeToIndex(ty, mod, .forward).?,
2008 } };2004 } };
2009 return initPayload(struct_pl);2005 return initPayload(struct_pl);
2010 },2006 },
...@@ -2016,7 +2012,7 @@ pub const CType = extern union {...@@ -2016,7 +2012,7 @@ pub const CType = extern union {
2016 .function,2012 .function,
2017 .varargs_function,2013 .varargs_function,
2018 => {2014 => {
2019 const info = ty.fnInfo();2015 const info = mod.typeToFunc(ty).?;
2020 assert(!info.is_generic);2016 assert(!info.is_generic);
2021 const param_kind: Kind = switch (kind) {2017 const param_kind: Kind = switch (kind) {
2022 .forward, .forward_parameter => .forward_parameter,2018 .forward, .forward_parameter => .forward_parameter,
...@@ -2026,21 +2022,21 @@ pub const CType = extern union {...@@ -2026,21 +2022,21 @@ pub const CType = extern union {
20262022
2027 var c_params_len: usize = 0;2023 var c_params_len: usize = 0;
2028 for (info.param_types) |param_type| {2024 for (info.param_types) |param_type| {
2029 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;2025 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2030 c_params_len += 1;2026 c_params_len += 1;
2031 }2027 }
20322028
2033 const params_pl = try arena.alloc(Index, c_params_len);2029 const params_pl = try arena.alloc(Index, c_params_len);
2034 var c_param_i: usize = 0;2030 var c_param_i: usize = 0;
2035 for (info.param_types) |param_type| {2031 for (info.param_types) |param_type| {
2036 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;2032 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2037 params_pl[c_param_i] = store.set.typeToIndex(param_type, target, param_kind).?;2033 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
2038 c_param_i += 1;2034 c_param_i += 1;
2039 }2035 }
20402036
2041 const fn_pl = try arena.create(Payload.Function);2037 const fn_pl = try arena.create(Payload.Function);
2042 fn_pl.* = .{ .base = .{ .tag = t }, .data = .{2038 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).?,
2044 .param_types = params_pl,2040 .param_types = params_pl,
2045 } };2041 } };
2046 return initPayload(fn_pl);2042 return initPayload(fn_pl);
...@@ -2067,33 +2063,33 @@ pub const CType = extern union {...@@ -2067,33 +2063,33 @@ pub const CType = extern union {
2067 }2063 }
20682064
2069 pub fn eql(self: @This(), ty: Type, cty: CType) bool {2065 pub fn eql(self: @This(), ty: Type, cty: CType) bool {
2066 const mod = self.lookup.getModule();
2070 switch (self.convert.value) {2067 switch (self.convert.value) {
2071 .cty => |c| return c.eql(cty),2068 .cty => |c| return c.eql(cty),
2072 .tag => |t| {2069 .tag => |t| {
2073 if (t != cty.tag()) return false;2070 if (t != cty.tag()) return false;
20742071
2075 const target = self.lookup.getTarget();
2076 switch (t) {2072 switch (t) {
2077 .fwd_anon_struct,2073 .fwd_anon_struct,
2078 .fwd_anon_union,2074 .fwd_anon_union,
2079 => {2075 => {
2080 if (!ty.isTupleOrAnonStruct()) return false;2076 if (!ty.isTupleOrAnonStruct(mod)) return false;
20812077
2082 var name_buf: [2078 var name_buf: [
2083 std.fmt.count("f{}", .{std.math.maxInt(usize)})2079 std.fmt.count("f{}", .{std.math.maxInt(usize)})
2084 ]u8 = undefined;2080 ]u8 = undefined;
2085 const c_fields = cty.cast(Payload.Fields).?.data;2081 const c_fields = cty.cast(Payload.Fields).?.data;
20862082
2087 const zig_ty_tag = ty.zigTypeTag();2083 const zig_ty_tag = ty.zigTypeTag(mod);
2088 var c_field_i: usize = 0;2084 var c_field_i: usize = 0;
2089 for (0..switch (zig_ty_tag) {2085 for (0..switch (zig_ty_tag) {
2090 .Struct => ty.structFieldCount(),2086 .Struct => ty.structFieldCount(mod),
2091 .Union => ty.unionFields().count(),2087 .Union => ty.unionFields(mod).count(),
2092 else => unreachable,2088 else => unreachable,
2093 }) |field_i| {2089 }) |field_i| {
2094 const field_ty = ty.structFieldType(field_i);2090 const field_ty = ty.structFieldType(field_i, mod);
2095 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or2091 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
2096 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;2092 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
20972093
2098 defer c_field_i += 1;2094 defer c_field_i += 1;
2099 const c_field = &c_fields[c_field_i];2095 const c_field = &c_fields[c_field_i];
...@@ -2105,15 +2101,16 @@ pub const CType = extern union {...@@ -2105,15 +2101,16 @@ pub const CType = extern union {
2105 .payload => unreachable,2101 .payload => unreachable,
2106 }) or !mem.eql(2102 }) or !mem.eql(
2107 u8,2103 u8,
2108 if (ty.isSimpleTuple())2104 if (ty.isSimpleTuple(mod))
2109 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable2105 std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable
2110 else switch (zig_ty_tag) {2106 else
2111 .Struct => ty.structFieldName(field_i),2107 mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
2112 .Union => ty.unionFields().keys()[field_i],2108 .Struct => ty.structFieldName(field_i, mod),
2113 else => unreachable,2109 .Union => ty.unionFields(mod).keys()[field_i],
2114 },2110 else => unreachable,
2111 }),
2115 mem.span(c_field.name),2112 mem.span(c_field.name),
2116 ) or AlignAs.fieldAlign(ty, field_i, target).@"align" !=2113 ) or AlignAs.fieldAlign(ty, field_i, mod).@"align" !=
2117 c_field.alignas.@"align") return false;2114 c_field.alignas.@"align") return false;
2118 }2115 }
2119 return true;2116 return true;
...@@ -2125,9 +2122,9 @@ pub const CType = extern union {...@@ -2125,9 +2122,9 @@ pub const CType = extern union {
2125 .packed_unnamed_union,2122 .packed_unnamed_union,
2126 => switch (self.kind) {2123 => switch (self.kind) {
2127 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,2124 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
2128 .payload => if (ty.unionTagTypeSafety()) |_| {2125 .payload => if (ty.unionTagTypeSafety(mod)) |_| {
2129 const data = cty.cast(Payload.Unnamed).?.data;2126 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;
2131 } else unreachable,2128 } else unreachable,
2132 },2129 },
21332130
...@@ -2146,9 +2143,9 @@ pub const CType = extern union {...@@ -2146,9 +2143,9 @@ pub const CType = extern union {
2146 .function,2143 .function,
2147 .varargs_function,2144 .varargs_function,
2148 => {2145 => {
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).?;
2152 assert(!info.is_generic);2149 assert(!info.is_generic);
2153 const data = cty.cast(Payload.Function).?.data;2150 const data = cty.cast(Payload.Function).?.data;
2154 const param_kind: Kind = switch (self.kind) {2151 const param_kind: Kind = switch (self.kind) {
...@@ -2157,18 +2154,18 @@ pub const CType = extern union {...@@ -2157,18 +2154,18 @@ pub const CType = extern union {
2157 .payload => unreachable,2154 .payload => unreachable,
2158 };2155 };
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))
2161 return false;2158 return false;
21622159
2163 var c_param_i: usize = 0;2160 var c_param_i: usize = 0;
2164 for (info.param_types) |param_type| {2161 for (info.param_types) |param_type| {
2165 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;2162 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21662163
2167 if (c_param_i >= data.param_types.len) return false;2164 if (c_param_i >= data.param_types.len) return false;
2168 const param_cty = data.param_types[c_param_i];2165 const param_cty = data.param_types[c_param_i];
2169 c_param_i += 1;2166 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))
2172 return false;2169 return false;
2173 }2170 }
2174 return c_param_i == data.param_types.len;2171 return c_param_i == data.param_types.len;
...@@ -2202,7 +2199,7 @@ pub const CType = extern union {...@@ -2202,7 +2199,7 @@ pub const CType = extern union {
2202 .tag => |t| {2199 .tag => |t| {
2203 autoHash(hasher, t);2200 autoHash(hasher, t);
22042201
2205 const target = self.lookup.getTarget();2202 const mod = self.lookup.getModule();
2206 switch (t) {2203 switch (t) {
2207 .fwd_anon_struct,2204 .fwd_anon_struct,
2208 .fwd_anon_union,2205 .fwd_anon_union,
...@@ -2211,15 +2208,15 @@ pub const CType = extern union {...@@ -2211,15 +2208,15 @@ pub const CType = extern union {
2211 std.fmt.count("f{}", .{std.math.maxInt(usize)})2208 std.fmt.count("f{}", .{std.math.maxInt(usize)})
2212 ]u8 = undefined;2209 ]u8 = undefined;
22132210
2214 const zig_ty_tag = ty.zigTypeTag();2211 const zig_ty_tag = ty.zigTypeTag(mod);
2215 for (0..switch (ty.zigTypeTag()) {2212 for (0..switch (ty.zigTypeTag(mod)) {
2216 .Struct => ty.structFieldCount(),2213 .Struct => ty.structFieldCount(mod),
2217 .Union => ty.unionFields().count(),2214 .Union => ty.unionFields(mod).count(),
2218 else => unreachable,2215 else => unreachable,
2219 }) |field_i| {2216 }) |field_i| {
2220 const field_ty = ty.structFieldType(field_i);2217 const field_ty = ty.structFieldType(field_i, mod);
2221 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or2218 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
2222 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;2219 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
22232220
2224 self.updateHasherRecurse(hasher, field_ty, switch (self.kind) {2221 self.updateHasherRecurse(hasher, field_ty, switch (self.kind) {
2225 .forward, .forward_parameter => .forward,2222 .forward, .forward_parameter => .forward,
...@@ -2227,14 +2224,15 @@ pub const CType = extern union {...@@ -2227,14 +2224,15 @@ pub const CType = extern union {
2227 .global => .global,2224 .global => .global,
2228 .payload => unreachable,2225 .payload => unreachable,
2229 });2226 });
2230 hasher.update(if (ty.isSimpleTuple())2227 hasher.update(if (ty.isSimpleTuple(mod))
2231 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable2228 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
2232 else switch (zig_ty_tag) {2229 else
2233 .Struct => ty.structFieldName(field_i),2230 mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
2234 .Union => ty.unionFields().keys()[field_i],2231 .Struct => ty.structFieldName(field_i, mod),
2235 else => unreachable,2232 .Union => ty.unionFields(mod).keys()[field_i],
2236 });2233 else => unreachable,
2237 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, target).@"align");2234 }));
2235 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align");
2238 }2236 }
2239 },2237 },
22402238
...@@ -2244,8 +2242,8 @@ pub const CType = extern union {...@@ -2244,8 +2242,8 @@ pub const CType = extern union {
2244 .packed_unnamed_union,2242 .packed_unnamed_union,
2245 => switch (self.kind) {2243 => switch (self.kind) {
2246 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,2244 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
2247 .payload => if (ty.unionTagTypeSafety()) |_| {2245 .payload => if (ty.unionTagTypeSafety(mod)) |_| {
2248 autoHash(hasher, ty.getOwnerDecl());2246 autoHash(hasher, ty.getOwnerDecl(mod));
2249 autoHash(hasher, @as(u32, 0));2247 autoHash(hasher, @as(u32, 0));
2250 } else unreachable,2248 } else unreachable,
2251 },2249 },
...@@ -2261,7 +2259,7 @@ pub const CType = extern union {...@@ -2261,7 +2259,7 @@ pub const CType = extern union {
2261 .function,2259 .function,
2262 .varargs_function,2260 .varargs_function,
2263 => {2261 => {
2264 const info = ty.fnInfo();2262 const info = mod.typeToFunc(ty).?;
2265 assert(!info.is_generic);2263 assert(!info.is_generic);
2266 const param_kind: Kind = switch (self.kind) {2264 const param_kind: Kind = switch (self.kind) {
2267 .forward, .forward_parameter => .forward_parameter,2265 .forward, .forward_parameter => .forward_parameter,
...@@ -2269,10 +2267,10 @@ pub const CType = extern union {...@@ -2269,10 +2267,10 @@ pub const CType = extern union {
2269 .payload => unreachable,2267 .payload => unreachable,
2270 };2268 };
22712269
2272 self.updateHasherRecurse(hasher, info.return_type, param_kind);2270 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
2273 for (info.param_types) |param_type| {2271 for (info.param_types) |param_type| {
2274 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;2272 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2275 self.updateHasherRecurse(hasher, param_type, param_kind);2273 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
2276 }2274 }
2277 },2275 },
22782276
src/codegen/llvm.zig+2024-2211
...@@ -12,6 +12,7 @@ const link = @import("../link.zig");...@@ -12,6 +12,7 @@ const link = @import("../link.zig");
12const Compilation = @import("../Compilation.zig");12const Compilation = @import("../Compilation.zig");
13const build_options = @import("build_options");13const build_options = @import("build_options");
14const Module = @import("../Module.zig");14const Module = @import("../Module.zig");
15const InternPool = @import("../InternPool.zig");
15const Package = @import("../Package.zig");16const Package = @import("../Package.zig");
16const TypedValue = @import("../TypedValue.zig");17const TypedValue = @import("../TypedValue.zig");
17const Air = @import("../Air.zig");18const Air = @import("../Air.zig");
...@@ -361,15 +362,11 @@ pub const Object = struct {...@@ -361,15 +362,11 @@ pub const Object = struct {
361 decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value),362 decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value),
362 /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction.363 /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction.
363 named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value),364 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 of365 /// Maps Zig types to LLVM types. The table memory is backed by the GPA of
365 /// the compiler, but the Type/Value memory here is backed by `type_map_arena`.366 /// the compiler.
366 /// TODO we need to remove entries from this map in response to incremental compilation367 /// TODO when InternPool garbage collection is implemented, this map needs
367 /// but I think the frontend won't tell us about types that get deleted because368 /// to be garbage collected as well.
368 /// hasRuntimeBits() is false for types.
369 type_map: TypeMap,369 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,
373 di_type_map: DITypeMap,370 di_type_map: DITypeMap,
374 /// The LLVM global table which holds the names corresponding to Zig errors.371 /// The LLVM global table which holds the names corresponding to Zig errors.
375 /// Note that the values are not added until flushModule, when all errors in372 /// Note that the values are not added until flushModule, when all errors in
...@@ -380,21 +377,11 @@ pub const Object = struct {...@@ -380,21 +377,11 @@ pub const Object = struct {
380 /// name collision.377 /// name collision.
381 extern_collisions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void),378 extern_collisions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void),
382379
383 pub const TypeMap = std.HashMapUnmanaged(380 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, *llvm.Type);
384 Type,
385 *llvm.Type,
386 Type.HashContext64,
387 std.hash_map.default_max_load_percentage,
388 );
389381
390 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we382 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
391 /// want to iterate over it while adding entries to it.383 /// want to iterate over it while adding entries to it.
392 pub const DITypeMap = std.ArrayHashMapUnmanaged(384 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
393 Type,
394 AnnotatedDITypePtr,
395 Type.HashContext32,
396 true,
397 );
398385
399 pub fn create(gpa: Allocator, options: link.Options) !*Object {386 pub fn create(gpa: Allocator, options: link.Options) !*Object {
400 const obj = try gpa.create(Object);387 const obj = try gpa.create(Object);
...@@ -542,7 +529,6 @@ pub const Object = struct {...@@ -542,7 +529,6 @@ pub const Object = struct {
542 .decl_map = .{},529 .decl_map = .{},
543 .named_enum_map = .{},530 .named_enum_map = .{},
544 .type_map = .{},531 .type_map = .{},
545 .type_map_arena = std.heap.ArenaAllocator.init(gpa),
546 .di_type_map = .{},532 .di_type_map = .{},
547 .error_name_table = null,533 .error_name_table = null,
548 .extern_collisions = .{},534 .extern_collisions = .{},
...@@ -562,7 +548,6 @@ pub const Object = struct {...@@ -562,7 +548,6 @@ pub const Object = struct {
562 self.decl_map.deinit(gpa);548 self.decl_map.deinit(gpa);
563 self.named_enum_map.deinit(gpa);549 self.named_enum_map.deinit(gpa);
564 self.type_map.deinit(gpa);550 self.type_map.deinit(gpa);
565 self.type_map_arena.deinit();
566 self.extern_collisions.deinit(gpa);551 self.extern_collisions.deinit(gpa);
567 self.* = undefined;552 self.* = undefined;
568 }553 }
...@@ -597,16 +582,16 @@ pub const Object = struct {...@@ -597,16 +582,16 @@ pub const Object = struct {
597 llvm_usize_ty,582 llvm_usize_ty,
598 };583 };
599 const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False);584 const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False);
600 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);585 const slice_ty = Type.slice_const_u8_sentinel_0;
601 const slice_alignment = slice_ty.abiAlignment(target);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();
604 const llvm_errors = try mod.gpa.alloc(*llvm.Value, error_name_list.len);589 const llvm_errors = try mod.gpa.alloc(*llvm.Value, error_name_list.len);
605 defer mod.gpa.free(llvm_errors);590 defer mod.gpa.free(llvm_errors);
606591
607 llvm_errors[0] = llvm_slice_ty.getUndef();592 llvm_errors[0] = llvm_slice_ty.getUndef();
608 for (llvm_errors[1..], 0..) |*llvm_error, i| {593 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| {
609 const name = error_name_list[1..][i];594 const name = mod.intern_pool.stringToSlice(name_nts);
610 const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False);595 const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False);
611 const str_global = self.llvm_module.addGlobal(str_init.typeOf(), "");596 const str_global = self.llvm_module.addGlobal(str_init.typeOf(), "");
612 str_global.setInitializer(str_init);597 str_global.setInitializer(str_init);
...@@ -686,7 +671,7 @@ pub const Object = struct {...@@ -686,7 +671,7 @@ pub const Object = struct {
686 const llvm_global = entry.value_ptr.*;671 const llvm_global = entry.value_ptr.*;
687 // Same logic as below but for externs instead of exports.672 // Same logic as below but for externs instead of exports.
688 const decl = mod.declPtr(decl_index);673 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;
690 if (other_global == llvm_global) continue;675 if (other_global == llvm_global) continue;
691676
692 llvm_global.replaceAllUsesWith(other_global);677 llvm_global.replaceAllUsesWith(other_global);
...@@ -702,12 +687,9 @@ pub const Object = struct {...@@ -702,12 +687,9 @@ pub const Object = struct {
702 for (export_list.items) |exp| {687 for (export_list.items) |exp| {
703 // Detect if the LLVM global has already been created as an extern. In such688 // Detect if the LLVM global has already been created as an extern. In such
704 // case, we need to replace all uses of it with this exported global.689 // case, we need to replace all uses of it with this exported global.
705 // TODO update std.builtin.ExportOptions to have the name be a690 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
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);
709691
710 const other_global = object.getLlvmGlobal(exp_name_z.ptr) orelse continue;692 const other_global = object.getLlvmGlobal(exp_name.ptr) orelse continue;
711 if (other_global == llvm_global) continue;693 if (other_global == llvm_global) continue;
712694
713 other_global.replaceAllUsesWith(llvm_global);695 other_global.replaceAllUsesWith(llvm_global);
...@@ -880,28 +862,29 @@ pub const Object = struct {...@@ -880,28 +862,29 @@ pub const Object = struct {
880862
881 pub fn updateFunc(863 pub fn updateFunc(
882 o: *Object,864 o: *Object,
883 module: *Module,865 mod: *Module,
884 func: *Module.Fn,866 func_index: Module.Fn.Index,
885 air: Air,867 air: Air,
886 liveness: Liveness,868 liveness: Liveness,
887 ) !void {869 ) !void {
870 const func = mod.funcPtr(func_index);
888 const decl_index = func.owner_decl;871 const decl_index = func.owner_decl;
889 const decl = module.declPtr(decl_index);872 const decl = mod.declPtr(decl_index);
890 const target = module.getTarget();873 const target = mod.getTarget();
891874
892 var dg: DeclGen = .{875 var dg: DeclGen = .{
893 .context = o.context,876 .context = o.context,
894 .object = o,877 .object = o,
895 .module = module,878 .module = mod,
896 .decl_index = decl_index,879 .decl_index = decl_index,
897 .decl = decl,880 .decl = decl,
898 .err_msg = null,881 .err_msg = null,
899 .gpa = module.gpa,882 .gpa = mod.gpa,
900 };883 };
901884
902 const llvm_func = try dg.resolveLlvmFunction(decl_index);885 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| {
905 dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment);888 dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment);
906 dg.addFnAttr(llvm_func, "noinline");889 dg.addFnAttr(llvm_func, "noinline");
907 } else {890 } else {
...@@ -922,7 +905,7 @@ pub const Object = struct {...@@ -922,7 +905,7 @@ pub const Object = struct {
922 }905 }
923906
924 // TODO: disable this if safety is off for the function scope907 // 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;
926 if (ssp_buf_size != 0) {909 if (ssp_buf_size != 0) {
927 var buf: [12]u8 = undefined;910 var buf: [12]u8 = undefined;
928 const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable;911 const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable;
...@@ -931,15 +914,14 @@ pub const Object = struct {...@@ -931,15 +914,14 @@ pub const Object = struct {
931 }914 }
932915
933 // TODO: disable this if safety is off for the function scope916 // 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) {
935 dg.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack");918 dg.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack");
936 } else if (target.os.tag == .uefi) {919 } else if (target.os.tag == .uefi) {
937 dg.addFnAttrString(llvm_func, "no-stack-arg-probe", "");920 dg.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
938 }921 }
939922
940 if (decl.@"linksection") |section| {923 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
941 llvm_func.setSection(section);924 llvm_func.setSection(section);
942 }
943925
944 // Remove all the basic blocks of a function in order to start over, generating926 // Remove all the basic blocks of a function in order to start over, generating
945 // LLVM IR from an empty function body.927 // LLVM IR from an empty function body.
...@@ -953,18 +935,18 @@ pub const Object = struct {...@@ -953,18 +935,18 @@ pub const Object = struct {
953 builder.positionBuilderAtEnd(entry_block);935 builder.positionBuilderAtEnd(entry_block);
954936
955 // This gets the LLVM values from the function and stores them in `dg.args`.937 // This gets the LLVM values from the function and stores them in `dg.args`.
956 const fn_info = decl.ty.fnInfo();938 const fn_info = mod.typeToFunc(decl.ty).?;
957 const sret = firstParamSRet(fn_info, target);939 const sret = firstParamSRet(fn_info, mod);
958 const ret_ptr = if (sret) llvm_func.getParam(0) else null;940 const ret_ptr = if (sret) llvm_func.getParam(0) else null;
959 const gpa = dg.gpa;941 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) {
962 .signed => dg.addAttr(llvm_func, 0, "signext"),944 .signed => dg.addAttr(llvm_func, 0, "signext"),
963 .unsigned => dg.addAttr(llvm_func, 0, "zeroext"),945 .unsigned => dg.addAttr(llvm_func, 0, "zeroext"),
964 };946 };
965947
966 const err_return_tracing = fn_info.return_type.isError() and948 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
967 module.comp.bin_file.options.error_return_tracing;949 mod.comp.bin_file.options.error_return_tracing;
968950
969 const err_ret_trace = if (err_return_tracing)951 const err_ret_trace = if (err_return_tracing)
970 llvm_func.getParam(@boolToInt(ret_ptr != null))952 llvm_func.getParam(@boolToInt(ret_ptr != null))
...@@ -985,12 +967,12 @@ pub const Object = struct {...@@ -985,12 +967,12 @@ pub const Object = struct {
985 .byval => {967 .byval => {
986 assert(!it.byval_attr);968 assert(!it.byval_attr);
987 const param_index = it.zig_index - 1;969 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();
989 const param = llvm_func.getParam(llvm_arg_i);971 const param = llvm_func.getParam(llvm_arg_i);
990 try args.ensureUnusedCapacity(1);972 try args.ensureUnusedCapacity(1);
991973
992 if (isByRef(param_ty)) {974 if (isByRef(param_ty, mod)) {
993 const alignment = param_ty.abiAlignment(target);975 const alignment = param_ty.abiAlignment(mod);
994 const param_llvm_ty = param.typeOf();976 const param_llvm_ty = param.typeOf();
995 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);977 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
996 const store_inst = builder.buildStore(param, arg_ptr);978 const store_inst = builder.buildStore(param, arg_ptr);
...@@ -1004,17 +986,17 @@ pub const Object = struct {...@@ -1004,17 +986,17 @@ pub const Object = struct {
1004 llvm_arg_i += 1;986 llvm_arg_i += 1;
1005 },987 },
1006 .byref => {988 .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();
1008 const param_llvm_ty = try dg.lowerType(param_ty);990 const param_llvm_ty = try dg.lowerType(param_ty);
1009 const param = llvm_func.getParam(llvm_arg_i);991 const param = llvm_func.getParam(llvm_arg_i);
1010 const alignment = param_ty.abiAlignment(target);992 const alignment = param_ty.abiAlignment(mod);
1011993
1012 dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);994 dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
1013 llvm_arg_i += 1;995 llvm_arg_i += 1;
1014996
1015 try args.ensureUnusedCapacity(1);997 try args.ensureUnusedCapacity(1);
1016998
1017 if (isByRef(param_ty)) {999 if (isByRef(param_ty, mod)) {
1018 args.appendAssumeCapacity(param);1000 args.appendAssumeCapacity(param);
1019 } else {1001 } else {
1020 const load_inst = builder.buildLoad(param_llvm_ty, param, "");1002 const load_inst = builder.buildLoad(param_llvm_ty, param, "");
...@@ -1023,17 +1005,17 @@ pub const Object = struct {...@@ -1023,17 +1005,17 @@ pub const Object = struct {
1023 }1005 }
1024 },1006 },
1025 .byref_mut => {1007 .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();
1027 const param_llvm_ty = try dg.lowerType(param_ty);1009 const param_llvm_ty = try dg.lowerType(param_ty);
1028 const param = llvm_func.getParam(llvm_arg_i);1010 const param = llvm_func.getParam(llvm_arg_i);
1029 const alignment = param_ty.abiAlignment(target);1011 const alignment = param_ty.abiAlignment(mod);
10301012
1031 dg.addArgAttr(llvm_func, llvm_arg_i, "noundef");1013 dg.addArgAttr(llvm_func, llvm_arg_i, "noundef");
1032 llvm_arg_i += 1;1014 llvm_arg_i += 1;
10331015
1034 try args.ensureUnusedCapacity(1);1016 try args.ensureUnusedCapacity(1);
10351017
1036 if (isByRef(param_ty)) {1018 if (isByRef(param_ty, mod)) {
1037 args.appendAssumeCapacity(param);1019 args.appendAssumeCapacity(param);
1038 } else {1020 } else {
1039 const load_inst = builder.buildLoad(param_llvm_ty, param, "");1021 const load_inst = builder.buildLoad(param_llvm_ty, param, "");
...@@ -1043,15 +1025,15 @@ pub const Object = struct {...@@ -1043,15 +1025,15 @@ pub const Object = struct {
1043 },1025 },
1044 .abi_sized_int => {1026 .abi_sized_int => {
1045 assert(!it.byval_attr);1027 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();
1047 const param = llvm_func.getParam(llvm_arg_i);1029 const param = llvm_func.getParam(llvm_arg_i);
1048 llvm_arg_i += 1;1030 llvm_arg_i += 1;
10491031
1050 const param_llvm_ty = try dg.lowerType(param_ty);1032 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));
1052 const int_llvm_ty = dg.context.intType(abi_size * 8);1034 const int_llvm_ty = dg.context.intType(abi_size * 8);
1053 const alignment = @max(1035 const alignment = @max(
1054 param_ty.abiAlignment(target),1036 param_ty.abiAlignment(mod),
1055 dg.object.target_data.abiAlignmentOfType(int_llvm_ty),1037 dg.object.target_data.abiAlignmentOfType(int_llvm_ty),
1056 );1038 );
1057 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);1039 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
...@@ -1060,7 +1042,7 @@ pub const Object = struct {...@@ -1060,7 +1042,7 @@ pub const Object = struct {
10601042
1061 try args.ensureUnusedCapacity(1);1043 try args.ensureUnusedCapacity(1);
10621044
1063 if (isByRef(param_ty)) {1045 if (isByRef(param_ty, mod)) {
1064 args.appendAssumeCapacity(arg_ptr);1046 args.appendAssumeCapacity(arg_ptr);
1065 } else {1047 } else {
1066 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");1048 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
...@@ -1070,15 +1052,15 @@ pub const Object = struct {...@@ -1070,15 +1052,15 @@ pub const Object = struct {
1070 },1052 },
1071 .slice => {1053 .slice => {
1072 assert(!it.byval_attr);1054 assert(!it.byval_attr);
1073 const param_ty = fn_info.param_types[it.zig_index - 1];1055 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1074 const ptr_info = param_ty.ptrInfo().data;1056 const ptr_info = param_ty.ptrInfo(mod);
10751057
1076 if (math.cast(u5, it.zig_index - 1)) |i| {1058 if (math.cast(u5, it.zig_index - 1)) |i| {
1077 if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {1059 if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
1078 dg.addArgAttr(llvm_func, llvm_arg_i, "noalias");1060 dg.addArgAttr(llvm_func, llvm_arg_i, "noalias");
1079 }1061 }
1080 }1062 }
1081 if (param_ty.zigTypeTag() != .Optional) {1063 if (param_ty.zigTypeTag(mod) != .Optional) {
1082 dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");1064 dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
1083 }1065 }
1084 if (!ptr_info.mutable) {1066 if (!ptr_info.mutable) {
...@@ -1087,7 +1069,7 @@ pub const Object = struct {...@@ -1087,7 +1069,7 @@ pub const Object = struct {
1087 if (ptr_info.@"align" != 0) {1069 if (ptr_info.@"align" != 0) {
1088 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align");1070 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align");
1089 } else {1071 } 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);
1091 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align);1073 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align);
1092 }1074 }
1093 const ptr_param = llvm_func.getParam(llvm_arg_i);1075 const ptr_param = llvm_func.getParam(llvm_arg_i);
...@@ -1103,9 +1085,9 @@ pub const Object = struct {...@@ -1103,9 +1085,9 @@ pub const Object = struct {
1103 .multiple_llvm_types => {1085 .multiple_llvm_types => {
1104 assert(!it.byval_attr);1086 assert(!it.byval_attr);
1105 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];1087 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();
1107 const param_llvm_ty = try dg.lowerType(param_ty);1089 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);
1109 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);1091 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
1110 const llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);1092 const llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
1111 for (field_types, 0..) |_, field_i_usize| {1093 for (field_types, 0..) |_, field_i_usize| {
...@@ -1117,7 +1099,7 @@ pub const Object = struct {...@@ -1117,7 +1099,7 @@ pub const Object = struct {
1117 store_inst.setAlignment(target.ptrBitWidth() / 8);1099 store_inst.setAlignment(target.ptrBitWidth() / 8);
1118 }1100 }
11191101
1120 const is_by_ref = isByRef(param_ty);1102 const is_by_ref = isByRef(param_ty, mod);
1121 const loaded = if (is_by_ref) arg_ptr else l: {1103 const loaded = if (is_by_ref) arg_ptr else l: {
1122 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");1104 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
1123 load_inst.setAlignment(param_alignment);1105 load_inst.setAlignment(param_alignment);
...@@ -1134,16 +1116,16 @@ pub const Object = struct {...@@ -1134,16 +1116,16 @@ pub const Object = struct {
1134 args.appendAssumeCapacity(casted);1116 args.appendAssumeCapacity(casted);
1135 },1117 },
1136 .float_array => {1118 .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();
1138 const param_llvm_ty = try dg.lowerType(param_ty);1120 const param_llvm_ty = try dg.lowerType(param_ty);
1139 const param = llvm_func.getParam(llvm_arg_i);1121 const param = llvm_func.getParam(llvm_arg_i);
1140 llvm_arg_i += 1;1122 llvm_arg_i += 1;
11411123
1142 const alignment = param_ty.abiAlignment(target);1124 const alignment = param_ty.abiAlignment(mod);
1143 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);1125 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
1144 _ = builder.buildStore(param, arg_ptr);1126 _ = builder.buildStore(param, arg_ptr);
11451127
1146 if (isByRef(param_ty)) {1128 if (isByRef(param_ty, mod)) {
1147 try args.append(arg_ptr);1129 try args.append(arg_ptr);
1148 } else {1130 } else {
1149 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");1131 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
...@@ -1152,16 +1134,16 @@ pub const Object = struct {...@@ -1152,16 +1134,16 @@ pub const Object = struct {
1152 }1134 }
1153 },1135 },
1154 .i32_array, .i64_array => {1136 .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();
1156 const param_llvm_ty = try dg.lowerType(param_ty);1138 const param_llvm_ty = try dg.lowerType(param_ty);
1157 const param = llvm_func.getParam(llvm_arg_i);1139 const param = llvm_func.getParam(llvm_arg_i);
1158 llvm_arg_i += 1;1140 llvm_arg_i += 1;
11591141
1160 const alignment = param_ty.abiAlignment(target);1142 const alignment = param_ty.abiAlignment(mod);
1161 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);1143 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
1162 _ = builder.buildStore(param, arg_ptr);1144 _ = builder.buildStore(param, arg_ptr);
11631145
1164 if (isByRef(param_ty)) {1146 if (isByRef(param_ty, mod)) {
1165 try args.append(arg_ptr);1147 try args.append(arg_ptr);
1166 } else {1148 } else {
1167 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");1149 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
...@@ -1176,27 +1158,28 @@ pub const Object = struct {...@@ -1176,27 +1158,28 @@ pub const Object = struct {
1176 var di_scope: ?*llvm.DIScope = null;1158 var di_scope: ?*llvm.DIScope = null;
11771159
1178 if (dg.object.di_builder) |dib| {1160 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
1181 const line_number = decl.src_line + 1;1163 const line_number = decl.src_line + 1;
1182 const is_internal_linkage = decl.val.tag() != .extern_fn and1164 const is_internal_linkage = decl.val.getExternFunc(mod) == null and
1183 !module.decl_exports.contains(decl_index);1165 !mod.decl_exports.contains(decl_index);
1184 const noret_bit: c_uint = if (fn_info.return_type.isNoReturn())1166 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
1185 llvm.DIFlags.NoReturn1167 llvm.DIFlags.NoReturn
1186 else1168 else
1187 0;1169 0;
1170 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
1188 const subprogram = dib.createFunction(1171 const subprogram = dib.createFunction(
1189 di_file.?.toScope(),1172 di_file.?.toScope(),
1190 decl.name,1173 mod.intern_pool.stringToSlice(decl.name),
1191 llvm_func.getValueName(),1174 llvm_func.getValueName(),
1192 di_file.?,1175 di_file.?,
1193 line_number,1176 line_number,
1194 try o.lowerDebugType(decl.ty, .full),1177 decl_di_ty,
1195 is_internal_linkage,1178 is_internal_linkage,
1196 true, // is definition1179 true, // is definition
1197 line_number + func.lbrace_line, // scope line1180 line_number + func.lbrace_line, // scope line
1198 llvm.DIFlags.StaticMember | noret_bit,1181 llvm.DIFlags.StaticMember | noret_bit,
1199 module.comp.bin_file.options.optimize_mode != .Debug,1182 mod.comp.bin_file.options.optimize_mode != .Debug,
1200 null, // decl_subprogram1183 null, // decl_subprogram
1201 );1184 );
1202 try dg.object.di_map.put(gpa, decl, subprogram.toNode());1185 try dg.object.di_map.put(gpa, decl, subprogram.toNode());
...@@ -1219,7 +1202,7 @@ pub const Object = struct {...@@ -1219,7 +1202,7 @@ pub const Object = struct {
1219 .func_inst_table = .{},1202 .func_inst_table = .{},
1220 .llvm_func = llvm_func,1203 .llvm_func = llvm_func,
1221 .blocks = .{},1204 .blocks = .{},
1222 .single_threaded = module.comp.bin_file.options.single_threaded,1205 .single_threaded = mod.comp.bin_file.options.single_threaded,
1223 .di_scope = di_scope,1206 .di_scope = di_scope,
1224 .di_file = di_file,1207 .di_file = di_file,
1225 .base_line = dg.decl.src_line,1208 .base_line = dg.decl.src_line,
...@@ -1232,14 +1215,14 @@ pub const Object = struct {...@@ -1232,14 +1215,14 @@ pub const Object = struct {
1232 fg.genBody(air.getMainBody()) catch |err| switch (err) {1215 fg.genBody(air.getMainBody()) catch |err| switch (err) {
1233 error.CodegenFail => {1216 error.CodegenFail => {
1234 decl.analysis = .codegen_failure;1217 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.?);
1236 dg.err_msg = null;1219 dg.err_msg = null;
1237 return;1220 return;
1238 },1221 },
1239 else => |e| return e,1222 else => |e| return e,
1240 };1223 };
12411224
1242 try o.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));1225 try o.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
1243 }1226 }
12441227
1245 pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void {1228 pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void {
...@@ -1275,63 +1258,72 @@ pub const Object = struct {...@@ -1275,63 +1258,72 @@ pub const Object = struct {
12751258
1276 pub fn updateDeclExports(1259 pub fn updateDeclExports(
1277 self: *Object,1260 self: *Object,
1278 module: *Module,1261 mod: *Module,
1279 decl_index: Module.Decl.Index,1262 decl_index: Module.Decl.Index,
1280 exports: []const *Module.Export,1263 exports: []const *Module.Export,
1281 ) !void {1264 ) !void {
1265 const gpa = mod.gpa;
1282 // If the module does not already have the function, we ignore this function call1266 // If the module does not already have the function, we ignore this function call
1283 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.1267 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
1284 const llvm_global = self.decl_map.get(decl_index) orelse return;1268 const llvm_global = self.decl_map.get(decl_index) orelse return;
1285 const decl = module.declPtr(decl_index);1269 const decl = mod.declPtr(decl_index);
1286 if (decl.isExtern()) {1270 if (decl.isExtern(mod)) {
1287 const is_wasm_fn = module.getTarget().isWasm() and try decl.isFunction();1271 var free_decl_name = false;
1288 const mangle_name = is_wasm_fn and1272 const decl_name = decl_name: {
1289 decl.getExternFn().?.lib_name != null and1273 const decl_name = mod.intern_pool.stringToSlice(decl.name);
1290 !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c");1274
1291 const decl_name = if (mangle_name) name: {1275 if (mod.getTarget().isWasm() and try decl.isFunction(mod)) {
1292 const tmp = try std.fmt.allocPrintZ(module.gpa, "{s}|{s}", .{ decl.name, decl.getExternFn().?.lib_name.? });1276 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
1293 break :name tmp.ptr;1277 if (!std.mem.eql(u8, lib_name, "c")) {
1294 } else decl.name;1278 free_decl_name = true;
1295 defer if (mangle_name) module.gpa.free(std.mem.sliceTo(decl_name, 0));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
1297 llvm_global.setValueName(decl_name);1290 llvm_global.setValueName(decl_name);
1298 if (self.getLlvmGlobal(decl_name)) |other_global| {1291 if (self.getLlvmGlobal(decl_name)) |other_global| {
1299 if (other_global != llvm_global) {1292 if (other_global != llvm_global) {
1300 log.debug("updateDeclExports isExtern()=true setValueName({s}) conflict", .{decl.name});1293 try self.extern_collisions.put(gpa, decl_index, {});
1301 try self.extern_collisions.put(module.gpa, decl_index, {});
1302 }1294 }
1303 }1295 }
1304 llvm_global.setUnnamedAddr(.False);1296 llvm_global.setUnnamedAddr(.False);
1305 llvm_global.setLinkage(.External);1297 llvm_global.setLinkage(.External);
1306 if (module.wantDllExports()) llvm_global.setDLLStorageClass(.Default);1298 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
1307 if (self.di_map.get(decl)) |di_node| {1299 if (self.di_map.get(decl)) |di_node| {
1308 if (try decl.isFunction()) {1300 if (try decl.isFunction(mod)) {
1309 const di_func = @ptrCast(*llvm.DISubprogram, di_node);1301 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);
1311 di_func.replaceLinkageName(linkage_name);1303 di_func.replaceLinkageName(linkage_name);
1312 } else {1304 } else {
1313 const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);1305 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);
1315 di_global.replaceLinkageName(linkage_name);1307 di_global.replaceLinkageName(linkage_name);
1316 }1308 }
1317 }1309 }
1318 if (decl.val.castTag(.variable)) |variable| {1310 if (decl.val.getVariable(mod)) |variable| {
1319 if (variable.data.is_threadlocal) {1311 if (variable.is_threadlocal) {
1320 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1312 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1321 } else {1313 } else {
1322 llvm_global.setThreadLocalMode(.NotThreadLocal);1314 llvm_global.setThreadLocalMode(.NotThreadLocal);
1323 }1315 }
1324 if (variable.data.is_weak_linkage) {1316 if (variable.is_weak_linkage) {
1325 llvm_global.setLinkage(.ExternalWeak);1317 llvm_global.setLinkage(.ExternalWeak);
1326 }1318 }
1327 }1319 }
1328 } else if (exports.len != 0) {1320 } 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);
1330 llvm_global.setValueName2(exp_name.ptr, exp_name.len);1322 llvm_global.setValueName2(exp_name.ptr, exp_name.len);
1331 llvm_global.setUnnamedAddr(.False);1323 llvm_global.setUnnamedAddr(.False);
1332 if (module.wantDllExports()) llvm_global.setDLLStorageClass(.DLLExport);1324 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.DLLExport);
1333 if (self.di_map.get(decl)) |di_node| {1325 if (self.di_map.get(decl)) |di_node| {
1334 if (try decl.isFunction()) {1326 if (try decl.isFunction(mod)) {
1335 const di_func = @ptrCast(*llvm.DISubprogram, di_node);1327 const di_func = @ptrCast(*llvm.DISubprogram, di_node);
1336 const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);1328 const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
1337 di_func.replaceLinkageName(linkage_name);1329 di_func.replaceLinkageName(linkage_name);
...@@ -1341,37 +1333,34 @@ pub const Object = struct {...@@ -1341,37 +1333,34 @@ pub const Object = struct {
1341 di_global.replaceLinkageName(linkage_name);1333 di_global.replaceLinkageName(linkage_name);
1342 }1334 }
1343 }1335 }
1344 switch (exports[0].options.linkage) {1336 switch (exports[0].opts.linkage) {
1345 .Internal => unreachable,1337 .Internal => unreachable,
1346 .Strong => llvm_global.setLinkage(.External),1338 .Strong => llvm_global.setLinkage(.External),
1347 .Weak => llvm_global.setLinkage(.WeakODR),1339 .Weak => llvm_global.setLinkage(.WeakODR),
1348 .LinkOnce => llvm_global.setLinkage(.LinkOnceODR),1340 .LinkOnce => llvm_global.setLinkage(.LinkOnceODR),
1349 }1341 }
1350 switch (exports[0].options.visibility) {1342 switch (exports[0].opts.visibility) {
1351 .default => llvm_global.setVisibility(.Default),1343 .default => llvm_global.setVisibility(.Default),
1352 .hidden => llvm_global.setVisibility(.Hidden),1344 .hidden => llvm_global.setVisibility(.Hidden),
1353 .protected => llvm_global.setVisibility(.Protected),1345 .protected => llvm_global.setVisibility(.Protected),
1354 }1346 }
1355 if (exports[0].options.section) |section| {1347 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section| {
1356 const section_z = try module.gpa.dupeZ(u8, section);1348 llvm_global.setSection(section);
1357 defer module.gpa.free(section_z);
1358 llvm_global.setSection(section_z);
1359 }1349 }
1360 if (decl.val.castTag(.variable)) |variable| {1350 if (decl.val.getVariable(mod)) |variable| {
1361 if (variable.data.is_threadlocal) {1351 if (variable.is_threadlocal) {
1362 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1352 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1363 }1353 }
1364 }1354 }
13651355
1366 // If a Decl is exported more than one time (which is rare),1356 // If a Decl is exported more than one time (which is rare),
1367 // we add aliases for all but the first export.1357 // we add aliases for all but the first export.
1368 // TODO LLVM C API does not support deleting aliases. We need to1358 // TODO LLVM C API does not support deleting aliases.
1369 // patch it to support this or figure out how to wrap the C++ API ourselves.1359 // The planned solution to this is https://github.com/ziglang/zig/issues/13265
1370 // Until then we iterate over existing aliases and make them point1360 // Until then we iterate over existing aliases and make them point
1371 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.1361 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
1372 for (exports[1..]) |exp| {1362 for (exports[1..]) |exp| {
1373 const exp_name_z = try module.gpa.dupeZ(u8, exp.options.name);1363 const exp_name_z = mod.intern_pool.stringToSlice(exp.opts.name);
1374 defer module.gpa.free(exp_name_z);
13751364
1376 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {1365 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {
1377 alias.setAliasee(llvm_global);1366 alias.setAliasee(llvm_global);
...@@ -1385,15 +1374,14 @@ pub const Object = struct {...@@ -1385,15 +1374,14 @@ pub const Object = struct {
1385 }1374 }
1386 }1375 }
1387 } else {1376 } else {
1388 const fqn = try decl.getFullyQualifiedName(module);1377 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1389 defer module.gpa.free(fqn);
1390 llvm_global.setValueName2(fqn.ptr, fqn.len);1378 llvm_global.setValueName2(fqn.ptr, fqn.len);
1391 llvm_global.setLinkage(.Internal);1379 llvm_global.setLinkage(.Internal);
1392 if (module.wantDllExports()) llvm_global.setDLLStorageClass(.Default);1380 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
1393 llvm_global.setUnnamedAddr(.True);1381 llvm_global.setUnnamedAddr(.True);
1394 if (decl.val.castTag(.variable)) |variable| {1382 if (decl.val.getVariable(mod)) |variable| {
1395 const single_threaded = module.comp.bin_file.options.single_threaded;1383 const single_threaded = mod.comp.bin_file.options.single_threaded;
1396 if (variable.data.is_threadlocal and !single_threaded) {1384 if (variable.is_threadlocal and !single_threaded) {
1397 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1385 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1398 } else {1386 } else {
1399 llvm_global.setThreadLocalMode(.NotThreadLocal);1387 llvm_global.setThreadLocalMode(.NotThreadLocal);
...@@ -1444,7 +1432,7 @@ pub const Object = struct {...@@ -1444,7 +1432,7 @@ pub const Object = struct {
1444 const gpa = o.gpa;1432 const gpa = o.gpa;
1445 // Be careful not to reference this `gop` variable after any recursive calls1433 // Be careful not to reference this `gop` variable after any recursive calls
1446 // to `lowerDebugType`.1434 // 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());
1448 if (gop.found_existing) {1436 if (gop.found_existing) {
1449 const annotated = gop.value_ptr.*;1437 const annotated = gop.value_ptr.*;
1450 const di_type = annotated.toDIType();1438 const di_type = annotated.toDIType();
...@@ -1457,10 +1445,7 @@ pub const Object = struct {...@@ -1457,10 +1445,7 @@ pub const Object = struct {
1457 };1445 };
1458 return o.lowerDebugTypeImpl(entry, resolve, di_type);1446 return o.lowerDebugTypeImpl(entry, resolve, di_type);
1459 }1447 }
1460 errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .mod = o.module }));1448 errdefer assert(o.di_type_map.orderedRemove(ty.toIntern()));
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());
1464 const entry: Object.DITypeMap.Entry = .{1449 const entry: Object.DITypeMap.Entry = .{
1465 .key_ptr = gop.key_ptr,1450 .key_ptr = gop.key_ptr,
1466 .value_ptr = gop.value_ptr,1451 .value_ptr = gop.value_ptr,
...@@ -1475,18 +1460,19 @@ pub const Object = struct {...@@ -1475,18 +1460,19 @@ pub const Object = struct {
1475 resolve: DebugResolveStatus,1460 resolve: DebugResolveStatus,
1476 opt_fwd_decl: ?*llvm.DIType,1461 opt_fwd_decl: ?*llvm.DIType,
1477 ) Allocator.Error!*llvm.DIType {1462 ) Allocator.Error!*llvm.DIType {
1478 const ty = gop.key_ptr.*;1463 const ty = gop.key_ptr.toType();
1479 const gpa = o.gpa;1464 const gpa = o.gpa;
1480 const target = o.target;1465 const target = o.target;
1481 const dib = o.di_builder.?;1466 const dib = o.di_builder.?;
1482 switch (ty.zigTypeTag()) {1467 const mod = o.module;
1468 switch (ty.zigTypeTag(mod)) {
1483 .Void, .NoReturn => {1469 .Void, .NoReturn => {
1484 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);1470 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
1485 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);1471 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
1486 return di_type;1472 return di_type;
1487 },1473 },
1488 .Int => {1474 .Int => {
1489 const info = ty.intInfo(target);1475 const info = ty.intInfo(mod);
1490 assert(info.bits != 0);1476 assert(info.bits != 0);
1491 const name = try ty.nameAlloc(gpa, o.module);1477 const name = try ty.nameAlloc(gpa, o.module);
1492 defer gpa.free(name);1478 defer gpa.free(name);
...@@ -1494,49 +1480,41 @@ pub const Object = struct {...@@ -1494,49 +1480,41 @@ pub const Object = struct {
1494 .signed => DW.ATE.signed,1480 .signed => DW.ATE.signed,
1495 .unsigned => DW.ATE.unsigned,1481 .unsigned => DW.ATE.unsigned,
1496 };1482 };
1497 const di_bits = ty.abiSize(target) * 8; // lldb cannot handle non-byte sized types1483 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
1498 const di_type = dib.createBasicType(name, di_bits, dwarf_encoding);1484 const di_type = dib.createBasicType(name, di_bits, dwarf_encoding);
1499 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);1485 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
1500 return di_type;1486 return di_type;
1501 },1487 },
1502 .Enum => {1488 .Enum => {
1503 const owner_decl_index = ty.getOwnerDecl();1489 const owner_decl_index = ty.getOwnerDecl(mod);
1504 const owner_decl = o.module.declPtr(owner_decl_index);1490 const owner_decl = o.module.declPtr(owner_decl_index);
15051491
1506 if (!ty.hasRuntimeBitsIgnoreComptime()) {1492 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
1507 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);1493 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
1508 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`1494 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1509 // means we can't use `gop` anymore.1495 // 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));
1511 return enum_di_ty;1497 return enum_di_ty;
1512 }1498 }
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);
1517 defer gpa.free(enumerators);1504 defer gpa.free(enumerators);
15181505
1519 var buf_field_index: Value.Payload.U32 = .{1506 const int_ty = enum_type.tag_ty.toType();
1520 .base = .{ .tag = .enum_field_index },1507 const int_info = ty.intInfo(mod);
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);
1528 assert(int_info.bits != 0);1508 assert(int_info.bits != 0);
15291509
1530 for (field_names, 0..) |field_name, i| {1510 for (enum_type.names, 0..) |field_name_ip, i| {
1531 const field_name_z = try gpa.dupeZ(u8, field_name);1511 const field_name_z = ip.stringToSlice(field_name_ip);
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);
15371512
1538 var bigint_space: Value.BigIntSpace = undefined;1513 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
1541 if (bigint.limbs.len == 1) {1519 if (bigint.limbs.len == 1) {
1542 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);1520 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);
...@@ -1555,7 +1533,7 @@ pub const Object = struct {...@@ -1555,7 +1533,7 @@ pub const Object = struct {
1555 @panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds");1533 @panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds");
1556 }1534 }
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);
1559 const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);1537 const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
15601538
1561 const name = try ty.nameAlloc(gpa, o.module);1539 const name = try ty.nameAlloc(gpa, o.module);
...@@ -1566,15 +1544,15 @@ pub const Object = struct {...@@ -1566,15 +1544,15 @@ pub const Object = struct {
1566 name,1544 name,
1567 di_file,1545 di_file,
1568 owner_decl.src_node + 1,1546 owner_decl.src_node + 1,
1569 ty.abiSize(target) * 8,1547 ty.abiSize(mod) * 8,
1570 ty.abiAlignment(target) * 8,1548 ty.abiAlignment(mod) * 8,
1571 enumerators.ptr,1549 enumerators.ptr,
1572 @intCast(c_int, enumerators.len),1550 @intCast(c_int, enumerators.len),
1573 try o.lowerDebugType(int_ty, .full),1551 try o.lowerDebugType(int_ty, .full),
1574 "",1552 "",
1575 );1553 );
1576 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1554 // 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));
1578 return enum_di_ty;1556 return enum_di_ty;
1579 },1557 },
1580 .Float => {1558 .Float => {
...@@ -1593,49 +1571,40 @@ pub const Object = struct {...@@ -1593,49 +1571,40 @@ pub const Object = struct {
1593 },1571 },
1594 .Pointer => {1572 .Pointer => {
1595 // Normalize everything that the debug info does not represent.1573 // Normalize everything that the debug info does not represent.
1596 const ptr_info = ty.ptrInfo().data;1574 const ptr_info = Type.ptrInfoIp(&mod.intern_pool, ty.toIntern());
15971575
1598 if (ptr_info.sentinel != null or1576 if (ptr_info.sentinel != .none or
1599 ptr_info.@"addrspace" != .generic or1577 ptr_info.flags.address_space != .generic or
1600 ptr_info.bit_offset != 0 or1578 ptr_info.packed_offset.bit_offset != 0 or
1601 ptr_info.host_size != 0 or1579 ptr_info.packed_offset.host_size != 0 or
1602 ptr_info.vector_index != .none or1580 ptr_info.flags.vector_index != .none or
1603 ptr_info.@"allowzero" or1581 ptr_info.flags.is_allowzero or
1604 !ptr_info.mutable or1582 ptr_info.flags.is_const or
1605 ptr_info.@"volatile" or1583 ptr_info.flags.is_volatile or
1606 ptr_info.size == .Many or ptr_info.size == .C or1584 ptr_info.flags.size == .Many or ptr_info.flags.size == .C or
1607 !ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime())1585 !ptr_info.child.toType().hasRuntimeBitsIgnoreComptime(mod))
1608 {1586 {
1609 var payload: Type.Payload.Pointer = .{1587 const bland_ptr_ty = try mod.ptrType(.{
1610 .data = .{1588 .child = if (!ptr_info.child.toType().hasRuntimeBitsIgnoreComptime(mod))
1611 .pointee_type = ptr_info.pointee_type,1589 .anyopaque_type
1612 .sentinel = null,1590 else
1613 .@"align" = ptr_info.@"align",1591 ptr_info.child,
1614 .@"addrspace" = .generic,1592 .flags = .{
1615 .bit_offset = 0,1593 .alignment = ptr_info.flags.alignment,
1616 .host_size = 0,1594 .size = switch (ptr_info.flags.size) {
1617 .@"allowzero" = false,
1618 .mutable = true,
1619 .@"volatile" = false,
1620 .size = switch (ptr_info.size) {
1621 .Many, .C, .One => .One,1595 .Many, .C, .One => .One,
1622 .Slice => .Slice,1596 .Slice => .Slice,
1623 },1597 },
1624 },1598 },
1625 };1599 });
1626 if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) {
1627 payload.data.pointee_type = Type.anyopaque;
1628 }
1629 const bland_ptr_ty = Type.initPayload(&payload.base);
1630 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);1600 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
1631 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1601 // 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));
1633 return ptr_di_ty;1603 return ptr_di_ty;
1634 }1604 }
16351605
1636 if (ty.isSlice()) {1606 if (ty.isSlice(mod)) {
1637 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1607 const ptr_ty = ty.slicePtrFieldType(mod);
1638 const ptr_ty = ty.slicePtrFieldType(&buf);
1639 const len_ty = Type.usize;1608 const len_ty = Type.usize;
16401609
1641 const name = try ty.nameAlloc(gpa, o.module);1610 const name = try ty.nameAlloc(gpa, o.module);
...@@ -1657,10 +1626,10 @@ pub const Object = struct {...@@ -1657,10 +1626,10 @@ pub const Object = struct {
1657 break :blk fwd_decl;1626 break :blk fwd_decl;
1658 };1627 };
16591628
1660 const ptr_size = ptr_ty.abiSize(target);1629 const ptr_size = ptr_ty.abiSize(mod);
1661 const ptr_align = ptr_ty.abiAlignment(target);1630 const ptr_align = ptr_ty.abiAlignment(mod);
1662 const len_size = len_ty.abiSize(target);1631 const len_size = len_ty.abiSize(mod);
1663 const len_align = len_ty.abiAlignment(target);1632 const len_align = len_ty.abiAlignment(mod);
16641633
1665 var offset: u64 = 0;1634 var offset: u64 = 0;
1666 offset += ptr_size;1635 offset += ptr_size;
...@@ -1697,8 +1666,8 @@ pub const Object = struct {...@@ -1697,8 +1666,8 @@ pub const Object = struct {
1697 name.ptr,1666 name.ptr,
1698 di_file,1667 di_file,
1699 line,1668 line,
1700 ty.abiSize(target) * 8, // size in bits1669 ty.abiSize(mod) * 8, // size in bits
1701 ty.abiAlignment(target) * 8, // align in bits1670 ty.abiAlignment(mod) * 8, // align in bits
1702 0, // flags1671 0, // flags
1703 null, // derived from1672 null, // derived from
1704 &fields,1673 &fields,
...@@ -1709,65 +1678,65 @@ pub const Object = struct {...@@ -1709,65 +1678,65 @@ pub const Object = struct {
1709 );1678 );
1710 dib.replaceTemporary(fwd_decl, full_di_ty);1679 dib.replaceTemporary(fwd_decl, full_di_ty);
1711 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1680 // 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));
1713 return full_di_ty;1682 return full_di_ty;
1714 }1683 }
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);
1717 const name = try ty.nameAlloc(gpa, o.module);1686 const name = try ty.nameAlloc(gpa, o.module);
1718 defer gpa.free(name);1687 defer gpa.free(name);
1719 const ptr_di_ty = dib.createPointerType(1688 const ptr_di_ty = dib.createPointerType(
1720 elem_di_ty,1689 elem_di_ty,
1721 target.ptrBitWidth(),1690 target.ptrBitWidth(),
1722 ty.ptrAlignment(target) * 8,1691 ty.ptrAlignment(mod) * 8,
1723 name,1692 name,
1724 );1693 );
1725 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1694 // 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));
1727 return ptr_di_ty;1696 return ptr_di_ty;
1728 },1697 },
1729 .Opaque => {1698 .Opaque => {
1730 if (ty.tag() == .anyopaque) {1699 if (ty.toIntern() == .anyopaque_type) {
1731 const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);1700 const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);
1732 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);1701 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
1733 return di_ty;1702 return di_ty;
1734 }1703 }
1735 const name = try ty.nameAlloc(gpa, o.module);1704 const name = try ty.nameAlloc(gpa, o.module);
1736 defer gpa.free(name);1705 defer gpa.free(name);
1737 const owner_decl_index = ty.getOwnerDecl();1706 const owner_decl_index = ty.getOwnerDecl(mod);
1738 const owner_decl = o.module.declPtr(owner_decl_index);1707 const owner_decl = o.module.declPtr(owner_decl_index);
1739 const opaque_di_ty = dib.createForwardDeclType(1708 const opaque_di_ty = dib.createForwardDeclType(
1740 DW.TAG.structure_type,1709 DW.TAG.structure_type,
1741 name,1710 name,
1742 try o.namespaceToDebugScope(owner_decl.src_namespace),1711 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),
1744 owner_decl.src_node + 1,1713 owner_decl.src_node + 1,
1745 );1714 );
1746 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`1715 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`
1747 // means we can't use `gop` anymore.1716 // 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));
1749 return opaque_di_ty;1718 return opaque_di_ty;
1750 },1719 },
1751 .Array => {1720 .Array => {
1752 const array_di_ty = dib.createArrayType(1721 const array_di_ty = dib.createArrayType(
1753 ty.abiSize(target) * 8,1722 ty.abiSize(mod) * 8,
1754 ty.abiAlignment(target) * 8,1723 ty.abiAlignment(mod) * 8,
1755 try o.lowerDebugType(ty.childType(), .full),1724 try o.lowerDebugType(ty.childType(mod), .full),
1756 @intCast(c_int, ty.arrayLen()),1725 @intCast(c_int, ty.arrayLen(mod)),
1757 );1726 );
1758 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1727 // 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));
1760 return array_di_ty;1729 return array_di_ty;
1761 },1730 },
1762 .Vector => {1731 .Vector => {
1763 const elem_ty = ty.elemType2();1732 const elem_ty = ty.elemType2(mod);
1764 // Vector elements cannot be padded since that would make1733 // Vector elements cannot be padded since that would make
1765 // @bitSizOf(elem) * len > @bitSizOf(vec).1734 // @bitSizOf(elem) * len > @bitSizOf(vec).
1766 // Neither gdb nor lldb seem to be able to display non-byte sized1735 // Neither gdb nor lldb seem to be able to display non-byte sized
1767 // vectors properly.1736 // vectors properly.
1768 const elem_di_type = switch (elem_ty.zigTypeTag()) {1737 const elem_di_type = switch (elem_ty.zigTypeTag(mod)) {
1769 .Int => blk: {1738 .Int => blk: {
1770 const info = elem_ty.intInfo(target);1739 const info = elem_ty.intInfo(mod);
1771 assert(info.bits != 0);1740 assert(info.bits != 0);
1772 const name = try ty.nameAlloc(gpa, o.module);1741 const name = try ty.nameAlloc(gpa, o.module);
1773 defer gpa.free(name);1742 defer gpa.free(name);
...@@ -1778,34 +1747,33 @@ pub const Object = struct {...@@ -1778,34 +1747,33 @@ pub const Object = struct {
1778 break :blk dib.createBasicType(name, info.bits, dwarf_encoding);1747 break :blk dib.createBasicType(name, info.bits, dwarf_encoding);
1779 },1748 },
1780 .Bool => dib.createBasicType("bool", 1, DW.ATE.boolean),1749 .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),
1782 };1751 };
17831752
1784 const vector_di_ty = dib.createVectorType(1753 const vector_di_ty = dib.createVectorType(
1785 ty.abiSize(target) * 8,1754 ty.abiSize(mod) * 8,
1786 ty.abiAlignment(target) * 8,1755 ty.abiAlignment(mod) * 8,
1787 elem_di_type,1756 elem_di_type,
1788 ty.vectorLen(),1757 ty.vectorLen(mod),
1789 );1758 );
1790 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1759 // 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));
1792 return vector_di_ty;1761 return vector_di_ty;
1793 },1762 },
1794 .Optional => {1763 .Optional => {
1795 const name = try ty.nameAlloc(gpa, o.module);1764 const name = try ty.nameAlloc(gpa, o.module);
1796 defer gpa.free(name);1765 defer gpa.free(name);
1797 var buf: Type.Payload.ElemType = undefined;1766 const child_ty = ty.optionalChild(mod);
1798 const child_ty = ty.optionalChild(&buf);1767 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1799 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
1800 const di_bits = 8; // lldb cannot handle non-byte sized types1768 const di_bits = 8; // lldb cannot handle non-byte sized types
1801 const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean);1769 const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean);
1802 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);1770 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
1803 return di_ty;1771 return di_ty;
1804 }1772 }
1805 if (ty.optionalReprIsPayload()) {1773 if (ty.optionalReprIsPayload(mod)) {
1806 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);1774 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);
1807 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1775 // 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));
1809 return ptr_di_ty;1777 return ptr_di_ty;
1810 }1778 }
18111779
...@@ -1826,10 +1794,10 @@ pub const Object = struct {...@@ -1826,10 +1794,10 @@ pub const Object = struct {
1826 };1794 };
18271795
1828 const non_null_ty = Type.u8;1796 const non_null_ty = Type.u8;
1829 const payload_size = child_ty.abiSize(target);1797 const payload_size = child_ty.abiSize(mod);
1830 const payload_align = child_ty.abiAlignment(target);1798 const payload_align = child_ty.abiAlignment(mod);
1831 const non_null_size = non_null_ty.abiSize(target);1799 const non_null_size = non_null_ty.abiSize(mod);
1832 const non_null_align = non_null_ty.abiAlignment(target);1800 const non_null_align = non_null_ty.abiAlignment(mod);
18331801
1834 var offset: u64 = 0;1802 var offset: u64 = 0;
1835 offset += payload_size;1803 offset += payload_size;
...@@ -1866,8 +1834,8 @@ pub const Object = struct {...@@ -1866,8 +1834,8 @@ pub const Object = struct {
1866 name.ptr,1834 name.ptr,
1867 di_file,1835 di_file,
1868 line,1836 line,
1869 ty.abiSize(target) * 8, // size in bits1837 ty.abiSize(mod) * 8, // size in bits
1870 ty.abiAlignment(target) * 8, // align in bits1838 ty.abiAlignment(mod) * 8, // align in bits
1871 0, // flags1839 0, // flags
1872 null, // derived from1840 null, // derived from
1873 &fields,1841 &fields,
...@@ -1878,15 +1846,15 @@ pub const Object = struct {...@@ -1878,15 +1846,15 @@ pub const Object = struct {
1878 );1846 );
1879 dib.replaceTemporary(fwd_decl, full_di_ty);1847 dib.replaceTemporary(fwd_decl, full_di_ty);
1880 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1848 // 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));
1882 return full_di_ty;1850 return full_di_ty;
1883 },1851 },
1884 .ErrorUnion => {1852 .ErrorUnion => {
1885 const payload_ty = ty.errorUnionPayload();1853 const payload_ty = ty.errorUnionPayload(mod);
1886 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1854 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1887 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);1855 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);
1888 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1856 // 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));
1890 return err_set_di_ty;1858 return err_set_di_ty;
1891 }1859 }
1892 const name = try ty.nameAlloc(gpa, o.module);1860 const name = try ty.nameAlloc(gpa, o.module);
...@@ -1907,10 +1875,10 @@ pub const Object = struct {...@@ -1907,10 +1875,10 @@ pub const Object = struct {
1907 break :blk fwd_decl;1875 break :blk fwd_decl;
1908 };1876 };
19091877
1910 const error_size = Type.anyerror.abiSize(target);1878 const error_size = Type.anyerror.abiSize(mod);
1911 const error_align = Type.anyerror.abiAlignment(target);1879 const error_align = Type.anyerror.abiAlignment(mod);
1912 const payload_size = payload_ty.abiSize(target);1880 const payload_size = payload_ty.abiSize(mod);
1913 const payload_align = payload_ty.abiAlignment(target);1881 const payload_align = payload_ty.abiAlignment(mod);
19141882
1915 var error_index: u32 = undefined;1883 var error_index: u32 = undefined;
1916 var payload_index: u32 = undefined;1884 var payload_index: u32 = undefined;
...@@ -1957,8 +1925,8 @@ pub const Object = struct {...@@ -1957,8 +1925,8 @@ pub const Object = struct {
1957 name.ptr,1925 name.ptr,
1958 di_file,1926 di_file,
1959 line,1927 line,
1960 ty.abiSize(target) * 8, // size in bits1928 ty.abiSize(mod) * 8, // size in bits
1961 ty.abiAlignment(target) * 8, // align in bits1929 ty.abiAlignment(mod) * 8, // align in bits
1962 0, // flags1930 0, // flags
1963 null, // derived from1931 null, // derived from
1964 &fields,1932 &fields,
...@@ -1969,7 +1937,7 @@ pub const Object = struct {...@@ -1969,7 +1937,7 @@ pub const Object = struct {
1969 );1937 );
1970 dib.replaceTemporary(fwd_decl, full_di_ty);1938 dib.replaceTemporary(fwd_decl, full_di_ty);
1971 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1939 // 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));
1973 return full_di_ty;1941 return full_di_ty;
1974 },1942 },
1975 .ErrorSet => {1943 .ErrorSet => {
...@@ -1984,16 +1952,15 @@ pub const Object = struct {...@@ -1984,16 +1952,15 @@ pub const Object = struct {
1984 const name = try ty.nameAlloc(gpa, o.module);1952 const name = try ty.nameAlloc(gpa, o.module);
1985 defer gpa.free(name);1953 defer gpa.free(name);
19861954
1987 if (ty.castTag(.@"struct")) |payload| {1955 if (mod.typeToStruct(ty)) |struct_obj| {
1988 const struct_obj = payload.data;
1989 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {1956 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {
1990 assert(struct_obj.haveLayout());1957 assert(struct_obj.haveLayout());
1991 const info = struct_obj.backing_int_ty.intInfo(target);1958 const info = struct_obj.backing_int_ty.intInfo(mod);
1992 const dwarf_encoding: c_uint = switch (info.signedness) {1959 const dwarf_encoding: c_uint = switch (info.signedness) {
1993 .signed => DW.ATE.signed,1960 .signed => DW.ATE.signed,
1994 .unsigned => DW.ATE.unsigned,1961 .unsigned => DW.ATE.unsigned,
1995 };1962 };
1996 const di_bits = ty.abiSize(target) * 8; // lldb cannot handle non-byte sized types1963 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
1997 const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding);1964 const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding);
1998 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);1965 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
1999 return di_ty;1966 return di_ty;
...@@ -2013,98 +1980,98 @@ pub const Object = struct {...@@ -2013,98 +1980,98 @@ pub const Object = struct {
2013 break :blk fwd_decl;1980 break :blk fwd_decl;
2014 };1981 };
20151982
2016 if (ty.isSimpleTupleOrAnonStruct()) {1983 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2017 const tuple = ty.tupleFields();1984 .anon_struct_type => |tuple| {
20181985 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2019 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};1986 defer di_fields.deinit(gpa);
2020 defer di_fields.deinit(gpa);1987
20211988 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
2022 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);1989
20231990 comptime assert(struct_layout_version == 2);
2024 comptime assert(struct_layout_version == 2);1991 var offset: u64 = 0;
2025 var offset: u64 = 0;1992
20261993 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
2027 for (tuple.types, 0..) |field_ty, i| {1994 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
2028 const field_val = tuple.values[i];1995
2029 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;1996 const field_size = field_ty.toType().abiSize(mod);
20301997 const field_align = field_ty.toType().abiAlignment(mod);
2031 const field_size = field_ty.abiSize(target);1998 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2032 const field_align = field_ty.abiAlignment(target);1999 offset = field_offset + field_size;
2033 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);2000
2034 offset = field_offset + field_size;2001 const field_name = if (tuple.names.len != 0)
20352002 mod.intern_pool.stringToSlice(tuple.names[i])
2036 const field_name = if (ty.castTag(.anon_struct)) |payload|2003 else
2037 try gpa.dupeZ(u8, payload.data.names[i])2004 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2038 else2005 defer if (tuple.names.len == 0) gpa.free(field_name);
2039 try std.fmt.allocPrintZ(gpa, "{d}", .{i});2006
2040 defer gpa.free(field_name);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(2020 const full_di_ty = dib.createStructType(
2043 fwd_decl.toScope(),2021 compile_unit_scope,
2044 field_name,2022 name.ptr,
2045 null, // file2023 null, // file
2046 0, // line2024 0, // line
2047 field_size * 8, // size in bits2025 ty.abiSize(mod) * 8, // size in bits
2048 field_align * 8, // align in bits2026 ty.abiAlignment(mod) * 8, // align in bits
2049 field_offset * 8, // offset in bits
2050 0, // flags2027 0, // flags
2051 try o.lowerDebugType(field_ty, .full),2028 null, // derived from
2052 ));2029 di_fields.items.ptr,
2053 }2030 @intCast(c_int, di_fields.items.len),
20542031 0, // run time lang
2055 const full_di_ty = dib.createStructType(2032 null, // vtable holder
2056 compile_unit_scope,2033 "", // unique id
2057 name.ptr,2034 );
2058 null, // file2035 dib.replaceTemporary(fwd_decl, full_di_ty);
2059 0, // line2036 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2060 ty.abiSize(target) * 8, // size in bits2037 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2061 ty.abiAlignment(target) * 8, // align in bits2038 return full_di_ty;
2062 0, // flags2039 },
2063 null, // derived from2040 .struct_type => |struct_type| s: {
2064 di_fields.items.ptr,2041 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
2065 @intCast(c_int, di_fields.items.len),2042
2066 0, // run time lang2043 if (!struct_obj.haveFieldTypes()) {
2067 null, // vtable holder2044 // This can happen if a struct type makes it all the way to
2068 "", // unique id2045 // flush() without ever being instantiated or referenced (even
2069 );2046 // via pointer). The only reason we are hearing about it now is
2070 dib.replaceTemporary(fwd_decl, full_di_ty);2047 // that it is being used as a namespace to put other debug types
2071 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2048 // into. Therefore we can satisfy this by making an empty namespace,
2072 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });2049 // rather than changing the frontend to unnecessarily resolve the
2073 return full_di_ty;2050 // struct field types.
2074 }2051 const owner_decl_index = ty.getOwnerDecl(mod);
20752052 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2076 if (ty.castTag(.@"struct")) |payload| {2053 dib.replaceTemporary(fwd_decl, struct_di_ty);
2077 const struct_obj = payload.data;2054 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2078 if (!struct_obj.haveFieldTypes()) {2055 // means we can't use `gop` anymore.
2079 // This can happen if a struct type makes it all the way to2056 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2080 // flush() without ever being instantiated or referenced (even2057 return struct_di_ty;
2081 // via pointer). The only reason we are hearing about it now is2058 }
2082 // that it is being used as a namespace to put other debug types2059 },
2083 // into. Therefore we can satisfy this by making an empty namespace,2060 else => {},
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 }
2094 }2061 }
20952062
2096 if (!ty.hasRuntimeBitsIgnoreComptime()) {2063 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
2097 const owner_decl_index = ty.getOwnerDecl();2064 const owner_decl_index = ty.getOwnerDecl(mod);
2098 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2065 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2099 dib.replaceTemporary(fwd_decl, struct_di_ty);2066 dib.replaceTemporary(fwd_decl, struct_di_ty);
2100 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2067 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2101 // means we can't use `gop` anymore.2068 // 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));
2103 return struct_di_ty;2070 return struct_di_ty;
2104 }2071 }
21052072
2106 const fields = ty.structFields();2073 const fields = ty.structFields(mod);
2107 const layout = ty.containerLayout();2074 const layout = ty.containerLayout(mod);
21082075
2109 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2076 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2110 defer di_fields.deinit(gpa);2077 defer di_fields.deinit(gpa);
...@@ -2114,16 +2081,15 @@ pub const Object = struct {...@@ -2114,16 +2081,15 @@ pub const Object = struct {
2114 comptime assert(struct_layout_version == 2);2081 comptime assert(struct_layout_version == 2);
2115 var offset: u64 = 0;2082 var offset: u64 = 0;
21162083
2117 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator();2084 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);
2118 while (it.next()) |field_and_index| {2085 while (it.next()) |field_and_index| {
2119 const field = field_and_index.field;2086 const field = field_and_index.field;
2120 const field_size = field.ty.abiSize(target);2087 const field_size = field.ty.abiSize(mod);
2121 const field_align = field.alignment(target, layout);2088 const field_align = field.alignment(mod, layout);
2122 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);2089 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2123 offset = field_offset + field_size;2090 offset = field_offset + field_size;
21242091
2125 const field_name = try gpa.dupeZ(u8, fields.keys()[field_and_index.index]);2092 const field_name = mod.intern_pool.stringToSlice(fields.keys()[field_and_index.index]);
2126 defer gpa.free(field_name);
21272093
2128 try di_fields.append(gpa, dib.createMemberType(2094 try di_fields.append(gpa, dib.createMemberType(
2129 fwd_decl.toScope(),2095 fwd_decl.toScope(),
...@@ -2143,8 +2109,8 @@ pub const Object = struct {...@@ -2143,8 +2109,8 @@ pub const Object = struct {
2143 name.ptr,2109 name.ptr,
2144 null, // file2110 null, // file
2145 0, // line2111 0, // line
2146 ty.abiSize(target) * 8, // size in bits2112 ty.abiSize(mod) * 8, // size in bits
2147 ty.abiAlignment(target) * 8, // align in bits2113 ty.abiAlignment(mod) * 8, // align in bits
2148 0, // flags2114 0, // flags
2149 null, // derived from2115 null, // derived from
2150 di_fields.items.ptr,2116 di_fields.items.ptr,
...@@ -2155,12 +2121,12 @@ pub const Object = struct {...@@ -2155,12 +2121,12 @@ pub const Object = struct {
2155 );2121 );
2156 dib.replaceTemporary(fwd_decl, full_di_ty);2122 dib.replaceTemporary(fwd_decl, full_di_ty);
2157 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2123 // 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));
2159 return full_di_ty;2125 return full_di_ty;
2160 },2126 },
2161 .Union => {2127 .Union => {
2162 const compile_unit_scope = o.di_compile_unit.?.toScope();2128 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
2165 const name = try ty.nameAlloc(gpa, o.module);2131 const name = try ty.nameAlloc(gpa, o.module);
2166 defer gpa.free(name);2132 defer gpa.free(name);
...@@ -2178,17 +2144,17 @@ pub const Object = struct {...@@ -2178,17 +2144,17 @@ pub const Object = struct {
2178 break :blk fwd_decl;2144 break :blk fwd_decl;
2179 };2145 };
21802146
2181 const union_obj = ty.cast(Type.Payload.Union).?.data;2147 const union_obj = mod.typeToUnion(ty).?;
2182 if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime()) {2148 if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime(mod)) {
2183 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2149 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2184 dib.replaceTemporary(fwd_decl, union_di_ty);2150 dib.replaceTemporary(fwd_decl, union_di_ty);
2185 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2151 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2186 // means we can't use `gop` anymore.2152 // 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));
2188 return union_di_ty;2154 return union_di_ty;
2189 }2155 }
21902156
2191 const layout = ty.unionGetLayout(target);2157 const layout = ty.unionGetLayout(mod);
21922158
2193 if (layout.payload_size == 0) {2159 if (layout.payload_size == 0) {
2194 const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);2160 const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);
...@@ -2198,8 +2164,8 @@ pub const Object = struct {...@@ -2198,8 +2164,8 @@ pub const Object = struct {
2198 name.ptr,2164 name.ptr,
2199 null, // file2165 null, // file
2200 0, // line2166 0, // line
2201 ty.abiSize(target) * 8, // size in bits2167 ty.abiSize(mod) * 8, // size in bits
2202 ty.abiAlignment(target) * 8, // align in bits2168 ty.abiAlignment(mod) * 8, // align in bits
2203 0, // flags2169 0, // flags
2204 null, // derived from2170 null, // derived from
2205 &di_fields,2171 &di_fields,
...@@ -2211,7 +2177,7 @@ pub const Object = struct {...@@ -2211,7 +2177,7 @@ pub const Object = struct {
2211 dib.replaceTemporary(fwd_decl, full_di_ty);2177 dib.replaceTemporary(fwd_decl, full_di_ty);
2212 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2178 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2213 // means we can't use `gop` anymore.2179 // 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));
2215 return full_di_ty;2181 return full_di_ty;
2216 }2182 }
22172183
...@@ -2225,24 +2191,22 @@ pub const Object = struct {...@@ -2225,24 +2191,22 @@ pub const Object = struct {
2225 const field_name = kv.key_ptr.*;2191 const field_name = kv.key_ptr.*;
2226 const field = kv.value_ptr.*;2192 const field = kv.value_ptr.*;
22272193
2228 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;2194 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
2229
2230 const field_size = field.ty.abiSize(target);
2231 const field_align = field.normalAlignment(target);
22322195
2233 const field_name_copy = try gpa.dupeZ(u8, field_name);2196 const field_size = field.ty.abiSize(mod);
2234 defer gpa.free(field_name_copy);2197 const field_align = field.normalAlignment(mod);
22352198
2199 const field_di_ty = try o.lowerDebugType(field.ty, .full);
2236 di_fields.appendAssumeCapacity(dib.createMemberType(2200 di_fields.appendAssumeCapacity(dib.createMemberType(
2237 fwd_decl.toScope(),2201 fwd_decl.toScope(),
2238 field_name_copy,2202 mod.intern_pool.stringToSlice(field_name),
2239 null, // file2203 null, // file
2240 0, // line2204 0, // line
2241 field_size * 8, // size in bits2205 field_size * 8, // size in bits
2242 field_align * 8, // align in bits2206 field_align * 8, // align in bits
2243 0, // offset in bits2207 0, // offset in bits
2244 0, // flags2208 0, // flags
2245 try o.lowerDebugType(field.ty, .full),2209 field_di_ty,
2246 ));2210 ));
2247 }2211 }
22482212
...@@ -2258,8 +2222,8 @@ pub const Object = struct {...@@ -2258,8 +2222,8 @@ pub const Object = struct {
2258 union_name.ptr,2222 union_name.ptr,
2259 null, // file2223 null, // file
2260 0, // line2224 0, // line
2261 ty.abiSize(target) * 8, // size in bits2225 ty.abiSize(mod) * 8, // size in bits
2262 ty.abiAlignment(target) * 8, // align in bits2226 ty.abiAlignment(mod) * 8, // align in bits
2263 0, // flags2227 0, // flags
2264 di_fields.items.ptr,2228 di_fields.items.ptr,
2265 @intCast(c_int, di_fields.items.len),2229 @intCast(c_int, di_fields.items.len),
...@@ -2270,7 +2234,7 @@ pub const Object = struct {...@@ -2270,7 +2234,7 @@ pub const Object = struct {
2270 if (layout.tag_size == 0) {2234 if (layout.tag_size == 0) {
2271 dib.replaceTemporary(fwd_decl, union_di_ty);2235 dib.replaceTemporary(fwd_decl, union_di_ty);
2272 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2236 // 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));
2274 return union_di_ty;2238 return union_di_ty;
2275 }2239 }
22762240
...@@ -2319,8 +2283,8 @@ pub const Object = struct {...@@ -2319,8 +2283,8 @@ pub const Object = struct {
2319 name.ptr,2283 name.ptr,
2320 null, // file2284 null, // file
2321 0, // line2285 0, // line
2322 ty.abiSize(target) * 8, // size in bits2286 ty.abiSize(mod) * 8, // size in bits
2323 ty.abiAlignment(target) * 8, // align in bits2287 ty.abiAlignment(mod) * 8, // align in bits
2324 0, // flags2288 0, // flags
2325 null, // derived from2289 null, // derived from
2326 &full_di_fields,2290 &full_di_fields,
...@@ -2331,53 +2295,42 @@ pub const Object = struct {...@@ -2331,53 +2295,42 @@ pub const Object = struct {
2331 );2295 );
2332 dib.replaceTemporary(fwd_decl, full_di_ty);2296 dib.replaceTemporary(fwd_decl, full_di_ty);
2333 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2297 // 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));
2335 return full_di_ty;2299 return full_di_ty;
2336 },2300 },
2337 .Fn => {2301 .Fn => {
2338 const fn_info = ty.fnInfo();2302 const fn_info = mod.typeToFunc(ty).?;
23392303
2340 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);2304 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);
2341 defer param_di_types.deinit();2305 defer param_di_types.deinit();
23422306
2343 // Return type goes first.2307 // Return type goes first.
2344 if (fn_info.return_type.hasRuntimeBitsIgnoreComptime()) {2308 if (fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
2345 const sret = firstParamSRet(fn_info, target);2309 const sret = firstParamSRet(fn_info, mod);
2346 const di_ret_ty = if (sret) Type.void else fn_info.return_type;2310 const di_ret_ty = if (sret) Type.void else fn_info.return_type.toType();
2347 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));2311 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));
23482312
2349 if (sret) {2313 if (sret) {
2350 var ptr_ty_payload: Type.Payload.ElemType = .{2314 const ptr_ty = try mod.singleMutPtrType(fn_info.return_type.toType());
2351 .base = .{ .tag = .single_mut_pointer },
2352 .data = fn_info.return_type,
2353 };
2354 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2355 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));2315 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2356 }2316 }
2357 } else {2317 } else {
2358 try param_di_types.append(try o.lowerDebugType(Type.void, .full));2318 try param_di_types.append(try o.lowerDebugType(Type.void, .full));
2359 }2319 }
23602320
2361 if (fn_info.return_type.isError() and2321 if (fn_info.return_type.toType().isError(mod) and
2362 o.module.comp.bin_file.options.error_return_tracing)2322 o.module.comp.bin_file.options.error_return_tracing)
2363 {2323 {
2364 var ptr_ty_payload: Type.Payload.ElemType = .{2324 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
2365 .base = .{ .tag = .single_mut_pointer },
2366 .data = o.getStackTraceType(),
2367 };
2368 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2369 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));2325 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2370 }2326 }
23712327
2372 for (fn_info.param_types) |param_ty| {2328 for (0..mod.typeToFunc(ty).?.param_types.len) |i| {
2373 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;2329 const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();
2330 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
23742331
2375 if (isByRef(param_ty)) {2332 if (isByRef(param_ty, mod)) {
2376 var ptr_ty_payload: Type.Payload.ElemType = .{2333 const ptr_ty = try mod.singleMutPtrType(param_ty);
2377 .base = .{ .tag = .single_mut_pointer },
2378 .data = param_ty,
2379 };
2380 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2381 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));2334 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2382 } else {2335 } else {
2383 try param_di_types.append(try o.lowerDebugType(param_ty, .full));2336 try param_di_types.append(try o.lowerDebugType(param_ty, .full));
...@@ -2390,7 +2343,7 @@ pub const Object = struct {...@@ -2390,7 +2343,7 @@ pub const Object = struct {
2390 0,2343 0,
2391 );2344 );
2392 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2345 // 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));
2394 return fn_di_ty;2347 return fn_di_ty;
2395 },2348 },
2396 .ComptimeInt => unreachable,2349 .ComptimeInt => unreachable,
...@@ -2405,8 +2358,10 @@ pub const Object = struct {...@@ -2405,8 +2358,10 @@ pub const Object = struct {
2405 }2358 }
2406 }2359 }
24072360
2408 fn namespaceToDebugScope(o: *Object, namespace: *const Module.Namespace) !*llvm.DIScope {2361 fn namespaceToDebugScope(o: *Object, namespace_index: Module.Namespace.Index) !*llvm.DIScope {
2409 if (namespace.parent == null) {2362 const mod = o.module;
2363 const namespace = mod.namespacePtr(namespace_index);
2364 if (namespace.parent == .none) {
2410 const di_file = try o.getDIFile(o.gpa, namespace.file_scope);2365 const di_file = try o.getDIFile(o.gpa, namespace.file_scope);
2411 return di_file.toScope();2366 return di_file.toScope();
2412 }2367 }
...@@ -2418,12 +2373,14 @@ pub const Object = struct {...@@ -2418,12 +2373,14 @@ pub const Object = struct {
2418 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'2373 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
2419 /// when targeting CodeView (Windows).2374 /// when targeting CodeView (Windows).
2420 fn makeEmptyNamespaceDIType(o: *Object, decl_index: Module.Decl.Index) !*llvm.DIType {2375 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);
2422 const fields: [0]*llvm.DIType = .{};2378 const fields: [0]*llvm.DIType = .{};
2379 const di_scope = try o.namespaceToDebugScope(decl.src_namespace);
2423 return o.di_builder.?.createStructType(2380 return o.di_builder.?.createStructType(
2424 try o.namespaceToDebugScope(decl.src_namespace),2381 di_scope,
2425 decl.name, // TODO use fully qualified name2382 mod.intern_pool.stringToSlice(decl.name), // TODO use fully qualified name
2426 try o.getDIFile(o.gpa, decl.src_namespace.file_scope),2383 try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope),
2427 decl.src_line + 1,2384 decl.src_line + 1,
2428 0, // size in bits2385 0, // size in bits
2429 0, // align in bits2386 0, // align in bits
...@@ -2437,28 +2394,28 @@ pub const Object = struct {...@@ -2437,28 +2394,28 @@ pub const Object = struct {
2437 );2394 );
2438 }2395 }
24392396
2440 fn getStackTraceType(o: *Object) Type {2397 fn getStackTraceType(o: *Object) Allocator.Error!Type {
2441 const mod = o.module;2398 const mod = o.module;
24422399
2443 const std_pkg = mod.main_pkg.table.get("std").?;2400 const std_pkg = mod.main_pkg.table.get("std").?;
2444 const std_file = (mod.importPkg(std_pkg) catch unreachable).file;2401 const std_file = (mod.importPkg(std_pkg) catch unreachable).file;
24452402
2446 const builtin_str: []const u8 = "builtin";2403 const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin");
2447 const std_namespace = mod.declPtr(std_file.root_decl.unwrap().?).src_namespace;2404 const std_namespace = mod.namespacePtr(mod.declPtr(std_file.root_decl.unwrap().?).src_namespace);
2448 const builtin_decl = std_namespace.decls2405 const builtin_decl = std_namespace.decls
2449 .getKeyAdapted(builtin_str, Module.DeclAdapter{ .mod = mod }).?;2406 .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");
2452 // buffer is only used for int_type, `builtin` is a struct.2409 // buffer is only used for int_type, `builtin` is a struct.
2453 const builtin_ty = mod.declPtr(builtin_decl).val.toType(undefined);2410 const builtin_ty = mod.declPtr(builtin_decl).val.toType();
2454 const builtin_namespace = builtin_ty.getNamespace().?;2411 const builtin_namespace = builtin_ty.getNamespace(mod).?;
2455 const stack_trace_decl_index = builtin_namespace.decls2412 const stack_trace_decl_index = builtin_namespace.decls
2456 .getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .mod = mod }).?;2413 .getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .mod = mod }).?;
2457 const stack_trace_decl = mod.declPtr(stack_trace_decl_index);2414 const stack_trace_decl = mod.declPtr(stack_trace_decl_index);
24582415
2459 // Sema should have ensured that StackTrace was analyzed.2416 // Sema should have ensured that StackTrace was analyzed.
2460 assert(stack_trace_decl.has_tv);2417 assert(stack_trace_decl.has_tv);
2461 return stack_trace_decl.val.toType(undefined);2418 return stack_trace_decl.val.toType();
2462 }2419 }
2463};2420};
24642421
...@@ -2474,7 +2431,8 @@ pub const DeclGen = struct {...@@ -2474,7 +2431,8 @@ pub const DeclGen = struct {
2474 fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error {2431 fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
2475 @setCold(true);2432 @setCold(true);
2476 assert(self.err_msg == null);2433 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);
2478 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args);2436 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args);
2479 return error.CodegenFail;2437 return error.CodegenFail;
2480 }2438 }
...@@ -2484,31 +2442,27 @@ pub const DeclGen = struct {...@@ -2484,31 +2442,27 @@ pub const DeclGen = struct {
2484 }2442 }
24852443
2486 fn genDecl(dg: *DeclGen) !void {2444 fn genDecl(dg: *DeclGen) !void {
2445 const mod = dg.module;
2487 const decl = dg.decl;2446 const decl = dg.decl;
2488 const decl_index = dg.decl_index;2447 const decl_index = dg.decl_index;
2489 assert(decl.has_tv);2448 assert(decl.has_tv);
24902449
2491 log.debug("gen: {s} type: {}, value: {}", .{2450 if (decl.val.getExternFunc(mod)) |extern_func| {
2492 decl.name, decl.ty.fmtDebug(), decl.val.fmtDebug(),2451 _ = try dg.resolveLlvmFunction(extern_func.decl);
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);
2497 } else {2452 } else {
2498 const target = dg.module.getTarget();2453 const target = mod.getTarget();
2499 var global = try dg.resolveGlobalDecl(decl_index);2454 var global = try dg.resolveGlobalDecl(decl_index);
2500 global.setAlignment(decl.getAlignment(target));2455 global.setAlignment(decl.getAlignment(mod));
2501 if (decl.@"linksection") |section| global.setSection(section);2456 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| global.setSection(s);
2502 assert(decl.has_tv);2457 assert(decl.has_tv);
2503 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {2458 const init_val = if (decl.val.getVariable(mod)) |variable| init_val: {
2504 const variable = payload.data;
2505 break :init_val variable.init;2459 break :init_val variable.init;
2506 } else init_val: {2460 } else init_val: {
2507 global.setGlobalConstant(.True);2461 global.setGlobalConstant(.True);
2508 break :init_val decl.val;2462 break :init_val decl.val.toIntern();
2509 };2463 };
2510 if (init_val.tag() != .unreachable_value) {2464 if (init_val != .none) {
2511 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val });2465 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val.toValue() });
2512 if (global.globalGetValueType() == llvm_init.typeOf()) {2466 if (global.globalGetValueType() == llvm_init.typeOf()) {
2513 global.setInitializer(llvm_init);2467 global.setInitializer(llvm_init);
2514 } else {2468 } else {
...@@ -2533,7 +2487,8 @@ pub const DeclGen = struct {...@@ -2533,7 +2487,8 @@ pub const DeclGen = struct {
2533 new_global.setLinkage(global.getLinkage());2487 new_global.setLinkage(global.getLinkage());
2534 new_global.setUnnamedAddr(global.getUnnamedAddress());2488 new_global.setUnnamedAddr(global.getUnnamedAddress());
2535 new_global.setAlignment(global.getAlignment());2489 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);
2537 new_global.setInitializer(llvm_init);2492 new_global.setInitializer(llvm_init);
2538 // TODO: How should this work then the address space of a global changed?2493 // TODO: How should this work then the address space of a global changed?
2539 global.replaceAllUsesWith(new_global);2494 global.replaceAllUsesWith(new_global);
...@@ -2545,13 +2500,13 @@ pub const DeclGen = struct {...@@ -2545,13 +2500,13 @@ pub const DeclGen = struct {
2545 }2500 }
25462501
2547 if (dg.object.di_builder) |dib| {2502 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
2550 const line_number = decl.src_line + 1;2505 const line_number = decl.src_line + 1;
2551 const is_internal_linkage = !dg.module.decl_exports.contains(decl_index);2506 const is_internal_linkage = !dg.module.decl_exports.contains(decl_index);
2552 const di_global = dib.createGlobalVariableExpression(2507 const di_global = dib.createGlobalVariableExpression(
2553 di_file.toScope(),2508 di_file.toScope(),
2554 decl.name,2509 mod.intern_pool.stringToSlice(decl.name),
2555 global.getValueName(),2510 global.getValueName(),
2556 di_file,2511 di_file,
2557 line_number,2512 line_number,
...@@ -2560,7 +2515,7 @@ pub const DeclGen = struct {...@@ -2560,7 +2515,7 @@ pub const DeclGen = struct {
2560 );2515 );
25612516
2562 try dg.object.di_map.put(dg.gpa, dg.decl, di_global.getVariable().toNode());2517 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);
2564 }2519 }
2565 }2520 }
2566 }2521 }
...@@ -2569,36 +2524,35 @@ pub const DeclGen = struct {...@@ -2569,36 +2524,35 @@ pub const DeclGen = struct {
2569 /// Note that this can be called before the function's semantic analysis has2524 /// Note that this can be called before the function's semantic analysis has
2570 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.2525 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
2571 fn resolveLlvmFunction(dg: *DeclGen, decl_index: Module.Decl.Index) !*llvm.Value {2526 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);
2573 const zig_fn_type = decl.ty;2529 const zig_fn_type = decl.ty;
2574 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index);2530 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index);
2575 if (gop.found_existing) return gop.value_ptr.*;2531 if (gop.found_existing) return gop.value_ptr.*;
25762532
2577 assert(decl.has_tv);2533 assert(decl.has_tv);
2578 const fn_info = zig_fn_type.fnInfo();2534 const fn_info = mod.typeToFunc(zig_fn_type).?;
2579 const target = dg.module.getTarget();2535 const target = mod.getTarget();
2580 const sret = firstParamSRet(fn_info, target);2536 const sret = firstParamSRet(fn_info, mod);
25812537
2582 const fn_type = try dg.lowerType(zig_fn_type);2538 const fn_type = try dg.lowerType(zig_fn_type);
25832539
2584 const fqn = try decl.getFullyQualifiedName(dg.module);2540 const fqn = try decl.getFullyQualifiedName(mod);
2585 defer dg.gpa.free(fqn);
25862541
2587 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);2542 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);
2589 gop.value_ptr.* = llvm_fn;2544 gop.value_ptr.* = llvm_fn;
25902545
2591 const is_extern = decl.isExtern();2546 const is_extern = decl.isExtern(mod);
2592 if (!is_extern) {2547 if (!is_extern) {
2593 llvm_fn.setLinkage(.Internal);2548 llvm_fn.setLinkage(.Internal);
2594 llvm_fn.setUnnamedAddr(.True);2549 llvm_fn.setUnnamedAddr(.True);
2595 } else {2550 } else {
2596 if (dg.module.getTarget().isWasm()) {2551 if (target.isWasm()) {
2597 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));2552 dg.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));
2598 if (decl.getExternFn().?.lib_name) |lib_name| {2553 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2599 const module_name = std.mem.sliceTo(lib_name, 0);2554 if (!std.mem.eql(u8, lib_name, "c")) {
2600 if (!std.mem.eql(u8, module_name, "c")) {2555 dg.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
2601 dg.addFnAttrString(llvm_fn, "wasm-import-module", module_name);
2602 }2556 }
2603 }2557 }
2604 }2558 }
...@@ -2608,12 +2562,12 @@ pub const DeclGen = struct {...@@ -2608,12 +2562,12 @@ pub const DeclGen = struct {
2608 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 02562 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0
2609 dg.addArgAttr(llvm_fn, 0, "noalias");2563 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());
2612 llvm_fn.addSretAttr(raw_llvm_ret_ty);2566 llvm_fn.addSretAttr(raw_llvm_ret_ty);
2613 }2567 }
26142568
2615 const err_return_tracing = fn_info.return_type.isError() and2569 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
2616 dg.module.comp.bin_file.options.error_return_tracing;2570 mod.comp.bin_file.options.error_return_tracing;
26172571
2618 if (err_return_tracing) {2572 if (err_return_tracing) {
2619 dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull");2573 dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull");
...@@ -2635,14 +2589,14 @@ pub const DeclGen = struct {...@@ -2635,14 +2589,14 @@ pub const DeclGen = struct {
2635 },2589 },
2636 }2590 }
26372591
2638 if (fn_info.alignment != 0) {2592 if (fn_info.alignment.toByteUnitsOptional()) |a| {
2639 llvm_fn.setAlignment(fn_info.alignment);2593 llvm_fn.setAlignment(@intCast(c_uint, a));
2640 }2594 }
26412595
2642 // Function attributes that are independent of analysis results of the function body.2596 // Function attributes that are independent of analysis results of the function body.
2643 dg.addCommonFnAttributes(llvm_fn);2597 dg.addCommonFnAttributes(llvm_fn);
26442598
2645 if (fn_info.return_type.isNoReturn()) {2599 if (fn_info.return_type == .noreturn_type) {
2646 dg.addFnAttr(llvm_fn, "noreturn");2600 dg.addFnAttr(llvm_fn, "noreturn");
2647 }2601 }
26482602
...@@ -2655,15 +2609,15 @@ pub const DeclGen = struct {...@@ -2655,15 +2609,15 @@ pub const DeclGen = struct {
2655 while (it.next()) |lowering| switch (lowering) {2609 while (it.next()) |lowering| switch (lowering) {
2656 .byval => {2610 .byval => {
2657 const param_index = it.zig_index - 1;2611 const param_index = it.zig_index - 1;
2658 const param_ty = fn_info.param_types[param_index];2612 const param_ty = fn_info.param_types[param_index].toType();
2659 if (!isByRef(param_ty)) {2613 if (!isByRef(param_ty, mod)) {
2660 dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);2614 dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
2661 }2615 }
2662 },2616 },
2663 .byref => {2617 .byref => {
2664 const param_ty = fn_info.param_types[it.zig_index - 1];2618 const param_ty = fn_info.param_types[it.zig_index - 1];
2665 const param_llvm_ty = try dg.lowerType(param_ty);2619 const param_llvm_ty = try dg.lowerType(param_ty.toType());
2666 const alignment = param_ty.abiAlignment(target);2620 const alignment = param_ty.toType().abiAlignment(mod);
2667 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);2621 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
2668 },2622 },
2669 .byref_mut => {2623 .byref_mut => {
...@@ -2735,35 +2689,35 @@ pub const DeclGen = struct {...@@ -2735,35 +2689,35 @@ pub const DeclGen = struct {
2735 if (gop.found_existing) return gop.value_ptr.*;2689 if (gop.found_existing) return gop.value_ptr.*;
2736 errdefer assert(dg.object.decl_map.remove(decl_index));2690 errdefer assert(dg.object.decl_map.remove(decl_index));
27372691
2738 const decl = dg.module.declPtr(decl_index);2692 const mod = dg.module;
2739 const fqn = try decl.getFullyQualifiedName(dg.module);2693 const decl = mod.declPtr(decl_index);
2740 defer dg.gpa.free(fqn);2694 const fqn = try decl.getFullyQualifiedName(mod);
27412695
2742 const target = dg.module.getTarget();2696 const target = mod.getTarget();
27432697
2744 const llvm_type = try dg.lowerType(decl.ty);2698 const llvm_type = try dg.lowerType(decl.ty);
2745 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);2699 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
27462700
2747 const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace(2701 const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace(
2748 llvm_type,2702 llvm_type,
2749 fqn,2703 mod.intern_pool.stringToSlice(fqn),
2750 llvm_actual_addrspace,2704 llvm_actual_addrspace,
2751 );2705 );
2752 gop.value_ptr.* = llvm_global;2706 gop.value_ptr.* = llvm_global;
27532707
2754 // This is needed for declarations created by `@extern`.2708 // This is needed for declarations created by `@extern`.
2755 if (decl.isExtern()) {2709 if (decl.isExtern(mod)) {
2756 llvm_global.setValueName(decl.name);2710 llvm_global.setValueName(mod.intern_pool.stringToSlice(decl.name));
2757 llvm_global.setUnnamedAddr(.False);2711 llvm_global.setUnnamedAddr(.False);
2758 llvm_global.setLinkage(.External);2712 llvm_global.setLinkage(.External);
2759 if (decl.val.castTag(.variable)) |variable| {2713 if (decl.val.getVariable(mod)) |variable| {
2760 const single_threaded = dg.module.comp.bin_file.options.single_threaded;2714 const single_threaded = mod.comp.bin_file.options.single_threaded;
2761 if (variable.data.is_threadlocal and !single_threaded) {2715 if (variable.is_threadlocal and !single_threaded) {
2762 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);2716 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
2763 } else {2717 } else {
2764 llvm_global.setThreadLocalMode(.NotThreadLocal);2718 llvm_global.setThreadLocalMode(.NotThreadLocal);
2765 }2719 }
2766 if (variable.data.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);2720 if (variable.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
2767 }2721 }
2768 } else {2722 } else {
2769 llvm_global.setLinkage(.Internal);2723 llvm_global.setLinkage(.Internal);
...@@ -2784,12 +2738,13 @@ pub const DeclGen = struct {...@@ -2784,12 +2738,13 @@ pub const DeclGen = struct {
27842738
2785 fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type {2739 fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type {
2786 const llvm_ty = try lowerTypeInner(dg, t);2740 const llvm_ty = try lowerTypeInner(dg, t);
2741 const mod = dg.module;
2787 if (std.debug.runtime_safety and false) check: {2742 if (std.debug.runtime_safety and false) check: {
2788 if (t.zigTypeTag() == .Opaque) break :check;2743 if (t.zigTypeTag(mod) == .Opaque) break :check;
2789 if (!t.hasRuntimeBits()) break :check;2744 if (!t.hasRuntimeBits(mod)) break :check;
2790 if (!llvm_ty.isSized().toBool()) break :check;2745 if (!llvm_ty.isSized().toBool()) break :check;
27912746
2792 const zig_size = t.abiSize(dg.module.getTarget());2747 const zig_size = t.abiSize(mod);
2793 const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty);2748 const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty);
2794 if (llvm_size != zig_size) {2749 if (llvm_size != zig_size) {
2795 log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{2750 log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{
...@@ -2802,18 +2757,18 @@ pub const DeclGen = struct {...@@ -2802,18 +2757,18 @@ pub const DeclGen = struct {
28022757
2803 fn lowerTypeInner(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type {2758 fn lowerTypeInner(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type {
2804 const gpa = dg.gpa;2759 const gpa = dg.gpa;
2805 const target = dg.module.getTarget();2760 const mod = dg.module;
2806 switch (t.zigTypeTag()) {2761 const target = mod.getTarget();
2762 switch (t.zigTypeTag(mod)) {
2807 .Void, .NoReturn => return dg.context.voidType(),2763 .Void, .NoReturn => return dg.context.voidType(),
2808 .Int => {2764 .Int => {
2809 const info = t.intInfo(target);2765 const info = t.intInfo(mod);
2810 assert(info.bits != 0);2766 assert(info.bits != 0);
2811 return dg.context.intType(info.bits);2767 return dg.context.intType(info.bits);
2812 },2768 },
2813 .Enum => {2769 .Enum => {
2814 var buffer: Type.Payload.Bits = undefined;2770 const int_ty = t.intTagType(mod);
2815 const int_ty = t.intTagType(&buffer);2771 const bit_count = int_ty.intInfo(mod).bits;
2816 const bit_count = int_ty.intInfo(target).bits;
2817 assert(bit_count != 0);2772 assert(bit_count != 0);
2818 return dg.context.intType(bit_count);2773 return dg.context.intType(bit_count);
2819 },2774 },
...@@ -2827,9 +2782,8 @@ pub const DeclGen = struct {...@@ -2827,9 +2782,8 @@ pub const DeclGen = struct {
2827 },2782 },
2828 .Bool => return dg.context.intType(1),2783 .Bool => return dg.context.intType(1),
2829 .Pointer => {2784 .Pointer => {
2830 if (t.isSlice()) {2785 if (t.isSlice(mod)) {
2831 var buf: Type.SlicePtrFieldTypeBuffer = undefined;2786 const ptr_type = t.slicePtrFieldType(mod);
2832 const ptr_type = t.slicePtrFieldType(&buf);
28332787
2834 const fields: [2]*llvm.Type = .{2788 const fields: [2]*llvm.Type = .{
2835 try dg.lowerType(ptr_type),2789 try dg.lowerType(ptr_type),
...@@ -2837,49 +2791,41 @@ pub const DeclGen = struct {...@@ -2837,49 +2791,41 @@ pub const DeclGen = struct {
2837 };2791 };
2838 return dg.context.structType(&fields, fields.len, .False);2792 return dg.context.structType(&fields, fields.len, .False);
2839 }2793 }
2840 const ptr_info = t.ptrInfo().data;2794 const ptr_info = t.ptrInfo(mod);
2841 const llvm_addrspace = toLlvmAddressSpace(ptr_info.@"addrspace", target);2795 const llvm_addrspace = toLlvmAddressSpace(ptr_info.@"addrspace", target);
2842 return dg.context.pointerType(llvm_addrspace);2796 return dg.context.pointerType(llvm_addrspace);
2843 },2797 },
2844 .Opaque => switch (t.tag()) {2798 .Opaque => {
2845 .@"opaque" => {2799 if (t.toIntern() == .anyopaque_type) return dg.context.intType(8);
2846 const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
2847 if (gop.found_existing) return gop.value_ptr.*;
28482800
2849 // The Type memory is ephemeral; since we want to store a longer-lived2801 const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern());
2850 // reference, we need to copy it here.2802 if (gop.found_existing) return gop.value_ptr.*;
2851 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
28522803
2853 const opaque_obj = t.castTag(.@"opaque").?.data;2804 const opaque_type = mod.intern_pool.indexToKey(t.toIntern()).opaque_type;
2854 const name = try opaque_obj.getFullyQualifiedName(dg.module);2805 const name = mod.intern_pool.stringToSlice(try mod.opaqueFullyQualifiedName(opaque_type));
2855 defer gpa.free(name);
28562806
2857 const llvm_struct_ty = dg.context.structCreateNamed(name);2807 const llvm_struct_ty = dg.context.structCreateNamed(name);
2858 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls2808 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2859 return llvm_struct_ty;2809 return llvm_struct_ty;
2860 },
2861 .anyopaque => return dg.context.intType(8),
2862 else => unreachable,
2863 },2810 },
2864 .Array => {2811 .Array => {
2865 const elem_ty = t.childType();2812 const elem_ty = t.childType(mod);
2866 assert(elem_ty.onePossibleValue() == null);2813 if (std.debug.runtime_safety) assert((try elem_ty.onePossibleValue(mod)) == null);
2867 const elem_llvm_ty = try dg.lowerType(elem_ty);2814 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);
2869 return elem_llvm_ty.arrayType(@intCast(c_uint, total_len));2816 return elem_llvm_ty.arrayType(@intCast(c_uint, total_len));
2870 },2817 },
2871 .Vector => {2818 .Vector => {
2872 const elem_type = try dg.lowerType(t.childType());2819 const elem_type = try dg.lowerType(t.childType(mod));
2873 return elem_type.vectorType(t.vectorLen());2820 return elem_type.vectorType(t.vectorLen(mod));
2874 },2821 },
2875 .Optional => {2822 .Optional => {
2876 var buf: Type.Payload.ElemType = undefined;2823 const child_ty = t.optionalChild(mod);
2877 const child_ty = t.optionalChild(&buf);2824 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2878 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
2879 return dg.context.intType(8);2825 return dg.context.intType(8);
2880 }2826 }
2881 const payload_llvm_ty = try dg.lowerType(child_ty);2827 const payload_llvm_ty = try dg.lowerType(child_ty);
2882 if (t.optionalReprIsPayload()) {2828 if (t.optionalReprIsPayload(mod)) {
2883 return payload_llvm_ty;2829 return payload_llvm_ty;
2884 }2830 }
28852831
...@@ -2887,8 +2833,8 @@ pub const DeclGen = struct {...@@ -2887,8 +2833,8 @@ pub const DeclGen = struct {
2887 var fields_buf: [3]*llvm.Type = .{2833 var fields_buf: [3]*llvm.Type = .{
2888 payload_llvm_ty, dg.context.intType(8), undefined,2834 payload_llvm_ty, dg.context.intType(8), undefined,
2889 };2835 };
2890 const offset = child_ty.abiSize(target) + 1;2836 const offset = child_ty.abiSize(mod) + 1;
2891 const abi_size = t.abiSize(target);2837 const abi_size = t.abiSize(mod);
2892 const padding = @intCast(c_uint, abi_size - offset);2838 const padding = @intCast(c_uint, abi_size - offset);
2893 if (padding == 0) {2839 if (padding == 0) {
2894 return dg.context.structType(&fields_buf, 2, .False);2840 return dg.context.structType(&fields_buf, 2, .False);
...@@ -2897,18 +2843,18 @@ pub const DeclGen = struct {...@@ -2897,18 +2843,18 @@ pub const DeclGen = struct {
2897 return dg.context.structType(&fields_buf, 3, .False);2843 return dg.context.structType(&fields_buf, 3, .False);
2898 },2844 },
2899 .ErrorUnion => {2845 .ErrorUnion => {
2900 const payload_ty = t.errorUnionPayload();2846 const payload_ty = t.errorUnionPayload(mod);
2901 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2847 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2902 return try dg.lowerType(Type.anyerror);2848 return try dg.lowerType(Type.anyerror);
2903 }2849 }
2904 const llvm_error_type = try dg.lowerType(Type.anyerror);2850 const llvm_error_type = try dg.lowerType(Type.anyerror);
2905 const llvm_payload_type = try dg.lowerType(payload_ty);2851 const llvm_payload_type = try dg.lowerType(payload_ty);
29062852
2907 const payload_align = payload_ty.abiAlignment(target);2853 const payload_align = payload_ty.abiAlignment(mod);
2908 const error_align = Type.anyerror.abiAlignment(target);2854 const error_align = Type.anyerror.abiAlignment(mod);
29092855
2910 const payload_size = payload_ty.abiSize(target);2856 const payload_size = payload_ty.abiSize(mod);
2911 const error_size = Type.anyerror.abiSize(target);2857 const error_size = Type.anyerror.abiSize(mod);
29122858
2913 var fields_buf: [3]*llvm.Type = undefined;2859 var fields_buf: [3]*llvm.Type = undefined;
2914 if (error_align > payload_align) {2860 if (error_align > payload_align) {
...@@ -2941,66 +2887,64 @@ pub const DeclGen = struct {...@@ -2941,66 +2887,64 @@ pub const DeclGen = struct {
2941 },2887 },
2942 .ErrorSet => return dg.context.intType(16),2888 .ErrorSet => return dg.context.intType(16),
2943 .Struct => {2889 .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());
2945 if (gop.found_existing) return gop.value_ptr.*;2891 if (gop.found_existing) return gop.value_ptr.*;
29462892
2947 // The Type memory is ephemeral; since we want to store a longer-lived2893 const struct_type = switch (mod.intern_pool.indexToKey(t.toIntern())) {
2948 // reference, we need to copy it here.2894 .anon_struct_type => |tuple| {
2949 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());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()) {2898 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
2952 const tuple = t.tupleFields();2899 defer llvm_field_types.deinit(gpa);
2953 const llvm_struct_ty = dg.context.structCreateNamed("");
2954 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
29552900
2956 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};2901 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
2957 defer llvm_field_types.deinit(gpa);
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);2907 for (tuple.types, tuple.values) |field_ty, field_val| {
2962 var offset: u64 = 0;2908 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
2963 var big_align: u32 = 0;
29642909
2965 for (tuple.types, 0..) |field_ty, i| {2910 const field_align = field_ty.toType().abiAlignment(mod);
2966 const field_val = tuple.values[i];2911 big_align = @max(big_align, field_align);
2967 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;2912 const prev_offset = offset;
2913 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
29682914
2969 const field_align = field_ty.abiAlignment(target);2915 const padding_len = offset - prev_offset;
2970 big_align = @max(big_align, field_align);2916 if (padding_len > 0) {
2971 const prev_offset = offset;2917 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2972 offset = std.mem.alignForwardGeneric(u64, offset, field_align);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;2923 offset += field_ty.toType().abiSize(mod);
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);
2978 }2924 }
2979 const field_llvm_ty = try dg.lowerType(field_ty);2925 {
2980 try llvm_field_types.append(gpa, field_llvm_ty);2926 const prev_offset = offset;
29812927 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2982 offset += field_ty.abiSize(target);2928 const padding_len = offset - prev_offset;
2983 }2929 if (padding_len > 0) {
2984 {2930 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2985 const prev_offset = offset;2931 try llvm_field_types.append(gpa, llvm_array_ty);
2986 offset = std.mem.alignForwardGeneric(u64, offset, big_align);2932 }
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);
2991 }2933 }
2992 }
29932934
2994 llvm_struct_ty.structSetBody(2935 llvm_struct_ty.structSetBody(
2995 llvm_field_types.items.ptr,2936 llvm_field_types.items.ptr,
2996 @intCast(c_uint, llvm_field_types.items.len),2937 @intCast(c_uint, llvm_field_types.items.len),
2997 .False,2938 .False,
2998 );2939 );
29992940
3000 return llvm_struct_ty;2941 return llvm_struct_ty;
3001 }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
3005 if (struct_obj.layout == .Packed) {2949 if (struct_obj.layout == .Packed) {
3006 assert(struct_obj.haveLayout());2950 assert(struct_obj.haveLayout());
...@@ -3009,8 +2953,7 @@ pub const DeclGen = struct {...@@ -3009,8 +2953,7 @@ pub const DeclGen = struct {
3009 return int_llvm_ty;2953 return int_llvm_ty;
3010 }2954 }
30112955
3012 const name = try struct_obj.getFullyQualifiedName(dg.module);2956 const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(mod));
3013 defer gpa.free(name);
30142957
3015 const llvm_struct_ty = dg.context.structCreateNamed(name);2958 const llvm_struct_ty = dg.context.structCreateNamed(name);
3016 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls2959 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
...@@ -3027,11 +2970,11 @@ pub const DeclGen = struct {...@@ -3027,11 +2970,11 @@ pub const DeclGen = struct {
3027 var big_align: u32 = 1;2970 var big_align: u32 = 1;
3028 var any_underaligned_fields = false;2971 var any_underaligned_fields = false;
30292972
3030 var it = struct_obj.runtimeFieldIterator();2973 var it = struct_obj.runtimeFieldIterator(mod);
3031 while (it.next()) |field_and_index| {2974 while (it.next()) |field_and_index| {
3032 const field = field_and_index.field;2975 const field = field_and_index.field;
3033 const field_align = field.alignment(target, struct_obj.layout);2976 const field_align = field.alignment(mod, struct_obj.layout);
3034 const field_ty_align = field.ty.abiAlignment(target);2977 const field_ty_align = field.ty.abiAlignment(mod);
3035 any_underaligned_fields = any_underaligned_fields or2978 any_underaligned_fields = any_underaligned_fields or
3036 field_align < field_ty_align;2979 field_align < field_ty_align;
3037 big_align = @max(big_align, field_align);2980 big_align = @max(big_align, field_align);
...@@ -3046,7 +2989,7 @@ pub const DeclGen = struct {...@@ -3046,7 +2989,7 @@ pub const DeclGen = struct {
3046 const field_llvm_ty = try dg.lowerType(field.ty);2989 const field_llvm_ty = try dg.lowerType(field.ty);
3047 try llvm_field_types.append(gpa, field_llvm_ty);2990 try llvm_field_types.append(gpa, field_llvm_ty);
30482991
3049 offset += field.ty.abiSize(target);2992 offset += field.ty.abiSize(mod);
3050 }2993 }
3051 {2994 {
3052 const prev_offset = offset;2995 const prev_offset = offset;
...@@ -3067,18 +3010,14 @@ pub const DeclGen = struct {...@@ -3067,18 +3010,14 @@ pub const DeclGen = struct {
3067 return llvm_struct_ty;3010 return llvm_struct_ty;
3068 },3011 },
3069 .Union => {3012 .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());
3071 if (gop.found_existing) return gop.value_ptr.*;3014 if (gop.found_existing) return gop.value_ptr.*;
30723015
3073 // The Type memory is ephemeral; since we want to store a longer-lived3016 const layout = t.unionGetLayout(mod);
3074 // reference, we need to copy it here.3017 const union_obj = mod.typeToUnion(t).?;
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;
30793018
3080 if (union_obj.layout == .Packed) {3019 if (union_obj.layout == .Packed) {
3081 const bitsize = @intCast(c_uint, t.bitSize(target));3020 const bitsize = @intCast(c_uint, t.bitSize(mod));
3082 const int_llvm_ty = dg.context.intType(bitsize);3021 const int_llvm_ty = dg.context.intType(bitsize);
3083 gop.value_ptr.* = int_llvm_ty;3022 gop.value_ptr.* = int_llvm_ty;
3084 return int_llvm_ty;3023 return int_llvm_ty;
...@@ -3090,8 +3029,7 @@ pub const DeclGen = struct {...@@ -3090,8 +3029,7 @@ pub const DeclGen = struct {
3090 return enum_tag_llvm_ty;3029 return enum_tag_llvm_ty;
3091 }3030 }
30923031
3093 const name = try union_obj.getFullyQualifiedName(dg.module);3032 const name = mod.intern_pool.stringToSlice(try union_obj.getFullyQualifiedName(mod));
3094 defer gpa.free(name);
30953033
3096 const llvm_union_ty = dg.context.structCreateNamed(name);3034 const llvm_union_ty = dg.context.structCreateNamed(name);
3097 gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls3035 gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls
...@@ -3155,25 +3093,21 @@ pub const DeclGen = struct {...@@ -3155,25 +3093,21 @@ pub const DeclGen = struct {
3155 }3093 }
31563094
3157 fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type {3095 fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type {
3158 const target = dg.module.getTarget();3096 const mod = dg.module;
3159 const fn_info = fn_ty.fnInfo();3097 const fn_info = mod.typeToFunc(fn_ty).?;
3160 const llvm_ret_ty = try lowerFnRetTy(dg, fn_info);3098 const llvm_ret_ty = try lowerFnRetTy(dg, fn_info);
31613099
3162 var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa);3100 var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa);
3163 defer llvm_params.deinit();3101 defer llvm_params.deinit();
31643102
3165 if (firstParamSRet(fn_info, target)) {3103 if (firstParamSRet(fn_info, mod)) {
3166 try llvm_params.append(dg.context.pointerType(0));3104 try llvm_params.append(dg.context.pointerType(0));
3167 }3105 }
31683106
3169 if (fn_info.return_type.isError() and3107 if (fn_info.return_type.toType().isError(mod) and
3170 dg.module.comp.bin_file.options.error_return_tracing)3108 mod.comp.bin_file.options.error_return_tracing)
3171 {3109 {
3172 var ptr_ty_payload: Type.Payload.ElemType = .{3110 const ptr_ty = try mod.singleMutPtrType(try dg.object.getStackTraceType());
3173 .base = .{ .tag = .single_mut_pointer },
3174 .data = dg.object.getStackTraceType(),
3175 };
3176 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
3177 try llvm_params.append(try dg.lowerType(ptr_ty));3111 try llvm_params.append(try dg.lowerType(ptr_ty));
3178 }3112 }
31793113
...@@ -3181,25 +3115,23 @@ pub const DeclGen = struct {...@@ -3181,25 +3115,23 @@ pub const DeclGen = struct {
3181 while (it.next()) |lowering| switch (lowering) {3115 while (it.next()) |lowering| switch (lowering) {
3182 .no_bits => continue,3116 .no_bits => continue,
3183 .byval => {3117 .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();
3185 try llvm_params.append(try dg.lowerType(param_ty));3119 try llvm_params.append(try dg.lowerType(param_ty));
3186 },3120 },
3187 .byref, .byref_mut => {3121 .byref, .byref_mut => {
3188 try llvm_params.append(dg.context.pointerType(0));3122 try llvm_params.append(dg.context.pointerType(0));
3189 },3123 },
3190 .abi_sized_int => {3124 .abi_sized_int => {
3191 const param_ty = fn_info.param_types[it.zig_index - 1];3125 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3192 const abi_size = @intCast(c_uint, param_ty.abiSize(target));3126 const abi_size = @intCast(c_uint, param_ty.abiSize(mod));
3193 try llvm_params.append(dg.context.intType(abi_size * 8));3127 try llvm_params.append(dg.context.intType(abi_size * 8));
3194 },3128 },
3195 .slice => {3129 .slice => {
3196 const param_ty = fn_info.param_types[it.zig_index - 1];3130 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3197 var buf: Type.SlicePtrFieldTypeBuffer = undefined;3131 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
3198 var opt_buf: Type.Payload.ElemType = undefined;3132 param_ty.optionalChild(mod).slicePtrFieldType(mod)
3199 const ptr_ty = if (param_ty.zigTypeTag() == .Optional)
3200 param_ty.optionalChild(&opt_buf).slicePtrFieldType(&buf)
3201 else3133 else
3202 param_ty.slicePtrFieldType(&buf);3134 param_ty.slicePtrFieldType(mod);
3203 const ptr_llvm_ty = try dg.lowerType(ptr_ty);3135 const ptr_llvm_ty = try dg.lowerType(ptr_ty);
3204 const len_llvm_ty = try dg.lowerType(Type.usize);3136 const len_llvm_ty = try dg.lowerType(Type.usize);
32053137
...@@ -3214,8 +3146,8 @@ pub const DeclGen = struct {...@@ -3214,8 +3146,8 @@ pub const DeclGen = struct {
3214 try llvm_params.append(dg.context.intType(16));3146 try llvm_params.append(dg.context.intType(16));
3215 },3147 },
3216 .float_array => |count| {3148 .float_array => |count| {
3217 const param_ty = fn_info.param_types[it.zig_index - 1];3149 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3218 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty).?);3150 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
3219 const field_count = @intCast(c_uint, count);3151 const field_count = @intCast(c_uint, count);
3220 const arr_ty = float_ty.arrayType(field_count);3152 const arr_ty = float_ty.arrayType(field_count);
3221 try llvm_params.append(arr_ty);3153 try llvm_params.append(arr_ty);
...@@ -3239,11 +3171,12 @@ pub const DeclGen = struct {...@@ -3239,11 +3171,12 @@ pub const DeclGen = struct {
3239 /// being a zero bit type, but it should still be lowered as an i8 in such case.3171 /// being a zero bit type, but it should still be lowered as an i8 in such case.
3240 /// There are other similar cases handled here as well.3172 /// There are other similar cases handled here as well.
3241 fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type {3173 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)) {
3243 .Opaque => true,3176 .Opaque => true,
3244 .Fn => !elem_ty.fnInfo().is_generic,3177 .Fn => !mod.typeToFunc(elem_ty).?.is_generic,
3245 .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),3178 .Array => elem_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod),
3246 else => elem_ty.hasRuntimeBitsIgnoreComptime(),3179 else => elem_ty.hasRuntimeBitsIgnoreComptime(mod),
3247 };3180 };
3248 const llvm_elem_ty = if (lower_elem_ty)3181 const llvm_elem_ty = if (lower_elem_ty)
3249 try dg.lowerType(elem_ty)3182 try dg.lowerType(elem_ty)
...@@ -3254,59 +3187,132 @@ pub const DeclGen = struct {...@@ -3254,59 +3187,132 @@ pub const DeclGen = struct {
3254 }3187 }
32553188
3256 fn lowerValue(dg: *DeclGen, arg_tv: TypedValue) Error!*llvm.Value {3189 fn lowerValue(dg: *DeclGen, arg_tv: TypedValue) Error!*llvm.Value {
3190 const mod = dg.module;
3191 const target = mod.getTarget();
3257 var tv = arg_tv;3192 var tv = arg_tv;
3258 if (tv.val.castTag(.runtime_value)) |rt| {3193 switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
3259 tv.val = rt.data;3194 .runtime_value => |rt| tv.val = rt.val.toValue(),
3195 else => {},
3260 }3196 }
3261 if (tv.val.isUndef()) {3197 if (tv.val.isUndefDeep(mod)) {
3262 const llvm_type = try dg.lowerType(tv.ty);3198 const llvm_type = try dg.lowerType(tv.ty);
3263 return llvm_type.getUndef();3199 return llvm_type.getUndef();
3264 }3200 }
3265 const target = dg.module.getTarget();
32663201
3267 switch (tv.ty.zigTypeTag()) {3202 const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());
3268 .Bool => {3203 switch (val_key) {
3269 const llvm_type = try dg.lowerType(tv.ty);3204 .int_type,
3270 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();3205 .ptr_type,
3271 },3206 .array_type,
3272 // TODO this duplicates code with Pointer but they should share the handling3207 .vector_type,
3273 // of the tv.val.tag() and then Int should do extra constPtrToInt on top3208 .opt_type,
3274 .Int => switch (tv.val.tag()) {3209 .anyframe_type,
3275 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),3210 .error_union_type,
3276 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),3211 .simple_type,
3277 else => {3212 .struct_type,
3278 var bigint_space: Value.BigIntSpace = undefined;3213 .anon_struct_type,
3279 const bigint = tv.val.toBigInt(&bigint_space, target);3214 .union_type,
3280 const int_info = tv.ty.intInfo(target);3215 .opaque_type,
3281 assert(int_info.bits != 0);3216 .enum_type,
3282 const llvm_type = dg.context.intType(int_info.bits);3217 .func_type,
32833218 .error_set_type,
3284 const unsigned_val = v: {3219 .inferred_error_set_type,
3285 if (bigint.limbs.len == 1) {3220 => unreachable, // types, not values
3286 break :v llvm_type.constInt(bigint.limbs[0], .False);3221
3287 }3222 .undef, .runtime_value => unreachable, // handled above
3288 if (@sizeOf(usize) == @sizeOf(u64)) {3223 .simple_value => |simple_value| switch (simple_value) {
3289 break :v llvm_type.constIntOfArbitraryPrecision(3224 .undefined,
3290 @intCast(c_uint, bigint.limbs.len),3225 .void,
3291 bigint.limbs.ptr,3226 .null,
3292 );3227 .empty_struct,
3293 }3228 .@"unreachable",
3294 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");3229 .generic_poison,
3295 };3230 => unreachable, // non-runtime values
3296 if (!bigint.positive) {3231 .false, .true => {
3297 return llvm.constNeg(unsigned_val);3232 const llvm_type = try dg.lowerType(tv.ty);
3298 }3233 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
3299 return unsigned_val;
3300 },3234 },
3301 },3235 },
3302 .Enum => {3236 .variable,
3303 var int_buffer: Value.Payload.U64 = undefined;3237 .enum_literal,
3304 const int_val = tv.enumToInt(&int_buffer);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
3306 var bigint_space: Value.BigIntSpace = undefined;3312 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);
3310 const llvm_type = dg.context.intType(int_info.bits);3316 const llvm_type = dg.context.intType(int_info.bits);
33113317
3312 const unsigned_val = v: {3318 const unsigned_val = v: {
...@@ -3326,29 +3332,29 @@ pub const DeclGen = struct {...@@ -3326,29 +3332,29 @@ pub const DeclGen = struct {
3326 }3332 }
3327 return unsigned_val;3333 return unsigned_val;
3328 },3334 },
3329 .Float => {3335 .float => {
3330 const llvm_ty = try dg.lowerType(tv.ty);3336 const llvm_ty = try dg.lowerType(tv.ty);
3331 switch (tv.ty.floatBits(target)) {3337 switch (tv.ty.floatBits(target)) {
3332 16 => {3338 16 => {
3333 const repr = @bitCast(u16, tv.val.toFloat(f16));3339 const repr = @bitCast(u16, tv.val.toFloat(f16, mod));
3334 const llvm_i16 = dg.context.intType(16);3340 const llvm_i16 = dg.context.intType(16);
3335 const int = llvm_i16.constInt(repr, .False);3341 const int = llvm_i16.constInt(repr, .False);
3336 return int.constBitCast(llvm_ty);3342 return int.constBitCast(llvm_ty);
3337 },3343 },
3338 32 => {3344 32 => {
3339 const repr = @bitCast(u32, tv.val.toFloat(f32));3345 const repr = @bitCast(u32, tv.val.toFloat(f32, mod));
3340 const llvm_i32 = dg.context.intType(32);3346 const llvm_i32 = dg.context.intType(32);
3341 const int = llvm_i32.constInt(repr, .False);3347 const int = llvm_i32.constInt(repr, .False);
3342 return int.constBitCast(llvm_ty);3348 return int.constBitCast(llvm_ty);
3343 },3349 },
3344 64 => {3350 64 => {
3345 const repr = @bitCast(u64, tv.val.toFloat(f64));3351 const repr = @bitCast(u64, tv.val.toFloat(f64, mod));
3346 const llvm_i64 = dg.context.intType(64);3352 const llvm_i64 = dg.context.intType(64);
3347 const int = llvm_i64.constInt(repr, .False);3353 const int = llvm_i64.constInt(repr, .False);
3348 return int.constBitCast(llvm_ty);3354 return int.constBitCast(llvm_ty);
3349 },3355 },
3350 80 => {3356 80 => {
3351 const float = tv.val.toFloat(f80);3357 const float = tv.val.toFloat(f80, mod);
3352 const repr = std.math.break_f80(float);3358 const repr = std.math.break_f80(float);
3353 const llvm_i80 = dg.context.intType(80);3359 const llvm_i80 = dg.context.intType(80);
3354 var x = llvm_i80.constInt(repr.exp, .False);3360 var x = llvm_i80.constInt(repr.exp, .False);
...@@ -3361,7 +3367,7 @@ pub const DeclGen = struct {...@@ -3361,7 +3367,7 @@ pub const DeclGen = struct {
3361 }3367 }
3362 },3368 },
3363 128 => {3369 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));
3365 // LLVM seems to require that the lower half of the f128 be placed first3371 // LLVM seems to require that the lower half of the f128 be placed first
3366 // in the buffer.3372 // in the buffer.
3367 if (native_endian == .Big) {3373 if (native_endian == .Big) {
...@@ -3373,204 +3379,60 @@ pub const DeclGen = struct {...@@ -3373,204 +3379,60 @@ pub const DeclGen = struct {
3373 else => unreachable,3379 else => unreachable,
3374 }3380 }
3375 },3381 },
3376 .Pointer => switch (tv.val.tag()) {3382 .ptr => |ptr| {
3377 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),3383 const ptr_tv: TypedValue = switch (ptr.len) {
3378 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),3384 .none => tv,
3379 .variable => {3385 else => .{ .ty = tv.ty.slicePtrFieldType(mod), .val = tv.val.slicePtr(mod) },
3380 const decl_index = tv.val.castTag(.variable).?.data.owner_decl;3386 };
3381 const decl = dg.module.declPtr(decl_index);3387 const llvm_ptr_val = switch (ptr.addr) {
3382 dg.module.markDeclAlive(decl);3388 .decl => |decl| try dg.lowerDeclRefValue(ptr_tv, decl),
33833389 .mut_decl => |mut_decl| try dg.lowerDeclRefValue(ptr_tv, mut_decl.decl),
3384 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);3390 .int => |int| try dg.lowerIntAsPtr(int.toValue()),
3385 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);3391 .eu_payload,
33863392 .opt_payload,
3387 const val = try dg.resolveGlobalDecl(decl_index);3393 .elem,
3388 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)3394 .field,
3389 val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace))3395 => try dg.lowerParentPtr(ptr_tv.val, ptr_tv.ty.ptrInfo(mod).bit_offset % 8 == 0),
3390 else3396 .comptime_field => unreachable,
3391 val;3397 };
3392 return addrspace_casted_ptr;3398 switch (ptr.len) {
3393 },3399 .none => return llvm_ptr_val,
3394 .slice => {3400 else => {
3395 const slice = tv.val.castTag(.slice).?.data;3401 const fields: [2]*llvm.Value = .{
3396 var buf: Type.SlicePtrFieldTypeBuffer = undefined;3402 llvm_ptr_val,
3397 const fields: [2]*llvm.Value = .{3403 try dg.lowerValue(.{ .ty = Type.usize, .val = ptr.len.toValue() }),
3398 try dg.lowerValue(.{3404 };
3399 .ty = tv.ty.slicePtrFieldType(&buf),3405 return dg.context.constStruct(&fields, fields.len, .False);
3400 .val = slice.ptr,3406 },
3401 }),3407 }
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,
3545 },3408 },
3546 .Optional => {3409 .opt => |opt| {
3547 comptime assert(optional_layout_version == 3);3410 comptime assert(optional_layout_version == 3);
3548 var buf: Type.Payload.ElemType = undefined;3411 const payload_ty = tv.ty.optionalChild(mod);
3549 const payload_ty = tv.ty.optionalChild(&buf);
35503412
3551 const llvm_i8 = dg.context.intType(8);3413 const llvm_i8 = dg.context.intType(8);
3552 const is_pl = !tv.val.isNull();3414 const non_null_bit = switch (opt.val) {
3553 const non_null_bit = if (is_pl) llvm_i8.constInt(1, .False) else llvm_i8.constNull();3415 .none => llvm_i8.constNull(),
3554 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3416 else => llvm_i8.constInt(1, .False),
3417 };
3418 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3555 return non_null_bit;3419 return non_null_bit;
3556 }3420 }
3557 const llvm_ty = try dg.lowerType(tv.ty);3421 const llvm_ty = try dg.lowerType(tv.ty);
3558 if (tv.ty.optionalReprIsPayload()) {3422 if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {
3559 if (tv.val.castTag(.opt_payload)) |payload| {3423 .none => llvm_ty.constNull(),
3560 return dg.lowerValue(.{ .ty = payload_ty, .val = payload.data });3424 else => |payload| dg.lowerValue(.{ .ty = payload_ty, .val = payload.toValue() }),
3561 } else if (is_pl) {3425 };
3562 return dg.lowerValue(.{ .ty = payload_ty, .val = tv.val });3426 assert(payload_ty.zigTypeTag(mod) != .Fn);
3563 } else {
3564 return llvm_ty.constNull();
3565 }
3566 }
3567 assert(payload_ty.zigTypeTag() != .Fn);
35683427
3569 const llvm_field_count = llvm_ty.countStructElementTypes();3428 const llvm_field_count = llvm_ty.countStructElementTypes();
3570 var fields_buf: [3]*llvm.Value = undefined;3429 var fields_buf: [3]*llvm.Value = undefined;
3571 fields_buf[0] = try dg.lowerValue(.{3430 fields_buf[0] = try dg.lowerValue(.{
3572 .ty = payload_ty,3431 .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(),
3574 });3436 });
3575 fields_buf[1] = non_null_bit;3437 fields_buf[1] = non_null_bit;
3576 if (llvm_field_count > 2) {3438 if (llvm_field_count > 2) {
...@@ -3579,76 +3441,100 @@ pub const DeclGen = struct {...@@ -3579,76 +3441,100 @@ pub const DeclGen = struct {
3579 }3441 }
3580 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);3442 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3581 },3443 },
3582 .Fn => {3444 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(tv.ty.toIntern())) {
3583 const fn_decl_index = switch (tv.val.tag()) {3445 .array_type => switch (aggregate.storage) {
3584 .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,3446 .bytes => |bytes| return dg.context.constString(
3585 .function => tv.val.castTag(.function).?.data.owner_decl,3447 bytes.ptr,
3586 else => unreachable,3448 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel(mod)),
3587 };3449 .True, // Don't null terminate. Bytes has the sentinel, if any.
3588 const fn_decl = dg.module.declPtr(fn_decl_index);3450 ),
3589 dg.module.markDeclAlive(fn_decl);3451 .elems => |elem_vals| {
3590 return dg.resolveLlvmFunction(fn_decl_index);3452 const elem_ty = tv.ty.childType(mod);
3591 },3453 const gpa = dg.gpa;
3592 .ErrorSet => {3454 const llvm_elems = try gpa.alloc(*llvm.Value, elem_vals.len);
3593 const llvm_ty = try dg.lowerType(Type.anyerror);3455 defer gpa.free(llvm_elems);
3594 switch (tv.val.tag()) {3456 var need_unnamed = false;
3595 .@"error" => {3457 for (elem_vals, 0..) |elem_val, i| {
3596 const err_name = tv.val.castTag(.@"error").?.data.name;3458 llvm_elems[i] = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_val.toValue() });
3597 const kv = try dg.module.getErrorValue(err_name);3459 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
3598 return llvm_ty.constInt(kv.value, .False);3460 }
3599 },3461 if (need_unnamed) {
3600 else => {3462 return dg.context.constStruct(
3601 // In this case we are rendering an error union which has a 0 bits payload.3463 llvm_elems.ptr,
3602 return llvm_ty.constNull();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 }
3603 },3474 },
3604 }3475 .repeated_elem => |val| {
3605 },3476 const elem_ty = tv.ty.childType(mod);
3606 .ErrorUnion => {3477 const sentinel = tv.ty.sentinel(mod);
3607 const payload_type = tv.ty.errorUnionPayload();3478 const len = @intCast(usize, tv.ty.arrayLen(mod));
3608 const is_pl = tv.val.errorUnionIsPayload();3479 const len_including_sent = len + @boolToInt(sentinel != null);
36093480 const gpa = dg.gpa;
3610 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {3481 const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent);
3611 // We use the error type directly as the type.3482 defer gpa.free(llvm_elems);
3612 const err_val = if (!is_pl) tv.val else Value.initTag(.zero);3483
3613 return dg.lowerValue(.{ .ty = Type.anyerror, .val = err_val });3484 var need_unnamed = false;
3614 }3485 if (len != 0) {
36153486 for (llvm_elems[0..len]) |*elem| {
3616 const payload_align = payload_type.abiAlignment(target);3487 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val.toValue() });
3617 const error_align = Type.anyerror.abiAlignment(target);3488 }
3618 const llvm_error_value = try dg.lowerValue(.{3489 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3619 .ty = Type.anyerror,3490 }
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;
36273491
3628 const llvm_ty = try dg.lowerType(tv.ty);3492 if (sentinel) |sent| {
3629 const llvm_field_count = llvm_ty.countStructElementTypes();3493 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });
3630 if (llvm_field_count > 2) {3494 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
3631 assert(llvm_field_count == 3);3495 }
3632 fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef();
3633 }
36343496
3635 if (error_align > payload_align) {3497 if (need_unnamed) {
3636 fields_buf[0] = llvm_error_value;3498 return dg.context.constStruct(
3637 fields_buf[1] = llvm_payload_value;3499 llvm_elems.ptr,
3638 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);3500 @intCast(c_uint, llvm_elems.len),
3639 } else {3501 .True,
3640 fields_buf[0] = llvm_payload_value;3502 );
3641 fields_buf[1] = llvm_error_value;3503 } else {
3642 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);3504 const llvm_elem_ty = try dg.lowerType(elem_ty);
3643 }3505 return llvm_elem_ty.constArray(
3644 },3506 llvm_elems.ptr,
3645 .Struct => {3507 @intCast(c_uint, llvm_elems.len),
3646 const llvm_struct_ty = try dg.lowerType(tv.ty);3508 );
3647 const field_vals = tv.val.castTag(.aggregate).?.data;3509 }
3648 const gpa = dg.gpa;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();
3652 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};3538 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3653 defer llvm_fields.deinit(gpa);3539 defer llvm_fields.deinit(gpa);
36543540
...@@ -3659,11 +3545,11 @@ pub const DeclGen = struct {...@@ -3659,11 +3545,11 @@ pub const DeclGen = struct {
3659 var big_align: u32 = 0;3545 var big_align: u32 = 0;
3660 var need_unnamed = false;3546 var need_unnamed = false;
36613547
3662 for (tuple.types, 0..) |field_ty, i| {3548 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3663 if (tuple.values[i].tag() != .unreachable_value) continue;3549 if (field_val != .none) continue;
3664 if (!field_ty.hasRuntimeBitsIgnoreComptime()) 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);
3667 big_align = @max(big_align, field_align);3553 big_align = @max(big_align, field_align);
3668 const prev_offset = offset;3554 const prev_offset = offset;
3669 offset = std.mem.alignForwardGeneric(u64, offset, field_align);3555 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
...@@ -3677,15 +3563,15 @@ pub const DeclGen = struct {...@@ -3677,15 +3563,15 @@ pub const DeclGen = struct {
3677 }3563 }
36783564
3679 const field_llvm_val = try dg.lowerValue(.{3565 const field_llvm_val = try dg.lowerValue(.{
3680 .ty = field_ty,3566 .ty = field_ty.toType(),
3681 .val = field_vals[i],3567 .val = try tv.val.fieldValue(mod, i),
3682 });3568 });
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
3686 llvm_fields.appendAssumeCapacity(field_llvm_val);3572 llvm_fields.appendAssumeCapacity(field_llvm_val);
36873573
3688 offset += field_ty.abiSize(target);3574 offset += field_ty.toType().abiSize(mod);
3689 }3575 }
3690 {3576 {
3691 const prev_offset = offset;3577 const prev_offset = offset;
...@@ -3704,132 +3590,142 @@ pub const DeclGen = struct {...@@ -3704,132 +3590,142 @@ pub const DeclGen = struct {
3704 .False,3590 .False,
3705 );3591 );
3706 } else {3592 } else {
3593 const llvm_struct_ty = try dg.lowerType(tv.ty);
3707 return llvm_struct_ty.constNamedStruct(3594 return llvm_struct_ty.constNamedStruct(
3708 llvm_fields.items.ptr,3595 llvm_fields.items.ptr,
3709 @intCast(c_uint, llvm_fields.items.len),3596 @intCast(c_uint, llvm_fields.items.len),
3710 );3597 );
3711 }3598 }
3712 }3599 },
37133600 .struct_type => |struct_type| {
3714 const struct_obj = tv.ty.castTag(.@"struct").?.data;3601 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
37153602 const llvm_struct_ty = try dg.lowerType(tv.ty);
3716 if (struct_obj.layout == .Packed) {3603 const gpa = dg.gpa;
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;
37273604
3728 const non_int_val = try dg.lowerValue(.{3605 if (struct_obj.layout == .Packed) {
3729 .ty = field.ty,3606 assert(struct_obj.haveLayout());
3730 .val = field_val,3607 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
3731 });3608 const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits));
3732 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));3609 const fields = struct_obj.fields.values();
3733 const small_int_ty = dg.context.intType(ty_bit_size);3610 comptime assert(Type.packed_struct_layout_version == 2);
3734 const small_int_val = if (field.ty.isPtrAtRuntime())3611 var running_int: *llvm.Value = int_llvm_ty.constNull();
3735 non_int_val.constPtrToInt(small_int_ty)3612 var running_bits: u16 = 0;
3736 else3613 for (fields, 0..) |field, i| {
3737 non_int_val.constBitCast(small_int_ty);3614 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
3738 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);3615
3739 // If the field is as large as the entire packed struct, this3616 const non_int_val = try dg.lowerValue(.{
3740 // zext would go from, e.g. i16 to i16. This is legal with3617 .ty = field.ty,
3741 // constZExtOrBitCast but not legal with constZExt.3618 .val = try tv.val.fieldValue(mod, i),
3742 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);3619 });
3743 const shifted = extended_int_val.constShl(shift_rhs);3620 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
3744 running_int = running_int.constOr(shifted);3621 const small_int_ty = dg.context.intType(ty_bit_size);
3745 running_bits += 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;
3746 }3636 }
3747 return running_int;
3748 }
37493637
3750 const llvm_field_count = llvm_struct_ty.countStructElementTypes();3638 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3751 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);3639 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3752 defer llvm_fields.deinit(gpa);3640 defer llvm_fields.deinit(gpa);
37533641
3754 comptime assert(struct_layout_version == 2);3642 comptime assert(struct_layout_version == 2);
3755 var offset: u64 = 0;3643 var offset: u64 = 0;
3756 var big_align: u32 = 0;3644 var big_align: u32 = 0;
3757 var need_unnamed = false;3645 var need_unnamed = false;
37583646
3759 var it = struct_obj.runtimeFieldIterator();3647 var it = struct_obj.runtimeFieldIterator(mod);
3760 while (it.next()) |field_and_index| {3648 while (it.next()) |field_and_index| {
3761 const field = field_and_index.field;3649 const field = field_and_index.field;
3762 const field_align = field.alignment(target, struct_obj.layout);3650 const field_align = field.alignment(mod, struct_obj.layout);
3763 big_align = @max(big_align, field_align);3651 big_align = @max(big_align, field_align);
3764 const prev_offset = offset;3652 const prev_offset = offset;
3765 offset = std.mem.alignForwardGeneric(u64, offset, field_align);3653 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
37663654
3767 const padding_len = offset - prev_offset;3655 const padding_len = offset - prev_offset;
3768 if (padding_len > 0) {3656 if (padding_len > 0) {
3769 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));3657 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3770 // TODO make this and all other padding elsewhere in debug3658 // TODO make this and all other padding elsewhere in debug
3771 // builds be 0xaa not undef.3659 // builds be 0xaa not undef.
3772 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());3660 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3773 }3661 }
37743662
3775 const field_llvm_val = try dg.lowerValue(.{3663 const field_llvm_val = try dg.lowerValue(.{
3776 .ty = field.ty,3664 .ty = field.ty,
3777 .val = field_vals[field_and_index.index],3665 .val = try tv.val.fieldValue(mod, field_and_index.index),
3778 });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);3672 offset += field.ty.abiSize(mod);
3785 }3673 }
3786 {3674 {
3787 const prev_offset = offset;3675 const prev_offset = offset;
3788 offset = std.mem.alignForwardGeneric(u64, offset, big_align);3676 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3789 const padding_len = offset - prev_offset;3677 const padding_len = offset - prev_offset;
3790 if (padding_len > 0) {3678 if (padding_len > 0) {
3791 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));3679 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3792 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());3680 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3681 }
3793 }3682 }
3794 }
37953683
3796 if (need_unnamed) {3684 if (need_unnamed) {
3797 return dg.context.constStruct(3685 return dg.context.constStruct(
3798 llvm_fields.items.ptr,3686 llvm_fields.items.ptr,
3799 @intCast(c_uint, llvm_fields.items.len),3687 @intCast(c_uint, llvm_fields.items.len),
3800 .False,3688 .False,
3801 );3689 );
3802 } else {3690 } else {
3803 return llvm_struct_ty.constNamedStruct(3691 return llvm_struct_ty.constNamedStruct(
3804 llvm_fields.items.ptr,3692 llvm_fields.items.ptr,
3805 @intCast(c_uint, llvm_fields.items.len),3693 @intCast(c_uint, llvm_fields.items.len),
3806 );3694 );
3807 }3695 }
3696 },
3697 else => unreachable,
3808 },3698 },
3809 .Union => {3699 .un => {
3810 const llvm_union_ty = try dg.lowerType(tv.ty);3700 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
3815 if (layout.payload_size == 0) {3711 if (layout.payload_size == 0) {
3816 return lowerValue(dg, .{3712 return lowerValue(dg, .{
3817 .ty = tv.ty.unionTagTypeSafety().?,3713 .ty = tv.ty.unionTagTypeSafety(mod).?,
3818 .val = tag_and_val.tag,3714 .val = tag_and_val.tag,
3819 });3715 });
3820 }3716 }
3821 const union_obj = tv.ty.cast(Type.Payload.Union).?.data;3717 const union_obj = mod.typeToUnion(tv.ty).?;
3822 const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?;3718 const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?;
3823 assert(union_obj.haveFieldTypes());3719 assert(union_obj.haveFieldTypes());
38243720
3825 const field_ty = union_obj.fields.values()[field_index].ty;3721 const field_ty = union_obj.fields.values()[field_index].ty;
3826 if (union_obj.layout == .Packed) {3722 if (union_obj.layout == .Packed) {
3827 if (!field_ty.hasRuntimeBits())3723 if (!field_ty.hasRuntimeBits(mod))
3828 return llvm_union_ty.constNull();3724 return llvm_union_ty.constNull();
3829 const non_int_val = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });3725 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));
3831 const small_int_ty = dg.context.intType(ty_bit_size);3727 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))
3833 non_int_val.constPtrToInt(small_int_ty)3729 non_int_val.constPtrToInt(small_int_ty)
3834 else3730 else
3835 non_int_val.constBitCast(small_int_ty);3731 non_int_val.constBitCast(small_int_ty);
...@@ -3842,13 +3738,13 @@ pub const DeclGen = struct {...@@ -3842,13 +3738,13 @@ pub const DeclGen = struct {
3842 // must pointer cast to the expected type before accessing the union.3738 // must pointer cast to the expected type before accessing the union.
3843 var need_unnamed: bool = layout.most_aligned_field != field_index;3739 var need_unnamed: bool = layout.most_aligned_field != field_index;
3844 const payload = p: {3740 const payload = p: {
3845 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {3741 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3846 const padding_len = @intCast(c_uint, layout.payload_size);3742 const padding_len = @intCast(c_uint, layout.payload_size);
3847 break :p dg.context.intType(8).arrayType(padding_len).getUndef();3743 break :p dg.context.intType(8).arrayType(padding_len).getUndef();
3848 }3744 }
3849 const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });3745 const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });
3850 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field);3746 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);
3852 if (field_size == layout.payload_size) {3748 if (field_size == layout.payload_size) {
3853 break :p field;3749 break :p field;
3854 }3750 }
...@@ -3868,7 +3764,7 @@ pub const DeclGen = struct {...@@ -3868,7 +3764,7 @@ pub const DeclGen = struct {
3868 }3764 }
3869 }3765 }
3870 const llvm_tag_value = try lowerValue(dg, .{3766 const llvm_tag_value = try lowerValue(dg, .{
3871 .ty = tv.ty.unionTagTypeSafety().?,3767 .ty = tv.ty.unionTagTypeSafety(mod).?,
3872 .val = tag_and_val.tag,3768 .val = tag_and_val.tag,
3873 });3769 });
3874 var fields: [3]*llvm.Value = undefined;3770 var fields: [3]*llvm.Value = undefined;
...@@ -3888,107 +3784,45 @@ pub const DeclGen = struct {...@@ -3888,107 +3784,45 @@ pub const DeclGen = struct {
3888 return llvm_union_ty.constNamedStruct(&fields, fields_len);3784 return llvm_union_ty.constNamedStruct(&fields, fields_len);
3889 }3785 }
3890 },3786 },
3891 .Vector => switch (tv.val.tag()) {3787 .memoized_call => unreachable,
3892 .bytes => {3788 }
3893 // Note, sentinel is not stored even if the type has a sentinel.3789 }
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 };
39643790
3965 elem.* = try dg.lowerValue(.{3791 fn lowerIntAsPtr(dg: *DeclGen, val: Value) Error!*llvm.Value {
3966 .ty = elem_ty,3792 switch (dg.module.intern_pool.indexToKey(val.toIntern())) {
3967 .val = Value.initPayload(&byte_payload.base),3793 .undef => return dg.context.pointerType(0).getUndef(),
3968 });3794 .int => {
3969 }3795 var bigint_space: Value.BigIntSpace = undefined;
3970 return llvm.constVector(3796 const bigint = val.toBigInt(&bigint_space, dg.module);
3971 llvm_elems.ptr,3797 const llvm_int = lowerBigInt(dg, Type.usize, bigint);
3972 @intCast(c_uint, llvm_elems.len),3798 return llvm_int.constIntToPtr(dg.context.pointerType(0));
3973 );
3974 },
3975 else => unreachable,
3976 },3799 },
3800 else => unreachable,
3801 }
3802 }
39773803
3978 .ComptimeInt => unreachable,3804 fn lowerBigInt(dg: *DeclGen, ty: Type, bigint: std.math.big.int.Const) *llvm.Value {
3979 .ComptimeFloat => unreachable,3805 const mod = dg.module;
3980 .Type => unreachable,3806 const int_info = ty.intInfo(mod);
3981 .EnumLiteral => unreachable,3807 assert(int_info.bits != 0);
3982 .Void => unreachable,3808 const llvm_type = dg.context.intType(int_info.bits);
3983 .NoReturn => unreachable,
3984 .Undefined => unreachable,
3985 .Null => unreachable,
3986 .Opaque => unreachable,
39873809
3988 .Frame,3810 const unsigned_val = v: {
3989 .AnyFrame,3811 if (bigint.limbs.len == 1) {
3990 => return dg.todo("implement const of type '{}'", .{tv.ty.fmtDebug()}),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);
3991 }3824 }
3825 return unsigned_val;
3992 }3826 }
39933827
3994 const ParentPtr = struct {3828 const ParentPtr = struct {
...@@ -4001,57 +3835,86 @@ pub const DeclGen = struct {...@@ -4001,57 +3835,86 @@ pub const DeclGen = struct {
4001 ptr_val: Value,3835 ptr_val: Value,
4002 decl_index: Module.Decl.Index,3836 decl_index: Module.Decl.Index,
4003 ) Error!*llvm.Value {3837 ) Error!*llvm.Value {
4004 const decl = dg.module.declPtr(decl_index);3838 const mod = dg.module;
4005 dg.module.markDeclAlive(decl);3839 const decl = mod.declPtr(decl_index);
4006 var ptr_ty_payload: Type.Payload.ElemType = .{3840 try mod.markDeclAlive(decl);
4007 .base = .{ .tag = .single_mut_pointer },3841 const ptr_ty = try mod.singleMutPtrType(decl.ty);
4008 .data = decl.ty,
4009 };
4010 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4011 return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);3842 return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);
4012 }3843 }
40133844
4014 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value {3845 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value {
4015 const target = dg.module.getTarget();3846 const mod = dg.module;
4016 switch (ptr_val.tag()) {3847 const target = mod.getTarget();
4017 .decl_ref_mut => {3848 return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) {
4018 const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;3849 .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl),
4019 return dg.lowerParentPtrDecl(ptr_val, decl);3850 .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl),
4020 },3851 .int => |int| dg.lowerIntAsPtr(int.toValue()),
4021 .decl_ref => {3852 .eu_payload => |eu_ptr| {
4022 const decl = ptr_val.castTag(.decl_ref).?.data;3853 const parent_llvm_ptr = try dg.lowerParentPtr(eu_ptr.toValue(), true);
4023 return dg.lowerParentPtrDecl(ptr_val, decl);3854
4024 },3855 const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod);
4025 .variable => {3856 const payload_ty = eu_ty.errorUnionPayload(mod);
4026 const decl = ptr_val.castTag(.variable).?.data.owner_decl;3857 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4027 return dg.lowerParentPtrDecl(ptr_val, decl);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);
4028 },3871 },
4029 .int_i64 => {3872 .opt_payload => |opt_ptr| {
4030 const int = ptr_val.castTag(.int_i64).?.data;3873 const parent_llvm_ptr = try dg.lowerParentPtr(opt_ptr.toValue(), true);
4031 const llvm_usize = try dg.lowerType(Type.usize);3874
4032 const llvm_int = llvm_usize.constInt(@bitCast(u64, int), .False);3875 const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod);
4033 return llvm_int.constIntToPtr(dg.context.pointerType(0));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);
4034 },3892 },
4035 .int_u64 => {3893 .comptime_field => unreachable,
4036 const int = ptr_val.castTag(.int_u64).?.data;3894 .elem => |elem_ptr| {
3895 const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.base.toValue(), true);
3896
4037 const llvm_usize = try dg.lowerType(Type.usize);3897 const llvm_usize = try dg.lowerType(Type.usize);
4038 const llvm_int = llvm_usize.constInt(int, .False);3898 const indices: [1]*llvm.Value = .{
4039 return llvm_int.constIntToPtr(dg.context.pointerType(0));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);
4040 },3904 },
4041 .field_ptr => {3905 .field => |field_ptr| {
4042 const field_ptr = ptr_val.castTag(.field_ptr).?.data;3906 const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.base.toValue(), byte_aligned);
4043 const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr, byte_aligned);3907 const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
4044 const parent_ty = field_ptr.container_ty;
40453908
4046 const field_index = @intCast(u32, field_ptr.field_index);3909 const field_index = @intCast(u32, field_ptr.index);
4047 const llvm_u32 = dg.context.intType(32);3910 const llvm_u32 = dg.context.intType(32);
4048 switch (parent_ty.zigTypeTag()) {3911 switch (parent_ty.zigTypeTag(mod)) {
4049 .Union => {3912 .Union => {
4050 if (parent_ty.containerLayout() == .Packed) {3913 if (parent_ty.containerLayout(mod) == .Packed) {
4051 return parent_llvm_ptr;3914 return parent_llvm_ptr;
4052 }3915 }
40533916
4054 const layout = parent_ty.unionGetLayout(target);3917 const layout = parent_ty.unionGetLayout(mod);
4055 if (layout.payload_size == 0) {3918 if (layout.payload_size == 0) {
4056 // In this case a pointer to the union and a pointer to any3919 // In this case a pointer to the union and a pointer to any
4057 // (void) payload is the same.3920 // (void) payload is the same.
...@@ -4069,16 +3932,16 @@ pub const DeclGen = struct {...@@ -4069,16 +3932,16 @@ pub const DeclGen = struct {
4069 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);3932 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4070 },3933 },
4071 .Struct => {3934 .Struct => {
4072 if (parent_ty.containerLayout() == .Packed) {3935 if (parent_ty.containerLayout(mod) == .Packed) {
4073 if (!byte_aligned) return parent_llvm_ptr;3936 if (!byte_aligned) return parent_llvm_ptr;
4074 const llvm_usize = dg.context.intType(target.ptrBitWidth());3937 const llvm_usize = dg.context.intType(target.ptrBitWidth());
4075 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);3938 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
4076 // count bits of fields before this one3939 // count bits of fields before this one
4077 const prev_bits = b: {3940 const prev_bits = b: {
4078 var b: usize = 0;3941 var b: usize = 0;
4079 for (parent_ty.structFields().values()[0..field_index]) |field| {3942 for (parent_ty.structFields(mod).values()[0..field_index]) |field| {
4080 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;3943 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
4081 b += @intCast(usize, field.ty.bitSize(target));3944 b += @intCast(usize, field.ty.bitSize(mod));
4082 }3945 }
4083 break :b b;3946 break :b b;
4084 };3947 };
...@@ -4088,23 +3951,21 @@ pub const DeclGen = struct {...@@ -4088,23 +3951,21 @@ pub const DeclGen = struct {
4088 return field_addr.constIntToPtr(final_llvm_ty);3951 return field_addr.constIntToPtr(final_llvm_ty);
4089 }3952 }
40903953
4091 var ty_buf: Type.Payload.Pointer = undefined;
4092
4093 const parent_llvm_ty = try dg.lowerType(parent_ty);3954 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| {
4095 const indices: [2]*llvm.Value = .{3956 const indices: [2]*llvm.Value = .{
4096 llvm_u32.constInt(0, .False),3957 llvm_u32.constInt(0, .False),
4097 llvm_u32.constInt(llvm_field_index, .False),3958 llvm_u32.constInt(llvm_field.index, .False),
4098 };3959 };
4099 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);3960 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4100 } else {3961 } 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);
4102 const indices: [1]*llvm.Value = .{llvm_index};3963 const indices: [1]*llvm.Value = .{llvm_index};
4103 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);3964 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4104 }3965 }
4105 },3966 },
4106 .Pointer => {3967 .Pointer => {
4107 assert(parent_ty.isSlice());3968 assert(parent_ty.isSlice(mod));
4108 const indices: [2]*llvm.Value = .{3969 const indices: [2]*llvm.Value = .{
4109 llvm_u32.constInt(0, .False),3970 llvm_u32.constInt(0, .False),
4110 llvm_u32.constInt(field_index, .False),3971 llvm_u32.constInt(field_index, .False),
...@@ -4115,61 +3976,7 @@ pub const DeclGen = struct {...@@ -4115,61 +3976,7 @@ pub const DeclGen = struct {
4115 else => unreachable,3976 else => unreachable,
4116 }3977 }
4117 },3978 },
4118 .elem_ptr => {3979 };
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 }
4173 }3980 }
41743981
4175 fn lowerDeclRefValue(3982 fn lowerDeclRefValue(
...@@ -4177,57 +3984,39 @@ pub const DeclGen = struct {...@@ -4177,57 +3984,39 @@ pub const DeclGen = struct {
4177 tv: TypedValue,3984 tv: TypedValue,
4178 decl_index: Module.Decl.Index,3985 decl_index: Module.Decl.Index,
4179 ) Error!*llvm.Value {3986 ) Error!*llvm.Value {
4180 if (tv.ty.isSlice()) {3987 const mod = self.module;
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 }
41993988
4200 // In the case of something like:3989 // In the case of something like:
4201 // fn foo() void {}3990 // fn foo() void {}
4202 // const bar = foo;3991 // const bar = foo;
4203 // ... &bar;3992 // ... &bar;
4204 // `bar` is just an alias and we actually want to lower a reference to `foo`.3993 // `bar` is just an alias and we actually want to lower a reference to `foo`.
4205 const decl = self.module.declPtr(decl_index);3994 const decl = mod.declPtr(decl_index);
4206 if (decl.val.castTag(.function)) |func| {3995 if (decl.val.getFunction(mod)) |func| {
4207 if (func.data.owner_decl != decl_index) {3996 if (func.owner_decl != decl_index) {
4208 return self.lowerDeclRefValue(tv, func.data.owner_decl);3997 return self.lowerDeclRefValue(tv, func.owner_decl);
4209 }3998 }
4210 } else if (decl.val.castTag(.extern_fn)) |func| {3999 } else if (decl.val.getExternFunc(mod)) |func| {
4211 if (func.data.owner_decl != decl_index) {4000 if (func.decl != decl_index) {
4212 return self.lowerDeclRefValue(tv, func.data.owner_decl);4001 return self.lowerDeclRefValue(tv, func.decl);
4213 }4002 }
4214 }4003 }
42154004
4216 const is_fn_body = decl.ty.zigTypeTag() == .Fn;4005 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;
4217 if ((!is_fn_body and !decl.ty.hasRuntimeBits()) or4006 if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or
4218 (is_fn_body and decl.ty.fnInfo().is_generic))4007 (is_fn_body and mod.typeToFunc(decl.ty).?.is_generic))
4219 {4008 {
4220 return self.lowerPtrToVoid(tv.ty);4009 return self.lowerPtrToVoid(tv.ty);
4221 }4010 }
42224011
4223 self.module.markDeclAlive(decl);4012 try mod.markDeclAlive(decl);
42244013
4225 const llvm_decl_val = if (is_fn_body)4014 const llvm_decl_val = if (is_fn_body)
4226 try self.resolveLlvmFunction(decl_index)4015 try self.resolveLlvmFunction(decl_index)
4227 else4016 else
4228 try self.resolveGlobalDecl(decl_index);4017 try self.resolveGlobalDecl(decl_index);
42294018
4230 const target = self.module.getTarget();4019 const target = mod.getTarget();
4231 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);4020 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
4232 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);4021 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
4233 const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) blk: {4022 const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) blk: {
...@@ -4236,7 +4025,7 @@ pub const DeclGen = struct {...@@ -4236,7 +4025,7 @@ pub const DeclGen = struct {
4236 } else llvm_decl_val;4025 } else llvm_decl_val;
42374026
4238 const llvm_type = try self.lowerType(tv.ty);4027 const llvm_type = try self.lowerType(tv.ty);
4239 if (tv.ty.zigTypeTag() == .Int) {4028 if (tv.ty.zigTypeTag(mod) == .Int) {
4240 return llvm_val.constPtrToInt(llvm_type);4029 return llvm_val.constPtrToInt(llvm_type);
4241 } else {4030 } else {
4242 return llvm_val.constBitCast(llvm_type);4031 return llvm_val.constBitCast(llvm_type);
...@@ -4244,7 +4033,8 @@ pub const DeclGen = struct {...@@ -4244,7 +4033,8 @@ pub const DeclGen = struct {
4244 }4033 }
42454034
4246 fn lowerPtrToVoid(dg: *DeclGen, ptr_ty: Type) !*llvm.Value {4035 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";
4248 // Even though we are pointing at something which has zero bits (e.g. `void`),4038 // Even though we are pointing at something which has zero bits (e.g. `void`),
4249 // Pointers are defined to have bits. So we must return something here.4039 // Pointers are defined to have bits. So we must return something here.
4250 // The value cannot be undefined, because we use the `nonnull` annotation4040 // The value cannot be undefined, because we use the `nonnull` annotation
...@@ -4338,21 +4128,20 @@ pub const DeclGen = struct {...@@ -4338,21 +4128,20 @@ pub const DeclGen = struct {
4338 /// RMW exchange of floating-point values is bitcasted to same-sized integer4128 /// RMW exchange of floating-point values is bitcasted to same-sized integer
4339 /// types to work around a LLVM deficiency when targeting ARM/AArch64.4129 /// types to work around a LLVM deficiency when targeting ARM/AArch64.
4340 fn getAtomicAbiType(dg: *DeclGen, ty: Type, is_rmw_xchg: bool) ?*llvm.Type {4130 fn getAtomicAbiType(dg: *DeclGen, ty: Type, is_rmw_xchg: bool) ?*llvm.Type {
4341 const target = dg.module.getTarget();4131 const mod = dg.module;
4342 var buffer: Type.Payload.Bits = undefined;4132 const int_ty = switch (ty.zigTypeTag(mod)) {
4343 const int_ty = switch (ty.zigTypeTag()) {
4344 .Int => ty,4133 .Int => ty,
4345 .Enum => ty.intTagType(&buffer),4134 .Enum => ty.intTagType(mod),
4346 .Float => {4135 .Float => {
4347 if (!is_rmw_xchg) return null;4136 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));
4349 },4138 },
4350 .Bool => return dg.context.intType(8),4139 .Bool => return dg.context.intType(8),
4351 else => return null,4140 else => return null,
4352 };4141 };
4353 const bit_count = int_ty.intInfo(target).bits;4142 const bit_count = int_ty.intInfo(mod).bits;
4354 if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) {4143 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));
4356 } else {4145 } else {
4357 return null;4146 return null;
4358 }4147 }
...@@ -4363,18 +4152,18 @@ pub const DeclGen = struct {...@@ -4363,18 +4152,18 @@ pub const DeclGen = struct {
4363 llvm_fn: *llvm.Value,4152 llvm_fn: *llvm.Value,
4364 param_ty: Type,4153 param_ty: Type,
4365 param_index: u32,4154 param_index: u32,
4366 fn_info: Type.Payload.Function.Data,4155 fn_info: InternPool.Key.FuncType,
4367 llvm_arg_i: u32,4156 llvm_arg_i: u32,
4368 ) void {4157 ) void {
4369 const target = dg.module.getTarget();4158 const mod = dg.module;
4370 if (param_ty.isPtrAtRuntime()) {4159 if (param_ty.isPtrAtRuntime(mod)) {
4371 const ptr_info = param_ty.ptrInfo().data;4160 const ptr_info = param_ty.ptrInfo(mod);
4372 if (math.cast(u5, param_index)) |i| {4161 if (math.cast(u5, param_index)) |i| {
4373 if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {4162 if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
4374 dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias");4163 dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias");
4375 }4164 }
4376 }4165 }
4377 if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") {4166 if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.@"allowzero") {
4378 dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");4167 dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
4379 }4168 }
4380 if (!ptr_info.mutable) {4169 if (!ptr_info.mutable) {
...@@ -4383,13 +4172,10 @@ pub const DeclGen = struct {...@@ -4383,13 +4172,10 @@ pub const DeclGen = struct {
4383 if (ptr_info.@"align" != 0) {4172 if (ptr_info.@"align" != 0) {
4384 dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align");4173 dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align");
4385 } else {4174 } else {
4386 const elem_align = @max(4175 const elem_align = @max(ptr_info.pointee_type.abiAlignment(mod), 1);
4387 ptr_info.pointee_type.abiAlignment(target),
4388 1,
4389 );
4390 dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align);4176 dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align);
4391 }4177 }
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) {
4393 .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"),4179 .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"),
4394 .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"),4180 .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"),
4395 };4181 };
...@@ -4490,21 +4276,23 @@ pub const FuncGen = struct {...@@ -4490,21 +4276,23 @@ pub const FuncGen = struct {
4490 const gop = try self.func_inst_table.getOrPut(self.dg.gpa, inst);4276 const gop = try self.func_inst_table.getOrPut(self.dg.gpa, inst);
4491 if (gop.found_existing) return gop.value_ptr.*;4277 if (gop.found_existing) return gop.value_ptr.*;
44924278
4279 const mod = self.dg.module;
4493 const llvm_val = try self.resolveValue(.{4280 const llvm_val = try self.resolveValue(.{
4494 .ty = self.air.typeOf(inst),4281 .ty = self.typeOf(inst),
4495 .val = self.air.value(inst).?,4282 .val = (try self.air.value(inst, mod)).?,
4496 });4283 });
4497 gop.value_ptr.* = llvm_val;4284 gop.value_ptr.* = llvm_val;
4498 return llvm_val;4285 return llvm_val;
4499 }4286 }
45004287
4501 fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value {4288 fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value {
4289 const mod = self.dg.module;
4502 const llvm_val = try self.dg.lowerValue(tv);4290 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
4505 // We have an LLVM value but we need to create a global constant and4293 // We have an LLVM value but we need to create a global constant and
4506 // set the value as its initializer, and then return a pointer to the global.4294 // 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();
4508 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);4296 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);
4509 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);4297 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);
4510 const global = self.dg.object.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace);4298 const global = self.dg.object.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace);
...@@ -4512,7 +4300,7 @@ pub const FuncGen = struct {...@@ -4512,7 +4300,7 @@ pub const FuncGen = struct {
4512 global.setLinkage(.Private);4300 global.setLinkage(.Private);
4513 global.setGlobalConstant(.True);4301 global.setGlobalConstant(.True);
4514 global.setUnnamedAddr(.True);4302 global.setUnnamedAddr(.True);
4515 global.setAlignment(tv.ty.abiAlignment(target));4303 global.setAlignment(tv.ty.abiAlignment(mod));
4516 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)4304 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
4517 global.constAddrSpaceCast(self.context.pointerType(llvm_wanted_addrspace))4305 global.constAddrSpaceCast(self.context.pointerType(llvm_wanted_addrspace))
4518 else4306 else
...@@ -4521,11 +4309,12 @@ pub const FuncGen = struct {...@@ -4521,11 +4309,12 @@ pub const FuncGen = struct {
4521 }4309 }
45224310
4523 fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void {4311 fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void {
4312 const mod = self.dg.module;
4313 const ip = &mod.intern_pool;
4524 const air_tags = self.air.instructions.items(.tag);4314 const air_tags = self.air.instructions.items(.tag);
4525 for (body, 0..) |inst, i| {4315 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))
4527 continue;4317 continue;
4528 }
45294318
4530 const opt_value: ?*llvm.Value = switch (air_tags[inst]) {4319 const opt_value: ?*llvm.Value = switch (air_tags[inst]) {
4531 // zig fmt: off4320 // zig fmt: off
...@@ -4742,8 +4531,8 @@ pub const FuncGen = struct {...@@ -4742,8 +4531,8 @@ pub const FuncGen = struct {
47424531
4743 .vector_store_elem => try self.airVectorStoreElem(inst),4532 .vector_store_elem => try self.airVectorStoreElem(inst),
47444533
4745 .constant => unreachable,4534 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
4746 .const_ty => unreachable,4535
4747 .unreach => self.airUnreach(inst),4536 .unreach => self.airUnreach(inst),
4748 .dbg_stmt => self.airDbgStmt(inst),4537 .dbg_stmt => self.airDbgStmt(inst),
4749 .dbg_inline_begin => try self.airDbgInlineBegin(inst),4538 .dbg_inline_begin => try self.airDbgInlineBegin(inst),
...@@ -4774,29 +4563,30 @@ pub const FuncGen = struct {...@@ -4774,29 +4563,30 @@ pub const FuncGen = struct {
4774 const pl_op = self.air.instructions.items(.data)[inst].pl_op;4563 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
4775 const extra = self.air.extraData(Air.Call, pl_op.payload);4564 const extra = self.air.extraData(Air.Call, pl_op.payload);
4776 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);4565 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);4566 const mod = self.dg.module;
4778 const zig_fn_ty = switch (callee_ty.zigTypeTag()) {4567 const callee_ty = self.typeOf(pl_op.operand);
4568 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
4779 .Fn => callee_ty,4569 .Fn => callee_ty,
4780 .Pointer => callee_ty.childType(),4570 .Pointer => callee_ty.childType(mod),
4781 else => unreachable,4571 else => unreachable,
4782 };4572 };
4783 const fn_info = zig_fn_ty.fnInfo();4573 const fn_info = mod.typeToFunc(zig_fn_ty).?;
4784 const return_type = fn_info.return_type;4574 const return_type = fn_info.return_type.toType();
4785 const llvm_fn = try self.resolveInst(pl_op.operand);4575 const llvm_fn = try self.resolveInst(pl_op.operand);
4786 const target = self.dg.module.getTarget();4576 const target = mod.getTarget();
4787 const sret = firstParamSRet(fn_info, target);4577 const sret = firstParamSRet(fn_info, mod);
47884578
4789 var llvm_args = std.ArrayList(*llvm.Value).init(self.gpa);4579 var llvm_args = std.ArrayList(*llvm.Value).init(self.gpa);
4790 defer llvm_args.deinit();4580 defer llvm_args.deinit();
47914581
4792 const ret_ptr = if (!sret) null else blk: {4582 const ret_ptr = if (!sret) null else blk: {
4793 const llvm_ret_ty = try self.dg.lowerType(return_type);4583 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));
4795 try llvm_args.append(ret_ptr);4585 try llvm_args.append(ret_ptr);
4796 break :blk ret_ptr;4586 break :blk ret_ptr;
4797 };4587 };
47984588
4799 const err_return_tracing = fn_info.return_type.isError() and4589 const err_return_tracing = return_type.isError(mod) and
4800 self.dg.module.comp.bin_file.options.error_return_tracing;4590 self.dg.module.comp.bin_file.options.error_return_tracing;
4801 if (err_return_tracing) {4591 if (err_return_tracing) {
4802 try llvm_args.append(self.err_ret_trace.?);4592 try llvm_args.append(self.err_ret_trace.?);
...@@ -4807,11 +4597,11 @@ pub const FuncGen = struct {...@@ -4807,11 +4597,11 @@ pub const FuncGen = struct {
4807 .no_bits => continue,4597 .no_bits => continue,
4808 .byval => {4598 .byval => {
4809 const arg = args[it.zig_index - 1];4599 const arg = args[it.zig_index - 1];
4810 const param_ty = self.air.typeOf(arg);4600 const param_ty = self.typeOf(arg);
4811 const llvm_arg = try self.resolveInst(arg);4601 const llvm_arg = try self.resolveInst(arg);
4812 const llvm_param_ty = try self.dg.lowerType(param_ty);4602 const llvm_param_ty = try self.dg.lowerType(param_ty);
4813 if (isByRef(param_ty)) {4603 if (isByRef(param_ty, mod)) {
4814 const alignment = param_ty.abiAlignment(target);4604 const alignment = param_ty.abiAlignment(mod);
4815 const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, "");4605 const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, "");
4816 load_inst.setAlignment(alignment);4606 load_inst.setAlignment(alignment);
4817 try llvm_args.append(load_inst);4607 try llvm_args.append(load_inst);
...@@ -4821,12 +4611,12 @@ pub const FuncGen = struct {...@@ -4821,12 +4611,12 @@ pub const FuncGen = struct {
4821 },4611 },
4822 .byref => {4612 .byref => {
4823 const arg = args[it.zig_index - 1];4613 const arg = args[it.zig_index - 1];
4824 const param_ty = self.air.typeOf(arg);4614 const param_ty = self.typeOf(arg);
4825 const llvm_arg = try self.resolveInst(arg);4615 const llvm_arg = try self.resolveInst(arg);
4826 if (isByRef(param_ty)) {4616 if (isByRef(param_ty, mod)) {
4827 try llvm_args.append(llvm_arg);4617 try llvm_args.append(llvm_arg);
4828 } else {4618 } else {
4829 const alignment = param_ty.abiAlignment(target);4619 const alignment = param_ty.abiAlignment(mod);
4830 const param_llvm_ty = llvm_arg.typeOf();4620 const param_llvm_ty = llvm_arg.typeOf();
4831 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);4621 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);
4832 const store_inst = self.builder.buildStore(llvm_arg, arg_ptr);4622 const store_inst = self.builder.buildStore(llvm_arg, arg_ptr);
...@@ -4836,13 +4626,13 @@ pub const FuncGen = struct {...@@ -4836,13 +4626,13 @@ pub const FuncGen = struct {
4836 },4626 },
4837 .byref_mut => {4627 .byref_mut => {
4838 const arg = args[it.zig_index - 1];4628 const arg = args[it.zig_index - 1];
4839 const param_ty = self.air.typeOf(arg);4629 const param_ty = self.typeOf(arg);
4840 const llvm_arg = try self.resolveInst(arg);4630 const llvm_arg = try self.resolveInst(arg);
48414631
4842 const alignment = param_ty.abiAlignment(target);4632 const alignment = param_ty.abiAlignment(mod);
4843 const param_llvm_ty = try self.dg.lowerType(param_ty);4633 const param_llvm_ty = try self.dg.lowerType(param_ty);
4844 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);4634 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);
4845 if (isByRef(param_ty)) {4635 if (isByRef(param_ty, mod)) {
4846 const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, "");4636 const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, "");
4847 load_inst.setAlignment(alignment);4637 load_inst.setAlignment(alignment);
48484638
...@@ -4857,13 +4647,13 @@ pub const FuncGen = struct {...@@ -4857,13 +4647,13 @@ pub const FuncGen = struct {
4857 },4647 },
4858 .abi_sized_int => {4648 .abi_sized_int => {
4859 const arg = args[it.zig_index - 1];4649 const arg = args[it.zig_index - 1];
4860 const param_ty = self.air.typeOf(arg);4650 const param_ty = self.typeOf(arg);
4861 const llvm_arg = try self.resolveInst(arg);4651 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));
4863 const int_llvm_ty = self.context.intType(abi_size * 8);4653 const int_llvm_ty = self.context.intType(abi_size * 8);
48644654
4865 if (isByRef(param_ty)) {4655 if (isByRef(param_ty, mod)) {
4866 const alignment = param_ty.abiAlignment(target);4656 const alignment = param_ty.abiAlignment(mod);
4867 const load_inst = self.builder.buildLoad(int_llvm_ty, llvm_arg, "");4657 const load_inst = self.builder.buildLoad(int_llvm_ty, llvm_arg, "");
4868 load_inst.setAlignment(alignment);4658 load_inst.setAlignment(alignment);
4869 try llvm_args.append(load_inst);4659 try llvm_args.append(load_inst);
...@@ -4871,7 +4661,7 @@ pub const FuncGen = struct {...@@ -4871,7 +4661,7 @@ pub const FuncGen = struct {
4871 // LLVM does not allow bitcasting structs so we must allocate4661 // LLVM does not allow bitcasting structs so we must allocate
4872 // a local, store as one type, and then load as another type.4662 // a local, store as one type, and then load as another type.
4873 const alignment = @max(4663 const alignment = @max(
4874 param_ty.abiAlignment(target),4664 param_ty.abiAlignment(mod),
4875 self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty),4665 self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty),
4876 );4666 );
4877 const int_ptr = self.buildAlloca(int_llvm_ty, alignment);4667 const int_ptr = self.buildAlloca(int_llvm_ty, alignment);
...@@ -4893,14 +4683,14 @@ pub const FuncGen = struct {...@@ -4893,14 +4683,14 @@ pub const FuncGen = struct {
4893 },4683 },
4894 .multiple_llvm_types => {4684 .multiple_llvm_types => {
4895 const arg = args[it.zig_index - 1];4685 const arg = args[it.zig_index - 1];
4896 const param_ty = self.air.typeOf(arg);4686 const param_ty = self.typeOf(arg);
4897 const llvm_types = it.llvm_types_buffer[0..it.llvm_types_len];4687 const llvm_types = it.llvm_types_buffer[0..it.llvm_types_len];
4898 const llvm_arg = try self.resolveInst(arg);4688 const llvm_arg = try self.resolveInst(arg);
4899 const is_by_ref = isByRef(param_ty);4689 const is_by_ref = isByRef(param_ty, mod);
4900 const arg_ptr = if (is_by_ref) llvm_arg else p: {4690 const arg_ptr = if (is_by_ref) llvm_arg else p: {
4901 const p = self.buildAlloca(llvm_arg.typeOf(), null);4691 const p = self.buildAlloca(llvm_arg.typeOf(), null);
4902 const store_inst = self.builder.buildStore(llvm_arg, p);4692 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));
4904 break :p p;4694 break :p p;
4905 };4695 };
49064696
...@@ -4922,19 +4712,19 @@ pub const FuncGen = struct {...@@ -4922,19 +4712,19 @@ pub const FuncGen = struct {
4922 },4712 },
4923 .float_array => |count| {4713 .float_array => |count| {
4924 const arg = args[it.zig_index - 1];4714 const arg = args[it.zig_index - 1];
4925 const arg_ty = self.air.typeOf(arg);4715 const arg_ty = self.typeOf(arg);
4926 var llvm_arg = try self.resolveInst(arg);4716 var llvm_arg = try self.resolveInst(arg);
4927 if (!isByRef(arg_ty)) {4717 if (!isByRef(arg_ty, mod)) {
4928 const p = self.buildAlloca(llvm_arg.typeOf(), null);4718 const p = self.buildAlloca(llvm_arg.typeOf(), null);
4929 const store_inst = self.builder.buildStore(llvm_arg, p);4719 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));
4931 llvm_arg = store_inst;4721 llvm_arg = store_inst;
4932 }4722 }
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).?);
4935 const array_llvm_ty = float_ty.arrayType(count);4725 const array_llvm_ty = float_ty.arrayType(count);
49364726
4937 const alignment = arg_ty.abiAlignment(target);4727 const alignment = arg_ty.abiAlignment(mod);
4938 const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, "");4728 const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, "");
4939 load_inst.setAlignment(alignment);4729 load_inst.setAlignment(alignment);
4940 try llvm_args.append(load_inst);4730 try llvm_args.append(load_inst);
...@@ -4942,17 +4732,17 @@ pub const FuncGen = struct {...@@ -4942,17 +4732,17 @@ pub const FuncGen = struct {
4942 .i32_array, .i64_array => |arr_len| {4732 .i32_array, .i64_array => |arr_len| {
4943 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;4733 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
4944 const arg = args[it.zig_index - 1];4734 const arg = args[it.zig_index - 1];
4945 const arg_ty = self.air.typeOf(arg);4735 const arg_ty = self.typeOf(arg);
4946 var llvm_arg = try self.resolveInst(arg);4736 var llvm_arg = try self.resolveInst(arg);
4947 if (!isByRef(arg_ty)) {4737 if (!isByRef(arg_ty, mod)) {
4948 const p = self.buildAlloca(llvm_arg.typeOf(), null);4738 const p = self.buildAlloca(llvm_arg.typeOf(), null);
4949 const store_inst = self.builder.buildStore(llvm_arg, p);4739 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));
4951 llvm_arg = store_inst;4741 llvm_arg = store_inst;
4952 }4742 }
49534743
4954 const array_llvm_ty = self.context.intType(elem_size).arrayType(arr_len);4744 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);
4956 const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, "");4746 const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, "");
4957 load_inst.setAlignment(alignment);4747 load_inst.setAlignment(alignment);
4958 try llvm_args.append(load_inst);4748 try llvm_args.append(load_inst);
...@@ -4969,7 +4759,7 @@ pub const FuncGen = struct {...@@ -4969,7 +4759,7 @@ pub const FuncGen = struct {
4969 "",4759 "",
4970 );4760 );
49714761
4972 if (callee_ty.zigTypeTag() == .Pointer) {4762 if (callee_ty.zigTypeTag(mod) == .Pointer) {
4973 // Add argument attributes for function pointer calls.4763 // Add argument attributes for function pointer calls.
4974 it = iterateParamTypes(self.dg, fn_info);4764 it = iterateParamTypes(self.dg, fn_info);
4975 it.llvm_index += @boolToInt(sret);4765 it.llvm_index += @boolToInt(sret);
...@@ -4977,16 +4767,16 @@ pub const FuncGen = struct {...@@ -4977,16 +4767,16 @@ pub const FuncGen = struct {
4977 while (it.next()) |lowering| switch (lowering) {4767 while (it.next()) |lowering| switch (lowering) {
4978 .byval => {4768 .byval => {
4979 const param_index = it.zig_index - 1;4769 const param_index = it.zig_index - 1;
4980 const param_ty = fn_info.param_types[param_index];4770 const param_ty = fn_info.param_types[param_index].toType();
4981 if (!isByRef(param_ty)) {4771 if (!isByRef(param_ty, mod)) {
4982 self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);4772 self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
4983 }4773 }
4984 },4774 },
4985 .byref => {4775 .byref => {
4986 const param_index = it.zig_index - 1;4776 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();
4988 const param_llvm_ty = try self.dg.lowerType(param_ty);4778 const param_llvm_ty = try self.dg.lowerType(param_ty);
4989 const alignment = param_ty.abiAlignment(target);4779 const alignment = param_ty.abiAlignment(mod);
4990 self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);4780 self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
4991 },4781 },
4992 .byref_mut => {4782 .byref_mut => {
...@@ -5004,8 +4794,8 @@ pub const FuncGen = struct {...@@ -5004,8 +4794,8 @@ pub const FuncGen = struct {
50044794
5005 .slice => {4795 .slice => {
5006 assert(!it.byval_attr);4796 assert(!it.byval_attr);
5007 const param_ty = fn_info.param_types[it.zig_index - 1];4797 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
5008 const ptr_info = param_ty.ptrInfo().data;4798 const ptr_info = param_ty.ptrInfo(mod);
5009 const llvm_arg_i = it.llvm_index - 2;4799 const llvm_arg_i = it.llvm_index - 2;
50104800
5011 if (math.cast(u5, it.zig_index - 1)) |i| {4801 if (math.cast(u5, it.zig_index - 1)) |i| {
...@@ -5013,7 +4803,7 @@ pub const FuncGen = struct {...@@ -5013,7 +4803,7 @@ pub const FuncGen = struct {
5013 self.dg.addArgAttr(call, llvm_arg_i, "noalias");4803 self.dg.addArgAttr(call, llvm_arg_i, "noalias");
5014 }4804 }
5015 }4805 }
5016 if (param_ty.zigTypeTag() != .Optional) {4806 if (param_ty.zigTypeTag(mod) != .Optional) {
5017 self.dg.addArgAttr(call, llvm_arg_i, "nonnull");4807 self.dg.addArgAttr(call, llvm_arg_i, "nonnull");
5018 }4808 }
5019 if (!ptr_info.mutable) {4809 if (!ptr_info.mutable) {
...@@ -5022,18 +4812,18 @@ pub const FuncGen = struct {...@@ -5022,18 +4812,18 @@ pub const FuncGen = struct {
5022 if (ptr_info.@"align" != 0) {4812 if (ptr_info.@"align" != 0) {
5023 self.dg.addArgAttrInt(call, llvm_arg_i, "align", ptr_info.@"align");4813 self.dg.addArgAttrInt(call, llvm_arg_i, "align", ptr_info.@"align");
5024 } else {4814 } 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);
5026 self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align);4816 self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align);
5027 }4817 }
5028 },4818 },
5029 };4819 };
5030 }4820 }
50314821
5032 if (return_type.isNoReturn() and attr != .AlwaysTail) {4822 if (fn_info.return_type == .noreturn_type and attr != .AlwaysTail) {
5033 return null;4823 return null;
5034 }4824 }
50354825
5036 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime()) {4826 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) {
5037 return null;4827 return null;
5038 }4828 }
50394829
...@@ -5041,12 +4831,12 @@ pub const FuncGen = struct {...@@ -5041,12 +4831,12 @@ pub const FuncGen = struct {
50414831
5042 if (ret_ptr) |rp| {4832 if (ret_ptr) |rp| {
5043 call.setCallSret(llvm_ret_ty);4833 call.setCallSret(llvm_ret_ty);
5044 if (isByRef(return_type)) {4834 if (isByRef(return_type, mod)) {
5045 return rp;4835 return rp;
5046 } else {4836 } else {
5047 // our by-ref status disagrees with sret so we must load.4837 // our by-ref status disagrees with sret so we must load.
5048 const loaded = self.builder.buildLoad(llvm_ret_ty, rp, "");4838 const loaded = self.builder.buildLoad(llvm_ret_ty, rp, "");
5049 loaded.setAlignment(return_type.abiAlignment(target));4839 loaded.setAlignment(return_type.abiAlignment(mod));
5050 return loaded;4840 return loaded;
5051 }4841 }
5052 }4842 }
...@@ -5061,7 +4851,7 @@ pub const FuncGen = struct {...@@ -5061,7 +4851,7 @@ pub const FuncGen = struct {
5061 const rp = self.buildAlloca(llvm_ret_ty, alignment);4851 const rp = self.buildAlloca(llvm_ret_ty, alignment);
5062 const store_inst = self.builder.buildStore(call, rp);4852 const store_inst = self.builder.buildStore(call, rp);
5063 store_inst.setAlignment(alignment);4853 store_inst.setAlignment(alignment);
5064 if (isByRef(return_type)) {4854 if (isByRef(return_type, mod)) {
5065 return rp;4855 return rp;
5066 } else {4856 } else {
5067 const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, "");4857 const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, "");
...@@ -5070,10 +4860,10 @@ pub const FuncGen = struct {...@@ -5070,10 +4860,10 @@ pub const FuncGen = struct {
5070 }4860 }
5071 }4861 }
50724862
5073 if (isByRef(return_type)) {4863 if (isByRef(return_type, mod)) {
5074 // our by-ref status disagrees with sret so we must allocate, store,4864 // our by-ref status disagrees with sret so we must allocate, store,
5075 // and return the allocation pointer.4865 // and return the allocation pointer.
5076 const alignment = return_type.abiAlignment(target);4866 const alignment = return_type.abiAlignment(mod);
5077 const rp = self.buildAlloca(llvm_ret_ty, alignment);4867 const rp = self.buildAlloca(llvm_ret_ty, alignment);
5078 const store_inst = self.builder.buildStore(call, rp);4868 const store_inst = self.builder.buildStore(call, rp);
5079 store_inst.setAlignment(alignment);4869 store_inst.setAlignment(alignment);
...@@ -5084,22 +4874,19 @@ pub const FuncGen = struct {...@@ -5084,22 +4874,19 @@ pub const FuncGen = struct {
5084 }4874 }
50854875
5086 fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {4876 fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4877 const mod = self.dg.module;
5087 const un_op = self.air.instructions.items(.data)[inst].un_op;4878 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);
5089 if (self.ret_ptr) |ret_ptr| {4880 if (self.ret_ptr) |ret_ptr| {
5090 const operand = try self.resolveInst(un_op);4881 const operand = try self.resolveInst(un_op);
5091 var ptr_ty_payload: Type.Payload.ElemType = .{4882 const ptr_ty = try mod.singleMutPtrType(ret_ty);
5092 .base = .{ .tag = .single_mut_pointer },
5093 .data = ret_ty,
5094 };
5095 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
5096 try self.store(ret_ptr, ptr_ty, operand, .NotAtomic);4883 try self.store(ret_ptr, ptr_ty, operand, .NotAtomic);
5097 _ = self.builder.buildRetVoid();4884 _ = self.builder.buildRetVoid();
5098 return null;4885 return null;
5099 }4886 }
5100 const fn_info = self.dg.decl.ty.fnInfo();4887 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
5101 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {4888 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5102 if (fn_info.return_type.isError()) {4889 if (fn_info.return_type.toType().isError(mod)) {
5103 // Functions with an empty error set are emitted with an error code4890 // Functions with an empty error set are emitted with an error code
5104 // return type and return zero so they can be function pointers coerced4891 // return type and return zero so they can be function pointers coerced
5105 // to functions that return anyerror.4892 // to functions that return anyerror.
...@@ -5113,10 +4900,9 @@ pub const FuncGen = struct {...@@ -5113,10 +4900,9 @@ pub const FuncGen = struct {
51134900
5114 const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info);4901 const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info);
5115 const operand = try self.resolveInst(un_op);4902 const operand = try self.resolveInst(un_op);
5116 const target = self.dg.module.getTarget();4903 const alignment = ret_ty.abiAlignment(mod);
5117 const alignment = ret_ty.abiAlignment(target);
51184904
5119 if (isByRef(ret_ty)) {4905 if (isByRef(ret_ty, mod)) {
5120 // operand is a pointer however self.ret_ptr is null so that means4906 // operand is a pointer however self.ret_ptr is null so that means
5121 // we need to return a value.4907 // we need to return a value.
5122 const load_inst = self.builder.buildLoad(abi_ret_ty, operand, "");4908 const load_inst = self.builder.buildLoad(abi_ret_ty, operand, "");
...@@ -5141,12 +4927,13 @@ pub const FuncGen = struct {...@@ -5141,12 +4927,13 @@ pub const FuncGen = struct {
5141 }4927 }
51424928
5143 fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {4929 fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4930 const mod = self.dg.module;
5144 const un_op = self.air.instructions.items(.data)[inst].un_op;4931 const un_op = self.air.instructions.items(.data)[inst].un_op;
5145 const ptr_ty = self.air.typeOf(un_op);4932 const ptr_ty = self.typeOf(un_op);
5146 const ret_ty = ptr_ty.childType();4933 const ret_ty = ptr_ty.childType(mod);
5147 const fn_info = self.dg.decl.ty.fnInfo();4934 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
5148 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {4935 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5149 if (fn_info.return_type.isError()) {4936 if (fn_info.return_type.toType().isError(mod)) {
5150 // Functions with an empty error set are emitted with an error code4937 // Functions with an empty error set are emitted with an error code
5151 // return type and return zero so they can be function pointers coerced4938 // return type and return zero so they can be function pointers coerced
5152 // to functions that return anyerror.4939 // to functions that return anyerror.
...@@ -5162,10 +4949,9 @@ pub const FuncGen = struct {...@@ -5162,10 +4949,9 @@ pub const FuncGen = struct {
5162 return null;4949 return null;
5163 }4950 }
5164 const ptr = try self.resolveInst(un_op);4951 const ptr = try self.resolveInst(un_op);
5165 const target = self.dg.module.getTarget();
5166 const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info);4952 const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info);
5167 const loaded = self.builder.buildLoad(abi_ret_ty, ptr, "");4953 const loaded = self.builder.buildLoad(abi_ret_ty, ptr, "");
5168 loaded.setAlignment(ret_ty.abiAlignment(target));4954 loaded.setAlignment(ret_ty.abiAlignment(mod));
5169 _ = self.builder.buildRet(loaded);4955 _ = self.builder.buildRet(loaded);
5170 return null;4956 return null;
5171 }4957 }
...@@ -5184,9 +4970,9 @@ pub const FuncGen = struct {...@@ -5184,9 +4970,9 @@ pub const FuncGen = struct {
5184 const src_list = try self.resolveInst(ty_op.operand);4970 const src_list = try self.resolveInst(ty_op.operand);
5185 const va_list_ty = self.air.getRefType(ty_op.ty);4971 const va_list_ty = self.air.getRefType(ty_op.ty);
5186 const llvm_va_list_ty = try self.dg.lowerType(va_list_ty);4972 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();4975 const result_alignment = va_list_ty.abiAlignment(mod);
5189 const result_alignment = va_list_ty.abiAlignment(target);
5190 const dest_list = self.buildAlloca(llvm_va_list_ty, result_alignment);4976 const dest_list = self.buildAlloca(llvm_va_list_ty, result_alignment);
51914977
5192 const llvm_fn_name = "llvm.va_copy";4978 const llvm_fn_name = "llvm.va_copy";
...@@ -5202,7 +4988,7 @@ pub const FuncGen = struct {...@@ -5202,7 +4988,7 @@ pub const FuncGen = struct {
5202 const args: [2]*llvm.Value = .{ dest_list, src_list };4988 const args: [2]*llvm.Value = .{ dest_list, src_list };
5203 _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, "");4989 _ = 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)) {
5206 return dest_list;4992 return dest_list;
5207 } else {4993 } else {
5208 const loaded = self.builder.buildLoad(llvm_va_list_ty, dest_list, "");4994 const loaded = self.builder.buildLoad(llvm_va_list_ty, dest_list, "");
...@@ -5227,11 +5013,11 @@ pub const FuncGen = struct {...@@ -5227,11 +5013,11 @@ pub const FuncGen = struct {
5227 }5013 }
52285014
5229 fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5015 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);
5231 const llvm_va_list_ty = try self.dg.lowerType(va_list_ty);5018 const llvm_va_list_ty = try self.dg.lowerType(va_list_ty);
52325019
5233 const target = self.dg.module.getTarget();5020 const result_alignment = va_list_ty.abiAlignment(mod);
5234 const result_alignment = va_list_ty.abiAlignment(target);
5235 const list = self.buildAlloca(llvm_va_list_ty, result_alignment);5021 const list = self.buildAlloca(llvm_va_list_ty, result_alignment);
52365022
5237 const llvm_fn_name = "llvm.va_start";5023 const llvm_fn_name = "llvm.va_start";
...@@ -5243,7 +5029,7 @@ pub const FuncGen = struct {...@@ -5243,7 +5029,7 @@ pub const FuncGen = struct {
5243 const args: [1]*llvm.Value = .{list};5029 const args: [1]*llvm.Value = .{list};
5244 _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, "");5030 _ = 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)) {
5247 return list;5033 return list;
5248 } else {5034 } else {
5249 const loaded = self.builder.buildLoad(llvm_va_list_ty, list, "");5035 const loaded = self.builder.buildLoad(llvm_va_list_ty, list, "");
...@@ -5258,7 +5044,7 @@ pub const FuncGen = struct {...@@ -5258,7 +5044,7 @@ pub const FuncGen = struct {
5258 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5044 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5259 const lhs = try self.resolveInst(bin_op.lhs);5045 const lhs = try self.resolveInst(bin_op.lhs);
5260 const rhs = try self.resolveInst(bin_op.rhs);5046 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
5263 return self.cmp(lhs, rhs, operand_ty, op);5049 return self.cmp(lhs, rhs, operand_ty, op);
5264 }5050 }
...@@ -5271,7 +5057,7 @@ pub const FuncGen = struct {...@@ -5271,7 +5057,7 @@ pub const FuncGen = struct {
52715057
5272 const lhs = try self.resolveInst(extra.lhs);5058 const lhs = try self.resolveInst(extra.lhs);
5273 const rhs = try self.resolveInst(extra.rhs);5059 const rhs = try self.resolveInst(extra.rhs);
5274 const vec_ty = self.air.typeOf(extra.lhs);5060 const vec_ty = self.typeOf(extra.lhs);
5275 const cmp_op = extra.compareOperator();5061 const cmp_op = extra.compareOperator();
52765062
5277 return self.cmp(lhs, rhs, vec_ty, cmp_op);5063 return self.cmp(lhs, rhs, vec_ty, cmp_op);
...@@ -5292,23 +5078,21 @@ pub const FuncGen = struct {...@@ -5292,23 +5078,21 @@ pub const FuncGen = struct {
5292 operand_ty: Type,5078 operand_ty: Type,
5293 op: math.CompareOperator,5079 op: math.CompareOperator,
5294 ) Allocator.Error!*llvm.Value {5080 ) Allocator.Error!*llvm.Value {
5295 var int_buffer: Type.Payload.Bits = undefined;5081 const mod = self.dg.module;
5296 var opt_buffer: Type.Payload.ElemType = undefined;5082 const scalar_ty = operand_ty.scalarType(mod);
52975083 const int_ty = switch (scalar_ty.zigTypeTag(mod)) {
5298 const scalar_ty = operand_ty.scalarType();5084 .Enum => scalar_ty.intTagType(mod),
5299 const int_ty = switch (scalar_ty.zigTypeTag()) {
5300 .Enum => scalar_ty.intTagType(&int_buffer),
5301 .Int, .Bool, .Pointer, .ErrorSet => scalar_ty,5085 .Int, .Bool, .Pointer, .ErrorSet => scalar_ty,
5302 .Optional => blk: {5086 .Optional => blk: {
5303 const payload_ty = operand_ty.optionalChild(&opt_buffer);5087 const payload_ty = operand_ty.optionalChild(mod);
5304 if (!payload_ty.hasRuntimeBitsIgnoreComptime() or5088 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or
5305 operand_ty.optionalReprIsPayload())5089 operand_ty.optionalReprIsPayload(mod))
5306 {5090 {
5307 break :blk operand_ty;5091 break :blk operand_ty;
5308 }5092 }
5309 // We need to emit instructions to check for equality/inequality5093 // We need to emit instructions to check for equality/inequality
5310 // of optionals that are not pointers.5094 // of optionals that are not pointers.
5311 const is_by_ref = isByRef(scalar_ty);5095 const is_by_ref = isByRef(scalar_ty, mod);
5312 const opt_llvm_ty = try self.dg.lowerType(scalar_ty);5096 const opt_llvm_ty = try self.dg.lowerType(scalar_ty);
5313 const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref);5097 const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref);
5314 const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref);5098 const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref);
...@@ -5375,7 +5159,7 @@ pub const FuncGen = struct {...@@ -5375,7 +5159,7 @@ pub const FuncGen = struct {
5375 .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }),5159 .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }),
5376 else => unreachable,5160 else => unreachable,
5377 };5161 };
5378 const is_signed = int_ty.isSignedInt();5162 const is_signed = int_ty.isSignedInt(mod);
5379 const operation: llvm.IntPredicate = switch (op) {5163 const operation: llvm.IntPredicate = switch (op) {
5380 .eq => .EQ,5164 .eq => .EQ,
5381 .neq => .NE,5165 .neq => .NE,
...@@ -5388,13 +5172,14 @@ pub const FuncGen = struct {...@@ -5388,13 +5172,14 @@ pub const FuncGen = struct {
5388 }5172 }
53895173
5390 fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5174 fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5175 const mod = self.dg.module;
5391 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5176 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5392 const extra = self.air.extraData(Air.Block, ty_pl.payload);5177 const extra = self.air.extraData(Air.Block, ty_pl.payload);
5393 const body = self.air.extra[extra.end..][0..extra.data.body_len];5178 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);
5395 const parent_bb = self.context.createBasicBlock("Block");5180 const parent_bb = self.context.createBasicBlock("Block");
53965181
5397 if (inst_ty.isNoReturn()) {5182 if (inst_ty.isNoReturn(mod)) {
5398 try self.genBody(body);5183 try self.genBody(body);
5399 return null;5184 return null;
5400 }5185 }
...@@ -5414,8 +5199,8 @@ pub const FuncGen = struct {...@@ -5414,8 +5199,8 @@ pub const FuncGen = struct {
5414 self.builder.positionBuilderAtEnd(parent_bb);5199 self.builder.positionBuilderAtEnd(parent_bb);
54155200
5416 // Create a phi node only if the block returns a value.5201 // Create a phi node only if the block returns a value.
5417 const is_body = inst_ty.zigTypeTag() == .Fn;5202 const is_body = inst_ty.zigTypeTag(mod) == .Fn;
5418 if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime()) return null;5203 if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
54195204
5420 const raw_llvm_ty = try self.dg.lowerType(inst_ty);5205 const raw_llvm_ty = try self.dg.lowerType(inst_ty);
54215206
...@@ -5424,7 +5209,7 @@ pub const FuncGen = struct {...@@ -5424,7 +5209,7 @@ pub const FuncGen = struct {
5424 // a pointer to it. LLVM IR allows the call instruction to use function bodies instead5209 // a pointer to it. LLVM IR allows the call instruction to use function bodies instead
5425 // of function pointers, however the phi makes it a runtime value and therefore5210 // of function pointers, however the phi makes it a runtime value and therefore
5426 // the LLVM type has to be wrapped in a pointer.5211 // 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)) {
5428 break :ty self.context.pointerType(0);5213 break :ty self.context.pointerType(0);
5429 }5214 }
5430 break :ty raw_llvm_ty;5215 break :ty raw_llvm_ty;
...@@ -5444,8 +5229,9 @@ pub const FuncGen = struct {...@@ -5444,8 +5229,9 @@ pub const FuncGen = struct {
5444 const block = self.blocks.get(branch.block_inst).?;5229 const block = self.blocks.get(branch.block_inst).?;
54455230
5446 // Add the values to the lists only if the break provides a value.5231 // Add the values to the lists only if the break provides a value.
5447 const operand_ty = self.air.typeOf(branch.operand);5232 const operand_ty = self.typeOf(branch.operand);
5448 if (operand_ty.hasRuntimeBitsIgnoreComptime() or operand_ty.zigTypeTag() == .Fn) {5233 const mod = self.dg.module;
5234 if (operand_ty.hasRuntimeBitsIgnoreComptime(mod) or operand_ty.zigTypeTag(mod) == .Fn) {
5449 const val = try self.resolveInst(branch.operand);5235 const val = try self.resolveInst(branch.operand);
54505236
5451 // For the phi node, we need the basic blocks and the values of the5237 // For the phi node, we need the basic blocks and the values of the
...@@ -5481,24 +5267,26 @@ pub const FuncGen = struct {...@@ -5481,24 +5267,26 @@ pub const FuncGen = struct {
5481 }5267 }
54825268
5483 fn airTry(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {5269 fn airTry(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5270 const mod = self.dg.module;
5484 const inst = body_tail[0];5271 const inst = body_tail[0];
5485 const pl_op = self.air.instructions.items(.data)[inst].pl_op;5272 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
5486 const err_union = try self.resolveInst(pl_op.operand);5273 const err_union = try self.resolveInst(pl_op.operand);
5487 const extra = self.air.extraData(Air.Try, pl_op.payload);5274 const extra = self.air.extraData(Air.Try, pl_op.payload);
5488 const body = self.air.extra[extra.end..][0..extra.data.body_len];5275 const body = self.air.extra[extra.end..][0..extra.data.body_len];
5489 const err_union_ty = self.air.typeOf(pl_op.operand);5276 const err_union_ty = self.typeOf(pl_op.operand);
5490 const payload_ty = self.air.typeOfIndex(inst);5277 const payload_ty = self.typeOfIndex(inst);
5491 const can_elide_load = if (isByRef(payload_ty)) self.canElideLoad(body_tail) else false;5278 const can_elide_load = if (isByRef(payload_ty, mod)) self.canElideLoad(body_tail) else false;
5492 const is_unused = self.liveness.isUnused(inst);5279 const is_unused = self.liveness.isUnused(inst);
5493 return lowerTry(self, err_union, body, err_union_ty, false, can_elide_load, is_unused);5280 return lowerTry(self, err_union, body, err_union_ty, false, can_elide_load, is_unused);
5494 }5281 }
54955282
5496 fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5283 fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5284 const mod = self.dg.module;
5497 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5285 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5498 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);5286 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
5499 const err_union_ptr = try self.resolveInst(extra.data.ptr);5287 const err_union_ptr = try self.resolveInst(extra.data.ptr);
5500 const body = self.air.extra[extra.end..][0..extra.data.body_len];5288 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);
5502 const is_unused = self.liveness.isUnused(inst);5290 const is_unused = self.liveness.isUnused(inst);
5503 return lowerTry(self, err_union_ptr, body, err_union_ty, true, true, is_unused);5291 return lowerTry(self, err_union_ptr, body, err_union_ty, true, true, is_unused);
5504 }5292 }
...@@ -5512,12 +5300,12 @@ pub const FuncGen = struct {...@@ -5512,12 +5300,12 @@ pub const FuncGen = struct {
5512 can_elide_load: bool,5300 can_elide_load: bool,
5513 is_unused: bool,5301 is_unused: bool,
5514 ) !?*llvm.Value {5302 ) !?*llvm.Value {
5515 const payload_ty = err_union_ty.errorUnionPayload();5303 const mod = fg.dg.module;
5516 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();5304 const payload_ty = err_union_ty.errorUnionPayload(mod);
5517 const target = fg.dg.module.getTarget();5305 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5518 const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty);5306 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)) {
5521 const is_err = err: {5309 const is_err = err: {
5522 const err_set_ty = try fg.dg.lowerType(Type.anyerror);5310 const err_set_ty = try fg.dg.lowerType(Type.anyerror);
5523 const zero = err_set_ty.constNull();5311 const zero = err_set_ty.constNull();
...@@ -5529,8 +5317,8 @@ pub const FuncGen = struct {...@@ -5529,8 +5317,8 @@ pub const FuncGen = struct {
5529 err_union;5317 err_union;
5530 break :err fg.builder.buildICmp(.NE, loaded, zero, "");5318 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
5531 }5319 }
5532 const err_field_index = errUnionErrorOffset(payload_ty, target);5320 const err_field_index = errUnionErrorOffset(payload_ty, mod);
5533 if (operand_is_ptr or isByRef(err_union_ty)) {5321 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
5534 const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, "");5322 const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, "");
5535 // TODO add alignment to this load5323 // TODO add alignment to this load
5536 const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, "");5324 const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, "");
...@@ -5555,30 +5343,31 @@ pub const FuncGen = struct {...@@ -5555,30 +5343,31 @@ pub const FuncGen = struct {
5555 if (!payload_has_bits) {5343 if (!payload_has_bits) {
5556 return if (operand_is_ptr) err_union else null;5344 return if (operand_is_ptr) err_union else null;
5557 }5345 }
5558 const offset = errUnionPayloadOffset(payload_ty, target);5346 const offset = errUnionPayloadOffset(payload_ty, mod);
5559 if (operand_is_ptr) {5347 if (operand_is_ptr) {
5560 return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, "");5348 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)) {
5562 const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, "");5350 const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, "");
5563 if (isByRef(payload_ty)) {5351 if (isByRef(payload_ty, mod)) {
5564 if (can_elide_load)5352 if (can_elide_load)
5565 return payload_ptr;5353 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);
5568 }5356 }
5569 const load_inst = fg.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, "");5357 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));
5571 return load_inst;5359 return load_inst;
5572 }5360 }
5573 return fg.builder.buildExtractValue(err_union, offset, "");5361 return fg.builder.buildExtractValue(err_union, offset, "");
5574 }5362 }
55755363
5576 fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5364 fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5365 const mod = self.dg.module;
5577 const pl_op = self.air.instructions.items(.data)[inst].pl_op;5366 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
5578 const cond = try self.resolveInst(pl_op.operand);5367 const cond = try self.resolveInst(pl_op.operand);
5579 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);5368 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
5580 const else_block = self.context.appendBasicBlock(self.llvm_func, "Else");5369 const else_block = self.context.appendBasicBlock(self.llvm_func, "Else");
5581 const target = self.dg.module.getTarget();5370 const target = mod.getTarget();
5582 const llvm_usize = self.context.intType(target.ptrBitWidth());5371 const llvm_usize = self.context.intType(target.ptrBitWidth());
5583 const cond_int = if (cond.typeOf().getTypeKind() == .Pointer)5372 const cond_int = if (cond.typeOf().getTypeKind() == .Pointer)
5584 self.builder.buildPtrToInt(cond, llvm_usize, "")5373 self.builder.buildPtrToInt(cond, llvm_usize, "")
...@@ -5623,6 +5412,7 @@ pub const FuncGen = struct {...@@ -5623,6 +5412,7 @@ pub const FuncGen = struct {
5623 }5412 }
56245413
5625 fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5414 fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5415 const mod = self.dg.module;
5626 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5416 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5627 const loop = self.air.extraData(Air.Block, ty_pl.payload);5417 const loop = self.air.extraData(Air.Block, ty_pl.payload);
5628 const body = self.air.extra[loop.end..][0..loop.data.body_len];5418 const body = self.air.extra[loop.end..][0..loop.data.body_len];
...@@ -5638,21 +5428,22 @@ pub const FuncGen = struct {...@@ -5638,21 +5428,22 @@ pub const FuncGen = struct {
5638 // would have been emitted already. Also the main loop in genBody can5428 // would have been emitted already. Also the main loop in genBody can
5639 // be while(true) instead of for(body), which will eliminate 1 branch on5429 // be while(true) instead of for(body), which will eliminate 1 branch on
5640 // a hot path.5430 // 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)) {
5642 _ = self.builder.buildBr(loop_block);5432 _ = self.builder.buildBr(loop_block);
5643 }5433 }
5644 return null;5434 return null;
5645 }5435 }
56465436
5647 fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5437 fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5438 const mod = self.dg.module;
5648 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5439 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5649 const operand_ty = self.air.typeOf(ty_op.operand);5440 const operand_ty = self.typeOf(ty_op.operand);
5650 const array_ty = operand_ty.childType();5441 const array_ty = operand_ty.childType(mod);
5651 const llvm_usize = try self.dg.lowerType(Type.usize);5442 const llvm_usize = try self.dg.lowerType(Type.usize);
5652 const len = llvm_usize.constInt(array_ty.arrayLen(), .False);5443 const len = llvm_usize.constInt(array_ty.arrayLen(mod), .False);
5653 const slice_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));5444 const slice_llvm_ty = try self.dg.lowerType(self.typeOfIndex(inst));
5654 const operand = try self.resolveInst(ty_op.operand);5445 const operand = try self.resolveInst(ty_op.operand);
5655 if (!array_ty.hasRuntimeBitsIgnoreComptime()) {5446 if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5656 const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, "");5447 const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, "");
5657 return self.builder.buildInsertValue(partial, len, 1, "");5448 return self.builder.buildInsertValue(partial, len, 1, "");
5658 }5449 }
...@@ -5666,30 +5457,31 @@ pub const FuncGen = struct {...@@ -5666,30 +5457,31 @@ pub const FuncGen = struct {
5666 }5457 }
56675458
5668 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5459 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5460 const mod = self.dg.module;
5669 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5461 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
56705462
5671 const operand = try self.resolveInst(ty_op.operand);5463 const operand = try self.resolveInst(ty_op.operand);
5672 const operand_ty = self.air.typeOf(ty_op.operand);5464 const operand_ty = self.typeOf(ty_op.operand);
5673 const operand_scalar_ty = operand_ty.scalarType();5465 const operand_scalar_ty = operand_ty.scalarType(mod);
56745466
5675 const dest_ty = self.air.typeOfIndex(inst);5467 const dest_ty = self.typeOfIndex(inst);
5676 const dest_scalar_ty = dest_ty.scalarType();5468 const dest_scalar_ty = dest_ty.scalarType(mod);
5677 const dest_llvm_ty = try self.dg.lowerType(dest_ty);5469 const dest_llvm_ty = try self.dg.lowerType(dest_ty);
5678 const target = self.dg.module.getTarget();5470 const target = mod.getTarget();
56795471
5680 if (intrinsicsAllowed(dest_scalar_ty, target)) {5472 if (intrinsicsAllowed(dest_scalar_ty, target)) {
5681 if (operand_scalar_ty.isSignedInt()) {5473 if (operand_scalar_ty.isSignedInt(mod)) {
5682 return self.builder.buildSIToFP(operand, dest_llvm_ty, "");5474 return self.builder.buildSIToFP(operand, dest_llvm_ty, "");
5683 } else {5475 } else {
5684 return self.builder.buildUIToFP(operand, dest_llvm_ty, "");5476 return self.builder.buildUIToFP(operand, dest_llvm_ty, "");
5685 }5477 }
5686 }5478 }
56875479
5688 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));5480 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(mod));
5689 const rt_int_bits = compilerRtIntBits(operand_bits);5481 const rt_int_bits = compilerRtIntBits(operand_bits);
5690 const rt_int_ty = self.context.intType(rt_int_bits);5482 const rt_int_ty = self.context.intType(rt_int_bits);
5691 var extended = e: {5483 var extended = e: {
5692 if (operand_scalar_ty.isSignedInt()) {5484 if (operand_scalar_ty.isSignedInt(mod)) {
5693 break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, "");5485 break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, "");
5694 } else {5486 } else {
5695 break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty, "");5487 break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty, "");
...@@ -5698,7 +5490,7 @@ pub const FuncGen = struct {...@@ -5698,7 +5490,7 @@ pub const FuncGen = struct {
5698 const dest_bits = dest_scalar_ty.floatBits(target);5490 const dest_bits = dest_scalar_ty.floatBits(target);
5699 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);5491 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);
5700 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);5492 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";
5702 var fn_name_buf: [64]u8 = undefined;5494 var fn_name_buf: [64]u8 = undefined;
5703 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{5495 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{
5704 sign_prefix,5496 sign_prefix,
...@@ -5724,27 +5516,28 @@ pub const FuncGen = struct {...@@ -5724,27 +5516,28 @@ pub const FuncGen = struct {
5724 fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {5516 fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
5725 self.builder.setFastMath(want_fast_math);5517 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();
5728 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5521 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
57295522
5730 const operand = try self.resolveInst(ty_op.operand);5523 const operand = try self.resolveInst(ty_op.operand);
5731 const operand_ty = self.air.typeOf(ty_op.operand);5524 const operand_ty = self.typeOf(ty_op.operand);
5732 const operand_scalar_ty = operand_ty.scalarType();5525 const operand_scalar_ty = operand_ty.scalarType(mod);
57335526
5734 const dest_ty = self.air.typeOfIndex(inst);5527 const dest_ty = self.typeOfIndex(inst);
5735 const dest_scalar_ty = dest_ty.scalarType();5528 const dest_scalar_ty = dest_ty.scalarType(mod);
5736 const dest_llvm_ty = try self.dg.lowerType(dest_ty);5529 const dest_llvm_ty = try self.dg.lowerType(dest_ty);
57375530
5738 if (intrinsicsAllowed(operand_scalar_ty, target)) {5531 if (intrinsicsAllowed(operand_scalar_ty, target)) {
5739 // TODO set fast math flag5532 // TODO set fast math flag
5740 if (dest_scalar_ty.isSignedInt()) {5533 if (dest_scalar_ty.isSignedInt(mod)) {
5741 return self.builder.buildFPToSI(operand, dest_llvm_ty, "");5534 return self.builder.buildFPToSI(operand, dest_llvm_ty, "");
5742 } else {5535 } else {
5743 return self.builder.buildFPToUI(operand, dest_llvm_ty, "");5536 return self.builder.buildFPToUI(operand, dest_llvm_ty, "");
5744 }5537 }
5745 }5538 }
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)));
5748 const ret_ty = self.context.intType(rt_int_bits);5541 const ret_ty = self.context.intType(rt_int_bits);
5749 const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: {5542 const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: {
5750 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard5543 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
...@@ -5756,7 +5549,7 @@ pub const FuncGen = struct {...@@ -5756,7 +5549,7 @@ pub const FuncGen = struct {
5756 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);5549 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
57575550
5758 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits);5551 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
5761 var fn_name_buf: [64]u8 = undefined;5554 var fn_name_buf: [64]u8 = undefined;
5762 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{5555 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{
...@@ -5778,7 +5571,8 @@ pub const FuncGen = struct {...@@ -5778,7 +5571,8 @@ pub const FuncGen = struct {
5778 }5571 }
57795572
5780 fn sliceOrArrayPtr(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value {5573 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)) {
5782 return fg.builder.buildExtractValue(ptr, 0, "");5576 return fg.builder.buildExtractValue(ptr, 0, "");
5783 } else {5577 } else {
5784 return ptr;5578 return ptr;
...@@ -5786,22 +5580,23 @@ pub const FuncGen = struct {...@@ -5786,22 +5580,23 @@ pub const FuncGen = struct {
5786 }5580 }
57875581
5788 fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value {5582 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();
5790 const llvm_usize_ty = fg.context.intType(target.ptrBitWidth());5585 const llvm_usize_ty = fg.context.intType(target.ptrBitWidth());
5791 switch (ty.ptrSize()) {5586 switch (ty.ptrSize(mod)) {
5792 .Slice => {5587 .Slice => {
5793 const len = fg.builder.buildExtractValue(ptr, 1, "");5588 const len = fg.builder.buildExtractValue(ptr, 1, "");
5794 const elem_ty = ty.childType();5589 const elem_ty = ty.childType(mod);
5795 const abi_size = elem_ty.abiSize(target);5590 const abi_size = elem_ty.abiSize(mod);
5796 if (abi_size == 1) return len;5591 if (abi_size == 1) return len;
5797 const abi_size_llvm_val = llvm_usize_ty.constInt(abi_size, .False);5592 const abi_size_llvm_val = llvm_usize_ty.constInt(abi_size, .False);
5798 return fg.builder.buildMul(len, abi_size_llvm_val, "");5593 return fg.builder.buildMul(len, abi_size_llvm_val, "");
5799 },5594 },
5800 .One => {5595 .One => {
5801 const array_ty = ty.childType();5596 const array_ty = ty.childType(mod);
5802 const elem_ty = array_ty.childType();5597 const elem_ty = array_ty.childType(mod);
5803 const abi_size = elem_ty.abiSize(target);5598 const abi_size = elem_ty.abiSize(mod);
5804 return llvm_usize_ty.constInt(array_ty.arrayLen() * abi_size, .False);5599 return llvm_usize_ty.constInt(array_ty.arrayLen(mod) * abi_size, .False);
5805 },5600 },
5806 .Many, .C => unreachable,5601 .Many, .C => unreachable,
5807 }5602 }
...@@ -5814,67 +5609,69 @@ pub const FuncGen = struct {...@@ -5814,67 +5609,69 @@ pub const FuncGen = struct {
5814 }5609 }
58155610
5816 fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value {5611 fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value {
5612 const mod = self.dg.module;
5817 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5613 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5818 const slice_ptr = try self.resolveInst(ty_op.operand);5614 const slice_ptr = try self.resolveInst(ty_op.operand);
5819 const slice_ptr_ty = self.air.typeOf(ty_op.operand);5615 const slice_ptr_ty = self.typeOf(ty_op.operand);
5820 const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType());5616 const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType(mod));
58215617
5822 return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, "");5618 return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, "");
5823 }5619 }
58245620
5825 fn airSliceElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {5621 fn airSliceElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5622 const mod = self.dg.module;
5826 const inst = body_tail[0];5623 const inst = body_tail[0];
5827 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5624 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);
5829 const slice = try self.resolveInst(bin_op.lhs);5626 const slice = try self.resolveInst(bin_op.lhs);
5830 const index = try self.resolveInst(bin_op.rhs);5627 const index = try self.resolveInst(bin_op.rhs);
5831 const elem_ty = slice_ty.childType();5628 const elem_ty = slice_ty.childType(mod);
5832 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);5629 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
5833 const base_ptr = self.builder.buildExtractValue(slice, 0, "");5630 const base_ptr = self.builder.buildExtractValue(slice, 0, "");
5834 const indices: [1]*llvm.Value = .{index};5631 const indices: [1]*llvm.Value = .{index};
5835 const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");5632 const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
5836 if (isByRef(elem_ty)) {5633 if (isByRef(elem_ty, mod)) {
5837 if (self.canElideLoad(body_tail))5634 if (self.canElideLoad(body_tail))
5838 return ptr;5635 return ptr;
58395636
5840 const target = self.dg.module.getTarget();5637 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(mod), false);
5841 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false);
5842 }5638 }
58435639
5844 return self.load(ptr, slice_ty);5640 return self.load(ptr, slice_ty);
5845 }5641 }
58465642
5847 fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5643 fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5644 const mod = self.dg.module;
5848 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5645 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5849 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;5646 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
5852 const slice = try self.resolveInst(bin_op.lhs);5649 const slice = try self.resolveInst(bin_op.lhs);
5853 const index = try self.resolveInst(bin_op.rhs);5650 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));
5855 const base_ptr = self.builder.buildExtractValue(slice, 0, "");5652 const base_ptr = self.builder.buildExtractValue(slice, 0, "");
5856 const indices: [1]*llvm.Value = .{index};5653 const indices: [1]*llvm.Value = .{index};
5857 return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");5654 return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
5858 }5655 }
58595656
5860 fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {5657 fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5658 const mod = self.dg.module;
5861 const inst = body_tail[0];5659 const inst = body_tail[0];
58625660
5863 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5661 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);
5865 const array_llvm_val = try self.resolveInst(bin_op.lhs);5663 const array_llvm_val = try self.resolveInst(bin_op.lhs);
5866 const rhs = try self.resolveInst(bin_op.rhs);5664 const rhs = try self.resolveInst(bin_op.rhs);
5867 const array_llvm_ty = try self.dg.lowerType(array_ty);5665 const array_llvm_ty = try self.dg.lowerType(array_ty);
5868 const elem_ty = array_ty.childType();5666 const elem_ty = array_ty.childType(mod);
5869 if (isByRef(array_ty)) {5667 if (isByRef(array_ty, mod)) {
5870 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };5668 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
5871 if (isByRef(elem_ty)) {5669 if (isByRef(elem_ty, mod)) {
5872 const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, "");5670 const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, "");
5873 if (canElideLoad(self, body_tail))5671 if (canElideLoad(self, body_tail))
5874 return elem_ptr;5672 return elem_ptr;
58755673
5876 const target = self.dg.module.getTarget();5674 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false);
5877 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(target), false);
5878 } else {5675 } else {
5879 const lhs_index = Air.refToIndex(bin_op.lhs).?;5676 const lhs_index = Air.refToIndex(bin_op.lhs).?;
5880 const elem_llvm_ty = try self.dg.lowerType(elem_ty);5677 const elem_llvm_ty = try self.dg.lowerType(elem_ty);
...@@ -5901,15 +5698,16 @@ pub const FuncGen = struct {...@@ -5901,15 +5698,16 @@ pub const FuncGen = struct {
5901 }5698 }
59025699
5903 fn airPtrElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {5700 fn airPtrElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5701 const mod = self.dg.module;
5904 const inst = body_tail[0];5702 const inst = body_tail[0];
5905 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5703 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5906 const ptr_ty = self.air.typeOf(bin_op.lhs);5704 const ptr_ty = self.typeOf(bin_op.lhs);
5907 const elem_ty = ptr_ty.childType();5705 const elem_ty = ptr_ty.childType(mod);
5908 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);5706 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
5909 const base_ptr = try self.resolveInst(bin_op.lhs);5707 const base_ptr = try self.resolveInst(bin_op.lhs);
5910 const rhs = try self.resolveInst(bin_op.rhs);5708 const rhs = try self.resolveInst(bin_op.rhs);
5911 // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch5709 // 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: {
5913 // If this is a single-item pointer to an array, we need another index in the GEP.5711 // If this is a single-item pointer to an array, we need another index in the GEP.
5914 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };5712 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
5915 break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");5713 break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
...@@ -5917,32 +5715,32 @@ pub const FuncGen = struct {...@@ -5917,32 +5715,32 @@ pub const FuncGen = struct {
5917 const indices: [1]*llvm.Value = .{rhs};5715 const indices: [1]*llvm.Value = .{rhs};
5918 break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");5716 break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
5919 };5717 };
5920 if (isByRef(elem_ty)) {5718 if (isByRef(elem_ty, mod)) {
5921 if (self.canElideLoad(body_tail))5719 if (self.canElideLoad(body_tail))
5922 return ptr;5720 return ptr;
59235721
5924 const target = self.dg.module.getTarget();5722 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(mod), false);
5925 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false);
5926 }5723 }
59275724
5928 return self.load(ptr, ptr_ty);5725 return self.load(ptr, ptr_ty);
5929 }5726 }
59305727
5931 fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5728 fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5729 const mod = self.dg.module;
5932 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5730 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5933 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;5731 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
5934 const ptr_ty = self.air.typeOf(bin_op.lhs);5732 const ptr_ty = self.typeOf(bin_op.lhs);
5935 const elem_ty = ptr_ty.childType();5733 const elem_ty = ptr_ty.childType(mod);
5936 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);5734 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty);
59375735
5938 const base_ptr = try self.resolveInst(bin_op.lhs);5736 const base_ptr = try self.resolveInst(bin_op.lhs);
5939 const rhs = try self.resolveInst(bin_op.rhs);5737 const rhs = try self.resolveInst(bin_op.rhs);
59405738
5941 const elem_ptr = self.air.getRefType(ty_pl.ty);5739 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
5944 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);5742 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
5945 if (ptr_ty.isSinglePointer()) {5743 if (ptr_ty.isSinglePointer(mod)) {
5946 // If this is a single-item pointer to an array, we need another index in the GEP.5744 // If this is a single-item pointer to an array, we need another index in the GEP.
5947 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };5745 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
5948 return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");5746 return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
...@@ -5956,7 +5754,7 @@ pub const FuncGen = struct {...@@ -5956,7 +5754,7 @@ pub const FuncGen = struct {
5956 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5754 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5957 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;5755 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
5958 const struct_ptr = try self.resolveInst(struct_field.struct_operand);5756 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);
5960 return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, struct_field.field_index);5758 return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, struct_field.field_index);
5961 }5759 }
59625760
...@@ -5967,41 +5765,41 @@ pub const FuncGen = struct {...@@ -5967,41 +5765,41 @@ pub const FuncGen = struct {
5967 ) !?*llvm.Value {5765 ) !?*llvm.Value {
5968 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5766 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5969 const struct_ptr = try self.resolveInst(ty_op.operand);5767 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);
5971 return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, field_index);5769 return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, field_index);
5972 }5770 }
59735771
5974 fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {5772 fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5773 const mod = self.dg.module;
5975 const inst = body_tail[0];5774 const inst = body_tail[0];
5976 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5775 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5977 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;5776 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);
5979 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);5778 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
5980 const field_index = struct_field.field_index;5779 const field_index = struct_field.field_index;
5981 const field_ty = struct_ty.structFieldType(field_index);5780 const field_ty = struct_ty.structFieldType(field_index, mod);
5982 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {5781 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5983 return null;5782 return null;
5984 }5783 }
5985 const target = self.dg.module.getTarget();
59865784
5987 if (!isByRef(struct_ty)) {5785 if (!isByRef(struct_ty, mod)) {
5988 assert(!isByRef(field_ty));5786 assert(!isByRef(field_ty, mod));
5989 switch (struct_ty.zigTypeTag()) {5787 switch (struct_ty.zigTypeTag(mod)) {
5990 .Struct => switch (struct_ty.containerLayout()) {5788 .Struct => switch (struct_ty.containerLayout(mod)) {
5991 .Packed => {5789 .Packed => {
5992 const struct_obj = struct_ty.castTag(.@"struct").?.data;5790 const struct_obj = mod.typeToStruct(struct_ty).?;
5993 const bit_offset = struct_obj.packedFieldBitOffset(target, field_index);5791 const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index);
5994 const containing_int = struct_llvm_val;5792 const containing_int = struct_llvm_val;
5995 const shift_amt = containing_int.typeOf().constInt(bit_offset, .False);5793 const shift_amt = containing_int.typeOf().constInt(bit_offset, .False);
5996 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");5794 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");
5997 const elem_llvm_ty = try self.dg.lowerType(field_ty);5795 const elem_llvm_ty = try self.dg.lowerType(field_ty);
5998 if (field_ty.zigTypeTag() == .Float or field_ty.zigTypeTag() == .Vector) {5796 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
5999 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));5797 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
6000 const same_size_int = self.context.intType(elem_bits);5798 const same_size_int = self.context.intType(elem_bits);
6001 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");5799 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
6002 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");5800 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
6003 } else if (field_ty.isPtrAtRuntime()) {5801 } else if (field_ty.isPtrAtRuntime(mod)) {
6004 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));5802 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
6005 const same_size_int = self.context.intType(elem_bits);5803 const same_size_int = self.context.intType(elem_bits);
6006 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");5804 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
6007 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");5805 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
...@@ -6009,22 +5807,21 @@ pub const FuncGen = struct {...@@ -6009,22 +5807,21 @@ pub const FuncGen = struct {
6009 return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");5807 return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");
6010 },5808 },
6011 else => {5809 else => {
6012 var ptr_ty_buf: Type.Payload.Pointer = undefined;5810 const llvm_field_index = llvmField(struct_ty, field_index, mod).?.index;
6013 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
6014 return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, "");5811 return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, "");
6015 },5812 },
6016 },5813 },
6017 .Union => {5814 .Union => {
6018 assert(struct_ty.containerLayout() == .Packed);5815 assert(struct_ty.containerLayout(mod) == .Packed);
6019 const containing_int = struct_llvm_val;5816 const containing_int = struct_llvm_val;
6020 const elem_llvm_ty = try self.dg.lowerType(field_ty);5817 const elem_llvm_ty = try self.dg.lowerType(field_ty);
6021 if (field_ty.zigTypeTag() == .Float or field_ty.zigTypeTag() == .Vector) {5818 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
6022 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));5819 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
6023 const same_size_int = self.context.intType(elem_bits);5820 const same_size_int = self.context.intType(elem_bits);
6024 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");5821 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");
6025 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");5822 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
6026 } else if (field_ty.isPtrAtRuntime()) {5823 } else if (field_ty.isPtrAtRuntime(mod)) {
6027 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));5824 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
6028 const same_size_int = self.context.intType(elem_bits);5825 const same_size_int = self.context.intType(elem_bits);
6029 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");5826 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");
6030 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");5827 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
...@@ -6035,30 +5832,35 @@ pub const FuncGen = struct {...@@ -6035,30 +5832,35 @@ pub const FuncGen = struct {
6035 }5832 }
6036 }5833 }
60375834
6038 switch (struct_ty.zigTypeTag()) {5835 switch (struct_ty.zigTypeTag(mod)) {
6039 .Struct => {5836 .Struct => {
6040 assert(struct_ty.containerLayout() != .Packed);5837 assert(struct_ty.containerLayout(mod) != .Packed);
6041 var ptr_ty_buf: Type.Payload.Pointer = undefined;5838 const llvm_field = llvmField(struct_ty, field_index, mod).?;
6042 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
6043 const struct_llvm_ty = try self.dg.lowerType(struct_ty);5839 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, "");5840 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);5841 const field_ptr_ty = try mod.ptrType(.{
6046 if (isByRef(field_ty)) {5842 .child = llvm_field.ty.toIntern(),
5843 .flags = .{
5844 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
5845 },
5846 });
5847 if (isByRef(field_ty, mod)) {
6047 if (canElideLoad(self, body_tail))5848 if (canElideLoad(self, body_tail))
6048 return field_ptr;5849 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);
6051 } else {5853 } else {
6052 return self.load(field_ptr, field_ptr_ty);5854 return self.load(field_ptr, field_ptr_ty);
6053 }5855 }
6054 },5856 },
6055 .Union => {5857 .Union => {
6056 const union_llvm_ty = try self.dg.lowerType(struct_ty);5858 const union_llvm_ty = try self.dg.lowerType(struct_ty);
6057 const layout = struct_ty.unionGetLayout(target);5859 const layout = struct_ty.unionGetLayout(mod);
6058 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);5860 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
6059 const field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, "");5861 const field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, "");
6060 const llvm_field_ty = try self.dg.lowerType(field_ty);5862 const llvm_field_ty = try self.dg.lowerType(field_ty);
6061 if (isByRef(field_ty)) {5863 if (isByRef(field_ty, mod)) {
6062 if (canElideLoad(self, body_tail))5864 if (canElideLoad(self, body_tail))
6063 return field_ptr;5865 return field_ptr;
60645866
...@@ -6072,14 +5874,15 @@ pub const FuncGen = struct {...@@ -6072,14 +5874,15 @@ pub const FuncGen = struct {
6072 }5874 }
60735875
6074 fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5876 fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5877 const mod = self.dg.module;
6075 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5878 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
6076 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;5879 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
60775880
6078 const field_ptr = try self.resolveInst(extra.field_ptr);5881 const field_ptr = try self.resolveInst(extra.field_ptr);
60795882
6080 const target = self.dg.module.getTarget();5883 const target = self.dg.module.getTarget();
6081 const parent_ty = self.air.getRefType(ty_pl.ty).childType();5884 const parent_ty = self.air.getRefType(ty_pl.ty).childType(mod);
6082 const field_offset = parent_ty.structFieldOffset(extra.field_index, target);5885 const field_offset = parent_ty.structFieldOffset(extra.field_index, mod);
60835886
6084 const res_ty = try self.dg.lowerType(self.air.getRefType(ty_pl.ty));5887 const res_ty = try self.dg.lowerType(self.air.getRefType(ty_pl.ty));
6085 if (field_offset == 0) {5888 if (field_offset == 0) {
...@@ -6120,12 +5923,13 @@ pub const FuncGen = struct {...@@ -6120,12 +5923,13 @@ pub const FuncGen = struct {
61205923
6121 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5924 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6122 const dib = self.dg.object.di_builder orelse return null;5925 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);
6126 const decl_index = func.owner_decl;5930 const decl_index = func.owner_decl;
6127 const decl = self.dg.module.declPtr(decl_index);5931 const decl = mod.declPtr(decl_index);
6128 const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope);5932 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
6129 self.di_file = di_file;5933 self.di_file = di_file;
6130 const line_number = decl.src_line + 1;5934 const line_number = decl.src_line + 1;
6131 const cur_debug_location = self.builder.getCurrentDebugLocation2();5935 const cur_debug_location = self.builder.getCurrentDebugLocation2();
...@@ -6136,22 +5940,37 @@ pub const FuncGen = struct {...@@ -6136,22 +5940,37 @@ pub const FuncGen = struct {
6136 .base_line = self.base_line,5940 .base_line = self.base_line,
6137 });5941 });
61385942
6139 const fqn = try decl.getFullyQualifiedName(self.dg.module);5943 const fqn = try decl.getFullyQualifiedName(mod);
6140 defer self.gpa.free(fqn);5944
61415945 const is_internal_linkage = !mod.decl_exports.contains(decl_index);
6142 const is_internal_linkage = !self.dg.module.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);
6143 const subprogram = dib.createFunction(5962 const subprogram = dib.createFunction(
6144 di_file.toScope(),5963 di_file.toScope(),
6145 decl.name,5964 mod.intern_pool.stringToSlice(decl.name),
6146 fqn,5965 mod.intern_pool.stringToSlice(fqn),
6147 di_file,5966 di_file,
6148 line_number,5967 line_number,
6149 try self.dg.object.lowerDebugType(Type.initTag(.fn_void_no_args), .full),5968 fn_di_ty,
6150 is_internal_linkage,5969 is_internal_linkage,
6151 true, // is definition5970 true, // is definition
6152 line_number + func.lbrace_line, // scope line5971 line_number + func.lbrace_line, // scope line
6153 llvm.DIFlags.StaticMember,5972 llvm.DIFlags.StaticMember,
6154 self.dg.module.comp.bin_file.options.optimize_mode != .Debug,5973 mod.comp.bin_file.options.optimize_mode != .Debug,
6155 null, // decl_subprogram5974 null, // decl_subprogram
6156 );5975 );
61575976
...@@ -6163,12 +5982,12 @@ pub const FuncGen = struct {...@@ -6163,12 +5982,12 @@ pub const FuncGen = struct {
61635982
6164 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5983 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6165 if (self.dg.object.di_builder == null) return null;5984 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;
6169 const mod = self.dg.module;5987 const mod = self.dg.module;
5988 const func = mod.funcPtr(ty_fn.func);
6170 const decl = mod.declPtr(func.owner_decl);5989 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);
6172 self.di_file = di_file;5991 self.di_file = di_file;
6173 const old = self.dbg_inlined.pop();5992 const old = self.dbg_inlined.pop();
6174 self.di_scope = old.scope;5993 self.di_scope = old.scope;
...@@ -6192,18 +6011,19 @@ pub const FuncGen = struct {...@@ -6192,18 +6011,19 @@ pub const FuncGen = struct {
6192 }6011 }
61936012
6194 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6013 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6014 const mod = self.dg.module;
6195 const dib = self.dg.object.di_builder orelse return null;6015 const dib = self.dg.object.di_builder orelse return null;
6196 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6016 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
6197 const operand = try self.resolveInst(pl_op.operand);6017 const operand = try self.resolveInst(pl_op.operand);
6198 const name = self.air.nullTerminatedString(pl_op.payload);6018 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
6201 const di_local_var = dib.createAutoVariable(6021 const di_local_var = dib.createAutoVariable(
6202 self.di_scope.?,6022 self.di_scope.?,
6203 name.ptr,6023 name.ptr,
6204 self.di_file.?,6024 self.di_file.?,
6205 self.prev_dbg_line,6025 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),
6207 true, // always preserve6027 true, // always preserve
6208 0, // flags6028 0, // flags
6209 );6029 );
...@@ -6221,7 +6041,7 @@ pub const FuncGen = struct {...@@ -6221,7 +6041,7 @@ pub const FuncGen = struct {
6221 const dib = self.dg.object.di_builder orelse return null;6041 const dib = self.dg.object.di_builder orelse return null;
6222 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6042 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
6223 const operand = try self.resolveInst(pl_op.operand);6043 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);
6225 const name = self.air.nullTerminatedString(pl_op.payload);6045 const name = self.air.nullTerminatedString(pl_op.payload);
62266046
6227 if (needDbgVarWorkaround(self.dg)) {6047 if (needDbgVarWorkaround(self.dg)) {
...@@ -6243,10 +6063,11 @@ pub const FuncGen = struct {...@@ -6243,10 +6063,11 @@ pub const FuncGen = struct {
6243 null;6063 null;
6244 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);6064 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);
6245 const insert_block = self.builder.getInsertBlock();6065 const insert_block = self.builder.getInsertBlock();
6246 if (isByRef(operand_ty)) {6066 const mod = self.dg.module;
6067 if (isByRef(operand_ty, mod)) {
6247 _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block);6068 _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block);
6248 } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) {6069 } 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);
6250 const alloca = self.buildAlloca(operand.typeOf(), alignment);6071 const alloca = self.buildAlloca(operand.typeOf(), alignment);
6251 const store_inst = self.builder.buildStore(operand, alloca);6072 const store_inst = self.builder.buildStore(operand, alloca);
6252 store_inst.setAlignment(alignment);6073 store_inst.setAlignment(alignment);
...@@ -6294,7 +6115,8 @@ pub const FuncGen = struct {...@@ -6294,7 +6115,8 @@ pub const FuncGen = struct {
6294 // This stores whether we need to add an elementtype attribute and6115 // This stores whether we need to add an elementtype attribute and
6295 // if so, the element type itself.6116 // if so, the element type itself.
6296 const llvm_param_attrs = try arena.alloc(?*llvm.Type, max_param_count);6117 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
6299 var llvm_ret_i: usize = 0;6121 var llvm_ret_i: usize = 0;
6300 var llvm_param_i: usize = 0;6122 var llvm_param_i: usize = 0;
...@@ -6321,9 +6143,9 @@ pub const FuncGen = struct {...@@ -6321,9 +6143,9 @@ pub const FuncGen = struct {
6321 llvm_ret_indirect[i] = (output != .none) and constraintAllowsMemory(constraint);6143 llvm_ret_indirect[i] = (output != .none) and constraintAllowsMemory(constraint);
6322 if (output != .none) {6144 if (output != .none) {
6323 const output_inst = try self.resolveInst(output);6145 const output_inst = try self.resolveInst(output);
6324 const output_ty = self.air.typeOf(output);6146 const output_ty = self.typeOf(output);
6325 assert(output_ty.zigTypeTag() == .Pointer);6147 assert(output_ty.zigTypeTag(mod) == .Pointer);
6326 const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType());6148 const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType(mod));
63276149
6328 if (llvm_ret_indirect[i]) {6150 if (llvm_ret_indirect[i]) {
6329 // Pass the result by reference as an indirect output (e.g. "=*m")6151 // Pass the result by reference as an indirect output (e.g. "=*m")
...@@ -6339,7 +6161,7 @@ pub const FuncGen = struct {...@@ -6339,7 +6161,7 @@ pub const FuncGen = struct {
6339 llvm_ret_i += 1;6161 llvm_ret_i += 1;
6340 }6162 }
6341 } else {6163 } else {
6342 const ret_ty = self.air.typeOfIndex(inst);6164 const ret_ty = self.typeOfIndex(inst);
6343 llvm_ret_types[llvm_ret_i] = try self.dg.lowerType(ret_ty);6165 llvm_ret_types[llvm_ret_i] = try self.dg.lowerType(ret_ty);
6344 llvm_ret_i += 1;6166 llvm_ret_i += 1;
6345 }6167 }
...@@ -6374,15 +6196,15 @@ pub const FuncGen = struct {...@@ -6374,15 +6196,15 @@ pub const FuncGen = struct {
6374 extra_i += (constraint.len + name.len + (2 + 3)) / 4;6196 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
63756197
6376 const arg_llvm_value = try self.resolveInst(input);6198 const arg_llvm_value = try self.resolveInst(input);
6377 const arg_ty = self.air.typeOf(input);6199 const arg_ty = self.typeOf(input);
6378 var llvm_elem_ty: ?*llvm.Type = null;6200 var llvm_elem_ty: ?*llvm.Type = null;
6379 if (isByRef(arg_ty)) {6201 if (isByRef(arg_ty, mod)) {
6380 llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty);6202 llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty);
6381 if (constraintAllowsMemory(constraint)) {6203 if (constraintAllowsMemory(constraint)) {
6382 llvm_param_values[llvm_param_i] = arg_llvm_value;6204 llvm_param_values[llvm_param_i] = arg_llvm_value;
6383 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();6205 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
6384 } else {6206 } else {
6385 const alignment = arg_ty.abiAlignment(target);6207 const alignment = arg_ty.abiAlignment(mod);
6386 const arg_llvm_ty = try self.dg.lowerType(arg_ty);6208 const arg_llvm_ty = try self.dg.lowerType(arg_ty);
6387 const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, "");6209 const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, "");
6388 load_inst.setAlignment(alignment);6210 load_inst.setAlignment(alignment);
...@@ -6394,7 +6216,7 @@ pub const FuncGen = struct {...@@ -6394,7 +6216,7 @@ pub const FuncGen = struct {
6394 llvm_param_values[llvm_param_i] = arg_llvm_value;6216 llvm_param_values[llvm_param_i] = arg_llvm_value;
6395 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();6217 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
6396 } else {6218 } else {
6397 const alignment = arg_ty.abiAlignment(target);6219 const alignment = arg_ty.abiAlignment(mod);
6398 const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf(), alignment);6220 const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf(), alignment);
6399 const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr);6221 const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr);
6400 store_inst.setAlignment(alignment);6222 store_inst.setAlignment(alignment);
...@@ -6424,7 +6246,7 @@ pub const FuncGen = struct {...@@ -6424,7 +6246,7 @@ pub const FuncGen = struct {
6424 // an elementtype(<ty>) attribute.6246 // an elementtype(<ty>) attribute.
6425 if (constraint[0] == '*') {6247 if (constraint[0] == '*') {
6426 llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse6248 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));
6428 } else {6250 } else {
6429 llvm_param_attrs[llvm_param_i] = null;6251 llvm_param_attrs[llvm_param_i] = null;
6430 }6252 }
...@@ -6596,10 +6418,10 @@ pub const FuncGen = struct {...@@ -6596,10 +6418,10 @@ pub const FuncGen = struct {
65966418
6597 if (output != .none) {6419 if (output != .none) {
6598 const output_ptr = try self.resolveInst(output);6420 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
6601 const store_inst = self.builder.buildStore(output_value, output_ptr);6423 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));
6603 } else {6425 } else {
6604 ret_val = output_value;6426 ret_val = output_value;
6605 }6427 }
...@@ -6615,22 +6437,21 @@ pub const FuncGen = struct {...@@ -6615,22 +6437,21 @@ pub const FuncGen = struct {
6615 operand_is_ptr: bool,6437 operand_is_ptr: bool,
6616 pred: llvm.IntPredicate,6438 pred: llvm.IntPredicate,
6617 ) !?*llvm.Value {6439 ) !?*llvm.Value {
6440 const mod = self.dg.module;
6618 const un_op = self.air.instructions.items(.data)[inst].un_op;6441 const un_op = self.air.instructions.items(.data)[inst].un_op;
6619 const operand = try self.resolveInst(un_op);6442 const operand = try self.resolveInst(un_op);
6620 const operand_ty = self.air.typeOf(un_op);6443 const operand_ty = self.typeOf(un_op);
6621 const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;6444 const optional_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6622 const optional_llvm_ty = try self.dg.lowerType(optional_ty);6445 const optional_llvm_ty = try self.dg.lowerType(optional_ty);
6623 var buf: Type.Payload.ElemType = undefined;6446 const payload_ty = optional_ty.optionalChild(mod);
6624 const payload_ty = optional_ty.optionalChild(&buf);6447 if (optional_ty.optionalReprIsPayload(mod)) {
6625 if (optional_ty.optionalReprIsPayload()) {
6626 const loaded = if (operand_is_ptr)6448 const loaded = if (operand_is_ptr)
6627 self.builder.buildLoad(optional_llvm_ty, operand, "")6449 self.builder.buildLoad(optional_llvm_ty, operand, "")
6628 else6450 else
6629 operand;6451 operand;
6630 if (payload_ty.isSlice()) {6452 if (payload_ty.isSlice(mod)) {
6631 const slice_ptr = self.builder.buildExtractValue(loaded, 0, "");6453 const slice_ptr = self.builder.buildExtractValue(loaded, 0, "");
6632 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;6454 const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(mod));
6633 const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf));
6634 return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), "");6455 return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), "");
6635 }6456 }
6636 return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), "");6457 return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), "");
...@@ -6638,7 +6459,7 @@ pub const FuncGen = struct {...@@ -6638,7 +6459,7 @@ pub const FuncGen = struct {
66386459
6639 comptime assert(optional_layout_version == 3);6460 comptime assert(optional_layout_version == 3);
66406461
6641 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6462 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6642 const loaded = if (operand_is_ptr)6463 const loaded = if (operand_is_ptr)
6643 self.builder.buildLoad(optional_llvm_ty, operand, "")6464 self.builder.buildLoad(optional_llvm_ty, operand, "")
6644 else6465 else
...@@ -6647,7 +6468,7 @@ pub const FuncGen = struct {...@@ -6647,7 +6468,7 @@ pub const FuncGen = struct {
6647 return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), "");6468 return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), "");
6648 }6469 }
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);
6651 const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref);6472 const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref);
6652 if (pred == .EQ) {6473 if (pred == .EQ) {
6653 return self.builder.buildNot(non_null_bit, "");6474 return self.builder.buildNot(non_null_bit, "");
...@@ -6662,15 +6483,16 @@ pub const FuncGen = struct {...@@ -6662,15 +6483,16 @@ pub const FuncGen = struct {
6662 op: llvm.IntPredicate,6483 op: llvm.IntPredicate,
6663 operand_is_ptr: bool,6484 operand_is_ptr: bool,
6664 ) !?*llvm.Value {6485 ) !?*llvm.Value {
6486 const mod = self.dg.module;
6665 const un_op = self.air.instructions.items(.data)[inst].un_op;6487 const un_op = self.air.instructions.items(.data)[inst].un_op;
6666 const operand = try self.resolveInst(un_op);6488 const operand = try self.resolveInst(un_op);
6667 const operand_ty = self.air.typeOf(un_op);6489 const operand_ty = self.typeOf(un_op);
6668 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;6490 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6669 const payload_ty = err_union_ty.errorUnionPayload();6491 const payload_ty = err_union_ty.errorUnionPayload(mod);
6670 const err_set_ty = try self.dg.lowerType(Type.anyerror);6492 const err_set_ty = try self.dg.lowerType(Type.anyerror);
6671 const zero = err_set_ty.constNull();6493 const zero = err_set_ty.constNull();
66726494
6673 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {6495 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
6674 const llvm_i1 = self.context.intType(1);6496 const llvm_i1 = self.context.intType(1);
6675 switch (op) {6497 switch (op) {
6676 .EQ => return llvm_i1.constInt(1, .False), // 0 == 06498 .EQ => return llvm_i1.constInt(1, .False), // 0 == 0
...@@ -6679,7 +6501,7 @@ pub const FuncGen = struct {...@@ -6679,7 +6501,7 @@ pub const FuncGen = struct {
6679 }6501 }
6680 }6502 }
66816503
6682 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6504 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6683 const loaded = if (operand_is_ptr)6505 const loaded = if (operand_is_ptr)
6684 self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "")6506 self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "")
6685 else6507 else
...@@ -6687,10 +6509,9 @@ pub const FuncGen = struct {...@@ -6687,10 +6509,9 @@ pub const FuncGen = struct {
6687 return self.builder.buildICmp(op, loaded, zero, "");6509 return self.builder.buildICmp(op, loaded, zero, "");
6688 }6510 }
66896511
6690 const target = self.dg.module.getTarget();6512 const err_field_index = errUnionErrorOffset(payload_ty, mod);
6691 const err_field_index = errUnionErrorOffset(payload_ty, target);
66926513
6693 if (operand_is_ptr or isByRef(err_union_ty)) {6514 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
6694 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);6515 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
6695 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, "");6516 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, "");
6696 const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, "");6517 const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, "");
...@@ -6702,17 +6523,17 @@ pub const FuncGen = struct {...@@ -6702,17 +6523,17 @@ pub const FuncGen = struct {
6702 }6523 }
67036524
6704 fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6525 fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6526 const mod = self.dg.module;
6705 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6527 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6706 const operand = try self.resolveInst(ty_op.operand);6528 const operand = try self.resolveInst(ty_op.operand);
6707 const optional_ty = self.air.typeOf(ty_op.operand).childType();6529 const optional_ty = self.typeOf(ty_op.operand).childType(mod);
6708 var buf: Type.Payload.ElemType = undefined;6530 const payload_ty = optional_ty.optionalChild(mod);
6709 const payload_ty = optional_ty.optionalChild(&buf);6531 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6710 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6711 // We have a pointer to a zero-bit value and we need to return6532 // We have a pointer to a zero-bit value and we need to return
6712 // a pointer to a zero-bit value.6533 // a pointer to a zero-bit value.
6713 return operand;6534 return operand;
6714 }6535 }
6715 if (optional_ty.optionalReprIsPayload()) {6536 if (optional_ty.optionalReprIsPayload(mod)) {
6716 // The payload and the optional are the same value.6537 // The payload and the optional are the same value.
6717 return operand;6538 return operand;
6718 }6539 }
...@@ -6723,18 +6544,18 @@ pub const FuncGen = struct {...@@ -6723,18 +6544,18 @@ pub const FuncGen = struct {
6723 fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6544 fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6724 comptime assert(optional_layout_version == 3);6545 comptime assert(optional_layout_version == 3);
67256546
6547 const mod = self.dg.module;
6726 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6548 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6727 const operand = try self.resolveInst(ty_op.operand);6549 const operand = try self.resolveInst(ty_op.operand);
6728 const optional_ty = self.air.typeOf(ty_op.operand).childType();6550 const optional_ty = self.typeOf(ty_op.operand).childType(mod);
6729 var buf: Type.Payload.ElemType = undefined;6551 const payload_ty = optional_ty.optionalChild(mod);
6730 const payload_ty = optional_ty.optionalChild(&buf);
6731 const non_null_bit = self.context.intType(8).constInt(1, .False);6552 const non_null_bit = self.context.intType(8).constInt(1, .False);
6732 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6553 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6733 // We have a pointer to a i8. We need to set it to 1 and then return the same pointer.6554 // We have a pointer to a i8. We need to set it to 1 and then return the same pointer.
6734 _ = self.builder.buildStore(non_null_bit, operand);6555 _ = self.builder.buildStore(non_null_bit, operand);
6735 return operand;6556 return operand;
6736 }6557 }
6737 if (optional_ty.optionalReprIsPayload()) {6558 if (optional_ty.optionalReprIsPayload(mod)) {
6738 // The payload and the optional are the same value.6559 // The payload and the optional are the same value.
6739 // Setting to non-null will be done when the payload is set.6560 // Setting to non-null will be done when the payload is set.
6740 return operand;6561 return operand;
...@@ -6754,20 +6575,21 @@ pub const FuncGen = struct {...@@ -6754,20 +6575,21 @@ pub const FuncGen = struct {
6754 }6575 }
67556576
6756 fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {6577 fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
6578 const mod = self.dg.module;
6757 const inst = body_tail[0];6579 const inst = body_tail[0];
6758 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6580 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6759 const operand = try self.resolveInst(ty_op.operand);6581 const operand = try self.resolveInst(ty_op.operand);
6760 const optional_ty = self.air.typeOf(ty_op.operand);6582 const optional_ty = self.typeOf(ty_op.operand);
6761 const payload_ty = self.air.typeOfIndex(inst);6583 const payload_ty = self.typeOfIndex(inst);
6762 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return null;6584 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
67636585
6764 if (optional_ty.optionalReprIsPayload()) {6586 if (optional_ty.optionalReprIsPayload(mod)) {
6765 // Payload value is the same as the optional value.6587 // Payload value is the same as the optional value.
6766 return operand;6588 return operand;
6767 }6589 }
67686590
6769 const opt_llvm_ty = try self.dg.lowerType(optional_ty);6591 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;
6771 return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty, can_elide_load);6593 return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty, can_elide_load);
6772 }6594 }
67736595
...@@ -6776,32 +6598,32 @@ pub const FuncGen = struct {...@@ -6776,32 +6598,32 @@ pub const FuncGen = struct {
6776 body_tail: []const Air.Inst.Index,6598 body_tail: []const Air.Inst.Index,
6777 operand_is_ptr: bool,6599 operand_is_ptr: bool,
6778 ) !?*llvm.Value {6600 ) !?*llvm.Value {
6601 const mod = self.dg.module;
6779 const inst = body_tail[0];6602 const inst = body_tail[0];
6780 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6603 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6781 const operand = try self.resolveInst(ty_op.operand);6604 const operand = try self.resolveInst(ty_op.operand);
6782 const operand_ty = self.air.typeOf(ty_op.operand);6605 const operand_ty = self.typeOf(ty_op.operand);
6783 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;6606 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6784 const result_ty = self.air.typeOfIndex(inst);6607 const result_ty = self.typeOfIndex(inst);
6785 const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty;6608 const payload_ty = if (operand_is_ptr) result_ty.childType(mod) else result_ty;
6786 const target = self.dg.module.getTarget();
67876609
6788 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6610 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6789 return if (operand_is_ptr) operand else null;6611 return if (operand_is_ptr) operand else null;
6790 }6612 }
6791 const offset = errUnionPayloadOffset(payload_ty, target);6613 const offset = errUnionPayloadOffset(payload_ty, mod);
6792 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);6614 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
6793 if (operand_is_ptr) {6615 if (operand_is_ptr) {
6794 return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");6616 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)) {
6796 const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");6618 const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");
6797 if (isByRef(payload_ty)) {6619 if (isByRef(payload_ty, mod)) {
6798 if (self.canElideLoad(body_tail))6620 if (self.canElideLoad(body_tail))
6799 return payload_ptr;6621 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);
6802 }6624 }
6803 const load_inst = self.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, "");6625 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));
6805 return load_inst;6627 return load_inst;
6806 }6628 }
6807 return self.builder.buildExtractValue(operand, offset, "");6629 return self.builder.buildExtractValue(operand, offset, "");
...@@ -6812,11 +6634,12 @@ pub const FuncGen = struct {...@@ -6812,11 +6634,12 @@ pub const FuncGen = struct {
6812 inst: Air.Inst.Index,6634 inst: Air.Inst.Index,
6813 operand_is_ptr: bool,6635 operand_is_ptr: bool,
6814 ) !?*llvm.Value {6636 ) !?*llvm.Value {
6637 const mod = self.dg.module;
6815 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6638 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6816 const operand = try self.resolveInst(ty_op.operand);6639 const operand = try self.resolveInst(ty_op.operand);
6817 const operand_ty = self.air.typeOf(ty_op.operand);6640 const operand_ty = self.typeOf(ty_op.operand);
6818 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;6641 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6819 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {6642 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
6820 const err_llvm_ty = try self.dg.lowerType(Type.anyerror);6643 const err_llvm_ty = try self.dg.lowerType(Type.anyerror);
6821 if (operand_is_ptr) {6644 if (operand_is_ptr) {
6822 return operand;6645 return operand;
...@@ -6827,16 +6650,15 @@ pub const FuncGen = struct {...@@ -6827,16 +6650,15 @@ pub const FuncGen = struct {
68276650
6828 const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror);6651 const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror);
68296652
6830 const payload_ty = err_union_ty.errorUnionPayload();6653 const payload_ty = err_union_ty.errorUnionPayload(mod);
6831 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6654 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6832 if (!operand_is_ptr) return operand;6655 if (!operand_is_ptr) return operand;
6833 return self.builder.buildLoad(err_set_llvm_ty, operand, "");6656 return self.builder.buildLoad(err_set_llvm_ty, operand, "");
6834 }6657 }
68356658
6836 const target = self.dg.module.getTarget();6659 const offset = errUnionErrorOffset(payload_ty, mod);
6837 const offset = errUnionErrorOffset(payload_ty, target);
68386660
6839 if (operand_is_ptr or isByRef(err_union_ty)) {6661 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
6840 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);6662 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
6841 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");6663 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");
6842 return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, "");6664 return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, "");
...@@ -6846,30 +6668,30 @@ pub const FuncGen = struct {...@@ -6846,30 +6668,30 @@ pub const FuncGen = struct {
6846 }6668 }
68476669
6848 fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6670 fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6671 const mod = self.dg.module;
6849 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6672 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6850 const operand = try self.resolveInst(ty_op.operand);6673 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();6676 const payload_ty = err_union_ty.errorUnionPayload(mod);
6854 const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero });6677 const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = try mod.intValue(Type.err_int, 0) });
6855 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6678 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6856 _ = self.builder.buildStore(non_error_val, operand);6679 _ = self.builder.buildStore(non_error_val, operand);
6857 return operand;6680 return operand;
6858 }6681 }
6859 const target = self.dg.module.getTarget();
6860 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);6682 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
6861 {6683 {
6862 const error_offset = errUnionErrorOffset(payload_ty, target);6684 const error_offset = errUnionErrorOffset(payload_ty, mod);
6863 // First set the non-error value.6685 // First set the non-error value.
6864 const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, "");6686 const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, "");
6865 const store_inst = self.builder.buildStore(non_error_val, non_null_ptr);6687 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));
6867 }6689 }
6868 // Then return the payload pointer (only if it is used).6690 // Then return the payload pointer (only if it is used).
6869 if (self.liveness.isUnused(inst))6691 if (self.liveness.isUnused(inst))
6870 return null;6692 return null;
68716693
6872 const payload_offset = errUnionPayloadOffset(payload_ty, target);6694 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
6873 return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, "");6695 return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, "");
6874 }6696 }
68756697
...@@ -6885,42 +6707,41 @@ pub const FuncGen = struct {...@@ -6885,42 +6707,41 @@ pub const FuncGen = struct {
6885 }6707 }
68866708
6887 fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6709 fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6888 const target = self.dg.module.getTarget();
6889
6890 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6710 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
6891 //const struct_ty = try self.resolveInst(ty_pl.ty);6711 //const struct_ty = try self.resolveInst(ty_pl.ty);
6892 const struct_ty = self.air.getRefType(ty_pl.ty);6712 const struct_ty = self.air.getRefType(ty_pl.ty);
6893 const field_index = ty_pl.payload;6713 const field_index = ty_pl.payload;
68946714
6895 var ptr_ty_buf: Type.Payload.Pointer = undefined;6715 const mod = self.dg.module;
6896 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;6716 const llvm_field = llvmField(struct_ty, field_index, mod).?;
6897 const struct_llvm_ty = try self.dg.lowerType(struct_ty);6717 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, "");6718 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);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 });
6900 return self.load(field_ptr, field_ptr_ty);6725 return self.load(field_ptr, field_ptr_ty);
6901 }6726 }
69026727
6903 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6728 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6729 const mod = self.dg.module;
6904 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6730 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);
6906 const non_null_bit = self.context.intType(8).constInt(1, .False);6732 const non_null_bit = self.context.intType(8).constInt(1, .False);
6907 comptime assert(optional_layout_version == 3);6733 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;
6909 const operand = try self.resolveInst(ty_op.operand);6735 const operand = try self.resolveInst(ty_op.operand);
6910 const optional_ty = self.air.typeOfIndex(inst);6736 const optional_ty = self.typeOfIndex(inst);
6911 if (optional_ty.optionalReprIsPayload()) {6737 if (optional_ty.optionalReprIsPayload(mod)) {
6912 return operand;6738 return operand;
6913 }6739 }
6914 const llvm_optional_ty = try self.dg.lowerType(optional_ty);6740 const llvm_optional_ty = try self.dg.lowerType(optional_ty);
6915 if (isByRef(optional_ty)) {6741 if (isByRef(optional_ty, mod)) {
6916 const target = self.dg.module.getTarget();6742 const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(mod));
6917 const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(target));
6918 const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, "");6743 const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, "");
6919 var ptr_ty_payload: Type.Payload.ElemType = .{6744 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
6920 .base = .{ .tag = .single_mut_pointer },
6921 .data = payload_ty,
6922 };
6923 const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
6924 try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);6745 try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
6925 const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, "");6746 const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, "");
6926 _ = self.builder.buildStore(non_null_bit, non_null_ptr);6747 _ = self.builder.buildStore(non_null_bit, non_null_ptr);
...@@ -6931,30 +6752,26 @@ pub const FuncGen = struct {...@@ -6931,30 +6752,26 @@ pub const FuncGen = struct {
6931 }6752 }
69326753
6933 fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6754 fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6755 const mod = self.dg.module;
6934 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6756 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);
6936 const operand = try self.resolveInst(ty_op.operand);6758 const operand = try self.resolveInst(ty_op.operand);
6937 const payload_ty = self.air.typeOf(ty_op.operand);6759 const payload_ty = self.typeOf(ty_op.operand);
6938 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6760 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6939 return operand;6761 return operand;
6940 }6762 }
6941 const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull();6763 const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull();
6942 const err_un_llvm_ty = try self.dg.lowerType(err_un_ty);6764 const err_un_llvm_ty = try self.dg.lowerType(err_un_ty);
69436765
6944 const target = self.dg.module.getTarget();6766 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
6945 const payload_offset = errUnionPayloadOffset(payload_ty, target);6767 const error_offset = errUnionErrorOffset(payload_ty, mod);
6946 const error_offset = errUnionErrorOffset(payload_ty, target);6768 if (isByRef(err_un_ty, mod)) {
6947 if (isByRef(err_un_ty)) {6769 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod));
6948 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target));
6949 const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, "");6770 const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, "");
6950 const store_inst = self.builder.buildStore(ok_err_code, err_ptr);6771 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));
6952 const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, "");6773 const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, "");
6953 var ptr_ty_payload: Type.Payload.ElemType = .{6774 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
6954 .base = .{ .tag = .single_mut_pointer },
6955 .data = payload_ty,
6956 };
6957 const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
6958 try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);6775 try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
6959 return result_ptr;6776 return result_ptr;
6960 }6777 }
...@@ -6964,29 +6781,25 @@ pub const FuncGen = struct {...@@ -6964,29 +6781,25 @@ pub const FuncGen = struct {
6964 }6781 }
69656782
6966 fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6783 fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6784 const mod = self.dg.module;
6967 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6785 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6968 const err_un_ty = self.air.typeOfIndex(inst);6786 const err_un_ty = self.typeOfIndex(inst);
6969 const payload_ty = err_un_ty.errorUnionPayload();6787 const payload_ty = err_un_ty.errorUnionPayload(mod);
6970 const operand = try self.resolveInst(ty_op.operand);6788 const operand = try self.resolveInst(ty_op.operand);
6971 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {6789 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
6972 return operand;6790 return operand;
6973 }6791 }
6974 const err_un_llvm_ty = try self.dg.lowerType(err_un_ty);6792 const err_un_llvm_ty = try self.dg.lowerType(err_un_ty);
69756793
6976 const target = self.dg.module.getTarget();6794 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
6977 const payload_offset = errUnionPayloadOffset(payload_ty, target);6795 const error_offset = errUnionErrorOffset(payload_ty, mod);
6978 const error_offset = errUnionErrorOffset(payload_ty, target);6796 if (isByRef(err_un_ty, mod)) {
6979 if (isByRef(err_un_ty)) {6797 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod));
6980 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target));
6981 const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, "");6798 const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, "");
6982 const store_inst = self.builder.buildStore(operand, err_ptr);6799 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));
6984 const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, "");6801 const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, "");
6985 var ptr_ty_payload: Type.Payload.ElemType = .{6802 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
6986 .base = .{ .tag = .single_mut_pointer },
6987 .data = payload_ty,
6988 };
6989 const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
6990 // TODO store undef to payload_ptr6803 // TODO store undef to payload_ptr
6991 _ = payload_ptr;6804 _ = payload_ptr;
6992 _ = payload_ptr_ty;6805 _ = payload_ptr_ty;
...@@ -7021,20 +6834,20 @@ pub const FuncGen = struct {...@@ -7021,20 +6834,20 @@ pub const FuncGen = struct {
7021 }6834 }
70226835
7023 fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6836 fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6837 const mod = self.dg.module;
7024 const data = self.air.instructions.items(.data)[inst].vector_store_elem;6838 const data = self.air.instructions.items(.data)[inst].vector_store_elem;
7025 const extra = self.air.extraData(Air.Bin, data.payload).data;6839 const extra = self.air.extraData(Air.Bin, data.payload).data;
70266840
7027 const vector_ptr = try self.resolveInst(data.vector_ptr);6841 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);
7029 const index = try self.resolveInst(extra.lhs);6843 const index = try self.resolveInst(extra.lhs);
7030 const operand = try self.resolveInst(extra.rhs);6844 const operand = try self.resolveInst(extra.rhs);
70316845
7032 const loaded_vector = blk: {6846 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));
7034 const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, "");6848 const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, "");
7035 const target = self.dg.module.getTarget();6849 load_inst.setAlignment(vector_ptr_ty.ptrAlignment(mod));
7036 load_inst.setAlignment(vector_ptr_ty.ptrAlignment(target));6850 load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr(mod)));
7037 load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr()));
7038 break :blk load_inst;6851 break :blk load_inst;
7039 };6852 };
7040 const modified_vector = self.builder.buildInsertElement(loaded_vector, operand, index, "");6853 const modified_vector = self.builder.buildInsertElement(loaded_vector, operand, index, "");
...@@ -7043,24 +6856,26 @@ pub const FuncGen = struct {...@@ -7043,24 +6856,26 @@ pub const FuncGen = struct {
7043 }6856 }
70446857
7045 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6858 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6859 const mod = self.dg.module;
7046 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6860 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7047 const lhs = try self.resolveInst(bin_op.lhs);6861 const lhs = try self.resolveInst(bin_op.lhs);
7048 const rhs = try self.resolveInst(bin_op.rhs);6862 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
7051 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs });6865 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, "");
7053 return self.builder.buildUMin(lhs, rhs, "");6867 return self.builder.buildUMin(lhs, rhs, "");
7054 }6868 }
70556869
7056 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6870 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6871 const mod = self.dg.module;
7057 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6872 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7058 const lhs = try self.resolveInst(bin_op.lhs);6873 const lhs = try self.resolveInst(bin_op.lhs);
7059 const rhs = try self.resolveInst(bin_op.rhs);6874 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
7062 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs });6877 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, "");
7064 return self.builder.buildUMax(lhs, rhs, "");6879 return self.builder.buildUMax(lhs, rhs, "");
7065 }6880 }
70666881
...@@ -7069,7 +6884,7 @@ pub const FuncGen = struct {...@@ -7069,7 +6884,7 @@ pub const FuncGen = struct {
7069 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;6884 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
7070 const ptr = try self.resolveInst(bin_op.lhs);6885 const ptr = try self.resolveInst(bin_op.lhs);
7071 const len = try self.resolveInst(bin_op.rhs);6886 const len = try self.resolveInst(bin_op.rhs);
7072 const inst_ty = self.air.typeOfIndex(inst);6887 const inst_ty = self.typeOfIndex(inst);
7073 const llvm_slice_ty = try self.dg.lowerType(inst_ty);6888 const llvm_slice_ty = try self.dg.lowerType(inst_ty);
70746889
7075 // In case of slicing a global, the result type looks something like `{ i8*, i64 }`6890 // In case of slicing a global, the result type looks something like `{ i8*, i64 }`
...@@ -7081,14 +6896,15 @@ pub const FuncGen = struct {...@@ -7081,14 +6896,15 @@ pub const FuncGen = struct {
7081 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {6896 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7082 self.builder.setFastMath(want_fast_math);6897 self.builder.setFastMath(want_fast_math);
70836898
6899 const mod = self.dg.module;
7084 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6900 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7085 const lhs = try self.resolveInst(bin_op.lhs);6901 const lhs = try self.resolveInst(bin_op.lhs);
7086 const rhs = try self.resolveInst(bin_op.rhs);6902 const rhs = try self.resolveInst(bin_op.rhs);
7087 const inst_ty = self.air.typeOfIndex(inst);6903 const inst_ty = self.typeOfIndex(inst);
7088 const scalar_ty = inst_ty.scalarType();6904 const scalar_ty = inst_ty.scalarType(mod);
70896905
7090 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, inst_ty, 2, .{ lhs, rhs });6906 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, "");
7092 return self.builder.buildNUWAdd(lhs, rhs, "");6908 return self.builder.buildNUWAdd(lhs, rhs, "");
7093 }6909 }
70946910
...@@ -7103,14 +6919,15 @@ pub const FuncGen = struct {...@@ -7103,14 +6919,15 @@ pub const FuncGen = struct {
7103 }6919 }
71046920
7105 fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6921 fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6922 const mod = self.dg.module;
7106 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6923 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7107 const lhs = try self.resolveInst(bin_op.lhs);6924 const lhs = try self.resolveInst(bin_op.lhs);
7108 const rhs = try self.resolveInst(bin_op.rhs);6925 const rhs = try self.resolveInst(bin_op.rhs);
7109 const inst_ty = self.air.typeOfIndex(inst);6926 const inst_ty = self.typeOfIndex(inst);
7110 const scalar_ty = inst_ty.scalarType();6927 const scalar_ty = inst_ty.scalarType(mod);
71116928
7112 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});6929 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
7115 return self.builder.buildUAddSat(lhs, rhs, "");6932 return self.builder.buildUAddSat(lhs, rhs, "");
7116 }6933 }
...@@ -7118,14 +6935,15 @@ pub const FuncGen = struct {...@@ -7118,14 +6935,15 @@ pub const FuncGen = struct {
7118 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {6935 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7119 self.builder.setFastMath(want_fast_math);6936 self.builder.setFastMath(want_fast_math);
71206937
6938 const mod = self.dg.module;
7121 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6939 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7122 const lhs = try self.resolveInst(bin_op.lhs);6940 const lhs = try self.resolveInst(bin_op.lhs);
7123 const rhs = try self.resolveInst(bin_op.rhs);6941 const rhs = try self.resolveInst(bin_op.rhs);
7124 const inst_ty = self.air.typeOfIndex(inst);6942 const inst_ty = self.typeOfIndex(inst);
7125 const scalar_ty = inst_ty.scalarType();6943 const scalar_ty = inst_ty.scalarType(mod);
71266944
7127 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, inst_ty, 2, .{ lhs, rhs });6945 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, "");
7129 return self.builder.buildNUWSub(lhs, rhs, "");6947 return self.builder.buildNUWSub(lhs, rhs, "");
7130 }6948 }
71316949
...@@ -7140,28 +6958,30 @@ pub const FuncGen = struct {...@@ -7140,28 +6958,30 @@ pub const FuncGen = struct {
7140 }6958 }
71416959
7142 fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6960 fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6961 const mod = self.dg.module;
7143 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6962 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7144 const lhs = try self.resolveInst(bin_op.lhs);6963 const lhs = try self.resolveInst(bin_op.lhs);
7145 const rhs = try self.resolveInst(bin_op.rhs);6964 const rhs = try self.resolveInst(bin_op.rhs);
7146 const inst_ty = self.air.typeOfIndex(inst);6965 const inst_ty = self.typeOfIndex(inst);
7147 const scalar_ty = inst_ty.scalarType();6966 const scalar_ty = inst_ty.scalarType(mod);
71486967
7149 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});6968 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, "");
7151 return self.builder.buildUSubSat(lhs, rhs, "");6970 return self.builder.buildUSubSat(lhs, rhs, "");
7152 }6971 }
71536972
7154 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {6973 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7155 self.builder.setFastMath(want_fast_math);6974 self.builder.setFastMath(want_fast_math);
71566975
6976 const mod = self.dg.module;
7157 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6977 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7158 const lhs = try self.resolveInst(bin_op.lhs);6978 const lhs = try self.resolveInst(bin_op.lhs);
7159 const rhs = try self.resolveInst(bin_op.rhs);6979 const rhs = try self.resolveInst(bin_op.rhs);
7160 const inst_ty = self.air.typeOfIndex(inst);6980 const inst_ty = self.typeOfIndex(inst);
7161 const scalar_ty = inst_ty.scalarType();6981 const scalar_ty = inst_ty.scalarType(mod);
71626982
7163 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, inst_ty, 2, .{ lhs, rhs });6983 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, "");
7165 return self.builder.buildNUWMul(lhs, rhs, "");6985 return self.builder.buildNUWMul(lhs, rhs, "");
7166 }6986 }
71676987
...@@ -7176,14 +6996,15 @@ pub const FuncGen = struct {...@@ -7176,14 +6996,15 @@ pub const FuncGen = struct {
7176 }6996 }
71776997
7178 fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6998 fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6999 const mod = self.dg.module;
7179 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7000 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7180 const lhs = try self.resolveInst(bin_op.lhs);7001 const lhs = try self.resolveInst(bin_op.lhs);
7181 const rhs = try self.resolveInst(bin_op.rhs);7002 const rhs = try self.resolveInst(bin_op.rhs);
7182 const inst_ty = self.air.typeOfIndex(inst);7003 const inst_ty = self.typeOfIndex(inst);
7183 const scalar_ty = inst_ty.scalarType();7004 const scalar_ty = inst_ty.scalarType(mod);
71847005
7185 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});7006 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, "");
7187 return self.builder.buildUMulFixSat(lhs, rhs, "");7008 return self.builder.buildUMulFixSat(lhs, rhs, "");
7188 }7009 }
71897010
...@@ -7193,7 +7014,7 @@ pub const FuncGen = struct {...@@ -7193,7 +7014,7 @@ pub const FuncGen = struct {
7193 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7014 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7194 const lhs = try self.resolveInst(bin_op.lhs);7015 const lhs = try self.resolveInst(bin_op.lhs);
7195 const rhs = try self.resolveInst(bin_op.rhs);7016 const rhs = try self.resolveInst(bin_op.rhs);
7196 const inst_ty = self.air.typeOfIndex(inst);7017 const inst_ty = self.typeOfIndex(inst);
71977018
7198 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7019 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7199 }7020 }
...@@ -7201,39 +7022,40 @@ pub const FuncGen = struct {...@@ -7201,39 +7022,40 @@ pub const FuncGen = struct {
7201 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7022 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7202 self.builder.setFastMath(want_fast_math);7023 self.builder.setFastMath(want_fast_math);
72037024
7025 const mod = self.dg.module;
7204 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7026 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7205 const lhs = try self.resolveInst(bin_op.lhs);7027 const lhs = try self.resolveInst(bin_op.lhs);
7206 const rhs = try self.resolveInst(bin_op.rhs);7028 const rhs = try self.resolveInst(bin_op.rhs);
7207 const inst_ty = self.air.typeOfIndex(inst);7029 const inst_ty = self.typeOfIndex(inst);
7208 const scalar_ty = inst_ty.scalarType();7030 const scalar_ty = inst_ty.scalarType(mod);
72097031
7210 if (scalar_ty.isRuntimeFloat()) {7032 if (scalar_ty.isRuntimeFloat()) {
7211 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7033 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7212 return self.buildFloatOp(.trunc, inst_ty, 1, .{result});7034 return self.buildFloatOp(.trunc, inst_ty, 1, .{result});
7213 }7035 }
7214 if (scalar_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, "");7036 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSDiv(lhs, rhs, "");
7215 return self.builder.buildUDiv(lhs, rhs, "");7037 return self.builder.buildUDiv(lhs, rhs, "");
7216 }7038 }
72177039
7218 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7040 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7219 self.builder.setFastMath(want_fast_math);7041 self.builder.setFastMath(want_fast_math);
72207042
7043 const mod = self.dg.module;
7221 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7044 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7222 const lhs = try self.resolveInst(bin_op.lhs);7045 const lhs = try self.resolveInst(bin_op.lhs);
7223 const rhs = try self.resolveInst(bin_op.rhs);7046 const rhs = try self.resolveInst(bin_op.rhs);
7224 const inst_ty = self.air.typeOfIndex(inst);7047 const inst_ty = self.typeOfIndex(inst);
7225 const scalar_ty = inst_ty.scalarType();7048 const scalar_ty = inst_ty.scalarType(mod);
72267049
7227 if (scalar_ty.isRuntimeFloat()) {7050 if (scalar_ty.isRuntimeFloat()) {
7228 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7051 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7229 return self.buildFloatOp(.floor, inst_ty, 1, .{result});7052 return self.buildFloatOp(.floor, inst_ty, 1, .{result});
7230 }7053 }
7231 if (scalar_ty.isSignedInt()) {7054 if (scalar_ty.isSignedInt(mod)) {
7232 const target = self.dg.module.getTarget();
7233 const inst_llvm_ty = try self.dg.lowerType(inst_ty);7055 const inst_llvm_ty = try self.dg.lowerType(inst_ty);
7234 const scalar_bit_size_minus_one = scalar_ty.bitSize(target) - 1;7056 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
7235 const bit_size_minus_one = if (inst_ty.zigTypeTag() == .Vector) const_vector: {7057 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
7236 const vec_len = inst_ty.vectorLen();7058 const vec_len = inst_ty.vectorLen(mod);
7237 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);7059 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
72387060
7239 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);7061 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
...@@ -7258,40 +7080,43 @@ pub const FuncGen = struct {...@@ -7258,40 +7080,43 @@ pub const FuncGen = struct {
7258 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7080 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7259 self.builder.setFastMath(want_fast_math);7081 self.builder.setFastMath(want_fast_math);
72607082
7083 const mod = self.dg.module;
7261 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7084 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7262 const lhs = try self.resolveInst(bin_op.lhs);7085 const lhs = try self.resolveInst(bin_op.lhs);
7263 const rhs = try self.resolveInst(bin_op.rhs);7086 const rhs = try self.resolveInst(bin_op.rhs);
7264 const inst_ty = self.air.typeOfIndex(inst);7087 const inst_ty = self.typeOfIndex(inst);
7265 const scalar_ty = inst_ty.scalarType();7088 const scalar_ty = inst_ty.scalarType(mod);
72667089
7267 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7090 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, "");
7269 return self.builder.buildExactUDiv(lhs, rhs, "");7092 return self.builder.buildExactUDiv(lhs, rhs, "");
7270 }7093 }
72717094
7272 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7095 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7273 self.builder.setFastMath(want_fast_math);7096 self.builder.setFastMath(want_fast_math);
72747097
7098 const mod = self.dg.module;
7275 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7099 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7276 const lhs = try self.resolveInst(bin_op.lhs);7100 const lhs = try self.resolveInst(bin_op.lhs);
7277 const rhs = try self.resolveInst(bin_op.rhs);7101 const rhs = try self.resolveInst(bin_op.rhs);
7278 const inst_ty = self.air.typeOfIndex(inst);7102 const inst_ty = self.typeOfIndex(inst);
7279 const scalar_ty = inst_ty.scalarType();7103 const scalar_ty = inst_ty.scalarType(mod);
72807104
7281 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });7105 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, "");
7283 return self.builder.buildURem(lhs, rhs, "");7107 return self.builder.buildURem(lhs, rhs, "");
7284 }7108 }
72857109
7286 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7110 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7287 self.builder.setFastMath(want_fast_math);7111 self.builder.setFastMath(want_fast_math);
72887112
7113 const mod = self.dg.module;
7289 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7114 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7290 const lhs = try self.resolveInst(bin_op.lhs);7115 const lhs = try self.resolveInst(bin_op.lhs);
7291 const rhs = try self.resolveInst(bin_op.rhs);7116 const rhs = try self.resolveInst(bin_op.rhs);
7292 const inst_ty = self.air.typeOfIndex(inst);7117 const inst_ty = self.typeOfIndex(inst);
7293 const inst_llvm_ty = try self.dg.lowerType(inst_ty);7118 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
7296 if (scalar_ty.isRuntimeFloat()) {7121 if (scalar_ty.isRuntimeFloat()) {
7297 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });7122 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
...@@ -7301,11 +7126,10 @@ pub const FuncGen = struct {...@@ -7301,11 +7126,10 @@ pub const FuncGen = struct {
7301 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });7126 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });
7302 return self.builder.buildSelect(ltz, c, a, "");7127 return self.builder.buildSelect(ltz, c, a, "");
7303 }7128 }
7304 if (scalar_ty.isSignedInt()) {7129 if (scalar_ty.isSignedInt(mod)) {
7305 const target = self.dg.module.getTarget();7130 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
7306 const scalar_bit_size_minus_one = scalar_ty.bitSize(target) - 1;7131 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
7307 const bit_size_minus_one = if (inst_ty.zigTypeTag() == .Vector) const_vector: {7132 const vec_len = inst_ty.vectorLen(mod);
7308 const vec_len = inst_ty.vectorLen();
7309 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);7133 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
73107134
7311 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);7135 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
...@@ -7328,13 +7152,14 @@ pub const FuncGen = struct {...@@ -7328,13 +7152,14 @@ pub const FuncGen = struct {
7328 }7152 }
73297153
7330 fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7154 fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7155 const mod = self.dg.module;
7331 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7156 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7332 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;7157 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
7333 const ptr = try self.resolveInst(bin_op.lhs);7158 const ptr = try self.resolveInst(bin_op.lhs);
7334 const offset = try self.resolveInst(bin_op.rhs);7159 const offset = try self.resolveInst(bin_op.rhs);
7335 const ptr_ty = self.air.typeOf(bin_op.lhs);7160 const ptr_ty = self.typeOf(bin_op.lhs);
7336 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType());7161 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType(mod));
7337 switch (ptr_ty.ptrSize()) {7162 switch (ptr_ty.ptrSize(mod)) {
7338 .One => {7163 .One => {
7339 // It's a pointer to an array, so according to LLVM we need an extra GEP index.7164 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
7340 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), offset };7165 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), offset };
...@@ -7353,14 +7178,15 @@ pub const FuncGen = struct {...@@ -7353,14 +7178,15 @@ pub const FuncGen = struct {
7353 }7178 }
73547179
7355 fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7180 fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7181 const mod = self.dg.module;
7356 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7182 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7357 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;7183 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
7358 const ptr = try self.resolveInst(bin_op.lhs);7184 const ptr = try self.resolveInst(bin_op.lhs);
7359 const offset = try self.resolveInst(bin_op.rhs);7185 const offset = try self.resolveInst(bin_op.rhs);
7360 const negative_offset = self.builder.buildNeg(offset, "");7186 const negative_offset = self.builder.buildNeg(offset, "");
7361 const ptr_ty = self.air.typeOf(bin_op.lhs);7187 const ptr_ty = self.typeOf(bin_op.lhs);
7362 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType());7188 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType(mod));
7363 switch (ptr_ty.ptrSize()) {7189 switch (ptr_ty.ptrSize(mod)) {
7364 .One => {7190 .One => {
7365 // It's a pointer to an array, so according to LLVM we need an extra GEP index.7191 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
7366 const indices: [2]*llvm.Value = .{7192 const indices: [2]*llvm.Value = .{
...@@ -7386,36 +7212,33 @@ pub const FuncGen = struct {...@@ -7386,36 +7212,33 @@ pub const FuncGen = struct {
7386 signed_intrinsic: []const u8,7212 signed_intrinsic: []const u8,
7387 unsigned_intrinsic: []const u8,7213 unsigned_intrinsic: []const u8,
7388 ) !?*llvm.Value {7214 ) !?*llvm.Value {
7215 const mod = self.dg.module;
7389 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7216 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7390 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;7217 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
73917218
7392 const lhs = try self.resolveInst(extra.lhs);7219 const lhs = try self.resolveInst(extra.lhs);
7393 const rhs = try self.resolveInst(extra.rhs);7220 const rhs = try self.resolveInst(extra.rhs);
73947221
7395 const lhs_ty = self.air.typeOf(extra.lhs);7222 const lhs_ty = self.typeOf(extra.lhs);
7396 const scalar_ty = lhs_ty.scalarType();7223 const scalar_ty = lhs_ty.scalarType(mod);
7397 const dest_ty = self.air.typeOfIndex(inst);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
7401 const llvm_lhs_ty = try self.dg.lowerType(lhs_ty);7228 const llvm_lhs_ty = try self.dg.lowerType(lhs_ty);
7402 const llvm_dest_ty = try self.dg.lowerType(dest_ty);7229 const llvm_dest_ty = try self.dg.lowerType(dest_ty);
74037230
7404 const tg = self.dg.module.getTarget();
7405
7406 const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty});7231 const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty});
7407 const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, "");7232 const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, "");
74087233
7409 const result = self.builder.buildExtractValue(result_struct, 0, "");7234 const result = self.builder.buildExtractValue(result_struct, 0, "");
7410 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");7235 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");
74117236
7412 var ty_buf: Type.Payload.Pointer = undefined;7237 const result_index = llvmField(dest_ty, 0, mod).?.index;
7413 const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?;7238 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
7414 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
74157239
7416 if (isByRef(dest_ty)) {7240 if (isByRef(dest_ty, mod)) {
7417 const target = self.dg.module.getTarget();7241 const result_alignment = dest_ty.abiAlignment(mod);
7418 const result_alignment = dest_ty.abiAlignment(target);
7419 const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment);7242 const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment);
7420 {7243 {
7421 const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, "");7244 const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, "");
...@@ -7486,8 +7309,9 @@ pub const FuncGen = struct {...@@ -7486,8 +7309,9 @@ pub const FuncGen = struct {
7486 ty: Type,7309 ty: Type,
7487 params: [2]*llvm.Value,7310 params: [2]*llvm.Value,
7488 ) !*llvm.Value {7311 ) !*llvm.Value {
7312 const mod = self.dg.module;
7489 const target = self.dg.module.getTarget();7313 const target = self.dg.module.getTarget();
7490 const scalar_ty = ty.scalarType();7314 const scalar_ty = ty.scalarType(mod);
7491 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);7315 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
74927316
7493 if (intrinsicsAllowed(scalar_ty, target)) {7317 if (intrinsicsAllowed(scalar_ty, target)) {
...@@ -7531,8 +7355,8 @@ pub const FuncGen = struct {...@@ -7531,8 +7355,8 @@ pub const FuncGen = struct {
7531 .gte => .SGE,7355 .gte => .SGE,
7532 };7356 };
75337357
7534 if (ty.zigTypeTag() == .Vector) {7358 if (ty.zigTypeTag(mod) == .Vector) {
7535 const vec_len = ty.vectorLen();7359 const vec_len = ty.vectorLen(mod);
7536 const vector_result_ty = llvm_i32.vectorType(vec_len);7360 const vector_result_ty = llvm_i32.vectorType(vec_len);
75377361
7538 var result = vector_result_ty.getUndef();7362 var result = vector_result_ty.getUndef();
...@@ -7587,8 +7411,9 @@ pub const FuncGen = struct {...@@ -7587,8 +7411,9 @@ pub const FuncGen = struct {
7587 comptime params_len: usize,7411 comptime params_len: usize,
7588 params: [params_len]*llvm.Value,7412 params: [params_len]*llvm.Value,
7589 ) !*llvm.Value {7413 ) !*llvm.Value {
7590 const target = self.dg.module.getTarget();7414 const mod = self.dg.module;
7591 const scalar_ty = ty.scalarType();7415 const target = mod.getTarget();
7416 const scalar_ty = ty.scalarType(mod);
7592 const llvm_ty = try self.dg.lowerType(ty);7417 const llvm_ty = try self.dg.lowerType(ty);
7593 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);7418 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
75947419
...@@ -7615,9 +7440,9 @@ pub const FuncGen = struct {...@@ -7615,9 +7440,9 @@ pub const FuncGen = struct {
7615 const one = int_llvm_ty.constInt(1, .False);7440 const one = int_llvm_ty.constInt(1, .False);
7616 const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False);7441 const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False);
7617 const sign_mask = one.constShl(shift_amt);7442 const sign_mask = one.constShl(shift_amt);
7618 const result = if (ty.zigTypeTag() == .Vector) blk: {7443 const result = if (ty.zigTypeTag(mod) == .Vector) blk: {
7619 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(), sign_mask, "");7444 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(mod), sign_mask, "");
7620 const cast_ty = int_llvm_ty.vectorType(ty.vectorLen());7445 const cast_ty = int_llvm_ty.vectorType(ty.vectorLen(mod));
7621 const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, "");7446 const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, "");
7622 break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, "");7447 break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, "");
7623 } else blk: {7448 } else blk: {
...@@ -7662,9 +7487,9 @@ pub const FuncGen = struct {...@@ -7662,9 +7487,9 @@ pub const FuncGen = struct {
7662 .libc => |fn_name| b: {7487 .libc => |fn_name| b: {
7663 const param_types = [3]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty, scalar_llvm_ty };7488 const param_types = [3]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty, scalar_llvm_ty };
7664 const libc_fn = self.getLibcFunction(fn_name, param_types[0..params.len], scalar_llvm_ty);7489 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) {
7666 const result = llvm_ty.getUndef();7491 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));
7668 }7493 }
76697494
7670 break :b libc_fn;7495 break :b libc_fn;
...@@ -7681,47 +7506,44 @@ pub const FuncGen = struct {...@@ -7681,47 +7506,44 @@ pub const FuncGen = struct {
7681 const mulend2 = try self.resolveInst(extra.rhs);7506 const mulend2 = try self.resolveInst(extra.rhs);
7682 const addend = try self.resolveInst(pl_op.operand);7507 const addend = try self.resolveInst(pl_op.operand);
76837508
7684 const ty = self.air.typeOfIndex(inst);7509 const ty = self.typeOfIndex(inst);
7685 return self.buildFloatOp(.fma, ty, 3, .{ mulend1, mulend2, addend });7510 return self.buildFloatOp(.fma, ty, 3, .{ mulend1, mulend2, addend });
7686 }7511 }
76877512
7688 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7513 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7514 const mod = self.dg.module;
7689 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7515 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7690 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;7516 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
76917517
7692 const lhs = try self.resolveInst(extra.lhs);7518 const lhs = try self.resolveInst(extra.lhs);
7693 const rhs = try self.resolveInst(extra.rhs);7519 const rhs = try self.resolveInst(extra.rhs);
76947520
7695 const lhs_ty = self.air.typeOf(extra.lhs);7521 const lhs_ty = self.typeOf(extra.lhs);
7696 const rhs_ty = self.air.typeOf(extra.rhs);7522 const rhs_ty = self.typeOf(extra.rhs);
7697 const lhs_scalar_ty = lhs_ty.scalarType();7523 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7698 const rhs_scalar_ty = rhs_ty.scalarType();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);
7701 const llvm_dest_ty = try self.dg.lowerType(dest_ty);7527 const llvm_dest_ty = try self.dg.lowerType(dest_ty);
77027528
7703 const tg = self.dg.module.getTarget();7529 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
7704
7705 const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
7706 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")7530 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")
7707 else7531 else
7708 rhs;7532 rhs;
77097533
7710 const result = self.builder.buildShl(lhs, casted_rhs, "");7534 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))
7712 self.builder.buildAShr(result, casted_rhs, "")7536 self.builder.buildAShr(result, casted_rhs, "")
7713 else7537 else
7714 self.builder.buildLShr(result, casted_rhs, "");7538 self.builder.buildLShr(result, casted_rhs, "");
77157539
7716 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");7540 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");
77177541
7718 var ty_buf: Type.Payload.Pointer = undefined;7542 const result_index = llvmField(dest_ty, 0, mod).?.index;
7719 const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?;7543 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
7720 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
77217544
7722 if (isByRef(dest_ty)) {7545 if (isByRef(dest_ty, mod)) {
7723 const target = self.dg.module.getTarget();7546 const result_alignment = dest_ty.abiAlignment(mod);
7724 const result_alignment = dest_ty.abiAlignment(target);
7725 const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment);7547 const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment);
7726 {7548 {
7727 const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, "");7549 const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, "");
...@@ -7763,40 +7585,38 @@ pub const FuncGen = struct {...@@ -7763,40 +7585,38 @@ pub const FuncGen = struct {
7763 }7585 }
77647586
7765 fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7587 fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7588 const mod = self.dg.module;
7766 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7589 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
77677590
7768 const lhs = try self.resolveInst(bin_op.lhs);7591 const lhs = try self.resolveInst(bin_op.lhs);
7769 const rhs = try self.resolveInst(bin_op.rhs);7592 const rhs = try self.resolveInst(bin_op.rhs);
77707593
7771 const lhs_ty = self.air.typeOf(bin_op.lhs);7594 const lhs_ty = self.typeOf(bin_op.lhs);
7772 const rhs_ty = self.air.typeOf(bin_op.rhs);7595 const rhs_ty = self.typeOf(bin_op.rhs);
7773 const lhs_scalar_ty = lhs_ty.scalarType();7596 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7774 const rhs_scalar_ty = rhs_ty.scalarType();7597 const rhs_scalar_ty = rhs_ty.scalarType(mod);
7775
7776 const tg = self.dg.module.getTarget();
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))
7779 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")7600 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")
7780 else7601 else
7781 rhs;7602 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, "");
7783 return self.builder.buildNUWShl(lhs, casted_rhs, "");7604 return self.builder.buildNUWShl(lhs, casted_rhs, "");
7784 }7605 }
77857606
7786 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7607 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7608 const mod = self.dg.module;
7787 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7609 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
77887610
7789 const lhs = try self.resolveInst(bin_op.lhs);7611 const lhs = try self.resolveInst(bin_op.lhs);
7790 const rhs = try self.resolveInst(bin_op.rhs);7612 const rhs = try self.resolveInst(bin_op.rhs);
77917613
7792 const lhs_type = self.air.typeOf(bin_op.lhs);7614 const lhs_type = self.typeOf(bin_op.lhs);
7793 const rhs_type = self.air.typeOf(bin_op.rhs);7615 const rhs_type = self.typeOf(bin_op.rhs);
7794 const lhs_scalar_ty = lhs_type.scalarType();7616 const lhs_scalar_ty = lhs_type.scalarType(mod);
7795 const rhs_scalar_ty = rhs_type.scalarType();7617 const rhs_scalar_ty = rhs_type.scalarType(mod);
7796
7797 const tg = self.dg.module.getTarget();
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))
7800 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_type), "")7620 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_type), "")
7801 else7621 else
7802 rhs;7622 rhs;
...@@ -7804,24 +7624,24 @@ pub const FuncGen = struct {...@@ -7804,24 +7624,24 @@ pub const FuncGen = struct {
7804 }7624 }
78057625
7806 fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7626 fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7627 const mod = self.dg.module;
7807 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7628 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78087629
7809 const lhs = try self.resolveInst(bin_op.lhs);7630 const lhs = try self.resolveInst(bin_op.lhs);
7810 const rhs = try self.resolveInst(bin_op.rhs);7631 const rhs = try self.resolveInst(bin_op.rhs);
78117632
7812 const lhs_ty = self.air.typeOf(bin_op.lhs);7633 const lhs_ty = self.typeOf(bin_op.lhs);
7813 const rhs_ty = self.air.typeOf(bin_op.rhs);7634 const rhs_ty = self.typeOf(bin_op.rhs);
7814 const lhs_scalar_ty = lhs_ty.scalarType();7635 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7815 const rhs_scalar_ty = rhs_ty.scalarType();7636 const rhs_scalar_ty = rhs_ty.scalarType(mod);
7816 const tg = self.dg.module.getTarget();7637 const lhs_bits = lhs_scalar_ty.bitSize(mod);
7817 const lhs_bits = lhs_scalar_ty.bitSize(tg);
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)
7820 self.builder.buildZExt(rhs, lhs.typeOf(), "")7640 self.builder.buildZExt(rhs, lhs.typeOf(), "")
7821 else7641 else
7822 rhs;7642 rhs;
78237643
7824 const result = if (lhs_scalar_ty.isSignedInt())7644 const result = if (lhs_scalar_ty.isSignedInt(mod))
7825 self.builder.buildSShlSat(lhs, casted_rhs, "")7645 self.builder.buildSShlSat(lhs, casted_rhs, "")
7826 else7646 else
7827 self.builder.buildUShlSat(lhs, casted_rhs, "");7647 self.builder.buildUShlSat(lhs, casted_rhs, "");
...@@ -7834,8 +7654,8 @@ pub const FuncGen = struct {...@@ -7834,8 +7654,8 @@ pub const FuncGen = struct {
7834 const lhs_scalar_llvm_ty = try self.dg.lowerType(lhs_scalar_ty);7654 const lhs_scalar_llvm_ty = try self.dg.lowerType(lhs_scalar_ty);
7835 const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False);7655 const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False);
7836 const lhs_max = lhs_scalar_llvm_ty.constAllOnes();7656 const lhs_max = lhs_scalar_llvm_ty.constAllOnes();
7837 if (rhs_ty.zigTypeTag() == .Vector) {7657 if (rhs_ty.zigTypeTag(mod) == .Vector) {
7838 const vec_len = rhs_ty.vectorLen();7658 const vec_len = rhs_ty.vectorLen(mod);
7839 const bits_vec = self.builder.buildVectorSplat(vec_len, bits, "");7659 const bits_vec = self.builder.buildVectorSplat(vec_len, bits, "");
7840 const lhs_max_vec = self.builder.buildVectorSplat(vec_len, lhs_max, "");7660 const lhs_max_vec = self.builder.buildVectorSplat(vec_len, lhs_max, "");
7841 const in_range = self.builder.buildICmp(.ULT, rhs, bits_vec, "");7661 const in_range = self.builder.buildICmp(.ULT, rhs, bits_vec, "");
...@@ -7847,23 +7667,22 @@ pub const FuncGen = struct {...@@ -7847,23 +7667,22 @@ pub const FuncGen = struct {
7847 }7667 }
78487668
7849 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value {7669 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value {
7670 const mod = self.dg.module;
7850 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7671 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78517672
7852 const lhs = try self.resolveInst(bin_op.lhs);7673 const lhs = try self.resolveInst(bin_op.lhs);
7853 const rhs = try self.resolveInst(bin_op.rhs);7674 const rhs = try self.resolveInst(bin_op.rhs);
78547675
7855 const lhs_ty = self.air.typeOf(bin_op.lhs);7676 const lhs_ty = self.typeOf(bin_op.lhs);
7856 const rhs_ty = self.air.typeOf(bin_op.rhs);7677 const rhs_ty = self.typeOf(bin_op.rhs);
7857 const lhs_scalar_ty = lhs_ty.scalarType();7678 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7858 const rhs_scalar_ty = rhs_ty.scalarType();7679 const rhs_scalar_ty = rhs_ty.scalarType(mod);
78597680
7860 const tg = self.dg.module.getTarget();7681 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
7861
7862 const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
7863 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")7682 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")
7864 else7683 else
7865 rhs;7684 rhs;
7866 const is_signed_int = lhs_scalar_ty.isSignedInt();7685 const is_signed_int = lhs_scalar_ty.isSignedInt(mod);
78677686
7868 if (is_exact) {7687 if (is_exact) {
7869 if (is_signed_int) {7688 if (is_signed_int) {
...@@ -7881,14 +7700,14 @@ pub const FuncGen = struct {...@@ -7881,14 +7700,14 @@ pub const FuncGen = struct {
7881 }7700 }
78827701
7883 fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7702 fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7884 const target = self.dg.module.getTarget();7703 const mod = self.dg.module;
7885 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7704 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7886 const dest_ty = self.air.typeOfIndex(inst);7705 const dest_ty = self.typeOfIndex(inst);
7887 const dest_info = dest_ty.intInfo(target);7706 const dest_info = dest_ty.intInfo(mod);
7888 const dest_llvm_ty = try self.dg.lowerType(dest_ty);7707 const dest_llvm_ty = try self.dg.lowerType(dest_ty);
7889 const operand = try self.resolveInst(ty_op.operand);7708 const operand = try self.resolveInst(ty_op.operand);
7890 const operand_ty = self.air.typeOf(ty_op.operand);7709 const operand_ty = self.typeOf(ty_op.operand);
7891 const operand_info = operand_ty.intInfo(target);7710 const operand_info = operand_ty.intInfo(mod);
78927711
7893 if (operand_info.bits < dest_info.bits) {7712 if (operand_info.bits < dest_info.bits) {
7894 switch (operand_info.signedness) {7713 switch (operand_info.signedness) {
...@@ -7905,16 +7724,17 @@ pub const FuncGen = struct {...@@ -7905,16 +7724,17 @@ pub const FuncGen = struct {
7905 fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7724 fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7906 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7725 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7907 const operand = try self.resolveInst(ty_op.operand);7726 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));
7909 return self.builder.buildTrunc(operand, dest_llvm_ty, "");7728 return self.builder.buildTrunc(operand, dest_llvm_ty, "");
7910 }7729 }
79117730
7912 fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7731 fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7732 const mod = self.dg.module;
7913 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7733 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7914 const operand = try self.resolveInst(ty_op.operand);7734 const operand = try self.resolveInst(ty_op.operand);
7915 const operand_ty = self.air.typeOf(ty_op.operand);7735 const operand_ty = self.typeOf(ty_op.operand);
7916 const dest_ty = self.air.typeOfIndex(inst);7736 const dest_ty = self.typeOfIndex(inst);
7917 const target = self.dg.module.getTarget();7737 const target = mod.getTarget();
7918 const dest_bits = dest_ty.floatBits(target);7738 const dest_bits = dest_ty.floatBits(target);
7919 const src_bits = operand_ty.floatBits(target);7739 const src_bits = operand_ty.floatBits(target);
79207740
...@@ -7939,11 +7759,12 @@ pub const FuncGen = struct {...@@ -7939,11 +7759,12 @@ pub const FuncGen = struct {
7939 }7759 }
79407760
7941 fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7761 fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7762 const mod = self.dg.module;
7942 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7763 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7943 const operand = try self.resolveInst(ty_op.operand);7764 const operand = try self.resolveInst(ty_op.operand);
7944 const operand_ty = self.air.typeOf(ty_op.operand);7765 const operand_ty = self.typeOf(ty_op.operand);
7945 const dest_ty = self.air.typeOfIndex(inst);7766 const dest_ty = self.typeOfIndex(inst);
7946 const target = self.dg.module.getTarget();7767 const target = mod.getTarget();
7947 const dest_bits = dest_ty.floatBits(target);7768 const dest_bits = dest_ty.floatBits(target);
7948 const src_bits = operand_ty.floatBits(target);7769 const src_bits = operand_ty.floatBits(target);
79497770
...@@ -7970,25 +7791,25 @@ pub const FuncGen = struct {...@@ -7970,25 +7791,25 @@ pub const FuncGen = struct {
7970 fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7791 fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7971 const un_op = self.air.instructions.items(.data)[inst].un_op;7792 const un_op = self.air.instructions.items(.data)[inst].un_op;
7972 const operand = try self.resolveInst(un_op);7793 const operand = try self.resolveInst(un_op);
7973 const ptr_ty = self.air.typeOf(un_op);7794 const ptr_ty = self.typeOf(un_op);
7974 const operand_ptr = self.sliceOrArrayPtr(operand, ptr_ty);7795 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));
7976 return self.builder.buildPtrToInt(operand_ptr, dest_llvm_ty, "");7797 return self.builder.buildPtrToInt(operand_ptr, dest_llvm_ty, "");
7977 }7798 }
79787799
7979 fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !*llvm.Value {7800 fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !*llvm.Value {
7980 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7801 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7981 const operand_ty = self.air.typeOf(ty_op.operand);7802 const operand_ty = self.typeOf(ty_op.operand);
7982 const inst_ty = self.air.typeOfIndex(inst);7803 const inst_ty = self.typeOfIndex(inst);
7983 const operand = try self.resolveInst(ty_op.operand);7804 const operand = try self.resolveInst(ty_op.operand);
7984 return self.bitCast(operand, operand_ty, inst_ty);7805 return self.bitCast(operand, operand_ty, inst_ty);
7985 }7806 }
79867807
7987 fn bitCast(self: *FuncGen, operand: *llvm.Value, operand_ty: Type, inst_ty: Type) !*llvm.Value {7808 fn bitCast(self: *FuncGen, operand: *llvm.Value, operand_ty: Type, inst_ty: Type) !*llvm.Value {
7988 const operand_is_ref = isByRef(operand_ty);7809 const mod = self.dg.module;
7989 const result_is_ref = isByRef(inst_ty);7810 const operand_is_ref = isByRef(operand_ty, mod);
7811 const result_is_ref = isByRef(inst_ty, mod);
7990 const llvm_dest_ty = try self.dg.lowerType(inst_ty);7812 const llvm_dest_ty = try self.dg.lowerType(inst_ty);
7991 const target = self.dg.module.getTarget();
79927813
7993 if (operand_is_ref and result_is_ref) {7814 if (operand_is_ref and result_is_ref) {
7994 // They are both pointers, so just return the same opaque pointer :)7815 // They are both pointers, so just return the same opaque pointer :)
...@@ -8001,27 +7822,27 @@ pub const FuncGen = struct {...@@ -8001,27 +7822,27 @@ pub const FuncGen = struct {
8001 return self.builder.buildZExtOrBitCast(operand, llvm_dest_ty, "");7822 return self.builder.buildZExtOrBitCast(operand, llvm_dest_ty, "");
8002 }7823 }
80037824
8004 if (operand_ty.zigTypeTag() == .Int and inst_ty.isPtrAtRuntime()) {7825 if (operand_ty.zigTypeTag(mod) == .Int and inst_ty.isPtrAtRuntime(mod)) {
8005 return self.builder.buildIntToPtr(operand, llvm_dest_ty, "");7826 return self.builder.buildIntToPtr(operand, llvm_dest_ty, "");
8006 }7827 }
80077828
8008 if (operand_ty.zigTypeTag() == .Vector and inst_ty.zigTypeTag() == .Array) {7829 if (operand_ty.zigTypeTag(mod) == .Vector and inst_ty.zigTypeTag(mod) == .Array) {
8009 const elem_ty = operand_ty.childType();7830 const elem_ty = operand_ty.childType(mod);
8010 if (!result_is_ref) {7831 if (!result_is_ref) {
8011 return self.dg.todo("implement bitcast vector to non-ref array", .{});7832 return self.dg.todo("implement bitcast vector to non-ref array", .{});
8012 }7833 }
8013 const array_ptr = self.buildAlloca(llvm_dest_ty, null);7834 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;
8015 if (bitcast_ok) {7836 if (bitcast_ok) {
8016 const llvm_store = self.builder.buildStore(operand, array_ptr);7837 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));
8018 } else {7839 } else {
8019 // If the ABI size of the element type is not evenly divisible by size in bits;7840 // If the ABI size of the element type is not evenly divisible by size in bits;
8020 // a simple bitcast will not work, and we fall back to extractelement.7841 // a simple bitcast will not work, and we fall back to extractelement.
8021 const llvm_usize = try self.dg.lowerType(Type.usize);7842 const llvm_usize = try self.dg.lowerType(Type.usize);
8022 const llvm_u32 = self.context.intType(32);7843 const llvm_u32 = self.context.intType(32);
8023 const zero = llvm_usize.constNull();7844 const zero = llvm_usize.constNull();
8024 const vector_len = operand_ty.arrayLen();7845 const vector_len = operand_ty.arrayLen(mod);
8025 var i: u64 = 0;7846 var i: u64 = 0;
8026 while (i < vector_len) : (i += 1) {7847 while (i < vector_len) : (i += 1) {
8027 const index_usize = llvm_usize.constInt(i, .False);7848 const index_usize = llvm_usize.constInt(i, .False);
...@@ -8033,19 +7854,19 @@ pub const FuncGen = struct {...@@ -8033,19 +7854,19 @@ pub const FuncGen = struct {
8033 }7854 }
8034 }7855 }
8035 return array_ptr;7856 return array_ptr;
8036 } else if (operand_ty.zigTypeTag() == .Array and inst_ty.zigTypeTag() == .Vector) {7857 } else if (operand_ty.zigTypeTag(mod) == .Array and inst_ty.zigTypeTag(mod) == .Vector) {
8037 const elem_ty = operand_ty.childType();7858 const elem_ty = operand_ty.childType(mod);
8038 const llvm_vector_ty = try self.dg.lowerType(inst_ty);7859 const llvm_vector_ty = try self.dg.lowerType(inst_ty);
8039 if (!operand_is_ref) {7860 if (!operand_is_ref) {
8040 return self.dg.todo("implement bitcast non-ref array to vector", .{});7861 return self.dg.todo("implement bitcast non-ref array to vector", .{});
8041 }7862 }
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;
8044 if (bitcast_ok) {7865 if (bitcast_ok) {
8045 const vector = self.builder.buildLoad(llvm_vector_ty, operand, "");7866 const vector = self.builder.buildLoad(llvm_vector_ty, operand, "");
8046 // The array is aligned to the element's alignment, while the vector might have a completely7867 // The array is aligned to the element's alignment, while the vector might have a completely
8047 // different alignment. This means we need to enforce the alignment of this load.7868 // 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));
8049 return vector;7870 return vector;
8050 } else {7871 } else {
8051 // If the ABI size of the element type is not evenly divisible by size in bits;7872 // If the ABI size of the element type is not evenly divisible by size in bits;
...@@ -8055,7 +7876,7 @@ pub const FuncGen = struct {...@@ -8055,7 +7876,7 @@ pub const FuncGen = struct {
8055 const llvm_usize = try self.dg.lowerType(Type.usize);7876 const llvm_usize = try self.dg.lowerType(Type.usize);
8056 const llvm_u32 = self.context.intType(32);7877 const llvm_u32 = self.context.intType(32);
8057 const zero = llvm_usize.constNull();7878 const zero = llvm_usize.constNull();
8058 const vector_len = operand_ty.arrayLen();7879 const vector_len = operand_ty.arrayLen(mod);
8059 var vector = llvm_vector_ty.getUndef();7880 var vector = llvm_vector_ty.getUndef();
8060 var i: u64 = 0;7881 var i: u64 = 0;
8061 while (i < vector_len) : (i += 1) {7882 while (i < vector_len) : (i += 1) {
...@@ -8073,12 +7894,12 @@ pub const FuncGen = struct {...@@ -8073,12 +7894,12 @@ pub const FuncGen = struct {
80737894
8074 if (operand_is_ref) {7895 if (operand_is_ref) {
8075 const load_inst = self.builder.buildLoad(llvm_dest_ty, operand, "");7896 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));
8077 return load_inst;7898 return load_inst;
8078 }7899 }
80797900
8080 if (result_is_ref) {7901 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));
8082 const result_ptr = self.buildAlloca(llvm_dest_ty, alignment);7903 const result_ptr = self.buildAlloca(llvm_dest_ty, alignment);
8083 const store_inst = self.builder.buildStore(operand, result_ptr);7904 const store_inst = self.builder.buildStore(operand, result_ptr);
8084 store_inst.setAlignment(alignment);7905 store_inst.setAlignment(alignment);
...@@ -8089,7 +7910,7 @@ pub const FuncGen = struct {...@@ -8089,7 +7910,7 @@ pub const FuncGen = struct {
8089 // Both our operand and our result are values, not pointers,7910 // Both our operand and our result are values, not pointers,
8090 // but LLVM won't let us bitcast struct values.7911 // but LLVM won't let us bitcast struct values.
8091 // Therefore, we store operand to alloca, then load for result.7912 // 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));
8093 const result_ptr = self.buildAlloca(llvm_dest_ty, alignment);7914 const result_ptr = self.buildAlloca(llvm_dest_ty, alignment);
8094 const store_inst = self.builder.buildStore(operand, result_ptr);7915 const store_inst = self.builder.buildStore(operand, result_ptr);
8095 store_inst.setAlignment(alignment);7916 store_inst.setAlignment(alignment);
...@@ -8108,22 +7929,23 @@ pub const FuncGen = struct {...@@ -8108,22 +7929,23 @@ pub const FuncGen = struct {
8108 }7929 }
81097930
8110 fn airArg(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7931 fn airArg(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7932 const mod = self.dg.module;
8111 const arg_val = self.args[self.arg_index];7933 const arg_val = self.args[self.arg_index];
8112 self.arg_index += 1;7934 self.arg_index += 1;
81137935
8114 const inst_ty = self.air.typeOfIndex(inst);7936 const inst_ty = self.typeOfIndex(inst);
8115 if (self.dg.object.di_builder) |dib| {7937 if (self.dg.object.di_builder) |dib| {
8116 if (needDbgVarWorkaround(self.dg)) {7938 if (needDbgVarWorkaround(self.dg)) {
8117 return arg_val;7939 return arg_val;
8118 }7940 }
81197941
8120 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;7942 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
8121 const func = self.dg.decl.getFunction().?;7943 const func = self.dg.decl.getOwnedFunction(mod).?;
8122 const lbrace_line = self.dg.module.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;7944 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8123 const lbrace_col = func.lbrace_column + 1;7945 const lbrace_col = func.lbrace_column + 1;
8124 const di_local_var = dib.createParameterVariable(7946 const di_local_var = dib.createParameterVariable(
8125 self.di_scope.?,7947 self.di_scope.?,
8126 func.getParamName(self.dg.module, src_index).ptr, // TODO test 0 bit args7948 func.getParamName(mod, src_index).ptr, // TODO test 0 bit args
8127 self.di_file.?,7949 self.di_file.?,
8128 lbrace_line,7950 lbrace_line,
8129 try self.dg.object.lowerDebugType(inst_ty, .full),7951 try self.dg.object.lowerDebugType(inst_ty, .full),
...@@ -8134,10 +7956,10 @@ pub const FuncGen = struct {...@@ -8134,10 +7956,10 @@ pub const FuncGen = struct {
81347956
8135 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);7957 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);
8136 const insert_block = self.builder.getInsertBlock();7958 const insert_block = self.builder.getInsertBlock();
8137 if (isByRef(inst_ty)) {7959 if (isByRef(inst_ty, mod)) {
8138 _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block);7960 _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block);
8139 } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) {7961 } 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);
8141 const alloca = self.buildAlloca(arg_val.typeOf(), alignment);7963 const alloca = self.buildAlloca(arg_val.typeOf(), alignment);
8142 const store_inst = self.builder.buildStore(arg_val, alloca);7964 const store_inst = self.builder.buildStore(arg_val, alloca);
8143 store_inst.setAlignment(alignment);7965 store_inst.setAlignment(alignment);
...@@ -8151,24 +7973,24 @@ pub const FuncGen = struct {...@@ -8151,24 +7973,24 @@ pub const FuncGen = struct {
8151 }7973 }
81527974
8153 fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7975 fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8154 const ptr_ty = self.air.typeOfIndex(inst);7976 const mod = self.dg.module;
8155 const pointee_type = ptr_ty.childType();7977 const ptr_ty = self.typeOfIndex(inst);
8156 if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);7978 const pointee_type = ptr_ty.childType(mod);
7979 if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty);
81577980
8158 const pointee_llvm_ty = try self.dg.lowerType(pointee_type);7981 const pointee_llvm_ty = try self.dg.lowerType(pointee_type);
8159 const target = self.dg.module.getTarget();7982 const alignment = ptr_ty.ptrAlignment(mod);
8160 const alignment = ptr_ty.ptrAlignment(target);
8161 return self.buildAlloca(pointee_llvm_ty, alignment);7983 return self.buildAlloca(pointee_llvm_ty, alignment);
8162 }7984 }
81637985
8164 fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7986 fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8165 const ptr_ty = self.air.typeOfIndex(inst);7987 const mod = self.dg.module;
8166 const ret_ty = ptr_ty.childType();7988 const ptr_ty = self.typeOfIndex(inst);
8167 if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);7989 const ret_ty = ptr_ty.childType(mod);
7990 if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty);
8168 if (self.ret_ptr) |ret_ptr| return ret_ptr;7991 if (self.ret_ptr) |ret_ptr| return ret_ptr;
8169 const ret_llvm_ty = try self.dg.lowerType(ret_ty);7992 const ret_llvm_ty = try self.dg.lowerType(ret_ty);
8170 const target = self.dg.module.getTarget();7993 return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(mod));
8171 return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(target));
8172 }7994 }
81737995
8174 /// Use this instead of builder.buildAlloca, because this function makes sure to7996 /// Use this instead of builder.buildAlloca, because this function makes sure to
...@@ -8178,12 +8000,13 @@ pub const FuncGen = struct {...@@ -8178,12 +8000,13 @@ pub const FuncGen = struct {
8178 }8000 }
81798001
8180 fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value {8002 fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value {
8003 const mod = self.dg.module;
8181 const bin_op = self.air.instructions.items(.data)[inst].bin_op;8004 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8182 const dest_ptr = try self.resolveInst(bin_op.lhs);8005 const dest_ptr = try self.resolveInst(bin_op.lhs);
8183 const ptr_ty = self.air.typeOf(bin_op.lhs);8006 const ptr_ty = self.typeOf(bin_op.lhs);
8184 const operand_ty = ptr_ty.childType();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;
8187 if (val_is_undef) {8010 if (val_is_undef) {
8188 // Even if safety is disabled, we still emit a memset to undefined since it conveys8011 // Even if safety is disabled, we still emit a memset to undefined since it conveys
8189 // extra information to LLVM. However, safety makes the difference between using8012 // extra information to LLVM. However, safety makes the difference between using
...@@ -8193,13 +8016,12 @@ pub const FuncGen = struct {...@@ -8193,13 +8016,12 @@ pub const FuncGen = struct {
8193 u8_llvm_ty.constInt(0xaa, .False)8016 u8_llvm_ty.constInt(0xaa, .False)
8194 else8017 else
8195 u8_llvm_ty.getUndef();8018 u8_llvm_ty.getUndef();
8196 const target = self.dg.module.getTarget();8019 const operand_size = operand_ty.abiSize(mod);
8197 const operand_size = operand_ty.abiSize(target);
8198 const usize_llvm_ty = try self.dg.lowerType(Type.usize);8020 const usize_llvm_ty = try self.dg.lowerType(Type.usize);
8199 const len = usize_llvm_ty.constInt(operand_size, .False);8021 const len = usize_llvm_ty.constInt(operand_size, .False);
8200 const dest_ptr_align = ptr_ty.ptrAlignment(target);8022 const dest_ptr_align = ptr_ty.ptrAlignment(mod);
8201 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr());8023 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod));
8202 if (safety and self.dg.module.comp.bin_file.options.valgrind) {8024 if (safety and mod.comp.bin_file.options.valgrind) {
8203 self.valgrindMarkUndef(dest_ptr, len);8025 self.valgrindMarkUndef(dest_ptr, len);
8204 }8026 }
8205 return null;8027 return null;
...@@ -8217,8 +8039,10 @@ pub const FuncGen = struct {...@@ -8217,8 +8039,10 @@ pub const FuncGen = struct {
8217 ///8039 ///
8218 /// The first instruction of `body_tail` is the one whose copy we want to elide.8040 /// The first instruction of `body_tail` is the one whose copy we want to elide.
8219 fn canElideLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) bool {8041 fn canElideLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) bool {
8042 const mod = fg.dg.module;
8043 const ip = &mod.intern_pool;
8220 for (body_tail[1..]) |body_inst| {8044 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)) {
8222 .none => continue,8046 .none => continue,
8223 .write, .noret, .complex => return false,8047 .write, .noret, .complex => return false,
8224 .tomb => return true,8048 .tomb => return true,
...@@ -8230,14 +8054,15 @@ pub const FuncGen = struct {...@@ -8230,14 +8054,15 @@ pub const FuncGen = struct {
8230 }8054 }
82318055
8232 fn airLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {8056 fn airLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
8057 const mod = fg.dg.module;
8233 const inst = body_tail[0];8058 const inst = body_tail[0];
8234 const ty_op = fg.air.instructions.items(.data)[inst].ty_op;8059 const ty_op = fg.air.instructions.items(.data)[inst].ty_op;
8235 const ptr_ty = fg.air.typeOf(ty_op.operand);8060 const ptr_ty = fg.typeOf(ty_op.operand);
8236 const ptr_info = ptr_ty.ptrInfo().data;8061 const ptr_info = ptr_ty.ptrInfo(mod);
8237 const ptr = try fg.resolveInst(ty_op.operand);8062 const ptr = try fg.resolveInst(ty_op.operand);
82388063
8239 elide: {8064 elide: {
8240 if (!isByRef(ptr_info.pointee_type)) break :elide;8065 if (!isByRef(ptr_info.pointee_type, mod)) break :elide;
8241 if (!canElideLoad(fg, body_tail)) break :elide;8066 if (!canElideLoad(fg, body_tail)) break :elide;
8242 return ptr;8067 return ptr;
8243 }8068 }
...@@ -8261,8 +8086,9 @@ pub const FuncGen = struct {...@@ -8261,8 +8086,9 @@ pub const FuncGen = struct {
82618086
8262 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8087 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8263 _ = inst;8088 _ = inst;
8089 const mod = self.dg.module;
8264 const llvm_usize = try self.dg.lowerType(Type.usize);8090 const llvm_usize = try self.dg.lowerType(Type.usize);
8265 const target = self.dg.module.getTarget();8091 const target = mod.getTarget();
8266 if (!target_util.supportsReturnAddress(target)) {8092 if (!target_util.supportsReturnAddress(target)) {
8267 // https://github.com/ziglang/zig/issues/119468093 // https://github.com/ziglang/zig/issues/11946
8268 return llvm_usize.constNull();8094 return llvm_usize.constNull();
...@@ -8301,16 +8127,17 @@ pub const FuncGen = struct {...@@ -8301,16 +8127,17 @@ pub const FuncGen = struct {
8301 }8127 }
83028128
8303 fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !?*llvm.Value {8129 fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !?*llvm.Value {
8130 const mod = self.dg.module;
8304 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8131 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
8305 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;8132 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
8306 const ptr = try self.resolveInst(extra.ptr);8133 const ptr = try self.resolveInst(extra.ptr);
8307 var expected_value = try self.resolveInst(extra.expected_value);8134 var expected_value = try self.resolveInst(extra.expected_value);
8308 var new_value = try self.resolveInst(extra.new_value);8135 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);
8310 const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false);8137 const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false);
8311 if (opt_abi_ty) |abi_ty| {8138 if (opt_abi_ty) |abi_ty| {
8312 // operand needs widening and truncating8139 // operand needs widening and truncating
8313 if (operand_ty.isSignedInt()) {8140 if (operand_ty.isSignedInt(mod)) {
8314 expected_value = self.builder.buildSExt(expected_value, abi_ty, "");8141 expected_value = self.builder.buildSExt(expected_value, abi_ty, "");
8315 new_value = self.builder.buildSExt(new_value, abi_ty, "");8142 new_value = self.builder.buildSExt(new_value, abi_ty, "");
8316 } else {8143 } else {
...@@ -8328,7 +8155,7 @@ pub const FuncGen = struct {...@@ -8328,7 +8155,7 @@ pub const FuncGen = struct {
8328 );8155 );
8329 result.setWeak(llvm.Bool.fromBool(is_weak));8156 result.setWeak(llvm.Bool.fromBool(is_weak));
83308157
8331 const optional_ty = self.air.typeOfIndex(inst);8158 const optional_ty = self.typeOfIndex(inst);
83328159
8333 var payload = self.builder.buildExtractValue(result, 0, "");8160 var payload = self.builder.buildExtractValue(result, 0, "");
8334 if (opt_abi_ty != null) {8161 if (opt_abi_ty != null) {
...@@ -8336,7 +8163,7 @@ pub const FuncGen = struct {...@@ -8336,7 +8163,7 @@ pub const FuncGen = struct {
8336 }8163 }
8337 const success_bit = self.builder.buildExtractValue(result, 1, "");8164 const success_bit = self.builder.buildExtractValue(result, 1, "");
83388165
8339 if (optional_ty.optionalReprIsPayload()) {8166 if (optional_ty.optionalReprIsPayload(mod)) {
8340 return self.builder.buildSelect(success_bit, payload.typeOf().constNull(), payload, "");8167 return self.builder.buildSelect(success_bit, payload.typeOf().constNull(), payload, "");
8341 }8168 }
83428169
...@@ -8347,13 +8174,14 @@ pub const FuncGen = struct {...@@ -8347,13 +8174,14 @@ pub const FuncGen = struct {
8347 }8174 }
83488175
8349 fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8176 fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8177 const mod = self.dg.module;
8350 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8178 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8351 const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data;8179 const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data;
8352 const ptr = try self.resolveInst(pl_op.operand);8180 const ptr = try self.resolveInst(pl_op.operand);
8353 const ptr_ty = self.air.typeOf(pl_op.operand);8181 const ptr_ty = self.typeOf(pl_op.operand);
8354 const operand_ty = ptr_ty.elemType();8182 const operand_ty = ptr_ty.childType(mod);
8355 const operand = try self.resolveInst(extra.operand);8183 const operand = try self.resolveInst(extra.operand);
8356 const is_signed_int = operand_ty.isSignedInt();8184 const is_signed_int = operand_ty.isSignedInt(mod);
8357 const is_float = operand_ty.isRuntimeFloat();8185 const is_float = operand_ty.isRuntimeFloat();
8358 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);8186 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
8359 const ordering = toLlvmAtomicOrdering(extra.ordering());8187 const ordering = toLlvmAtomicOrdering(extra.ordering());
...@@ -8402,17 +8230,17 @@ pub const FuncGen = struct {...@@ -8402,17 +8230,17 @@ pub const FuncGen = struct {
8402 }8230 }
84038231
8404 fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8232 fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8233 const mod = self.dg.module;
8405 const atomic_load = self.air.instructions.items(.data)[inst].atomic_load;8234 const atomic_load = self.air.instructions.items(.data)[inst].atomic_load;
8406 const ptr = try self.resolveInst(atomic_load.ptr);8235 const ptr = try self.resolveInst(atomic_load.ptr);
8407 const ptr_ty = self.air.typeOf(atomic_load.ptr);8236 const ptr_ty = self.typeOf(atomic_load.ptr);
8408 const ptr_info = ptr_ty.ptrInfo().data;8237 const ptr_info = ptr_ty.ptrInfo(mod);
8409 const elem_ty = ptr_info.pointee_type;8238 const elem_ty = ptr_info.pointee_type;
8410 if (!elem_ty.hasRuntimeBitsIgnoreComptime())8239 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod))
8411 return null;8240 return null;
8412 const ordering = toLlvmAtomicOrdering(atomic_load.order);8241 const ordering = toLlvmAtomicOrdering(atomic_load.order);
8413 const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false);8242 const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false);
8414 const target = self.dg.module.getTarget();8243 const ptr_alignment = ptr_info.alignment(mod);
8415 const ptr_alignment = ptr_info.alignment(target);
8416 const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile");8244 const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile");
8417 const elem_llvm_ty = try self.dg.lowerType(elem_ty);8245 const elem_llvm_ty = try self.dg.lowerType(elem_ty);
84188246
...@@ -8436,17 +8264,18 @@ pub const FuncGen = struct {...@@ -8436,17 +8264,18 @@ pub const FuncGen = struct {
8436 inst: Air.Inst.Index,8264 inst: Air.Inst.Index,
8437 ordering: llvm.AtomicOrdering,8265 ordering: llvm.AtomicOrdering,
8438 ) !?*llvm.Value {8266 ) !?*llvm.Value {
8267 const mod = self.dg.module;
8439 const bin_op = self.air.instructions.items(.data)[inst].bin_op;8268 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8440 const ptr_ty = self.air.typeOf(bin_op.lhs);8269 const ptr_ty = self.typeOf(bin_op.lhs);
8441 const operand_ty = ptr_ty.childType();8270 const operand_ty = ptr_ty.childType(mod);
8442 if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return null;8271 if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return null;
8443 const ptr = try self.resolveInst(bin_op.lhs);8272 const ptr = try self.resolveInst(bin_op.lhs);
8444 var element = try self.resolveInst(bin_op.rhs);8273 var element = try self.resolveInst(bin_op.rhs);
8445 const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false);8274 const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false);
84468275
8447 if (opt_abi_ty) |abi_ty| {8276 if (opt_abi_ty) |abi_ty| {
8448 // operand needs widening8277 // operand needs widening
8449 if (operand_ty.isSignedInt()) {8278 if (operand_ty.isSignedInt(mod)) {
8450 element = self.builder.buildSExt(element, abi_ty, "");8279 element = self.builder.buildSExt(element, abi_ty, "");
8451 } else {8280 } else {
8452 element = self.builder.buildZExt(element, abi_ty, "");8281 element = self.builder.buildZExt(element, abi_ty, "");
...@@ -8457,19 +8286,19 @@ pub const FuncGen = struct {...@@ -8457,19 +8286,19 @@ pub const FuncGen = struct {
8457 }8286 }
84588287
8459 fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value {8288 fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value {
8289 const mod = self.dg.module;
8460 const bin_op = self.air.instructions.items(.data)[inst].bin_op;8290 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8461 const dest_slice = try self.resolveInst(bin_op.lhs);8291 const dest_slice = try self.resolveInst(bin_op.lhs);
8462 const ptr_ty = self.air.typeOf(bin_op.lhs);8292 const ptr_ty = self.typeOf(bin_op.lhs);
8463 const elem_ty = self.air.typeOf(bin_op.rhs);8293 const elem_ty = self.typeOf(bin_op.rhs);
8464 const module = self.dg.module;8294 const target = mod.getTarget();
8465 const target = module.getTarget();8295 const dest_ptr_align = ptr_ty.ptrAlignment(mod);
8466 const dest_ptr_align = ptr_ty.ptrAlignment(target);
8467 const u8_llvm_ty = self.context.intType(8);8296 const u8_llvm_ty = self.context.intType(8);
8468 const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty);8297 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| {8300 if (try self.air.value(bin_op.rhs, mod)) |elem_val| {
8472 if (elem_val.isUndefDeep()) {8301 if (elem_val.isUndefDeep(mod)) {
8473 // Even if safety is disabled, we still emit a memset to undefined since it conveys8302 // Even if safety is disabled, we still emit a memset to undefined since it conveys
8474 // extra information to LLVM. However, safety makes the difference between using8303 // extra information to LLVM. However, safety makes the difference between using
8475 // 0xaa or actual undefined for the fill byte.8304 // 0xaa or actual undefined for the fill byte.
...@@ -8480,7 +8309,7 @@ pub const FuncGen = struct {...@@ -8480,7 +8309,7 @@ pub const FuncGen = struct {
8480 const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);8309 const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
8481 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);8310 _ = 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) {
8484 self.valgrindMarkUndef(dest_ptr, len);8313 self.valgrindMarkUndef(dest_ptr, len);
8485 }8314 }
8486 return null;8315 return null;
...@@ -8490,8 +8319,7 @@ pub const FuncGen = struct {...@@ -8490,8 +8319,7 @@ pub const FuncGen = struct {
8490 // repeating byte pattern, for example, `@as(u64, 0)` has a8319 // repeating byte pattern, for example, `@as(u64, 0)` has a
8491 // repeating byte pattern of 0 bytes. In such case, the memset8320 // repeating byte pattern of 0 bytes. In such case, the memset
8492 // intrinsic can be used.8321 // intrinsic can be used.
8493 var value_buffer: Value.Payload.U64 = undefined;8322 if (try elem_val.hasRepeatedByteRepr(elem_ty, mod)) |byte_val| {
8494 if (try elem_val.hasRepeatedByteRepr(elem_ty, module, &value_buffer)) |byte_val| {
8495 const fill_byte = try self.resolveValue(.{8323 const fill_byte = try self.resolveValue(.{
8496 .ty = Type.u8,8324 .ty = Type.u8,
8497 .val = byte_val,8325 .val = byte_val,
...@@ -8503,7 +8331,7 @@ pub const FuncGen = struct {...@@ -8503,7 +8331,7 @@ pub const FuncGen = struct {
8503 }8331 }
85048332
8505 const value = try self.resolveInst(bin_op.rhs);8333 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
8508 if (elem_abi_size == 1) {8336 if (elem_abi_size == 1) {
8509 // In this case we can take advantage of LLVM's intrinsic.8337 // In this case we can take advantage of LLVM's intrinsic.
...@@ -8535,9 +8363,9 @@ pub const FuncGen = struct {...@@ -8535,9 +8363,9 @@ pub const FuncGen = struct {
8535 const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd");8363 const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd");
85368364
8537 const llvm_usize_ty = self.context.intType(target.ptrBitWidth());8365 const llvm_usize_ty = self.context.intType(target.ptrBitWidth());
8538 const len = switch (ptr_ty.ptrSize()) {8366 const len = switch (ptr_ty.ptrSize(mod)) {
8539 .Slice => self.builder.buildExtractValue(dest_slice, 1, ""),8367 .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),
8541 .Many, .C => unreachable,8369 .Many, .C => unreachable,
8542 };8370 };
8543 const elem_llvm_ty = try self.dg.lowerType(elem_ty);8371 const elem_llvm_ty = try self.dg.lowerType(elem_ty);
...@@ -8551,9 +8379,9 @@ pub const FuncGen = struct {...@@ -8551,9 +8379,9 @@ pub const FuncGen = struct {
8551 _ = self.builder.buildCondBr(end, body_block, end_block);8379 _ = self.builder.buildCondBr(end, body_block, end_block);
85528380
8553 self.builder.positionBuilderAtEnd(body_block);8381 self.builder.positionBuilderAtEnd(body_block);
8554 const elem_abi_alignment = elem_ty.abiAlignment(target);8382 const elem_abi_alignment = elem_ty.abiAlignment(mod);
8555 const it_ptr_alignment = @min(elem_abi_alignment, dest_ptr_align);8383 const it_ptr_alignment = @min(elem_abi_alignment, dest_ptr_align);
8556 if (isByRef(elem_ty)) {8384 if (isByRef(elem_ty, mod)) {
8557 _ = self.builder.buildMemCpy(8385 _ = self.builder.buildMemCpy(
8558 it_ptr,8386 it_ptr,
8559 it_ptr_alignment,8387 it_ptr_alignment,
...@@ -8583,19 +8411,19 @@ pub const FuncGen = struct {...@@ -8583,19 +8411,19 @@ pub const FuncGen = struct {
8583 fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8411 fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8584 const bin_op = self.air.instructions.items(.data)[inst].bin_op;8412 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8585 const dest_slice = try self.resolveInst(bin_op.lhs);8413 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);
8587 const src_slice = try self.resolveInst(bin_op.rhs);8415 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);
8589 const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty);8417 const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty);
8590 const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);8418 const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);
8591 const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty);8419 const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty);
8592 const is_volatile = src_ptr_ty.isVolatilePtr() or dest_ptr_ty.isVolatilePtr();8420 const mod = self.dg.module;
8593 const target = self.dg.module.getTarget();8421 const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod);
8594 _ = self.builder.buildMemCpy(8422 _ = self.builder.buildMemCpy(
8595 dest_ptr,8423 dest_ptr,
8596 dest_ptr_ty.ptrAlignment(target),8424 dest_ptr_ty.ptrAlignment(mod),
8597 src_ptr,8425 src_ptr,
8598 src_ptr_ty.ptrAlignment(target),8426 src_ptr_ty.ptrAlignment(mod),
8599 len,8427 len,
8600 is_volatile,8428 is_volatile,
8601 );8429 );
...@@ -8603,10 +8431,10 @@ pub const FuncGen = struct {...@@ -8603,10 +8431,10 @@ pub const FuncGen = struct {
8603 }8431 }
86048432
8605 fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8433 fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8434 const mod = self.dg.module;
8606 const bin_op = self.air.instructions.items(.data)[inst].bin_op;8435 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8607 const un_ty = self.air.typeOf(bin_op.lhs).childType();8436 const un_ty = self.typeOf(bin_op.lhs).childType(mod);
8608 const target = self.dg.module.getTarget();8437 const layout = un_ty.unionGetLayout(mod);
8609 const layout = un_ty.unionGetLayout(target);
8610 if (layout.tag_size == 0) return null;8438 if (layout.tag_size == 0) return null;
8611 const union_ptr = try self.resolveInst(bin_op.lhs);8439 const union_ptr = try self.resolveInst(bin_op.lhs);
8612 const new_tag = try self.resolveInst(bin_op.rhs);8440 const new_tag = try self.resolveInst(bin_op.rhs);
...@@ -8624,13 +8452,13 @@ pub const FuncGen = struct {...@@ -8624,13 +8452,13 @@ pub const FuncGen = struct {
8624 }8452 }
86258453
8626 fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8454 fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8455 const mod = self.dg.module;
8627 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8456 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8628 const un_ty = self.air.typeOf(ty_op.operand);8457 const un_ty = self.typeOf(ty_op.operand);
8629 const target = self.dg.module.getTarget();8458 const layout = un_ty.unionGetLayout(mod);
8630 const layout = un_ty.unionGetLayout(target);
8631 if (layout.tag_size == 0) return null;8459 if (layout.tag_size == 0) return null;
8632 const union_handle = try self.resolveInst(ty_op.operand);8460 const union_handle = try self.resolveInst(ty_op.operand);
8633 if (isByRef(un_ty)) {8461 if (isByRef(un_ty, mod)) {
8634 const llvm_un_ty = try self.dg.lowerType(un_ty);8462 const llvm_un_ty = try self.dg.lowerType(un_ty);
8635 if (layout.payload_size == 0) {8463 if (layout.payload_size == 0) {
8636 return self.builder.buildLoad(llvm_un_ty, union_handle, "");8464 return self.builder.buildLoad(llvm_un_ty, union_handle, "");
...@@ -8650,7 +8478,7 @@ pub const FuncGen = struct {...@@ -8650,7 +8478,7 @@ pub const FuncGen = struct {
8650 fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) !?*llvm.Value {8478 fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) !?*llvm.Value {
8651 const un_op = self.air.instructions.items(.data)[inst].un_op;8479 const un_op = self.air.instructions.items(.data)[inst].un_op;
8652 const operand = try self.resolveInst(un_op);8480 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
8655 return self.buildFloatOp(op, operand_ty, 1, .{operand});8483 return self.buildFloatOp(op, operand_ty, 1, .{operand});
8656 }8484 }
...@@ -8660,14 +8488,15 @@ pub const FuncGen = struct {...@@ -8660,14 +8488,15 @@ pub const FuncGen = struct {
86608488
8661 const un_op = self.air.instructions.items(.data)[inst].un_op;8489 const un_op = self.air.instructions.items(.data)[inst].un_op;
8662 const operand = try self.resolveInst(un_op);8490 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
8665 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});8493 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
8666 }8494 }
86678495
8668 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {8496 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8497 const mod = self.dg.module;
8669 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8498 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);
8671 const operand = try self.resolveInst(ty_op.operand);8500 const operand = try self.resolveInst(ty_op.operand);
86728501
8673 const llvm_i1 = self.context.intType(1);8502 const llvm_i1 = self.context.intType(1);
...@@ -8676,12 +8505,11 @@ pub const FuncGen = struct {...@@ -8676,12 +8505,11 @@ pub const FuncGen = struct {
86768505
8677 const params = [_]*llvm.Value{ operand, llvm_i1.constNull() };8506 const params = [_]*llvm.Value{ operand, llvm_i1.constNull() };
8678 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");8507 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);
8680 const result_llvm_ty = try self.dg.lowerType(result_ty);8509 const result_llvm_ty = try self.dg.lowerType(result_ty);
86818510
8682 const target = self.dg.module.getTarget();8511 const bits = operand_ty.intInfo(mod).bits;
8683 const bits = operand_ty.intInfo(target).bits;8512 const result_bits = result_ty.intInfo(mod).bits;
8684 const result_bits = result_ty.intInfo(target).bits;
8685 if (bits > result_bits) {8513 if (bits > result_bits) {
8686 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");8514 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
8687 } else if (bits < result_bits) {8515 } else if (bits < result_bits) {
...@@ -8692,8 +8520,9 @@ pub const FuncGen = struct {...@@ -8692,8 +8520,9 @@ pub const FuncGen = struct {
8692 }8520 }
86938521
8694 fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {8522 fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8523 const mod = self.dg.module;
8695 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8524 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);
8697 const operand = try self.resolveInst(ty_op.operand);8526 const operand = try self.resolveInst(ty_op.operand);
86988527
8699 const params = [_]*llvm.Value{operand};8528 const params = [_]*llvm.Value{operand};
...@@ -8701,12 +8530,11 @@ pub const FuncGen = struct {...@@ -8701,12 +8530,11 @@ pub const FuncGen = struct {
8701 const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});8530 const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
87028531
8703 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");8532 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);
8705 const result_llvm_ty = try self.dg.lowerType(result_ty);8534 const result_llvm_ty = try self.dg.lowerType(result_ty);
87068535
8707 const target = self.dg.module.getTarget();8536 const bits = operand_ty.intInfo(mod).bits;
8708 const bits = operand_ty.intInfo(target).bits;8537 const result_bits = result_ty.intInfo(mod).bits;
8709 const result_bits = result_ty.intInfo(target).bits;
8710 if (bits > result_bits) {8538 if (bits > result_bits) {
8711 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");8539 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
8712 } else if (bits < result_bits) {8540 } else if (bits < result_bits) {
...@@ -8717,10 +8545,10 @@ pub const FuncGen = struct {...@@ -8717,10 +8545,10 @@ pub const FuncGen = struct {
8717 }8545 }
87188546
8719 fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {8547 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;
8721 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8549 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8722 const operand_ty = self.air.typeOf(ty_op.operand);8550 const operand_ty = self.typeOf(ty_op.operand);
8723 var bits = operand_ty.intInfo(target).bits;8551 var bits = operand_ty.intInfo(mod).bits;
8724 assert(bits % 8 == 0);8552 assert(bits % 8 == 0);
87258553
8726 var operand = try self.resolveInst(ty_op.operand);8554 var operand = try self.resolveInst(ty_op.operand);
...@@ -8730,8 +8558,8 @@ pub const FuncGen = struct {...@@ -8730,8 +8558,8 @@ pub const FuncGen = struct {
8730 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte8558 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte
8731 // The truncated result at the end will be the correct bswap8559 // The truncated result at the end will be the correct bswap
8732 const scalar_llvm_ty = self.context.intType(bits + 8);8560 const scalar_llvm_ty = self.context.intType(bits + 8);
8733 if (operand_ty.zigTypeTag() == .Vector) {8561 if (operand_ty.zigTypeTag(mod) == .Vector) {
8734 const vec_len = operand_ty.vectorLen();8562 const vec_len = operand_ty.vectorLen(mod);
8735 operand_llvm_ty = scalar_llvm_ty.vectorType(vec_len);8563 operand_llvm_ty = scalar_llvm_ty.vectorType(vec_len);
87368564
8737 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);8565 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
...@@ -8757,9 +8585,9 @@ pub const FuncGen = struct {...@@ -8757,9 +8585,9 @@ pub const FuncGen = struct {
87578585
8758 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");8586 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);
8761 const result_llvm_ty = try self.dg.lowerType(result_ty);8589 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;
8763 if (bits > result_bits) {8591 if (bits > result_bits) {
8764 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");8592 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
8765 } else if (bits < result_bits) {8593 } else if (bits < result_bits) {
...@@ -8770,28 +8598,23 @@ pub const FuncGen = struct {...@@ -8770,28 +8598,23 @@ pub const FuncGen = struct {
8770 }8598 }
87718599
8772 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8600 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8601 const mod = self.dg.module;
8773 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8602 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8774 const operand = try self.resolveInst(ty_op.operand);8603 const operand = try self.resolveInst(ty_op.operand);
8775 const error_set_ty = self.air.getRefType(ty_op.ty);8604 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);
8778 const valid_block = self.context.appendBasicBlock(self.llvm_func, "Valid");8607 const valid_block = self.context.appendBasicBlock(self.llvm_func, "Valid");
8779 const invalid_block = self.context.appendBasicBlock(self.llvm_func, "Invalid");8608 const invalid_block = self.context.appendBasicBlock(self.llvm_func, "Invalid");
8780 const end_block = self.context.appendBasicBlock(self.llvm_func, "End");8609 const end_block = self.context.appendBasicBlock(self.llvm_func, "End");
8781 const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len));8610 const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len));
87828611
8783 for (names) |name| {8612 for (names) |name| {
8784 const err_int = self.dg.module.global_error_set.get(name).?;8613 const err_int = @intCast(Module.ErrorInt, mod.global_error_set.getIndex(name).?);
8785 const this_tag_int_value = int: {8614 const this_tag_int_value = try self.dg.lowerValue(.{
8786 var tag_val_payload: Value.Payload.U64 = .{8615 .ty = Type.err_int,
8787 .base = .{ .tag = .int_u64 },8616 .val = try mod.intValue(Type.err_int, err_int),
8788 .data = err_int,8617 });
8789 };
8790 break :int try self.dg.lowerValue(.{
8791 .ty = Type.err_int,
8792 .val = Value.initPayload(&tag_val_payload.base),
8793 });
8794 };
8795 switch_instr.addCase(this_tag_int_value, valid_block);8618 switch_instr.addCase(this_tag_int_value, valid_block);
8796 }8619 }
8797 self.builder.positionBuilderAtEnd(valid_block);8620 self.builder.positionBuilderAtEnd(valid_block);
...@@ -8817,7 +8640,7 @@ pub const FuncGen = struct {...@@ -8817,7 +8640,7 @@ pub const FuncGen = struct {
8817 fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8640 fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8818 const un_op = self.air.instructions.items(.data)[inst].un_op;8641 const un_op = self.air.instructions.items(.data)[inst].un_op;
8819 const operand = try self.resolveInst(un_op);8642 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
8822 const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty);8645 const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty);
8823 const params = [_]*llvm.Value{operand};8646 const params = [_]*llvm.Value{operand};
...@@ -8825,25 +8648,22 @@ pub const FuncGen = struct {...@@ -8825,25 +8648,22 @@ pub const FuncGen = struct {
8825 }8648 }
88268649
8827 fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !*llvm.Value {8650 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
8830 // TODO: detect when the type changes and re-emit this function.8654 // 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);
8832 if (gop.found_existing) return gop.value_ptr.*;8656 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
8835 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);8659 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
8836 defer arena_allocator.deinit();8660 defer arena_allocator.deinit();
8837 const arena = arena_allocator.allocator();8661 const arena = arena_allocator.allocator();
88388662
8839 const mod = self.dg.module;8663 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
8840 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);8664 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)});
8841 defer self.gpa.free(fqn);
8842 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn});
88438665
8844 var int_tag_type_buffer: Type.Payload.Bits = undefined;8666 const param_types = [_]*llvm.Type{try self.dg.lowerType(enum_type.tag_ty.toType())};
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)};
88478667
8848 const llvm_ret_ty = try self.dg.lowerType(Type.bool);8668 const llvm_ret_ty = try self.dg.lowerType(Type.bool);
8849 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);8669 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);
...@@ -8866,21 +8686,17 @@ pub const FuncGen = struct {...@@ -8866,21 +8686,17 @@ pub const FuncGen = struct {
8866 self.builder.positionBuilderAtEnd(entry_block);8686 self.builder.positionBuilderAtEnd(entry_block);
8867 self.builder.clearCurrentDebugLocation();8687 self.builder.clearCurrentDebugLocation();
88688688
8869 const fields = enum_ty.enumFields();
8870 const named_block = self.context.appendBasicBlock(fn_val, "Named");8689 const named_block = self.context.appendBasicBlock(fn_val, "Named");
8871 const unnamed_block = self.context.appendBasicBlock(fn_val, "Unnamed");8690 const unnamed_block = self.context.appendBasicBlock(fn_val, "Unnamed");
8872 const tag_int_value = fn_val.getParam(0);8691 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);
8876 const this_tag_int_value = int: {8696 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 };
8881 break :int try self.dg.lowerValue(.{8697 break :int try self.dg.lowerValue(.{
8882 .ty = enum_ty,8698 .ty = enum_ty,
8883 .val = Value.initPayload(&tag_val_payload.base),8699 .val = try mod.enumValueFieldIndex(enum_ty, field_index),
8884 });8700 });
8885 };8701 };
8886 switch_instr.addCase(this_tag_int_value, named_block);8702 switch_instr.addCase(this_tag_int_value, named_block);
...@@ -8896,7 +8712,7 @@ pub const FuncGen = struct {...@@ -8896,7 +8712,7 @@ pub const FuncGen = struct {
8896 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8712 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8897 const un_op = self.air.instructions.items(.data)[inst].un_op;8713 const un_op = self.air.instructions.items(.data)[inst].un_op;
8898 const operand = try self.resolveInst(un_op);8714 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
8901 const llvm_fn = try self.getEnumTagNameFunction(enum_ty);8717 const llvm_fn = try self.getEnumTagNameFunction(enum_ty);
8902 const params = [_]*llvm.Value{operand};8718 const params = [_]*llvm.Value{operand};
...@@ -8904,31 +8720,27 @@ pub const FuncGen = struct {...@@ -8904,31 +8720,27 @@ pub const FuncGen = struct {
8904 }8720 }
89058721
8906 fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*llvm.Value {8722 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
8909 // TODO: detect when the type changes and re-emit this function.8726 // 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);
8911 if (gop.found_existing) return gop.value_ptr.*;8728 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
8914 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);8731 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
8915 defer arena_allocator.deinit();8732 defer arena_allocator.deinit();
8916 const arena = arena_allocator.allocator();8733 const arena = arena_allocator.allocator();
89178734
8918 const mod = self.dg.module;8735 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
8919 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);8736 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)});
8920 defer self.gpa.free(fqn);
8921 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
89228737
8923 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);8738 const slice_ty = Type.slice_const_u8_sentinel_0;
8924 const llvm_ret_ty = try self.dg.lowerType(slice_ty);8739 const llvm_ret_ty = try self.dg.lowerType(slice_ty);
8925 const usize_llvm_ty = try self.dg.lowerType(Type.usize);8740 const usize_llvm_ty = try self.dg.lowerType(Type.usize);
8926 const target = self.dg.module.getTarget();8741 const slice_alignment = slice_ty.abiAlignment(mod);
8927 const slice_alignment = slice_ty.abiAlignment(target);
89288742
8929 var int_tag_type_buffer: Type.Payload.Bits = undefined;8743 const param_types = [_]*llvm.Type{try self.dg.lowerType(enum_type.tag_ty.toType())};
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)};
89328744
8933 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);8745 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);
8934 const fn_val = self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);8746 const fn_val = self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
...@@ -8950,16 +8762,17 @@ pub const FuncGen = struct {...@@ -8950,16 +8762,17 @@ pub const FuncGen = struct {
8950 self.builder.positionBuilderAtEnd(entry_block);8762 self.builder.positionBuilderAtEnd(entry_block);
8951 self.builder.clearCurrentDebugLocation();8763 self.builder.clearCurrentDebugLocation();
89528764
8953 const fields = enum_ty.enumFields();
8954 const bad_value_block = self.context.appendBasicBlock(fn_val, "BadValue");8765 const bad_value_block = self.context.appendBasicBlock(fn_val, "BadValue");
8955 const tag_int_value = fn_val.getParam(0);8766 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
8958 const array_ptr_indices = [_]*llvm.Value{8769 const array_ptr_indices = [_]*llvm.Value{
8959 usize_llvm_ty.constNull(), usize_llvm_ty.constNull(),8770 usize_llvm_ty.constNull(), usize_llvm_ty.constNull(),
8960 };8771 };
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);
8963 const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False);8776 const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False);
8964 const str_init_llvm_ty = str_init.typeOf();8777 const str_init_llvm_ty = str_init.typeOf();
8965 const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, "");8778 const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, "");
...@@ -8982,16 +8795,10 @@ pub const FuncGen = struct {...@@ -8982,16 +8795,10 @@ pub const FuncGen = struct {
8982 slice_global.setAlignment(slice_alignment);8795 slice_global.setAlignment(slice_alignment);
89838796
8984 const return_block = self.context.appendBasicBlock(fn_val, "Name");8797 const return_block = self.context.appendBasicBlock(fn_val, "Name");
8985 const this_tag_int_value = int: {8798 const this_tag_int_value = try self.dg.lowerValue(.{
8986 var tag_val_payload: Value.Payload.U32 = .{8799 .ty = enum_ty,
8987 .base = .{ .tag = .enum_field_index },8800 .val = try mod.enumValueFieldIndex(enum_ty, field_index),
8988 .data = @intCast(u32, field_index),8801 });
8989 };
8990 break :int try self.dg.lowerValue(.{
8991 .ty = enum_ty,
8992 .val = Value.initPayload(&tag_val_payload.base),
8993 });
8994 };
8995 switch_instr.addCase(this_tag_int_value, return_block);8802 switch_instr.addCase(this_tag_int_value, return_block);
89968803
8997 self.builder.positionBuilderAtEnd(return_block);8804 self.builder.positionBuilderAtEnd(return_block);
...@@ -9027,7 +8834,7 @@ pub const FuncGen = struct {...@@ -9027,7 +8834,7 @@ pub const FuncGen = struct {
9027 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8834 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9028 const un_op = self.air.instructions.items(.data)[inst].un_op;8835 const un_op = self.air.instructions.items(.data)[inst].un_op;
9029 const operand = try self.resolveInst(un_op);8836 const operand = try self.resolveInst(un_op);
9030 const slice_ty = self.air.typeOfIndex(inst);8837 const slice_ty = self.typeOfIndex(inst);
9031 const slice_llvm_ty = try self.dg.lowerType(slice_ty);8838 const slice_llvm_ty = try self.dg.lowerType(slice_ty);
90328839
9033 const error_name_table_ptr = try self.getErrorNameTable();8840 const error_name_table_ptr = try self.getErrorNameTable();
...@@ -9039,10 +8846,11 @@ pub const FuncGen = struct {...@@ -9039,10 +8846,11 @@ pub const FuncGen = struct {
9039 }8846 }
90408847
9041 fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8848 fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8849 const mod = self.dg.module;
9042 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8850 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9043 const scalar = try self.resolveInst(ty_op.operand);8851 const scalar = try self.resolveInst(ty_op.operand);
9044 const vector_ty = self.air.typeOfIndex(inst);8852 const vector_ty = self.typeOfIndex(inst);
9045 const len = vector_ty.vectorLen();8853 const len = vector_ty.vectorLen(mod);
9046 return self.builder.buildVectorSplat(len, scalar, "");8854 return self.builder.buildVectorSplat(len, scalar, "");
9047 }8855 }
90488856
...@@ -9057,13 +8865,14 @@ pub const FuncGen = struct {...@@ -9057,13 +8865,14 @@ pub const FuncGen = struct {
9057 }8865 }
90588866
9059 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8867 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8868 const mod = self.dg.module;
9060 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8869 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9061 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;8870 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
9062 const a = try self.resolveInst(extra.a);8871 const a = try self.resolveInst(extra.a);
9063 const b = try self.resolveInst(extra.b);8872 const b = try self.resolveInst(extra.b);
9064 const mask = self.air.values[extra.mask];8873 const mask = extra.mask.toValue();
9065 const mask_len = extra.mask_len;8874 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
9068 // LLVM uses integers larger than the length of the first array to8877 // LLVM uses integers larger than the length of the first array to
9069 // index into the second array. This was deemed unnecessarily fragile8878 // index into the second array. This was deemed unnecessarily fragile
...@@ -9076,12 +8885,11 @@ pub const FuncGen = struct {...@@ -9076,12 +8885,11 @@ pub const FuncGen = struct {
9076 const llvm_i32 = self.context.intType(32);8885 const llvm_i32 = self.context.intType(32);
90778886
9078 for (values, 0..) |*val, i| {8887 for (values, 0..) |*val, i| {
9079 var buf: Value.ElemValueBuffer = undefined;8888 const elem = try mask.elemValue(mod, i);
9080 const elem = mask.elemValueBuffer(self.dg.module, i, &buf);8889 if (elem.isUndef(mod)) {
9081 if (elem.isUndef()) {
9082 val.* = llvm_i32.getUndef();8890 val.* = llvm_i32.getUndef();
9083 } else {8891 } else {
9084 const int = elem.toSignedInt(self.dg.module.getTarget());8892 const int = elem.toSignedInt(mod);
9085 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);8893 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
9086 val.* = llvm_i32.constInt(unsigned, .False);8894 val.* = llvm_i32.constInt(unsigned, .False);
9087 }8895 }
...@@ -9157,32 +8965,33 @@ pub const FuncGen = struct {...@@ -9157,32 +8965,33 @@ pub const FuncGen = struct {
91578965
9158 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {8966 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
9159 self.builder.setFastMath(want_fast_math);8967 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
9162 const reduce = self.air.instructions.items(.data)[inst].reduce;8971 const reduce = self.air.instructions.items(.data)[inst].reduce;
9163 const operand = try self.resolveInst(reduce.operand);8972 const operand = try self.resolveInst(reduce.operand);
9164 const operand_ty = self.air.typeOf(reduce.operand);8973 const operand_ty = self.typeOf(reduce.operand);
9165 const scalar_ty = self.air.typeOfIndex(inst);8974 const scalar_ty = self.typeOfIndex(inst);
91668975
9167 switch (reduce.operation) {8976 switch (reduce.operation) {
9168 .And => return self.builder.buildAndReduce(operand),8977 .And => return self.builder.buildAndReduce(operand),
9169 .Or => return self.builder.buildOrReduce(operand),8978 .Or => return self.builder.buildOrReduce(operand),
9170 .Xor => return self.builder.buildXorReduce(operand),8979 .Xor => return self.builder.buildXorReduce(operand),
9171 .Min => switch (scalar_ty.zigTypeTag()) {8980 .Min => switch (scalar_ty.zigTypeTag(mod)) {
9172 .Int => return self.builder.buildIntMinReduce(operand, scalar_ty.isSignedInt()),8981 .Int => return self.builder.buildIntMinReduce(operand, scalar_ty.isSignedInt(mod)),
9173 .Float => if (intrinsicsAllowed(scalar_ty, target)) {8982 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
9174 return self.builder.buildFPMinReduce(operand);8983 return self.builder.buildFPMinReduce(operand);
9175 },8984 },
9176 else => unreachable,8985 else => unreachable,
9177 },8986 },
9178 .Max => switch (scalar_ty.zigTypeTag()) {8987 .Max => switch (scalar_ty.zigTypeTag(mod)) {
9179 .Int => return self.builder.buildIntMaxReduce(operand, scalar_ty.isSignedInt()),8988 .Int => return self.builder.buildIntMaxReduce(operand, scalar_ty.isSignedInt(mod)),
9180 .Float => if (intrinsicsAllowed(scalar_ty, target)) {8989 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
9181 return self.builder.buildFPMaxReduce(operand);8990 return self.builder.buildFPMaxReduce(operand);
9182 },8991 },
9183 else => unreachable,8992 else => unreachable,
9184 },8993 },
9185 .Add => switch (scalar_ty.zigTypeTag()) {8994 .Add => switch (scalar_ty.zigTypeTag(mod)) {
9186 .Int => return self.builder.buildAddReduce(operand),8995 .Int => return self.builder.buildAddReduce(operand),
9187 .Float => if (intrinsicsAllowed(scalar_ty, target)) {8996 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
9188 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);8997 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
...@@ -9191,7 +9000,7 @@ pub const FuncGen = struct {...@@ -9191,7 +9000,7 @@ pub const FuncGen = struct {
9191 },9000 },
9192 else => unreachable,9001 else => unreachable,
9193 },9002 },
9194 .Mul => switch (scalar_ty.zigTypeTag()) {9003 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
9195 .Int => return self.builder.buildMulReduce(operand),9004 .Int => return self.builder.buildMulReduce(operand),
9196 .Float => if (intrinsicsAllowed(scalar_ty, target)) {9005 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
9197 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);9006 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
...@@ -9221,35 +9030,32 @@ pub const FuncGen = struct {...@@ -9221,35 +9030,32 @@ pub const FuncGen = struct {
9221 }) catch unreachable,9030 }) catch unreachable,
9222 else => unreachable,9031 else => unreachable,
9223 };9032 };
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
9234 const param_llvm_ty = try self.dg.lowerType(scalar_ty);9034 const param_llvm_ty = try self.dg.lowerType(scalar_ty);
9235 const param_types = [2]*llvm.Type{ param_llvm_ty, param_llvm_ty };9035 const param_types = [2]*llvm.Type{ param_llvm_ty, param_llvm_ty };
9236 const libc_fn = self.getLibcFunction(fn_name, &param_types, param_llvm_ty);9036 const libc_fn = self.getLibcFunction(fn_name, &param_types, param_llvm_ty);
9237 const init_value = try self.dg.lowerValue(.{9037 const init_value = try self.dg.lowerValue(.{
9238 .ty = scalar_ty,9038 .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 }),
9240 });9046 });
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);
9242 }9048 }
92439049
9244 fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9050 fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9051 const mod = self.dg.module;
9245 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;9052 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9246 const result_ty = self.air.typeOfIndex(inst);9053 const result_ty = self.typeOfIndex(inst);
9247 const len = @intCast(usize, result_ty.arrayLen());9054 const len = @intCast(usize, result_ty.arrayLen(mod));
9248 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);9055 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
9249 const llvm_result_ty = try self.dg.lowerType(result_ty);9056 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)) {
9253 .Vector => {9059 .Vector => {
9254 const llvm_u32 = self.context.intType(32);9060 const llvm_u32 = self.context.intType(32);
92559061
...@@ -9262,10 +9068,10 @@ pub const FuncGen = struct {...@@ -9262,10 +9068,10 @@ pub const FuncGen = struct {
9262 return vector;9068 return vector;
9263 },9069 },
9264 .Struct => {9070 .Struct => {
9265 if (result_ty.containerLayout() == .Packed) {9071 if (result_ty.containerLayout(mod) == .Packed) {
9266 const struct_obj = result_ty.castTag(.@"struct").?.data;9072 const struct_obj = mod.typeToStruct(result_ty).?;
9267 assert(struct_obj.haveLayout());9073 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);
9269 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));9075 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));
9270 const fields = struct_obj.fields.values();9076 const fields = struct_obj.fields.values();
9271 comptime assert(Type.packed_struct_layout_version == 2);9077 comptime assert(Type.packed_struct_layout_version == 2);
...@@ -9273,12 +9079,12 @@ pub const FuncGen = struct {...@@ -9273,12 +9079,12 @@ pub const FuncGen = struct {
9273 var running_bits: u16 = 0;9079 var running_bits: u16 = 0;
9274 for (elements, 0..) |elem, i| {9080 for (elements, 0..) |elem, i| {
9275 const field = fields[i];9081 const field = fields[i];
9276 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;9082 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
92779083
9278 const non_int_val = try self.resolveInst(elem);9084 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));
9280 const small_int_ty = self.context.intType(ty_bit_size);9086 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))
9282 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")9088 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
9283 else9089 else
9284 self.builder.buildBitCast(non_int_val, small_int_ty, "");9090 self.builder.buildBitCast(non_int_val, small_int_ty, "");
...@@ -9294,30 +9100,28 @@ pub const FuncGen = struct {...@@ -9294,30 +9100,28 @@ pub const FuncGen = struct {
9294 return running_int;9100 return running_int;
9295 }9101 }
92969102
9297 var ptr_ty_buf: Type.Payload.Pointer = undefined;9103 if (isByRef(result_ty, mod)) {
9298
9299 if (isByRef(result_ty)) {
9300 const llvm_u32 = self.context.intType(32);9104 const llvm_u32 = self.context.intType(32);
9301 // TODO in debug builds init to undef so that the padding will be 0xaa9105 // TODO in debug builds init to undef so that the padding will be 0xaa
9302 // even if we fully populate the fields.9106 // 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
9305 var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined };9109 var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined };
9306 for (elements, 0..) |elem, i| {9110 for (elements, 0..) |elem, i| {
9307 if (result_ty.structFieldValueComptime(i) != null) continue;9111 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93089112
9309 const llvm_elem = try self.resolveInst(elem);9113 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;
9311 indices[1] = llvm_u32.constInt(llvm_i, .False);9115 indices[1] = llvm_u32.constInt(llvm_i, .False);
9312 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");9116 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
9313 var field_ptr_payload: Type.Payload.Pointer = .{9117 const field_ptr_ty = try mod.ptrType(.{
9314 .data = .{9118 .child = self.typeOf(elem).toIntern(),
9315 .pointee_type = self.air.typeOf(elem),9119 .flags = .{
9316 .@"align" = result_ty.structFieldAlign(i, target),9120 .alignment = InternPool.Alignment.fromNonzeroByteUnits(
9317 .@"addrspace" = .generic,9121 result_ty.structFieldAlign(i, mod),
9122 ),
9318 },9123 },
9319 };9124 });
9320 const field_ptr_ty = Type.initPayload(&field_ptr_payload.base);
9321 try self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);9125 try self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);
9322 }9126 }
93239127
...@@ -9325,29 +9129,25 @@ pub const FuncGen = struct {...@@ -9325,29 +9129,25 @@ pub const FuncGen = struct {
9325 } else {9129 } else {
9326 var result = llvm_result_ty.getUndef();9130 var result = llvm_result_ty.getUndef();
9327 for (elements, 0..) |elem, i| {9131 for (elements, 0..) |elem, i| {
9328 if (result_ty.structFieldValueComptime(i) != null) continue;9132 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93299133
9330 const llvm_elem = try self.resolveInst(elem);9134 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;
9332 result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, "");9136 result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, "");
9333 }9137 }
9334 return result;9138 return result;
9335 }9139 }
9336 },9140 },
9337 .Array => {9141 .Array => {
9338 assert(isByRef(result_ty));9142 assert(isByRef(result_ty, mod));
93399143
9340 const llvm_usize = try self.dg.lowerType(Type.usize);9144 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();9147 const array_info = result_ty.arrayInfo(mod);
9344 var elem_ptr_payload: Type.Payload.Pointer = .{9148 const elem_ptr_ty = try mod.ptrType(.{
9345 .data = .{9149 .child = array_info.elem_type.toIntern(),
9346 .pointee_type = array_info.elem_type,9150 });
9347 .@"addrspace" = .generic,
9348 },
9349 };
9350 const elem_ptr_ty = Type.initPayload(&elem_ptr_payload.base);
93519151
9352 for (elements, 0..) |elem, i| {9152 for (elements, 0..) |elem, i| {
9353 const indices: [2]*llvm.Value = .{9153 const indices: [2]*llvm.Value = .{
...@@ -9379,22 +9179,22 @@ pub const FuncGen = struct {...@@ -9379,22 +9179,22 @@ pub const FuncGen = struct {
9379 }9179 }
93809180
9381 fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9181 fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9182 const mod = self.dg.module;
9382 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;9183 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9383 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;9184 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);
9385 const union_llvm_ty = try self.dg.lowerType(union_ty);9186 const union_llvm_ty = try self.dg.lowerType(union_ty);
9386 const target = self.dg.module.getTarget();9187 const layout = union_ty.unionGetLayout(mod);
9387 const layout = union_ty.unionGetLayout(target);9188 const union_obj = mod.typeToUnion(union_ty).?;
9388 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
93899189
9390 if (union_obj.layout == .Packed) {9190 if (union_obj.layout == .Packed) {
9391 const big_bits = union_ty.bitSize(target);9191 const big_bits = union_ty.bitSize(mod);
9392 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));9192 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));
9393 const field = union_obj.fields.values()[extra.field_index];9193 const field = union_obj.fields.values()[extra.field_index];
9394 const non_int_val = try self.resolveInst(extra.init);9194 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));
9396 const small_int_ty = self.context.intType(ty_bit_size);9196 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))
9398 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")9198 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
9399 else9199 else
9400 self.builder.buildBitCast(non_int_val, small_int_ty, "");9200 self.builder.buildBitCast(non_int_val, small_int_ty, "");
...@@ -9402,26 +9202,21 @@ pub const FuncGen = struct {...@@ -9402,26 +9202,21 @@ pub const FuncGen = struct {
9402 }9202 }
94039203
9404 const tag_int = blk: {9204 const tag_int = blk: {
9405 const tag_ty = union_ty.unionTagTypeHypothetical();9205 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
9406 const union_field_name = union_obj.fields.keys()[extra.field_index];9206 const union_field_name = union_obj.fields.keys()[extra.field_index];
9407 const enum_field_index = tag_ty.enumFieldIndex(union_field_name).?;9207 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
9408 var tag_val_payload: Value.Payload.U32 = .{9208 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
9409 .base = .{ .tag = .enum_field_index },9209 const tag_int_val = try tag_val.enumToInt(tag_ty, mod);
9410 .data = @intCast(u32, enum_field_index),9210 break :blk tag_int_val.toUnsignedInt(mod);
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);
9416 };9211 };
9417 if (layout.payload_size == 0) {9212 if (layout.payload_size == 0) {
9418 if (layout.tag_size == 0) {9213 if (layout.tag_size == 0) {
9419 return null;9214 return null;
9420 }9215 }
9421 assert(!isByRef(union_ty));9216 assert(!isByRef(union_ty, mod));
9422 return union_llvm_ty.constInt(tag_int, .False);9217 return union_llvm_ty.constInt(tag_int, .False);
9423 }9218 }
9424 assert(isByRef(union_ty));9219 assert(isByRef(union_ty, mod));
9425 // The llvm type of the alloca will be the named LLVM union type, and will not9220 // The llvm type of the alloca will be the named LLVM union type, and will not
9426 // necessarily match the format that we need, depending on which tag is active.9221 // necessarily match the format that we need, depending on which tag is active.
9427 // We must construct the correct unnamed struct type here, in order to then set9222 // We must construct the correct unnamed struct type here, in order to then set
...@@ -9431,12 +9226,12 @@ pub const FuncGen = struct {...@@ -9431,12 +9226,12 @@ pub const FuncGen = struct {
9431 assert(union_obj.haveFieldTypes());9226 assert(union_obj.haveFieldTypes());
9432 const field = union_obj.fields.values()[extra.field_index];9227 const field = union_obj.fields.values()[extra.field_index];
9433 const field_llvm_ty = try self.dg.lowerType(field.ty);9228 const field_llvm_ty = try self.dg.lowerType(field.ty);
9434 const field_size = field.ty.abiSize(target);9229 const field_size = field.ty.abiSize(mod);
9435 const field_align = field.normalAlignment(target);9230 const field_align = field.normalAlignment(mod);
94369231
9437 const llvm_union_ty = t: {9232 const llvm_union_ty = t: {
9438 const payload = p: {9233 const payload = p: {
9439 if (!field.ty.hasRuntimeBitsIgnoreComptime()) {9234 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) {
9440 const padding_len = @intCast(c_uint, layout.payload_size);9235 const padding_len = @intCast(c_uint, layout.payload_size);
9441 break :p self.context.intType(8).arrayType(padding_len);9236 break :p self.context.intType(8).arrayType(padding_len);
9442 }9237 }
...@@ -9472,14 +9267,12 @@ pub const FuncGen = struct {...@@ -9472,14 +9267,12 @@ pub const FuncGen = struct {
9472 // tag and the payload.9267 // tag and the payload.
9473 const index_type = self.context.intType(32);9268 const index_type = self.context.intType(32);
94749269
9475 var field_ptr_payload: Type.Payload.Pointer = .{9270 const field_ptr_ty = try mod.ptrType(.{
9476 .data = .{9271 .child = field.ty.toIntern(),
9477 .pointee_type = field.ty,9272 .flags = .{
9478 .@"align" = field_align,9273 .alignment = InternPool.Alignment.fromNonzeroByteUnits(field_align),
9479 .@"addrspace" = .generic,
9480 },9274 },
9481 };9275 });
9482 const field_ptr_ty = Type.initPayload(&field_ptr_payload.base);
9483 if (layout.tag_size == 0) {9276 if (layout.tag_size == 0) {
9484 const indices: [3]*llvm.Value = .{9277 const indices: [3]*llvm.Value = .{
9485 index_type.constNull(),9278 index_type.constNull(),
...@@ -9511,7 +9304,7 @@ pub const FuncGen = struct {...@@ -9511,7 +9304,7 @@ pub const FuncGen = struct {
9511 const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty);9304 const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty);
9512 const llvm_tag = tag_llvm_ty.constInt(tag_int, .False);9305 const llvm_tag = tag_llvm_ty.constInt(tag_int, .False);
9513 const store_inst = self.builder.buildStore(llvm_tag, field_ptr);9306 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));
9515 }9308 }
95169309
9517 return result_ptr;9310 return result_ptr;
...@@ -9535,7 +9328,8 @@ pub const FuncGen = struct {...@@ -9535,7 +9328,8 @@ pub const FuncGen = struct {
9535 // by the target.9328 // by the target.
9536 // To work around this, don't emit llvm.prefetch in this case.9329 // To work around this, don't emit llvm.prefetch in this case.
9537 // See https://bugs.llvm.org/show_bug.cgi?id=210379330 // 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();
9539 switch (prefetch.cache) {9333 switch (prefetch.cache) {
9540 .instruction => switch (target.cpu.arch) {9334 .instruction => switch (target.cpu.arch) {
9541 .x86_64,9335 .x86_64,
...@@ -9584,7 +9378,7 @@ pub const FuncGen = struct {...@@ -9584,7 +9378,7 @@ pub const FuncGen = struct {
95849378
9585 fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9379 fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9586 const ty_op = self.air.instructions.items(.data)[inst].ty_op;9380 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);
9588 const operand = try self.resolveInst(ty_op.operand);9382 const operand = try self.resolveInst(ty_op.operand);
95899383
9590 const llvm_dest_ty = try self.dg.lowerType(inst_ty);9384 const llvm_dest_ty = try self.dg.lowerType(inst_ty);
...@@ -9658,8 +9452,9 @@ pub const FuncGen = struct {...@@ -9658,8 +9452,9 @@ pub const FuncGen = struct {
9658 return table;9452 return table;
9659 }9453 }
96609454
9661 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);9455 const mod = self.dg.module;
9662 const slice_alignment = slice_ty.abiAlignment(self.dg.module.getTarget());9456 const slice_ty = Type.slice_const_u8_sentinel_0;
9457 const slice_alignment = slice_ty.abiAlignment(mod);
9663 const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space9458 const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space
96649459
9665 const error_name_table_global = self.dg.object.llvm_module.addGlobal(llvm_slice_ptr_ty, "__zig_err_name_table");9460 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 {...@@ -9701,16 +9496,15 @@ pub const FuncGen = struct {
9701 opt_ty: Type,9496 opt_ty: Type,
9702 can_elide_load: bool,9497 can_elide_load: bool,
9703 ) !*llvm.Value {9498 ) !*llvm.Value {
9704 var buf: Type.Payload.ElemType = undefined;9499 const mod = fg.dg.module;
9705 const payload_ty = opt_ty.optionalChild(&buf);9500 const payload_ty = opt_ty.optionalChild(mod);
97069501
9707 if (isByRef(opt_ty)) {9502 if (isByRef(opt_ty, mod)) {
9708 // We have a pointer and we need to return a pointer to the first field.9503 // We have a pointer and we need to return a pointer to the first field.
9709 const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, "");9504 const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, "");
97109505
9711 const target = fg.dg.module.getTarget();9506 const payload_alignment = payload_ty.abiAlignment(mod);
9712 const payload_alignment = payload_ty.abiAlignment(target);9507 if (isByRef(payload_ty, mod)) {
9713 if (isByRef(payload_ty)) {
9714 if (can_elide_load)9508 if (can_elide_load)
9715 return payload_ptr;9509 return payload_ptr;
97169510
...@@ -9722,7 +9516,7 @@ pub const FuncGen = struct {...@@ -9722,7 +9516,7 @@ pub const FuncGen = struct {
9722 return load_inst;9516 return load_inst;
9723 }9517 }
97249518
9725 assert(!isByRef(payload_ty));9519 assert(!isByRef(payload_ty, mod));
9726 return fg.builder.buildExtractValue(opt_handle, 0, "");9520 return fg.builder.buildExtractValue(opt_handle, 0, "");
9727 }9521 }
97289522
...@@ -9734,10 +9528,10 @@ pub const FuncGen = struct {...@@ -9734,10 +9528,10 @@ pub const FuncGen = struct {
9734 ) !?*llvm.Value {9528 ) !?*llvm.Value {
9735 const optional_llvm_ty = try self.dg.lowerType(optional_ty);9529 const optional_llvm_ty = try self.dg.lowerType(optional_ty);
9736 const non_null_field = self.builder.buildZExt(non_null_bit, self.context.intType(8), "");9530 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)) {9533 if (isByRef(optional_ty, mod)) {
9739 const target = self.dg.module.getTarget();9534 const payload_alignment = optional_ty.abiAlignment(mod);
9740 const payload_alignment = optional_ty.abiAlignment(target);
9741 const alloca_inst = self.buildAlloca(optional_llvm_ty, payload_alignment);9535 const alloca_inst = self.buildAlloca(optional_llvm_ty, payload_alignment);
97429536
9743 {9537 {
...@@ -9765,13 +9559,13 @@ pub const FuncGen = struct {...@@ -9765,13 +9559,13 @@ pub const FuncGen = struct {
9765 struct_ptr_ty: Type,9559 struct_ptr_ty: Type,
9766 field_index: u32,9560 field_index: u32,
9767 ) !?*llvm.Value {9561 ) !?*llvm.Value {
9768 const target = self.dg.object.target;9562 const mod = self.dg.module;
9769 const struct_ty = struct_ptr_ty.childType();9563 const struct_ty = struct_ptr_ty.childType(mod);
9770 switch (struct_ty.zigTypeTag()) {9564 switch (struct_ty.zigTypeTag(mod)) {
9771 .Struct => switch (struct_ty.containerLayout()) {9565 .Struct => switch (struct_ty.containerLayout(mod)) {
9772 .Packed => {9566 .Packed => {
9773 const result_ty = self.air.typeOfIndex(inst);9567 const result_ty = self.typeOfIndex(inst);
9774 const result_ty_info = result_ty.ptrInfo().data;9568 const result_ty_info = result_ty.ptrInfo(mod);
97759569
9776 if (result_ty_info.host_size != 0) {9570 if (result_ty_info.host_size != 0) {
9777 // From LLVM's perspective, a pointer to a packed struct and a pointer9571 // From LLVM's perspective, a pointer to a packed struct and a pointer
...@@ -9783,7 +9577,7 @@ pub const FuncGen = struct {...@@ -9783,7 +9577,7 @@ pub const FuncGen = struct {
97839577
9784 // We have a pointer to a packed struct field that happens to be byte-aligned.9578 // We have a pointer to a packed struct field that happens to be byte-aligned.
9785 // Offset our operand pointer by the correct number of bytes.9579 // 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);
9787 if (byte_offset == 0) return struct_ptr;9581 if (byte_offset == 0) return struct_ptr;
9788 const byte_llvm_ty = self.context.intType(8);9582 const byte_llvm_ty = self.context.intType(8);
9789 const llvm_usize = try self.dg.lowerType(Type.usize);9583 const llvm_usize = try self.dg.lowerType(Type.usize);
...@@ -9794,24 +9588,23 @@ pub const FuncGen = struct {...@@ -9794,24 +9588,23 @@ pub const FuncGen = struct {
9794 else => {9588 else => {
9795 const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty);9589 const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty);
97969590
9797 var ty_buf: Type.Payload.Pointer = undefined;9591 if (llvmField(struct_ty, field_index, mod)) |llvm_field| {
9798 if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| {9592 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field.index, "");
9799 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, "");
9800 } else {9593 } else {
9801 // If we found no index then this means this is a zero sized field at the9594 // If we found no index then this means this is a zero sized field at the
9802 // end of the struct. Treat our struct pointer as an array of two and get9595 // end of the struct. Treat our struct pointer as an array of two and get
9803 // the index to the element at index `1` to get a pointer to the end of9596 // the index to the element at index `1` to get a pointer to the end of
9804 // the struct.9597 // the struct.
9805 const llvm_u32 = self.context.intType(32);9598 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);
9807 const indices: [1]*llvm.Value = .{llvm_index};9600 const indices: [1]*llvm.Value = .{llvm_index};
9808 return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, "");9601 return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, "");
9809 }9602 }
9810 },9603 },
9811 },9604 },
9812 .Union => {9605 .Union => {
9813 const layout = struct_ty.unionGetLayout(target);9606 const layout = struct_ty.unionGetLayout(mod);
9814 if (layout.payload_size == 0 or struct_ty.containerLayout() == .Packed) return struct_ptr;9607 if (layout.payload_size == 0 or struct_ty.containerLayout(mod) == .Packed) return struct_ptr;
9815 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);9608 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
9816 const union_llvm_ty = try self.dg.lowerType(struct_ty);9609 const union_llvm_ty = try self.dg.lowerType(struct_ty);
9817 const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, "");9610 const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, "");
...@@ -9835,12 +9628,12 @@ pub const FuncGen = struct {...@@ -9835,12 +9628,12 @@ pub const FuncGen = struct {
9835 ptr_alignment: u32,9628 ptr_alignment: u32,
9836 is_volatile: bool,9629 is_volatile: bool,
9837 ) !*llvm.Value {9630 ) !*llvm.Value {
9631 const mod = fg.dg.module;
9838 const pointee_llvm_ty = try fg.dg.lowerType(pointee_type);9632 const pointee_llvm_ty = try fg.dg.lowerType(pointee_type);
9839 const target = fg.dg.module.getTarget();9633 const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod));
9840 const result_align = @max(ptr_alignment, pointee_type.abiAlignment(target));
9841 const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align);9634 const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align);
9842 const llvm_usize = fg.context.intType(Type.usize.intInfo(target).bits);9635 const llvm_usize = fg.context.intType(Type.usize.intInfo(mod).bits);
9843 const size_bytes = pointee_type.abiSize(target);9636 const size_bytes = pointee_type.abiSize(mod);
9844 _ = fg.builder.buildMemCpy(9637 _ = fg.builder.buildMemCpy(
9845 result_ptr,9638 result_ptr,
9846 result_align,9639 result_align,
...@@ -9856,12 +9649,12 @@ pub const FuncGen = struct {...@@ -9856,12 +9649,12 @@ pub const FuncGen = struct {
9856 /// alloca and copies the value into it, then returns the alloca instruction.9649 /// alloca and copies the value into it, then returns the alloca instruction.
9857 /// For isByRef=false types, it creates a load instruction and returns it.9650 /// For isByRef=false types, it creates a load instruction and returns it.
9858 fn load(self: *FuncGen, ptr: *llvm.Value, ptr_ty: Type) !?*llvm.Value {9651 fn load(self: *FuncGen, ptr: *llvm.Value, ptr_ty: Type) !?*llvm.Value {
9859 const info = ptr_ty.ptrInfo().data;9652 const mod = self.dg.module;
9860 if (!info.pointee_type.hasRuntimeBitsIgnoreComptime()) return null;9653 const info = ptr_ty.ptrInfo(mod);
9654 if (!info.pointee_type.hasRuntimeBitsIgnoreComptime(mod)) return null;
98619655
9862 const target = self.dg.module.getTarget();9656 const ptr_alignment = info.alignment(mod);
9863 const ptr_alignment = info.alignment(target);9657 const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr(mod));
9864 const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr());
98659658
9866 assert(info.vector_index != .runtime);9659 assert(info.vector_index != .runtime);
9867 if (info.vector_index != .none) {9660 if (info.vector_index != .none) {
...@@ -9877,7 +9670,7 @@ pub const FuncGen = struct {...@@ -9877,7 +9670,7 @@ pub const FuncGen = struct {
9877 }9670 }
98789671
9879 if (info.host_size == 0) {9672 if (info.host_size == 0) {
9880 if (isByRef(info.pointee_type)) {9673 if (isByRef(info.pointee_type, mod)) {
9881 return self.loadByRef(ptr, info.pointee_type, ptr_alignment, info.@"volatile");9674 return self.loadByRef(ptr, info.pointee_type, ptr_alignment, info.@"volatile");
9882 }9675 }
9883 const elem_llvm_ty = try self.dg.lowerType(info.pointee_type);9676 const elem_llvm_ty = try self.dg.lowerType(info.pointee_type);
...@@ -9892,13 +9685,13 @@ pub const FuncGen = struct {...@@ -9892,13 +9685,13 @@ pub const FuncGen = struct {
9892 containing_int.setAlignment(ptr_alignment);9685 containing_int.setAlignment(ptr_alignment);
9893 containing_int.setVolatile(ptr_volatile);9686 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));
9896 const shift_amt = containing_int.typeOf().constInt(info.bit_offset, .False);9689 const shift_amt = containing_int.typeOf().constInt(info.bit_offset, .False);
9897 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");9690 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");
9898 const elem_llvm_ty = try self.dg.lowerType(info.pointee_type);9691 const elem_llvm_ty = try self.dg.lowerType(info.pointee_type);
98999692
9900 if (isByRef(info.pointee_type)) {9693 if (isByRef(info.pointee_type, mod)) {
9901 const result_align = info.pointee_type.abiAlignment(target);9694 const result_align = info.pointee_type.abiAlignment(mod);
9902 const result_ptr = self.buildAlloca(elem_llvm_ty, result_align);9695 const result_ptr = self.buildAlloca(elem_llvm_ty, result_align);
99039696
9904 const same_size_int = self.context.intType(elem_bits);9697 const same_size_int = self.context.intType(elem_bits);
...@@ -9908,13 +9701,13 @@ pub const FuncGen = struct {...@@ -9908,13 +9701,13 @@ pub const FuncGen = struct {
9908 return result_ptr;9701 return result_ptr;
9909 }9702 }
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) {
9912 const same_size_int = self.context.intType(elem_bits);9705 const same_size_int = self.context.intType(elem_bits);
9913 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");9706 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
9914 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");9707 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
9915 }9708 }
99169709
9917 if (info.pointee_type.isPtrAtRuntime()) {9710 if (info.pointee_type.isPtrAtRuntime(mod)) {
9918 const same_size_int = self.context.intType(elem_bits);9711 const same_size_int = self.context.intType(elem_bits);
9919 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");9712 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
9920 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");9713 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
...@@ -9930,13 +9723,13 @@ pub const FuncGen = struct {...@@ -9930,13 +9723,13 @@ pub const FuncGen = struct {
9930 elem: *llvm.Value,9723 elem: *llvm.Value,
9931 ordering: llvm.AtomicOrdering,9724 ordering: llvm.AtomicOrdering,
9932 ) !void {9725 ) !void {
9933 const info = ptr_ty.ptrInfo().data;9726 const mod = self.dg.module;
9727 const info = ptr_ty.ptrInfo(mod);
9934 const elem_ty = info.pointee_type;9728 const elem_ty = info.pointee_type;
9935 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) {9729 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
9936 return;9730 return;
9937 }9731 }
9938 const target = self.dg.module.getTarget();9732 const ptr_alignment = ptr_ty.ptrAlignment(mod);
9939 const ptr_alignment = ptr_ty.ptrAlignment(target);
9940 const ptr_volatile = llvm.Bool.fromBool(info.@"volatile");9733 const ptr_volatile = llvm.Bool.fromBool(info.@"volatile");
99419734
9942 assert(info.vector_index != .runtime);9735 assert(info.vector_index != .runtime);
...@@ -9964,13 +9757,13 @@ pub const FuncGen = struct {...@@ -9964,13 +9757,13 @@ pub const FuncGen = struct {
9964 assert(ordering == .NotAtomic);9757 assert(ordering == .NotAtomic);
9965 containing_int.setAlignment(ptr_alignment);9758 containing_int.setAlignment(ptr_alignment);
9966 containing_int.setVolatile(ptr_volatile);9759 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));
9968 const containing_int_ty = containing_int.typeOf();9761 const containing_int_ty = containing_int.typeOf();
9969 const shift_amt = containing_int_ty.constInt(info.bit_offset, .False);9762 const shift_amt = containing_int_ty.constInt(info.bit_offset, .False);
9970 // Convert to equally-sized integer type in order to perform the bit9763 // Convert to equally-sized integer type in order to perform the bit
9971 // operations on the value to store9764 // operations on the value to store
9972 const value_bits_type = self.context.intType(elem_bits);9765 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))
9974 self.builder.buildPtrToInt(elem, value_bits_type, "")9767 self.builder.buildPtrToInt(elem, value_bits_type, "")
9975 else9768 else
9976 self.builder.buildBitCast(elem, value_bits_type, "");9769 self.builder.buildBitCast(elem, value_bits_type, "");
...@@ -9991,7 +9784,7 @@ pub const FuncGen = struct {...@@ -9991,7 +9784,7 @@ pub const FuncGen = struct {
9991 store_inst.setVolatile(ptr_volatile);9784 store_inst.setVolatile(ptr_volatile);
9992 return;9785 return;
9993 }9786 }
9994 if (!isByRef(elem_ty)) {9787 if (!isByRef(elem_ty, mod)) {
9995 const store_inst = self.builder.buildStore(elem, ptr);9788 const store_inst = self.builder.buildStore(elem, ptr);
9996 store_inst.setOrdering(ordering);9789 store_inst.setOrdering(ordering);
9997 store_inst.setAlignment(ptr_alignment);9790 store_inst.setAlignment(ptr_alignment);
...@@ -9999,13 +9792,13 @@ pub const FuncGen = struct {...@@ -9999,13 +9792,13 @@ pub const FuncGen = struct {
9999 return;9792 return;
10000 }9793 }
10001 assert(ordering == .NotAtomic);9794 assert(ordering == .NotAtomic);
10002 const size_bytes = elem_ty.abiSize(target);9795 const size_bytes = elem_ty.abiSize(mod);
10003 _ = self.builder.buildMemCpy(9796 _ = self.builder.buildMemCpy(
10004 ptr,9797 ptr,
10005 ptr_alignment,9798 ptr_alignment,
10006 elem,9799 elem,
10007 elem_ty.abiAlignment(target),9800 elem_ty.abiAlignment(mod),
10008 self.context.intType(Type.usize.intInfo(target).bits).constInt(size_bytes, .False),9801 self.context.intType(Type.usize.intInfo(mod).bits).constInt(size_bytes, .False),
10009 info.@"volatile",9802 info.@"volatile",
10010 );9803 );
10011 }9804 }
...@@ -10030,11 +9823,12 @@ pub const FuncGen = struct {...@@ -10030,11 +9823,12 @@ pub const FuncGen = struct {
10030 a4: *llvm.Value,9823 a4: *llvm.Value,
10031 a5: *llvm.Value,9824 a5: *llvm.Value,
10032 ) *llvm.Value {9825 ) *llvm.Value {
10033 const target = fg.dg.module.getTarget();9826 const mod = fg.dg.module;
9827 const target = mod.getTarget();
10034 if (!target_util.hasValgrindSupport(target)) return default_value;9828 if (!target_util.hasValgrindSupport(target)) return default_value;
100359829
10036 const usize_llvm_ty = fg.context.intType(target.ptrBitWidth());9830 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
10039 const array_llvm_ty = usize_llvm_ty.arrayType(6);9833 const array_llvm_ty = usize_llvm_ty.arrayType(6);
10040 const array_ptr = fg.valgrind_client_request_array orelse a: {9834 const array_ptr = fg.valgrind_client_request_array orelse a: {
...@@ -10111,6 +9905,16 @@ pub const FuncGen = struct {...@@ -10111,6 +9905,16 @@ pub const FuncGen = struct {
10111 );9905 );
10112 return call;9906 return call;
10113 }9907 }
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 }
10114};9918};
101159919
10116fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void {9920fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void {
...@@ -10444,62 +10248,64 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ...@@ -10444,62 +10248,64 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ
10444 };10248 };
10445}10249}
1044610250
10251const LlvmField = struct {
10252 index: c_uint,
10253 ty: Type,
10254 alignment: u32,
10255};
10256
10447/// Take into account 0 bit fields and padding. Returns null if an llvm10257/// Take into account 0 bit fields and padding. Returns null if an llvm
10448/// field could not be found.10258/// field could not be found.
10449/// This only happens if you want the field index of a zero sized field at10259/// This only happens if you want the field index of a zero sized field at
10450/// the end of the struct.10260/// the end of the struct.
10451fn llvmFieldIndex(10261fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
10452 ty: Type,
10453 field_index: usize,
10454 target: std.Target,
10455 ptr_pl_buf: *Type.Payload.Pointer,
10456) ?c_uint {
10457 // Detects where we inserted extra padding fields so that we can skip10262 // Detects where we inserted extra padding fields so that we can skip
10458 // over them in this function.10263 // over them in this function.
10459 comptime assert(struct_layout_version == 2);10264 comptime assert(struct_layout_version == 2);
10460 var offset: u64 = 0;10265 var offset: u64 = 0;
10461 var big_align: u32 = 0;10266 var big_align: u32 = 0;
1046210267
10463 if (ty.isSimpleTupleOrAnonStruct()) {10268 const struct_type = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
10464 const tuple = ty.tupleFields();10269 .anon_struct_type => |tuple| {
10465 var llvm_field_index: c_uint = 0;10270 var llvm_field_index: c_uint = 0;
10466 for (tuple.types, 0..) |field_ty, i| {10271 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
10467 if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;10272 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1046810273
10469 const field_align = field_ty.abiAlignment(target);10274 const field_align = field_ty.toType().abiAlignment(mod);
10470 big_align = @max(big_align, field_align);10275 big_align = @max(big_align, field_align);
10471 const prev_offset = offset;10276 const prev_offset = offset;
10472 offset = std.mem.alignForwardGeneric(u64, offset, field_align);10277 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1047310278
10474 const padding_len = offset - prev_offset;10279 const padding_len = offset - prev_offset;
10475 if (padding_len > 0) {10280 if (padding_len > 0) {
10476 llvm_field_index += 1;10281 llvm_field_index += 1;
10477 }10282 }
1047810283
10479 if (field_index <= i) {10284 if (field_index <= i) {
10480 ptr_pl_buf.* = .{10285 return .{
10481 .data = .{10286 .index = llvm_field_index,
10482 .pointee_type = field_ty,10287 .ty = field_ty.toType(),
10483 .@"align" = field_align,10288 .alignment = field_align,
10484 .@"addrspace" = .generic,10289 };
10485 },10290 }
10486 };
10487 return llvm_field_index;
10488 }
1048910291
10490 llvm_field_index += 1;10292 llvm_field_index += 1;
10491 offset += field_ty.abiSize(target);10293 offset += field_ty.toType().abiSize(mod);
10492 }10294 }
10493 return null;10295 return null;
10494 }10296 },
10495 const layout = ty.containerLayout();10297 .struct_type => |s| s,
10298 else => unreachable,
10299 };
10300 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
10301 const layout = struct_obj.layout;
10496 assert(layout != .Packed);10302 assert(layout != .Packed);
1049710303
10498 var llvm_field_index: c_uint = 0;10304 var llvm_field_index: c_uint = 0;
10499 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator();10305 var it = struct_obj.runtimeFieldIterator(mod);
10500 while (it.next()) |field_and_index| {10306 while (it.next()) |field_and_index| {
10501 const field = field_and_index.field;10307 const field = field_and_index.field;
10502 const field_align = field.alignment(target, layout);10308 const field_align = field.alignment(mod, layout);
10503 big_align = @max(big_align, field_align);10309 big_align = @max(big_align, field_align);
10504 const prev_offset = offset;10310 const prev_offset = offset;
10505 offset = std.mem.alignForwardGeneric(u64, offset, field_align);10311 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
...@@ -10510,54 +10316,52 @@ fn llvmFieldIndex(...@@ -10510,54 +10316,52 @@ fn llvmFieldIndex(
10510 }10316 }
1051110317
10512 if (field_index == field_and_index.index) {10318 if (field_index == field_and_index.index) {
10513 ptr_pl_buf.* = .{10319 return .{
10514 .data = .{10320 .index = llvm_field_index,
10515 .pointee_type = field.ty,10321 .ty = field.ty,
10516 .@"align" = field_align,10322 .alignment = field_align,
10517 .@"addrspace" = .generic,
10518 },
10519 };10323 };
10520 return llvm_field_index;
10521 }10324 }
1052210325
10523 llvm_field_index += 1;10326 llvm_field_index += 1;
10524 offset += field.ty.abiSize(target);10327 offset += field.ty.abiSize(mod);
10525 } else {10328 } else {
10526 // We did not find an llvm field that corresponds to this zig field.10329 // We did not find an llvm field that corresponds to this zig field.
10527 return null;10330 return null;
10528 }10331 }
10529}10332}
1053010333
10531fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool {10334fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {
10532 if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime()) return false;10335 if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false;
1053310336
10337 const target = mod.getTarget();
10534 switch (fn_info.cc) {10338 switch (fn_info.cc) {
10535 .Unspecified, .Inline => return isByRef(fn_info.return_type),10339 .Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod),
10536 .C => switch (target.cpu.arch) {10340 .C => switch (target.cpu.arch) {
10537 .mips, .mipsel => return false,10341 .mips, .mipsel => return false,
10538 .x86_64 => switch (target.os.tag) {10342 .x86_64 => switch (target.os.tag) {
10539 .windows => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,10343 .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10540 else => return firstParamSRetSystemV(fn_info.return_type, target),10344 else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10541 },10345 },
10542 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect,10346 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect,
10543 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory,10347 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
10544 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, target, .ret)) {10348 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) {
10545 .memory, .i64_array => return true,10349 .memory, .i64_array => return true,
10546 .i32_array => |size| return size != 1,10350 .i32_array => |size| return size != 1,
10547 .byval => return false,10351 .byval => return false,
10548 },10352 },
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,
10550 else => return false, // TODO investigate C ABI for other architectures10354 else => return false, // TODO investigate C ABI for other architectures
10551 },10355 },
10552 .SysV => return firstParamSRetSystemV(fn_info.return_type, target),10356 .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10553 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,10357 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10554 .Stdcall => return !isScalar(fn_info.return_type),10358 .Stdcall => return !isScalar(mod, fn_info.return_type.toType()),
10555 else => return false,10359 else => return false,
10556 }10360 }
10557}10361}
1055810362
10559fn firstParamSRetSystemV(ty: Type, target: std.Target) bool {10363fn firstParamSRetSystemV(ty: Type, mod: *Module) bool {
10560 const class = x86_64_abi.classifySystemV(ty, target, .ret);10364 const class = x86_64_abi.classifySystemV(ty, mod, .ret);
10561 if (class[0] == .memory) return true;10365 if (class[0] == .memory) return true;
10562 if (class[0] == .x87 and class[2] != .none) return true;10366 if (class[0] == .x87 and class[2] != .none) return true;
10563 return false;10367 return false;
...@@ -10566,75 +10370,77 @@ fn firstParamSRetSystemV(ty: Type, target: std.Target) bool {...@@ -10566,75 +10370,77 @@ fn firstParamSRetSystemV(ty: Type, target: std.Target) bool {
10566/// In order to support the C calling convention, some return types need to be lowered10370/// In order to support the C calling convention, some return types need to be lowered
10567/// completely differently in the function prototype to honor the C ABI, and then10371/// completely differently in the function prototype to honor the C ABI, and then
10568/// be effectively bitcasted to the actual return type.10372/// be effectively bitcasted to the actual return type.
10569fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {10373fn lowerFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10570 if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime()) {10374 const mod = dg.module;
10375 const return_type = fn_info.return_type.toType();
10376 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
10571 // If the return type is an error set or an error union, then we make this10377 // If the return type is an error set or an error union, then we make this
10572 // anyerror return type instead, so that it can be coerced into a function10378 // anyerror return type instead, so that it can be coerced into a function
10573 // pointer type which has anyerror as the return type.10379 // pointer type which has anyerror as the return type.
10574 if (fn_info.return_type.isError()) {10380 if (return_type.isError(mod)) {
10575 return dg.lowerType(Type.anyerror);10381 return dg.lowerType(Type.anyerror);
10576 } else {10382 } else {
10577 return dg.context.voidType();10383 return dg.context.voidType();
10578 }10384 }
10579 }10385 }
10580 const target = dg.module.getTarget();10386 const target = mod.getTarget();
10581 switch (fn_info.cc) {10387 switch (fn_info.cc) {
10582 .Unspecified, .Inline => {10388 .Unspecified, .Inline => {
10583 if (isByRef(fn_info.return_type)) {10389 if (isByRef(return_type, mod)) {
10584 return dg.context.voidType();10390 return dg.context.voidType();
10585 } else {10391 } else {
10586 return dg.lowerType(fn_info.return_type);10392 return dg.lowerType(return_type);
10587 }10393 }
10588 },10394 },
10589 .C => {10395 .C => {
10590 switch (target.cpu.arch) {10396 switch (target.cpu.arch) {
10591 .mips, .mipsel => return dg.lowerType(fn_info.return_type),10397 .mips, .mipsel => return dg.lowerType(return_type),
10592 .x86_64 => switch (target.os.tag) {10398 .x86_64 => switch (target.os.tag) {
10593 .windows => return lowerWin64FnRetTy(dg, fn_info),10399 .windows => return lowerWin64FnRetTy(dg, fn_info),
10594 else => return lowerSystemVFnRetTy(dg, fn_info),10400 else => return lowerSystemVFnRetTy(dg, fn_info),
10595 },10401 },
10596 .wasm32 => {10402 .wasm32 => {
10597 if (isScalar(fn_info.return_type)) {10403 if (isScalar(mod, return_type)) {
10598 return dg.lowerType(fn_info.return_type);10404 return dg.lowerType(return_type);
10599 }10405 }
10600 const classes = wasm_c_abi.classifyType(fn_info.return_type, target);10406 const classes = wasm_c_abi.classifyType(return_type, mod);
10601 if (classes[0] == .indirect or classes[0] == .none) {10407 if (classes[0] == .indirect or classes[0] == .none) {
10602 return dg.context.voidType();10408 return dg.context.voidType();
10603 }10409 }
1060410410
10605 assert(classes[0] == .direct and classes[1] == .none);10411 assert(classes[0] == .direct and classes[1] == .none);
10606 const scalar_type = wasm_c_abi.scalarType(fn_info.return_type, target);10412 const scalar_type = wasm_c_abi.scalarType(return_type, mod);
10607 const abi_size = scalar_type.abiSize(target);10413 const abi_size = scalar_type.abiSize(mod);
10608 return dg.context.intType(@intCast(c_uint, abi_size * 8));10414 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10609 },10415 },
10610 .aarch64, .aarch64_be => {10416 .aarch64, .aarch64_be => {
10611 switch (aarch64_c_abi.classifyType(fn_info.return_type, target)) {10417 switch (aarch64_c_abi.classifyType(return_type, mod)) {
10612 .memory => return dg.context.voidType(),10418 .memory => return dg.context.voidType(),
10613 .float_array => return dg.lowerType(fn_info.return_type),10419 .float_array => return dg.lowerType(return_type),
10614 .byval => return dg.lowerType(fn_info.return_type),10420 .byval => return dg.lowerType(return_type),
10615 .integer => {10421 .integer => {
10616 const bit_size = fn_info.return_type.bitSize(target);10422 const bit_size = return_type.bitSize(mod);
10617 return dg.context.intType(@intCast(c_uint, bit_size));10423 return dg.context.intType(@intCast(c_uint, bit_size));
10618 },10424 },
10619 .double_integer => return dg.context.intType(64).arrayType(2),10425 .double_integer => return dg.context.intType(64).arrayType(2),
10620 }10426 }
10621 },10427 },
10622 .arm, .armeb => {10428 .arm, .armeb => {
10623 switch (arm_c_abi.classifyType(fn_info.return_type, target, .ret)) {10429 switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
10624 .memory, .i64_array => return dg.context.voidType(),10430 .memory, .i64_array => return dg.context.voidType(),
10625 .i32_array => |len| if (len == 1) {10431 .i32_array => |len| if (len == 1) {
10626 return dg.context.intType(32);10432 return dg.context.intType(32);
10627 } else {10433 } else {
10628 return dg.context.voidType();10434 return dg.context.voidType();
10629 },10435 },
10630 .byval => return dg.lowerType(fn_info.return_type),10436 .byval => return dg.lowerType(return_type),
10631 }10437 }
10632 },10438 },
10633 .riscv32, .riscv64 => {10439 .riscv32, .riscv64 => {
10634 switch (riscv_c_abi.classifyType(fn_info.return_type, target)) {10440 switch (riscv_c_abi.classifyType(return_type, mod)) {
10635 .memory => return dg.context.voidType(),10441 .memory => return dg.context.voidType(),
10636 .integer => {10442 .integer => {
10637 const bit_size = fn_info.return_type.bitSize(target);10443 const bit_size = return_type.bitSize(mod);
10638 return dg.context.intType(@intCast(c_uint, bit_size));10444 return dg.context.intType(@intCast(c_uint, bit_size));
10639 },10445 },
10640 .double_integer => {10446 .double_integer => {
...@@ -10644,50 +10450,52 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10644,50 +10450,52 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10644 };10450 };
10645 return dg.context.structType(&llvm_types_buffer, 2, .False);10451 return dg.context.structType(&llvm_types_buffer, 2, .False);
10646 },10452 },
10647 .byval => return dg.lowerType(fn_info.return_type),10453 .byval => return dg.lowerType(return_type),
10648 }10454 }
10649 },10455 },
10650 // TODO investigate C ABI for other architectures10456 // TODO investigate C ABI for other architectures
10651 else => return dg.lowerType(fn_info.return_type),10457 else => return dg.lowerType(return_type),
10652 }10458 }
10653 },10459 },
10654 .Win64 => return lowerWin64FnRetTy(dg, fn_info),10460 .Win64 => return lowerWin64FnRetTy(dg, fn_info),
10655 .SysV => return lowerSystemVFnRetTy(dg, fn_info),10461 .SysV => return lowerSystemVFnRetTy(dg, fn_info),
10656 .Stdcall => {10462 .Stdcall => {
10657 if (isScalar(fn_info.return_type)) {10463 if (isScalar(mod, return_type)) {
10658 return dg.lowerType(fn_info.return_type);10464 return dg.lowerType(return_type);
10659 } else {10465 } else {
10660 return dg.context.voidType();10466 return dg.context.voidType();
10661 }10467 }
10662 },10468 },
10663 else => return dg.lowerType(fn_info.return_type),10469 else => return dg.lowerType(return_type),
10664 }10470 }
10665}10471}
1066610472
10667fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {10473fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10668 const target = dg.module.getTarget();10474 const mod = dg.module;
10669 switch (x86_64_abi.classifyWindows(fn_info.return_type, target)) {10475 const return_type = fn_info.return_type.toType();
10476 switch (x86_64_abi.classifyWindows(return_type, mod)) {
10670 .integer => {10477 .integer => {
10671 if (isScalar(fn_info.return_type)) {10478 if (isScalar(mod, return_type)) {
10672 return dg.lowerType(fn_info.return_type);10479 return dg.lowerType(return_type);
10673 } else {10480 } else {
10674 const abi_size = fn_info.return_type.abiSize(target);10481 const abi_size = return_type.abiSize(mod);
10675 return dg.context.intType(@intCast(c_uint, abi_size * 8));10482 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10676 }10483 }
10677 },10484 },
10678 .win_i128 => return dg.context.intType(64).vectorType(2),10485 .win_i128 => return dg.context.intType(64).vectorType(2),
10679 .memory => return dg.context.voidType(),10486 .memory => return dg.context.voidType(),
10680 .sse => return dg.lowerType(fn_info.return_type),10487 .sse => return dg.lowerType(return_type),
10681 else => unreachable,10488 else => unreachable,
10682 }10489 }
10683}10490}
1068410491
10685fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {10492fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10686 if (isScalar(fn_info.return_type)) {10493 const mod = dg.module;
10687 return dg.lowerType(fn_info.return_type);10494 const return_type = fn_info.return_type.toType();
10495 if (isScalar(mod, return_type)) {
10496 return dg.lowerType(return_type);
10688 }10497 }
10689 const target = dg.module.getTarget();10498 const classes = x86_64_abi.classifySystemV(return_type, mod, .ret);
10690 const classes = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret);
10691 if (classes[0] == .memory) {10499 if (classes[0] == .memory) {
10692 return dg.context.voidType();10500 return dg.context.voidType();
10693 }10501 }
...@@ -10728,7 +10536,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm...@@ -10728,7 +10536,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
10728 }10536 }
10729 }10537 }
10730 if (classes[0] == .integer and classes[1] == .none) {10538 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);
10732 return dg.context.intType(@intCast(c_uint, abi_size * 8));10540 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10733 }10541 }
10734 return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False);10542 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...@@ -10736,10 +10544,9 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
1073610544
10737const ParamTypeIterator = struct {10545const ParamTypeIterator = struct {
10738 dg: *DeclGen,10546 dg: *DeclGen,
10739 fn_info: Type.Payload.Function.Data,10547 fn_info: InternPool.Key.FuncType,
10740 zig_index: u32,10548 zig_index: u32,
10741 llvm_index: u32,10549 llvm_index: u32,
10742 target: std.Target,
10743 llvm_types_len: u32,10550 llvm_types_len: u32,
10744 llvm_types_buffer: [8]*llvm.Type,10551 llvm_types_buffer: [8]*llvm.Type,
10745 byval_attr: bool,10552 byval_attr: bool,
...@@ -10762,7 +10569,7 @@ const ParamTypeIterator = struct {...@@ -10762,7 +10569,7 @@ const ParamTypeIterator = struct {
10762 if (it.zig_index >= it.fn_info.param_types.len) return null;10569 if (it.zig_index >= it.fn_info.param_types.len) return null;
10763 const ty = it.fn_info.param_types[it.zig_index];10570 const ty = it.fn_info.param_types[it.zig_index];
10764 it.byval_attr = false;10571 it.byval_attr = false;
10765 return nextInner(it, ty);10572 return nextInner(it, ty.toType());
10766 }10573 }
1076710574
10768 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.10575 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
...@@ -10771,15 +10578,18 @@ const ParamTypeIterator = struct {...@@ -10771,15 +10578,18 @@ const ParamTypeIterator = struct {
10771 if (it.zig_index >= args.len) {10578 if (it.zig_index >= args.len) {
10772 return null;10579 return null;
10773 } else {10580 } else {
10774 return nextInner(it, fg.air.typeOf(args[it.zig_index]));10581 return nextInner(it, fg.typeOf(args[it.zig_index]));
10775 }10582 }
10776 } else {10583 } 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());
10778 }10585 }
10779 }10586 }
1078010587
10781 fn nextInner(it: *ParamTypeIterator, ty: Type) ?Lowering {10588 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)) {
10783 it.zig_index += 1;10593 it.zig_index += 1;
10784 return .no_bits;10594 return .no_bits;
10785 }10595 }
...@@ -10787,11 +10597,10 @@ const ParamTypeIterator = struct {...@@ -10787,11 +10597,10 @@ const ParamTypeIterator = struct {
10787 .Unspecified, .Inline => {10597 .Unspecified, .Inline => {
10788 it.zig_index += 1;10598 it.zig_index += 1;
10789 it.llvm_index += 1;10599 it.llvm_index += 1;
10790 var buf: Type.Payload.ElemType = undefined;10600 if (ty.isSlice(mod) or (ty.zigTypeTag(mod) == .Optional and ty.optionalChild(mod).isSlice(mod))) {
10791 if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) {
10792 it.llvm_index += 1;10601 it.llvm_index += 1;
10793 return .slice;10602 return .slice;
10794 } else if (isByRef(ty)) {10603 } else if (isByRef(ty, mod)) {
10795 return .byref;10604 return .byref;
10796 } else {10605 } else {
10797 return .byval;10606 return .byval;
...@@ -10801,23 +10610,23 @@ const ParamTypeIterator = struct {...@@ -10801,23 +10610,23 @@ const ParamTypeIterator = struct {
10801 @panic("TODO implement async function lowering in the LLVM backend");10610 @panic("TODO implement async function lowering in the LLVM backend");
10802 },10611 },
10803 .C => {10612 .C => {
10804 switch (it.target.cpu.arch) {10613 switch (target.cpu.arch) {
10805 .mips, .mipsel => {10614 .mips, .mipsel => {
10806 it.zig_index += 1;10615 it.zig_index += 1;
10807 it.llvm_index += 1;10616 it.llvm_index += 1;
10808 return .byval;10617 return .byval;
10809 },10618 },
10810 .x86_64 => switch (it.target.os.tag) {10619 .x86_64 => switch (target.os.tag) {
10811 .windows => return it.nextWin64(ty),10620 .windows => return it.nextWin64(ty),
10812 else => return it.nextSystemV(ty),10621 else => return it.nextSystemV(ty),
10813 },10622 },
10814 .wasm32 => {10623 .wasm32 => {
10815 it.zig_index += 1;10624 it.zig_index += 1;
10816 it.llvm_index += 1;10625 it.llvm_index += 1;
10817 if (isScalar(ty)) {10626 if (isScalar(mod, ty)) {
10818 return .byval;10627 return .byval;
10819 }10628 }
10820 const classes = wasm_c_abi.classifyType(ty, it.target);10629 const classes = wasm_c_abi.classifyType(ty, mod);
10821 if (classes[0] == .indirect) {10630 if (classes[0] == .indirect) {
10822 return .byref;10631 return .byref;
10823 }10632 }
...@@ -10826,7 +10635,7 @@ const ParamTypeIterator = struct {...@@ -10826,7 +10635,7 @@ const ParamTypeIterator = struct {
10826 .aarch64, .aarch64_be => {10635 .aarch64, .aarch64_be => {
10827 it.zig_index += 1;10636 it.zig_index += 1;
10828 it.llvm_index += 1;10637 it.llvm_index += 1;
10829 switch (aarch64_c_abi.classifyType(ty, it.target)) {10638 switch (aarch64_c_abi.classifyType(ty, mod)) {
10830 .memory => return .byref_mut,10639 .memory => return .byref_mut,
10831 .float_array => |len| return Lowering{ .float_array = len },10640 .float_array => |len| return Lowering{ .float_array = len },
10832 .byval => return .byval,10641 .byval => return .byval,
...@@ -10841,7 +10650,7 @@ const ParamTypeIterator = struct {...@@ -10841,7 +10650,7 @@ const ParamTypeIterator = struct {
10841 .arm, .armeb => {10650 .arm, .armeb => {
10842 it.zig_index += 1;10651 it.zig_index += 1;
10843 it.llvm_index += 1;10652 it.llvm_index += 1;
10844 switch (arm_c_abi.classifyType(ty, it.target, .arg)) {10653 switch (arm_c_abi.classifyType(ty, mod, .arg)) {
10845 .memory => {10654 .memory => {
10846 it.byval_attr = true;10655 it.byval_attr = true;
10847 return .byref;10656 return .byref;
...@@ -10854,10 +10663,10 @@ const ParamTypeIterator = struct {...@@ -10854,10 +10663,10 @@ const ParamTypeIterator = struct {
10854 .riscv32, .riscv64 => {10663 .riscv32, .riscv64 => {
10855 it.zig_index += 1;10664 it.zig_index += 1;
10856 it.llvm_index += 1;10665 it.llvm_index += 1;
10857 if (ty.tag() == .f16) {10666 if (ty.toIntern() == .f16_type) {
10858 return .as_u16;10667 return .as_u16;
10859 }10668 }
10860 switch (riscv_c_abi.classifyType(ty, it.target)) {10669 switch (riscv_c_abi.classifyType(ty, mod)) {
10861 .memory => return .byref_mut,10670 .memory => return .byref_mut,
10862 .byval => return .byval,10671 .byval => return .byval,
10863 .integer => return .abi_sized_int,10672 .integer => return .abi_sized_int,
...@@ -10878,7 +10687,7 @@ const ParamTypeIterator = struct {...@@ -10878,7 +10687,7 @@ const ParamTypeIterator = struct {
10878 it.zig_index += 1;10687 it.zig_index += 1;
10879 it.llvm_index += 1;10688 it.llvm_index += 1;
1088010689
10881 if (isScalar(ty)) {10690 if (isScalar(mod, ty)) {
10882 return .byval;10691 return .byval;
10883 } else {10692 } else {
10884 it.byval_attr = true;10693 it.byval_attr = true;
...@@ -10894,9 +10703,10 @@ const ParamTypeIterator = struct {...@@ -10894,9 +10703,10 @@ const ParamTypeIterator = struct {
10894 }10703 }
1089510704
10896 fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {10705 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)) {
10898 .integer => {10708 .integer => {
10899 if (isScalar(ty)) {10709 if (isScalar(mod, ty)) {
10900 it.zig_index += 1;10710 it.zig_index += 1;
10901 it.llvm_index += 1;10711 it.llvm_index += 1;
10902 return .byval;10712 return .byval;
...@@ -10926,14 +10736,15 @@ const ParamTypeIterator = struct {...@@ -10926,14 +10736,15 @@ const ParamTypeIterator = struct {
10926 }10736 }
1092710737
10928 fn nextSystemV(it: *ParamTypeIterator, ty: Type) ?Lowering {10738 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);
10930 if (classes[0] == .memory) {10741 if (classes[0] == .memory) {
10931 it.zig_index += 1;10742 it.zig_index += 1;
10932 it.llvm_index += 1;10743 it.llvm_index += 1;
10933 it.byval_attr = true;10744 it.byval_attr = true;
10934 return .byref;10745 return .byref;
10935 }10746 }
10936 if (isScalar(ty)) {10747 if (isScalar(mod, ty)) {
10937 it.zig_index += 1;10748 it.zig_index += 1;
10938 it.llvm_index += 1;10749 it.llvm_index += 1;
10939 return .byval;10750 return .byval;
...@@ -10986,13 +10797,12 @@ const ParamTypeIterator = struct {...@@ -10986,13 +10797,12 @@ const ParamTypeIterator = struct {
10986 }10797 }
10987};10798};
1098810799
10989fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTypeIterator {10800fn iterateParamTypes(dg: *DeclGen, fn_info: InternPool.Key.FuncType) ParamTypeIterator {
10990 return .{10801 return .{
10991 .dg = dg,10802 .dg = dg,
10992 .fn_info = fn_info,10803 .fn_info = fn_info,
10993 .zig_index = 0,10804 .zig_index = 0,
10994 .llvm_index = 0,10805 .llvm_index = 0,
10995 .target = dg.module.getTarget(),
10996 .llvm_types_buffer = undefined,10806 .llvm_types_buffer = undefined,
10997 .llvm_types_len = 0,10807 .llvm_types_len = 0,
10998 .byval_attr = false,10808 .byval_attr = false,
...@@ -11001,16 +10811,17 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp...@@ -11001,16 +10811,17 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp
1100110811
11002fn ccAbiPromoteInt(10812fn ccAbiPromoteInt(
11003 cc: std.builtin.CallingConvention,10813 cc: std.builtin.CallingConvention,
11004 target: std.Target,10814 mod: *Module,
11005 ty: Type,10815 ty: Type,
11006) ?std.builtin.Signedness {10816) ?std.builtin.Signedness {
10817 const target = mod.getTarget();
11007 switch (cc) {10818 switch (cc) {
11008 .Unspecified, .Inline, .Async => return null,10819 .Unspecified, .Inline, .Async => return null,
11009 else => {},10820 else => {},
11010 }10821 }
11011 const int_info = switch (ty.zigTypeTag()) {10822 const int_info = switch (ty.zigTypeTag(mod)) {
11012 .Bool => Type.u1.intInfo(target),10823 .Bool => Type.u1.intInfo(mod),
11013 .Int, .Enum, .ErrorSet => ty.intInfo(target),10824 .Int, .Enum, .ErrorSet => ty.intInfo(mod),
11014 else => return null,10825 else => return null,
11015 };10826 };
11016 if (int_info.bits <= 16) return int_info.signedness;10827 if (int_info.bits <= 16) return int_info.signedness;
...@@ -11039,12 +10850,12 @@ fn ccAbiPromoteInt(...@@ -11039,12 +10850,12 @@ fn ccAbiPromoteInt(
1103910850
11040/// This is the one source of truth for whether a type is passed around as an LLVM pointer,10851/// This is the one source of truth for whether a type is passed around as an LLVM pointer,
11041/// or as an LLVM value.10852/// or as an LLVM value.
11042fn isByRef(ty: Type) bool {10853fn isByRef(ty: Type, mod: *Module) bool {
11043 // For tuples and structs, if there are more than this many non-void10854 // For tuples and structs, if there are more than this many non-void
11044 // fields, then we make it byref, otherwise byval.10855 // fields, then we make it byref, otherwise byval.
11045 const max_fields_byval = 0;10856 const max_fields_byval = 0;
1104610857
11047 switch (ty.zigTypeTag()) {10858 switch (ty.zigTypeTag(mod)) {
11048 .Type,10859 .Type,
11049 .ComptimeInt,10860 .ComptimeInt,
11050 .ComptimeFloat,10861 .ComptimeFloat,
...@@ -11067,51 +10878,53 @@ fn isByRef(ty: Type) bool {...@@ -11067,51 +10878,53 @@ fn isByRef(ty: Type) bool {
11067 .AnyFrame,10878 .AnyFrame,
11068 => return false,10879 => return false,
1106910880
11070 .Array, .Frame => return ty.hasRuntimeBits(),10881 .Array, .Frame => return ty.hasRuntimeBits(mod),
11071 .Struct => {10882 .Struct => {
11072 // Packed structs are represented to LLVM as integers.10883 // Packed structs are represented to LLVM as integers.
11073 if (ty.containerLayout() == .Packed) return false;10884 if (ty.containerLayout(mod) == .Packed) return false;
11074 if (ty.isSimpleTupleOrAnonStruct()) {10885 const struct_type = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
11075 const tuple = ty.tupleFields();10886 .anon_struct_type => |tuple| {
11076 var count: usize = 0;10887 var count: usize = 0;
11077 for (tuple.values, 0..) |field_val, i| {10888 for (tuple.types, tuple.values) |field_ty, field_val| {
11078 if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue;10889 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1107910890
11080 count += 1;10891 count += 1;
11081 if (count > max_fields_byval) return true;10892 if (count > max_fields_byval) return true;
11082 if (isByRef(tuple.types[i])) return true;10893 if (isByRef(field_ty.toType(), mod)) return true;
11083 }10894 }
11084 return false;10895 return false;
11085 }10896 },
10897 .struct_type => |s| s,
10898 else => unreachable,
10899 };
10900 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
11086 var count: usize = 0;10901 var count: usize = 0;
11087 const fields = ty.structFields();10902 for (struct_obj.fields.values()) |field| {
11088 for (fields.values()) |field| {10903 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
11089 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
1109010904
11091 count += 1;10905 count += 1;
11092 if (count > max_fields_byval) return true;10906 if (count > max_fields_byval) return true;
11093 if (isByRef(field.ty)) return true;10907 if (isByRef(field.ty, mod)) return true;
11094 }10908 }
11095 return false;10909 return false;
11096 },10910 },
11097 .Union => switch (ty.containerLayout()) {10911 .Union => switch (ty.containerLayout(mod)) {
11098 .Packed => return false,10912 .Packed => return false,
11099 else => return ty.hasRuntimeBits(),10913 else => return ty.hasRuntimeBits(mod),
11100 },10914 },
11101 .ErrorUnion => {10915 .ErrorUnion => {
11102 const payload_ty = ty.errorUnionPayload();10916 const payload_ty = ty.errorUnionPayload(mod);
11103 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {10917 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
11104 return false;10918 return false;
11105 }10919 }
11106 return true;10920 return true;
11107 },10921 },
11108 .Optional => {10922 .Optional => {
11109 var buf: Type.Payload.ElemType = undefined;10923 const payload_ty = ty.optionalChild(mod);
11110 const payload_ty = ty.optionalChild(&buf);10924 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
11111 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
11112 return false;10925 return false;
11113 }10926 }
11114 if (ty.optionalReprIsPayload()) {10927 if (ty.optionalReprIsPayload(mod)) {
11115 return false;10928 return false;
11116 }10929 }
11117 return true;10930 return true;
...@@ -11119,8 +10932,8 @@ fn isByRef(ty: Type) bool {...@@ -11119,8 +10932,8 @@ fn isByRef(ty: Type) bool {
11119 }10932 }
11120}10933}
1112110934
11122fn isScalar(ty: Type) bool {10935fn isScalar(mod: *Module, ty: Type) bool {
11123 return switch (ty.zigTypeTag()) {10936 return switch (ty.zigTypeTag(mod)) {
11124 .Void,10937 .Void,
11125 .Bool,10938 .Bool,
11126 .NoReturn,10939 .NoReturn,
...@@ -11134,8 +10947,8 @@ fn isScalar(ty: Type) bool {...@@ -11134,8 +10947,8 @@ fn isScalar(ty: Type) bool {
11134 .Vector,10947 .Vector,
11135 => true,10948 => true,
1113610949
11137 .Struct => ty.containerLayout() == .Packed,10950 .Struct => ty.containerLayout(mod) == .Packed,
11138 .Union => ty.containerLayout() == .Packed,10951 .Union => ty.containerLayout(mod) == .Packed,
11139 else => false,10952 else => false,
11140 };10953 };
11141}10954}
...@@ -11184,10 +10997,10 @@ fn backendSupportsF128(target: std.Target) bool {...@@ -11184,10 +10997,10 @@ fn backendSupportsF128(target: std.Target) bool {
11184/// LLVM does not support all relevant intrinsics for all targets, so we10997/// LLVM does not support all relevant intrinsics for all targets, so we
11185/// may need to manually generate a libc call10998/// may need to manually generate a libc call
11186fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool {10999fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool {
11187 return switch (scalar_ty.tag()) {11000 return switch (scalar_ty.toIntern()) {
11188 .f16 => backendSupportsF16(target),11001 .f16_type => backendSupportsF16(target),
11189 .f80 => (target.c_type_bit_size(.longdouble) == 80) and backendSupportsF80(target),11002 .f80_type => (target.c_type_bit_size(.longdouble) == 80) and backendSupportsF80(target),
11190 .f128 => (target.c_type_bit_size(.longdouble) == 128) and backendSupportsF128(target),11003 .f128_type => (target.c_type_bit_size(.longdouble) == 128) and backendSupportsF128(target),
11191 else => true,11004 else => true,
11192 };11005 };
11193}11006}
...@@ -11304,12 +11117,12 @@ fn buildAllocaInner(...@@ -11304,12 +11117,12 @@ fn buildAllocaInner(
11304 return alloca;11117 return alloca;
11305}11118}
1130611119
11307fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 {11120fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 {
11308 return @boolToInt(Type.anyerror.abiAlignment(target) > payload_ty.abiAlignment(target));11121 return @boolToInt(Type.anyerror.abiAlignment(mod) > payload_ty.abiAlignment(mod));
11309}11122}
1131011123
11311fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 {11124fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u1 {
11312 return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target));11125 return @boolToInt(Type.anyerror.abiAlignment(mod) <= payload_ty.abiAlignment(mod));
11313}11126}
1131411127
11315/// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location11128/// 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 {...@@ -218,8 +218,9 @@ pub const DeclGen = struct {
218218
219 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {219 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
220 @setCold(true);220 @setCold(true);
221 const mod = self.module;
221 const src = LazySrcLoc.nodeOffset(0);222 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);
223 assert(self.error_msg == null);224 assert(self.error_msg == null);
224 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);225 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);
225 return error.CodegenFail;226 return error.CodegenFail;
...@@ -231,12 +232,13 @@ pub const DeclGen = struct {...@@ -231,12 +232,13 @@ pub const DeclGen = struct {
231232
232 /// Fetch the result-id for a previously generated instruction or constant.233 /// Fetch the result-id for a previously generated instruction or constant.
233 fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef {234 fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef {
234 if (self.air.value(inst)) |val| {235 const mod = self.module;
235 const ty = self.air.typeOf(inst);236 if (try self.air.value(inst, mod)) |val| {
236 if (ty.zigTypeTag() == .Fn) {237 const ty = self.typeOf(inst);
237 const fn_decl_index = switch (val.tag()) {238 if (ty.zigTypeTag(mod) == .Fn) {
238 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
239 .function => val.castTag(.function).?.data.owner_decl,240 .extern_func => |extern_func| extern_func.decl,
241 .func => |func| mod.funcPtr(func.index).owner_decl,
240 else => unreachable,242 else => unreachable,
241 };243 };
242 const spv_decl_index = try self.resolveDecl(fn_decl_index);244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
...@@ -254,12 +256,12 @@ pub const DeclGen = struct {...@@ -254,12 +256,12 @@ pub const DeclGen = struct {
254 /// Note: Function does not actually generate the decl.256 /// Note: Function does not actually generate the decl.
255 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
256 const decl = self.module.declPtr(decl_index);258 const decl = self.module.declPtr(decl_index);
257 self.module.markDeclAlive(decl);259 try self.module.markDeclAlive(decl);
258260
259 const entry = try self.decl_link.getOrPut(decl_index);261 const entry = try self.decl_link.getOrPut(decl_index);
260 if (!entry.found_existing) {262 if (!entry.found_existing) {
261 // TODO: Extern fn?263 // 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)
263 .func265 .func
264 else266 else
265 .global;267 .global;
...@@ -340,8 +342,9 @@ pub const DeclGen = struct {...@@ -340,8 +342,9 @@ pub const DeclGen = struct {
340 }342 }
341343
342 fn arithmeticTypeInfo(self: *DeclGen, ty: Type) !ArithmeticTypeInfo {344 fn arithmeticTypeInfo(self: *DeclGen, ty: Type) !ArithmeticTypeInfo {
345 const mod = self.module;
343 const target = self.getTarget();346 const target = self.getTarget();
344 return switch (ty.zigTypeTag()) {347 return switch (ty.zigTypeTag(mod)) {
345 .Bool => ArithmeticTypeInfo{348 .Bool => ArithmeticTypeInfo{
346 .bits = 1, // Doesn't matter for this class.349 .bits = 1, // Doesn't matter for this class.
347 .is_vector = false,350 .is_vector = false,
...@@ -355,7 +358,7 @@ pub const DeclGen = struct {...@@ -355,7 +358,7 @@ pub const DeclGen = struct {
355 .class = .float,358 .class = .float,
356 },359 },
357 .Int => blk: {360 .Int => blk: {
358 const int_info = ty.intInfo(target);361 const int_info = ty.intInfo(mod);
359 // TODO: Maybe it's useful to also return this value.362 // TODO: Maybe it's useful to also return this value.
360 const maybe_backing_bits = self.backingIntBits(int_info.bits);363 const maybe_backing_bits = self.backingIntBits(int_info.bits);
361 break :blk ArithmeticTypeInfo{364 break :blk ArithmeticTypeInfo{
...@@ -533,34 +536,35 @@ pub const DeclGen = struct {...@@ -533,34 +536,35 @@ pub const DeclGen = struct {
533 }536 }
534537
535 fn addInt(self: *@This(), ty: Type, val: Value) !void {538 fn addInt(self: *@This(), ty: Type, val: Value) !void {
536 const target = self.dg.getTarget();539 const mod = self.dg.module;
537 const int_info = ty.intInfo(target);540 const int_info = ty.intInfo(mod);
538 const int_bits = switch (int_info.signedness) {541 const int_bits = switch (int_info.signedness) {
539 .signed => @bitCast(u64, val.toSignedInt(target)),542 .signed => @bitCast(u64, val.toSignedInt(mod)),
540 .unsigned => val.toUnsignedInt(target),543 .unsigned => val.toUnsignedInt(mod),
541 };544 };
542545
543 // TODO: Swap endianess if the compiler is big endian.546 // TODO: Swap endianess if the compiler is big endian.
544 const len = ty.abiSize(target);547 const len = ty.abiSize(mod);
545 try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]);548 try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]);
546 }549 }
547550
548 fn addFloat(self: *@This(), ty: Type, val: Value) !void {551 fn addFloat(self: *@This(), ty: Type, val: Value) !void {
552 const mod = self.dg.module;
549 const target = self.dg.getTarget();553 const target = self.dg.getTarget();
550 const len = ty.abiSize(target);554 const len = ty.abiSize(mod);
551555
552 // TODO: Swap endianess if the compiler is big endian.556 // TODO: Swap endianess if the compiler is big endian.
553 switch (ty.floatBits(target)) {557 switch (ty.floatBits(target)) {
554 16 => {558 16 => {
555 const float_bits = val.toFloat(f16);559 const float_bits = val.toFloat(f16, mod);
556 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);560 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
557 },561 },
558 32 => {562 32 => {
559 const float_bits = val.toFloat(f32);563 const float_bits = val.toFloat(f32, mod);
560 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);564 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
561 },565 },
562 64 => {566 64 => {
563 const float_bits = val.toFloat(f64);567 const float_bits = val.toFloat(f64, mod);
564 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);568 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
565 },569 },
566 else => unreachable,570 else => unreachable,
...@@ -569,6 +573,7 @@ pub const DeclGen = struct {...@@ -569,6 +573,7 @@ pub const DeclGen = struct {
569573
570 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {574 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
571 const dg = self.dg;575 const dg = self.dg;
576 const mod = dg.module;
572577
573 const ty_ref = try self.dg.resolveType(ty, .indirect);578 const ty_ref = try self.dg.resolveType(ty, .indirect);
574 const ty_id = dg.typeId(ty_ref);579 const ty_id = dg.typeId(ty_ref);
...@@ -576,19 +581,18 @@ pub const DeclGen = struct {...@@ -576,19 +581,18 @@ pub const DeclGen = struct {
576 const decl = dg.module.declPtr(decl_index);581 const decl = dg.module.declPtr(decl_index);
577 const spv_decl_index = try dg.resolveDecl(decl_index);582 const spv_decl_index = try dg.resolveDecl(decl_index);
578583
579 switch (decl.val.tag()) {584 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
580 .function => {585 .func => {
581 // TODO: Properly lower function pointers. For now we are going to hack around it and586 // TODO: Properly lower function pointers. For now we are going to hack around it and
582 // just generate an empty pointer. Function pointers are represented by usize for now,587 // just generate an empty pointer. Function pointers are represented by usize for now,
583 // though.588 // though.
584 try self.addInt(Type.usize, Value.initTag(.zero));589 try self.addInt(Type.usize, Value.zero_usize);
585 // TODO: Add dependency590 // TODO: Add dependency
586 return;591 return;
587 },592 },
588 .extern_fn => unreachable, // TODO593 .extern_func => unreachable, // TODO
589 else => {594 else => {
590 const result_id = dg.spv.allocId();595 const result_id = dg.spv.allocId();
591 log.debug("addDeclRef: id = {}, index = {}, name = {s}", .{ result_id.id, @enumToInt(spv_decl_index), decl.name });
592596
593 try self.decl_deps.put(spv_decl_index, {});597 try self.decl_deps.put(spv_decl_index, {});
594598
...@@ -606,117 +610,122 @@ pub const DeclGen = struct {...@@ -606,117 +610,122 @@ pub const DeclGen = struct {
606 }610 }
607 }611 }
608612
609 fn lower(self: *@This(), ty: Type, val: Value) !void {613 fn lower(self: *@This(), ty: Type, arg_val: Value) !void {
610 const target = self.dg.getTarget();
611 const dg = self.dg;614 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()) {623 if (val.isUndefDeep(mod)) {
614 const size = ty.abiSize(target);624 const size = ty.abiSize(mod);
615 return try self.addUndef(size);625 return try self.addUndef(size);
616 }626 }
617627
618 switch (ty.zigTypeTag()) {628 switch (mod.intern_pool.indexToKey(val.toIntern())) {
619 .Int => try self.addInt(ty, val),629 .int_type,
620 .Float => try self.addFloat(ty, val),630 .ptr_type,
621 .Bool => try self.addConstBool(val.toBool()),631 .array_type,
622 .Array => switch (val.tag()) {632 .vector_type,
623 .aggregate => {633 .opt_type,
624 const elem_vals = val.castTag(.aggregate).?.data;634 .anyframe_type,
625 const elem_ty = ty.elemType();635 .error_union_type,
626 const len = @intCast(u32, ty.arrayLenIncludingSentinel()); // TODO: limit spir-v to 32 bit arrays in a more elegant way.636 .simple_type,
627 for (elem_vals[0..len]) |elem_val| {637 .struct_type,
628 try self.lower(elem_ty, elem_val);638 .anon_struct_type,
629 }639 .union_type,
630 },640 .opaque_type,
631 .repeated => {641 .enum_type,
632 const elem_val = val.castTag(.repeated).?.data;642 .func_type,
633 const elem_ty = ty.elemType();643 .error_set_type,
634 const len = @intCast(u32, ty.arrayLen());644 .inferred_error_set_type,
635 for (0..len) |_| {645 => unreachable, // types, not values
636 try self.lower(elem_ty, elem_val);646
637 }647 .undef, .runtime_value => unreachable, // handled above
638 if (ty.sentinel()) |sentinel| {648 .simple_value => |simple_value| switch (simple_value) {
639 try self.lower(elem_ty, sentinel);649 .undefined,
640 }650 .void,
641 },651 .null,
642 .str_lit => {652 .empty_struct,
643 const str_lit = val.castTag(.str_lit).?.data;653 .@"unreachable",
644 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];654 .generic_poison,
645 try self.addBytes(bytes);655 => unreachable, // non-runtime values
646 if (ty.sentinel()) |sentinel| {656 .false, .true => try self.addConstBool(val.toBool()),
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)}),
655 },657 },
656 .Pointer => switch (val.tag()) {658 .variable,
657 .decl_ref_mut => {659 .extern_func,
658 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;660 .func,
659 try self.addDeclRef(ty, decl_index);661 .enum_literal,
660 },662 .empty_enum_value,
661 .decl_ref => {663 => unreachable, // non-runtime values
662 const decl_index = val.castTag(.decl_ref).?.data;664 .int => try self.addInt(ty, val),
663 try self.addDeclRef(ty, decl_index);665 .err => |err| {
664 },666 const int = try mod.getErrorValue(err.name);
665 .slice => {667 try self.addConstInt(u16, @intCast(u16, int));
666 const slice = val.castTag(.slice).?.data;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;674 const eu_layout = dg.errorUnionLayout(payload_ty);
669 const ptr_ty = ty.slicePtrFieldType(&buf);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);679 const payload_size = payload_ty.abiSize(mod);
672 try self.addInt(Type.usize, slice.len);680 const error_size = Type.anyerror.abiAlignment(mod);
673 },681 const ty_size = ty.abiSize(mod);
674 .null_value, .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)),682 const padding = ty_size - payload_size - error_size;
675 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {683
676 try self.addInt(Type.usize, val);684 const payload_val = switch (error_union.val) {
677 },685 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
678 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),686 .payload => |payload| payload,
679 },687 }.toValue();
680 .Struct => {688
681 if (ty.isSimpleTupleOrAnonStruct()) {689 if (eu_layout.error_first) {
682 unreachable; // TODO690 try self.lower(Type.anyerror, error_val);
691 try self.lower(payload_ty, payload_val);
683 } else {692 } 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) {697 try self.addUndef(padding);
687 return dg.todo("packed struct constants", .{});698 },
688 }699 .enum_tag => {
700 const int_val = try val.enumToInt(ty, mod);
689701
690 const struct_begin = self.size;702 const int_ty = ty.intTagType(mod);
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]);
695703
696 // Add padding if required.704 try self.lower(int_ty, int_val);
697 // TODO: Add to type generation as well?705 },
698 const unpadded_field_end = self.size - struct_begin;706 .float => try self.addFloat(ty, val),
699 const padded_field_end = ty.structFieldOffset(i + 1, target);707 .ptr => |ptr| {
700 const padding = padded_field_end - unpadded_field_end;708 switch (ptr.addr) {
701 try self.addUndef(padding);709 .decl => |decl| try self.addDeclRef(ty, decl),
702 }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());
703 }715 }
704 },716 },
705 .Optional => {717 .opt => {
706 var opt_buf: Type.Payload.ElemType = undefined;718 const payload_ty = ty.optionalChild(mod);
707 const payload_ty = ty.optionalChild(&opt_buf);719 const payload_val = val.optionalValue(mod);
708 const has_payload = !val.isNull();720 const abi_size = ty.abiSize(mod);
709 const abi_size = ty.abiSize(target);721
710722 if (!payload_ty.hasRuntimeBits(mod)) {
711 if (!payload_ty.hasRuntimeBits()) {723 try self.addConstBool(payload_val != null);
712 try self.addConstBool(has_payload);
713 return;724 return;
714 } else if (ty.optionalReprIsPayload()) {725 } else if (ty.optionalReprIsPayload(mod)) {
715 // Optional representation is a nullable pointer or slice.726 // Optional representation is a nullable pointer or slice.
716 if (val.castTag(.opt_payload)) |payload| {727 if (payload_val) |pl_val| {
717 try self.lower(payload_ty, payload.data);728 try self.lower(payload_ty, pl_val);
718 } else if (has_payload) {
719 try self.lower(payload_ty, val);
720 } else {729 } else {
721 const ptr_ty_ref = try dg.resolveType(ty, .indirect);730 const ptr_ty_ref = try dg.resolveType(ty, .indirect);
722 try self.addNullPtr(ptr_ty_ref);731 try self.addNullPtr(ptr_ty_ref);
...@@ -729,102 +738,98 @@ pub const DeclGen = struct {...@@ -729,102 +738,98 @@ pub const DeclGen = struct {
729738
730 // Subtract 1 for @sizeOf(bool).739 // Subtract 1 for @sizeOf(bool).
731 // TODO: Make this not hardcoded.740 // TODO: Make this not hardcoded.
732 const payload_size = payload_ty.abiSize(target);741 const payload_size = payload_ty.abiSize(mod);
733 const padding = abi_size - payload_size - 1;742 const padding = abi_size - payload_size - 1;
734743
735 if (val.castTag(.opt_payload)) |payload| {744 if (payload_val) |pl_val| {
736 try self.lower(payload_ty, payload.data);745 try self.lower(payload_ty, pl_val);
737 } else {746 } else {
738 try self.addUndef(payload_size);747 try self.addUndef(payload_size);
739 }748 }
740 try self.addConstBool(has_payload);749 try self.addConstBool(payload_val != null);
741 try self.addUndef(padding);750 try self.addUndef(padding);
742 },751 },
743 .Enum => {752 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(ty.ip_index)) {
744 var int_val_buffer: Value.Payload.U64 = undefined;753 .array_type => |array_type| {
745 const int_val = val.enumToInt(ty, &int_val_buffer);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;775 if (struct_ty.layout == .Packed) {
748 const int_ty = ty.intTagType(&int_ty_buffer);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,
751 },795 },
752 .Union => {796 .un => |un| {
753 const tag_and_val = val.castTag(.@"union").?.data;797 const layout = ty.unionGetLayout(mod);
754 const layout = ty.unionGetLayout(target);
755798
756 if (layout.payload_size == 0) {799 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());
758 }801 }
759802
760 const union_ty = ty.cast(Type.Payload.Union).?.data;803 const union_ty = mod.typeToUnion(ty).?;
761 if (union_ty.layout == .Packed) {804 if (union_ty.layout == .Packed) {
762 return dg.todo("packed union constants", .{});805 return dg.todo("packed union constants", .{});
763 }806 }
764807
765 const active_field = ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?;808 const active_field = ty.unionTagFieldIndex(un.tag.toValue(), dg.module).?;
766 const active_field_ty = union_ty.fields.values()[active_field].ty;809 const active_field_ty = union_ty.fields.values()[active_field].ty;
767810
768 const has_tag = layout.tag_size != 0;811 const has_tag = layout.tag_size != 0;
769 const tag_first = layout.tag_align >= layout.payload_align;812 const tag_first = layout.tag_align >= layout.payload_align;
770813
771 if (has_tag and tag_first) {814 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());
773 }816 }
774817
775 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime()) blk: {818 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {
776 try self.lower(active_field_ty, tag_and_val.val);819 try self.lower(active_field_ty, un.val.toValue());
777 break :blk active_field_ty.abiSize(target);820 break :blk active_field_ty.abiSize(mod);
778 } else 0;821 } else 0;
779822
780 const payload_padding_len = layout.payload_size - active_field_size;823 const payload_padding_len = layout.payload_size - active_field_size;
781 try self.addUndef(payload_padding_len);824 try self.addUndef(payload_padding_len);
782825
783 if (has_tag and !tag_first) {826 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());
785 }828 }
786829
787 try self.addUndef(layout.padding);830 try self.addUndef(layout.padding);
788 },831 },
789 .ErrorSet => switch (val.tag()) {832 .memoized_call => unreachable,
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)}),
828 }833 }
829 }834 }
830 };835 };
...@@ -878,7 +883,7 @@ pub const DeclGen = struct {...@@ -878,7 +883,7 @@ pub const DeclGen = struct {
878 // const target = self.getTarget();883 // const target = self.getTarget();
879884
880 // TODO: Fix the resulting global linking for these paths.885 // TODO: Fix the resulting global linking for these paths.
881 // if (val.isUndef()) {886 // if (val.isUndef(mod)) {
882 // // Special case: the entire value is undefined. In this case, we can just887 // // Special case: the entire value is undefined. In this case, we can just
883 // // generate an OpVariable with no initializer.888 // // generate an OpVariable with no initializer.
884 // return try section.emit(self.spv.gpa, .OpVariable, .{889 // return try section.emit(self.spv.gpa, .OpVariable, .{
...@@ -886,7 +891,7 @@ pub const DeclGen = struct {...@@ -886,7 +891,7 @@ pub const DeclGen = struct {
886 // .id_result = result_id,891 // .id_result = result_id,
887 // .storage_class = storage_class,892 // .storage_class = storage_class,
888 // });893 // });
889 // } else if (ty.abiSize(target) == 0) {894 // } else if (ty.abiSize(mod) == 0) {
890 // // Special case: if the type has no size, then return an undefined pointer.895 // // Special case: if the type has no size, then return an undefined pointer.
891 // return try section.emit(self.spv.gpa, .OpUndef, .{896 // return try section.emit(self.spv.gpa, .OpUndef, .{
892 // .id_result_type = self.typeId(ptr_ty_ref),897 // .id_result_type = self.typeId(ptr_ty_ref),
...@@ -968,68 +973,25 @@ pub const DeclGen = struct {...@@ -968,68 +973,25 @@ pub const DeclGen = struct {
968 /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default.973 /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default.
969 /// This function should only be called during function code generation.974 /// This function should only be called during function code generation.
970 fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef {975 fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef {
971 const target = self.getTarget();976 const mod = self.module;
972 const result_ty_ref = try self.resolveType(ty, repr);977 const result_ty_ref = try self.resolveType(ty, repr);
973978
974 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });979 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });
975980
976 if (val.isUndef()) {981 if (val.isUndef(mod)) {
977 return self.spv.constUndef(result_ty_ref);982 return self.spv.constUndef(result_ty_ref);
978 }983 }
979984
980 switch (ty.zigTypeTag()) {985 switch (ty.zigTypeTag(mod)) {
981 .Int => {986 .Int => {
982 if (ty.isSignedInt()) {987 if (ty.isSignedInt(mod)) {
983 return try self.spv.constInt(result_ty_ref, val.toSignedInt(target));988 return try self.spv.constInt(result_ty_ref, val.toSignedInt(mod));
984 } else {989 } 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));
986 }991 }
987 },992 },
988 .Bool => switch (repr) {993 .Bool => {
989 .direct => return try self.spv.constBool(result_ty_ref, val.toBool()),994 @compileError("TODO merge conflict failure");
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);
1033 },995 },
1034 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra996 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1035 // OpVariable that is not really required.997 // OpVariable that is not really required.
...@@ -1037,7 +999,7 @@ pub const DeclGen = struct {...@@ -1037,7 +999,7 @@ pub const DeclGen = struct {
1037 // The value cannot be generated directly, so generate it as an indirect constant,999 // The value cannot be generated directly, so generate it as an indirect constant,
1038 // and then perform an OpLoad.1000 // and then perform an OpLoad.
1039 const result_id = self.spv.allocId();1001 const result_id = self.spv.allocId();
1040 const alignment = ty.abiAlignment(target);1002 const alignment = ty.abiAlignment(mod);
1041 const spv_decl_index = try self.spv.allocDecl(.global);1003 const spv_decl_index = try self.spv.allocDecl(.global);
10421004
1043 try self.lowerIndirectConstant(1005 try self.lowerIndirectConstant(
...@@ -1114,9 +1076,9 @@ pub const DeclGen = struct {...@@ -1114,9 +1076,9 @@ pub const DeclGen = struct {
1114 /// NOTE: When the active field is set to something other than the most aligned field, the1076 /// NOTE: When the active field is set to something other than the most aligned field, the
1115 /// resulting struct will be *underaligned*.1077 /// resulting struct will be *underaligned*.
1116 fn resolveUnionType(self: *DeclGen, ty: Type, maybe_active_field: ?usize) !CacheRef {1078 fn resolveUnionType(self: *DeclGen, ty: Type, maybe_active_field: ?usize) !CacheRef {
1117 const target = self.getTarget();1079 const mod = self.module;
1118 const layout = ty.unionGetLayout(target);1080 const layout = ty.unionGetLayout(mod);
1119 const union_ty = ty.cast(Type.Payload.Union).?.data;1081 const union_ty = mod.typeToUnion(ty).?;
11201082
1121 if (union_ty.layout == .Packed) {1083 if (union_ty.layout == .Packed) {
1122 return self.todo("packed union types", .{});1084 return self.todo("packed union types", .{});
...@@ -1143,11 +1105,11 @@ pub const DeclGen = struct {...@@ -1143,11 +1105,11 @@ pub const DeclGen = struct {
1143 const active_field = maybe_active_field orelse layout.most_aligned_field;1105 const active_field = maybe_active_field orelse layout.most_aligned_field;
1144 const active_field_ty = union_ty.fields.values()[active_field].ty;1106 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: {
1147 const active_payload_ty_ref = try self.resolveType(active_field_ty, .indirect);1109 const active_payload_ty_ref = try self.resolveType(active_field_ty, .indirect);
1148 member_types.appendAssumeCapacity(active_payload_ty_ref);1110 member_types.appendAssumeCapacity(active_payload_ty_ref);
1149 member_names.appendAssumeCapacity(try self.spv.resolveString("payload"));1111 member_names.appendAssumeCapacity(try self.spv.resolveString("payload"));
1150 break :blk active_field_ty.abiSize(target);1112 break :blk active_field_ty.abiSize(mod);
1151 } else 0;1113 } else 0;
11521114
1153 const payload_padding_len = layout.payload_size - active_field_size;1115 const payload_padding_len = layout.payload_size - active_field_size;
...@@ -1177,21 +1139,21 @@ pub const DeclGen = struct {...@@ -1177,21 +1139,21 @@ pub const DeclGen = struct {
11771139
1178 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.1140 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
1179 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef {1141 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef {
1142 const mod = self.module;
1180 log.debug("resolveType: ty = {}", .{ty.fmt(self.module)});1143 log.debug("resolveType: ty = {}", .{ty.fmt(self.module)});
1181 const target = self.getTarget();1144 const target = self.getTarget();
1182 switch (ty.zigTypeTag()) {1145 switch (ty.zigTypeTag(mod)) {
1183 .Void, .NoReturn => return try self.spv.resolve(.void_type),1146 .Void, .NoReturn => return try self.spv.resolve(.void_type),
1184 .Bool => switch (repr) {1147 .Bool => switch (repr) {
1185 .direct => return try self.spv.resolve(.bool_type),1148 .direct => return try self.spv.resolve(.bool_type),
1186 .indirect => return try self.intType(.unsigned, 1),1149 .indirect => return try self.intType(.unsigned, 1),
1187 },1150 },
1188 .Int => {1151 .Int => {
1189 const int_info = ty.intInfo(target);1152 const int_info = ty.intInfo(mod);
1190 return try self.intType(int_info.signedness, int_info.bits);1153 return try self.intType(int_info.signedness, int_info.bits);
1191 },1154 },
1192 .Enum => {1155 .Enum => {
1193 var buffer: Type.Payload.Bits = undefined;1156 const tag_ty = ty.intTagType(mod);
1194 const tag_ty = ty.intTagType(&buffer);
1195 return self.resolveType(tag_ty, repr);1157 return self.resolveType(tag_ty, repr);
1196 },1158 },
1197 .Float => {1159 .Float => {
...@@ -1213,17 +1175,18 @@ pub const DeclGen = struct {...@@ -1213,17 +1175,18 @@ pub const DeclGen = struct {
1213 return try self.spv.resolve(.{ .float_type = .{ .bits = bits } });1175 return try self.spv.resolve(.{ .float_type = .{ .bits = bits } });
1214 },1176 },
1215 .Array => {1177 .Array => {
1216 const elem_ty = ty.childType();1178 const elem_ty = ty.childType(mod);
1217 const elem_ty_ref = try self.resolveType(elem_ty, .direct);1179 const elem_ty_ref = try self.resolveType(elem_ty, .direct);
1218 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel()) orelse {1180 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse {
1219 return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel()});1181 return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)});
1220 };1182 };
1221 return self.spv.arrayType(total_len, elem_ty_ref);1183 return self.spv.arrayType(total_len, elem_ty_ref);
1222 },1184 },
1223 .Fn => switch (repr) {1185 .Fn => switch (repr) {
1224 .direct => {1186 .direct => {
1187 const fn_info = mod.typeToFunc(ty).?;
1225 // TODO: Put this somewhere in Sema.zig1188 // TODO: Put this somewhere in Sema.zig
1226 if (ty.fnIsVarArgs())1189 if (fn_info.is_var_args)
1227 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});1190 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});
12281191
1229 const param_ty_refs = try self.gpa.alloc(CacheRef, ty.fnParamLen());1192 const param_ty_refs = try self.gpa.alloc(CacheRef, ty.fnParamLen());
...@@ -1245,7 +1208,7 @@ pub const DeclGen = struct {...@@ -1245,7 +1208,7 @@ pub const DeclGen = struct {
1245 },1208 },
1246 },1209 },
1247 .Pointer => {1210 .Pointer => {
1248 const ptr_info = ty.ptrInfo().data;1211 const ptr_info = ty.ptrInfo(mod);
12491212
1250 const storage_class = spvStorageClass(ptr_info.@"addrspace");1213 const storage_class = spvStorageClass(ptr_info.@"addrspace");
1251 const child_ty_ref = try self.resolveType(ptr_info.pointee_type, .indirect);1214 const child_ty_ref = try self.resolveType(ptr_info.pointee_type, .indirect);
...@@ -1277,8 +1240,8 @@ pub const DeclGen = struct {...@@ -1277,8 +1240,8 @@ pub const DeclGen = struct {
1277 // TODO: Properly verify sizes and child type.1240 // TODO: Properly verify sizes and child type.
12781241
1279 return try self.spv.resolve(.{ .vector_type = .{1242 return try self.spv.resolve(.{ .vector_type = .{
1280 .component_type = try self.resolveType(ty.elemType(), repr),1243 .component_type = try self.resolveType(ty.childType(mod), repr),
1281 .component_count = @intCast(u32, ty.vectorLen()),1244 .component_count = @intCast(u32, ty.vectorLen(mod)),
1282 } });1245 } });
1283 },1246 },
1284 .Struct => {1247 .Struct => {
...@@ -1290,7 +1253,7 @@ pub const DeclGen = struct {...@@ -1290,7 +1253,7 @@ pub const DeclGen = struct {
1290 var member_index: usize = 0;1253 var member_index: usize = 0;
1291 for (tuple.types, 0..) |field_ty, i| {1254 for (tuple.types, 0..) |field_ty, i| {
1292 const field_val = tuple.values[i];1255 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
1295 member_types[member_index] = try self.resolveType(field_ty, .indirect);1258 member_types[member_index] = try self.resolveType(field_ty, .indirect);
1296 member_index += 1;1259 member_index += 1;
...@@ -1301,7 +1264,7 @@ pub const DeclGen = struct {...@@ -1301,7 +1264,7 @@ pub const DeclGen = struct {
1301 } });1264 } });
1302 }1265 }
13031266
1304 const struct_ty = ty.castTag(.@"struct").?.data;1267 const struct_ty = mod.typeToStruct(ty).?;
13051268
1306 if (struct_ty.layout == .Packed) {1269 if (struct_ty.layout == .Packed) {
1307 return try self.resolveType(struct_ty.backing_int_ty, .direct);1270 return try self.resolveType(struct_ty.backing_int_ty, .direct);
...@@ -1314,16 +1277,16 @@ pub const DeclGen = struct {...@@ -1314,16 +1277,16 @@ pub const DeclGen = struct {
1314 defer self.gpa.free(member_names);1277 defer self.gpa.free(member_names);
13151278
1316 var member_index: usize = 0;1279 var member_index: usize = 0;
1317 for (struct_ty.fields.values(), 0..) |field, i| {1280 const struct_obj = void; // TODO
1318 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;1281 for (struct_obj.fields.values(), 0..) |field, i| {
1282 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
13191283
1320 member_types[member_index] = try self.resolveType(field.ty, .indirect);1284 member_types[member_index] = try self.resolveType(field.ty, .indirect);
1321 member_names[member_index] = try self.spv.resolveString(struct_ty.fields.keys()[i]);1285 member_names[member_index] = try self.spv.resolveString(struct_ty.fields.keys()[i]);
1322 member_index += 1;1286 member_index += 1;
1323 }1287 }
13241288
1325 const name = try struct_ty.getFullyQualifiedName(self.module);1289 const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(self.module));
1326 defer self.module.gpa.free(name);
13271290
1328 return try self.spv.resolve(.{ .struct_type = .{1291 return try self.spv.resolve(.{ .struct_type = .{
1329 .name = try self.spv.resolveString(name),1292 .name = try self.spv.resolveString(name),
...@@ -1332,9 +1295,8 @@ pub const DeclGen = struct {...@@ -1332,9 +1295,8 @@ pub const DeclGen = struct {
1332 } });1295 } });
1333 },1296 },
1334 .Optional => {1297 .Optional => {
1335 var buf: Type.Payload.ElemType = undefined;1298 const payload_ty = ty.optionalChild(mod);
1336 const payload_ty = ty.optionalChild(&buf);1299 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1337 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1338 // Just use a bool.1300 // Just use a bool.
1339 // Note: Always generate the bool with indirect format, to save on some sanity1301 // Note: Always generate the bool with indirect format, to save on some sanity
1340 // Perform the conversion to a direct bool when the field is extracted.1302 // Perform the conversion to a direct bool when the field is extracted.
...@@ -1342,7 +1304,7 @@ pub const DeclGen = struct {...@@ -1342,7 +1304,7 @@ pub const DeclGen = struct {
1342 }1304 }
13431305
1344 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);1306 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);
1345 if (ty.optionalReprIsPayload()) {1307 if (ty.optionalReprIsPayload(mod)) {
1346 // Optional is actually a pointer or a slice.1308 // Optional is actually a pointer or a slice.
1347 return payload_ty_ref;1309 return payload_ty_ref;
1348 }1310 }
...@@ -1360,7 +1322,7 @@ pub const DeclGen = struct {...@@ -1360,7 +1322,7 @@ pub const DeclGen = struct {
1360 .Union => return try self.resolveUnionType(ty, null),1322 .Union => return try self.resolveUnionType(ty, null),
1361 .ErrorSet => return try self.intType(.unsigned, 16),1323 .ErrorSet => return try self.intType(.unsigned, 16),
1362 .ErrorUnion => {1324 .ErrorUnion => {
1363 const payload_ty = ty.errorUnionPayload();1325 const payload_ty = ty.errorUnionPayload(mod);
1364 const error_ty_ref = try self.resolveType(Type.anyerror, .indirect);1326 const error_ty_ref = try self.resolveType(Type.anyerror, .indirect);
13651327
1366 const eu_layout = self.errorUnionLayout(payload_ty);1328 const eu_layout = self.errorUnionLayout(payload_ty);
...@@ -1445,14 +1407,14 @@ pub const DeclGen = struct {...@@ -1445,14 +1407,14 @@ pub const DeclGen = struct {
1445 };1407 };
14461408
1447 fn errorUnionLayout(self: *DeclGen, payload_ty: Type) ErrorUnionLayout {1409 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);1412 const error_align = Type.anyerror.abiAlignment(mod);
1451 const payload_align = payload_ty.abiAlignment(target);1413 const payload_align = payload_ty.abiAlignment(mod);
14521414
1453 const error_first = error_align > payload_align;1415 const error_first = error_align > payload_align;
1454 return .{1416 return .{
1455 .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(),1417 .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod),
1456 .error_first = error_first,1418 .error_first = error_first,
1457 };1419 };
1458 }1420 }
...@@ -1529,28 +1491,28 @@ pub const DeclGen = struct {...@@ -1529,28 +1491,28 @@ pub const DeclGen = struct {
1529 }1491 }
15301492
1531 fn genDecl(self: *DeclGen) !void {1493 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);
1533 const spv_decl_index = try self.resolveDecl(self.decl_index);1497 const spv_decl_index = try self.resolveDecl(self.decl_index);
15341498
1535 const decl_id = self.spv.declPtr(spv_decl_index).result_id;1499 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)) |_| {1501 if (decl.val.getFunction(mod)) |_| {
1539 assert(decl.ty.zigTypeTag() == .Fn);1502 assert(decl.ty.zigTypeTag(mod) == .Fn);
1540 const prototype_id = try self.resolveTypeId(decl.ty);1503 const prototype_id = try self.resolveTypeId(decl.ty);
1541 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{1504 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)),
1543 .id_result = decl_id,1506 .id_result = decl_id,
1544 .function_control = .{}, // TODO: We can set inline here if the type requires it.1507 .function_control = .{}, // TODO: We can set inline here if the type requires it.
1545 .function_type = prototype_id,1508 .function_type = prototype_id,
1546 });1509 });
15471510
1548 const params = decl.ty.fnParamLen();1511 const fn_info = mod.typeToFunc(decl.ty).?;
1549 var i: usize = 0;
15501512
1551 try self.args.ensureUnusedCapacity(self.gpa, params);1513 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
1552 while (i < params) : (i += 1) {1514 for (fn_info.param_types) |param_type| {
1553 const param_type_id = try self.resolveTypeId(decl.ty.fnParamType(i));1515 const param_type_id = try self.resolveTypeId(param_type.toType());
1554 const arg_result_id = self.spv.allocId();1516 const arg_result_id = self.spv.allocId();
1555 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{1517 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
1556 .id_result_type = param_type_id,1518 .id_result_type = param_type_id,
...@@ -1576,8 +1538,7 @@ pub const DeclGen = struct {...@@ -1576,8 +1538,7 @@ pub const DeclGen = struct {
1576 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});1538 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
1577 try self.spv.addFunction(spv_decl_index, self.func);1539 try self.spv.addFunction(spv_decl_index, self.func);
15781540
1579 const fqn = try decl.getFullyQualifiedName(self.module);1541 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module));
1580 defer self.module.gpa.free(fqn);
15811542
1582 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{1543 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
1583 .target = decl_id,1544 .target = decl_id,
...@@ -1589,12 +1550,12 @@ pub const DeclGen = struct {...@@ -1589,12 +1550,12 @@ pub const DeclGen = struct {
1589 try self.generateTestEntryPoint(fqn, spv_decl_index);1550 try self.generateTestEntryPoint(fqn, spv_decl_index);
1590 }1551 }
1591 } else {1552 } else {
1592 const init_val = if (decl.val.castTag(.variable)) |payload|1553 const init_val = if (decl.val.getVariable(mod)) |payload|
1593 payload.data.init1554 payload.init.toValue()
1594 else1555 else
1595 decl.val;1556 decl.val;
15961557
1597 if (init_val.tag() == .unreachable_value) {1558 if (init_val.ip_index == .unreachable_value) {
1598 return self.todo("importing extern variables", .{});1559 return self.todo("importing extern variables", .{});
1599 }1560 }
16001561
...@@ -1634,7 +1595,8 @@ pub const DeclGen = struct {...@@ -1634,7 +1595,8 @@ pub const DeclGen = struct {
1634 /// Convert representation from indirect (in memory) to direct (in 'register')1595 /// Convert representation from indirect (in memory) to direct (in 'register')
1635 /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct).1596 /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct).
1636 fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef {1597 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)) {
1638 .Bool => blk: {1600 .Bool => blk: {
1639 const direct_bool_ty_ref = try self.resolveType(ty, .direct);1601 const direct_bool_ty_ref = try self.resolveType(ty, .direct);
1640 const indirect_bool_ty_ref = try self.resolveType(ty, .indirect);1602 const indirect_bool_ty_ref = try self.resolveType(ty, .indirect);
...@@ -1655,7 +1617,8 @@ pub const DeclGen = struct {...@@ -1655,7 +1617,8 @@ pub const DeclGen = struct {
1655 /// Convert representation from direct (in 'register) to direct (in memory)1617 /// Convert representation from direct (in 'register) to direct (in memory)
1656 /// This converts the argument type from resolveType(ty, .direct) to resolveType(ty, .indirect).1618 /// This converts the argument type from resolveType(ty, .direct) to resolveType(ty, .indirect).
1657 fn convertToIndirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef {1619 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)) {
1659 .Bool => blk: {1622 .Bool => blk: {
1660 const indirect_bool_ty_ref = try self.resolveType(ty, .indirect);1623 const indirect_bool_ty_ref = try self.resolveType(ty, .indirect);
1661 break :blk self.boolToInt(indirect_bool_ty_ref, operand_id);1624 break :blk self.boolToInt(indirect_bool_ty_ref, operand_id);
...@@ -1679,11 +1642,12 @@ pub const DeclGen = struct {...@@ -1679,11 +1642,12 @@ pub const DeclGen = struct {
1679 }1642 }
16801643
1681 fn load(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef) !IdRef {1644 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);
1683 const indirect_value_ty_ref = try self.resolveType(value_ty, .indirect);1647 const indirect_value_ty_ref = try self.resolveType(value_ty, .indirect);
1684 const result_id = self.spv.allocId();1648 const result_id = self.spv.allocId();
1685 const access = spec.MemoryAccess.Extended{1649 const access = spec.MemoryAccess.Extended{
1686 .Volatile = ptr_ty.isVolatilePtr(),1650 .Volatile = ptr_ty.isVolatilePtr(mod),
1687 };1651 };
1688 try self.func.body.emit(self.spv.gpa, .OpLoad, .{1652 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
1689 .id_result_type = self.typeId(indirect_value_ty_ref),1653 .id_result_type = self.typeId(indirect_value_ty_ref),
...@@ -1695,10 +1659,11 @@ pub const DeclGen = struct {...@@ -1695,10 +1659,11 @@ pub const DeclGen = struct {
1695 }1659 }
16961660
1697 fn store(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, value_id: IdRef) !void {1661 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);
1699 const indirect_value_id = try self.convertToIndirect(value_ty, value_id);1664 const indirect_value_id = try self.convertToIndirect(value_ty, value_id);
1700 const access = spec.MemoryAccess.Extended{1665 const access = spec.MemoryAccess.Extended{
1701 .Volatile = ptr_ty.isVolatilePtr(),1666 .Volatile = ptr_ty.isVolatilePtr(mod),
1702 };1667 };
1703 try self.func.body.emit(self.spv.gpa, .OpStore, .{1668 try self.func.body.emit(self.spv.gpa, .OpStore, .{
1704 .pointer = ptr_id,1669 .pointer = ptr_id,
...@@ -1714,10 +1679,11 @@ pub const DeclGen = struct {...@@ -1714,10 +1679,11 @@ pub const DeclGen = struct {
1714 }1679 }
17151680
1716 fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void {1681 fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void {
1682 const mod = self.module;
1683 const ip = &mod.intern_pool;
1717 // TODO: remove now-redundant isUnused calls from AIR handler functions1684 // 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))
1719 return;1686 return;
1720 }
17211687
1722 const air_tags = self.air.instructions.items(.tag);1688 const air_tags = self.air.instructions.items(.tag);
1723 const maybe_result_id: ?IdRef = switch (air_tags[inst]) {1689 const maybe_result_id: ?IdRef = switch (air_tags[inst]) {
...@@ -1794,8 +1760,6 @@ pub const DeclGen = struct {...@@ -1794,8 +1760,6 @@ pub const DeclGen = struct {
1794 .br => return self.airBr(inst),1760 .br => return self.airBr(inst),
1795 .breakpoint => return,1761 .breakpoint => return,
1796 .cond_br => return self.airCondBr(inst),1762 .cond_br => return self.airCondBr(inst),
1797 .constant => unreachable,
1798 .const_ty => unreachable,
1799 .dbg_stmt => return self.airDbgStmt(inst),1763 .dbg_stmt => return self.airDbgStmt(inst),
1800 .loop => return self.airLoop(inst),1764 .loop => return self.airLoop(inst),
1801 .ret => return self.airRet(inst),1765 .ret => return self.airRet(inst),
...@@ -1841,7 +1805,7 @@ pub const DeclGen = struct {...@@ -1841,7 +1805,7 @@ pub const DeclGen = struct {
1841 const lhs_id = try self.resolve(bin_op.lhs);1805 const lhs_id = try self.resolve(bin_op.lhs);
1842 const rhs_id = try self.resolve(bin_op.rhs);1806 const rhs_id = try self.resolve(bin_op.rhs);
1843 const result_id = self.spv.allocId();1807 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));
1845 try self.func.body.emit(self.spv.gpa, opcode, .{1809 try self.func.body.emit(self.spv.gpa, opcode, .{
1846 .id_result_type = result_type_id,1810 .id_result_type = result_type_id,
1847 .id_result = result_id,1811 .id_result = result_id,
...@@ -1856,7 +1820,7 @@ pub const DeclGen = struct {...@@ -1856,7 +1820,7 @@ pub const DeclGen = struct {
1856 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1820 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1857 const lhs_id = try self.resolve(bin_op.lhs);1821 const lhs_id = try self.resolve(bin_op.lhs);
1858 const rhs_id = try self.resolve(bin_op.rhs);1822 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
1861 // the shift and the base must be the same type in SPIR-V, but in Zig the shift is a smaller int.1825 // the shift and the base must be the same type in SPIR-V, but in Zig the shift is a smaller int.
1862 const shift_id = self.spv.allocId();1826 const shift_id = self.spv.allocId();
...@@ -1901,15 +1865,15 @@ pub const DeclGen = struct {...@@ -1901,15 +1865,15 @@ pub const DeclGen = struct {
1901 if (self.liveness.isUnused(inst)) return null;1865 if (self.liveness.isUnused(inst)) return null;
1902 // LHS and RHS are guaranteed to have the same type, and AIR guarantees1866 // LHS and RHS are guaranteed to have the same type, and AIR guarantees
1903 // the result to be the same as the LHS and RHS, which matches SPIR-V.1867 // 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);
1905 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1869 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1906 var lhs_id = try self.resolve(bin_op.lhs);1870 var lhs_id = try self.resolve(bin_op.lhs);
1907 var rhs_id = try self.resolve(bin_op.rhs);1871 var rhs_id = try self.resolve(bin_op.rhs);
19081872
1909 const result_ty_ref = try self.resolveType(ty, .direct);1873 const result_ty_ref = try self.resolveType(ty, .direct);
19101874
1911 assert(self.air.typeOf(bin_op.lhs).eql(ty, self.module));1875 assert(self.typeOf(bin_op.lhs).eql(ty, self.module));
1912 assert(self.air.typeOf(bin_op.rhs).eql(ty, self.module));1876 assert(self.typeOf(bin_op.rhs).eql(ty, self.module));
19131877
1914 // Binary operations are generally applicable to both scalar and vector operations1878 // Binary operations are generally applicable to both scalar and vector operations
1915 // in SPIR-V, but int and float versions of operations require different opcodes.1879 // in SPIR-V, but int and float versions of operations require different opcodes.
...@@ -1965,8 +1929,8 @@ pub const DeclGen = struct {...@@ -1965,8 +1929,8 @@ pub const DeclGen = struct {
1965 const lhs = try self.resolve(extra.lhs);1929 const lhs = try self.resolve(extra.lhs);
1966 const rhs = try self.resolve(extra.rhs);1930 const rhs = try self.resolve(extra.rhs);
19671931
1968 const operand_ty = self.air.typeOf(extra.lhs);1932 const operand_ty = self.typeOf(extra.lhs);
1969 const result_ty = self.air.typeOfIndex(inst);1933 const result_ty = self.typeOfIndex(inst);
19701934
1971 const info = try self.arithmeticTypeInfo(operand_ty);1935 const info = try self.arithmeticTypeInfo(operand_ty);
1972 switch (info.class) {1936 switch (info.class) {
...@@ -2056,15 +2020,16 @@ pub const DeclGen = struct {...@@ -2056,15 +2020,16 @@ pub const DeclGen = struct {
2056 }2020 }
20572021
2058 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2022 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2023 const mod = self.module;
2059 if (self.liveness.isUnused(inst)) return null;2024 if (self.liveness.isUnused(inst)) return null;
2060 const ty = self.air.typeOfIndex(inst);2025 const ty = self.typeOfIndex(inst);
2061 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2026 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2062 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;2027 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
2063 const a = try self.resolve(extra.a);2028 const a = try self.resolve(extra.a);
2064 const b = try self.resolve(extra.b);2029 const b = try self.resolve(extra.b);
2065 const mask = self.air.values[extra.mask];2030 const mask = extra.mask.toValue();
2066 const mask_len = extra.mask_len;2031 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
2069 const result_id = self.spv.allocId();2034 const result_id = self.spv.allocId();
2070 const result_type_id = try self.resolveTypeId(ty);2035 const result_type_id = try self.resolveTypeId(ty);
...@@ -2078,12 +2043,11 @@ pub const DeclGen = struct {...@@ -2078,12 +2043,11 @@ pub const DeclGen = struct {
20782043
2079 var i: usize = 0;2044 var i: usize = 0;
2080 while (i < mask_len) : (i += 1) {2045 while (i < mask_len) : (i += 1) {
2081 var buf: Value.ElemValueBuffer = undefined;2046 const elem = try mask.elemValue(mod, i);
2082 const elem = mask.elemValueBuffer(self.module, i, &buf);2047 if (elem.isUndef(mod)) {
2083 if (elem.isUndef()) {
2084 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);2048 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);
2085 } else {2049 } else {
2086 const int = elem.toSignedInt(self.getTarget());2050 const int = elem.toSignedInt(mod);
2087 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);2051 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
2088 self.func.body.writeOperand(spec.LiteralInteger, unsigned);2052 self.func.body.writeOperand(spec.LiteralInteger, unsigned);
2089 }2053 }
...@@ -2130,9 +2094,10 @@ pub const DeclGen = struct {...@@ -2130,9 +2094,10 @@ pub const DeclGen = struct {
2130 }2094 }
21312095
2132 fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef {2096 fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef {
2097 const mod = self.module;
2133 const result_ty_ref = try self.resolveType(result_ty, .direct);2098 const result_ty_ref = try self.resolveType(result_ty, .direct);
21342099
2135 switch (ptr_ty.ptrSize()) {2100 switch (ptr_ty.ptrSize(mod)) {
2136 .One => {2101 .One => {
2137 // Pointer to array2102 // Pointer to array
2138 // TODO: Is this correct?2103 // TODO: Is this correct?
...@@ -2155,8 +2120,8 @@ pub const DeclGen = struct {...@@ -2155,8 +2120,8 @@ pub const DeclGen = struct {
2155 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2120 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2156 const ptr_id = try self.resolve(bin_op.lhs);2121 const ptr_id = try self.resolve(bin_op.lhs);
2157 const offset_id = try self.resolve(bin_op.rhs);2122 const offset_id = try self.resolve(bin_op.rhs);
2158 const ptr_ty = self.air.typeOf(bin_op.lhs);2123 const ptr_ty = self.typeOf(bin_op.lhs);
2159 const result_ty = self.air.typeOfIndex(inst);2124 const result_ty = self.typeOfIndex(inst);
21602125
2161 return try self.ptrAdd(result_ty, ptr_ty, ptr_id, offset_id);2126 return try self.ptrAdd(result_ty, ptr_ty, ptr_id, offset_id);
2162 }2127 }
...@@ -2166,11 +2131,11 @@ pub const DeclGen = struct {...@@ -2166,11 +2131,11 @@ pub const DeclGen = struct {
2166 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2131 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2167 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2132 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2168 const ptr_id = try self.resolve(bin_op.lhs);2133 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);
2170 const offset_id = try self.resolve(bin_op.rhs);2135 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);
2172 const offset_ty_ref = try self.resolveType(offset_ty, .direct);2137 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
2175 const negative_offset_id = self.spv.allocId();2140 const negative_offset_id = self.spv.allocId();
2176 try self.func.body.emit(self.spv.gpa, .OpSNegate, .{2141 try self.func.body.emit(self.spv.gpa, .OpSNegate, .{
...@@ -2189,13 +2154,13 @@ pub const DeclGen = struct {...@@ -2189,13 +2154,13 @@ pub const DeclGen = struct {
2189 lhs_id: IdRef,2154 lhs_id: IdRef,
2190 rhs_id: IdRef,2155 rhs_id: IdRef,
2191 ) !IdRef {2156 ) !IdRef {
2157 const mod = self.module;
2192 var cmp_lhs_id = lhs_id;2158 var cmp_lhs_id = lhs_id;
2193 var cmp_rhs_id = rhs_id;2159 var cmp_rhs_id = rhs_id;
2194 const opcode: Opcode = opcode: {2160 const opcode: Opcode = opcode: {
2195 var int_buffer: Type.Payload.Bits = undefined;2161 const op_ty = switch (ty.zigTypeTag(mod)) {
2196 const op_ty = switch (ty.zigTypeTag()) {
2197 .Int, .Bool, .Float => ty,2162 .Int, .Bool, .Float => ty,
2198 .Enum => ty.intTagType(&int_buffer),2163 .Enum => ty.intTagType(),
2199 .ErrorSet => Type.u16,2164 .ErrorSet => Type.u16,
2200 .Pointer => blk: {2165 .Pointer => blk: {
2201 // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are2166 // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are
...@@ -2291,8 +2256,8 @@ pub const DeclGen = struct {...@@ -2291,8 +2256,8 @@ pub const DeclGen = struct {
2291 const lhs_id = try self.resolve(bin_op.lhs);2256 const lhs_id = try self.resolve(bin_op.lhs);
2292 const rhs_id = try self.resolve(bin_op.rhs);2257 const rhs_id = try self.resolve(bin_op.rhs);
2293 const bool_ty_id = try self.resolveTypeId(Type.bool);2258 const bool_ty_id = try self.resolveTypeId(Type.bool);
2294 const ty = self.air.typeOf(bin_op.lhs);2259 const ty = self.typeOf(bin_op.lhs);
2295 assert(ty.eql(self.air.typeOf(bin_op.rhs), self.module));2260 assert(ty.eql(self.typeOf(bin_op.rhs), self.module));
22962261
2297 return try self.cmp(op, bool_ty_id, ty, lhs_id, rhs_id);2262 return try self.cmp(op, bool_ty_id, ty, lhs_id, rhs_id);
2298 }2263 }
...@@ -2303,13 +2268,14 @@ pub const DeclGen = struct {...@@ -2303,13 +2268,14 @@ pub const DeclGen = struct {
2303 src_ty: Type,2268 src_ty: Type,
2304 src_id: IdRef,2269 src_id: IdRef,
2305 ) !IdRef {2270 ) !IdRef {
2271 const mod = self.module;
2306 const dst_ty_ref = try self.resolveType(dst_ty, .direct);2272 const dst_ty_ref = try self.resolveType(dst_ty, .direct);
2307 const result_id = self.spv.allocId();2273 const result_id = self.spv.allocId();
23082274
2309 // TODO: Some more cases are missing here2275 // TODO: Some more cases are missing here
2310 // See fn bitCast in llvm.zig2276 // 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)) {
2313 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{2279 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{
2314 .id_result_type = self.typeId(dst_ty_ref),2280 .id_result_type = self.typeId(dst_ty_ref),
2315 .id_result = result_id,2281 .id_result = result_id,
...@@ -2329,8 +2295,8 @@ pub const DeclGen = struct {...@@ -2329,8 +2295,8 @@ pub const DeclGen = struct {
2329 if (self.liveness.isUnused(inst)) return null;2295 if (self.liveness.isUnused(inst)) return null;
2330 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2296 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2331 const operand_id = try self.resolve(ty_op.operand);2297 const operand_id = try self.resolve(ty_op.operand);
2332 const operand_ty = self.air.typeOf(ty_op.operand);2298 const operand_ty = self.typeOf(ty_op.operand);
2333 const result_ty = self.air.typeOfIndex(inst);2299 const result_ty = self.typeOfIndex(inst);
2334 return try self.bitCast(result_ty, operand_ty, operand_id);2300 return try self.bitCast(result_ty, operand_ty, operand_id);
2335 }2301 }
23362302
...@@ -2339,11 +2305,11 @@ pub const DeclGen = struct {...@@ -2339,11 +2305,11 @@ pub const DeclGen = struct {
23392305
2340 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2306 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2341 const operand_id = try self.resolve(ty_op.operand);2307 const operand_id = try self.resolve(ty_op.operand);
2342 const dest_ty = self.air.typeOfIndex(inst);2308 const dest_ty = self.typeOfIndex(inst);
2343 const dest_ty_id = try self.resolveTypeId(dest_ty);2309 const dest_ty_id = try self.resolveTypeId(dest_ty);
23442310
2345 const target = self.getTarget();2311 const mod = self.module;
2346 const dest_info = dest_ty.intInfo(target);2312 const dest_info = dest_ty.intInfo(mod);
23472313
2348 // TODO: Masking?2314 // TODO: Masking?
23492315
...@@ -2383,10 +2349,10 @@ pub const DeclGen = struct {...@@ -2383,10 +2349,10 @@ pub const DeclGen = struct {
2383 if (self.liveness.isUnused(inst)) return null;2349 if (self.liveness.isUnused(inst)) return null;
23842350
2385 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2351 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);
2387 const operand_id = try self.resolve(ty_op.operand);2353 const operand_id = try self.resolve(ty_op.operand);
2388 const operand_info = try self.arithmeticTypeInfo(operand_ty);2354 const operand_info = try self.arithmeticTypeInfo(operand_ty);
2389 const dest_ty = self.air.typeOfIndex(inst);2355 const dest_ty = self.typeOfIndex(inst);
2390 const dest_ty_id = try self.resolveTypeId(dest_ty);2356 const dest_ty_id = try self.resolveTypeId(dest_ty);
23912357
2392 const result_id = self.spv.allocId();2358 const result_id = self.spv.allocId();
...@@ -2410,7 +2376,7 @@ pub const DeclGen = struct {...@@ -2410,7 +2376,7 @@ pub const DeclGen = struct {
24102376
2411 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2377 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2412 const operand_id = try self.resolve(ty_op.operand);2378 const operand_id = try self.resolve(ty_op.operand);
2413 const dest_ty = self.air.typeOfIndex(inst);2379 const dest_ty = self.typeOfIndex(inst);
2414 const dest_info = try self.arithmeticTypeInfo(dest_ty);2380 const dest_info = try self.arithmeticTypeInfo(dest_ty);
2415 const dest_ty_id = try self.resolveTypeId(dest_ty);2381 const dest_ty_id = try self.resolveTypeId(dest_ty);
24162382
...@@ -2447,20 +2413,21 @@ pub const DeclGen = struct {...@@ -2447,20 +2413,21 @@ pub const DeclGen = struct {
2447 fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {2413 fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {
2448 if (self.liveness.isUnused(inst)) return null;2414 if (self.liveness.isUnused(inst)) return null;
2449 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2415 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);
2451 const operand_id = try self.resolve(ty_op.operand);2417 const operand_id = try self.resolve(ty_op.operand);
2452 return try self.extractField(field_ty, operand_id, field);2418 return try self.extractField(field_ty, operand_id, field);
2453 }2419 }
24542420
2455 fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2421 fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2422 const mod = self.module;
2456 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2423 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2457 const slice_ty = self.air.typeOf(bin_op.lhs);2424 const slice_ty = self.typeOf(bin_op.lhs);
2458 if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;2425 if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;
24592426
2460 const slice_id = try self.resolve(bin_op.lhs);2427 const slice_id = try self.resolve(bin_op.lhs);
2461 const index_id = try self.resolve(bin_op.rhs);2428 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);
2464 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);2431 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
24652432
2466 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);2433 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
...@@ -2468,15 +2435,16 @@ pub const DeclGen = struct {...@@ -2468,15 +2435,16 @@ pub const DeclGen = struct {
2468 }2435 }
24692436
2470 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2437 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2438 const mod = self.module;
2471 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2439 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2472 const slice_ty = self.air.typeOf(bin_op.lhs);2440 const slice_ty = self.typeOf(bin_op.lhs);
2473 if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;2441 if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;
24742442
2475 const slice_id = try self.resolve(bin_op.lhs);2443 const slice_id = try self.resolve(bin_op.lhs);
2476 const index_id = try self.resolve(bin_op.rhs);2444 const index_id = try self.resolve(bin_op.rhs);
24772445
2478 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;2446 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);
2480 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);2448 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
24812449
2482 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);2450 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
...@@ -2485,11 +2453,12 @@ pub const DeclGen = struct {...@@ -2485,11 +2453,12 @@ pub const DeclGen = struct {
2485 }2453 }
24862454
2487 fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef {2455 fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef {
2456 const mod = self.module;
2488 // Construct new pointer type for the resulting pointer2457 // 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.
2490 const elem_ty_ref = try self.resolveType(elem_ty, .direct);2459 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()));2460 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace(mod)));
2492 if (ptr_ty.isSinglePointer()) {2461 if (ptr_ty.isSinglePointer(mod)) {
2493 // Pointer-to-array. In this case, the resulting pointer is not of the same type2462 // Pointer-to-array. In this case, the resulting pointer is not of the same type
2494 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.2463 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
2495 return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id});2464 return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id});
...@@ -2502,12 +2471,13 @@ pub const DeclGen = struct {...@@ -2502,12 +2471,13 @@ pub const DeclGen = struct {
2502 fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2471 fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2503 if (self.liveness.isUnused(inst)) return null;2472 if (self.liveness.isUnused(inst)) return null;
25042473
2474 const mod = self.module;
2505 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2475 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2506 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2476 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2507 const ptr_ty = self.air.typeOf(bin_op.lhs);2477 const ptr_ty = self.typeOf(bin_op.lhs);
2508 const elem_ty = ptr_ty.childType();2478 const elem_ty = ptr_ty.childType(mod);
2509 // TODO: Make this return a null ptr or something2479 // 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
2512 const ptr_id = try self.resolve(bin_op.lhs);2482 const ptr_id = try self.resolve(bin_op.lhs);
2513 const index_id = try self.resolve(bin_op.rhs);2483 const index_id = try self.resolve(bin_op.rhs);
...@@ -2515,8 +2485,9 @@ pub const DeclGen = struct {...@@ -2515,8 +2485,9 @@ pub const DeclGen = struct {
2515 }2485 }
25162486
2517 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2487 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2488 const mod = self.module;
2518 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2489 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);
2520 const ptr_id = try self.resolve(bin_op.lhs);2491 const ptr_id = try self.resolve(bin_op.lhs);
2521 const index_id = try self.resolve(bin_op.rhs);2492 const index_id = try self.resolve(bin_op.rhs);
25222493
...@@ -2525,19 +2496,19 @@ pub const DeclGen = struct {...@@ -2525,19 +2496,19 @@ pub const DeclGen = struct {
2525 // If we have a pointer-to-array, construct an element pointer to use with load()2496 // If we have a pointer-to-array, construct an element pointer to use with load()
2526 // If we pass ptr_ty directly, it will attempt to load the entire array rather than2497 // If we pass ptr_ty directly, it will attempt to load the entire array rather than
2527 // just an element.2498 // just an element.
2528 var elem_ptr_info = ptr_ty.ptrInfo();2499 var elem_ptr_info = ptr_ty.ptrInfo(mod);
2529 elem_ptr_info.data.size = .One;2500 elem_ptr_info.size = .One;
2530 const elem_ptr_ty = Type.initPayload(&elem_ptr_info.base);2501 const elem_ptr_ty = try Type.ptr(undefined, mod, elem_ptr_info);
25312502
2532 return try self.load(elem_ptr_ty, elem_ptr_id);2503 return try self.load(elem_ptr_ty, elem_ptr_id);
2533 }2504 }
25342505
2535 fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2506 fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2536 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2507 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();2510 const mod = self.module;
2540 const layout = un_ty.unionGetLayout(target);2511 const layout = un_ty.unionGetLayout(mod);
2541 if (layout.tag_size == 0) return null;2512 if (layout.tag_size == 0) return null;
25422513
2543 const union_handle = try self.resolve(ty_op.operand);2514 const union_handle = try self.resolve(ty_op.operand);
...@@ -2551,17 +2522,18 @@ pub const DeclGen = struct {...@@ -2551,17 +2522,18 @@ pub const DeclGen = struct {
2551 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2522 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2552 if (self.liveness.isUnused(inst)) return null;2523 if (self.liveness.isUnused(inst)) return null;
25532524
2525 const mod = self.module;
2554 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2526 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2555 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;2527 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);
2558 const object_id = try self.resolve(struct_field.struct_operand);2530 const object_id = try self.resolve(struct_field.struct_operand);
2559 const field_index = struct_field.field_index;2531 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
2566 return try self.extractField(field_ty, object_id, field_index);2538 return try self.extractField(field_ty, object_id, field_index);
2567 }2539 }
...@@ -2573,9 +2545,10 @@ pub const DeclGen = struct {...@@ -2573,9 +2545,10 @@ pub const DeclGen = struct {
2573 object_ptr: IdRef,2545 object_ptr: IdRef,
2574 field_index: u32,2546 field_index: u32,
2575 ) !?IdRef {2547 ) !?IdRef {
2576 const object_ty = object_ptr_ty.childType();2548 const mod = self.module;
2577 switch (object_ty.zigTypeTag()) {2549 const object_ty = object_ptr_ty.childType(mod);
2578 .Struct => switch (object_ty.containerLayout()) {2550 switch (object_ty.zigTypeTag(mod)) {
2551 .Struct => switch (object_ty.containerLayout(mod)) {
2579 .Packed => unreachable, // TODO2552 .Packed => unreachable, // TODO
2580 else => {2553 else => {
2581 const field_index_ty_ref = try self.intType(.unsigned, 32);2554 const field_index_ty_ref = try self.intType(.unsigned, 32);
...@@ -2592,8 +2565,8 @@ pub const DeclGen = struct {...@@ -2592,8 +2565,8 @@ pub const DeclGen = struct {
2592 if (self.liveness.isUnused(inst)) return null;2565 if (self.liveness.isUnused(inst)) return null;
2593 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2566 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2594 const struct_ptr = try self.resolve(ty_op.operand);2567 const struct_ptr = try self.resolve(ty_op.operand);
2595 const struct_ptr_ty = self.air.typeOf(ty_op.operand);2568 const struct_ptr_ty = self.typeOf(ty_op.operand);
2596 const result_ptr_ty = self.air.typeOfIndex(inst);2569 const result_ptr_ty = self.typeOfIndex(inst);
2597 return try self.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index);2570 return try self.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index);
2598 }2571 }
25992572
...@@ -2649,9 +2622,10 @@ pub const DeclGen = struct {...@@ -2649,9 +2622,10 @@ pub const DeclGen = struct {
26492622
2650 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2623 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2651 if (self.liveness.isUnused(inst)) return null;2624 if (self.liveness.isUnused(inst)) return null;
2652 const ptr_ty = self.air.typeOfIndex(inst);2625 const mod = self.module;
2653 assert(ptr_ty.ptrAddressSpace() == .generic);2626 const ptr_ty = self.typeOfIndex(inst);
2654 const child_ty = ptr_ty.childType();2627 assert(ptr_ty.ptrAddressSpace(mod) == .generic);
2628 const child_ty = ptr_ty.childType(mod);
2655 const child_ty_ref = try self.resolveType(child_ty, .indirect);2629 const child_ty_ref = try self.resolveType(child_ty, .indirect);
2656 return try self.alloc(child_ty_ref, null);2630 return try self.alloc(child_ty_ref, null);
2657 }2631 }
...@@ -2667,6 +2641,7 @@ pub const DeclGen = struct {...@@ -2667,6 +2641,7 @@ pub const DeclGen = struct {
2667 // the current block by first generating the code of the block, then a label, and then generate the rest of the current2641 // the current block by first generating the code of the block, then a label, and then generate the rest of the current
2668 // ir.Block in a different SPIR-V block.2642 // ir.Block in a different SPIR-V block.
26692643
2644 const mod = self.module;
2670 const label_id = self.spv.allocId();2645 const label_id = self.spv.allocId();
26712646
2672 // 4 chosen as arbitrary initial capacity.2647 // 4 chosen as arbitrary initial capacity.
...@@ -2681,7 +2656,7 @@ pub const DeclGen = struct {...@@ -2681,7 +2656,7 @@ pub const DeclGen = struct {
2681 incoming_blocks.deinit(self.gpa);2656 incoming_blocks.deinit(self.gpa);
2682 }2657 }
26832658
2684 const ty = self.air.typeOfIndex(inst);2659 const ty = self.typeOfIndex(inst);
2685 const inst_datas = self.air.instructions.items(.data);2660 const inst_datas = self.air.instructions.items(.data);
2686 const extra = self.air.extraData(Air.Block, inst_datas[inst].ty_pl.payload);2661 const extra = self.air.extraData(Air.Block, inst_datas[inst].ty_pl.payload);
2687 const body = self.air.extra[extra.end..][0..extra.data.body_len];2662 const body = self.air.extra[extra.end..][0..extra.data.body_len];
...@@ -2690,7 +2665,7 @@ pub const DeclGen = struct {...@@ -2690,7 +2665,7 @@ pub const DeclGen = struct {
2690 try self.beginSpvBlock(label_id);2665 try self.beginSpvBlock(label_id);
26912666
2692 // If this block didn't produce a value, simply return here.2667 // If this block didn't produce a value, simply return here.
2693 if (!ty.hasRuntimeBitsIgnoreComptime())2668 if (!ty.hasRuntimeBitsIgnoreComptime(mod))
2694 return null;2669 return null;
26952670
2696 // Combine the result from the blocks using the Phi instruction.2671 // Combine the result from the blocks using the Phi instruction.
...@@ -2714,9 +2689,10 @@ pub const DeclGen = struct {...@@ -2714,9 +2689,10 @@ pub const DeclGen = struct {
2714 fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void {2689 fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void {
2715 const br = self.air.instructions.items(.data)[inst].br;2690 const br = self.air.instructions.items(.data)[inst].br;
2716 const block = self.blocks.get(br.block_inst).?;2691 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)) {
2720 const operand_id = try self.resolve(br.operand);2696 const operand_id = try self.resolve(br.operand);
2721 // current_block_label_id should not be undefined here, lest there is a br or br_void in the function's body.2697 // current_block_label_id should not be undefined here, lest there is a br or br_void in the function's body.
2722 try block.incoming_blocks.append(self.gpa, .{ .src_label_id = self.current_block_label_id, .break_value_id = operand_id });2698 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 {...@@ -2753,7 +2729,10 @@ pub const DeclGen = struct {
27532729
2754 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {2730 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {
2755 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;2731 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 );
2757 try self.func.body.emit(self.spv.gpa, .OpLine, .{2736 try self.func.body.emit(self.spv.gpa, .OpLine, .{
2758 .file = src_fname_id,2737 .file = src_fname_id,
2759 .line = dbg_stmt.line,2738 .line = dbg_stmt.line,
...@@ -2762,22 +2741,24 @@ pub const DeclGen = struct {...@@ -2762,22 +2741,24 @@ pub const DeclGen = struct {
2762 }2741 }
27632742
2764 fn airLoad(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2743 fn airLoad(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2744 const mod = self.module;
2765 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2745 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);
2767 const operand = try self.resolve(ty_op.operand);2747 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
2770 return try self.load(ptr_ty, operand);2750 return try self.load(ptr_ty, operand);
2771 }2751 }
27722752
2773 fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void {2753 fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void {
2754 const mod = self.module;
2774 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2755 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);
2776 const ptr = try self.resolve(bin_op.lhs);2757 const ptr = try self.resolve(bin_op.lhs);
2777 const value = try self.resolve(bin_op.rhs);2758 const value = try self.resolve(bin_op.rhs);
2778 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);2759 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;
2781 if (val_is_undef) {2762 if (val_is_undef) {
2782 const undef = try self.spv.constUndef(ptr_ty_ref);2763 const undef = try self.spv.constUndef(ptr_ty_ref);
2783 try self.store(ptr_ty, ptr, undef);2764 try self.store(ptr_ty, ptr, undef);
...@@ -2804,8 +2785,9 @@ pub const DeclGen = struct {...@@ -2804,8 +2785,9 @@ pub const DeclGen = struct {
28042785
2805 fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void {2786 fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void {
2806 const operand = self.air.instructions.items(.data)[inst].un_op;2787 const operand = self.air.instructions.items(.data)[inst].un_op;
2807 const operand_ty = self.air.typeOf(operand);2788 const operand_ty = self.typeOf(operand);
2808 if (operand_ty.hasRuntimeBits()) {2789 const mod = self.module;
2790 if (operand_ty.hasRuntimeBits(mod)) {
2809 const operand_id = try self.resolve(operand);2791 const operand_id = try self.resolve(operand);
2810 try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id });2792 try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id });
2811 } else {2793 } else {
...@@ -2814,11 +2796,12 @@ pub const DeclGen = struct {...@@ -2814,11 +2796,12 @@ pub const DeclGen = struct {
2814 }2796 }
28152797
2816 fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void {2798 fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void {
2799 const mod = self.module;
2817 const un_op = self.air.instructions.items(.data)[inst].un_op;2800 const un_op = self.air.instructions.items(.data)[inst].un_op;
2818 const ptr_ty = self.air.typeOf(un_op);2801 const ptr_ty = self.typeOf(un_op);
2819 const ret_ty = ptr_ty.childType();2802 const ret_ty = ptr_ty.childType(mod);
28202803
2821 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {2804 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2822 try self.func.body.emit(self.spv.gpa, .OpReturn, {});2805 try self.func.body.emit(self.spv.gpa, .OpReturn, {});
2823 return;2806 return;
2824 }2807 }
...@@ -2831,20 +2814,21 @@ pub const DeclGen = struct {...@@ -2831,20 +2814,21 @@ pub const DeclGen = struct {
2831 }2814 }
28322815
2833 fn airTry(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2816 fn airTry(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2817 const mod = self.module;
2834 const pl_op = self.air.instructions.items(.data)[inst].pl_op;2818 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
2835 const err_union_id = try self.resolve(pl_op.operand);2819 const err_union_id = try self.resolve(pl_op.operand);
2836 const extra = self.air.extraData(Air.Try, pl_op.payload);2820 const extra = self.air.extraData(Air.Try, pl_op.payload);
2837 const body = self.air.extra[extra.end..][0..extra.data.body_len];2821 const body = self.air.extra[extra.end..][0..extra.data.body_len];
28382822
2839 const err_union_ty = self.air.typeOf(pl_op.operand);2823 const err_union_ty = self.typeOf(pl_op.operand);
2840 const payload_ty = self.air.typeOfIndex(inst);2824 const payload_ty = self.typeOfIndex(inst);
28412825
2842 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);2826 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
2843 const bool_ty_ref = try self.resolveType(Type.bool, .direct);2827 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
28442828
2845 const eu_layout = self.errorUnionLayout(payload_ty);2829 const eu_layout = self.errorUnionLayout(payload_ty);
28462830
2847 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {2831 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
2848 const err_id = if (eu_layout.payload_has_bits)2832 const err_id = if (eu_layout.payload_has_bits)
2849 try self.extractField(Type.anyerror, err_union_id, eu_layout.errorFieldIndex())2833 try self.extractField(Type.anyerror, err_union_id, eu_layout.errorFieldIndex())
2850 else2834 else
...@@ -2892,17 +2876,18 @@ pub const DeclGen = struct {...@@ -2892,17 +2876,18 @@ pub const DeclGen = struct {
2892 fn airErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2876 fn airErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2893 if (self.liveness.isUnused(inst)) return null;2877 if (self.liveness.isUnused(inst)) return null;
28942878
2879 const mod = self.module;
2895 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2880 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2896 const operand_id = try self.resolve(ty_op.operand);2881 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);
2898 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);2883 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)) {
2901 // No error possible, so just return undefined.2886 // No error possible, so just return undefined.
2902 return try self.spv.constUndef(err_ty_ref);2887 return try self.spv.constUndef(err_ty_ref);
2903 }2888 }
29042889
2905 const payload_ty = err_union_ty.errorUnionPayload();2890 const payload_ty = err_union_ty.errorUnionPayload(mod);
2906 const eu_layout = self.errorUnionLayout(payload_ty);2891 const eu_layout = self.errorUnionLayout(payload_ty);
29072892
2908 if (!eu_layout.payload_has_bits) {2893 if (!eu_layout.payload_has_bits) {
...@@ -2916,9 +2901,10 @@ pub const DeclGen = struct {...@@ -2916,9 +2901,10 @@ pub const DeclGen = struct {
2916 fn airWrapErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2901 fn airWrapErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2917 if (self.liveness.isUnused(inst)) return null;2902 if (self.liveness.isUnused(inst)) return null;
29182903
2904 const mod = self.module;
2919 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2905 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2920 const err_union_ty = self.air.typeOfIndex(inst);2906 const err_union_ty = self.typeOfIndex(inst);
2921 const payload_ty = err_union_ty.errorUnionPayload();2907 const payload_ty = err_union_ty.errorUnionPayload(mod);
2922 const operand_id = try self.resolve(ty_op.operand);2908 const operand_id = try self.resolve(ty_op.operand);
2923 const eu_layout = self.errorUnionLayout(payload_ty);2909 const eu_layout = self.errorUnionLayout(payload_ty);
29242910
...@@ -2946,25 +2932,24 @@ pub const DeclGen = struct {...@@ -2946,25 +2932,24 @@ pub const DeclGen = struct {
2946 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {2932 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {
2947 if (self.liveness.isUnused(inst)) return null;2933 if (self.liveness.isUnused(inst)) return null;
29482934
2935 const mod = self.module;
2949 const un_op = self.air.instructions.items(.data)[inst].un_op;2936 const un_op = self.air.instructions.items(.data)[inst].un_op;
2950 const operand_id = try self.resolve(un_op);2937 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;2940 const payload_ty = optional_ty.optionalChild(mod);
2954 const payload_ty = optional_ty.optionalChild(&buf);
29552941
2956 const bool_ty_ref = try self.resolveType(Type.bool, .direct);2942 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
29572943
2958 if (optional_ty.optionalReprIsPayload()) {2944 if (optional_ty.optionalReprIsPayload(mod)) {
2959 // Pointer payload represents nullability: pointer or slice.2945 // Pointer payload represents nullability: pointer or slice.
29602946
2961 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;2947 const ptr_ty = if (payload_ty.isSlice(mod))
2962 const ptr_ty = if (payload_ty.isSlice())2948 payload_ty.slicePtrFieldType(mod)
2963 payload_ty.slicePtrFieldType(&ptr_buf)
2964 else2949 else
2965 payload_ty;2950 payload_ty;
29662951
2967 const ptr_id = if (payload_ty.isSlice())2952 const ptr_id = if (payload_ty.isSlice(mod))
2968 try self.extractField(Type.bool, operand_id, 0)2953 try self.extractField(Type.bool, operand_id, 0)
2969 else2954 else
2970 operand_id;2955 operand_id;
...@@ -2985,7 +2970,7 @@ pub const DeclGen = struct {...@@ -2985,7 +2970,7 @@ pub const DeclGen = struct {
2985 return result_id;2970 return result_id;
2986 }2971 }
29872972
2988 const is_non_null_id = if (optional_ty.hasRuntimeBitsIgnoreComptime())2973 const is_non_null_id = if (optional_ty.hasRuntimeBitsIgnoreComptime(mod))
2989 try self.extractField(Type.bool, operand_id, 1)2974 try self.extractField(Type.bool, operand_id, 1)
2990 else2975 else
2991 // Optional representation is bool indicating whether the optional is set2976 // Optional representation is bool indicating whether the optional is set
...@@ -3009,14 +2994,15 @@ pub const DeclGen = struct {...@@ -3009,14 +2994,15 @@ pub const DeclGen = struct {
3009 fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2994 fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3010 if (self.liveness.isUnused(inst)) return null;2995 if (self.liveness.isUnused(inst)) return null;
30112996
2997 const mod = self.module;
3012 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2998 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3013 const operand_id = try self.resolve(ty_op.operand);2999 const operand_id = try self.resolve(ty_op.operand);
3014 const optional_ty = self.air.typeOf(ty_op.operand);3000 const optional_ty = self.typeOf(ty_op.operand);
3015 const payload_ty = self.air.typeOfIndex(inst);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)) {
3020 return operand_id;3006 return operand_id;
3021 }3007 }
30223008
...@@ -3026,16 +3012,17 @@ pub const DeclGen = struct {...@@ -3026,16 +3012,17 @@ pub const DeclGen = struct {
3026 fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3012 fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3027 if (self.liveness.isUnused(inst)) return null;3013 if (self.liveness.isUnused(inst)) return null;
30283014
3015 const mod = self.module;
3029 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3016 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)) {
3033 return try self.constBool(true, .direct);3020 return try self.constBool(true, .direct);
3034 }3021 }
30353022
3036 const operand_id = try self.resolve(ty_op.operand);3023 const operand_id = try self.resolve(ty_op.operand);
3037 const optional_ty = self.air.typeOfIndex(inst);3024 const optional_ty = self.typeOfIndex(inst);
3038 if (optional_ty.optionalReprIsPayload()) {3025 if (optional_ty.optionalReprIsPayload(mod)) {
3039 return operand_id;3026 return operand_id;
3040 }3027 }
30413028
...@@ -3045,30 +3032,29 @@ pub const DeclGen = struct {...@@ -3045,30 +3032,29 @@ pub const DeclGen = struct {
3045 }3032 }
30463033
3047 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {3034 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {
3048 const target = self.getTarget();3035 const mod = self.module;
3049 const pl_op = self.air.instructions.items(.data)[inst].pl_op;3036 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3050 const cond = try self.resolve(pl_op.operand);3037 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);
3052 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);3039 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)) {
3055 .Int => blk: {3042 .Int => blk: {
3056 const bits = cond_ty.intInfo(target).bits;3043 const bits = cond_ty.intInfo(mod).bits;
3057 const backing_bits = self.backingIntBits(bits) orelse {3044 const backing_bits = self.backingIntBits(bits) orelse {
3058 return self.todo("implement composite int switch", .{});3045 return self.todo("implement composite int switch", .{});
3059 };3046 };
3060 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;3047 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;
3061 },3048 },
3062 .Enum => blk: {3049 .Enum => blk: {
3063 var buffer: Type.Payload.Bits = undefined;3050 const int_ty = cond_ty.intTagType(mod);
3064 const int_ty = cond_ty.intTagType(&buffer);3051 const int_info = int_ty.intInfo(mod);
3065 const int_info = int_ty.intInfo(target);
3066 const backing_bits = self.backingIntBits(int_info.bits) orelse {3052 const backing_bits = self.backingIntBits(int_info.bits) orelse {
3067 return self.todo("implement composite int switch", .{});3053 return self.todo("implement composite int switch", .{});
3068 };3054 };
3069 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;3055 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;
3070 },3056 },
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.
3072 };3058 };
30733059
3074 const num_cases = switch_br.data.cases_len;3060 const num_cases = switch_br.data.cases_len;
...@@ -3112,15 +3098,14 @@ pub const DeclGen = struct {...@@ -3112,15 +3098,14 @@ pub const DeclGen = struct {
3112 const label = IdRef{ .id = first_case_label.id + case_i };3098 const label = IdRef{ .id = first_case_label.id + case_i };
31133099
3114 for (items) |item| {3100 for (items) |item| {
3115 const value = self.air.value(item) orelse {3101 const value = (try self.air.value(item, mod)) orelse {
3116 return self.todo("switch on runtime value???", .{});3102 return self.todo("switch on runtime value???", .{});
3117 };3103 };
3118 const int_val = switch (cond_ty.zigTypeTag()) {3104 const int_val = switch (cond_ty.zigTypeTag(mod)) {
3119 .Int => if (cond_ty.isSignedInt()) @bitCast(u64, value.toSignedInt(target)) else value.toUnsignedInt(target),3105 .Int => if (cond_ty.isSignedInt(mod)) @bitCast(u64, value.toSignedInt(mod)) else value.toUnsignedInt(mod),
3120 .Enum => blk: {3106 .Enum => blk: {
3121 var int_buffer: Value.Payload.U64 = undefined;
3122 // TODO: figure out of cond_ty is correct (something with enum literals)3107 // 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 constants3108 break :blk (try value.enumToInt(cond_ty, mod)).toUnsignedInt(mod); // TODO: composite integer constants
3124 },3109 },
3125 else => unreachable,3110 else => unreachable,
3126 };3111 };
...@@ -3164,6 +3149,7 @@ pub const DeclGen = struct {...@@ -3164,6 +3149,7 @@ pub const DeclGen = struct {
3164 }3149 }
31653150
3166 fn airAssembly(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3151 fn airAssembly(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3152 const mod = self.module;
3167 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;3153 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3168 const extra = self.air.extraData(Air.Asm, ty_pl.payload);3154 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
31693155
...@@ -3246,7 +3232,7 @@ pub const DeclGen = struct {...@@ -3246,7 +3232,7 @@ pub const DeclGen = struct {
3246 assert(as.errors.items.len != 0);3232 assert(as.errors.items.len != 0);
3247 assert(self.error_msg == null);3233 assert(self.error_msg == null);
3248 const loc = LazySrcLoc.nodeOffset(0);3234 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);
3250 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});3236 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
3251 const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);3237 const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);
32523238
...@@ -3294,19 +3280,20 @@ pub const DeclGen = struct {...@@ -3294,19 +3280,20 @@ pub const DeclGen = struct {
3294 fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef {3280 fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef {
3295 _ = modifier;3281 _ = modifier;
32963282
3283 const mod = self.module;
3297 const pl_op = self.air.instructions.items(.data)[inst].pl_op;3284 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3298 const extra = self.air.extraData(Air.Call, pl_op.payload);3285 const extra = self.air.extraData(Air.Call, pl_op.payload);
3299 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);3286 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);3287 const callee_ty = self.typeOf(pl_op.operand);
3301 const zig_fn_ty = switch (callee_ty.zigTypeTag()) {3288 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
3302 .Fn => callee_ty,3289 .Fn => callee_ty,
3303 .Pointer => return self.fail("cannot call function pointers", .{}),3290 .Pointer => return self.fail("cannot call function pointers", .{}),
3304 else => unreachable,3291 else => unreachable,
3305 };3292 };
3306 const fn_info = zig_fn_ty.fnInfo();3293 const fn_info = mod.typeToFunc(zig_fn_ty).?;
3307 const return_type = fn_info.return_type;3294 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());
3310 const result_id = self.spv.allocId();3297 const result_id = self.spv.allocId();
3311 const callee_id = try self.resolve(pl_op.operand);3298 const callee_id = try self.resolve(pl_op.operand);
33123299
...@@ -3319,8 +3306,8 @@ pub const DeclGen = struct {...@@ -3319,8 +3306,8 @@ pub const DeclGen = struct {
3319 // before starting to emit OpFunctionCall instructions. Hence the3306 // before starting to emit OpFunctionCall instructions. Hence the
3320 // temporary params buffer.3307 // temporary params buffer.
3321 const arg_id = try self.resolve(arg);3308 const arg_id = try self.resolve(arg);
3322 const arg_ty = self.air.typeOf(arg);3309 const arg_ty = self.typeOf(arg);
3323 if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue;3310 if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
33243311
3325 params[n_params] = arg_id;3312 params[n_params] = arg_id;
3326 n_params += 1;3313 n_params += 1;
...@@ -3333,14 +3320,24 @@ pub const DeclGen = struct {...@@ -3333,14 +3320,24 @@ pub const DeclGen = struct {
3333 .id_ref_3 = params[0..n_params],3320 .id_ref_3 = params[0..n_params],
3334 });3321 });
33353322
3336 if (return_type.isNoReturn()) {3323 if (return_type == .noreturn_type) {
3337 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});3324 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});
3338 }3325 }
33393326
3340 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime()) {3327 if (self.liveness.isUnused(inst) or !return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
3341 return null;3328 return null;
3342 }3329 }
33433330
3344 return result_id;3331 return result_id;
3345 }3332 }
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 }
3346};3343};
src/codegen/spirv/Module.zig+4-3
...@@ -11,7 +11,8 @@ const std = @import("std");...@@ -11,7 +11,8 @@ const std = @import("std");
11const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
12const assert = std.debug.assert;12const assert = std.debug.assert;
1313
14const ZigDecl = @import("../../Module.zig").Decl;14const ZigModule = @import("../../Module.zig");
15const ZigDecl = ZigModule.Decl;
1516
16const spec = @import("spec.zig");17const spec = @import("spec.zig");
17const Word = spec.Word;18const Word = spec.Word;
...@@ -389,8 +390,8 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void {...@@ -389,8 +390,8 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void {
389/// Fetch the result-id of an OpString instruction that encodes the path of the source390/// Fetch the result-id of an OpString instruction that encodes the path of the source
390/// file of the decl. This function may also emit an OpSource with source-level information regarding391/// file of the decl. This function may also emit an OpSource with source-level information regarding
391/// the decl.392/// the decl.
392pub fn resolveSourceFileName(self: *Module, decl: *ZigDecl) !IdRef {393pub fn resolveSourceFileName(self: *Module, zig_module: *ZigModule, zig_decl: *ZigDecl) !IdRef {
393 const path = decl.getFileScope().sub_file_path;394 const path = zig_decl.getFileScope(zig_module).sub_file_path;
394 const result = try self.source_file_names.getOrPut(self.gpa, path);395 const result = try self.source_file_names.getOrPut(self.gpa, path);
395 if (!result.found_existing) {396 if (!result.found_existing) {
396 const file_result_id = self.allocId();397 const file_result_id = self.allocId();
src/crash_report.zig+4-4
...@@ -99,7 +99,7 @@ fn dumpStatusReport() !void {...@@ -99,7 +99,7 @@ fn dumpStatusReport() !void {
99 allocator,99 allocator,
100 anal.body,100 anal.body,
101 anal.body_index,101 anal.body_index,
102 block.namespace.file_scope,102 mod.namespacePtr(block.namespace).file_scope,
103 block_src_decl.src_node,103 block_src_decl.src_node,
104 6, // indent104 6, // indent
105 stderr,105 stderr,
...@@ -108,7 +108,7 @@ fn dumpStatusReport() !void {...@@ -108,7 +108,7 @@ fn dumpStatusReport() !void {
108 else => |e| return e,108 else => |e| return e,
109 };109 };
110 try stderr.writeAll(" For full context, use the command\n zig ast-check -t ");110 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);
112 try stderr.writeAll("\n\n");112 try stderr.writeAll("\n\n");
113113
114 var parent = anal.parent;114 var parent = anal.parent;
...@@ -121,7 +121,7 @@ fn dumpStatusReport() !void {...@@ -121,7 +121,7 @@ fn dumpStatusReport() !void {
121 print_zir.renderSingleInstruction(121 print_zir.renderSingleInstruction(
122 allocator,122 allocator,
123 curr.body[curr.body_index],123 curr.body[curr.body_index],
124 curr.block.namespace.file_scope,124 mod.namespacePtr(curr.block.namespace).file_scope,
125 curr_block_src_decl.src_node,125 curr_block_src_decl.src_node,
126 6, // indent126 6, // indent
127 stderr,127 stderr,
...@@ -148,7 +148,7 @@ fn writeFilePath(file: *Module.File, stream: anytype) !void {...@@ -148,7 +148,7 @@ fn writeFilePath(file: *Module.File, stream: anytype) !void {
148}148}
149149
150fn writeFullyQualifiedDeclWithFile(mod: *Module, decl: *Decl, stream: anytype) !void {150fn writeFullyQualifiedDeclWithFile(mod: *Module, decl: *Decl, stream: anytype) !void {
151 try writeFilePath(decl.getFileScope(), stream);151 try writeFilePath(decl.getFileScope(mod), stream);
152 try stream.writeAll(": ");152 try stream.writeAll(": ");
153 try decl.renderFullyQualifiedDebugName(mod, stream);153 try decl.renderFullyQualifiedDebugName(mod, stream);
154}154}
src/link.zig+13-24
...@@ -502,8 +502,6 @@ pub const File = struct {...@@ -502,8 +502,6 @@ pub const File = struct {
502 /// of the final binary.502 /// of the final binary.
503 pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: Module.Decl.Index) UpdateDeclError!u32 {503 pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: Module.Decl.Index) UpdateDeclError!u32 {
504 if (build_options.only_c) @compileError("unreachable");504 if (build_options.only_c) @compileError("unreachable");
505 const decl = base.options.module.?.declPtr(decl_index);
506 log.debug("lowerUnnamedConst {*} ({s})", .{ decl, decl.name });
507 switch (base.tag) {505 switch (base.tag) {
508 // zig fmt: off506 // zig fmt: off
509 .coff => return @fieldParentPtr(Coff, "base", base).lowerUnnamedConst(tv, decl_index),507 .coff => return @fieldParentPtr(Coff, "base", base).lowerUnnamedConst(tv, decl_index),
...@@ -543,7 +541,6 @@ pub const File = struct {...@@ -543,7 +541,6 @@ pub const File = struct {
543 /// May be called before or after updateDeclExports for any given Decl.541 /// May be called before or after updateDeclExports for any given Decl.
544 pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void {542 pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void {
545 const decl = module.declPtr(decl_index);543 const decl = module.declPtr(decl_index);
546 log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmt(module) });
547 assert(decl.has_tv);544 assert(decl.has_tv);
548 if (build_options.only_c) {545 if (build_options.only_c) {
549 assert(base.tag == .c);546 assert(base.tag == .c);
...@@ -564,34 +561,27 @@ pub const File = struct {...@@ -564,34 +561,27 @@ pub const File = struct {
564 }561 }
565562
566 /// May be called before or after updateDeclExports for any given Decl.563 /// 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 {564 pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, 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 });
572 if (build_options.only_c) {565 if (build_options.only_c) {
573 assert(base.tag == .c);566 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);
575 }568 }
576 switch (base.tag) {569 switch (base.tag) {
577 // zig fmt: off570 // zig fmt: off
578 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func, air, liveness),571 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func_index, air, liveness),
579 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func, air, liveness),572 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func_index, air, liveness),
580 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func, air, liveness),573 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func_index, air, liveness),
581 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func, air, liveness),574 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness),
582 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func, air, liveness),575 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func_index, air, liveness),
583 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func, air, liveness),576 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func_index, air, liveness),
584 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func, air, liveness),577 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func_index, air, liveness),
585 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func, air, liveness),578 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func_index, air, liveness),
586 // zig fmt: on579 // zig fmt: on
587 }580 }
588 }581 }
589582
590 pub fn updateDeclLineNumber(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void {583 pub fn updateDeclLineNumber(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void {
591 const decl = module.declPtr(decl_index);584 const decl = module.declPtr(decl_index);
592 log.debug("updateDeclLineNumber {*} ({s}), line={}", .{
593 decl, decl.name, decl.src_line + 1,
594 });
595 assert(decl.has_tv);585 assert(decl.has_tv);
596 if (build_options.only_c) {586 if (build_options.only_c) {
597 assert(base.tag == .c);587 assert(base.tag == .c);
...@@ -867,7 +857,6 @@ pub const File = struct {...@@ -867,7 +857,6 @@ pub const File = struct {
867 exports: []const *Module.Export,857 exports: []const *Module.Export,
868 ) UpdateDeclExportsError!void {858 ) UpdateDeclExportsError!void {
869 const decl = module.declPtr(decl_index);859 const decl = module.declPtr(decl_index);
870 log.debug("updateDeclExports {*} ({s})", .{ decl, decl.name });
871 assert(decl.has_tv);860 assert(decl.has_tv);
872 if (build_options.only_c) {861 if (build_options.only_c) {
873 assert(base.tag == .c);862 assert(base.tag == .c);
...@@ -1124,13 +1113,13 @@ pub const File = struct {...@@ -1124,13 +1113,13 @@ pub const File = struct {
11241113
1125 pub fn initDecl(kind: Kind, decl: ?Module.Decl.Index, mod: *Module) LazySymbol {1114 pub fn initDecl(kind: Kind, decl: ?Module.Decl.Index, mod: *Module) LazySymbol {
1126 return .{ .kind = kind, .ty = if (decl) |decl_index|1115 return .{ .kind = kind, .ty = if (decl) |decl_index|
1127 mod.declPtr(decl_index).val.castTag(.ty).?.data1116 mod.declPtr(decl_index).val.toType()
1128 else1117 else
1129 Type.anyerror };1118 Type.anyerror };
1130 }1119 }
11311120
1132 pub fn getDecl(self: LazySymbol) Module.Decl.OptionalIndex {1121 pub fn getDecl(self: LazySymbol, mod: *Module) Module.Decl.OptionalIndex {
1133 return Module.Decl.OptionalIndex.init(self.ty.getOwnerDeclOrNull());1122 return Module.Decl.OptionalIndex.init(self.ty.getOwnerDeclOrNull(mod));
1134 }1123 }
1135 };1124 };
11361125
src/link/C.zig+10-7
...@@ -6,6 +6,7 @@ const fs = std.fs;...@@ -6,6 +6,7 @@ const fs = std.fs;
66
7const C = @This();7const C = @This();
8const Module = @import("../Module.zig");8const Module = @import("../Module.zig");
9const InternPool = @import("../InternPool.zig");
9const Compilation = @import("../Compilation.zig");10const Compilation = @import("../Compilation.zig");
10const codegen = @import("../codegen/c.zig");11const codegen = @import("../codegen/c.zig");
11const link = @import("../link.zig");12const link = @import("../link.zig");
...@@ -87,12 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {...@@ -87,12 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
87 }88 }
88}89}
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 {
91 const tracy = trace(@src());92 const tracy = trace(@src());
92 defer tracy.end();93 defer tracy.end();
9394
94 const gpa = self.base.allocator;95 const gpa = self.base.allocator;
9596
97 const func = module.funcPtr(func_index);
96 const decl_index = func.owner_decl;98 const decl_index = func.owner_decl;
97 const gop = try self.decl_table.getOrPut(gpa, decl_index);99 const gop = try self.decl_table.getOrPut(gpa, decl_index);
98 if (!gop.found_existing) {100 if (!gop.found_existing) {
...@@ -111,7 +113,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes...@@ -111,7 +113,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
111 .value_map = codegen.CValueMap.init(gpa),113 .value_map = codegen.CValueMap.init(gpa),
112 .air = air,114 .air = air,
113 .liveness = liveness,115 .liveness = liveness,
114 .func = func,116 .func_index = func_index,
115 .object = .{117 .object = .{
116 .dg = .{118 .dg = .{
117 .gpa = gpa,119 .gpa = gpa,
...@@ -288,11 +290,11 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo...@@ -288,11 +290,11 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
288 }290 }
289291
290 {292 {
291 var export_names = std.StringHashMapUnmanaged(void){};293 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
292 defer export_names.deinit(gpa);294 defer export_names.deinit(gpa);
293 try export_names.ensureTotalCapacity(gpa, @intCast(u32, module.decl_exports.entries.len));295 try export_names.ensureTotalCapacity(gpa, @intCast(u32, module.decl_exports.entries.len));
294 for (module.decl_exports.values()) |exports| for (exports.items) |@"export"|296 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
297 while (f.remaining_decls.popOrNull()) |kv| {299 while (f.remaining_decls.popOrNull()) |kv| {
298 const decl_index = kv.key;300 const decl_index = kv.key;
...@@ -552,10 +554,11 @@ fn flushDecl(...@@ -552,10 +554,11 @@ fn flushDecl(
552 self: *C,554 self: *C,
553 f: *Flush,555 f: *Flush,
554 decl_index: Module.Decl.Index,556 decl_index: Module.Decl.Index,
555 export_names: std.StringHashMapUnmanaged(void),557 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
556) FlushDeclError!void {558) FlushDeclError!void {
557 const gpa = self.base.allocator;559 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);
559 // Before flushing any particular Decl we must ensure its562 // Before flushing any particular Decl we must ensure its
560 // dependencies are already flushed, so that the order in the .c563 // dependencies are already flushed, so that the order in the .c
561 // file comes out correctly.564 // file comes out correctly.
...@@ -569,7 +572,7 @@ fn flushDecl(...@@ -569,7 +572,7 @@ fn flushDecl(
569572
570 try self.flushLazyFns(f, decl_block.lazy_fns);573 try self.flushLazyFns(f, decl_block.lazy_fns);
571 try f.all_buffers.ensureUnusedCapacity(gpa, 1);574 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)))
573 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);576 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
574}577}
575578
src/link/Coff.zig+71-66
...@@ -1032,20 +1032,21 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {...@@ -1032,20 +1032,21 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
1032 self.getAtomPtr(atom_index).sym_index = 0;1032 self.getAtomPtr(atom_index).sym_index = 0;
1033}1033}
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 {
1036 if (build_options.skip_non_native and builtin.object_format != .coff) {1036 if (build_options.skip_non_native and builtin.object_format != .coff) {
1037 @panic("Attempted to compile for object format that was disabled by build configuration");1037 @panic("Attempted to compile for object format that was disabled by build configuration");
1038 }1038 }
1039 if (build_options.have_llvm) {1039 if (build_options.have_llvm) {
1040 if (self.llvm_object) |llvm_object| {1040 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);
1042 }1042 }
1043 }1043 }
1044 const tracy = trace(@src());1044 const tracy = trace(@src());
1045 defer tracy.end();1045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);
1047 const decl_index = func.owner_decl;1048 const decl_index = func.owner_decl;
1048 const decl = module.declPtr(decl_index);1049 const decl = mod.declPtr(decl_index);
10491050
1050 const atom_index = try self.getOrCreateAtomForDecl(decl_index);1051 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
1051 self.freeUnnamedConsts(decl_index);1052 self.freeUnnamedConsts(decl_index);
...@@ -1056,8 +1057,8 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live...@@ -1056,8 +1057,8 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live
10561057
1057 const res = try codegen.generateFunction(1058 const res = try codegen.generateFunction(
1058 &self.base,1059 &self.base,
1059 decl.srcLoc(),1060 decl.srcLoc(mod),
1060 func,1061 func_index,
1061 air,1062 air,
1062 liveness,1063 liveness,
1063 &code_buffer,1064 &code_buffer,
...@@ -1067,7 +1068,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live...@@ -1067,7 +1068,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live
1067 .ok => code_buffer.items,1068 .ok => code_buffer.items,
1068 .fail => |em| {1069 .fail => |em| {
1069 decl.analysis = .codegen_failure;1070 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);
1071 return;1072 return;
1072 },1073 },
1073 };1074 };
...@@ -1076,7 +1077,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live...@@ -1076,7 +1077,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live
10761077
1077 // Since we updated the vaddr and the size, each corresponding export1078 // Since we updated the vaddr and the size, each corresponding export
1078 // symbol also needs to be updated.1079 // 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));
1080}1081}
10811082
1082pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {1083pub 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...@@ -1096,8 +1097,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
1096 const atom_index = try self.createAtom();1097 const atom_index = try self.createAtom();
10971098
1098 const sym_name = blk: {1099 const sym_name = blk: {
1099 const decl_name = try decl.getFullyQualifiedName(mod);1100 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1100 defer gpa.free(decl_name);
11011101
1102 const index = unnamed_consts.items.len;1102 const index = unnamed_consts.items.len;
1103 break :blk try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });1103 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...@@ -1110,7 +1110,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
1110 sym.section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.? + 1);1110 sym.section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.? + 1);
1111 }1111 }
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, .{
1114 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,1114 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
1115 });1115 });
1116 var code = switch (res) {1116 var code = switch (res) {
...@@ -1123,7 +1123,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In...@@ -1123,7 +1123,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
1123 },1123 },
1124 };1124 };
11251125
1126 const required_alignment = tv.ty.abiAlignment(self.base.options.target);1126 const required_alignment = tv.ty.abiAlignment(mod);
1127 const atom = self.getAtomPtr(atom_index);1127 const atom = self.getAtomPtr(atom_index);
1128 atom.size = @intCast(u32, code.len);1128 atom.size = @intCast(u32, code.len);
1129 atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment);1129 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...@@ -1141,25 +1141,24 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
11411141
1142pub fn updateDecl(1142pub fn updateDecl(
1143 self: *Coff,1143 self: *Coff,
1144 module: *Module,1144 mod: *Module,
1145 decl_index: Module.Decl.Index,1145 decl_index: Module.Decl.Index,
1146) link.File.UpdateDeclError!void {1146) link.File.UpdateDeclError!void {
1147 if (build_options.skip_non_native and builtin.object_format != .coff) {1147 if (build_options.skip_non_native and builtin.object_format != .coff) {
1148 @panic("Attempted to compile for object format that was disabled by build configuration");1148 @panic("Attempted to compile for object format that was disabled by build configuration");
1149 }1149 }
1150 if (build_options.have_llvm) {1150 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);
1152 }1152 }
1153 const tracy = trace(@src());1153 const tracy = trace(@src());
1154 defer tracy.end();1154 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)) |_| {
1159 return; // TODO Should we do more when front-end analyzed extern decl?1159 return; // TODO Should we do more when front-end analyzed extern decl?
1160 }1160 }
1161 if (decl.val.castTag(.variable)) |payload| {1161 if (decl.val.getVariable(mod)) |variable| {
1162 const variable = payload.data;
1163 if (variable.is_extern) {1162 if (variable.is_extern) {
1164 return; // TODO Should we do more when front-end analyzed extern decl?1163 return; // TODO Should we do more when front-end analyzed extern decl?
1165 }1164 }
...@@ -1172,8 +1171,8 @@ pub fn updateDecl(...@@ -1172,8 +1171,8 @@ pub fn updateDecl(
1172 var code_buffer = std.ArrayList(u8).init(self.base.allocator);1171 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
1173 defer code_buffer.deinit();1172 defer code_buffer.deinit();
11741173
1175 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;1174 const decl_val = if (decl.val.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
1176 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{1175 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
1177 .ty = decl.ty,1176 .ty = decl.ty,
1178 .val = decl_val,1177 .val = decl_val,
1179 }, &code_buffer, .none, .{1178 }, &code_buffer, .none, .{
...@@ -1183,7 +1182,7 @@ pub fn updateDecl(...@@ -1183,7 +1182,7 @@ pub fn updateDecl(
1183 .ok => code_buffer.items,1182 .ok => code_buffer.items,
1184 .fail => |em| {1183 .fail => |em| {
1185 decl.analysis = .codegen_failure;1184 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);
1187 return;1186 return;
1188 },1187 },
1189 };1188 };
...@@ -1192,7 +1191,7 @@ pub fn updateDecl(...@@ -1192,7 +1191,7 @@ pub fn updateDecl(
11921191
1193 // Since we updated the vaddr and the size, each corresponding export1192 // Since we updated the vaddr and the size, each corresponding export
1194 // symbol also needs to be updated.1193 // 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));
1196}1195}
11971196
1198fn updateLazySymbolAtom(1197fn updateLazySymbolAtom(
...@@ -1217,8 +1216,8 @@ fn updateLazySymbolAtom(...@@ -1217,8 +1216,8 @@ fn updateLazySymbolAtom(
1217 const atom = self.getAtomPtr(atom_index);1216 const atom = self.getAtomPtr(atom_index);
1218 const local_sym_index = atom.getSymbolIndex().?;1217 const local_sym_index = atom.getSymbolIndex().?;
12191218
1220 const src = if (sym.ty.getOwnerDeclOrNull()) |owner_decl|1219 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|
1221 mod.declPtr(owner_decl).srcLoc()1220 mod.declPtr(owner_decl).srcLoc(mod)
1222 else1221 else
1223 Module.SrcLoc{1222 Module.SrcLoc{
1224 .file_scope = undefined,1223 .file_scope = undefined,
...@@ -1262,7 +1261,8 @@ fn updateLazySymbolAtom(...@@ -1262,7 +1261,8 @@ fn updateLazySymbolAtom(
1262}1261}
12631262
1264pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index {1263pub 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));
1266 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();1266 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
1267 if (!gop.found_existing) gop.value_ptr.* = .{};1267 if (!gop.found_existing) gop.value_ptr.* = .{};
1268 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {1268 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...@@ -1277,7 +1277,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Ato
1277 metadata.state.* = .pending_flush;1277 metadata.state.* = .pending_flush;
1278 const atom = metadata.atom.*;1278 const atom = metadata.atom.*;
1279 // anyerror needs to be deferred until flushModule1279 // 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) {
1281 .code => self.text_section_index.?,1281 .code => self.text_section_index.?,
1282 .const_data => self.rdata_section_index.?,1282 .const_data => self.rdata_section_index.?,
1283 });1283 });
...@@ -1299,10 +1299,11 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom....@@ -1299,10 +1299,11 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom.
1299fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {1299fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
1300 const decl = self.base.options.module.?.declPtr(decl_index);1300 const decl = self.base.options.module.?.declPtr(decl_index);
1301 const ty = decl.ty;1301 const ty = decl.ty;
1302 const zig_ty = ty.zigTypeTag();1302 const mod = self.base.options.module.?;
1303 const zig_ty = ty.zigTypeTag(mod);
1303 const val = decl.val;1304 const val = decl.val;
1304 const index: u16 = blk: {1305 const index: u16 = blk: {
1305 if (val.isUndefDeep()) {1306 if (val.isUndefDeep(mod)) {
1306 // TODO in release-fast and release-small, we should put undef in .bss1307 // TODO in release-fast and release-small, we should put undef in .bss
1307 break :blk self.data_section_index.?;1308 break :blk self.data_section_index.?;
1308 }1309 }
...@@ -1311,7 +1312,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {...@@ -1311,7 +1312,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
1311 // TODO: what if this is a function pointer?1312 // TODO: what if this is a function pointer?
1312 .Fn => break :blk self.text_section_index.?,1313 .Fn => break :blk self.text_section_index.?,
1313 else => {1314 else => {
1314 if (val.castTag(.variable)) |_| {1315 if (val.getVariable(mod)) |_| {
1315 break :blk self.data_section_index.?;1316 break :blk self.data_section_index.?;
1316 }1317 }
1317 break :blk self.rdata_section_index.?;1318 break :blk self.rdata_section_index.?;
...@@ -1322,15 +1323,13 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {...@@ -1322,15 +1323,13 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
1322}1323}
13231324
1324fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, complex_type: coff.ComplexType) !void {1325fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, complex_type: coff.ComplexType) !void {
1325 const gpa = self.base.allocator;
1326 const mod = self.base.options.module.?;1326 const mod = self.base.options.module.?;
1327 const decl = mod.declPtr(decl_index);1327 const decl = mod.declPtr(decl_index);
13281328
1329 const decl_name = try decl.getFullyQualifiedName(mod);1329 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1330 defer gpa.free(decl_name);
13311330
1332 log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });1331 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
1335 const decl_metadata = self.decls.get(decl_index).?;1334 const decl_metadata = self.decls.get(decl_index).?;
1336 const atom_index = decl_metadata.atom;1335 const atom_index = decl_metadata.atom;
...@@ -1410,7 +1409,7 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void {...@@ -1410,7 +1409,7 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void {
14101409
1411pub fn updateDeclExports(1410pub fn updateDeclExports(
1412 self: *Coff,1411 self: *Coff,
1413 module: *Module,1412 mod: *Module,
1414 decl_index: Module.Decl.Index,1413 decl_index: Module.Decl.Index,
1415 exports: []const *Module.Export,1414 exports: []const *Module.Export,
1416) link.File.UpdateDeclExportsError!void {1415) link.File.UpdateDeclExportsError!void {
...@@ -1418,61 +1417,60 @@ pub fn updateDeclExports(...@@ -1418,61 +1417,60 @@ pub fn updateDeclExports(
1418 @panic("Attempted to compile for object format that was disabled by build configuration");1417 @panic("Attempted to compile for object format that was disabled by build configuration");
1419 }1418 }
14201419
1420 const ip = &mod.intern_pool;
1421
1421 if (build_options.have_llvm) {1422 if (build_options.have_llvm) {
1422 // Even in the case of LLVM, we need to notice certain exported symbols in order to1423 // Even in the case of LLVM, we need to notice certain exported symbols in order to
1423 // detect the default subsystem.1424 // detect the default subsystem.
1424 for (exports) |exp| {1425 for (exports) |exp| {
1425 const exported_decl = module.declPtr(exp.exported_decl);1426 const exported_decl = mod.declPtr(exp.exported_decl);
1426 if (exported_decl.getFunction() == null) continue;1427 if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;
1427 const winapi_cc = switch (self.base.options.target.cpu.arch) {1428 const winapi_cc = switch (self.base.options.target.cpu.arch) {
1428 .x86 => std.builtin.CallingConvention.Stdcall,1429 .x86 => std.builtin.CallingConvention.Stdcall,
1429 else => std.builtin.CallingConvention.C,1430 else => std.builtin.CallingConvention.C,
1430 };1431 };
1431 const decl_cc = exported_decl.ty.fnCallingConvention();1432 const decl_cc = exported_decl.ty.fnCallingConvention(mod);
1432 if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and1433 if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and
1433 self.base.options.link_libc)1434 self.base.options.link_libc)
1434 {1435 {
1435 module.stage1_flags.have_c_main = true;1436 mod.stage1_flags.have_c_main = true;
1436 } else if (decl_cc == winapi_cc and self.base.options.target.os.tag == .windows) {1437 } else if (decl_cc == winapi_cc and self.base.options.target.os.tag == .windows) {
1437 if (mem.eql(u8, exp.options.name, "WinMain")) {1438 if (ip.stringEqlSlice(exp.opts.name, "WinMain")) {
1438 module.stage1_flags.have_winmain = true;1439 mod.stage1_flags.have_winmain = true;
1439 } else if (mem.eql(u8, exp.options.name, "wWinMain")) {1440 } else if (ip.stringEqlSlice(exp.opts.name, "wWinMain")) {
1440 module.stage1_flags.have_wwinmain = true;1441 mod.stage1_flags.have_wwinmain = true;
1441 } else if (mem.eql(u8, exp.options.name, "WinMainCRTStartup")) {1442 } else if (ip.stringEqlSlice(exp.opts.name, "WinMainCRTStartup")) {
1442 module.stage1_flags.have_winmain_crt_startup = true;1443 mod.stage1_flags.have_winmain_crt_startup = true;
1443 } else if (mem.eql(u8, exp.options.name, "wWinMainCRTStartup")) {1444 } else if (ip.stringEqlSlice(exp.opts.name, "wWinMainCRTStartup")) {
1444 module.stage1_flags.have_wwinmain_crt_startup = true;1445 mod.stage1_flags.have_wwinmain_crt_startup = true;
1445 } else if (mem.eql(u8, exp.options.name, "DllMainCRTStartup")) {1446 } else if (ip.stringEqlSlice(exp.opts.name, "DllMainCRTStartup")) {
1446 module.stage1_flags.have_dllmain_crt_startup = true;1447 mod.stage1_flags.have_dllmain_crt_startup = true;
1447 }1448 }
1448 }1449 }
1449 }1450 }
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);
1452 }1453 }
14531454
1454 const tracy = trace(@src());
1455 defer tracy.end();
1456
1457 const gpa = self.base.allocator;1455 const gpa = self.base.allocator;
14581456
1459 const decl = module.declPtr(decl_index);1457 const decl = mod.declPtr(decl_index);
1460 const atom_index = try self.getOrCreateAtomForDecl(decl_index);1458 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
1461 const atom = self.getAtom(atom_index);1459 const atom = self.getAtom(atom_index);
1462 const decl_sym = atom.getSymbol(self);1460 const decl_sym = atom.getSymbol(self);
1463 const decl_metadata = self.decls.getPtr(decl_index).?;1461 const decl_metadata = self.decls.getPtr(decl_index).?;
14641462
1465 for (exports) |exp| {1463 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| {
1469 if (!mem.eql(u8, section_name, ".text")) {1467 if (!mem.eql(u8, section_name, ".text")) {
1470 try module.failed_exports.putNoClobber(1468 try mod.failed_exports.putNoClobber(
1471 module.gpa,1469 gpa,
1472 exp,1470 exp,
1473 try Module.ErrorMsg.create(1471 try Module.ErrorMsg.create(
1474 gpa,1472 gpa,
1475 decl.srcLoc(),1473 decl.srcLoc(mod),
1476 "Unimplemented: ExportOptions.section",1474 "Unimplemented: ExportOptions.section",
1477 .{},1475 .{},
1478 ),1476 ),
...@@ -1481,13 +1479,13 @@ pub fn updateDeclExports(...@@ -1481,13 +1479,13 @@ pub fn updateDeclExports(
1481 }1479 }
1482 }1480 }
14831481
1484 if (exp.options.linkage == .LinkOnce) {1482 if (exp.opts.linkage == .LinkOnce) {
1485 try module.failed_exports.putNoClobber(1483 try mod.failed_exports.putNoClobber(
1486 module.gpa,1484 gpa,
1487 exp,1485 exp,
1488 try Module.ErrorMsg.create(1486 try Module.ErrorMsg.create(
1489 gpa,1487 gpa,
1490 decl.srcLoc(),1488 decl.srcLoc(mod),
1491 "Unimplemented: GlobalLinkage.LinkOnce",1489 "Unimplemented: GlobalLinkage.LinkOnce",
1492 .{},1490 .{},
1493 ),1491 ),
...@@ -1495,19 +1493,19 @@ pub fn updateDeclExports(...@@ -1495,19 +1493,19 @@ pub fn updateDeclExports(
1495 continue;1493 continue;
1496 }1494 }
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: {
1499 const sym_index = try self.allocateSymbol();1497 const sym_index = try self.allocateSymbol();
1500 try decl_metadata.exports.append(gpa, sym_index);1498 try decl_metadata.exports.append(gpa, sym_index);
1501 break :blk sym_index;1499 break :blk sym_index;
1502 };1500 };
1503 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };1501 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
1504 const sym = self.getSymbolPtr(sym_loc);1502 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));
1506 sym.value = decl_sym.value;1504 sym.value = decl_sym.value;
1507 sym.section_number = @intToEnum(coff.SectionNumber, self.text_section_index.? + 1);1505 sym.section_number = @intToEnum(coff.SectionNumber, self.text_section_index.? + 1);
1508 sym.type = .{ .complex_type = .FUNCTION, .base_type = .NULL };1506 sym.type = .{ .complex_type = .FUNCTION, .base_type = .NULL };
15091507
1510 switch (exp.options.linkage) {1508 switch (exp.opts.linkage) {
1511 .Strong => {1509 .Strong => {
1512 sym.storage_class = .EXTERNAL;1510 sym.storage_class = .EXTERNAL;
1513 },1511 },
...@@ -1520,9 +1518,15 @@ pub fn updateDeclExports(...@@ -1520,9 +1518,15 @@ pub fn updateDeclExports(
1520 }1518 }
1521}1519}
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 {
1524 if (self.llvm_object) |_| return;1526 if (self.llvm_object) |_| return;
1525 const metadata = self.decls.getPtr(decl_index) orelse return;1527 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);
1526 const sym_index = metadata.getExportPtr(self, name) orelse return;1530 const sym_index = metadata.getExportPtr(self, name) orelse return;
15271531
1528 const gpa = self.base.allocator;1532 const gpa = self.base.allocator;
...@@ -2538,6 +2542,7 @@ const ImportTable = @import("Coff/ImportTable.zig");...@@ -2538,6 +2542,7 @@ const ImportTable = @import("Coff/ImportTable.zig");
2538const Liveness = @import("../Liveness.zig");2542const Liveness = @import("../Liveness.zig");
2539const LlvmObject = @import("../codegen/llvm.zig").Object;2543const LlvmObject = @import("../codegen/llvm.zig").Object;
2540const Module = @import("../Module.zig");2544const Module = @import("../Module.zig");
2545const InternPool = @import("../InternPool.zig");
2541const Object = @import("Coff/Object.zig");2546const Object = @import("Coff/Object.zig");
2542const Relocation = @import("Coff/Relocation.zig");2547const Relocation = @import("Coff/Relocation.zig");
2543const TableSection = @import("table_section.zig").TableSection;2548const TableSection = @import("table_section.zig").TableSection;
src/link/Dwarf.zig+119-136
...@@ -18,6 +18,7 @@ const LinkBlock = File.LinkBlock;...@@ -18,6 +18,7 @@ const LinkBlock = File.LinkBlock;
18const LinkFn = File.LinkFn;18const LinkFn = File.LinkFn;
19const LinkerLoad = @import("../codegen.zig").LinkerLoad;19const LinkerLoad = @import("../codegen.zig").LinkerLoad;
20const Module = @import("../Module.zig");20const Module = @import("../Module.zig");
21const InternPool = @import("../InternPool.zig");
21const StringTable = @import("strtab.zig").StringTable;22const StringTable = @import("strtab.zig").StringTable;
22const Type = @import("../type.zig").Type;23const Type = @import("../type.zig").Type;
23const Value = @import("../value.zig").Value;24const Value = @import("../value.zig").Value;
...@@ -86,12 +87,7 @@ pub const DeclState = struct {...@@ -86,12 +87,7 @@ pub const DeclState = struct {
86 dbg_info: std.ArrayList(u8),87 dbg_info: std.ArrayList(u8),
87 abbrev_type_arena: std.heap.ArenaAllocator,88 abbrev_type_arena: std.heap.ArenaAllocator,
88 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{},89 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{},
89 abbrev_resolver: std.HashMapUnmanaged(90 abbrev_resolver: std.AutoHashMapUnmanaged(InternPool.Index, u32) = .{},
90 Type,
91 u32,
92 Type.HashContext64,
93 std.hash_map.default_max_load_percentage,
94 ) = .{},
95 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},91 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},
96 exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{},92 exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{},
9793
...@@ -141,9 +137,7 @@ pub const DeclState = struct {...@@ -141,9 +137,7 @@ pub const DeclState = struct {
141 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section137 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section
142 /// which we use as our target of the relocation.138 /// which we use as our target of the relocation.
143 fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void {139 fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void {
144 const resolv = self.abbrev_resolver.getContext(ty, .{140 const resolv = self.abbrev_resolver.get(ty.toIntern()) orelse blk: {
145 .mod = self.mod,
146 }) orelse blk: {
147 const sym_index = @intCast(u32, self.abbrev_table.items.len);141 const sym_index = @intCast(u32, self.abbrev_table.items.len);
148 try self.abbrev_table.append(self.gpa, .{142 try self.abbrev_table.append(self.gpa, .{
149 .atom_index = atom_index,143 .atom_index = atom_index,
...@@ -151,12 +145,8 @@ pub const DeclState = struct {...@@ -151,12 +145,8 @@ pub const DeclState = struct {
151 .offset = undefined,145 .offset = undefined,
152 });146 });
153 log.debug("%{d}: {}", .{ sym_index, ty.fmt(self.mod) });147 log.debug("%{d}: {}", .{ sym_index, ty.fmt(self.mod) });
154 try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{148 try self.abbrev_resolver.putNoClobber(self.gpa, ty.toIntern(), sym_index);
155 .mod = self.mod,149 break :blk sym_index;
156 });
157 break :blk self.abbrev_resolver.getContext(ty, .{
158 .mod = self.mod,
159 }).?;
160 };150 };
161 log.debug("{x}: %{d} + 0", .{ offset, resolv });151 log.debug("{x}: %{d} + 0", .{ offset, resolv });
162 try self.abbrev_relocs.append(self.gpa, .{152 try self.abbrev_relocs.append(self.gpa, .{
...@@ -169,16 +159,16 @@ pub const DeclState = struct {...@@ -169,16 +159,16 @@ pub const DeclState = struct {
169159
170 fn addDbgInfoType(160 fn addDbgInfoType(
171 self: *DeclState,161 self: *DeclState,
172 module: *Module,162 mod: *Module,
173 atom_index: Atom.Index,163 atom_index: Atom.Index,
174 ty: Type,164 ty: Type,
175 ) error{OutOfMemory}!void {165 ) error{OutOfMemory}!void {
176 const arena = self.abbrev_type_arena.allocator();166 const arena = self.abbrev_type_arena.allocator();
177 const dbg_info_buffer = &self.dbg_info;167 const dbg_info_buffer = &self.dbg_info;
178 const target = module.getTarget();168 const target = mod.getTarget();
179 const target_endian = target.cpu.arch.endian();169 const target_endian = target.cpu.arch.endian();
180170
181 switch (ty.zigTypeTag()) {171 switch (ty.zigTypeTag(mod)) {
182 .NoReturn => unreachable,172 .NoReturn => unreachable,
183 .Void => {173 .Void => {
184 try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1));174 try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1));
...@@ -189,12 +179,12 @@ pub const DeclState = struct {...@@ -189,12 +179,12 @@ pub const DeclState = struct {
189 // DW.AT.encoding, DW.FORM.data1179 // DW.AT.encoding, DW.FORM.data1
190 dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean);180 dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean);
191 // DW.AT.byte_size, DW.FORM.udata181 // 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));
193 // DW.AT.name, DW.FORM.string183 // 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)});
195 },185 },
196 .Int => {186 .Int => {
197 const info = ty.intInfo(target);187 const info = ty.intInfo(mod);
198 try dbg_info_buffer.ensureUnusedCapacity(12);188 try dbg_info_buffer.ensureUnusedCapacity(12);
199 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));189 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
200 // DW.AT.encoding, DW.FORM.data1190 // DW.AT.encoding, DW.FORM.data1
...@@ -203,31 +193,30 @@ pub const DeclState = struct {...@@ -203,31 +193,30 @@ pub const DeclState = struct {
203 .unsigned => DW.ATE.unsigned,193 .unsigned => DW.ATE.unsigned,
204 });194 });
205 // DW.AT.byte_size, DW.FORM.udata195 // 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));
207 // DW.AT.name, DW.FORM.string197 // 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)});
209 },199 },
210 .Optional => {200 .Optional => {
211 if (ty.isPtrLikeOptional()) {201 if (ty.isPtrLikeOptional(mod)) {
212 try dbg_info_buffer.ensureUnusedCapacity(12);202 try dbg_info_buffer.ensureUnusedCapacity(12);
213 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));203 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
214 // DW.AT.encoding, DW.FORM.data1204 // DW.AT.encoding, DW.FORM.data1
215 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);205 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);
216 // DW.AT.byte_size, DW.FORM.udata206 // 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));
218 // DW.AT.name, DW.FORM.string208 // 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)});
220 } else {210 } else {
221 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }211 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }
222 var buf = try arena.create(Type.Payload.ElemType);212 const payload_ty = ty.optionalChild(mod);
223 const payload_ty = ty.optionalChild(buf);
224 // DW.AT.structure_type213 // DW.AT.structure_type
225 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));214 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
226 // DW.AT.byte_size, DW.FORM.udata215 // DW.AT.byte_size, DW.FORM.udata
227 const abi_size = ty.abiSize(target);216 const abi_size = ty.abiSize(mod);
228 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);217 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
229 // DW.AT.name, DW.FORM.string218 // 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)});
231 // DW.AT.member220 // DW.AT.member
232 try dbg_info_buffer.ensureUnusedCapacity(7);221 try dbg_info_buffer.ensureUnusedCapacity(7);
233 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));222 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
...@@ -251,14 +240,14 @@ pub const DeclState = struct {...@@ -251,14 +240,14 @@ pub const DeclState = struct {
251 try dbg_info_buffer.resize(index + 4);240 try dbg_info_buffer.resize(index + 4);
252 try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(u32, index));241 try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(u32, index));
253 // DW.AT.data_member_location, DW.FORM.udata242 // 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);
255 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);244 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
256 // DW.AT.structure_type delimit children245 // DW.AT.structure_type delimit children
257 try dbg_info_buffer.append(0);246 try dbg_info_buffer.append(0);
258 }247 }
259 },248 },
260 .Pointer => {249 .Pointer => {
261 if (ty.isSlice()) {250 if (ty.isSlice(mod)) {
262 // Slices are structs: struct { .ptr = *, .len = N }251 // Slices are structs: struct { .ptr = *, .len = N }
263 const ptr_bits = target.ptrBitWidth();252 const ptr_bits = target.ptrBitWidth();
264 const ptr_bytes = @intCast(u8, @divExact(ptr_bits, 8));253 const ptr_bytes = @intCast(u8, @divExact(ptr_bits, 8));
...@@ -266,9 +255,9 @@ pub const DeclState = struct {...@@ -266,9 +255,9 @@ pub const DeclState = struct {
266 try dbg_info_buffer.ensureUnusedCapacity(2);255 try dbg_info_buffer.ensureUnusedCapacity(2);
267 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_type));256 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_type));
268 // DW.AT.byte_size, DW.FORM.udata257 // 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));
270 // DW.AT.name, DW.FORM.string259 // 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)});
272 // DW.AT.member261 // DW.AT.member
273 try dbg_info_buffer.ensureUnusedCapacity(5);262 try dbg_info_buffer.ensureUnusedCapacity(5);
274 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));263 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
...@@ -278,8 +267,7 @@ pub const DeclState = struct {...@@ -278,8 +267,7 @@ pub const DeclState = struct {
278 // DW.AT.type, DW.FORM.ref4267 // DW.AT.type, DW.FORM.ref4
279 var index = dbg_info_buffer.items.len;268 var index = dbg_info_buffer.items.len;
280 try dbg_info_buffer.resize(index + 4);269 try dbg_info_buffer.resize(index + 4);
281 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);270 const ptr_ty = ty.slicePtrFieldType(mod);
282 const ptr_ty = ty.slicePtrFieldType(buf);
283 try self.addTypeRelocGlobal(atom_index, ptr_ty, @intCast(u32, index));271 try self.addTypeRelocGlobal(atom_index, ptr_ty, @intCast(u32, index));
284 // DW.AT.data_member_location, DW.FORM.udata272 // DW.AT.data_member_location, DW.FORM.udata
285 try dbg_info_buffer.ensureUnusedCapacity(6);273 try dbg_info_buffer.ensureUnusedCapacity(6);
...@@ -304,18 +292,18 @@ pub const DeclState = struct {...@@ -304,18 +292,18 @@ pub const DeclState = struct {
304 // DW.AT.type, DW.FORM.ref4292 // DW.AT.type, DW.FORM.ref4
305 const index = dbg_info_buffer.items.len;293 const index = dbg_info_buffer.items.len;
306 try dbg_info_buffer.resize(index + 4);294 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));
308 }296 }
309 },297 },
310 .Array => {298 .Array => {
311 // DW.AT.array_type299 // DW.AT.array_type
312 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_type));300 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_type));
313 // DW.AT.name, DW.FORM.string301 // 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)});
315 // DW.AT.type, DW.FORM.ref4303 // DW.AT.type, DW.FORM.ref4
316 var index = dbg_info_buffer.items.len;304 var index = dbg_info_buffer.items.len;
317 try dbg_info_buffer.resize(index + 4);305 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));
319 // DW.AT.subrange_type307 // DW.AT.subrange_type
320 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_dim));308 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_dim));
321 // DW.AT.type, DW.FORM.ref4309 // DW.AT.type, DW.FORM.ref4
...@@ -323,7 +311,7 @@ pub const DeclState = struct {...@@ -323,7 +311,7 @@ pub const DeclState = struct {
323 try dbg_info_buffer.resize(index + 4);311 try dbg_info_buffer.resize(index + 4);
324 try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(u32, index));312 try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(u32, index));
325 // DW.AT.count, DW.FORM.udata313 // DW.AT.count, DW.FORM.udata
326 const len = ty.arrayLenIncludingSentinel();314 const len = ty.arrayLenIncludingSentinel(mod);
327 try leb128.writeULEB128(dbg_info_buffer.writer(), len);315 try leb128.writeULEB128(dbg_info_buffer.writer(), len);
328 // DW.AT.array_type delimit children316 // DW.AT.array_type delimit children
329 try dbg_info_buffer.append(0);317 try dbg_info_buffer.append(0);
...@@ -332,15 +320,14 @@ pub const DeclState = struct {...@@ -332,15 +320,14 @@ pub const DeclState = struct {
332 // DW.AT.structure_type320 // DW.AT.structure_type
333 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));321 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
334 // DW.AT.byte_size, DW.FORM.udata322 // 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()) {325 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
338 .tuple, .anon_struct => {326 .anon_struct_type => |fields| {
339 // DW.AT.name, DW.FORM.string327 // 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();330 for (fields.types, 0..) |field_ty, field_index| {
343 for (fields.types, 0..) |field, field_index| {
344 // DW.AT.member331 // DW.AT.member
345 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));332 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
346 // DW.AT.name, DW.FORM.string333 // DW.AT.name, DW.FORM.string
...@@ -348,29 +335,32 @@ pub const DeclState = struct {...@@ -348,29 +335,32 @@ pub const DeclState = struct {
348 // DW.AT.type, DW.FORM.ref4335 // DW.AT.type, DW.FORM.ref4
349 var index = dbg_info_buffer.items.len;336 var index = dbg_info_buffer.items.len;
350 try dbg_info_buffer.resize(index + 4);337 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));
352 // DW.AT.data_member_location, DW.FORM.udata339 // 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);
354 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);341 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
355 }342 }
356 },343 },
357 else => {344 .struct_type => |struct_type| s: {
345 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
358 // DW.AT.name, DW.FORM.string346 // DW.AT.name, DW.FORM.string
359 const struct_name = try ty.nameAllocArena(arena, module);347 const struct_name = try ty.nameAllocArena(arena, mod);
360 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);348 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);
361 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);349 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
362 dbg_info_buffer.appendAssumeCapacity(0);350 dbg_info_buffer.appendAssumeCapacity(0);
363351
364 const struct_obj = ty.castTag(.@"struct").?.data;
365 if (struct_obj.layout == .Packed) {352 if (struct_obj.layout == .Packed) {
366 log.debug("TODO implement .debug_info for packed structs", .{});353 log.debug("TODO implement .debug_info for packed structs", .{});
367 break :blk;354 break :blk;
368 }355 }
369356
370 const fields = ty.structFields();357 for (
371 for (fields.keys(), 0..) |field_name, field_index| {358 struct_obj.fields.keys(),
372 const field = fields.get(field_name).?;359 struct_obj.fields.values(),
373 if (!field.ty.hasRuntimeBits()) continue;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);
374 // DW.AT.member364 // DW.AT.member
375 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);365 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
376 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));366 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
...@@ -382,10 +372,11 @@ pub const DeclState = struct {...@@ -382,10 +372,11 @@ pub const DeclState = struct {
382 try dbg_info_buffer.resize(index + 4);372 try dbg_info_buffer.resize(index + 4);
383 try self.addTypeRelocGlobal(atom_index, field.ty, @intCast(u32, index));373 try self.addTypeRelocGlobal(atom_index, field.ty, @intCast(u32, index));
384 // DW.AT.data_member_location, DW.FORM.udata374 // 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);
386 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);376 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
387 }377 }
388 },378 },
379 else => unreachable,
389 }380 }
390381
391 // DW.AT.structure_type delimit children382 // DW.AT.structure_type delimit children
...@@ -395,21 +386,16 @@ pub const DeclState = struct {...@@ -395,21 +386,16 @@ pub const DeclState = struct {
395 // DW.AT.enumeration_type386 // DW.AT.enumeration_type
396 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));387 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
397 // DW.AT.byte_size, DW.FORM.udata388 // 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));
399 // DW.AT.name, DW.FORM.string390 // DW.AT.name, DW.FORM.string
400 const enum_name = try ty.nameAllocArena(arena, module);391 const enum_name = try ty.nameAllocArena(arena, mod);
401 try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1);392 try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1);
402 dbg_info_buffer.appendSliceAssumeCapacity(enum_name);393 dbg_info_buffer.appendSliceAssumeCapacity(enum_name);
403 dbg_info_buffer.appendAssumeCapacity(0);394 dbg_info_buffer.appendAssumeCapacity(0);
404395
405 const fields = ty.enumFields();396 const enum_type = mod.intern_pool.indexToKey(ty.ip_index).enum_type;
406 const values: ?Module.EnumFull.ValueMap = switch (ty.tag()) {397 for (enum_type.names, 0..) |field_name_index, field_i| {
407 .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.values,398 const field_name = mod.intern_pool.stringToSlice(field_name_index);
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| {
413 // DW.AT.enumerator399 // DW.AT.enumerator
414 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));400 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
415 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));401 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));
...@@ -417,15 +403,14 @@ pub const DeclState = struct {...@@ -417,15 +403,14 @@ pub const DeclState = struct {
417 dbg_info_buffer.appendSliceAssumeCapacity(field_name);403 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
418 dbg_info_buffer.appendAssumeCapacity(0);404 dbg_info_buffer.appendAssumeCapacity(0);
419 // DW.AT.const_value, DW.FORM.data8405 // DW.AT.const_value, DW.FORM.data8
420 const value: u64 = if (values) |vals| value: {406 const value: u64 = value: {
421 if (vals.count() == 0) break :value @intCast(u64, field_i); // auto-numbered407 if (enum_type.values.len == 0) break :value field_i; // auto-numbered
422 const value = vals.keys()[field_i];408 const value = enum_type.values[field_i];
423 // TODO do not assume a 64bit enum value - could be bigger.409 // TODO do not assume a 64bit enum value - could be bigger.
424 // See https://github.com/ziglang/zig/issues/645410 // See https://github.com/ziglang/zig/issues/645
425 var int_buffer: Value.Payload.U64 = undefined;411 const field_int_val = try value.toValue().enumToInt(ty, mod);
426 const field_int_val = value.enumToInt(ty, &int_buffer);412 break :value @bitCast(u64, field_int_val.toSignedInt(mod));
427 break :value @bitCast(u64, field_int_val.toSignedInt(target));413 };
428 } else @intCast(u64, field_i);
429 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);414 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
430 }415 }
431416
...@@ -433,12 +418,12 @@ pub const DeclState = struct {...@@ -433,12 +418,12 @@ pub const DeclState = struct {
433 try dbg_info_buffer.append(0);418 try dbg_info_buffer.append(0);
434 },419 },
435 .Union => {420 .Union => {
436 const layout = ty.unionGetLayout(target);421 const layout = ty.unionGetLayout(mod);
437 const union_obj = ty.cast(Type.Payload.Union).?.data;422 const union_obj = mod.typeToUnion(ty).?;
438 const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0;423 const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0;
439 const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size;424 const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size;
440 const is_tagged = layout.tag_size > 0;425 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
443 // TODO this is temporary to match current state of unions in Zig - we don't yet have428 // TODO this is temporary to match current state of unions in Zig - we don't yet have
444 // safety checks implemented meaning the implicit tag is not yet stored and generated429 // safety checks implemented meaning the implicit tag is not yet stored and generated
...@@ -478,14 +463,15 @@ pub const DeclState = struct {...@@ -478,14 +463,15 @@ pub const DeclState = struct {
478 try dbg_info_buffer.writer().print("{s}\x00", .{union_name});463 try dbg_info_buffer.writer().print("{s}\x00", .{union_name});
479 }464 }
480465
481 const fields = ty.unionFields();466 const fields = ty.unionFields(mod);
482 for (fields.keys()) |field_name| {467 for (fields.keys()) |field_name| {
483 const field = fields.get(field_name).?;468 const field = fields.get(field_name).?;
484 if (!field.ty.hasRuntimeBits()) continue;469 if (!field.ty.hasRuntimeBits(mod)) continue;
485 // DW.AT.member470 // DW.AT.member
486 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));471 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
487 // DW.AT.name, DW.FORM.string472 // 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);
489 // DW.AT.type, DW.FORM.ref4475 // DW.AT.type, DW.FORM.ref4
490 const index = dbg_info_buffer.items.len;476 const index = dbg_info_buffer.items.len;
491 try dbg_info_buffer.resize(index + 4);477 try dbg_info_buffer.resize(index + 4);
...@@ -517,30 +503,30 @@ pub const DeclState = struct {...@@ -517,30 +503,30 @@ pub const DeclState = struct {
517 .ErrorSet => {503 .ErrorSet => {
518 try addDbgInfoErrorSet(504 try addDbgInfoErrorSet(
519 self.abbrev_type_arena.allocator(),505 self.abbrev_type_arena.allocator(),
520 module,506 mod,
521 ty,507 ty,
522 target,508 target,
523 &self.dbg_info,509 &self.dbg_info,
524 );510 );
525 },511 },
526 .ErrorUnion => {512 .ErrorUnion => {
527 const error_ty = ty.errorUnionSet();513 const error_ty = ty.errorUnionSet(mod);
528 const payload_ty = ty.errorUnionPayload();514 const payload_ty = ty.errorUnionPayload(mod);
529 const payload_align = if (payload_ty.isNoReturn()) 0 else payload_ty.abiAlignment(target);515 const payload_align = if (payload_ty.isNoReturn(mod)) 0 else payload_ty.abiAlignment(mod);
530 const error_align = Type.anyerror.abiAlignment(target);516 const error_align = Type.anyerror.abiAlignment(mod);
531 const abi_size = ty.abiSize(target);517 const abi_size = ty.abiSize(mod);
532 const payload_off = if (error_align >= payload_align) Type.anyerror.abiSize(target) else 0;518 const payload_off = if (error_align >= payload_align) Type.anyerror.abiSize(mod) else 0;
533 const error_off = if (error_align >= payload_align) 0 else payload_ty.abiSize(target);519 const error_off = if (error_align >= payload_align) 0 else payload_ty.abiSize(mod);
534520
535 // DW.AT.structure_type521 // DW.AT.structure_type
536 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));522 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
537 // DW.AT.byte_size, DW.FORM.udata523 // DW.AT.byte_size, DW.FORM.udata
538 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);524 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
539 // DW.AT.name, DW.FORM.string525 // DW.AT.name, DW.FORM.string
540 const name = try ty.nameAllocArena(arena, module);526 const name = try ty.nameAllocArena(arena, mod);
541 try dbg_info_buffer.writer().print("{s}\x00", .{name});527 try dbg_info_buffer.writer().print("{s}\x00", .{name});
542528
543 if (!payload_ty.isNoReturn()) {529 if (!payload_ty.isNoReturn(mod)) {
544 // DW.AT.member530 // DW.AT.member
545 try dbg_info_buffer.ensureUnusedCapacity(7);531 try dbg_info_buffer.ensureUnusedCapacity(7);
546 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));532 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
...@@ -685,9 +671,10 @@ pub const DeclState = struct {...@@ -685,9 +671,10 @@ pub const DeclState = struct {
685 const atom_index = self.di_atom_decls.get(owner_decl).?;671 const atom_index = self.di_atom_decls.get(owner_decl).?;
686 const name_with_null = name.ptr[0 .. name.len + 1];672 const name_with_null = name.ptr[0 .. name.len + 1];
687 try dbg_info.append(@enumToInt(AbbrevKind.variable));673 try dbg_info.append(@enumToInt(AbbrevKind.variable));
688 const target = self.mod.getTarget();674 const mod = self.mod;
675 const target = mod.getTarget();
689 const endian = target.cpu.arch.endian();676 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
692 switch (loc) {679 switch (loc) {
693 .register => |reg| {680 .register => |reg| {
...@@ -790,9 +777,9 @@ pub const DeclState = struct {...@@ -790,9 +777,9 @@ pub const DeclState = struct {
790 const fixup = dbg_info.items.len;777 const fixup = dbg_info.items.len;
791 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc778 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
792 1,779 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,
794 });781 });
795 if (child_ty.isSignedInt()) {782 if (child_ty.isSignedInt(mod)) {
796 try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x));783 try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x));
797 } else {784 } else {
798 try leb128.writeULEB128(dbg_info.writer(), x);785 try leb128.writeULEB128(dbg_info.writer(), x);
...@@ -805,7 +792,7 @@ pub const DeclState = struct {...@@ -805,7 +792,7 @@ pub const DeclState = struct {
805 // DW.AT.location, DW.FORM.exprloc792 // DW.AT.location, DW.FORM.exprloc
806 // uleb128(exprloc_len)793 // uleb128(exprloc_len)
807 // DW.OP.implicit_value uleb128(len_of_bytes) bytes794 // 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));
809 var implicit_value_len = std.ArrayList(u8).init(self.gpa);796 var implicit_value_len = std.ArrayList(u8).init(self.gpa);
810 defer implicit_value_len.deinit();797 defer implicit_value_len.deinit();
811 try leb128.writeULEB128(implicit_value_len.writer(), abi_size);798 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)...@@ -964,8 +951,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
964 defer tracy.end();951 defer tracy.end();
965952
966 const decl = mod.declPtr(decl_index);953 const decl = mod.declPtr(decl_index);
967 const decl_name = try decl.getFullyQualifiedName(mod);954 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
968 defer self.allocator.free(decl_name);
969955
970 log.debug("initDeclState {s}{*}", .{ decl_name, decl });956 log.debug("initDeclState {s}{*}", .{ decl_name, decl });
971957
...@@ -979,14 +965,14 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -979,14 +965,14 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
979965
980 assert(decl.has_tv);966 assert(decl.has_tv);
981967
982 switch (decl.ty.zigTypeTag()) {968 switch (decl.ty.zigTypeTag(mod)) {
983 .Fn => {969 .Fn => {
984 _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index);970 _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index);
985971
986 // For functions we need to add a prologue to the debug line program.972 // For functions we need to add a prologue to the debug line program.
987 try dbg_line_buffer.ensureTotalCapacity(26);973 try dbg_line_buffer.ensureTotalCapacity(26);
988974
989 const func = decl.val.castTag(.function).?.data;975 const func = decl.val.getFunction(mod).?;
990 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{976 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
991 decl.src_line,977 decl.src_line,
992 func.lbrace_line,978 func.lbrace_line,
...@@ -1026,8 +1012,8 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -1026,8 +1012,8 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
1026 const decl_name_with_null = decl_name[0 .. decl_name.len + 1];1012 const decl_name_with_null = decl_name[0 .. decl_name.len + 1];
1027 try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len);1013 try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len);
10281014
1029 const fn_ret_type = decl.ty.fnReturnType();1015 const fn_ret_type = decl.ty.fnReturnType(mod);
1030 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits();1016 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);
1031 if (fn_ret_has_bits) {1017 if (fn_ret_has_bits) {
1032 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram));1018 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram));
1033 } else {1019 } else {
...@@ -1059,7 +1045,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -1059,7 +1045,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
10591045
1060pub fn commitDeclState(1046pub fn commitDeclState(
1061 self: *Dwarf,1047 self: *Dwarf,
1062 module: *Module,1048 mod: *Module,
1063 decl_index: Module.Decl.Index,1049 decl_index: Module.Decl.Index,
1064 sym_addr: u64,1050 sym_addr: u64,
1065 sym_size: u64,1051 sym_size: u64,
...@@ -1071,12 +1057,12 @@ pub fn commitDeclState(...@@ -1071,12 +1057,12 @@ pub fn commitDeclState(
1071 const gpa = self.allocator;1057 const gpa = self.allocator;
1072 var dbg_line_buffer = &decl_state.dbg_line;1058 var dbg_line_buffer = &decl_state.dbg_line;
1073 var dbg_info_buffer = &decl_state.dbg_info;1059 var dbg_info_buffer = &decl_state.dbg_info;
1074 const decl = module.declPtr(decl_index);1060 const decl = mod.declPtr(decl_index);
10751061
1076 const target_endian = self.target.cpu.arch.endian();1062 const target_endian = self.target.cpu.arch.endian();
10771063
1078 assert(decl.has_tv);1064 assert(decl.has_tv);
1079 switch (decl.ty.zigTypeTag()) {1065 switch (decl.ty.zigTypeTag(mod)) {
1080 .Fn => {1066 .Fn => {
1081 // Since the Decl is a function, we need to update the .debug_line program.1067 // Since the Decl is a function, we need to update the .debug_line program.
1082 // Perform the relocations based on vaddr.1068 // Perform the relocations based on vaddr.
...@@ -1271,10 +1257,11 @@ pub fn commitDeclState(...@@ -1271,10 +1257,11 @@ pub fn commitDeclState(
1271 const symbol = &decl_state.abbrev_table.items[sym_index];1257 const symbol = &decl_state.abbrev_table.items[sym_index];
1272 const ty = symbol.type;1258 const ty = symbol.type;
1273 const deferred: bool = blk: {1259 const deferred: bool = blk: {
1274 if (ty.isAnyError()) break :blk true;1260 if (ty.isAnyError(mod)) break :blk true;
1275 switch (ty.tag()) {1261 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1276 .error_set_inferred => {1262 .inferred_error_set_type => |ies_index| {
1277 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;1263 const ies = mod.inferredErrorSetPtr(ies_index);
1264 if (!ies.is_resolved) break :blk true;
1278 },1265 },
1279 else => {},1266 else => {},
1280 }1267 }
...@@ -1283,11 +1270,10 @@ pub fn commitDeclState(...@@ -1283,11 +1270,10 @@ pub fn commitDeclState(
1283 if (deferred) continue;1270 if (deferred) continue;
12841271
1285 symbol.offset = @intCast(u32, dbg_info_buffer.items.len);1272 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);
1287 }1274 }
1288 }1275 }
12891276
1290 log.debug("updateDeclDebugInfoAllocation for '{s}'", .{decl.name});
1291 try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(u32, dbg_info_buffer.items.len));1277 try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(u32, dbg_info_buffer.items.len));
12921278
1293 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {1279 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
...@@ -1295,10 +1281,11 @@ pub fn commitDeclState(...@@ -1295,10 +1281,11 @@ pub fn commitDeclState(
1295 const symbol = decl_state.abbrev_table.items[target];1281 const symbol = decl_state.abbrev_table.items[target];
1296 const ty = symbol.type;1282 const ty = symbol.type;
1297 const deferred: bool = blk: {1283 const deferred: bool = blk: {
1298 if (ty.isAnyError()) break :blk true;1284 if (ty.isAnyError(mod)) break :blk true;
1299 switch (ty.tag()) {1285 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1300 .error_set_inferred => {1286 .inferred_error_set_type => |ies_index| {
1301 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;1287 const ies = mod.inferredErrorSetPtr(ies_index);
1288 if (!ies.is_resolved) break :blk true;
1302 },1289 },
1303 else => {},1290 else => {},
1304 }1291 }
...@@ -1319,7 +1306,7 @@ pub fn commitDeclState(...@@ -1319,7 +1306,7 @@ pub fn commitDeclState(
1319 reloc.offset,1306 reloc.offset,
1320 value,1307 value,
1321 target,1308 target,
1322 ty.fmt(module),1309 ty.fmt(mod),
1323 });1310 });
1324 mem.writeInt(1311 mem.writeInt(
1325 u32,1312 u32,
...@@ -1358,7 +1345,6 @@ pub fn commitDeclState(...@@ -1358,7 +1345,6 @@ pub fn commitDeclState(
1358 }1345 }
1359 }1346 }
13601347
1361 log.debug("writeDeclDebugInfo for '{s}", .{decl.name});
1362 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);1348 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);
1363}1349}
13641350
...@@ -1527,7 +1513,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons...@@ -1527,7 +1513,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
1527 }1513 }
1528}1514}
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 {
1531 const tracy = trace(@src());1517 const tracy = trace(@src());
1532 defer tracy.end();1518 defer tracy.end();
15331519
...@@ -1535,8 +1521,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De...@@ -1535,8 +1521,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De
1535 const atom = self.getAtom(.src_fn, atom_index);1521 const atom = self.getAtom(.src_fn, atom_index);
1536 if (atom.len == 0) return;1522 if (atom.len == 0) return;
15371523
1538 const decl = module.declPtr(decl_index);1524 const decl = mod.declPtr(decl_index);
1539 const func = decl.val.castTag(.function).?.data;1525 const func = decl.val.getFunction(mod).?;
1540 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{1526 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
1541 decl.src_line,1527 decl.src_line,
1542 func.lbrace_line,1528 func.lbrace_line,
...@@ -2534,18 +2520,14 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2534,18 +2520,14 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2534 defer arena_alloc.deinit();2520 defer arena_alloc.deinit();
2535 const arena = arena_alloc.allocator();2521 const arena = arena_alloc.allocator();
25362522
2537 const error_set = try arena.create(Module.ErrorSet);2523 // TODO: don't create a zig type for this, just make the dwarf info
2538 const error_ty = try Type.Tag.error_set.create(arena, error_set);2524 // without touching the zig type system.
2539 var names = Module.ErrorSet.NameMap{};2525 const names = try arena.dupe(InternPool.NullTerminatedString, module.global_error_set.keys());
2540 try names.ensureUnusedCapacity(arena, module.global_error_set.count());2526 std.mem.sort(InternPool.NullTerminatedString, names, {}, InternPool.NullTerminatedString.indexLessThan);
2541 var it = module.global_error_set.keyIterator();
2542 while (it.next()) |key| {
2543 names.putAssumeCapacityNoClobber(key.*, {});
2544 }
2545 error_set.names = names;
25462527
2528 const error_ty = try module.intern(.{ .error_set_type = .{ .names = names } });
2547 var dbg_info_buffer = std.ArrayList(u8).init(arena);2529 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
2550 const di_atom_index = try self.createAtom(.di_atom);2532 const di_atom_index = try self.createAtom(.di_atom);
2551 log.debug("updateDeclDebugInfoAllocation in flushModule", .{});2533 log.debug("updateDeclDebugInfoAllocation in flushModule", .{});
...@@ -2598,7 +2580,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2598,7 +2580,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
25982580
2599fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {2581fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {
2600 const decl = mod.declPtr(decl_index);2582 const decl = mod.declPtr(decl_index);
2601 const file_scope = decl.getFileScope();2583 const file_scope = decl.getFileScope(mod);
2602 const gop = try self.di_files.getOrPut(self.allocator, file_scope);2584 const gop = try self.di_files.getOrPut(self.allocator, file_scope);
2603 if (!gop.found_existing) {2585 if (!gop.found_existing) {
2604 switch (self.bin_file.tag) {2586 switch (self.bin_file.tag) {
...@@ -2663,7 +2645,7 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {...@@ -2663,7 +2645,7 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {
26632645
2664fn addDbgInfoErrorSet(2646fn addDbgInfoErrorSet(
2665 arena: Allocator,2647 arena: Allocator,
2666 module: *Module,2648 mod: *Module,
2667 ty: Type,2649 ty: Type,
2668 target: std.Target,2650 target: std.Target,
2669 dbg_info_buffer: *std.ArrayList(u8),2651 dbg_info_buffer: *std.ArrayList(u8),
...@@ -2673,10 +2655,10 @@ fn addDbgInfoErrorSet(...@@ -2673,10 +2655,10 @@ fn addDbgInfoErrorSet(
2673 // DW.AT.enumeration_type2655 // DW.AT.enumeration_type
2674 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));2656 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
2675 // DW.AT.byte_size, DW.FORM.udata2657 // DW.AT.byte_size, DW.FORM.udata
2676 const abi_size = Type.anyerror.abiSize(target);2658 const abi_size = Type.anyerror.abiSize(mod);
2677 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);2659 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
2678 // DW.AT.name, DW.FORM.string2660 // DW.AT.name, DW.FORM.string
2679 const name = try ty.nameAllocArena(arena, module);2661 const name = try ty.nameAllocArena(arena, mod);
2680 try dbg_info_buffer.writer().print("{s}\x00", .{name});2662 try dbg_info_buffer.writer().print("{s}\x00", .{name});
26812663
2682 // DW.AT.enumerator2664 // DW.AT.enumerator
...@@ -2689,9 +2671,10 @@ fn addDbgInfoErrorSet(...@@ -2689,9 +2671,10 @@ fn addDbgInfoErrorSet(
2689 // DW.AT.const_value, DW.FORM.data82671 // DW.AT.const_value, DW.FORM.data8
2690 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);2672 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
26912673
2692 const error_names = ty.errorSetNames();2674 const error_names = ty.errorSetNames(mod);
2693 for (error_names) |error_name| {2675 for (error_names) |error_name_ip| {
2694 const kv = module.getErrorValue(error_name) catch unreachable;2676 const int = try mod.getErrorValue(error_name_ip);
2677 const error_name = mod.intern_pool.stringToSlice(error_name_ip);
2695 // DW.AT.enumerator2678 // DW.AT.enumerator
2696 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));2679 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
2697 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));2680 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));
...@@ -2699,7 +2682,7 @@ fn addDbgInfoErrorSet(...@@ -2699,7 +2682,7 @@ fn addDbgInfoErrorSet(
2699 dbg_info_buffer.appendSliceAssumeCapacity(error_name);2682 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
2700 dbg_info_buffer.appendAssumeCapacity(0);2683 dbg_info_buffer.appendAssumeCapacity(0);
2701 // DW.AT.const_value, DW.FORM.data82684 // 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);
2703 }2686 }
27042687
2705 // DW.AT.enumeration_type delimit children2688 // DW.AT.enumeration_type delimit children
src/link/Elf.zig+63-58
...@@ -28,6 +28,7 @@ const File = link.File;...@@ -28,6 +28,7 @@ const File = link.File;
28const Liveness = @import("../Liveness.zig");28const Liveness = @import("../Liveness.zig");
29const LlvmObject = @import("../codegen/llvm.zig").Object;29const LlvmObject = @import("../codegen/llvm.zig").Object;
30const Module = @import("../Module.zig");30const Module = @import("../Module.zig");
31const InternPool = @import("../InternPool.zig");
31const Package = @import("../Package.zig");32const Package = @import("../Package.zig");
32const StringTable = @import("strtab.zig").StringTable;33const StringTable = @import("strtab.zig").StringTable;
33const TableSection = @import("table_section.zig").TableSection;34const TableSection = @import("table_section.zig").TableSection;
...@@ -2414,7 +2415,8 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void {...@@ -2414,7 +2415,8 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void {
2414}2415}
24152416
2416pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Index {2417pub 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));
2418 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();2420 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
2419 if (!gop.found_existing) gop.value_ptr.* = .{};2421 if (!gop.found_existing) gop.value_ptr.* = .{};
2420 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {2422 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...@@ -2429,7 +2431,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Inde
2429 metadata.state.* = .pending_flush;2431 metadata.state.* = .pending_flush;
2430 const atom = metadata.atom.*;2432 const atom = metadata.atom.*;
2431 // anyerror needs to be deferred until flushModule2433 // 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) {
2433 .code => self.text_section_index.?,2435 .code => self.text_section_index.?,
2434 .const_data => self.rodata_section_index.?,2436 .const_data => self.rodata_section_index.?,
2435 });2437 });
...@@ -2449,12 +2451,13 @@ pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.I...@@ -2449,12 +2451,13 @@ pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.I
2449}2451}
24502452
2451fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {2453fn 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);
2453 const ty = decl.ty;2456 const ty = decl.ty;
2454 const zig_ty = ty.zigTypeTag();2457 const zig_ty = ty.zigTypeTag(mod);
2455 const val = decl.val;2458 const val = decl.val;
2456 const shdr_index: u16 = blk: {2459 const shdr_index: u16 = blk: {
2457 if (val.isUndefDeep()) {2460 if (val.isUndefDeep(mod)) {
2458 // TODO in release-fast and release-small, we should put undef in .bss2461 // TODO in release-fast and release-small, we should put undef in .bss
2459 break :blk self.data_section_index.?;2462 break :blk self.data_section_index.?;
2460 }2463 }
...@@ -2463,7 +2466,7 @@ fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {...@@ -2463,7 +2466,7 @@ fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {
2463 // TODO: what if this is a function pointer?2466 // TODO: what if this is a function pointer?
2464 .Fn => break :blk self.text_section_index.?,2467 .Fn => break :blk self.text_section_index.?,
2465 else => {2468 else => {
2466 if (val.castTag(.variable)) |_| {2469 if (val.getVariable(mod)) |_| {
2467 break :blk self.data_section_index.?;2470 break :blk self.data_section_index.?;
2468 }2471 }
2469 break :blk self.rodata_section_index.?;2472 break :blk self.rodata_section_index.?;
...@@ -2478,11 +2481,10 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2478,11 +2481,10 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2478 const mod = self.base.options.module.?;2481 const mod = self.base.options.module.?;
2479 const decl = mod.declPtr(decl_index);2482 const decl = mod.declPtr(decl_index);
24802483
2481 const decl_name = try decl.getFullyQualifiedName(mod);2484 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
2482 defer self.base.allocator.free(decl_name);
24832485
2484 log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });2486 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
2487 const decl_metadata = self.decls.get(decl_index).?;2489 const decl_metadata = self.decls.get(decl_index).?;
2488 const atom_index = decl_metadata.atom;2490 const atom_index = decl_metadata.atom;
...@@ -2572,19 +2574,20 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2572,19 +2574,20 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2572 return local_sym;2574 return local_sym;
2573}2575}
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 {
2576 if (build_options.skip_non_native and builtin.object_format != .elf) {2578 if (build_options.skip_non_native and builtin.object_format != .elf) {
2577 @panic("Attempted to compile for object format that was disabled by build configuration");2579 @panic("Attempted to compile for object format that was disabled by build configuration");
2578 }2580 }
2579 if (build_options.have_llvm) {2581 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);
2581 }2583 }
25822584
2583 const tracy = trace(@src());2585 const tracy = trace(@src());
2584 defer tracy.end();2586 defer tracy.end();
25852587
2588 const func = mod.funcPtr(func_index);
2586 const decl_index = func.owner_decl;2589 const decl_index = func.owner_decl;
2587 const decl = module.declPtr(decl_index);2590 const decl = mod.declPtr(decl_index);
25882591
2589 const atom_index = try self.getOrCreateAtomForDecl(decl_index);2592 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2590 self.freeUnnamedConsts(decl_index);2593 self.freeUnnamedConsts(decl_index);
...@@ -2593,28 +2596,28 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven...@@ -2593,28 +2596,28 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
2593 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2596 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2594 defer code_buffer.deinit();2597 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;
2597 defer if (decl_state) |*ds| ds.deinit();2600 defer if (decl_state) |*ds| ds.deinit();
25982601
2599 const res = if (decl_state) |*ds|2602 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, .{
2601 .dwarf = ds,2604 .dwarf = ds,
2602 })2605 })
2603 else2606 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
2606 const code = switch (res) {2609 const code = switch (res) {
2607 .ok => code_buffer.items,2610 .ok => code_buffer.items,
2608 .fail => |em| {2611 .fail => |em| {
2609 decl.analysis = .codegen_failure;2612 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);
2611 return;2614 return;
2612 },2615 },
2613 };2616 };
2614 const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_FUNC);2617 const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_FUNC);
2615 if (decl_state) |*ds| {2618 if (decl_state) |*ds| {
2616 try self.dwarf.?.commitDeclState(2619 try self.dwarf.?.commitDeclState(
2617 module,2620 mod,
2618 decl_index,2621 decl_index,
2619 local_sym.st_value,2622 local_sym.st_value,
2620 local_sym.st_size,2623 local_sym.st_size,
...@@ -2624,31 +2627,30 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven...@@ -2624,31 +2627,30 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
26242627
2625 // Since we updated the vaddr and the size, each corresponding export2628 // Since we updated the vaddr and the size, each corresponding export
2626 // symbol also needs to be updated.2629 // 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));
2628}2631}
26292632
2630pub fn updateDecl(2633pub fn updateDecl(
2631 self: *Elf,2634 self: *Elf,
2632 module: *Module,2635 mod: *Module,
2633 decl_index: Module.Decl.Index,2636 decl_index: Module.Decl.Index,
2634) File.UpdateDeclError!void {2637) File.UpdateDeclError!void {
2635 if (build_options.skip_non_native and builtin.object_format != .elf) {2638 if (build_options.skip_non_native and builtin.object_format != .elf) {
2636 @panic("Attempted to compile for object format that was disabled by build configuration");2639 @panic("Attempted to compile for object format that was disabled by build configuration");
2637 }2640 }
2638 if (build_options.have_llvm) {2641 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);
2640 }2643 }
26412644
2642 const tracy = trace(@src());2645 const tracy = trace(@src());
2643 defer tracy.end();2646 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)) |_| {
2648 return; // TODO Should we do more when front-end analyzed extern decl?2651 return; // TODO Should we do more when front-end analyzed extern decl?
2649 }2652 }
2650 if (decl.val.castTag(.variable)) |payload| {2653 if (decl.val.getVariable(mod)) |variable| {
2651 const variable = payload.data;
2652 if (variable.is_extern) {2654 if (variable.is_extern) {
2653 return; // TODO Should we do more when front-end analyzed extern decl?2655 return; // TODO Should we do more when front-end analyzed extern decl?
2654 }2656 }
...@@ -2661,13 +2663,13 @@ pub fn updateDecl(...@@ -2661,13 +2663,13 @@ pub fn updateDecl(
2661 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2663 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2662 defer code_buffer.deinit();2664 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;
2665 defer if (decl_state) |*ds| ds.deinit();2667 defer if (decl_state) |*ds| ds.deinit();
26662668
2667 // TODO implement .debug_info for global variables2669 // 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;
2669 const res = if (decl_state) |*ds|2671 const res = if (decl_state) |*ds|
2670 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2672 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2671 .ty = decl.ty,2673 .ty = decl.ty,
2672 .val = decl_val,2674 .val = decl_val,
2673 }, &code_buffer, .{2675 }, &code_buffer, .{
...@@ -2676,7 +2678,7 @@ pub fn updateDecl(...@@ -2676,7 +2678,7 @@ pub fn updateDecl(
2676 .parent_atom_index = atom.getSymbolIndex().?,2678 .parent_atom_index = atom.getSymbolIndex().?,
2677 })2679 })
2678 else2680 else
2679 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2681 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2680 .ty = decl.ty,2682 .ty = decl.ty,
2681 .val = decl_val,2683 .val = decl_val,
2682 }, &code_buffer, .none, .{2684 }, &code_buffer, .none, .{
...@@ -2687,7 +2689,7 @@ pub fn updateDecl(...@@ -2687,7 +2689,7 @@ pub fn updateDecl(
2687 .ok => code_buffer.items,2689 .ok => code_buffer.items,
2688 .fail => |em| {2690 .fail => |em| {
2689 decl.analysis = .codegen_failure;2691 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);
2691 return;2693 return;
2692 },2694 },
2693 };2695 };
...@@ -2695,7 +2697,7 @@ pub fn updateDecl(...@@ -2695,7 +2697,7 @@ pub fn updateDecl(
2695 const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_OBJECT);2697 const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_OBJECT);
2696 if (decl_state) |*ds| {2698 if (decl_state) |*ds| {
2697 try self.dwarf.?.commitDeclState(2699 try self.dwarf.?.commitDeclState(
2698 module,2700 mod,
2699 decl_index,2701 decl_index,
2700 local_sym.st_value,2702 local_sym.st_value,
2701 local_sym.st_size,2703 local_sym.st_size,
...@@ -2705,7 +2707,7 @@ pub fn updateDecl(...@@ -2705,7 +2707,7 @@ pub fn updateDecl(
27052707
2706 // Since we updated the vaddr and the size, each corresponding export2708 // Since we updated the vaddr and the size, each corresponding export
2707 // symbol also needs to be updated.2709 // 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));
2709}2711}
27102712
2711fn updateLazySymbolAtom(2713fn updateLazySymbolAtom(
...@@ -2734,8 +2736,8 @@ fn updateLazySymbolAtom(...@@ -2734,8 +2736,8 @@ fn updateLazySymbolAtom(
2734 const atom = self.getAtom(atom_index);2736 const atom = self.getAtom(atom_index);
2735 const local_sym_index = atom.getSymbolIndex().?;2737 const local_sym_index = atom.getSymbolIndex().?;
27362738
2737 const src = if (sym.ty.getOwnerDeclOrNull()) |owner_decl|2739 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|
2738 mod.declPtr(owner_decl).srcLoc()2740 mod.declPtr(owner_decl).srcLoc(mod)
2739 else2741 else
2740 Module.SrcLoc{2742 Module.SrcLoc{
2741 .file_scope = undefined,2743 .file_scope = undefined,
...@@ -2800,8 +2802,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2800,8 +2802,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28002802
2801 const decl = mod.declPtr(decl_index);2803 const decl = mod.declPtr(decl_index);
2802 const name_str_index = blk: {2804 const name_str_index = blk: {
2803 const decl_name = try decl.getFullyQualifiedName(mod);2805 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
2804 defer gpa.free(decl_name);
2805 const index = unnamed_consts.items.len;2806 const index = unnamed_consts.items.len;
2806 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });2807 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
2807 defer gpa.free(name);2808 defer gpa.free(name);
...@@ -2811,7 +2812,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2811,7 +2812,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28112812
2812 const atom_index = try self.createAtom();2813 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, .{
2815 .none = {},2816 .none = {},
2816 }, .{2817 }, .{
2817 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,2818 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
...@@ -2826,7 +2827,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2826,7 +2827,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
2826 },2827 },
2827 };2828 };
28282829
2829 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);2830 const required_alignment = typed_value.ty.abiAlignment(mod);
2830 const shdr_index = self.rodata_section_index.?;2831 const shdr_index = self.rodata_section_index.?;
2831 const phdr_index = self.sections.items(.phdr_index)[shdr_index];2832 const phdr_index = self.sections.items(.phdr_index)[shdr_index];
2832 const local_sym = self.getAtom(atom_index).getSymbolPtr(self);2833 const local_sym = self.getAtom(atom_index).getSymbolPtr(self);
...@@ -2852,7 +2853,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2852,7 +2853,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28522853
2853pub fn updateDeclExports(2854pub fn updateDeclExports(
2854 self: *Elf,2855 self: *Elf,
2855 module: *Module,2856 mod: *Module,
2856 decl_index: Module.Decl.Index,2857 decl_index: Module.Decl.Index,
2857 exports: []const *Module.Export,2858 exports: []const *Module.Export,
2858) File.UpdateDeclExportsError!void {2859) File.UpdateDeclExportsError!void {
...@@ -2860,7 +2861,7 @@ pub fn updateDeclExports(...@@ -2860,7 +2861,7 @@ pub fn updateDeclExports(
2860 @panic("Attempted to compile for object format that was disabled by build configuration");2861 @panic("Attempted to compile for object format that was disabled by build configuration");
2861 }2862 }
2862 if (build_options.have_llvm) {2863 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);
2864 }2865 }
28652866
2866 const tracy = trace(@src());2867 const tracy = trace(@src());
...@@ -2868,7 +2869,7 @@ pub fn updateDeclExports(...@@ -2868,7 +2869,7 @@ pub fn updateDeclExports(
28682869
2869 const gpa = self.base.allocator;2870 const gpa = self.base.allocator;
28702871
2871 const decl = module.declPtr(decl_index);2872 const decl = mod.declPtr(decl_index);
2872 const atom_index = try self.getOrCreateAtomForDecl(decl_index);2873 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2873 const atom = self.getAtom(atom_index);2874 const atom = self.getAtom(atom_index);
2874 const decl_sym = atom.getSymbol(self);2875 const decl_sym = atom.getSymbol(self);
...@@ -2878,40 +2879,41 @@ pub fn updateDeclExports(...@@ -2878,40 +2879,41 @@ pub fn updateDeclExports(
2878 try self.global_symbols.ensureUnusedCapacity(gpa, exports.len);2879 try self.global_symbols.ensureUnusedCapacity(gpa, exports.len);
28792880
2880 for (exports) |exp| {2881 for (exports) |exp| {
2881 if (exp.options.section) |section_name| {2882 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
2882 if (!mem.eql(u8, section_name, ".text")) {2883 if (exp.opts.section.unwrap()) |section_name| {
2883 try module.failed_exports.ensureUnusedCapacity(module.gpa, 1);2884 if (!mod.intern_pool.stringEqlSlice(section_name, ".text")) {
2884 module.failed_exports.putAssumeCapacityNoClobber(2885 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
2886 mod.failed_exports.putAssumeCapacityNoClobber(
2885 exp,2887 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", .{}),
2887 );2889 );
2888 continue;2890 continue;
2889 }2891 }
2890 }2892 }
2891 const stb_bits: u8 = switch (exp.options.linkage) {2893 const stb_bits: u8 = switch (exp.opts.linkage) {
2892 .Internal => elf.STB_LOCAL,2894 .Internal => elf.STB_LOCAL,
2893 .Strong => blk: {2895 .Strong => blk: {
2894 const entry_name = self.base.options.entry orelse "_start";2896 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)) {
2896 self.entry_addr = decl_sym.st_value;2898 self.entry_addr = decl_sym.st_value;
2897 }2899 }
2898 break :blk elf.STB_GLOBAL;2900 break :blk elf.STB_GLOBAL;
2899 },2901 },
2900 .Weak => elf.STB_WEAK,2902 .Weak => elf.STB_WEAK,
2901 .LinkOnce => {2903 .LinkOnce => {
2902 try module.failed_exports.ensureUnusedCapacity(module.gpa, 1);2904 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
2903 module.failed_exports.putAssumeCapacityNoClobber(2905 mod.failed_exports.putAssumeCapacityNoClobber(
2904 exp,2906 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", .{}),
2906 );2908 );
2907 continue;2909 continue;
2908 },2910 },
2909 };2911 };
2910 const stt_bits: u8 = @truncate(u4, decl_sym.st_info);2912 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| {
2912 const sym = &self.global_symbols.items[i];2914 const sym = &self.global_symbols.items[i];
2913 sym.* = .{2915 sym.* = .{
2914 .st_name = try self.shstrtab.insert(gpa, exp.options.name),2916 .st_name = try self.shstrtab.insert(gpa, exp_name),
2915 .st_info = (stb_bits << 4) | stt_bits,2917 .st_info = (stb_bits << 4) | stt_bits,
2916 .st_other = 0,2918 .st_other = 0,
2917 .st_shndx = shdr_index,2919 .st_shndx = shdr_index,
...@@ -2925,7 +2927,7 @@ pub fn updateDeclExports(...@@ -2925,7 +2927,7 @@ pub fn updateDeclExports(
2925 };2927 };
2926 try decl_metadata.exports.append(gpa, @intCast(u32, i));2928 try decl_metadata.exports.append(gpa, @intCast(u32, i));
2927 self.global_symbols.items[i] = .{2929 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),
2929 .st_info = (stb_bits << 4) | stt_bits,2931 .st_info = (stb_bits << 4) | stt_bits,
2930 .st_other = 0,2932 .st_other = 0,
2931 .st_shndx = shdr_index,2933 .st_shndx = shdr_index,
...@@ -2942,8 +2944,7 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: Module.Decl.In...@@ -2942,8 +2944,7 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: Module.Decl.In
2942 defer tracy.end();2944 defer tracy.end();
29432945
2944 const decl = mod.declPtr(decl_index);2946 const decl = mod.declPtr(decl_index);
2945 const decl_name = try decl.getFullyQualifiedName(mod);2947 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
2946 defer self.base.allocator.free(decl_name);
29472948
2948 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });2949 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
29492950
...@@ -2953,11 +2954,15 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: Module.Decl.In...@@ -2953,11 +2954,15 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: Module.Decl.In
2953 }2954 }
2954}2955}
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 {
2957 if (self.llvm_object) |_| return;2962 if (self.llvm_object) |_| return;
2958 const metadata = self.decls.getPtr(decl_index) orelse return;2963 const metadata = self.decls.getPtr(decl_index) orelse return;
2959 const sym_index = metadata.getExportPtr(self, name) orelse return;2964 const mod = self.base.options.module.?;
2960 log.debug("deleting export '{s}'", .{name});2965 const sym_index = metadata.getExportPtr(self, mod.intern_pool.stringToSlice(name)) orelse return;
2961 self.global_symbol_free_list.append(self.base.allocator, sym_index.*) catch {};2966 self.global_symbol_free_list.append(self.base.allocator, sym_index.*) catch {};
2962 self.global_symbols.items[sym_index.*].st_info = 0;2967 self.global_symbols.items[sym_index.*].st_info = 0;
2963 sym_index.* = 0;2968 sym_index.* = 0;
src/link/MachO.zig+76-68
...@@ -40,6 +40,7 @@ const Liveness = @import("../Liveness.zig");...@@ -40,6 +40,7 @@ const Liveness = @import("../Liveness.zig");
40const LlvmObject = @import("../codegen/llvm.zig").Object;40const LlvmObject = @import("../codegen/llvm.zig").Object;
41const Md5 = std.crypto.hash.Md5;41const Md5 = std.crypto.hash.Md5;
42const Module = @import("../Module.zig");42const Module = @import("../Module.zig");
43const InternPool = @import("../InternPool.zig");
43const Relocation = @import("MachO/Relocation.zig");44const Relocation = @import("MachO/Relocation.zig");
44const StringTable = @import("strtab.zig").StringTable;45const StringTable = @import("strtab.zig").StringTable;
45const TableSection = @import("table_section.zig").TableSection;46const TableSection = @import("table_section.zig").TableSection;
...@@ -1847,18 +1848,19 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {...@@ -1847,18 +1848,19 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
1847 self.markRelocsDirtyByTarget(target);1848 self.markRelocsDirtyByTarget(target);
1848}1849}
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 {
1851 if (build_options.skip_non_native and builtin.object_format != .macho) {1852 if (build_options.skip_non_native and builtin.object_format != .macho) {
1852 @panic("Attempted to compile for object format that was disabled by build configuration");1853 @panic("Attempted to compile for object format that was disabled by build configuration");
1853 }1854 }
1854 if (build_options.have_llvm) {1855 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);
1856 }1857 }
1857 const tracy = trace(@src());1858 const tracy = trace(@src());
1858 defer tracy.end();1859 defer tracy.end();
18591860
1861 const func = mod.funcPtr(func_index);
1860 const decl_index = func.owner_decl;1862 const decl_index = func.owner_decl;
1861 const decl = module.declPtr(decl_index);1863 const decl = mod.declPtr(decl_index);
18621864
1863 const atom_index = try self.getOrCreateAtomForDecl(decl_index);1865 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
1864 self.freeUnnamedConsts(decl_index);1866 self.freeUnnamedConsts(decl_index);
...@@ -1868,23 +1870,23 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -1868,23 +1870,23 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
1868 defer code_buffer.deinit();1870 defer code_buffer.deinit();
18691871
1870 var decl_state = if (self.d_sym) |*d_sym|1872 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)
1872 else1874 else
1873 null;1875 null;
1874 defer if (decl_state) |*ds| ds.deinit();1876 defer if (decl_state) |*ds| ds.deinit();
18751877
1876 const res = if (decl_state) |*ds|1878 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, .{
1878 .dwarf = ds,1880 .dwarf = ds,
1879 })1881 })
1880 else1882 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
1883 var code = switch (res) {1885 var code = switch (res) {
1884 .ok => code_buffer.items,1886 .ok => code_buffer.items,
1885 .fail => |em| {1887 .fail => |em| {
1886 decl.analysis = .codegen_failure;1888 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);
1888 return;1890 return;
1889 },1891 },
1890 };1892 };
...@@ -1893,7 +1895,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -1893,7 +1895,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
18931895
1894 if (decl_state) |*ds| {1896 if (decl_state) |*ds| {
1895 try self.d_sym.?.dwarf.commitDeclState(1897 try self.d_sym.?.dwarf.commitDeclState(
1896 module,1898 mod,
1897 decl_index,1899 decl_index,
1898 addr,1900 addr,
1899 self.getAtom(atom_index).size,1901 self.getAtom(atom_index).size,
...@@ -1903,7 +1905,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -1903,7 +1905,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
19031905
1904 // Since we updated the vaddr and the size, each corresponding export symbol also1906 // Since we updated the vaddr and the size, each corresponding export symbol also
1905 // needs to be updated.1907 // 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));
1907}1909}
19081910
1909pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 {1911pub 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...@@ -1912,16 +1914,15 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
1912 var code_buffer = std.ArrayList(u8).init(gpa);1914 var code_buffer = std.ArrayList(u8).init(gpa);
1913 defer code_buffer.deinit();1915 defer code_buffer.deinit();
19141916
1915 const module = self.base.options.module.?;1917 const mod = self.base.options.module.?;
1916 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);1918 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);
1917 if (!gop.found_existing) {1919 if (!gop.found_existing) {
1918 gop.value_ptr.* = .{};1920 gop.value_ptr.* = .{};
1919 }1921 }
1920 const unnamed_consts = gop.value_ptr;1922 const unnamed_consts = gop.value_ptr;
19211923
1922 const decl = module.declPtr(decl_index);1924 const decl = mod.declPtr(decl_index);
1923 const decl_name = try decl.getFullyQualifiedName(module);1925 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1924 defer gpa.free(decl_name);
19251926
1926 const name_str_index = blk: {1927 const name_str_index = blk: {
1927 const index = unnamed_consts.items.len;1928 const index = unnamed_consts.items.len;
...@@ -1935,20 +1936,20 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu...@@ -1935,20 +1936,20 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
19351936
1936 const atom_index = try self.createAtom();1937 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, .{
1939 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,1940 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
1940 });1941 });
1941 var code = switch (res) {1942 var code = switch (res) {
1942 .ok => code_buffer.items,1943 .ok => code_buffer.items,
1943 .fail => |em| {1944 .fail => |em| {
1944 decl.analysis = .codegen_failure;1945 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);
1946 log.err("{s}", .{em.msg});1947 log.err("{s}", .{em.msg});
1947 return error.CodegenFail;1948 return error.CodegenFail;
1948 },1949 },
1949 };1950 };
19501951
1951 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);1952 const required_alignment = typed_value.ty.abiAlignment(mod);
1952 const atom = self.getAtomPtr(atom_index);1953 const atom = self.getAtomPtr(atom_index);
1953 atom.size = code.len;1954 atom.size = code.len;
1954 // TODO: work out logic for disambiguating functions from function pointers1955 // 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...@@ -1971,33 +1972,32 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
1971 return atom.getSymbolIndex().?;1972 return atom.getSymbolIndex().?;
1972}1973}
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 {
1975 if (build_options.skip_non_native and builtin.object_format != .macho) {1976 if (build_options.skip_non_native and builtin.object_format != .macho) {
1976 @panic("Attempted to compile for object format that was disabled by build configuration");1977 @panic("Attempted to compile for object format that was disabled by build configuration");
1977 }1978 }
1978 if (build_options.have_llvm) {1979 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);
1980 }1981 }
1981 const tracy = trace(@src());1982 const tracy = trace(@src());
1982 defer tracy.end();1983 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)) |_| {
1987 return; // TODO Should we do more when front-end analyzed extern decl?1988 return; // TODO Should we do more when front-end analyzed extern decl?
1988 }1989 }
1989 if (decl.val.castTag(.variable)) |payload| {1990 if (decl.val.getVariable(mod)) |variable| {
1990 const variable = payload.data;
1991 if (variable.is_extern) {1991 if (variable.is_extern) {
1992 return; // TODO Should we do more when front-end analyzed extern decl?1992 return; // TODO Should we do more when front-end analyzed extern decl?
1993 }1993 }
1994 }1994 }
19951995
1996 const is_threadlocal = if (decl.val.castTag(.variable)) |payload|1996 const is_threadlocal = if (decl.val.getVariable(mod)) |variable|
1997 payload.data.is_threadlocal and !self.base.options.single_threaded1997 variable.is_threadlocal and !self.base.options.single_threaded
1998 else1998 else
1999 false;1999 false;
2000 if (is_threadlocal) return self.updateThreadlocalVariable(module, decl_index);2000 if (is_threadlocal) return self.updateThreadlocalVariable(mod, decl_index);
20012001
2002 const atom_index = try self.getOrCreateAtomForDecl(decl_index);2002 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2003 const sym_index = self.getAtom(atom_index).getSymbolIndex().?;2003 const sym_index = self.getAtom(atom_index).getSymbolIndex().?;
...@@ -2007,14 +2007,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2007,14 +2007,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
2007 defer code_buffer.deinit();2007 defer code_buffer.deinit();
20082008
2009 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|2009 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)
2011 else2011 else
2012 null;2012 null;
2013 defer if (decl_state) |*ds| ds.deinit();2013 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;
2016 const res = if (decl_state) |*ds|2016 const res = if (decl_state) |*ds|
2017 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2017 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2018 .ty = decl.ty,2018 .ty = decl.ty,
2019 .val = decl_val,2019 .val = decl_val,
2020 }, &code_buffer, .{2020 }, &code_buffer, .{
...@@ -2023,7 +2023,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2023,7 +2023,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
2023 .parent_atom_index = sym_index,2023 .parent_atom_index = sym_index,
2024 })2024 })
2025 else2025 else
2026 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2026 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2027 .ty = decl.ty,2027 .ty = decl.ty,
2028 .val = decl_val,2028 .val = decl_val,
2029 }, &code_buffer, .none, .{2029 }, &code_buffer, .none, .{
...@@ -2034,7 +2034,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2034,7 +2034,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
2034 .ok => code_buffer.items,2034 .ok => code_buffer.items,
2035 .fail => |em| {2035 .fail => |em| {
2036 decl.analysis = .codegen_failure;2036 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);
2038 return;2038 return;
2039 },2039 },
2040 };2040 };
...@@ -2042,7 +2042,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2042,7 +2042,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
20422042
2043 if (decl_state) |*ds| {2043 if (decl_state) |*ds| {
2044 try self.d_sym.?.dwarf.commitDeclState(2044 try self.d_sym.?.dwarf.commitDeclState(
2045 module,2045 mod,
2046 decl_index,2046 decl_index,
2047 addr,2047 addr,
2048 self.getAtom(atom_index).size,2048 self.getAtom(atom_index).size,
...@@ -2052,7 +2052,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2052,7 +2052,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
20522052
2053 // Since we updated the vaddr and the size, each corresponding export symbol also2053 // Since we updated the vaddr and the size, each corresponding export symbol also
2054 // needs to be updated.2054 // 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));
2056}2056}
20572057
2058fn updateLazySymbolAtom(2058fn updateLazySymbolAtom(
...@@ -2081,8 +2081,8 @@ fn updateLazySymbolAtom(...@@ -2081,8 +2081,8 @@ fn updateLazySymbolAtom(
2081 const atom = self.getAtomPtr(atom_index);2081 const atom = self.getAtomPtr(atom_index);
2082 const local_sym_index = atom.getSymbolIndex().?;2082 const local_sym_index = atom.getSymbolIndex().?;
20832083
2084 const src = if (sym.ty.getOwnerDeclOrNull()) |owner_decl|2084 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|
2085 mod.declPtr(owner_decl).srcLoc()2085 mod.declPtr(owner_decl).srcLoc(mod)
2086 else2086 else
2087 Module.SrcLoc{2087 Module.SrcLoc{
2088 .file_scope = undefined,2088 .file_scope = undefined,
...@@ -2126,7 +2126,8 @@ fn updateLazySymbolAtom(...@@ -2126,7 +2126,8 @@ fn updateLazySymbolAtom(
2126}2126}
21272127
2128pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index {2128pub 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));
2130 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();2131 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
2131 if (!gop.found_existing) gop.value_ptr.* = .{};2132 if (!gop.found_existing) gop.value_ptr.* = .{};
2132 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {2133 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...@@ -2144,7 +2145,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In
2144 metadata.state.* = .pending_flush;2145 metadata.state.* = .pending_flush;
2145 const atom = metadata.atom.*;2146 const atom = metadata.atom.*;
2146 // anyerror needs to be deferred until flushModule2147 // 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) {
2148 .code => self.text_section_index.?,2149 .code => self.text_section_index.?,
2149 .const_data => self.data_const_section_index.?,2150 .const_data => self.data_const_section_index.?,
2150 });2151 });
...@@ -2152,6 +2153,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In...@@ -2152,6 +2153,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In
2152}2153}
21532154
2154fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void {2155fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void {
2156 const mod = self.base.options.module.?;
2155 // Lowering a TLV on macOS involves two stages:2157 // Lowering a TLV on macOS involves two stages:
2156 // 1. first we lower the initializer into appopriate section (__thread_data or __thread_bss)2158 // 1. first we lower the initializer into appopriate section (__thread_data or __thread_bss)
2157 // 2. next, we create a corresponding threadlocal variable descriptor in __thread_vars2159 // 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...@@ -2175,9 +2177,9 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
21752177
2176 const decl = module.declPtr(decl_index);2178 const decl = module.declPtr(decl_index);
2177 const decl_metadata = self.decls.get(decl_index).?;2179 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();
2179 const res = if (decl_state) |*ds|2181 const res = if (decl_state) |*ds|
2180 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2182 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2181 .ty = decl.ty,2183 .ty = decl.ty,
2182 .val = decl_val,2184 .val = decl_val,
2183 }, &code_buffer, .{2185 }, &code_buffer, .{
...@@ -2186,7 +2188,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D...@@ -2186,7 +2188,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
2186 .parent_atom_index = init_sym_index,2188 .parent_atom_index = init_sym_index,
2187 })2189 })
2188 else2190 else
2189 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2191 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
2190 .ty = decl.ty,2192 .ty = decl.ty,
2191 .val = decl_val,2193 .val = decl_val,
2192 }, &code_buffer, .none, .{2194 }, &code_buffer, .none, .{
...@@ -2202,10 +2204,9 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D...@@ -2202,10 +2204,9 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
2202 },2204 },
2203 };2205 };
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);2209 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(module));
2208 defer gpa.free(decl_name);
22092210
2210 const init_sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{decl_name});2211 const init_sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{decl_name});
2211 defer gpa.free(init_sym_name);2212 defer gpa.free(init_sym_name);
...@@ -2262,12 +2263,13 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {...@@ -2262,12 +2263,13 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
2262 const decl = self.base.options.module.?.declPtr(decl_index);2263 const decl = self.base.options.module.?.declPtr(decl_index);
2263 const ty = decl.ty;2264 const ty = decl.ty;
2264 const val = decl.val;2265 const val = decl.val;
2265 const zig_ty = ty.zigTypeTag();2266 const mod = self.base.options.module.?;
2267 const zig_ty = ty.zigTypeTag(mod);
2266 const mode = self.base.options.optimize_mode;2268 const mode = self.base.options.optimize_mode;
2267 const single_threaded = self.base.options.single_threaded;2269 const single_threaded = self.base.options.single_threaded;
2268 const sect_id: u8 = blk: {2270 const sect_id: u8 = blk: {
2269 // TODO finish and audit this function2271 // TODO finish and audit this function
2270 if (val.isUndefDeep()) {2272 if (val.isUndefDeep(mod)) {
2271 if (mode == .ReleaseFast or mode == .ReleaseSmall) {2273 if (mode == .ReleaseFast or mode == .ReleaseSmall) {
2272 @panic("TODO __DATA,__bss");2274 @panic("TODO __DATA,__bss");
2273 } else {2275 } else {
...@@ -2275,8 +2277,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {...@@ -2275,8 +2277,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
2275 }2277 }
2276 }2278 }
22772279
2278 if (val.castTag(.variable)) |variable| {2280 if (val.getVariable(mod)) |variable| {
2279 if (variable.data.is_threadlocal and !single_threaded) {2281 if (variable.is_threadlocal and !single_threaded) {
2280 break :blk self.thread_data_section_index.?;2282 break :blk self.thread_data_section_index.?;
2281 }2283 }
2282 break :blk self.data_section_index.?;2284 break :blk self.data_section_index.?;
...@@ -2286,7 +2288,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {...@@ -2286,7 +2288,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
2286 // TODO: what if this is a function pointer?2288 // TODO: what if this is a function pointer?
2287 .Fn => break :blk self.text_section_index.?,2289 .Fn => break :blk self.text_section_index.?,
2288 else => {2290 else => {
2289 if (val.castTag(.variable)) |_| {2291 if (val.getVariable(mod)) |_| {
2290 break :blk self.data_section_index.?;2292 break :blk self.data_section_index.?;
2291 }2293 }
2292 break :blk self.data_const_section_index.?;2294 break :blk self.data_const_section_index.?;
...@@ -2301,10 +2303,9 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64...@@ -2301,10 +2303,9 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64
2301 const mod = self.base.options.module.?;2303 const mod = self.base.options.module.?;
2302 const decl = mod.declPtr(decl_index);2304 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);2308 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
2307 defer gpa.free(decl_name);
23082309
2309 const decl_metadata = self.decls.get(decl_index).?;2310 const decl_metadata = self.decls.get(decl_index).?;
2310 const atom_index = decl_metadata.atom;2311 const atom_index = decl_metadata.atom;
...@@ -2376,7 +2377,7 @@ pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: Module.De...@@ -2376,7 +2377,7 @@ pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: Module.De
23762377
2377pub fn updateDeclExports(2378pub fn updateDeclExports(
2378 self: *MachO,2379 self: *MachO,
2379 module: *Module,2380 mod: *Module,
2380 decl_index: Module.Decl.Index,2381 decl_index: Module.Decl.Index,
2381 exports: []const *Module.Export,2382 exports: []const *Module.Export,
2382) File.UpdateDeclExportsError!void {2383) File.UpdateDeclExportsError!void {
...@@ -2385,7 +2386,7 @@ pub fn updateDeclExports(...@@ -2385,7 +2386,7 @@ pub fn updateDeclExports(
2385 }2386 }
2386 if (build_options.have_llvm) {2387 if (build_options.have_llvm) {
2387 if (self.llvm_object) |llvm_object|2388 if (self.llvm_object) |llvm_object|
2388 return llvm_object.updateDeclExports(module, decl_index, exports);2389 return llvm_object.updateDeclExports(mod, decl_index, exports);
2389 }2390 }
23902391
2391 const tracy = trace(@src());2392 const tracy = trace(@src());
...@@ -2393,26 +2394,28 @@ pub fn updateDeclExports(...@@ -2393,26 +2394,28 @@ pub fn updateDeclExports(
23932394
2394 const gpa = self.base.allocator;2395 const gpa = self.base.allocator;
23952396
2396 const decl = module.declPtr(decl_index);2397 const decl = mod.declPtr(decl_index);
2397 const atom_index = try self.getOrCreateAtomForDecl(decl_index);2398 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2398 const atom = self.getAtom(atom_index);2399 const atom = self.getAtom(atom_index);
2399 const decl_sym = atom.getSymbol(self);2400 const decl_sym = atom.getSymbol(self);
2400 const decl_metadata = self.decls.getPtr(decl_index).?;2401 const decl_metadata = self.decls.getPtr(decl_index).?;
24012402
2402 for (exports) |exp| {2403 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 });
2404 defer gpa.free(exp_name);2407 defer gpa.free(exp_name);
24052408
2406 log.debug("adding new export '{s}'", .{exp_name});2409 log.debug("adding new export '{s}'", .{exp_name});
24072410
2408 if (exp.options.section) |section_name| {2411 if (exp.opts.section.unwrap()) |section_name| {
2409 if (!mem.eql(u8, section_name, "__text")) {2412 if (!mod.intern_pool.stringEqlSlice(section_name, "__text")) {
2410 try module.failed_exports.putNoClobber(2413 try mod.failed_exports.putNoClobber(
2411 module.gpa,2414 mod.gpa,
2412 exp,2415 exp,
2413 try Module.ErrorMsg.create(2416 try Module.ErrorMsg.create(
2414 gpa,2417 gpa,
2415 decl.srcLoc(),2418 decl.srcLoc(mod),
2416 "Unimplemented: ExportOptions.section",2419 "Unimplemented: ExportOptions.section",
2417 .{},2420 .{},
2418 ),2421 ),
...@@ -2421,13 +2424,13 @@ pub fn updateDeclExports(...@@ -2421,13 +2424,13 @@ pub fn updateDeclExports(
2421 }2424 }
2422 }2425 }
24232426
2424 if (exp.options.linkage == .LinkOnce) {2427 if (exp.opts.linkage == .LinkOnce) {
2425 try module.failed_exports.putNoClobber(2428 try mod.failed_exports.putNoClobber(
2426 module.gpa,2429 mod.gpa,
2427 exp,2430 exp,
2428 try Module.ErrorMsg.create(2431 try Module.ErrorMsg.create(
2429 gpa,2432 gpa,
2430 decl.srcLoc(),2433 decl.srcLoc(mod),
2431 "Unimplemented: GlobalLinkage.LinkOnce",2434 "Unimplemented: GlobalLinkage.LinkOnce",
2432 .{},2435 .{},
2433 ),2436 ),
...@@ -2450,7 +2453,7 @@ pub fn updateDeclExports(...@@ -2450,7 +2453,7 @@ pub fn updateDeclExports(
2450 .n_value = decl_sym.n_value,2453 .n_value = decl_sym.n_value,
2451 };2454 };
24522455
2453 switch (exp.options.linkage) {2456 switch (exp.opts.linkage) {
2454 .Internal => {2457 .Internal => {
2455 // Symbol should be hidden, or in MachO lingo, private extern.2458 // Symbol should be hidden, or in MachO lingo, private extern.
2456 // We should also mark the symbol as Weak: n_desc == N_WEAK_DEF.2459 // We should also mark the symbol as Weak: n_desc == N_WEAK_DEF.
...@@ -2471,9 +2474,9 @@ pub fn updateDeclExports(...@@ -2471,9 +2474,9 @@ pub fn updateDeclExports(
2471 // TODO: this needs rethinking2474 // TODO: this needs rethinking
2472 const global = self.getGlobal(exp_name).?;2475 const global = self.getGlobal(exp_name).?;
2473 if (sym_loc.sym_index != global.sym_index and global.file != null) {2476 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(
2475 gpa,2478 gpa,
2476 decl.srcLoc(),2479 decl.srcLoc(mod),
2477 \\LinkError: symbol '{s}' defined multiple times2480 \\LinkError: symbol '{s}' defined multiple times
2478 ,2481 ,
2479 .{exp_name},2482 .{exp_name},
...@@ -2485,12 +2488,17 @@ pub fn updateDeclExports(...@@ -2485,12 +2488,17 @@ pub fn updateDeclExports(
2485 }2488 }
2486}2489}
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 {
2489 if (self.llvm_object) |_| return;2496 if (self.llvm_object) |_| return;
2490 const metadata = self.decls.getPtr(decl_index) orelse return;2497 const metadata = self.decls.getPtr(decl_index) orelse return;
24912498
2492 const gpa = self.base.allocator;2499 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)});
2494 defer gpa.free(exp_name);2502 defer gpa.free(exp_name);
2495 const sym_index = metadata.getExportPtr(self, exp_name) orelse return;2503 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 {...@@ -68,9 +68,9 @@ pub fn deinit(self: *NvPtx) void {
68 self.base.allocator.free(self.ptx_file_name);68 self.base.allocator.free(self.ptx_file_name);
69}69}
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 {
72 if (!build_options.have_llvm) return;72 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);
74}74}
7575
76pub fn updateDecl(self: *NvPtx, module: *Module, decl_index: Module.Decl.Index) !void {76pub 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 {...@@ -213,14 +213,14 @@ fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void {
213 const gpa = self.base.allocator;213 const gpa = self.base.allocator;
214 const mod = self.base.options.module.?;214 const mod = self.base.options.module.?;
215 const decl = mod.declPtr(decl_index);215 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));
217 if (fn_map_res.found_existing) {217 if (fn_map_res.found_existing) {
218 if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| {218 if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| {
219 gpa.free(old_entry.value.code);219 gpa.free(old_entry.value.code);
220 gpa.free(old_entry.value.lineinfo);220 gpa.free(old_entry.value.lineinfo);
221 }221 }
222 } else {222 } else {
223 const file = decl.getFileScope();223 const file = decl.getFileScope(mod);
224 const arena = self.path_arena.allocator();224 const arena = self.path_arena.allocator();
225 // each file gets a symbol225 // each file gets a symbol
226 fn_map_res.value_ptr.* = .{226 fn_map_res.value_ptr.* = .{
...@@ -276,17 +276,17 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi...@@ -276,17 +276,17 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
276 }276 }
277}277}
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 {
280 if (build_options.skip_non_native and builtin.object_format != .plan9) {280 if (build_options.skip_non_native and builtin.object_format != .plan9) {
281 @panic("Attempted to compile for object format that was disabled by build configuration");281 @panic("Attempted to compile for object format that was disabled by build configuration");
282 }282 }
283283
284 const func = mod.funcPtr(func_index);
284 const decl_index = func.owner_decl;285 const decl_index = func.owner_decl;
285 const decl = module.declPtr(decl_index);286 const decl = mod.declPtr(decl_index);
286 self.freeUnnamedConsts(decl_index);287 self.freeUnnamedConsts(decl_index);
287288
288 _ = try self.seeDecl(decl_index);289 _ = try self.seeDecl(decl_index);
289 log.debug("codegen decl {*} ({s})", .{ decl, decl.name });
290290
291 var code_buffer = std.ArrayList(u8).init(self.base.allocator);291 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
292 defer code_buffer.deinit();292 defer code_buffer.deinit();
...@@ -298,8 +298,8 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv...@@ -298,8 +298,8 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
298298
299 const res = try codegen.generateFunction(299 const res = try codegen.generateFunction(
300 &self.base,300 &self.base,
301 decl.srcLoc(),301 decl.srcLoc(mod),
302 func,302 func_index,
303 air,303 air,
304 liveness,304 liveness,
305 &code_buffer,305 &code_buffer,
...@@ -316,7 +316,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv...@@ -316,7 +316,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
316 .ok => try code_buffer.toOwnedSlice(),316 .ok => try code_buffer.toOwnedSlice(),
317 .fail => |em| {317 .fail => |em| {
318 decl.analysis = .codegen_failure;318 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);
320 return;320 return;
321 },321 },
322 };322 };
...@@ -344,8 +344,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I...@@ -344,8 +344,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
344 }344 }
345 const unnamed_consts = gop.value_ptr;345 const unnamed_consts = gop.value_ptr;
346346
347 const decl_name = try decl.getFullyQualifiedName(mod);347 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
348 defer self.base.allocator.free(decl_name);
349348
350 const index = unnamed_consts.items.len;349 const index = unnamed_consts.items.len;
351 // name is freed when the unnamed const is freed350 // 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...@@ -366,7 +365,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
366 };365 };
367 self.syms.items[info.sym_index.?] = sym;366 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, .{
370 .none = {},369 .none = {},
371 }, .{370 }, .{
372 .parent_atom_index = @enumToInt(decl_index),371 .parent_atom_index = @enumToInt(decl_index),
...@@ -388,14 +387,13 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I...@@ -388,14 +387,13 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
388 return @intCast(u32, info.got_index.?);387 return @intCast(u32, info.got_index.?);
389}388}
390389
391pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) !void {390pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void {
392 const decl = module.declPtr(decl_index);391 const decl = mod.declPtr(decl_index);
393392
394 if (decl.val.tag() == .extern_fn) {393 if (decl.val.getExternFunc(mod)) |_| {
395 return; // TODO Should we do more when front-end analyzed extern decl?394 return; // TODO Should we do more when front-end analyzed extern decl?
396 }395 }
397 if (decl.val.castTag(.variable)) |payload| {396 if (decl.val.getVariable(mod)) |variable| {
398 const variable = payload.data;
399 if (variable.is_extern) {397 if (variable.is_extern) {
400 return; // TODO Should we do more when front-end analyzed extern decl?398 return; // TODO Should we do more when front-end analyzed extern decl?
401 }399 }
...@@ -403,13 +401,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)...@@ -403,13 +401,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
403401
404 _ = try self.seeDecl(decl_index);402 _ = try self.seeDecl(decl_index);
405403
406 log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index });
407
408 var code_buffer = std.ArrayList(u8).init(self.base.allocator);404 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
409 defer code_buffer.deinit();405 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;
411 // TODO we need the symbol index for symbol in the table of locals for the containing atom407 // 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), .{
413 .ty = decl.ty,409 .ty = decl.ty,
414 .val = decl_val,410 .val = decl_val,
415 }, &code_buffer, .{ .none = {} }, .{411 }, &code_buffer, .{ .none = {} }, .{
...@@ -419,7 +415,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)...@@ -419,7 +415,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
419 .ok => code_buffer.items,415 .ok => code_buffer.items,
420 .fail => |em| {416 .fail => |em| {
421 decl.analysis = .codegen_failure;417 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);
423 return;419 return;
424 },420 },
425 };421 };
...@@ -432,9 +428,9 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)...@@ -432,9 +428,9 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
432}428}
433/// called at the end of update{Decl,Func}429/// called at the end of update{Decl,Func}
434fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void {430fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void {
435 const decl = self.base.options.module.?.declPtr(decl_index);431 const mod = self.base.options.module.?;
436 const is_fn = (decl.ty.zigTypeTag() == .Fn);432 const decl = mod.declPtr(decl_index);
437 log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name });433 const is_fn = (decl.ty.zigTypeTag(mod) == .Fn);
438 const sym_t: aout.Sym.Type = if (is_fn) .t else .d;434 const sym_t: aout.Sym.Type = if (is_fn) .t else .d;
439435
440 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);436 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 {...@@ -445,7 +441,7 @@ fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void {
445 const sym: aout.Sym = .{441 const sym: aout.Sym = .{
446 .value = undefined, // the value of stuff gets filled in in flushModule442 .value = undefined, // the value of stuff gets filled in in flushModule
447 .type = decl_block.type,443 .type = decl_block.type,
448 .name = mem.span(decl.name),444 .name = try self.base.allocator.dupe(u8, mod.intern_pool.stringToSlice(decl.name)),
449 };445 };
450446
451 if (decl_block.sym_index) |s| {447 if (decl_block.sym_index) |s| {
...@@ -566,10 +562,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -566,10 +562,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
566 var it = fentry.value_ptr.functions.iterator();562 var it = fentry.value_ptr.functions.iterator();
567 while (it.next()) |entry| {563 while (it.next()) |entry| {
568 const decl_index = entry.key_ptr.*;564 const decl_index = entry.key_ptr.*;
569 const decl = mod.declPtr(decl_index);
570 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);565 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
571 const out = entry.value_ptr.*;566 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 });
573 {567 {
574 // connect the previous decl to the next568 // connect the previous decl to the next
575 const delta_line = @intCast(i32, out.start_line) - @intCast(i32, linecount);569 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...@@ -615,10 +609,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
615 var it = self.data_decl_table.iterator();609 var it = self.data_decl_table.iterator();
616 while (it.next()) |entry| {610 while (it.next()) |entry| {
617 const decl_index = entry.key_ptr.*;611 const decl_index = entry.key_ptr.*;
618 const decl = mod.declPtr(decl_index);
619 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);612 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
620 const code = entry.value_ptr.*;613 const code = entry.value_ptr.*;
621 log.debug("write data decl {*} ({s})", .{ decl, decl.name });
622614
623 foff += code.len;615 foff += code.len;
624 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };616 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...@@ -694,19 +686,16 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
694 const source_decl = mod.declPtr(source_decl_index);686 const source_decl = mod.declPtr(source_decl_index);
695 for (kv.value_ptr.items) |reloc| {687 for (kv.value_ptr.items) |reloc| {
696 const target_decl_index = reloc.target;688 const target_decl_index = reloc.target;
697 const target_decl = mod.declPtr(target_decl_index);
698 const target_decl_block = self.getDeclBlock(self.decls.get(target_decl_index).?.index);689 const target_decl_block = self.getDeclBlock(self.decls.get(target_decl_index).?.index);
699 const target_decl_offset = target_decl_block.offset.?;690 const target_decl_offset = target_decl_block.offset.?;
700691
701 const offset = reloc.offset;692 const offset = reloc.offset;
702 const addend = reloc.addend;693 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
706 const code = blk: {695 const code = blk: {
707 const is_fn = source_decl.ty.zigTypeTag() == .Fn;696 const is_fn = source_decl.ty.zigTypeTag(mod) == .Fn;
708 if (is_fn) {697 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;
710 const output = table.get(source_decl_index).?;699 const output = table.get(source_decl_index).?;
711 break :blk output.code;700 break :blk output.code;
712 } else {701 } else {
...@@ -728,7 +717,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -728,7 +717,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
728}717}
729fn addDeclExports(718fn addDeclExports(
730 self: *Plan9,719 self: *Plan9,
731 module: *Module,720 mod: *Module,
732 decl_index: Module.Decl.Index,721 decl_index: Module.Decl.Index,
733 exports: []const *Module.Export,722 exports: []const *Module.Export,
734) !void {723) !void {
...@@ -736,12 +725,13 @@ fn addDeclExports(...@@ -736,12 +725,13 @@ fn addDeclExports(
736 const decl_block = self.getDeclBlock(metadata.index);725 const decl_block = self.getDeclBlock(metadata.index);
737726
738 for (exports) |exp| {727 for (exports) |exp| {
728 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
739 // plan9 does not support custom sections729 // plan9 does not support custom sections
740 if (exp.options.section) |section_name| {730 if (exp.opts.section.unwrap()) |section_name| {
741 if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) {731 if (!mod.intern_pool.stringEqlSlice(section_name, ".text") and !mod.intern_pool.stringEqlSlice(section_name, ".data")) {
742 try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(732 try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(
743 self.base.allocator,733 self.base.allocator,
744 module.declPtr(decl_index).srcLoc(),734 mod.declPtr(decl_index).srcLoc(mod),
745 "plan9 does not support extra sections",735 "plan9 does not support extra sections",
746 .{},736 .{},
747 ));737 ));
...@@ -751,10 +741,10 @@ fn addDeclExports(...@@ -751,10 +741,10 @@ fn addDeclExports(
751 const sym = .{741 const sym = .{
752 .value = decl_block.offset.?,742 .value = decl_block.offset.?,
753 .type = decl_block.type.toGlobal(),743 .type = decl_block.type.toGlobal(),
754 .name = exp.options.name,744 .name = try self.base.allocator.dupe(u8, exp_name),
755 };745 };
756746
757 if (metadata.getExport(self, exp.options.name)) |i| {747 if (metadata.getExport(self, exp_name)) |i| {
758 self.syms.items[i] = sym;748 self.syms.items[i] = sym;
759 } else {749 } else {
760 try self.syms.append(self.base.allocator, sym);750 try self.syms.append(self.base.allocator, sym);
...@@ -770,9 +760,9 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {...@@ -770,9 +760,9 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
770 // in the deleteUnusedDecl function.760 // in the deleteUnusedDecl function.
771 const mod = self.base.options.module.?;761 const mod = self.base.options.module.?;
772 const decl = mod.declPtr(decl_index);762 const decl = mod.declPtr(decl_index);
773 const is_fn = (decl.val.tag() == .function);763 const is_fn = decl.val.getFunctionIndex(mod) != .none;
774 if (is_fn) {764 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)).?;
776 var submap = symidx_and_submap.functions;766 var submap = symidx_and_submap.functions;
777 if (submap.fetchSwapRemove(decl_index)) |removed_entry| {767 if (submap.fetchSwapRemove(decl_index)) |removed_entry| {
778 self.base.allocator.free(removed_entry.value.code);768 self.base.allocator.free(removed_entry.value.code);
...@@ -955,7 +945,10 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {...@@ -955,7 +945,10 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {
955 try w.writeAll(sym.name);945 try w.writeAll(sym.name);
956 try w.writeByte(0);946 try w.writeByte(0);
957}947}
948
958pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {949pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
950 const mod = self.base.options.module.?;
951 const ip = &mod.intern_pool;
959 const writer = buf.writer();952 const writer = buf.writer();
960 // write the f symbols953 // write the f symbols
961 {954 {
...@@ -979,7 +972,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -979,7 +972,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
979 const sym = self.syms.items[decl_block.sym_index.?];972 const sym = self.syms.items[decl_block.sym_index.?];
980 try self.writeSym(writer, sym);973 try self.writeSym(writer, sym);
981 if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {974 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| {
983 try self.writeSym(writer, self.syms.items[exp_i]);976 try self.writeSym(writer, self.syms.items[exp_i]);
984 };977 };
985 }978 }
...@@ -1005,7 +998,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1005,7 +998,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1005 const sym = self.syms.items[decl_block.sym_index.?];998 const sym = self.syms.items[decl_block.sym_index.?];
1006 try self.writeSym(writer, sym);999 try self.writeSym(writer, sym);
1007 if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {1000 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| {
1009 const s = self.syms.items[exp_i];1002 const s = self.syms.items[exp_i];
1010 if (mem.eql(u8, s.name, "_start"))1003 if (mem.eql(u8, s.name, "_start"))
1011 self.entry_val = s.value;1004 self.entry_val = s.value;
...@@ -1031,7 +1024,7 @@ pub fn getDeclVAddr(...@@ -1031,7 +1024,7 @@ pub fn getDeclVAddr(
1031) !u64 {1024) !u64 {
1032 const mod = self.base.options.module.?;1025 const mod = self.base.options.module.?;
1033 const decl = mod.declPtr(decl_index);1026 const decl = mod.declPtr(decl_index);
1034 if (decl.ty.zigTypeTag() == .Fn) {1027 if (decl.ty.zigTypeTag(mod) == .Fn) {
1035 var start = self.bases.text;1028 var start = self.bases.text;
1036 var it_file = self.fn_decl_table.iterator();1029 var it_file = self.fn_decl_table.iterator();
1037 while (it_file.next()) |fentry| {1030 while (it_file.next()) |fentry| {
src/link/SpirV.zig+9-6
...@@ -103,11 +103,13 @@ pub fn deinit(self: *SpirV) void {...@@ -103,11 +103,13 @@ pub fn deinit(self: *SpirV) void {
103 self.decl_link.deinit();103 self.decl_link.deinit();
104}104}
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 {
107 if (build_options.skip_non_native) {107 if (build_options.skip_non_native) {
108 @panic("Attempted to compile for architecture that was disabled by build configuration");108 @panic("Attempted to compile for architecture that was disabled by build configuration");
109 }109 }
110110
111 const func = module.funcPtr(func_index);
112
111 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);113 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
112 defer decl_gen.deinit();114 defer decl_gen.deinit();
113115
...@@ -131,12 +133,12 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index)...@@ -131,12 +133,12 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index)
131133
132pub fn updateDeclExports(134pub fn updateDeclExports(
133 self: *SpirV,135 self: *SpirV,
134 module: *Module,136 mod: *Module,
135 decl_index: Module.Decl.Index,137 decl_index: Module.Decl.Index,
136 exports: []const *Module.Export,138 exports: []const *Module.Export,
137) !void {139) !void {
138 const decl = module.declPtr(decl_index);140 const decl = mod.declPtr(decl_index);
139 if (decl.val.tag() == .function and decl.ty.fnCallingConvention() == .Kernel) {141 if (decl.val.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) {
140 // TODO: Unify with resolveDecl in spirv.zig.142 // TODO: Unify with resolveDecl in spirv.zig.
141 const entry = try self.decl_link.getOrPut(decl_index);143 const entry = try self.decl_link.getOrPut(decl_index);
142 if (!entry.found_existing) {144 if (!entry.found_existing) {
...@@ -145,7 +147,7 @@ pub fn updateDeclExports(...@@ -145,7 +147,7 @@ pub fn updateDeclExports(
145 const spv_decl_index = entry.value_ptr.*;147 const spv_decl_index = entry.value_ptr.*;
146148
147 for (exports) |exp| {149 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));
149 }151 }
150 }152 }
151153
...@@ -188,7 +190,8 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No...@@ -188,7 +190,8 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
188 var error_info = std.ArrayList(u8).init(self.spv.arena);190 var error_info = std.ArrayList(u8).init(self.spv.arena);
189 try error_info.appendSlice("zig_errors");191 try error_info.appendSlice("zig_errors");
190 const module = self.base.options.module.?;192 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);
192 // Errors can contain pretty much any character - to encode them in a string we must escape195 // Errors can contain pretty much any character - to encode them in a string we must escape
193 // them somehow. Easiest here is to use some established scheme, one which also preseves the196 // them somehow. Easiest here is to use some established scheme, one which also preseves the
194 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.197 // 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) = .{},...@@ -149,7 +149,8 @@ discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{},
149/// into the final binary.149/// into the final binary.
150resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{},150resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{},
151/// Symbols that remain undefined after symbol resolution.151/// 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) = .{},
153/// Maps a symbol's location to an atom. This can be used to find meta154/// Maps a symbol's location to an atom. This can be used to find meta
154/// data of a symbol, such as its size, or its offset to perform a relocation.155/// data of a symbol, such as its size, or its offset to perform a relocation.
155/// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped.156/// 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 {...@@ -514,6 +515,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
514/// Leaves index undefined and the default flags (0).515/// Leaves index undefined and the default flags (0).
515fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc {516fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc {
516 const name_offset = try wasm.string_table.put(wasm.base.allocator, name);517 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 {
517 const sym_index = @intCast(u32, wasm.symbols.items.len);522 const sym_index = @intCast(u32, wasm.symbols.items.len);
518 const loc: SymbolLoc = .{ .index = sym_index, .file = null };523 const loc: SymbolLoc = .{ .index = sym_index, .file = null };
519 try wasm.symbols.append(wasm.base.allocator, .{524 try wasm.symbols.append(wasm.base.allocator, .{
...@@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
691 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});696 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});
692697
693 if (symbol.isUndefined()) {698 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);
695 }700 }
696 continue;701 continue;
697 }702 }
...@@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
801 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});806 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});
802 assert(wasm.resolved_symbols.swapRemove(existing_loc));807 assert(wasm.resolved_symbols.swapRemove(existing_loc));
803 if (existing_sym.isUndefined()) {808 if (existing_sym.isUndefined()) {
804 _ = wasm.undefs.swapRemove(sym_name);809 _ = wasm.undefs.swapRemove(sym_name_index);
805 }810 }
806 }811 }
807}812}
...@@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {...@@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {
812 log.debug("Resolving symbols in archives", .{});817 log.debug("Resolving symbols in archives", .{});
813 var index: u32 = 0;818 var index: u32 = 0;
814 undef_loop: while (index < wasm.undefs.count()) {819 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
817 for (wasm.archives.items) |archive| {822 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 });
818 const offset = archive.toc.get(sym_name) orelse {825 const offset = archive.toc.get(sym_name) orelse {
819 // symbol does not exist in this archive826 // symbol does not exist in this archive
820 continue;827 continue;
821 };828 };
822829
823 log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name });
824 // Symbol is found in unparsed object file within current archive.830 // Symbol is found in unparsed object file within current archive.
825 // Parse object and and resolve symbols again before we check remaining831 // Parse object and and resolve symbols again before we check remaining
826 // undefined symbols.832 // undefined symbols.
...@@ -1191,28 +1197,36 @@ fn validateFeatures(...@@ -1191,28 +1197,36 @@ fn validateFeatures(
1191/// if one or multiple undefined references exist. When none exist, the symbol will1197/// if one or multiple undefined references exist. When none exist, the symbol will
1192/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.1198/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.
1193fn resolveLazySymbols(wasm: *Wasm) !void {1199fn resolveLazySymbols(wasm: *Wasm) !void {
1194 if (wasm.undefs.fetchSwapRemove("__heap_base")) |kv| {1200 if (wasm.string_table.getOffset("__heap_base")) |name_offset| {
1195 const loc = try wasm.createSyntheticSymbol("__heap_base", .data);1201 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1196 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1202 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1197 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.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 }
1198 }1206 }
11991207
1200 if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| {1208 if (wasm.string_table.getOffset("__heap_end")) |name_offset| {
1201 const loc = try wasm.createSyntheticSymbol("__heap_end", .data);1209 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1202 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1210 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1203 _ = wasm.resolved_symbols.swapRemove(loc);1211 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1212 _ = wasm.resolved_symbols.swapRemove(loc);
1213 }
1204 }1214 }
12051215
1206 if (!wasm.base.options.shared_memory) {1216 if (!wasm.base.options.shared_memory) {
1207 if (wasm.undefs.fetchSwapRemove("__tls_base")) |kv| {1217 if (wasm.string_table.getOffset("__tls_base")) |name_offset| {
1208 const loc = try wasm.createSyntheticSymbol("__tls_base", .global);1218 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1209 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1219 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global);
1220 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1221 }
1210 }1222 }
1211 }1223 }
1212 if (wasm.undefs.fetchSwapRemove("__zig_errors_len")) |kv| {1224 if (wasm.string_table.getOffset("__zig_errors_len")) |name_offset| {
1213 const loc = try wasm.createSyntheticSymbol("__zig_errors_len", .data);1225 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1214 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1226 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1215 _ = wasm.resolved_symbols.swapRemove(kv.value);1227 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1228 _ = wasm.resolved_symbols.swapRemove(kv.value);
1229 }
1216 }1230 }
1217}1231}
12181232
...@@ -1324,17 +1338,18 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {...@@ -1324,17 +1338,18 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
1324 return index;1338 return index;
1325}1339}
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 {
1328 if (build_options.skip_non_native and builtin.object_format != .wasm) {1342 if (build_options.skip_non_native and builtin.object_format != .wasm) {
1329 @panic("Attempted to compile for object format that was disabled by build configuration");1343 @panic("Attempted to compile for object format that was disabled by build configuration");
1330 }1344 }
1331 if (build_options.have_llvm) {1345 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);
1333 }1347 }
13341348
1335 const tracy = trace(@src());1349 const tracy = trace(@src());
1336 defer tracy.end();1350 defer tracy.end();
13371351
1352 const func = mod.funcPtr(func_index);
1338 const decl_index = func.owner_decl;1353 const decl_index = func.owner_decl;
1339 const decl = mod.declPtr(decl_index);1354 const decl = mod.declPtr(decl_index);
1340 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);1355 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...@@ -1348,7 +1363,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
1348 defer code_writer.deinit();1363 defer code_writer.deinit();
1349 // const result = try codegen.generateFunction(1364 // const result = try codegen.generateFunction(
1350 // &wasm.base,1365 // &wasm.base,
1351 // decl.srcLoc(),1366 // decl.srcLoc(mod),
1352 // func,1367 // func,
1353 // air,1368 // air,
1354 // liveness,1369 // liveness,
...@@ -1357,8 +1372,8 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -1357,8 +1372,8 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
1357 // );1372 // );
1358 const result = try codegen.generateFunction(1373 const result = try codegen.generateFunction(
1359 &wasm.base,1374 &wasm.base,
1360 decl.srcLoc(),1375 decl.srcLoc(mod),
1361 func,1376 func_index,
1362 air,1377 air,
1363 liveness,1378 liveness,
1364 &code_writer,1379 &code_writer,
...@@ -1403,9 +1418,9 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -1403,9 +1418,9 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1403 defer tracy.end();1418 defer tracy.end();
14041419
1405 const decl = mod.declPtr(decl_index);1420 const decl = mod.declPtr(decl_index);
1406 if (decl.val.castTag(.function)) |_| {1421 if (decl.val.getFunction(mod)) |_| {
1407 return;1422 return;
1408 } else if (decl.val.castTag(.extern_fn)) |_| {1423 } else if (decl.val.getExternFunc(mod)) |_| {
1409 return;1424 return;
1410 }1425 }
14111426
...@@ -1413,19 +1428,20 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -1413,19 +1428,20 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1413 const atom = wasm.getAtomPtr(atom_index);1428 const atom = wasm.getAtomPtr(atom_index);
1414 atom.clear();1429 atom.clear();
14151430
1416 if (decl.isExtern()) {1431 if (decl.isExtern(mod)) {
1417 const variable = decl.getVariable().?;1432 const variable = decl.getOwnedVariable(mod).?;
1418 const name = mem.sliceTo(decl.name, 0);1433 const name = mod.intern_pool.stringToSlice(decl.name);
1419 return wasm.addOrUpdateImport(name, atom.sym_index, variable.lib_name, null);1434 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
1435 return wasm.addOrUpdateImport(name, atom.sym_index, lib_name, null);
1420 }1436 }
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
1423 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);1439 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);
1424 defer code_writer.deinit();1440 defer code_writer.deinit();
14251441
1426 const res = try codegen.generateSymbol(1442 const res = try codegen.generateSymbol(
1427 &wasm.base,1443 &wasm.base,
1428 decl.srcLoc(),1444 decl.srcLoc(mod),
1429 .{ .ty = decl.ty, .val = val },1445 .{ .ty = decl.ty, .val = val },
1430 &code_writer,1446 &code_writer,
1431 .none,1447 .none,
...@@ -1451,8 +1467,7 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I...@@ -1451,8 +1467,7 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I
1451 defer tracy.end();1467 defer tracy.end();
14521468
1453 const decl = mod.declPtr(decl_index);1469 const decl = mod.declPtr(decl_index);
1454 const decl_name = try decl.getFullyQualifiedName(mod);1470 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1455 defer wasm.base.allocator.free(decl_name);
14561471
1457 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });1472 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
1458 try dw.updateDeclLineNumber(mod, decl_index);1473 try dw.updateDeclLineNumber(mod, decl_index);
...@@ -1465,15 +1480,14 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8...@@ -1465,15 +1480,14 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8
1465 const atom_index = wasm.decls.get(decl_index).?;1480 const atom_index = wasm.decls.get(decl_index).?;
1466 const atom = wasm.getAtomPtr(atom_index);1481 const atom = wasm.getAtomPtr(atom_index);
1467 const symbol = &wasm.symbols.items[atom.sym_index];1482 const symbol = &wasm.symbols.items[atom.sym_index];
1468 const full_name = try decl.getFullyQualifiedName(mod);1483 const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1469 defer wasm.base.allocator.free(full_name);
1470 symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);1484 symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
1471 try atom.code.appendSlice(wasm.base.allocator, code);1485 try atom.code.appendSlice(wasm.base.allocator, code);
1472 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});1486 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});
14731487
1474 atom.size = @intCast(u32, code.len);1488 atom.size = @intCast(u32, code.len);
1475 if (code.len == 0) return;1489 if (code.len == 0) return;
1476 atom.alignment = decl.ty.abiAlignment(wasm.base.options.target);1490 atom.alignment = decl.ty.abiAlignment(mod);
1477}1491}
14781492
1479/// From a given symbol location, returns its `wasm.GlobalType`.1493/// From a given symbol location, returns its `wasm.GlobalType`.
...@@ -1523,9 +1537,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {...@@ -1523,9 +1537,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {
1523/// Returns the symbol index of the local1537/// Returns the symbol index of the local
1524/// The given `decl` is the parent decl whom owns the constant.1538/// The given `decl` is the parent decl whom owns the constant.
1525pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {1539pub 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
1528 const mod = wasm.base.options.module.?;1540 const mod = wasm.base.options.module.?;
1541 assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions
1529 const decl = mod.declPtr(decl_index);1542 const decl = mod.declPtr(decl_index);
15301543
1531 // Create and initialize a new local symbol and atom1544 // 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...@@ -1534,16 +1547,17 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
1534 const parent_atom = wasm.getAtomPtr(parent_atom_index);1547 const parent_atom = wasm.getAtomPtr(parent_atom_index);
1535 const local_index = parent_atom.locals.items.len;1548 const local_index = parent_atom.locals.items.len;
1536 try parent_atom.locals.append(wasm.base.allocator, atom_index);1549 try parent_atom.locals.append(wasm.base.allocator, atom_index);
1537 const fqdn = try decl.getFullyQualifiedName(mod);1550 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1538 defer wasm.base.allocator.free(fqdn);1551 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{
1539 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });1552 fqn, local_index,
1553 });
1540 defer wasm.base.allocator.free(name);1554 defer wasm.base.allocator.free(name);
1541 var value_bytes = std.ArrayList(u8).init(wasm.base.allocator);1555 var value_bytes = std.ArrayList(u8).init(wasm.base.allocator);
1542 defer value_bytes.deinit();1556 defer value_bytes.deinit();
15431557
1544 const code = code: {1558 const code = code: {
1545 const atom = wasm.getAtomPtr(atom_index);1559 const atom = wasm.getAtomPtr(atom_index);
1546 atom.alignment = tv.ty.abiAlignment(wasm.base.options.target);1560 atom.alignment = tv.ty.abiAlignment(mod);
1547 wasm.symbols.items[atom.sym_index] = .{1561 wasm.symbols.items[atom.sym_index] = .{
1548 .name = try wasm.string_table.put(wasm.base.allocator, name),1562 .name = try wasm.string_table.put(wasm.base.allocator, name),
1549 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),1563 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
...@@ -1555,7 +1569,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In...@@ -1555,7 +1569,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
15551569
1556 const result = try codegen.generateSymbol(1570 const result = try codegen.generateSymbol(
1557 &wasm.base,1571 &wasm.base,
1558 decl.srcLoc(),1572 decl.srcLoc(mod),
1559 tv,1573 tv,
1560 &value_bytes,1574 &value_bytes,
1561 .none,1575 .none,
...@@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3...@@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3
1611 wasm.symbols.items[sym_index] = symbol;1625 wasm.symbols.items[sym_index] = symbol;
1612 gop.value_ptr.* = .{ .index = sym_index, .file = null };1626 gop.value_ptr.* = .{ .index = sym_index, .file = null };
1613 try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {});1627 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.*);
1615 return sym_index;1629 return sym_index;
1616}1630}
16171631
...@@ -1632,7 +1646,7 @@ pub fn getDeclVAddr(...@@ -1632,7 +1646,7 @@ pub fn getDeclVAddr(
1632 const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;1646 const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
1633 const atom = wasm.getAtomPtr(atom_index);1647 const atom = wasm.getAtomPtr(atom_index);
1634 const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32;1648 const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32;
1635 if (decl.ty.zigTypeTag() == .Fn) {1649 if (decl.ty.zigTypeTag(mod) == .Fn) {
1636 assert(reloc_info.addend == 0); // addend not allowed for function relocations1650 assert(reloc_info.addend == 0); // addend not allowed for function relocations
1637 // We found a function pointer, so add it to our table,1651 // We found a function pointer, so add it to our table,
1638 // as function pointers are not allowed to be stored inside the data section.1652 // as function pointers are not allowed to be stored inside the data section.
...@@ -1689,36 +1703,37 @@ pub fn updateDeclExports(...@@ -1689,36 +1703,37 @@ pub fn updateDeclExports(
1689 const decl = mod.declPtr(decl_index);1703 const decl = mod.declPtr(decl_index);
1690 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);1704 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
1691 const atom = wasm.getAtom(atom_index);1705 const atom = wasm.getAtom(atom_index);
1706 const gpa = mod.gpa;
16921707
1693 for (exports) |exp| {1708 for (exports) |exp| {
1694 if (exp.options.section) |section| {1709 if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section| {
1695 try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create(1710 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(
1696 mod.gpa,1711 gpa,
1697 decl.srcLoc(),1712 decl.srcLoc(mod),
1698 "Unimplemented: ExportOptions.section '{s}'",1713 "Unimplemented: ExportOptions.section '{s}'",
1699 .{section},1714 .{section},
1700 ));1715 ));
1701 continue;1716 continue;
1702 }1717 }
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));
1705 if (wasm.globals.getPtr(export_name)) |existing_loc| {1720 if (wasm.globals.getPtr(export_name)) |existing_loc| {
1706 if (existing_loc.index == atom.sym_index) continue;1721 if (existing_loc.index == atom.sym_index) continue;
1707 const existing_sym: Symbol = existing_loc.getSymbol(wasm).*;1722 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;
1710 // When both the to-be-exported symbol and the already existing symbol1725 // When both the to-be-exported symbol and the already existing symbol
1711 // are strong symbols, we have a linker error.1726 // are strong symbols, we have a linker error.
1712 // In the other case we replace one with the other.1727 // In the other case we replace one with the other.
1713 if (!exp_is_weak and !existing_sym.isWeak()) {1728 if (!exp_is_weak and !existing_sym.isWeak()) {
1714 try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(1729 try mod.failed_exports.put(gpa, exp, try Module.ErrorMsg.create(
1715 mod.gpa,1730 gpa,
1716 decl.srcLoc(),1731 decl.srcLoc(mod),
1717 \\LinkError: symbol '{s}' defined multiple times1732 \\LinkError: symbol '{}' defined multiple times
1718 \\ first definition in '{s}'1733 \\ first definition in '{s}'
1719 \\ next definition in '{s}'1734 \\ next definition in '{s}'
1720 ,1735 ,
1721 .{ exp.options.name, wasm.name, wasm.name },1736 .{ exp.opts.name.fmt(&mod.intern_pool), wasm.name, wasm.name },
1722 ));1737 ));
1723 continue;1738 continue;
1724 } else if (exp_is_weak) {1739 } else if (exp_is_weak) {
...@@ -1735,7 +1750,7 @@ pub fn updateDeclExports(...@@ -1735,7 +1750,7 @@ pub fn updateDeclExports(
1735 const exported_atom = wasm.getAtom(exported_atom_index);1750 const exported_atom = wasm.getAtom(exported_atom_index);
1736 const sym_loc = exported_atom.symbolLoc();1751 const sym_loc = exported_atom.symbolLoc();
1737 const symbol = sym_loc.getSymbol(wasm);1752 const symbol = sym_loc.getSymbol(wasm);
1738 switch (exp.options.linkage) {1753 switch (exp.opts.linkage) {
1739 .Internal => {1754 .Internal => {
1740 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);1755 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);
1741 },1756 },
...@@ -1744,9 +1759,9 @@ pub fn updateDeclExports(...@@ -1744,9 +1759,9 @@ pub fn updateDeclExports(
1744 },1759 },
1745 .Strong => {}, // symbols are strong by default1760 .Strong => {}, // symbols are strong by default
1746 .LinkOnce => {1761 .LinkOnce => {
1747 try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create(1762 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(
1748 mod.gpa,1763 gpa,
1749 decl.srcLoc(),1764 decl.srcLoc(mod),
1750 "Unimplemented: LinkOnce",1765 "Unimplemented: LinkOnce",
1751 .{},1766 .{},
1752 ));1767 ));
...@@ -1754,7 +1769,7 @@ pub fn updateDeclExports(...@@ -1754,7 +1769,7 @@ pub fn updateDeclExports(
1754 },1769 },
1755 }1770 }
1756 // Ensure the symbol will be exported using the given name1771 // 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))) {
1758 try wasm.export_names.put(wasm.base.allocator, sym_loc, export_name);1773 try wasm.export_names.put(wasm.base.allocator, sym_loc, export_name);
1759 }1774 }
17601775
...@@ -1768,7 +1783,7 @@ pub fn updateDeclExports(...@@ -1768,7 +1783,7 @@ pub fn updateDeclExports(
17681783
1769 // if the symbol was previously undefined, remove it as an import1784 // if the symbol was previously undefined, remove it as an import
1770 _ = wasm.imports.remove(sym_loc);1785 _ = wasm.imports.remove(sym_loc);
1771 _ = wasm.undefs.swapRemove(exp.options.name);1786 _ = wasm.undefs.swapRemove(export_name);
1772 }1787 }
1773}1788}
17741789
...@@ -1792,7 +1807,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {...@@ -1792,7 +1807,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
1792 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));1807 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));
1793 }1808 }
17941809
1795 if (decl.isExtern()) {1810 if (decl.isExtern(mod)) {
1796 _ = wasm.imports.remove(atom.symbolLoc());1811 _ = wasm.imports.remove(atom.symbolLoc());
1797 }1812 }
1798 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());1813 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());
...@@ -1853,7 +1868,7 @@ pub fn addOrUpdateImport(...@@ -1853,7 +1868,7 @@ pub fn addOrUpdateImport(
1853 /// Symbol index that is external1868 /// Symbol index that is external
1854 symbol_index: u32,1869 symbol_index: u32,
1855 /// Optional library name (i.e. `extern "c" fn foo() void`1870 /// Optional library name (i.e. `extern "c" fn foo() void`
1856 lib_name: ?[*:0]const u8,1871 lib_name: ?[:0]const u8,
1857 /// The index of the type that represents the function signature1872 /// The index of the type that represents the function signature
1858 /// when the extern is a function. When this is null, a data-symbol1873 /// when the extern is a function. When this is null, a data-symbol
1859 /// is asserted instead.1874 /// is asserted instead.
...@@ -1864,7 +1879,7 @@ pub fn addOrUpdateImport(...@@ -1864,7 +1879,7 @@ pub fn addOrUpdateImport(
1864 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same1879 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same
1865 // name but different module can be resolved correctly.1880 // name but different module can be resolved correctly.
1866 const mangle_name = lib_name != null and1881 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");
1868 const full_name = if (mangle_name) full_name: {1883 const full_name = if (mangle_name) full_name: {
1869 break :full_name try std.fmt.allocPrint(wasm.base.allocator, "{s}|{s}", .{ name, lib_name.? });1884 break :full_name try std.fmt.allocPrint(wasm.base.allocator, "{s}|{s}", .{ name, lib_name.? });
1870 } else name;1885 } else name;
...@@ -1884,13 +1899,13 @@ pub fn addOrUpdateImport(...@@ -1884,13 +1899,13 @@ pub fn addOrUpdateImport(
1884 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };1899 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };
1885 global_gop.value_ptr.* = loc;1900 global_gop.value_ptr.* = loc;
1886 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});1901 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);
1888 }1903 }
18891904
1890 if (type_index) |ty_index| {1905 if (type_index) |ty_index| {
1891 const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null });1906 const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null });
1892 const module_name = if (lib_name) |l_name| blk: {1907 const module_name = if (lib_name) |l_name| blk: {
1893 break :blk mem.sliceTo(l_name, 0);1908 break :blk l_name;
1894 } else wasm.host_name;1909 } else wasm.host_name;
1895 if (!gop.found_existing) {1910 if (!gop.found_existing) {
1896 gop.value_ptr.* = .{1911 gop.value_ptr.* = .{
...@@ -2932,8 +2947,9 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {...@@ -2932,8 +2947,9 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
29322947
2933 const atom_index = try wasm.createAtom();2948 const atom_index = try wasm.createAtom();
2934 const atom = wasm.getAtomPtr(atom_index);2949 const atom = wasm.getAtomPtr(atom_index);
2935 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);2950 const slice_ty = Type.slice_const_u8_sentinel_0;
2936 atom.alignment = slice_ty.abiAlignment(wasm.base.options.target);2951 const mod = wasm.base.options.module.?;
2952 atom.alignment = slice_ty.abiAlignment(mod);
2937 const sym_index = atom.sym_index;2953 const sym_index = atom.sym_index;
29382954
2939 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table");2955 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table");
...@@ -2985,10 +3001,11 @@ fn populateErrorNameTable(wasm: *Wasm) !void {...@@ -2985,10 +3001,11 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
2985 // Addend for each relocation to the table3001 // Addend for each relocation to the table
2986 var addend: u32 = 0;3002 var addend: u32 = 0;
2987 const mod = wasm.base.options.module.?;3003 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);
2989 const len = @intCast(u32, error_name.len + 1); // names are 0-termianted3006 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;
2992 const offset = @intCast(u32, atom.code.items.len);3009 const offset = @intCast(u32, atom.code.items.len);
2993 // first we create the data for the slice of the name3010 // first we create the data for the slice of the name
2994 try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated3011 try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated
...@@ -3000,7 +3017,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {...@@ -3000,7 +3017,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
3000 .offset = offset,3017 .offset = offset,
3001 .addend = @intCast(i32, addend),3018 .addend = @intCast(i32, addend),
3002 });3019 });
3003 atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target));3020 atom.size += @intCast(u32, slice_ty.abiSize(mod));
3004 addend += len;3021 addend += len;
30053022
3006 // as we updated the error name table, we now store the actual name within the names atom3023 // 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...@@ -3366,15 +3383,15 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
3366 var decl_it = wasm.decls.iterator();3383 var decl_it = wasm.decls.iterator();
3367 while (decl_it.next()) |entry| {3384 while (decl_it.next()) |entry| {
3368 const decl = mod.declPtr(entry.key_ptr.*);3385 const decl = mod.declPtr(entry.key_ptr.*);
3369 if (decl.isExtern()) continue;3386 if (decl.isExtern(mod)) continue;
3370 const atom_index = entry.value_ptr.*;3387 const atom_index = entry.value_ptr.*;
3371 const atom = wasm.getAtomPtr(atom_index);3388 const atom = wasm.getAtomPtr(atom_index);
3372 if (decl.ty.zigTypeTag() == .Fn) {3389 if (decl.ty.zigTypeTag(mod) == .Fn) {
3373 try wasm.parseAtom(atom_index, .function);3390 try wasm.parseAtom(atom_index, .function);
3374 } else if (decl.getVariable()) |variable| {3391 } else if (decl.getOwnedVariable(mod)) |variable| {
3375 if (!variable.is_mutable) {3392 if (variable.is_const) {
3376 try wasm.parseAtom(atom_index, .{ .data = .read_only });3393 try wasm.parseAtom(atom_index, .{ .data = .read_only });
3377 } else if (variable.init.isUndefDeep()) {3394 } else if (variable.init.toValue().isUndefDeep(mod)) {
3378 // for safe build modes, we store the atom in the data segment,3395 // for safe build modes, we store the atom in the data segment,
3379 // whereas for unsafe build modes we store it in bss.3396 // whereas for unsafe build modes we store it in bss.
3380 const is_initialized = wasm.base.options.optimize_mode == .Debug or3397 const is_initialized = wasm.base.options.optimize_mode == .Debug or
src/main.zig+5
...@@ -569,6 +569,7 @@ const usage_build_generic =...@@ -569,6 +569,7 @@ const usage_build_generic =
569 \\ --verbose-link Display linker invocations569 \\ --verbose-link Display linker invocations
570 \\ --verbose-cc Display C compiler invocations570 \\ --verbose-cc Display C compiler invocations
571 \\ --verbose-air Enable compiler debug output for Zig AIR571 \\ --verbose-air Enable compiler debug output for Zig AIR
572 \\ --verbose-intern-pool Enable compiler debug output for InternPool
572 \\ --verbose-llvm-ir[=path] Enable compiler debug output for unoptimized LLVM IR573 \\ --verbose-llvm-ir[=path] Enable compiler debug output for unoptimized LLVM IR
573 \\ --verbose-llvm-bc=[path] Enable compiler debug output for unoptimized LLVM BC574 \\ --verbose-llvm-bc=[path] Enable compiler debug output for unoptimized LLVM BC
574 \\ --verbose-cimport Enable compiler debug output for C imports575 \\ --verbose-cimport Enable compiler debug output for C imports
...@@ -735,6 +736,7 @@ fn buildOutputType(...@@ -735,6 +736,7 @@ fn buildOutputType(
735 var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_LINK");736 var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_LINK");
736 var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_CC");737 var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_CC");
737 var verbose_air = false;738 var verbose_air = false;
739 var verbose_intern_pool = false;
738 var verbose_llvm_ir: ?[]const u8 = null;740 var verbose_llvm_ir: ?[]const u8 = null;
739 var verbose_llvm_bc: ?[]const u8 = null;741 var verbose_llvm_bc: ?[]const u8 = null;
740 var verbose_cimport = false;742 var verbose_cimport = false;
...@@ -1460,6 +1462,8 @@ fn buildOutputType(...@@ -1460,6 +1462,8 @@ fn buildOutputType(
1460 verbose_cc = true;1462 verbose_cc = true;
1461 } else if (mem.eql(u8, arg, "--verbose-air")) {1463 } else if (mem.eql(u8, arg, "--verbose-air")) {
1462 verbose_air = true;1464 verbose_air = true;
1465 } else if (mem.eql(u8, arg, "--verbose-intern-pool")) {
1466 verbose_intern_pool = true;
1463 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {1467 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
1464 verbose_llvm_ir = "-";1468 verbose_llvm_ir = "-";
1465 } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {1469 } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
...@@ -3156,6 +3160,7 @@ fn buildOutputType(...@@ -3156,6 +3160,7 @@ fn buildOutputType(
3156 .verbose_cc = verbose_cc,3160 .verbose_cc = verbose_cc,
3157 .verbose_link = verbose_link,3161 .verbose_link = verbose_link,
3158 .verbose_air = verbose_air,3162 .verbose_air = verbose_air,
3163 .verbose_intern_pool = verbose_intern_pool,
3159 .verbose_llvm_ir = verbose_llvm_ir,3164 .verbose_llvm_ir = verbose_llvm_ir,
3160 .verbose_llvm_bc = verbose_llvm_bc,3165 .verbose_llvm_bc = verbose_llvm_bc,
3161 .verbose_cimport = verbose_cimport,3166 .verbose_cimport = verbose_cimport,
src/print_air.zig+32-37
...@@ -7,6 +7,7 @@ const Value = @import("value.zig").Value;...@@ -7,6 +7,7 @@ const Value = @import("value.zig").Value;
7const Type = @import("type.zig").Type;7const Type = @import("type.zig").Type;
8const Air = @import("Air.zig");8const Air = @import("Air.zig");
9const Liveness = @import("Liveness.zig");9const Liveness = @import("Liveness.zig");
10const InternPool = @import("InternPool.zig");
1011
11pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) void {12pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) void {
12 const instruction_bytes = air.instructions.len *13 const instruction_bytes = air.instructions.len *
...@@ -14,12 +15,11 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo...@@ -14,12 +15,11 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo
14 // the debug safety tag but we want to measure release size.15 // the debug safety tag but we want to measure release size.
15 (@sizeOf(Air.Inst.Tag) + 8);16 (@sizeOf(Air.Inst.Tag) + 8);
16 const extra_bytes = air.extra.len * @sizeOf(u32);17 const extra_bytes = air.extra.len * @sizeOf(u32);
17 const values_bytes = air.values.len * @sizeOf(Value);
18 const tomb_bytes = if (liveness) |l| l.tomb_bits.len * @sizeOf(usize) else 0;18 const tomb_bytes = if (liveness) |l| l.tomb_bits.len * @sizeOf(usize) else 0;
19 const liveness_extra_bytes = if (liveness) |l| l.extra.len * @sizeOf(u32) else 0;19 const liveness_extra_bytes = if (liveness) |l| l.extra.len * @sizeOf(u32) else 0;
20 const liveness_special_bytes = if (liveness) |l| l.special.count() * 8 else 0;20 const liveness_special_bytes = if (liveness) |l| l.special.count() * 8 else 0;
21 const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes +21 const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes +
22 values_bytes + @sizeOf(Liveness) + liveness_extra_bytes +22 @sizeOf(Liveness) + liveness_extra_bytes +
23 liveness_special_bytes + tomb_bytes;23 liveness_special_bytes + tomb_bytes;
2424
25 // zig fmt: off25 // zig fmt: off
...@@ -27,7 +27,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo...@@ -27,7 +27,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo
27 \\# Total AIR+Liveness bytes: {}27 \\# Total AIR+Liveness bytes: {}
28 \\# AIR Instructions: {d} ({})28 \\# AIR Instructions: {d} ({})
29 \\# AIR Extra Data: {d} ({})29 \\# AIR Extra Data: {d} ({})
30 \\# AIR Values Bytes: {d} ({})
31 \\# Liveness tomb_bits: {}30 \\# Liveness tomb_bits: {}
32 \\# Liveness Extra Data: {d} ({})31 \\# Liveness Extra Data: {d} ({})
33 \\# Liveness special table: {d} ({})32 \\# Liveness special table: {d} ({})
...@@ -36,7 +35,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo...@@ -36,7 +35,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo
36 fmtIntSizeBin(total_bytes),35 fmtIntSizeBin(total_bytes),
37 air.instructions.len, fmtIntSizeBin(instruction_bytes),36 air.instructions.len, fmtIntSizeBin(instruction_bytes),
38 air.extra.len, fmtIntSizeBin(extra_bytes),37 air.extra.len, fmtIntSizeBin(extra_bytes),
39 air.values.len, fmtIntSizeBin(values_bytes),
40 fmtIntSizeBin(tomb_bytes),38 fmtIntSizeBin(tomb_bytes),
41 if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes),39 if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes),
42 if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes),40 if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes),
...@@ -92,14 +90,10 @@ const Writer = struct {...@@ -92,14 +90,10 @@ const Writer = struct {
9290
93 fn writeAllConstants(w: *Writer, s: anytype) @TypeOf(s).Error!void {91 fn writeAllConstants(w: *Writer, s: anytype) @TypeOf(s).Error!void {
94 for (w.air.instructions.items(.tag), 0..) |tag, i| {92 for (w.air.instructions.items(.tag), 0..) |tag, i| {
93 if (tag != .interned) continue;
95 const inst = @intCast(Air.Inst.Index, i);94 const inst = @intCast(Air.Inst.Index, i);
96 switch (tag) {95 try w.writeInst(s, inst);
97 .constant, .const_ty => {96 try s.writeByte('\n');
98 try w.writeInst(s, inst);
99 try s.writeByte('\n');
100 },
101 else => continue,
102 }
103 }97 }
104 }98 }
10599
...@@ -225,7 +219,6 @@ const Writer = struct {...@@ -225,7 +219,6 @@ const Writer = struct {
225 .save_err_return_trace_index,219 .save_err_return_trace_index,
226 => try w.writeNoOp(s, inst),220 => try w.writeNoOp(s, inst),
227221
228 .const_ty,
229 .alloc,222 .alloc,
230 .ret_ptr,223 .ret_ptr,
231 .err_return_trace,224 .err_return_trace,
...@@ -304,7 +297,9 @@ const Writer = struct {...@@ -304,7 +297,9 @@ const Writer = struct {
304297
305 .struct_field_ptr => try w.writeStructField(s, inst),298 .struct_field_ptr => try w.writeStructField(s, inst),
306 .struct_field_val => try w.writeStructField(s, inst),299 .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),
308 .assembly => try w.writeAssembly(s, inst),303 .assembly => try w.writeAssembly(s, inst),
309 .dbg_stmt => try w.writeDbgStmt(s, inst),304 .dbg_stmt => try w.writeDbgStmt(s, inst),
310305
...@@ -364,13 +359,7 @@ const Writer = struct {...@@ -364,13 +359,7 @@ const Writer = struct {
364 }359 }
365360
366 fn writeType(w: *Writer, s: anytype, ty: Type) !void {361 fn writeType(w: *Writer, s: anytype, ty: Type) !void {
367 const t = ty.tag();362 return ty.print(s, w.module);
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 }
374 }363 }
375364
376 fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {365 fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
...@@ -432,9 +421,10 @@ const Writer = struct {...@@ -432,9 +421,10 @@ const Writer = struct {
432 }421 }
433422
434 fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {423 fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
424 const mod = w.module;
435 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;425 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
436 const vector_ty = w.air.getRefType(ty_pl.ty);426 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));
438 const elements = @ptrCast([]const Air.Inst.Ref, w.air.extra[ty_pl.payload..][0..len]);428 const elements = @ptrCast([]const Air.Inst.Ref, w.air.extra[ty_pl.payload..][0..len]);
439429
440 try w.writeType(s, vector_ty);430 try w.writeType(s, vector_ty);
...@@ -511,10 +501,11 @@ const Writer = struct {...@@ -511,10 +501,11 @@ const Writer = struct {
511 }501 }
512502
513 fn writeSelect(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {503 fn writeSelect(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
504 const mod = w.module;
514 const pl_op = w.air.instructions.items(.data)[inst].pl_op;505 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
515 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;506 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);
518 try w.writeType(s, elem_ty);509 try w.writeType(s, elem_ty);
519 try s.writeAll(", ");510 try s.writeAll(", ");
520 try w.writeOperand(s, inst, 0, pl_op.operand);511 try w.writeOperand(s, inst, 0, pl_op.operand);
...@@ -605,12 +596,12 @@ const Writer = struct {...@@ -605,12 +596,12 @@ const Writer = struct {
605 try s.print(", {d}", .{extra.field_index});596 try s.print(", {d}", .{extra.field_index});
606 }597 }
607598
608 fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {599 fn writeInterned(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
609 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;600 const mod = w.module;
610 const val = w.air.values[ty_pl.payload];601 const ip_index = w.air.instructions.items(.data)[inst].interned;
611 const ty = w.air.getRefType(ty_pl.ty);602 const ty = mod.intern_pool.indexToKey(ip_index).typeOf().toType();
612 try w.writeType(s, ty);603 try w.writeType(s, ty);
613 try s.print(", {}", .{val.fmtValue(ty, w.module)});604 try s.print(", {}", .{ip_index.toValue().fmtValue(ty, mod)});
614 }605 }
615606
616 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {607 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
...@@ -621,7 +612,7 @@ const Writer = struct {...@@ -621,7 +612,7 @@ const Writer = struct {
621 var extra_i: usize = extra.end;612 var extra_i: usize = extra.end;
622 var op_index: usize = 0;613 var op_index: usize = 0;
623614
624 const ret_ty = w.air.typeOfIndex(inst);615 const ret_ty = w.typeOfIndex(inst);
625 try w.writeType(s, ret_ty);616 try w.writeType(s, ret_ty);
626617
627 if (is_volatile) {618 if (is_volatile) {
...@@ -692,17 +683,17 @@ const Writer = struct {...@@ -692,17 +683,17 @@ const Writer = struct {
692 }683 }
693684
694 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {685 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;686 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
696 const function = w.air.values[ty_pl.payload].castTag(.function).?.data;687 const func_index = ty_fn.func;
697 const owner_decl = w.module.declPtr(function.owner_decl);688 const owner_decl = w.module.declPtr(w.module.funcPtr(func_index).owner_decl);
698 try s.print("{s}", .{owner_decl.name});689 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
699 }690 }
700691
701 fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {692 fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
702 const pl_op = w.air.instructions.items(.data)[inst].pl_op;693 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
703 try w.writeOperand(s, inst, 0, pl_op.operand);694 try w.writeOperand(s, inst, 0, pl_op.operand);
704 const name = w.air.nullTerminatedString(pl_op.payload);695 const name = w.air.nullTerminatedString(pl_op.payload);
705 try s.print(", {s}", .{name});696 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)});
706 }697 }
707698
708 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {699 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
...@@ -965,14 +956,13 @@ const Writer = struct {...@@ -965,14 +956,13 @@ const Writer = struct {
965 operand: Air.Inst.Ref,956 operand: Air.Inst.Ref,
966 dies: bool,957 dies: bool,
967 ) @TypeOf(s).Error!void {958 ) @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) {
971 return s.print("@{}", .{operand});962 return s.print("@{}", .{operand});
972 }963 }
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);
976 }966 }
977967
978 fn writeInstIndex(968 fn writeInstIndex(
...@@ -985,4 +975,9 @@ const Writer = struct {...@@ -985,4 +975,9 @@ const Writer = struct {
985 try s.print("%{d}", .{inst});975 try s.print("%{d}", .{inst});
986 if (dies) try s.writeByte('!');976 if (dies) try s.writeByte('!');
987 }977 }
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 }
988};983};
src/print_zir.zig+5-9
...@@ -3,6 +3,7 @@ const mem = std.mem;...@@ -3,6 +3,7 @@ const mem = std.mem;
3const Allocator = std.mem.Allocator;3const Allocator = std.mem.Allocator;
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const Ast = std.zig.Ast;5const Ast = std.zig.Ast;
6const InternPool = @import("InternPool.zig");
67
7const Zir = @import("Zir.zig");8const Zir = @import("Zir.zig");
8const Module = @import("Module.zig");9const Module = @import("Module.zig");
...@@ -1191,7 +1192,7 @@ const Writer = struct {...@@ -1191,7 +1192,7 @@ const Writer = struct {
1191 .field => {1192 .field => {
1192 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);1193 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
1193 try self.writeInstRef(stream, extra.data.obj_ptr);1194 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)});
1195 },1196 },
1196 }1197 }
1197 try stream.writeAll(", [");1198 try stream.writeAll(", [");
...@@ -2468,14 +2469,9 @@ const Writer = struct {...@@ -2468,14 +2469,9 @@ const Writer = struct {
2468 }2469 }
24692470
2470 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {2471 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {
2471 var i: usize = @enumToInt(ref);2472 const i = @enumToInt(ref);
24722473 if (i < InternPool.static_len) return stream.print("@{}", .{@intToEnum(InternPool.Index, i)});
2473 if (i < Zir.Inst.Ref.typed_value_map.len) {2474 return self.writeInstIndex(stream, i - InternPool.static_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));
2479 }2475 }
24802476
2481 fn writeInstIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2477 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 {...@@ -512,134 +512,6 @@ pub fn needUnwindTables(target: std.Target) bool {
512 return target.os.tag == .windows;512 return target.os.tag == .windows;
513}513}
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
643pub fn defaultAddressSpace(515pub fn defaultAddressSpace(
644 target: std.Target,516 target: std.Target,
645 context: enum {517 context: enum {
...@@ -777,3 +649,14 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {...@@ -777,3 +649,14 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
777 else => "o", // Non-standard649 else => "o", // Non-standard
778 };650 };
779}651}
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);...@@ -9,176 +9,42 @@ const log = std.log.scoped(.Type);
9const target_util = @import("target.zig");9const target_util = @import("target.zig");
10const TypedValue = @import("TypedValue.zig");10const TypedValue = @import("TypedValue.zig");
11const Sema = @import("Sema.zig");11const Sema = @import("Sema.zig");
12const InternPool = @import("InternPool.zig");
1213
13const file_struct = @This();14/// Both types and values are canonically represented by a single 32-bit integer
1415/// which is an index into an `InternPool` data structure.
15/// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication.16/// This struct abstracts around this storage by providing methods only
16/// It's important for this type to be small.17/// applicable to types rather than values in general.
17/// Types are not de-duplicated, which helps with multi-threading since it obviates the requirement18pub const Type = struct {
18/// of obtaining a lock on a global type table, as well as making the19 ip_index: InternPool.Index,
19/// garbage collection bookkeeping simpler.20
20/// This union takes advantage of the fact that the first page of memory21 pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId {
21/// is unmapped, giving us 4096 possible enum tags that have no payload.22 return ty.zigTypeTagOrPoison(mod) catch unreachable;
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 }
160 }23 }
16124
162 pub fn baseZigTypeTag(self: Type) std.builtin.TypeId {25 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
163 return switch (self.zigTypeTag()) {26 return mod.intern_pool.zigTypeTagOrPoison(ty.toIntern());
164 .ErrorUnion => self.errorUnionPayload().baseZigTypeTag(),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),
165 .Optional => {32 .Optional => {
166 var buf: Payload.ElemType = undefined;33 return self.optionalChild(mod).baseZigTypeTag(mod);
167 return self.optionalChild(&buf).baseZigTypeTag();
168 },34 },
169 else => |t| t,35 else => |t| t,
170 };36 };
171 }37 }
17238
173 pub fn isSelfComparable(ty: Type, is_equality_cmp: bool) bool {39 pub fn isSelfComparable(ty: Type, mod: *const Module, is_equality_cmp: bool) bool {
174 return switch (ty.zigTypeTag()) {40 return switch (ty.zigTypeTag(mod)) {
175 .Int,41 .Int,
176 .Float,42 .Float,
177 .ComptimeFloat,43 .ComptimeFloat,
178 .ComptimeInt,44 .ComptimeInt,
179 => true,45 => true,
18046
181 .Vector => ty.elemType2().isSelfComparable(is_equality_cmp),47 .Vector => ty.elemType2(mod).isSelfComparable(mod, is_equality_cmp),
18248
183 .Bool,49 .Bool,
184 .Type,50 .Type,
...@@ -201,1317 +67,70 @@ pub const Type = extern union {...@@ -201,1317 +67,70 @@ pub const Type = extern union {
201 .Frame,67 .Frame,
202 => false,68 => 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)),
205 .Optional => {71 .Optional => {
206 if (!is_equality_cmp) return false;72 if (!is_equality_cmp) return false;
207 var buf: Payload.ElemType = undefined;73 return ty.optionalChild(mod).isSelfComparable(mod, is_equality_cmp);
208 return ty.optionalChild(&buf).isSelfComparable(is_equality_cmp);
209 },74 },
210 };75 };
211 }76 }
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
287 /// If it is a function pointer, returns the function type. Otherwise returns null.78 /// If it is a function pointer, returns the function type. Otherwise returns null.
288 pub fn castPtrToFn(ty: Type) ?Type {79 pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type {
289 if (ty.zigTypeTag() != .Pointer) return null;80 if (ty.zigTypeTag(mod) != .Pointer) return null;
290 const elem_ty = ty.childType();81 const elem_ty = ty.childType(mod);
291 if (elem_ty.zigTypeTag() != .Fn) return null;82 if (elem_ty.zigTypeTag(mod) != .Fn) return null;
292 return elem_ty;83 return elem_ty;
293 }84 }
29485
295 pub fn ptrIsMutable(ty: Type) bool {86 /// Asserts the type is a pointer.
296 return switch (ty.tag()) {87 pub fn ptrIsMutable(ty: Type, mod: *const Module) bool {
297 .single_const_pointer_to_comptime_int,88 return !mod.intern_pool.indexToKey(ty.toIntern()).ptr_type.flags.is_const;
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 };
328 }89 }
32990
330 pub fn ptrInfo(self: Type) Payload.Pointer {91 pub const ArrayInfo = struct {
331 switch (self.tag()) {92 elem_type: Type,
332 .single_const_pointer_to_comptime_int => return .{ .data = .{93 sentinel: ?Value = null,
333 .pointee_type = Type.initTag(.comptime_int),94 len: u64,
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 }
1275 };95 };
127696
1277 pub fn copy(self: Type, allocator: Allocator) error{OutOfMemory}!Type {97 pub fn arrayInfo(self: Type, mod: *const Module) ArrayInfo {
1278 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {98 return .{
1279 return Type{ .tag_if_small_enough = self.tag_if_small_enough };99 .len = self.arrayLen(mod),
1280 } else switch (self.ptr_otherwise.tag) {100 .sentinel = self.sentinel(mod),
1281 .u1,101 .elem_type = self.childType(mod),
1282 .u8,102 };
1283 .i8,103 }
1284 .u16,104
1285 .i16,105 pub fn ptrInfoIp(ip: *const InternPool, ty: InternPool.Index) InternPool.Key.PtrType {
1286 .u29,106 return switch (ip.indexToKey(ty)) {
1287 .u32,107 .ptr_type => |p| p,
1288 .i32,108 .opt_type => |child| switch (ip.indexToKey(child)) {
1289 .u64,109 .ptr_type => |p| p,
1290 .i64,110 else => unreachable,
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);
1496 },111 },
1497 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),112 else => unreachable,
1498 .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred),113 };
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 }
1508 }114 }
1509115
1510 fn copyPayloadShallow(self: Type, allocator: Allocator, comptime T: type) error{OutOfMemory}!Type {116 pub fn ptrInfo(ty: Type, mod: *const Module) Payload.Pointer.Data {
1511 const payload = self.cast(T).?;117 return Payload.Pointer.Data.fromKey(ptrInfoIp(&mod.intern_pool, ty.toIntern()));
1512 const new_payload = try allocator.create(T);118 }
1513 new_payload.* = payload.*;119
1514 return Type{ .ptr_otherwise = &new_payload.base };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()));
1515 }134 }
1516135
1517 pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {136 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 {...@@ -1550,7 +169,7 @@ pub const Type = extern union {
1550 }169 }
1551170
1552 /// This is a debug function. In order to print types in a meaningful way171 /// 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.
1554 pub fn dump(173 pub fn dump(
1555 start_type: Type,174 start_type: Type,
1556 comptime unused_format_string: []const u8,175 comptime unused_format_string: []const u8,
...@@ -1559,372 +178,7 @@ pub const Type = extern union {...@@ -1559,372 +178,7 @@ pub const Type = extern union {
1559 ) @TypeOf(writer).Error!void {178 ) @TypeOf(writer).Error!void {
1560 _ = options;179 _ = options;
1561 comptime assert(unused_format_string.len == 0);180 comptime assert(unused_format_string.len == 0);
1562 if (true) {181 return writer.print("{any}", .{start_type.ip_index});
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 }
1928 }182 }
1929183
1930 pub const nameAllocArena = nameAlloc;184 pub const nameAllocArena = nameAlloc;
...@@ -1938,253 +192,16 @@ pub const Type = extern union {...@@ -1938,253 +192,16 @@ pub const Type = extern union {
1938192
1939 /// Prints a name suitable for `@typeName`.193 /// Prints a name suitable for `@typeName`.
1940 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {194 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
1941 const t = ty.tag();195 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1942 switch (t) {196 .int_type => |int_type| {
1943 .inferred_alloc_const => unreachable,197 const sign_char: u8 = switch (int_type.signedness) {
1944 .inferred_alloc_mut => unreachable,198 .signed => 'i',
1945 .generic_poison => unreachable,199 .unsigned => 'u',
1946200 };
1947 // TODO get rid of these Type.Tag values.201 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
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("}");
2175 },202 },
2176203 .ptr_type => {
2177 .pointer,204 const info = ty.ptrInfo(mod);
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;
2188205
2189 if (info.sentinel) |s| switch (info.size) {206 if (info.sentinel) |s| switch (info.size) {
2190 .One, .C => unreachable,207 .One, .C => unreachable,
...@@ -2200,7 +217,7 @@ pub const Type = extern union {...@@ -2200,7 +217,7 @@ pub const Type = extern union {
2200 if (info.@"align" != 0) {217 if (info.@"align" != 0) {
2201 try writer.print("align({d}", .{info.@"align"});218 try writer.print("align({d}", .{info.@"align"});
2202 } else {219 } else {
2203 const alignment = info.pointee_type.abiAlignment(mod.getTarget());220 const alignment = info.pointee_type.abiAlignment(mod);
2204 try writer.print("align({d}", .{alignment});221 try writer.print("align({d}", .{alignment});
2205 }222 }
2206223
...@@ -2222,127 +239,228 @@ pub const Type = extern union {...@@ -2222,127 +239,228 @@ pub const Type = extern union {
2222 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");239 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
2223240
2224 try print(info.pointee_type, writer, mod);241 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("}");
2225 },370 },
2226371
2227 .int_signed => {372 .union_type => |union_type| {
2228 const bits = ty.castTag(.int_signed).?.data;373 const union_obj = mod.unionPtr(union_type.index);
2229 return writer.print("i{d}", .{bits});374 const decl = mod.declPtr(union_obj.owner_decl);
2230 },375 try decl.renderFullyQualifiedName(mod, writer);
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);
2244 },376 },
2245 .optional_single_const_pointer => {377 .opaque_type => |opaque_type| {
2246 const pointee_type = ty.castTag(.optional_single_const_pointer).?.data;378 const decl = mod.declPtr(opaque_type.decl);
2247 try writer.writeAll("?*const ");379 try decl.renderFullyQualifiedName(mod, writer);
2248 try print(pointee_type, writer, mod);
2249 },380 },
2250 .anyframe_T => {381 .enum_type => |enum_type| {
2251 const return_type = ty.castTag(.anyframe_T).?.data;382 const decl = mod.declPtr(enum_type.decl);
2252 try writer.print("anyframe->", .{});383 try decl.renderFullyQualifiedName(mod, writer);
2253 try print(return_type, writer, mod);
2254 },384 },
2255 .error_set => {385 .func_type => |fn_info| {
2256 const names = ty.castTag(.error_set).?.data.names.keys();386 if (fn_info.is_noinline) {
2257 try writer.writeAll("error{");387 try writer.writeAll("noinline ");
2258 for (names, 0..) |name, i| {
2259 if (i != 0) try writer.writeByte(',');
2260 try writer.writeAll(name);
2261 }388 }
2262 try writer.writeAll("}");389 try writer.writeAll("fn(");
2263 },390 for (fn_info.param_types, 0..) |param_ty, i| {
2264 .error_set_single => {391 if (i != 0) try writer.writeAll(", ");
2265 const name = ty.castTag(.error_set_single).?.data;392 if (std.math.cast(u5, i)) |index| {
2266 return writer.print("error{{{s}}}", .{name});393 if (fn_info.paramIsComptime(index)) {
2267 },394 try writer.writeAll("comptime ");
2268 .error_set_merged => {395 }
2269 const names = ty.castTag(.error_set_merged).?.data.keys();396 if (fn_info.paramIsNoalias(index)) {
2270 try writer.writeAll("error{");397 try writer.writeAll("noalias ");
2271 for (names, 0..) |name, i| {398 }
2272 if (i != 0) try writer.writeByte(',');399 }
2273 try writer.writeAll(name);400 if (param_ty == .generic_poison_type) {
401 try writer.writeAll("anytype");
402 } else {
403 try print(param_ty.toType(), writer, mod);
404 }
2274 }405 }
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);
2276 },431 },
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,
2277 }454 }
2278 }455 }
2279456
2280 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {457 pub fn toIntern(ty: Type) InternPool.Index {
2281 switch (self.tag()) {458 assert(ty.ip_index != .none);
2282 .u1 => return Value.initTag(.u1_type),459 return ty.ip_index;
2283 .u8 => return Value.initTag(.u8_type),460 }
2284 .i8 => return Value.initTag(.i8_type),461
2285 .u16 => return Value.initTag(.u16_type),462 pub fn toValue(self: Type) Value {
2286 .u29 => return Value.initTag(.u29_type),463 return self.toIntern().toValue();
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 }
2346 }464 }
2347465
2348 const RuntimeBitsError = Module.CompileError || error{NeedLazy};466 const RuntimeBitsError = Module.CompileError || error{NeedLazy};
...@@ -2360,365 +478,319 @@ pub const Type = extern union {...@@ -2360,365 +478,319 @@ pub const Type = extern union {
2360 /// may return false positives.478 /// may return false positives.
2361 pub fn hasRuntimeBitsAdvanced(479 pub fn hasRuntimeBitsAdvanced(
2362 ty: Type,480 ty: Type,
481 mod: *Module,
2363 ignore_comptime_only: bool,482 ignore_comptime_only: bool,
2364 strat: AbiAlignmentAdvancedStrat,483 strat: AbiAlignmentAdvancedStrat,
2365 ) RuntimeBitsError!bool {484 ) RuntimeBitsError!bool {
2366 switch (ty.tag()) {485 return switch (ty.toIntern()) {
2367 .u1,486 // False because it is a comptime-only type.
2368 .u8,487 .empty_struct_type => false,
2369 .i8,488 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2370 .u16,489 .int_type => |int_type| int_type.bits != 0,
2371 .i16,490 .ptr_type => |ptr_type| {
2372 .u29,491 // Pointers to zero-bit types still have a runtime address; however, pointers
2373 .u32,492 // to comptime-only types do not, with the exception of function pointers.
2374 .i32,493 if (ignore_comptime_only) return true;
2375 .u64,494 const child_ty = ptr_type.child.toType();
2376 .i64,495 if (child_ty.zigTypeTag(mod) == .Fn) return !mod.typeToFunc(child_ty).?.is_generic;
2377 .u128,496 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
2378 .i128,497 return !comptimeOnly(ty, mod);
2379 .usize,498 },
2380 .isize,499 .anyframe_type => true,
2381 .c_char,500 .array_type => |array_type| {
2382 .c_short,501 if (array_type.sentinel != .none) {
2383 .c_ushort,502 return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
2384 .c_int,503 } else {
2385 .c_uint,504 return array_type.len > 0 and
2386 .c_long,505 try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
2387 .c_ulong,506 }
2388 .c_longlong,507 },
2389 .c_ulonglong,508 .vector_type => |vector_type| {
2390 .c_longdouble,509 return vector_type.len > 0 and
2391 .f16,510 try vector_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
2392 .f32,511 },
2393 .f64,512 .opt_type => |child| {
2394 .f80,513 const child_ty = child.toType();
2395 .f128,514 if (child_ty.isNoReturn(mod)) {
2396 .bool,515 // Then the optional is comptime-known to be null.
2397 .anyerror,516 return false;
2398 .const_slice_u8,517 }
2399 .const_slice_u8_sentinel_0,518 if (ignore_comptime_only) {
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))
2541 return true;519 return true;
2542 } else {520 } else if (strat == .sema) {
2543 return false;521 return !(try strat.sema.typeRequiresComptime(child_ty));
2544 }522 } else {
2545 },523 return !comptimeOnly(child_ty, mod);
2546 .union_safety_tagged, .union_tagged => {524 }
2547 const union_obj = ty.cast(Payload.Union).?.data;525 },
2548 if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) {526 .error_union_type,
2549 return true;527 .error_set_type,
2550 }528 .inferred_error_set_type,
2551529 => true,
2552 switch (strat) {530
2553 .sema => |sema| _ = try sema.resolveTypeFields(ty),531 // These are function *bodies*, not pointers.
2554 .eager => assert(union_obj.haveFieldTypes()),532 // They return false here because they are comptime-only types.
2555 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,533 // Special exceptions have to be made when emitting functions due to
2556 }534 // this returning false.
2557 for (union_obj.fields.values()) |value| {535 .func_type => false,
2558 if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))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;
2559 return true;593 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 }
2561 return false;613 return false;
2562 }614 },
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),
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 => {646 .opaque_type => true,
2573 const tuple = ty.tupleFields();647 .enum_type => |enum_type| enum_type.tag_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
2574 for (tuple.types, 0..) |field_ty, i| {648
2575 const val = tuple.values[i];649 // values, not types
2576 if (val.tag() != .unreachable_value) continue; // comptime field650 .undef,
2577 if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) return true;651 .runtime_value,
2578 }652 .simple_value,
2579 return false;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,
2580 },670 },
2581671 };
2582 .inferred_alloc_const => unreachable,
2583 .inferred_alloc_mut => unreachable,
2584 .generic_poison => unreachable,
2585 }
2586 }672 }
2587673
2588 /// true if and only if the type has a well-defined memory layout674 /// true if and only if the type has a well-defined memory layout
2589 /// readFrom/writeToMemory are supported only for types with a well-675 /// readFrom/writeToMemory are supported only for types with a well-
2590 /// defined memory layout676 /// defined memory layout
2591 pub fn hasWellDefinedLayout(ty: Type) bool {677 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
2592 return switch (ty.tag()) {678 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2593 .u1,679 .int_type,
2594 .u8,680 .vector_type,
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,
2643 => true,681 => true,
2644682
2645 .anyopaque,683 .error_union_type,
2646 .anyerror,684 .error_set_type,
2647 .noreturn,685 .inferred_error_set_type,
2648 .null,686 .anon_struct_type,
2649 .@"anyframe",687 .opaque_type,
2650 .undefined,688 .anyframe_type,
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,
2672 // These are function bodies, not function pointers.689 // These are function bodies, not function pointers.
2673 .fn_noreturn_no_args,690 .func_type,
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,
2690 => false,691 => false,
2691692
2692 .enum_full,693 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
2693 .enum_nonexhaustive,694 .opt_type => ty.isPtrLikeOptional(mod),
2694 => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred,695 .ptr_type => |ptr_type| ptr_type.flags.size != .Slice,
2695
2696 .inferred_alloc_mut => unreachable,
2697 .inferred_alloc_const => unreachable,
2698696
2699 .array,697 .simple_type => |t| switch (t) {
2700 .array_sentinel,698 .f16,
2701 => ty.childType().hasWellDefinedLayout(),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(),719 .anyerror,
2704 .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto,720 .anyopaque,
2705 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,721 .atomic_order,
2706 .union_tagged => false,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,
2707 };779 };
2708 }780 }
2709781
2710 pub fn hasRuntimeBits(ty: Type) bool {782 pub fn hasRuntimeBits(ty: Type, mod: *Module) bool {
2711 return hasRuntimeBitsAdvanced(ty, false, .eager) catch unreachable;783 return hasRuntimeBitsAdvanced(ty, mod, false, .eager) catch unreachable;
2712 }784 }
2713785
2714 pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool {786 pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
2715 return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable;787 return hasRuntimeBitsAdvanced(ty, mod, true, .eager) catch unreachable;
2716 }788 }
2717789
2718 pub fn isFnOrHasRuntimeBits(ty: Type) bool {790 pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool {
2719 switch (ty.zigTypeTag()) {791 switch (ty.zigTypeTag(mod)) {
2720 .Fn => {792 .Fn => {
2721 const fn_info = ty.fnInfo();793 const fn_info = mod.typeToFunc(ty).?;
2722 if (fn_info.is_generic) return false;794 if (fn_info.is_generic) return false;
2723 if (fn_info.is_var_args) return true;795 if (fn_info.is_var_args) return true;
2724 switch (fn_info.cc) {796 switch (fn_info.cc) {
...@@ -2727,131 +799,66 @@ pub const Type = extern union {...@@ -2727,131 +799,66 @@ pub const Type = extern union {
2727 .Inline => return false,799 .Inline => return false,
2728 else => {},800 else => {},
2729 }801 }
2730 if (fn_info.return_type.comptimeOnly()) return false;802 if (fn_info.return_type.toType().comptimeOnly(mod)) return false;
2731 return true;803 return true;
2732 },804 },
2733 else => return ty.hasRuntimeBits(),805 else => return ty.hasRuntimeBits(mod),
2734 }806 }
2735 }807 }
2736808
2737 /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive.809 /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive.
2738 pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type) bool {810 pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
2739 return switch (ty.zigTypeTag()) {811 return switch (ty.zigTypeTag(mod)) {
2740 .Fn => true,812 .Fn => true,
2741 else => return ty.hasRuntimeBitsIgnoreComptime(),813 else => return ty.hasRuntimeBitsIgnoreComptime(mod),
2742 };814 };
2743 }815 }
2744816
2745 /// TODO add enums with no fields here817 pub fn isNoReturn(ty: Type, mod: *Module) bool {
2746 pub fn isNoReturn(ty: Type) bool {818 return mod.intern_pool.isNoReturn(ty.toIntern());
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 }
2761 }819 }
2762820
2763 /// Returns 0 if the pointer is naturally aligned and the element type is 0-bit.821 /// Returns 0 if the pointer is naturally aligned and the element type is 0-bit.
2764 pub fn ptrAlignment(ty: Type, target: Target) u32 {822 pub fn ptrAlignment(ty: Type, mod: *Module) u32 {
2765 return ptrAlignmentAdvanced(ty, target, null) catch unreachable;823 return ptrAlignmentAdvanced(ty, mod, null) catch unreachable;
2766 }824 }
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 },
2788825
2789 .manyptr_u8,826 pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) !u32 {
2790 .manyptr_const_u8,827 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2791 .manyptr_const_u8_sentinel_0,828 .ptr_type => |ptr_type| {
2792 .const_slice_u8,829 if (ptr_type.flags.alignment.toByteUnitsOptional()) |a| {
2793 .const_slice_u8_sentinel_0,830 return @intCast(u32, a);
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";
2800 } else if (opt_sema) |sema| {831 } 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 });
2802 return res.scalar;833 return res.scalar;
2803 } else {834 } 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;
2805 }836 }
2806 },837 },
2807 .optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(target, opt_sema),838 .opt_type => |child| child.toType().ptrAlignmentAdvanced(mod, opt_sema),
2808
2809 else => unreachable,839 else => unreachable,
2810 }840 };
2811 }841 }
2812842
2813 pub fn ptrAddressSpace(self: Type) std.builtin.AddressSpace {843 pub fn ptrAddressSpace(ty: Type, mod: *const Module) std.builtin.AddressSpace {
2814 return switch (self.tag()) {844 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2815 .single_const_pointer_to_comptime_int,845 .ptr_type => |ptr_type| ptr_type.flags.address_space,
2816 .const_slice_u8,846 .opt_type => |child| mod.intern_pool.indexToKey(child).ptr_type.flags.address_space,
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
2841 else => unreachable,847 else => unreachable,
2842 };848 };
2843 }849 }
2844850
2845 /// Returns 0 for 0-bit types.851 /// Returns 0 for 0-bit types.
2846 pub fn abiAlignment(ty: Type, target: Target) u32 {852 pub fn abiAlignment(ty: Type, mod: *Module) u32 {
2847 return (ty.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar;853 return (ty.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
2848 }854 }
2849855
2850 /// May capture a reference to `ty`.856 /// May capture a reference to `ty`.
2851 pub fn lazyAbiAlignment(ty: Type, target: Target, arena: Allocator) !Value {857 /// Returned value has type `comptime_int`.
2852 switch (try ty.abiAlignmentAdvanced(target, .{ .lazy = arena })) {858 pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value {
859 switch (try ty.abiAlignmentAdvanced(mod, .lazy)) {
2853 .val => |val| return val,860 .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),
2855 }862 }
2856 }863 }
2857864
...@@ -2862,7 +869,7 @@ pub const Type = extern union {...@@ -2862,7 +869,7 @@ pub const Type = extern union {
2862869
2863 pub const AbiAlignmentAdvancedStrat = union(enum) {870 pub const AbiAlignmentAdvancedStrat = union(enum) {
2864 eager,871 eager,
2865 lazy: Allocator,872 lazy,
2866 sema: *Sema,873 sema: *Sema,
2867 };874 };
2868875
...@@ -2874,314 +881,322 @@ pub const Type = extern union {...@@ -2874,314 +881,322 @@ pub const Type = extern union {
2874 /// necessary, possibly returning a CompileError.881 /// necessary, possibly returning a CompileError.
2875 pub fn abiAlignmentAdvanced(882 pub fn abiAlignmentAdvanced(
2876 ty: Type,883 ty: Type,
2877 target: Target,884 mod: *Module,
2878 strat: AbiAlignmentAdvancedStrat,885 strat: AbiAlignmentAdvancedStrat,
2879 ) Module.CompileError!AbiAlignmentAdvanced {886 ) Module.CompileError!AbiAlignmentAdvanced {
887 const target = mod.getTarget();
888
2880 const opt_sema = switch (strat) {889 const opt_sema = switch (strat) {
2881 .sema => |sema| sema,890 .sema => |sema| sema,
2882 else => null,891 else => null,
2883 };892 };
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,894 switch (ty.toIntern()) {
2919 .usize,895 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },
2920 .single_const_pointer_to_comptime_int,896 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2921 .const_slice_u8,897 .int_type => |int_type| {
2922 .const_slice_u8_sentinel_0,898 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
2923 .single_const_pointer,899 return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) };
2924 .single_mut_pointer,900 },
2925 .many_const_pointer,901 .ptr_type, .anyframe_type => {
2926 .many_mut_pointer,902 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2927 .c_const_pointer,903 },
2928 .c_mut_pointer,904 .array_type => |array_type| {
2929 .const_slice,905 return array_type.child.toType().abiAlignmentAdvanced(mod, strat);
2930 .mut_slice,906 },
2931 .optional_single_const_pointer,907 .vector_type => |vector_type| {
2932 .optional_single_mut_pointer,908 const bits_u64 = try bitSizeAdvanced(vector_type.child.toType(), mod, opt_sema);
2933 .pointer,909 const bits = @intCast(u32, bits_u64);
2934 .manyptr_u8,910 const bytes = ((bits * vector_type.len) + 7) / 8;
2935 .manyptr_const_u8,911 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
2936 .manyptr_const_u8_sentinel_0,912 return AbiAlignmentAdvanced{ .scalar = alignment };
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) };
2967 },913 },
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 => {915 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
3000 const bits: u16 = ty.cast(Payload.Bits).?.data;916 .error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, info.payload_type.toType()),
3001 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
3002 return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(bits, target) };
3003 },
3004917
3005 .optional => {918 // TODO revisit this when we have the concept of the error tag type
3006 var buf: Payload.ElemType = undefined;919 .error_set_type, .inferred_error_set_type => return AbiAlignmentAdvanced{ .scalar = 2 },
3007 const child_type = ty.optionalChild(&buf);
3008920
3009 switch (child_type.zigTypeTag()) {921 // represents machine code; not a pointer
3010 .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },922 .func_type => |func_type| return AbiAlignmentAdvanced{
3011 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, target, strat),923 .scalar = if (func_type.alignment.toByteUnitsOptional()) |a|
3012 .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },924 @intCast(u32, a)
3013 else => {},925 else
3014 }926 target_util.defaultFunctionAlignment(target),
927 },
3015928
3016 switch (strat) {929 .simple_type => |t| switch (t) {
3017 .eager, .sema => {930 .bool,
3018 if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {931 .atomic_order,
3019 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },932 .atomic_rmw_op,
3020 else => |e| return e,933 .calling_convention,
3021 })) {934 .address_space,
3022 return AbiAlignmentAdvanced{ .scalar = 1 };935 .float_mode,
3023 }936 .reduce_op,
3024 return child_type.abiAlignmentAdvanced(target, strat);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 },
3025 },964 },
3026 .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(target, strat)) {965 .f80 => switch (target.c_type_bit_size(.longdouble)) {
3027 .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) },966 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
3028 .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },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 },
3029 },975 },
3030 }
3031 },
3032976
3033 .error_union => {977 // TODO revisit this when we have the concept of the error tag type
3034 // This code needs to be kept in sync with the equivalent switch prong978 .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },
3035 // in abiSizeAdvanced.979
3036 const data = ty.castTag(.error_union).?.data;980 .void,
3037 const code_align = abiAlignment(Type.anyerror, target);981 .type,
3038 switch (strat) {982 .comptime_int,
3039 .eager, .sema => {983 .comptime_float,
3040 if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {984 .null,
3041 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },985 .undefined,
3042 else => |e| return e,986 .enum_literal,
3043 })) {987 .type_info,
3044 return AbiAlignmentAdvanced{ .scalar = code_align };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) };
3045 }1003 }
3046 return AbiAlignmentAdvanced{ .scalar = @max(1004 _ = try sema.resolveTypeFields(ty);
3047 code_align,1005 }
3048 (try data.payload.abiAlignmentAdvanced(target, strat)).scalar,1006 if (!struct_obj.haveFieldTypes()) switch (strat) {
3049 ) };1007 .eager => unreachable, // struct layout not resolved
3050 },1008 .sema => unreachable, // handled above
3051 .lazy => |arena| {1009 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
3052 switch (try data.payload.abiAlignmentAdvanced(target, strat)) {1010 .ty = .comptime_int_type,
3053 .scalar => |payload_align| {1011 .storage = .{ .lazy_align = ty.toIntern() },
3054 return AbiAlignmentAdvanced{1012 } })).toValue() },
3055 .scalar = @max(code_align, payload_align),1013 };
3056 };1014 if (struct_obj.layout == .Packed) {
3057 },1015 switch (strat) {
3058 .val => {},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 => {},
3059 }1022 }
3060 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };1023 assert(struct_obj.haveLayout());
3061 },1024 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) };
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) };
3073 }1025 }
3074 _ = try sema.resolveTypeFields(ty);1026
3075 }1027 const fields = ty.structFields(mod);
3076 if (!struct_obj.haveFieldTypes()) switch (strat) {1028 var big_align: u32 = 0;
3077 .eager => unreachable, // struct layout not resolved1029 for (fields.values()) |field| {
3078 .sema => unreachable, // handled above1030 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
3079 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },1031 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
3080 };1032 .ty = .comptime_int_type,
3081 if (struct_obj.layout == .Packed) {1033 .storage = .{ .lazy_align = ty.toIntern() },
3082 switch (strat) {1034 } })).toValue() },
3083 .sema => |sema| try sema.resolveTypeLayout(ty),1035 else => |e| return e,
3084 .lazy => |arena| {1036 })) continue;
3085 if (!struct_obj.haveLayout()) {1037
3086 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };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);
3087 }1059 }
3088 },1060 }
3089 .eager => {},
3090 }1061 }
3091 assert(struct_obj.haveLayout());1062 return AbiAlignmentAdvanced{ .scalar = big_align };
3092 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(target) };1063 },
3093 }1064 .anon_struct_type => |tuple| {
30941065 var big_align: u32 = 0;
3095 const fields = ty.structFields();1066 for (tuple.types, tuple.values) |field_ty, val| {
3096 var big_align: u32 = 0;1067 if (val != .none) continue; // comptime field
3097 for (fields.values()) |field| {1068 if (!(field_ty.toType().hasRuntimeBits(mod))) continue;
3098 if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {1069
3099 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },1070 switch (try field_ty.toType().abiAlignmentAdvanced(mod, strat)) {
3100 else => |e| return e,1071 .scalar => |field_align| big_align = @max(big_align, field_align),
3101 })) continue;1072 .val => switch (strat) {
31021073 .eager => unreachable, // field type alignment not resolved
3103 const field_align = if (field.abi_align != 0)1074 .sema => unreachable, // passed to abiAlignmentAdvanced above
3104 field.abi_align1075 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
3105 else switch (try field.ty.abiAlignmentAdvanced(target, strat)) {1076 .ty = .comptime_int_type,
3106 .scalar => |a| a,1077 .storage = .{ .lazy_align = ty.toIntern() },
3107 .val => switch (strat) {1078 } })).toValue() },
3108 .eager => unreachable, // struct layout not resolved1079 },
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);
3121 }1080 }
3122 }1081 }
3123 }1082 return AbiAlignmentAdvanced{ .scalar = big_align };
3124 return AbiAlignmentAdvanced{ .scalar = big_align };1083 },
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;
31341084
3135 switch (try field_ty.abiAlignmentAdvanced(target, strat)) {1085 .union_type => |union_type| {
3136 .scalar => |field_align| big_align = @max(big_align, field_align),1086 const union_obj = mod.unionPtr(union_type.index);
3137 .val => switch (strat) {1087 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
3138 .eager => unreachable, // field type alignment not resolved1088 },
3139 .sema => unreachable, // passed to abiAlignmentAdvanced above1089 .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 },
3140 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },1090 .enum_type => |enum_type| return AbiAlignmentAdvanced{ .scalar = enum_type.tag_ty.toType().abiAlignment(mod) },
3141 },1091
3142 }1092 // values, not types
3143 }1093 .undef,
3144 return AbiAlignmentAdvanced{ .scalar = big_align };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,
3145 },1113 },
1114 }
1115 }
31461116
3147 .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => {1117 fn abiAlignmentAdvancedErrorUnion(
3148 var buffer: Payload.Bits = undefined;1118 ty: Type,
3149 const int_tag_ty = ty.intTagType(&buffer);1119 mod: *Module,
3150 return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(target) };1120 strat: AbiAlignmentAdvancedStrat,
3151 },1121 payload_ty: Type,
3152 .@"union" => {1122 ) Module.CompileError!AbiAlignmentAdvanced {
3153 const union_obj = ty.castTag(.@"union").?.data;1123 // This code needs to be kept in sync with the equivalent switch prong
3154 return abiAlignmentAdvancedUnion(ty, target, strat, union_obj, false);1124 // in abiSizeAdvanced.
3155 },1125 const code_align = abiAlignment(Type.anyerror, mod);
3156 .union_safety_tagged, .union_tagged => {1126 switch (strat) {
3157 const union_obj = ty.cast(Payload.Union).?.data;1127 .eager, .sema => {
3158 return abiAlignmentAdvancedUnion(ty, target, strat, union_obj, true);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() };
3159 },1155 },
1156 }
1157 }
31601158
3161 .empty_struct,1159 fn abiAlignmentAdvancedOptional(
3162 .void,1160 ty: Type,
3163 .empty_struct_literal,1161 mod: *Module,
3164 .type,1162 strat: AbiAlignmentAdvancedStrat,
3165 .comptime_int,1163 ) Module.CompileError!AbiAlignmentAdvanced {
3166 .comptime_float,1164 const target = mod.getTarget();
3167 .null,1165 const child_type = ty.optionalChild(mod);
3168 .undefined,
3169 .enum_literal,
3170 .type_info,
3171 => return AbiAlignmentAdvanced{ .scalar = 0 },
31721166
3173 .noreturn,1167 switch (child_type.zigTypeTag(mod)) {
3174 .inferred_alloc_const,1168 .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
3175 .inferred_alloc_mut,1169 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat),
3176 => unreachable,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 },
3179 }1194 }
3180 }1195 }
31811196
3182 pub fn abiAlignmentAdvancedUnion(1197 pub fn abiAlignmentAdvancedUnion(
3183 ty: Type,1198 ty: Type,
3184 target: Target,1199 mod: *Module,
3185 strat: AbiAlignmentAdvancedStrat,1200 strat: AbiAlignmentAdvancedStrat,
3186 union_obj: *Module.Union,1201 union_obj: *Module.Union,
3187 have_tag: bool,1202 have_tag: bool,
...@@ -3195,6 +1210,7 @@ pub const Type = extern union {...@@ -3195,6 +1210,7 @@ pub const Type = extern union {
3195 // We'll guess "pointer-aligned", if the union has an1210 // We'll guess "pointer-aligned", if the union has an
3196 // underaligned pointer field then some allocations1211 // underaligned pointer field then some allocations
3197 // might require explicit alignment.1212 // might require explicit alignment.
1213 const target = mod.getTarget();
3198 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };1214 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
3199 }1215 }
3200 _ = try sema.resolveTypeFields(ty);1216 _ = try sema.resolveTypeFields(ty);
...@@ -3202,32 +1218,41 @@ pub const Type = extern union {...@@ -3202,32 +1218,41 @@ pub const Type = extern union {
3202 if (!union_obj.haveFieldTypes()) switch (strat) {1218 if (!union_obj.haveFieldTypes()) switch (strat) {
3203 .eager => unreachable, // union layout not resolved1219 .eager => unreachable, // union layout not resolved
3204 .sema => unreachable, // handled above1220 .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() },
3206 };1225 };
3207 if (union_obj.fields.count() == 0) {1226 if (union_obj.fields.count() == 0) {
3208 if (have_tag) {1227 if (have_tag) {
3209 return abiAlignmentAdvanced(union_obj.tag_ty, target, strat);1228 return abiAlignmentAdvanced(union_obj.tag_ty, mod, strat);
3210 } else {1229 } else {
3211 return AbiAlignmentAdvanced{ .scalar = @boolToInt(union_obj.layout == .Extern) };1230 return AbiAlignmentAdvanced{ .scalar = @boolToInt(union_obj.layout == .Extern) };
3212 }1231 }
3213 }1232 }
32141233
3215 var max_align: u32 = 0;1234 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);
3217 for (union_obj.fields.values()) |field| {1236 for (union_obj.fields.values()) |field| {
3218 if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {1237 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
3219 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },1238 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1239 .ty = .comptime_int_type,
1240 .storage = .{ .lazy_align = ty.toIntern() },
1241 } })).toValue() },
3220 else => |e| return e,1242 else => |e| return e,
3221 })) continue;1243 })) continue;
32221244
3223 const field_align = if (field.abi_align != 0)1245 const field_align = if (field.abi_align != 0)
3224 field.abi_align1246 field.abi_align
3225 else switch (try field.ty.abiAlignmentAdvanced(target, strat)) {1247 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {
3226 .scalar => |a| a,1248 .scalar => |a| a,
3227 .val => switch (strat) {1249 .val => switch (strat) {
3228 .eager => unreachable, // struct layout not resolved1250 .eager => unreachable, // struct layout not resolved
3229 .sema => unreachable, // handled above1251 .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() },
3231 },1256 },
3232 };1257 };
3233 max_align = @max(max_align, field_align);1258 max_align = @max(max_align, field_align);
...@@ -3236,17 +1261,17 @@ pub const Type = extern union {...@@ -3236,17 +1261,17 @@ pub const Type = extern union {
3236 }1261 }
32371262
3238 /// May capture a reference to `ty`.1263 /// May capture a reference to `ty`.
3239 pub fn lazyAbiSize(ty: Type, target: Target, arena: Allocator) !Value {1264 pub fn lazyAbiSize(ty: Type, mod: *Module) !Value {
3240 switch (try ty.abiSizeAdvanced(target, .{ .lazy = arena })) {1265 switch (try ty.abiSizeAdvanced(mod, .lazy)) {
3241 .val => |val| return val,1266 .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),
3243 }1268 }
3244 }1269 }
32451270
3246 /// Asserts the type has the ABI size already resolved.1271 /// Asserts the type has the ABI size already resolved.
3247 /// Types that return false for hasRuntimeBits() return 0.1272 /// Types that return false for hasRuntimeBits() return 0.
3248 pub fn abiSize(ty: Type, target: Target) u64 {1273 pub fn abiSize(ty: Type, mod: *Module) u64 {
3249 return (abiSizeAdvanced(ty, target, .eager) catch unreachable).scalar;1274 return (abiSizeAdvanced(ty, mod, .eager) catch unreachable).scalar;
3250 }1275 }
32511276
3252 const AbiSizeAdvanced = union(enum) {1277 const AbiSizeAdvanced = union(enum) {
...@@ -3262,315 +1287,310 @@ pub const Type = extern union {...@@ -3262,315 +1287,310 @@ pub const Type = extern union {
3262 /// necessary, possibly returning a CompileError.1287 /// necessary, possibly returning a CompileError.
3263 pub fn abiSizeAdvanced(1288 pub fn abiSizeAdvanced(
3264 ty: Type,1289 ty: Type,
3265 target: Target,1290 mod: *Module,
3266 strat: AbiAlignmentAdvancedStrat,1291 strat: AbiAlignmentAdvancedStrat,
3267 ) Module.CompileError!AbiSizeAdvanced {1292 ) Module.CompileError!AbiSizeAdvanced {
3268 switch (ty.tag()) {1293 const target = mod.getTarget();
3269 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer1294
3270 .fn_void_no_args => unreachable, // represents machine code; not a pointer1295 switch (ty.toIntern()) {
3271 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer1296 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
3272 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer1297
3273 .function => unreachable, // represents machine code; not a pointer1298 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3274 .@"opaque" => unreachable, // no size available1299 .int_type => |int_type| {
3275 .noreturn => unreachable,1300 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
3276 .inferred_alloc_const => unreachable,1301 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
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) };
3312 },1302 },
3313 else => {1303 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
3314 switch (strat) {1304 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
3315 .sema => |sema| try sema.resolveTypeLayout(ty),1305 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
3316 .lazy => |arena| {1306 },
3317 if (ty.castTag(.@"struct")) |payload| {1307 .anyframe_type => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
3318 const struct_obj = payload.data;1308
3319 if (!struct_obj.haveLayout()) {1309 .array_type => |array_type| {
3320 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };1310 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
3321 }1311 switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) {
3322 }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() },
3323 },1319 },
3324 .eager => {},
3325 }
3326 const field_count = ty.structFieldCount();
3327 if (field_count == 0) {
3328 return AbiSizeAdvanced{ .scalar = 0 };
3329 }1320 }
3330 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, target) };
3331 },1321 },
3332 },1322 .vector_type => |vector_type| {
33331323 const opt_sema = switch (strat) {
3334 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {1324 .sema => |sema| sema,
3335 var buffer: Payload.Bits = undefined;1325 .eager => null,
3336 const int_tag_ty = ty.intTagType(&buffer);1326 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
3337 return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(target) };1327 .ty = .comptime_int_type,
3338 },1328 .storage = .{ .lazy_size = ty.toIntern() },
3339 .@"union" => {1329 } })).toValue() },
3340 const union_obj = ty.castTag(.@"union").?.data;1330 };
3341 return abiSizeAdvancedUnion(ty, target, strat, union_obj, false);1331 const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema);
3342 },1332 const elem_bits = @intCast(u32, elem_bits_u64);
3343 .union_safety_tagged, .union_tagged => {1333 const total_bits = elem_bits * vector_type.len;
3344 const union_obj = ty.cast(Payload.Union).?.data;1334 const total_bytes = (total_bits + 7) / 8;
3345 return abiSizeAdvancedUnion(ty, target, strat, union_obj, true);1335 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
3346 },1336 .scalar => |x| x,
33471337 .val => return .{ .val = (try mod.intern(.{ .int = .{
3348 .u1,1338 .ty = .comptime_int_type,
3349 .u8,1339 .storage = .{ .lazy_size = ty.toIntern() },
3350 .i8,1340 } })).toValue() },
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,
3456 };1341 };
3457 const u80_ty = initPayload(&payload.base);1342 const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment);
3458 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, target) };1343 return AbiSizeAdvanced{ .scalar = result };
3459 },1344 },
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 => {1346 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
3483 var buf: Payload.ElemType = undefined;1347
3484 const child_type = ty.optionalChild(&buf);1348 // TODO revisit this when we have the concept of the error tag type
34851349 .error_set_type, .inferred_error_set_type => return AbiSizeAdvanced{ .scalar = 2 },
3486 if (child_type.isNoReturn()) {1350
3487 return AbiSizeAdvanced{ .scalar = 0 };1351 .error_union_type => |error_union_type| {
3488 }1352 const payload_ty = error_union_type.payload_type.toType();
34891353 // This code needs to be kept in sync with the equivalent switch prong
3490 if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {1354 // in abiAlignmentAdvanced.
3491 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },1355 const code_size = abiSize(Type.anyerror, mod);
3492 else => |e| return e,1356 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
3493 })) return AbiSizeAdvanced{ .scalar = 1 };1357 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
34941358 .ty = .comptime_int_type,
3495 if (ty.optionalReprIsPayload()) {1359 .storage = .{ .lazy_size = ty.toIntern() },
3496 return abiSizeAdvanced(child_type, target, strat);1360 } })).toValue() },
3497 }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)) {1380 var size: u64 = 0;
3500 .scalar => |elem_size| elem_size,1381 if (code_align > payload_align) {
3501 .val => switch (strat) {1382 size += code_size;
3502 .sema => unreachable,1383 size = std.mem.alignForwardGeneric(u64, size, payload_align);
3503 .eager => unreachable,1384 size += payload_size;
3504 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },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 },
3505 },1416 },
3506 };
35071417
3508 // Optional types are represented as a struct with the child type as the first1418 .usize,
3509 // field and a boolean as the second. Since the child type's abi alignment is1419 .isize,
3510 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal1420 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
3511 // to the child type's ABI alignment.1421
3512 return AbiSizeAdvanced{1422 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
3513 .scalar = child_type.abiAlignment(target) + payload_size,1423 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
3514 };1424 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
3515 },1425 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
35161426 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
3517 .error_union => {1427 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
3518 // This code needs to be kept in sync with the equivalent switch prong1428 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
3519 // in abiAlignmentAdvanced.1429 .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
3520 const data = ty.castTag(.error_union).?.data;1430 .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
3521 const code_size = abiSize(Type.anyerror, target);1431 .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
3522 if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {1432
3523 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },1433 .anyopaque,
3524 else => |e| return e,1434 .void,
3525 })) {1435 .type,
3526 // Same as anyerror.1436 .comptime_int,
3527 return AbiSizeAdvanced{ .scalar = code_size };1437 .comptime_float,
3528 }1438 .null,
3529 const code_align = abiAlignment(Type.anyerror, target);1439 .undefined,
3530 const payload_align = abiAlignment(data.payload, target);1440 .enum_literal,
3531 const payload_size = switch (try data.payload.abiSizeAdvanced(target, strat)) {1441 => return AbiSizeAdvanced{ .scalar = 0 },
3532 .scalar => |elem_size| elem_size,1442
3533 .val => switch (strat) {1443 // TODO revisit this when we have the concept of the error tag type
3534 .sema => unreachable,1444 .anyerror => return AbiSizeAdvanced{ .scalar = 2 },
3535 .eager => unreachable,1445
3536 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },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) };
3537 },1469 },
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;1502 .union_type => |union_type| {
3541 if (code_align > payload_align) {1503 const union_obj = mod.unionPtr(union_type.index);
3542 size += code_size;1504 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
3543 size = std.mem.alignForwardGeneric(u64, size, payload_align);1505 },
3544 size += payload_size;1506 .opaque_type => unreachable, // no size available
3545 size = std.mem.alignForwardGeneric(u64, size, code_align);1507 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },
3546 } else {1508
3547 size += payload_size;1509 // values, not types
3548 size = std.mem.alignForwardGeneric(u64, size, code_align);1510 .undef,
3549 size += code_size;1511 .runtime_value,
3550 size = std.mem.alignForwardGeneric(u64, size, payload_align);1512 .simple_value,
3551 }1513 .variable,
3552 return AbiSizeAdvanced{ .scalar = size };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,
3553 },1530 },
3554 }1531 }
3555 }1532 }
35561533
3557 pub fn abiSizeAdvancedUnion(1534 pub fn abiSizeAdvancedUnion(
3558 ty: Type,1535 ty: Type,
3559 target: Target,1536 mod: *Module,
3560 strat: AbiAlignmentAdvancedStrat,1537 strat: AbiAlignmentAdvancedStrat,
3561 union_obj: *Module.Union,1538 union_obj: *Module.Union,
3562 have_tag: bool,1539 have_tag: bool,
3563 ) Module.CompileError!AbiSizeAdvanced {1540 ) Module.CompileError!AbiSizeAdvanced {
3564 switch (strat) {1541 switch (strat) {
3565 .sema => |sema| try sema.resolveTypeLayout(ty),1542 .sema => |sema| try sema.resolveTypeLayout(ty),
3566 .lazy => |arena| {1543 .lazy => if (!union_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
3567 if (!union_obj.haveLayout()) {1544 .ty = .comptime_int_type,
3568 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };1545 .storage = .{ .lazy_size = ty.toIntern() },
3569 }1546 } })).toValue() },
3570 },
3571 .eager => {},1547 .eager => {},
3572 }1548 }
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 };
3574 }1594 }
35751595
3576 fn intAbiSize(bits: u16, target: Target) u64 {1596 fn intAbiSize(bits: u16, target: Target) u64 {
...@@ -3585,8 +1605,8 @@ pub const Type = extern union {...@@ -3585,8 +1605,8 @@ pub const Type = extern union {
3585 );1605 );
3586 }1606 }
35871607
3588 pub fn bitSize(ty: Type, target: Target) u64 {1608 pub fn bitSize(ty: Type, mod: *Module) u64 {
3589 return bitSizeAdvanced(ty, target, null) catch unreachable;1609 return bitSizeAdvanced(ty, mod, null) catch unreachable;
3590 }1610 }
35911611
3592 /// If you pass `opt_sema`, any recursive type resolutions will happen if1612 /// If you pass `opt_sema`, any recursive type resolutions will happen if
...@@ -3594,568 +1614,318 @@ pub const Type = extern union {...@@ -3594,568 +1614,318 @@ pub const Type = extern union {
3594 /// the type is fully resolved, and there will be no error, guaranteed.1614 /// the type is fully resolved, and there will be no error, guaranteed.
3595 pub fn bitSizeAdvanced(1615 pub fn bitSizeAdvanced(
3596 ty: Type,1616 ty: Type,
3597 target: Target,1617 mod: *Module,
3598 opt_sema: ?*Sema,1618 opt_sema: ?*Sema,
3599 ) Module.CompileError!u64 {1619 ) Module.CompileError!u64 {
1620 const target = mod.getTarget();
1621
3600 const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;1622 const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
3601 switch (ty.tag()) {1623
3602 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer1624 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3603 .fn_void_no_args => unreachable, // represents machine code; not a pointer1625 .int_type => |int_type| return int_type.bits,
3604 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer1626 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
3605 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer1627 .Slice => return target.ptrBitWidth() * 2,
3606 .function => unreachable, // represents machine code; not a pointer1628 else => return target.ptrBitWidth(),
3607 .anyopaque => unreachable,1629 },
3608 .type => unreachable,1630 .anyframe_type => return target.ptrBitWidth(),
3609 .comptime_int => unreachable,1631
3610 .comptime_float => unreachable,1632 .array_type => |array_type| {
3611 .noreturn => unreachable,1633 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
3612 .null => unreachable,1634 if (len == 0) return 0;
3613 .undefined => unreachable,1635 const elem_ty = array_type.child.toType();
3614 .enum_literal => unreachable,1636 const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod));
3615 .single_const_pointer_to_comptime_int => unreachable,1637 if (elem_size == 0) return 0;
3616 .empty_struct => unreachable,1638 const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema);
3617 .empty_struct_literal => unreachable,1639 return (len - 1) * 8 * elem_size + elem_bit_size;
3618 .inferred_alloc_const => unreachable,1640 },
3619 .inferred_alloc_mut => unreachable,1641 .vector_type => |vector_type| {
3620 .@"opaque" => unreachable,1642 const child_ty = vector_type.child.toType();
3621 .generic_poison => unreachable,1643 const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema);
36221644 return elem_bit_size * vector_type.len;
3623 .void => return 0,1645 },
3624 .bool, .u1 => return 1,1646 .opt_type => {
3625 .u8, .i8 => return 8,1647 // Optionals and error unions are not packed so their bitsize
3626 .i16, .u16, .f16 => return 16,1648 // includes padding bits.
3627 .u29 => return 29,1649 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
3628 .i32, .u32, .f32 => return 32,1650 },
3629 .i64, .u64, .f64 => return 64,1651
3630 .f80 => return 80,1652 // TODO revisit this when we have the concept of the error tag type
3631 .u128, .i128, .f128 => return 128,1653 .error_set_type, .inferred_error_set_type => return 16,
36321654
3633 .@"struct" => {1655 .error_union_type => {
3634 const struct_obj = ty.castTag(.@"struct").?.data;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;
3635 if (struct_obj.layout != .Packed) {1713 if (struct_obj.layout != .Packed) {
3636 return (try ty.abiSizeAdvanced(target, strat)).scalar * 8;1714 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
3637 }1715 }
3638 if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty);1716 if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty);
3639 assert(struct_obj.haveLayout());1717 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);
3641 },1719 },
36421720
3643 .tuple, .anon_struct => {1721 .anon_struct_type => {
3644 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);1722 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
3645 if (ty.containerLayout() != .Packed) {1723 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
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);
3659 },1724 },
36601725
3661 .@"union", .union_safety_tagged, .union_tagged => {1726 .union_type => |union_type| {
3662 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);1727 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
3663 if (ty.containerLayout() != .Packed) {1728 if (ty.containerLayout(mod) != .Packed) {
3664 return (try ty.abiSizeAdvanced(target, strat)).scalar * 8;1729 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
3665 }1730 }
3666 const union_obj = ty.cast(Payload.Union).?.data;1731 const union_obj = mod.unionPtr(union_type.index);
3667 assert(union_obj.haveFieldTypes());1732 assert(union_obj.haveFieldTypes());
36681733
3669 var size: u64 = 0;1734 var size: u64 = 0;
3670 for (union_obj.fields.values()) |field| {1735 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));
3672 }1737 }
3673 return size;1738 return size;
3674 },1739 },
36751740 .opaque_type => unreachable,
3676 .vector => {1741 .enum_type => |enum_type| return bitSizeAdvanced(enum_type.tag_ty.toType(), mod, opt_sema),
3677 const payload = ty.castTag(.vector).?.data;1742
3678 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema);1743 // values, not types
3679 return elem_bit_size * payload.len;1744 .undef,
3680 },1745 .runtime_value,
3681 .array_u8 => return 8 * ty.castTag(.array_u8).?.data,1746 .simple_value,
3682 .array_u8_sentinel_0 => return 8 * (ty.castTag(.array_u8_sentinel_0).?.data + 1),1747 .variable,
3683 .array => {1748 .extern_func,
3684 const payload = ty.castTag(.array).?.data;1749 .func,
3685 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));1750 .int,
3686 if (elem_size == 0 or payload.len == 0)1751 .err,
3687 return @as(u64, 0);1752 .error_union,
3688 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema);1753 .enum_literal,
3689 return (payload.len - 1) * 8 * elem_size + elem_bit_size;1754 .enum_tag,
3690 },1755 .empty_enum_value,
3691 .array_sentinel => {1756 .float,
3692 const payload = ty.castTag(.array_sentinel).?.data;1757 .ptr,
3693 const elem_size = std.math.max(1758 .opt,
3694 payload.elem_type.abiAlignment(target),1759 .aggregate,
3695 payload.elem_type.abiSize(target),1760 .un,
3696 );1761 // memoization, not types
3697 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema);1762 .memoized_call,
3698 return payload.len * 8 * elem_size + elem_bit_size;1763 => unreachable,
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"),
3780 }1764 }
3781 }1765 }
37821766
3783 /// Returns true if the type's layout is already resolved and it is safe1767 /// Returns true if the type's layout is already resolved and it is safe
3784 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.1768 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.
3785 pub fn layoutIsResolved(ty: Type) bool {1769 pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
3786 switch (ty.zigTypeTag()) {1770 switch (ty.zigTypeTag(mod)) {
3787 .Struct => {1771 .Struct => {
3788 if (ty.castTag(.@"struct")) |struct_ty| {1772 if (mod.typeToStruct(ty)) |struct_obj| {
3789 return struct_ty.data.haveLayout();1773 return struct_obj.haveLayout();
3790 }1774 }
3791 return true;1775 return true;
3792 },1776 },
3793 .Union => {1777 .Union => {
3794 if (ty.cast(Payload.Union)) |union_ty| {1778 if (mod.typeToUnion(ty)) |union_obj| {
3795 return union_ty.data.haveLayout();1779 return union_obj.haveLayout();
3796 }1780 }
3797 return true;1781 return true;
3798 },1782 },
3799 .Array => {1783 .Array => {
3800 if (ty.arrayLenIncludingSentinel() == 0) return true;1784 if (ty.arrayLenIncludingSentinel(mod) == 0) return true;
3801 return ty.childType().layoutIsResolved();1785 return ty.childType(mod).layoutIsResolved(mod);
3802 },1786 },
3803 .Optional => {1787 .Optional => {
3804 var buf: Type.Payload.ElemType = undefined;1788 const payload_ty = ty.optionalChild(mod);
3805 const payload_ty = ty.optionalChild(&buf);1789 return payload_ty.layoutIsResolved(mod);
3806 return payload_ty.layoutIsResolved();
3807 },1790 },
3808 .ErrorUnion => {1791 .ErrorUnion => {
3809 const payload_ty = ty.errorUnionPayload();1792 const payload_ty = ty.errorUnionPayload(mod);
3810 return payload_ty.layoutIsResolved();1793 return payload_ty.layoutIsResolved(mod);
3811 },1794 },
3812 else => return true,1795 else => return true,
3813 }1796 }
3814 }1797 }
38151798
3816 pub fn isSinglePointer(self: Type) bool {1799 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
3817 return switch (self.tag()) {1800 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3818 .single_const_pointer,1801 .ptr_type => |ptr_info| ptr_info.flags.size == .One,
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
3827 else => false,1802 else => false,
3828 };1803 };
3829 }1804 }
38301805
3831 /// Asserts `ty` is a pointer.1806 /// Asserts `ty` is a pointer.
3832 pub fn ptrSize(ty: Type) std.builtin.Type.Pointer.Size {1807 pub fn ptrSize(ty: Type, mod: *const Module) std.builtin.Type.Pointer.Size {
3833 return ptrSizeOrNull(ty).?;1808 return ptrSizeOrNull(ty, mod).?;
3834 }1809 }
38351810
3836 /// Returns `null` if `ty` is not a pointer.1811 /// Returns `null` if `ty` is not a pointer.
3837 pub fn ptrSizeOrNull(ty: Type) ?std.builtin.Type.Pointer.Size {1812 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
3838 return switch (ty.tag()) {1813 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3839 .const_slice,1814 .ptr_type => |ptr_info| ptr_info.flags.size,
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
3865 else => null,1815 else => null,
3866 };1816 };
3867 }1817 }
38681818
3869 pub fn isSlice(self: Type) bool {1819 pub fn isSlice(ty: Type, mod: *const Module) bool {
3870 return switch (self.tag()) {1820 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3871 .const_slice,1821 .ptr_type => |ptr_type| ptr_type.flags.size == .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
3879 else => false,1822 else => false,
3880 };1823 };
3881 }1824 }
38821825
3883 pub const SlicePtrFieldTypeBuffer = union {1826 pub fn slicePtrFieldType(ty: Type, mod: *const Module) Type {
3884 elem_type: Payload.ElemType,1827 return mod.intern_pool.slicePtrType(ty.toIntern()).toType();
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 }
3966 }1828 }
39671829
3968 pub fn isConstPtr(self: Type) bool {1830 pub fn isConstPtr(ty: Type, mod: *const Module) bool {
3969 return switch (self.tag()) {1831 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3970 .single_const_pointer,1832 .ptr_type => |ptr_type| ptr_type.flags.is_const,
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
3983 else => false,1833 else => false,
3984 };1834 };
3985 }1835 }
39861836
3987 pub fn isVolatilePtr(self: Type) bool {1837 pub fn isVolatilePtr(ty: Type, mod: *const Module) bool {
3988 return switch (self.tag()) {1838 return isVolatilePtrIp(ty, &mod.intern_pool);
3989 .pointer => {1839 }
3990 const payload = self.castTag(.pointer).?.data;1840
3991 return payload.@"volatile";1841 pub fn isVolatilePtrIp(ty: Type, ip: *const InternPool) bool {
3992 },1842 return switch (ip.indexToKey(ty.toIntern())) {
1843 .ptr_type => |ptr_type| ptr_type.flags.is_volatile,
3993 else => false,1844 else => false,
3994 };1845 };
3995 }1846 }
39961847
3997 pub fn isAllowzeroPtr(self: Type) bool {1848 pub fn isAllowzeroPtr(ty: Type, mod: *const Module) bool {
3998 return switch (self.tag()) {1849 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3999 .pointer => {1850 .ptr_type => |ptr_type| ptr_type.flags.is_allowzero,
4000 const payload = self.castTag(.pointer).?.data;1851 .opt_type => true,
4001 return payload.@"allowzero";1852 else => false,
4002 },
4003 else => return self.zigTypeTag() == .Optional,
4004 };1853 };
4005 }1854 }
40061855
4007 pub fn isCPtr(self: Type) bool {1856 pub fn isCPtr(ty: Type, mod: *const Module) bool {
4008 return switch (self.tag()) {1857 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4009 .c_const_pointer,1858 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
4010 .c_mut_pointer,1859 else => false,
4011 => return true,
4012
4013 .pointer => self.castTag(.pointer).?.data.size == .C,
4014
4015 else => return false,
4016 };1860 };
4017 }1861 }
40181862
4019 pub fn isPtrAtRuntime(self: Type) bool {1863 pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool {
4020 switch (self.tag()) {1864 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4021 .c_const_pointer,1865 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
4022 .c_mut_pointer,1866 .Slice => false,
4023 .many_const_pointer,1867 .One, .Many, .C => true,
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,
4038 },1868 },
40391869 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
4040 .optional => {1870 .ptr_type => |p| switch (p.flags.size) {
4041 var buf: Payload.ElemType = undefined;1871 .Slice, .C => false,
4042 const child_type = self.optionalChild(&buf);1872 .Many, .One => !p.flags.is_allowzero,
4043 if (child_type.zigTypeTag() != .Pointer) return false;1873 },
4044 const info = child_type.ptrInfo().data;1874 else => false,
4045 switch (info.size) {
4046 .Slice, .C => return false,
4047 .Many, .One => return !info.@"allowzero",
4048 }
4049 },1875 },
40501876 else => false,
4051 else => return false,1877 };
4052 }
4053 }1878 }
40541879
4055 /// For pointer-like optionals, returns true, otherwise returns the allowzero property1880 /// For pointer-like optionals, returns true, otherwise returns the allowzero property
4056 /// of pointers.1881 /// of pointers.
4057 pub fn ptrAllowsZero(ty: Type) bool {1882 pub fn ptrAllowsZero(ty: Type, mod: *const Module) bool {
4058 if (ty.isPtrLikeOptional()) {1883 if (ty.isPtrLikeOptional(mod)) {
4059 return true;1884 return true;
4060 }1885 }
4061 return ty.ptrInfo().data.@"allowzero";1886 return ty.ptrInfo(mod).@"allowzero";
4062 }1887 }
40631888
4064 /// See also `isPtrLikeOptional`.1889 /// See also `isPtrLikeOptional`.
4065 pub fn optionalReprIsPayload(ty: Type) bool {1890 pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {
4066 switch (ty.tag()) {1891 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4067 .optional_single_const_pointer,1892 .opt_type => |child_type| child_type == .anyerror_type or switch (mod.intern_pool.indexToKey(child_type)) {
4068 .optional_single_mut_pointer,1893 .ptr_type => |ptr_type| ptr_type.flags.size != .C and !ptr_type.flags.is_allowzero,
4069 .c_const_pointer,1894 .error_set_type => true,
4070 .c_mut_pointer,1895 else => false,
4071 => return true,1896 },
40721897 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
4073 .optional => {1898 else => false,
4074 const child_ty = ty.castTag(.optional).?.data;1899 };
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 }
4092 }1900 }
40931901
4094 /// Returns true if the type is optional and would be lowered to a single pointer1902 /// Returns true if the type is optional and would be lowered to a single pointer
4095 /// address value, using 0 for null. Note that this returns true for C pointers.1903 /// address value, using 0 for null. Note that this returns true for C pointers.
4096 pub fn isPtrLikeOptional(self: Type) bool {1904 /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
4097 switch (self.tag()) {1905 pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
4098 .optional_single_const_pointer,1906 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4099 .optional_single_mut_pointer,1907 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
4100 .c_const_pointer,1908 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
4101 .c_mut_pointer,1909 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
4102 => return true,1910 .Slice, .C => false,
41031911 .Many, .One => !ptr_type.flags.is_allowzero,
4104 .optional => {1912 },
4105 const child_ty = self.castTag(.optional).?.data;1913 else => false,
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 }
4112 },1914 },
41131915 else => false,
4114 .pointer => return self.castTag(.pointer).?.data.size == .C,1916 };
4115
4116 else => return false,
4117 }
4118 }1917 }
41191918
4120 /// For *[N]T, returns [N]T.1919 /// For *[N]T, returns [N]T.
4121 /// For *T, returns T.1920 /// For *T, returns T.
4122 /// For [*]T, returns T.1921 /// For [*]T, returns T.
4123 pub fn childType(ty: Type) Type {1922 pub fn childType(ty: Type, mod: *const Module) Type {
4124 return switch (ty.tag()) {1923 return childTypeIp(ty, &mod.intern_pool);
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 };
4154 }1924 }
41551925
4156 /// Asserts the type is a pointer or array type.1926 pub fn childTypeIp(ty: Type, ip: *const InternPool) Type {
4157 /// TODO this is deprecated in favor of `childType`.1927 return ip.childType(ty.toIntern()).toType();
4158 pub const elemType = childType;1928 }
41591929
4160 /// For *[N]T, returns T.1930 /// For *[N]T, returns T.
4161 /// For ?*T, returns T.1931 /// For ?*T, returns T.
...@@ -4166,283 +1936,178 @@ pub const Type = extern union {...@@ -4166,283 +1936,178 @@ pub const Type = extern union {
4166 /// For [N]T, returns T.1936 /// For [N]T, returns T.
4167 /// For []T, returns T.1937 /// For []T, returns T.
4168 /// For anyframe->T, returns T.1938 /// For anyframe->T, returns T.
4169 pub fn elemType2(ty: Type) Type {1939 pub fn elemType2(ty: Type, mod: *const Module) Type {
4170 return switch (ty.tag()) {1940 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4171 .vector => ty.castTag(.vector).?.data.elem_type,1941 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
4172 .array => ty.castTag(.array).?.data.elem_type,1942 .One => ptr_type.child.toType().shallowElemType(mod),
4173 .array_sentinel => ty.castTag(.array_sentinel).?.data.elem_type,1943 .Many, .C, .Slice => ptr_type.child.toType(),
4174 .many_const_pointer,1944 },
4175 .many_mut_pointer,1945 .anyframe_type => |child| {
4176 .c_const_pointer,1946 assert(child != .none);
4177 .c_mut_pointer,1947 return child.toType();
4178 .const_slice,1948 },
4179 .mut_slice,1949 .vector_type => |vector_type| vector_type.child.toType(),
4180 => ty.castPointer().?.data,1950 .array_type => |array_type| array_type.child.toType(),
41811951 .opt_type => |child| mod.intern_pool.childType(child).toType(),
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
4212 else => unreachable,1952 else => unreachable,
4213 };1953 };
4214 }1954 }
42151955
4216 fn shallowElemType(child_ty: Type) Type {1956 fn shallowElemType(child_ty: Type, mod: *const Module) Type {
4217 return switch (child_ty.zigTypeTag()) {1957 return switch (child_ty.zigTypeTag(mod)) {
4218 .Array, .Vector => child_ty.childType(),1958 .Array, .Vector => child_ty.childType(mod),
4219 else => child_ty,1959 else => child_ty,
4220 };1960 };
4221 }1961 }
42221962
4223 /// For vectors, returns the element type. Otherwise returns self.1963 /// For vectors, returns the element type. Otherwise returns self.
4224 pub fn scalarType(ty: Type) Type {1964 pub fn scalarType(ty: Type, mod: *Module) Type {
4225 return switch (ty.zigTypeTag()) {1965 return switch (ty.zigTypeTag(mod)) {
4226 .Vector => ty.childType(),1966 .Vector => ty.childType(mod),
4227 else => ty,1967 else => ty,
4228 };1968 };
4229 }1969 }
42301970
4231 /// Asserts that the type is an optional.1971 /// Asserts that the type is an optional.
4232 /// Resulting `Type` will have inner memory referencing `buf`.
4233 /// Note that for C pointers this returns the type unmodified.1972 /// Note that for C pointers this returns the type unmodified.
4234 pub fn optionalChild(ty: Type, buf: *Payload.ElemType) Type {1973 pub fn optionalChild(ty: Type, mod: *const Module) Type {
4235 return switch (ty.tag()) {1974 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4236 .optional => ty.castTag(.optional).?.data,1975 .opt_type => |child| child.toType(),
4237 .optional_single_mut_pointer => {1976 .ptr_type => |ptr_type| b: {
4238 buf.* = .{1977 assert(ptr_type.flags.size == .C);
4239 .base = .{ .tag = .single_mut_pointer },1978 break :b ty;
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);
4250 },1979 },
4251
4252 .pointer, // here we assume it is a C pointer
4253 .c_const_pointer,
4254 .c_mut_pointer,
4255 => return ty,
4256
4257 else => unreachable,1980 else => unreachable,
4258 };1981 };
4259 }1982 }
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
4281 /// Returns the tag type of a union, if the type is a union and it has a tag type.1984 /// Returns the tag type of a union, if the type is a union and it has a tag type.
4282 /// Otherwise, returns `null`.1985 /// Otherwise, returns `null`.
4283 pub fn unionTagType(ty: Type) ?Type {1986 pub fn unionTagType(ty: Type, mod: *Module) ?Type {
4284 return switch (ty.tag()) {1987 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4285 .union_tagged => {1988 .union_type => |union_type| switch (union_type.runtime_tag) {
4286 const union_obj = ty.castTag(.union_tagged).?.data;1989 .tagged => {
4287 assert(union_obj.haveFieldTypes());1990 const union_obj = mod.unionPtr(union_type.index);
4288 return union_obj.tag_ty;1991 assert(union_obj.haveFieldTypes());
1992 return union_obj.tag_ty;
1993 },
1994 else => null,
4289 },1995 },
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
4304 else => null,1996 else => null,
4305 };1997 };
4306 }1998 }
43071999
4308 /// Same as `unionTagType` but includes safety tag.2000 /// Same as `unionTagType` but includes safety tag.
4309 /// Codegen should use this version.2001 /// Codegen should use this version.
4310 pub fn unionTagTypeSafety(ty: Type) ?Type {2002 pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {
4311 return switch (ty.tag()) {2003 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4312 .union_safety_tagged, .union_tagged => {2004 .union_type => |union_type| {
4313 const union_obj = ty.cast(Payload.Union).?.data;2005 if (!union_type.hasTag()) return null;
2006 const union_obj = mod.unionPtr(union_type.index);
4314 assert(union_obj.haveFieldTypes());2007 assert(union_obj.haveFieldTypes());
4315 return union_obj.tag_ty;2008 return union_obj.tag_ty;
4316 },2009 },
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
4331 else => null,2010 else => null,
4332 };2011 };
4333 }2012 }
43342013
4335 /// Asserts the type is a union; returns the tag type, even if the tag will2014 /// Asserts the type is a union; returns the tag type, even if the tag will
4336 /// not be stored at runtime.2015 /// not be stored at runtime.
4337 pub fn unionTagTypeHypothetical(ty: Type) Type {2016 pub fn unionTagTypeHypothetical(ty: Type, mod: *Module) Type {
4338 const union_obj = ty.cast(Payload.Union).?.data;2017 const union_obj = mod.typeToUnion(ty).?;
4339 assert(union_obj.haveFieldTypes());2018 assert(union_obj.haveFieldTypes());
4340 return union_obj.tag_ty;2019 return union_obj.tag_ty;
4341 }2020 }
43422021
4343 pub fn unionFields(ty: Type) Module.Union.Fields {2022 pub fn unionFields(ty: Type, mod: *Module) Module.Union.Fields {
4344 const union_obj = ty.cast(Payload.Union).?.data;2023 const union_obj = mod.typeToUnion(ty).?;
4345 assert(union_obj.haveFieldTypes());2024 assert(union_obj.haveFieldTypes());
4346 return union_obj.fields;2025 return union_obj.fields;
4347 }2026 }
43482027
4349 pub fn unionFieldType(ty: Type, enum_tag: Value, mod: *Module) Type {2028 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).?;
4351 const index = ty.unionTagFieldIndex(enum_tag, mod).?;2030 const index = ty.unionTagFieldIndex(enum_tag, mod).?;
4352 assert(union_obj.haveFieldTypes());2031 assert(union_obj.haveFieldTypes());
4353 return union_obj.fields.values()[index].ty;2032 return union_obj.fields.values()[index].ty;
4354 }2033 }
43552034
4356 pub fn unionTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?usize {2035 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).?;
4358 const index = union_obj.tag_ty.enumTagFieldIndex(enum_tag, mod) orelse return null;2037 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);
4360 return union_obj.fields.getIndex(name);2039 return union_obj.fields.getIndex(name);
4361 }2040 }
43622041
4363 pub fn unionHasAllZeroBitFieldTypes(ty: Type) bool {2042 pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *Module) bool {
4364 return ty.cast(Payload.Union).?.data.hasAllZeroBitFieldTypes();2043 const union_obj = mod.typeToUnion(ty).?;
2044 return union_obj.hasAllZeroBitFieldTypes(mod);
4365 }2045 }
43662046
4367 pub fn unionGetLayout(ty: Type, target: Target) Module.Union.Layout {2047 pub fn unionGetLayout(ty: Type, mod: *Module) Module.Union.Layout {
4368 switch (ty.tag()) {2048 const union_type = mod.intern_pool.indexToKey(ty.toIntern()).union_type;
4369 .@"union" => {2049 const union_obj = mod.unionPtr(union_type.index);
4370 const union_obj = ty.castTag(.@"union").?.data;2050 return union_obj.getLayout(mod, union_type.hasTag());
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 }
4379 }2051 }
43802052
4381 pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout {2053 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
4382 return switch (ty.tag()) {2054 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4383 .tuple, .empty_struct_literal, .anon_struct => .Auto,2055 .struct_type => |struct_type| {
4384 .@"struct" => ty.castTag(.@"struct").?.data.layout,2056 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto;
4385 .@"union" => ty.castTag(.@"union").?.data.layout,2057 return struct_obj.layout;
4386 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,2058 },
4387 .union_tagged => ty.castTag(.union_tagged).?.data.layout,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 },
4388 else => unreachable,2064 else => unreachable,
4389 };2065 };
4390 }2066 }
43912067
4392 /// Asserts that the type is an error union.2068 /// Asserts that the type is an error union.
4393 pub fn errorUnionPayload(self: Type) Type {2069 pub fn errorUnionPayload(ty: Type, mod: *Module) Type {
4394 return switch (self.tag()) {2070 return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.payload_type.toType();
4395 .anyerror_void_error_union => Type.initTag(.void),
4396 .error_union => self.castTag(.error_union).?.data.payload,
4397 else => unreachable,
4398 };
4399 }2071 }
44002072
4401 pub fn errorUnionSet(self: Type) Type {2073 /// Asserts that the type is an error union.
4402 return switch (self.tag()) {2074 pub fn errorUnionSet(ty: Type, mod: *Module) Type {
4403 .anyerror_void_error_union => Type.initTag(.anyerror),2075 return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.error_set_type.toType();
4404 .error_union => self.castTag(.error_union).?.data.error_set,
4405 else => unreachable,
4406 };
4407 }2076 }
44082077
4409 /// Returns false for unresolved inferred error sets.2078 /// Returns false for unresolved inferred error sets.
4410 pub fn errorSetIsEmpty(ty: Type) bool {2079 pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {
4411 switch (ty.tag()) {2080 return switch (ty.toIntern()) {
4412 .anyerror => return false,2081 .anyerror_type => false,
4413 .error_set_inferred => {2082 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4414 const inferred_error_set = ty.castTag(.error_set_inferred).?.data;2083 .error_set_type => |error_set_type| error_set_type.names.len == 0,
4415 // Can't know for sure.2084 .inferred_error_set_type => |index| {
4416 if (!inferred_error_set.is_resolved) return false;2085 const inferred_error_set = mod.inferredErrorSetPtr(index);
4417 if (inferred_error_set.is_anyerror) return false;2086 // Can't know for sure.
4418 return inferred_error_set.errors.count() == 0;2087 if (!inferred_error_set.is_resolved) return false;
4419 },2088 if (inferred_error_set.is_anyerror) return false;
4420 .error_set_single => return false,2089 return inferred_error_set.errors.count() == 0;
4421 .error_set => {2090 },
4422 const err_set_obj = ty.castTag(.error_set).?.data;2091 else => unreachable,
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;
4428 },2092 },
4429 else => unreachable,2093 };
4430 }
4431 }2094 }
44322095
4433 /// Returns true if it is an error set that includes anyerror, false otherwise.2096 /// Returns true if it is an error set that includes anyerror, false otherwise.
4434 /// Note that the result may be a false negative if the type did not get error set2097 /// Note that the result may be a false negative if the type did not get error set
4435 /// resolution prior to this call.2098 /// resolution prior to this call.
4436 pub fn isAnyError(ty: Type) bool {2099 pub fn isAnyError(ty: Type, mod: *Module) bool {
4437 return switch (ty.tag()) {2100 return switch (ty.toIntern()) {
4438 .anyerror => true,2101 .anyerror_type => true,
4439 .error_set_inferred => ty.castTag(.error_set_inferred).?.data.is_anyerror,2102 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4440 else => false,2103 .inferred_error_set_type => |i| mod.inferredErrorSetPtr(i).is_anyerror,
2104 else => false,
2105 },
4441 };2106 };
4442 }2107 }
44432108
4444 pub fn isError(ty: Type) bool {2109 pub fn isError(ty: Type, mod: *const Module) bool {
4445 return switch (ty.zigTypeTag()) {2110 return switch (ty.zigTypeTag(mod)) {
4446 .ErrorUnion, .ErrorSet => true,2111 .ErrorUnion, .ErrorSet => true,
4447 else => false,2112 else => false,
4448 };2113 };
...@@ -4451,230 +2116,221 @@ pub const Type = extern union {...@@ -4451,230 +2116,221 @@ pub const Type = extern union {
4451 /// Returns whether ty, which must be an error set, includes an error `name`.2116 /// Returns whether ty, which must be an error set, includes an error `name`.
4452 /// Might return a false negative if `ty` is an inferred error set and not fully2117 /// Might return a false negative if `ty` is an inferred error set and not fully
4453 /// resolved yet.2118 /// resolved yet.
4454 pub fn errorSetHasField(ty: Type, name: []const u8) bool {2119 pub fn errorSetHasFieldIp(
4455 if (ty.isAnyError()) {2120 ip: *const InternPool,
4456 return true;2121 ty: InternPool.Index,
4457 }2122 name: InternPool.NullTerminatedString,
44582123 ) bool {
4459 switch (ty.tag()) {2124 return switch (ty) {
4460 .error_set_single => {2125 .anyerror_type => true,
4461 const data = ty.castTag(.error_set_single).?.data;2126 else => switch (ip.indexToKey(ty)) {
4462 return std.mem.eql(u8, data, name);2127 .error_set_type => |error_set_type| {
4463 },2128 return error_set_type.nameIndex(ip, name) != null;
4464 .error_set_inferred => {2129 },
4465 const data = ty.castTag(.error_set_inferred).?.data;2130 .inferred_error_set_type => |index| {
4466 return data.errors.contains(name);2131 const ies = ip.inferredErrorSetPtrConst(index);
4467 },2132 if (ies.is_anyerror) return true;
4468 .error_set_merged => {2133 return ies.errors.contains(name);
4469 const data = ty.castTag(.error_set_merged).?.data;2134 },
4470 return data.contains(name);2135 else => unreachable,
4471 },2136 },
4472 .error_set => {2137 };
4473 const data = ty.castTag(.error_set).?.data;2138 }
4474 return data.names.contains(name);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,
4475 },2161 },
4476 else => unreachable,2162 };
4477 }
4478 }2163 }
44792164
4480 /// Asserts the type is an array or vector or struct.2165 /// Asserts the type is an array or vector or struct.
4481 pub fn arrayLen(ty: Type) u64 {2166 pub fn arrayLen(ty: Type, mod: *const Module) u64 {
4482 return switch (ty.tag()) {2167 return arrayLenIp(ty, &mod.intern_pool);
4483 .vector => ty.castTag(.vector).?.data.len,2168 }
4484 .array => ty.castTag(.array).?.data.len,2169
4485 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,2170 pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {
4486 .array_u8 => ty.castTag(.array_u8).?.data,2171 return switch (ip.indexToKey(ty.toIntern())) {
4487 .array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data,2172 .vector_type => |vector_type| vector_type.len,
4488 .tuple => ty.castTag(.tuple).?.data.types.len,2173 .array_type => |array_type| array_type.len,
4489 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,2174 .struct_type => |struct_type| {
4490 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),2175 const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0;
4491 .empty_struct, .empty_struct_literal => 0,2176 return struct_obj.fields.count();
2177 },
2178 .anon_struct_type => |tuple| tuple.types.len,
44922179
4493 else => unreachable,2180 else => unreachable,
4494 };2181 };
4495 }2182 }
44962183
4497 pub fn arrayLenIncludingSentinel(ty: Type) u64 {2184 pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 {
4498 return ty.arrayLen() + @boolToInt(ty.sentinel() != null);2185 return ty.arrayLen(mod) + @boolToInt(ty.sentinel(mod) != null);
4499 }2186 }
45002187
4501 pub fn vectorLen(ty: Type) u32 {2188 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
4502 return switch (ty.tag()) {2189 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4503 .vector => @intCast(u32, ty.castTag(.vector).?.data.len),2190 .vector_type => |vector_type| vector_type.len,
4504 .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),2191 .anon_struct_type => |tuple| @intCast(u32, tuple.types.len),
4505 .anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len),
4506 else => unreachable,2192 else => unreachable,
4507 };2193 };
4508 }2194 }
45092195
4510 /// Asserts the type is an array, pointer or vector.2196 /// Asserts the type is an array, pointer or vector.
4511 pub fn sentinel(self: Type) ?Value {2197 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
4512 return switch (self.tag()) {2198 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4513 .single_const_pointer,2199 .vector_type,
4514 .single_mut_pointer,2200 .struct_type,
4515 .many_const_pointer,2201 .anon_struct_type,
4516 .many_mut_pointer,2202 => null,
4517 .c_const_pointer,2203
4518 .c_mut_pointer,2204 .array_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null,
4519 .single_const_pointer_to_comptime_int,2205 .ptr_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null,
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,
45402206
4541 else => unreachable,2207 else => unreachable,
4542 };2208 };
4543 }2209 }
45442210
4545 /// Returns true if and only if the type is a fixed-width integer.2211 /// Returns true if and only if the type is a fixed-width integer.
4546 pub fn isInt(self: Type) bool {2212 pub fn isInt(self: Type, mod: *const Module) bool {
4547 return self.isSignedInt() or self.isUnsignedInt();2213 return self.isSignedInt(mod) or self.isUnsignedInt(mod);
4548 }2214 }
45492215
4550 /// Returns true if and only if the type is a fixed-width, signed integer.2216 /// Returns true if and only if the type is a fixed-width, signed integer.
4551 pub fn isSignedInt(self: Type) bool {2217 pub fn isSignedInt(ty: Type, mod: *const Module) bool {
4552 return switch (self.tag()) {2218 return switch (ty.toIntern()) {
4553 .int_signed,2219 .c_char_type, .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
4554 .i8,2220 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4555 .isize,2221 .int_type => |int_type| int_type.signedness == .signed,
4556 .c_char,2222 else => false,
4557 .c_short,2223 },
4558 .c_int,
4559 .c_long,
4560 .c_longlong,
4561 .i16,
4562 .i32,
4563 .i64,
4564 .i128,
4565 => true,
4566
4567 else => false,
4568 };2224 };
4569 }2225 }
45702226
4571 /// Returns true if and only if the type is a fixed-width, unsigned integer.2227 /// Returns true if and only if the type is a fixed-width, unsigned integer.
4572 pub fn isUnsignedInt(self: Type) bool {2228 pub fn isUnsignedInt(ty: Type, mod: *const Module) bool {
4573 return switch (self.tag()) {2229 return switch (ty.toIntern()) {
4574 .int_unsigned,2230 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
4575 .usize,2231 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
4576 .c_ushort,2232 .int_type => |int_type| int_type.signedness == .unsigned,
4577 .c_uint,2233 else => false,
4578 .c_ulong,2234 },
4579 .c_ulonglong,
4580 .u1,
4581 .u8,
4582 .u16,
4583 .u29,
4584 .u32,
4585 .u64,
4586 .u128,
4587 => true,
4588
4589 else => false,
4590 };2235 };
4591 }2236 }
45922237
4593 /// Returns true for integers, enums, error sets, and packed structs.2238 /// Returns true for integers, enums, error sets, and packed structs.
4594 /// If this function returns true, then intInfo() can be called on the type.2239 /// If this function returns true, then intInfo() can be called on the type.
4595 pub fn isAbiInt(ty: Type) bool {2240 pub fn isAbiInt(ty: Type, mod: *Module) bool {
4596 return switch (ty.zigTypeTag()) {2241 return switch (ty.zigTypeTag(mod)) {
4597 .Int, .Enum, .ErrorSet => true,2242 .Int, .Enum, .ErrorSet => true,
4598 .Struct => ty.containerLayout() == .Packed,2243 .Struct => ty.containerLayout(mod) == .Packed,
4599 else => false,2244 else => false,
4600 };2245 };
4601 }2246 }
46022247
4603 /// Asserts the type is an integer, enum, error set, or vector of one of them.2248 /// 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 {2249 pub fn intInfo(starting_ty: Type, mod: *Module) InternPool.Key.IntType {
4605 var ty = self;2250 const target = mod.getTarget();
4606 while (true) switch (ty.tag()) {2251 var ty = starting_ty;
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 },
46472252
4648 .error_set, .error_set_single, .anyerror, .error_set_inferred, .error_set_merged => {2253 while (true) switch (ty.toIntern()) {
2254 .anyerror_type => {
4649 // TODO revisit this when error sets support custom int types2255 // TODO revisit this when error sets support custom int types
4650 return .{ .signedness = .unsigned, .bits = 16 };2256 return .{ .signedness = .unsigned, .bits = 16 };
4651 },2257 },
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,2279 // TODO revisit this when error sets support custom int types
46542280 .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = 16 },
4655 .@"struct" => {2281
4656 const struct_obj = ty.castTag(.@"struct").?.data;2282 .anon_struct_type => unreachable,
4657 assert(struct_obj.layout == .Packed);2283
4658 ty = struct_obj.backing_int_ty;2284 .ptr_type => unreachable,
4659 },2285 .anyframe_type => unreachable,
46602286 .array_type => unreachable,
4661 else => unreachable,2287
4662 };2288 .opt_type => unreachable,
4663 }2289 .error_union_type => unreachable,
46642290 .func_type => unreachable,
4665 pub fn isNamedInt(self: Type) bool {2291 .simple_type => unreachable, // handled via Index enum tag above
4666 return switch (self.tag()) {2292
4667 .usize,2293 .union_type => unreachable,
4668 .isize,2294 .opaque_type => unreachable,
4669 .c_char,2295
4670 .c_short,2296 // values, not types
4671 .c_ushort,2297 .undef,
4672 .c_int,2298 .runtime_value,
4673 .c_uint,2299 .simple_value,
4674 .c_long,2300 .variable,
4675 .c_ulong,2301 .extern_func,
4676 .c_longlong,2302 .func,
4677 .c_ulonglong,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,
4678 => true,2334 => true,
46792335
4680 else => false,2336 else => false,
...@@ -4682,14 +2338,14 @@ pub const Type = extern union {...@@ -4682,14 +2338,14 @@ pub const Type = extern union {
4682 }2338 }
46832339
4684 /// Returns `false` for `comptime_float`.2340 /// Returns `false` for `comptime_float`.
4685 pub fn isRuntimeFloat(self: Type) bool {2341 pub fn isRuntimeFloat(ty: Type) bool {
4686 return switch (self.tag()) {2342 return switch (ty.toIntern()) {
4687 .f16,2343 .f16_type,
4688 .f32,2344 .f32_type,
4689 .f64,2345 .f64_type,
4690 .f80,2346 .f80_type,
4691 .f128,2347 .f128_type,
4692 .c_longdouble,2348 .c_longdouble_type,
4693 => true,2349 => true,
46942350
4695 else => false,2351 else => false,
...@@ -4697,15 +2353,15 @@ pub const Type = extern union {...@@ -4697,15 +2353,15 @@ pub const Type = extern union {
4697 }2353 }
46982354
4699 /// Returns `true` for `comptime_float`.2355 /// Returns `true` for `comptime_float`.
4700 pub fn isAnyFloat(self: Type) bool {2356 pub fn isAnyFloat(ty: Type) bool {
4701 return switch (self.tag()) {2357 return switch (ty.toIntern()) {
4702 .f16,2358 .f16_type,
4703 .f32,2359 .f32_type,
4704 .f64,2360 .f64_type,
4705 .f80,2361 .f80_type,
4706 .f128,2362 .f128_type,
4707 .c_longdouble,2363 .c_longdouble_type,
4708 .comptime_float,2364 .comptime_float_type,
4709 => true,2365 => true,
47102366
4711 else => false,2367 else => false,
...@@ -4714,431 +2370,304 @@ pub const Type = extern union {...@@ -4714,431 +2370,304 @@ pub const Type = extern union {
47142370
4715 /// Asserts the type is a fixed-size float or comptime_float.2371 /// Asserts the type is a fixed-size float or comptime_float.
4716 /// Returns 128 for comptime_float types.2372 /// Returns 128 for comptime_float types.
4717 pub fn floatBits(self: Type, target: Target) u16 {2373 pub fn floatBits(ty: Type, target: Target) u16 {
4718 return switch (self.tag()) {2374 return switch (ty.toIntern()) {
4719 .f16 => 16,2375 .f16_type => 16,
4720 .f32 => 32,2376 .f32_type => 32,
4721 .f64 => 64,2377 .f64_type => 64,
4722 .f80 => 80,2378 .f80_type => 80,
4723 .f128, .comptime_float => 128,2379 .f128_type, .comptime_float_type => 128,
4724 .c_longdouble => target.c_type_bit_size(.longdouble),2380 .c_longdouble_type => 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,
47382381
4739 else => unreachable,2382 else => unreachable,
4740 };2383 };
4741 }2384 }
47422385
4743 /// Asserts the type is a function. The length of the slice must be at least the length2386 /// Asserts the type is a function or a function pointer.
4744 /// given by `fnParamLen`.2387 pub fn fnReturnType(ty: Type, mod: *Module) Type {
4745 pub fn fnParamTypes(self: Type, types: []Type) void {2388 return fnReturnTypeIp(ty, &mod.intern_pool);
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 };
4786 }2389 }
47872390
4788 /// Asserts the type is a function.2391 pub fn fnReturnTypeIp(ty: Type, ip: *const InternPool) Type {
4789 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {2392 return switch (ip.indexToKey(ty.toIntern())) {
4790 return switch (self.tag()) {2393 .ptr_type => |ptr_type| ip.indexToKey(ptr_type.child).func_type.return_type,
4791 .fn_noreturn_no_args => .Unspecified,2394 .func_type => |func_type| func_type.return_type,
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
4797 else => unreachable,2395 else => unreachable,
4798 };2396 }.toType();
4799 }2397 }
48002398
4801 /// Asserts the type is a function.2399 /// Asserts the type is a function.
4802 pub fn fnCallingConventionAllowsZigTypes(target: Target, cc: std.builtin.CallingConvention) bool {2400 pub fn fnCallingConvention(ty: Type, mod: *Module) std.builtin.CallingConvention {
4803 return switch (cc) {2401 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.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 };
4810 }2402 }
48112403
4812 pub fn isValidParamType(self: Type) bool {2404 pub fn isValidParamType(self: Type, mod: *const Module) bool {
4813 return switch (self.zigTypeTagOrPoison() catch return true) {2405 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
4814 .Undefined, .Null, .Opaque, .NoReturn => false,2406 .Undefined, .Null, .Opaque, .NoReturn => false,
4815 else => true,2407 else => true,
4816 };2408 };
4817 }2409 }
48182410
4819 pub fn isValidReturnType(self: Type) bool {2411 pub fn isValidReturnType(self: Type, mod: *const Module) bool {
4820 return switch (self.zigTypeTagOrPoison() catch return true) {2412 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
4821 .Undefined, .Null, .Opaque => false,2413 .Undefined, .Null, .Opaque => false,
4822 else => true,2414 else => true,
4823 };2415 };
4824 }2416 }
48252417
4826 /// Asserts the type is a function.2418 /// Asserts the type is a function.
4827 pub fn fnIsVarArgs(self: Type) bool {2419 pub fn fnIsVarArgs(ty: Type, mod: *Module) bool {
4828 return switch (self.tag()) {2420 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.is_var_args;
4829 .fn_noreturn_no_args => false,2421 }
4830 .fn_void_no_args => false,2422
4831 .fn_naked_noreturn_no_args => false,2423 pub fn isNumeric(ty: Type, mod: *const Module) bool {
4832 .fn_ccc_void_no_args => false,2424 return switch (ty.toIntern()) {
4833 .function => self.castTag(.function).?.data.is_var_args,2425 .f16_type,
48342426 .f32_type,
4835 else => unreachable,2427 .f64_type,
4836 };2428 .f80_type,
4837 }2429 .f128_type,
48382430 .c_longdouble_type,
4839 pub fn fnInfo(ty: Type) Payload.Function.Data {2431 .comptime_int_type,
4840 return switch (ty.tag()) {2432 .comptime_float_type,
4841 .fn_noreturn_no_args => .{2433 .usize_type,
4842 .param_types = &.{},2434 .isize_type,
4843 .comptime_params = undefined,2435 .c_char_type,
4844 .return_type = initTag(.noreturn),2436 .c_short_type,
4845 .cc = .Unspecified,2437 .c_ushort_type,
4846 .alignment = 0,2438 .c_int_type,
4847 .is_var_args = false,2439 .c_uint_type,
4848 .is_generic = false,2440 .c_long_type,
4849 .is_noinline = false,2441 .c_ulong_type,
4850 .align_is_generic = false,2442 .c_longlong_type,
4851 .cc_is_generic = false,2443 .c_ulonglong_type,
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,
4942 => true,2444 => true,
49432445
4944 else => false,2446 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2447 .int_type => true,
2448 else => false,
2449 },
4945 };2450 };
4946 }2451 }
49472452
4948 /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which2453 /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
4949 /// resolves field types rather than asserting they are already resolved.2454 /// 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 {
4951 var ty = starting_type;2456 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" => {2458 while (true) switch (ty.toIntern()) {
5046 const s = ty.castTag(.@"struct").?.data;2459 .empty_struct_type => return Value.empty_struct,
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 },
50552460
5056 .tuple, .anon_struct => {2461 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5057 const tuple = ty.tupleFields();2462 .int_type => |int_type| {
5058 for (tuple.values, 0..) |val, i| {2463 if (int_type.bits == 0) {
5059 const is_comptime = val.tag() != .unreachable_value;2464 return try mod.intValue(ty, 0);
5060 if (is_comptime) continue;2465 } else {
5061 if (tuple.types[i].onePossibleValue() != null) continue;2466 return null;
5062 return null;2467 }
5063 }2468 },
5064 return Value.initTag(.empty_struct_value);
5065 },
50662469
5067 .enum_numbered => {2470 .ptr_type,
5068 const enum_numbered = ty.castTag(.enum_numbered).?.data;2471 .error_union_type,
5069 // An explicit tag type is always provided for enum_numbered.2472 .func_type,
5070 if (enum_numbered.tag_ty.hasRuntimeBits()) {2473 .anyframe_type,
5071 return null;2474 .error_set_type,
5072 }2475 .inferred_error_set_type,
5073 assert(enum_numbered.fields.count() == 1);2476 => return null,
5074 return enum_numbered.values.keys()[0];2477
5075 },2478 inline .array_type, .vector_type => |seq_type, seq_tag| {
5076 .enum_full => {2479 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
5077 const enum_full = ty.castTag(.enum_full).?.data;2480 if (seq_type.len + @boolToInt(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{
5078 if (enum_full.tag_ty.hasRuntimeBits()) {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 }
5079 return null;2490 return null;
5080 }2491 },
5081 switch (enum_full.fields.count()) {2492 .opt_type => |child| {
5082 0 => return Value.initTag(.unreachable_value),2493 if (child == .noreturn_type) {
5083 1 => if (enum_full.values.count() == 0) {2494 return try mod.nullValue(ty);
5084 return Value.zero; // auto-numbered
5085 } else {2495 } 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;
5087 },2621 },
5088 else => return null,2622 .auto, .explicit => {
5089 }2623 if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
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 },
51172624
5118 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),2625 switch (enum_type.names.len) {
5119 .void => return Value.initTag(.void_value),2626 0 => {
5120 .noreturn => return Value.initTag(.unreachable_value),2627 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
5121 .null => return Value.initTag(.null_value),2628 return only.toValue();
5122 .undefined => return Value.initTag(.undef),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 => {2649 // values, not types
5125 if (ty.cast(Payload.Bits).?.data == 0) {2650 .undef,
5126 return Value.zero;2651 .runtime_value,
5127 } else {2652 .simple_value,
5128 return null;2653 .variable,
5129 }2654 .extern_func,
5130 },2655 .func,
5131 .vector, .array, .array_u8 => {2656 .int,
5132 if (ty.arrayLen() == 0)2657 .err,
5133 return Value.initTag(.empty_array);2658 .error_union,
5134 if (ty.elemType().onePossibleValue() != null)2659 .enum_literal,
5135 return Value.initTag(.the_only_possible_value);2660 .enum_tag,
5136 return null;2661 .empty_enum_value,
2662 .float,
2663 .ptr,
2664 .opt,
2665 .aggregate,
2666 .un,
2667 // memoization, not types
2668 .memoized_call,
2669 => unreachable,
5137 },2670 },
5138
5139 .inferred_alloc_const => unreachable,
5140 .inferred_alloc_mut => unreachable,
5141 .generic_poison => unreachable,
5142 };2671 };
5143 }2672 }
51442673
...@@ -5146,350 +2675,298 @@ pub const Type = extern union {...@@ -5146,350 +2675,298 @@ pub const Type = extern union {
5146 /// resolves field types rather than asserting they are already resolved.2675 /// resolves field types rather than asserting they are already resolved.
5147 /// TODO merge these implementations together with the "advanced" pattern seen2676 /// TODO merge these implementations together with the "advanced" pattern seen
5148 /// elsewhere in this file.2677 /// elsewhere in this file.
5149 pub fn comptimeOnly(ty: Type) bool {2678 pub fn comptimeOnly(ty: Type, mod: *Module) bool {
5150 return switch (ty.tag()) {2679 return switch (ty.toIntern()) {
5151 .u1,2680 .empty_struct_type => false,
5152 .u8,2681
5153 .i8,2682 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5154 .u16,2683 .int_type => false,
5155 .i16,2684 .ptr_type => |ptr_type| {
5156 .u29,2685 const child_ty = ptr_type.child.toType();
5157 .u32,2686 if (child_ty.zigTypeTag(mod) == .Fn) {
5158 .i32,2687 return false;
5159 .u64,2688 } else {
5160 .i64,2689 return child_ty.comptimeOnly(mod);
5161 .u128,2690 }
5162 .i128,2691 },
5163 .usize,2692 .anyframe_type => |child| {
5164 .isize,2693 if (child == .none) return false;
5165 .c_char,2694 return child.toType().comptimeOnly(mod);
5166 .c_short,2695 },
5167 .c_ushort,2696 .array_type => |array_type| array_type.child.toType().comptimeOnly(mod),
5168 .c_int,2697 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),
5169 .c_uint,2698 .opt_type => |child| child.toType().comptimeOnly(mod),
5170 .c_long,2699 .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod),
5171 .c_ulong,2700
5172 .c_longlong,2701 .error_set_type,
5173 .c_ulonglong,2702 .inferred_error_set_type,
5174 .c_longdouble,2703 => false,
5175 .f16,2704
5176 .f32,2705 // These are function bodies, not function pointers.
5177 .f64,2706 .func_type => true,
5178 .f80,2707
5179 .f128,2708 .simple_type => |t| switch (t) {
5180 .anyopaque,2709 .f16,
5181 .bool,2710 .f32,
5182 .void,2711 .f64,
5183 .anyerror,2712 .f80,
5184 .noreturn,2713 .f128,
5185 .@"anyframe",2714 .usize,
5186 .null,2715 .isize,
5187 .undefined,2716 .c_char,
5188 .atomic_order,2717 .c_short,
5189 .atomic_rmw_op,2718 .c_ushort,
5190 .calling_convention,2719 .c_int,
5191 .address_space,2720 .c_uint,
5192 .float_mode,2721 .c_long,
5193 .reduce_op,2722 .c_ulong,
5194 .modifier,2723 .c_longlong,
5195 .prefetch_options,2724 .c_ulonglong,
5196 .export_options,2725 .c_longdouble,
5197 .extern_options,2726 .anyopaque,
5198 .manyptr_u8,2727 .bool,
5199 .manyptr_const_u8,2728 .void,
5200 .manyptr_const_u8_sentinel_0,2729 .anyerror,
5201 .const_slice_u8,2730 .noreturn,
5202 .const_slice_u8_sentinel_0,2731 .generic_poison,
5203 .anyerror_void_error_union,2732 .atomic_order,
5204 .empty_struct_literal,2733 .atomic_rmw_op,
5205 .empty_struct,2734 .calling_convention,
5206 .error_set,2735 .address_space,
5207 .error_set_single,2736 .float_mode,
5208 .error_set_inferred,2737 .reduce_op,
5209 .error_set_merged,2738 .call_modifier,
5210 .@"opaque",2739 .prefetch_options,
5211 .generic_poison,2740 .export_options,
5212 .array_u8,2741 .extern_options,
5213 .array_u8_sentinel_0,2742 => false,
5214 .int_signed,2743
5215 .int_unsigned,2744 .type,
5216 .enum_simple,2745 .comptime_int,
5217 => false,2746 .comptime_float,
52182747 .null,
5219 .single_const_pointer_to_comptime_int,2748 .undefined,
5220 .type,2749 .enum_literal,
5221 .comptime_int,2750 .type_info,
5222 .comptime_float,2751 => true,
5223 .enum_literal,2752 },
5224 .type_info,2753 .struct_type => |struct_type| {
5225 // These are function bodies, not function pointers.2754 // A struct with no fields is not comptime-only.
5226 .fn_noreturn_no_args,2755 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
5227 .fn_void_no_args,2756 switch (struct_obj.requires_comptime) {
5228 .fn_naked_noreturn_no_args,2757 .wip, .unknown => {
5229 .fn_ccc_void_no_args,2758 // Return false to avoid incorrect dependency loops.
5230 .function,2759 // This will be handled correctly once merged with
5231 => true,2760 // `Sema.typeRequiresComptime`.
2761 return false;
2762 },
2763 .no => return false,
2764 .yes => return true,
2765 }
2766 },
52322767
5233 .inferred_alloc_mut => unreachable,2768 .anon_struct_type => |tuple| {
5234 .inferred_alloc_const => unreachable,2769 for (tuple.types, tuple.values) |field_ty, val| {
52352770 const have_comptime_val = val != .none;
5236 .array,2771 if (!have_comptime_val and field_ty.toType().comptimeOnly(mod)) return true;
5237 .array_sentinel,2772 }
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) {
5253 return false;2773 return false;
5254 } else {2774 },
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 },
52662775
5267 .tuple, .anon_struct => {2776 .union_type => |union_type| {
5268 const tuple = ty.tupleFields();2777 const union_obj = mod.unionPtr(union_type.index);
5269 for (tuple.types, 0..) |field_ty, i| {2778 switch (union_obj.requires_comptime) {
5270 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;2779 .wip, .unknown => {
5271 if (!have_comptime_val and field_ty.comptimeOnly()) return true;2780 // Return false to avoid incorrect dependency loops.
5272 }2781 // This will be handled correctly once merged with
5273 return false;2782 // `Sema.typeRequiresComptime`.
5274 },2783 return false;
2784 },
2785 .no => return false,
2786 .yes => return true,
2787 }
2788 },
52752789
5276 .@"struct" => {2790 .opaque_type => false,
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 },
52892791
5290 .@"union", .union_safety_tagged, .union_tagged => {2792 .enum_type => |enum_type| enum_type.tag_ty.toType().comptimeOnly(mod),
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 },
53032793
5304 .error_union => return ty.errorUnionPayload().comptimeOnly(),2794 // values, not types
5305 .anyframe_T => {2795 .undef,
5306 const child_ty = ty.castTag(.anyframe_T).?.data;2796 .runtime_value,
5307 return child_ty.comptimeOnly();2797 .simple_value,
5308 },2798 .variable,
5309 .enum_numbered => {2799 .extern_func,
5310 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;2800 .func,
5311 return tag_ty.comptimeOnly();2801 .int,
5312 },2802 .err,
5313 .enum_full, .enum_nonexhaustive => {2803 .error_union,
5314 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;2804 .enum_literal,
5315 return tag_ty.comptimeOnly();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,
5316 },2815 },
5317 };2816 };
5318 }2817 }
53192818
5320 pub fn isArrayOrVector(ty: Type) bool {2819 pub fn isVector(ty: Type, mod: *const Module) bool {
5321 return switch (ty.zigTypeTag()) {2820 return ty.zigTypeTag(mod) == .Vector;
2821 }
2822
2823 pub fn isArrayOrVector(ty: Type, mod: *const Module) bool {
2824 return switch (ty.zigTypeTag(mod)) {
5322 .Array, .Vector => true,2825 .Array, .Vector => true,
5323 else => false,2826 else => false,
5324 };2827 };
5325 }2828 }
53262829
5327 pub fn isIndexable(ty: Type) bool {2830 pub fn isIndexable(ty: Type, mod: *Module) bool {
5328 return switch (ty.zigTypeTag()) {2831 return switch (ty.zigTypeTag(mod)) {
5329 .Array, .Vector => true,2832 .Array, .Vector => true,
5330 .Pointer => switch (ty.ptrSize()) {2833 .Pointer => switch (ty.ptrSize(mod)) {
5331 .Slice, .Many, .C => true,2834 .Slice, .Many, .C => true,
5332 .One => ty.elemType().zigTypeTag() == .Array,2835 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
5333 },2836 },
5334 .Struct => ty.isTuple(),2837 .Struct => ty.isTuple(mod),
5335 else => false,2838 else => false,
5336 };2839 };
5337 }2840 }
53382841
5339 pub fn indexableHasLen(ty: Type) bool {2842 pub fn indexableHasLen(ty: Type, mod: *Module) bool {
5340 return switch (ty.zigTypeTag()) {2843 return switch (ty.zigTypeTag(mod)) {
5341 .Array, .Vector => true,2844 .Array, .Vector => true,
5342 .Pointer => switch (ty.ptrSize()) {2845 .Pointer => switch (ty.ptrSize(mod)) {
5343 .Many, .C => false,2846 .Many, .C => false,
5344 .Slice => true,2847 .Slice => true,
5345 .One => ty.elemType().zigTypeTag() == .Array,2848 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
5346 },2849 },
5347 .Struct => ty.isTuple(),2850 .Struct => ty.isTuple(mod),
5348 else => false,2851 else => false,
5349 };2852 };
5350 }2853 }
53512854
5352 /// Returns null if the type has no namespace.2855 /// Returns null if the type has no namespace.
5353 pub fn getNamespace(self: Type) ?*Module.Namespace {2856 pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex {
5354 return switch (self.tag()) {2857 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5355 .@"struct" => &self.castTag(.@"struct").?.data.namespace,2858 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
5356 .enum_full => &self.castTag(.enum_full).?.data.namespace,2859 .struct_type => |struct_type| struct_type.namespace,
5357 .enum_nonexhaustive => &self.castTag(.enum_nonexhaustive).?.data.namespace,2860 .union_type => |union_type| mod.unionPtr(union_type.index).namespace.toOptional(),
5358 .empty_struct => self.castTag(.empty_struct).?.data,2861 .enum_type => |enum_type| enum_type.namespace,
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,
53632862
5364 else => null,2863 else => .none,
5365 };2864 };
5366 }2865 }
53672866
5368 // Works for vectors and vectors of integers.2867 /// Returns null if the type has no namespace.
5369 pub fn minInt(ty: Type, arena: Allocator, target: Target) !Value {2868 pub fn getNamespace(ty: Type, mod: *Module) ?*Module.Namespace {
5370 const scalar = try minIntScalar(ty.scalarType(), arena, target);2869 return if (getNamespaceIndex(ty, mod).unwrap()) |i| mod.namespacePtr(i) else null;
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 }
5376 }2870 }
53772871
5378 /// Asserts that self.zigTypeTag() == .Int.2872 // Works for vectors and vectors of integers.
5379 pub fn minIntScalar(ty: Type, arena: Allocator, target: Target) !Value {2873 pub fn minInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
5380 assert(ty.zigTypeTag() == .Int);2874 const scalar = try minIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
5381 const info = ty.intInfo(target);2875 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
53822876 .ty = dest_ty.toIntern(),
5383 if (info.bits == 0) {2877 .storage = .{ .repeated_elem = scalar.toIntern() },
5384 return Value.initTag(.the_only_possible_value);2878 } })).toValue() else scalar;
5385 }2879 }
53862880
5387 if (info.signedness == .unsigned) {2881 /// Asserts that the type is an integer.
5388 return Value.zero;2882 pub fn minIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
5389 }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
5391 if (std.math.cast(u6, info.bits - 1)) |shift| {2887 if (std.math.cast(u6, info.bits - 1)) |shift| {
5392 const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);2888 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);
5394 }2890 }
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
5397 try res.setTwosCompIntLimit(.min, info.signedness, info.bits);2895 try res.setTwosCompIntLimit(.min, info.signedness, info.bits);
53982896
5399 const res_const = res.toConst();2897 return mod.intValue_big(dest_ty, 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 }
5405 }2898 }
54062899
5407 // Works for vectors and vectors of integers.2900 // Works for vectors and vectors of integers.
5408 pub fn maxInt(ty: Type, arena: Allocator, target: Target) !Value {2901 /// The returned Value will have type dest_ty.
5409 const scalar = try maxIntScalar(ty.scalarType(), arena, target);2902 pub fn maxInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
5410 if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) {2903 const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
5411 return Value.Tag.repeated.create(arena, scalar);2904 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
5412 } else {2905 .ty = dest_ty.toIntern(),
5413 return scalar;2906 .storage = .{ .repeated_elem = scalar.toIntern() },
5414 }2907 } })).toValue() else scalar;
5415 }2908 }
54162909
5417 /// Asserts that self.zigTypeTag() == .Int.2910 /// The returned Value will have type dest_ty.
5418 pub fn maxIntScalar(self: Type, arena: Allocator, target: Target) !Value {2911 pub fn maxIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
5419 assert(self.zigTypeTag() == .Int);2912 const info = ty.intInfo(mod);
5420 const info = self.intInfo(target);
5421
5422 if (info.bits == 0) {
5423 return Value.initTag(.the_only_possible_value);
5424 }
54252913
5426 switch (info.bits - @boolToInt(info.signedness == .signed)) {2914 switch (info.bits) {
5427 0 => return Value.zero,2915 0 => return switch (info.signedness) {
5428 1 => return Value.one,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 },
5429 else => {},2923 else => {},
5430 }2924 }
54312925
5432 if (std.math.cast(u6, info.bits - 1)) |shift| switch (info.signedness) {2926 if (std.math.cast(u6, info.bits - 1)) |shift| switch (info.signedness) {
5433 .signed => {2927 .signed => {
5434 const n = @as(i64, std.math.maxInt(i64)) >> (63 - shift);2928 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);
5436 },2930 },
5437 .unsigned => {2931 .unsigned => {
5438 const n = @as(u64, std.math.maxInt(u64)) >> (63 - shift);2932 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);
5440 },2934 },
5441 };2935 };
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
5444 try res.setTwosCompIntLimit(.max, info.signedness, info.bits);2940 try res.setTwosCompIntLimit(.max, info.signedness, info.bits);
54452941
5446 const res_const = res.toConst();2942 return mod.intValue_big(dest_ty, 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 }
5452 }2943 }
54532944
5454 /// Asserts the type is an enum or a union.2945 /// Asserts the type is an enum or a union.
5455 pub fn intTagType(ty: Type, buffer: *Payload.Bits) Type {2946 pub fn intTagType(ty: Type, mod: *Module) Type {
5456 switch (ty.tag()) {2947 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5457 .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty,2948 .union_type => |union_type| mod.unionPtr(union_type.index).tag_ty.intTagType(mod),
5458 .enum_numbered => return ty.castTag(.enum_numbered).?.data.tag_ty,2949 .enum_type => |enum_type| enum_type.tag_ty.toType(),
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),
5470 else => unreachable,2950 else => unreachable,
5471 }2951 };
5472 }2952 }
54732953
5474 pub fn isNonexhaustiveEnum(ty: Type) bool {2954 pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {
5475 return switch (ty.tag()) {2955 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5476 .enum_nonexhaustive => true,2956 .enum_type => |enum_type| switch (enum_type.tag_mode) {
2957 .nonexhaustive => true,
2958 .auto, .explicit => false,
2959 },
5477 else => false,2960 else => false,
5478 };2961 };
5479 }2962 }
54802963
5481 // Asserts that `ty` is an error set and not `anyerror`.2964 // Asserts that `ty` is an error set and not `anyerror`.
5482 pub fn errorSetNames(ty: Type) []const []const u8 {2965 pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
5483 return switch (ty.tag()) {2966 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5484 .error_set_single => blk: {2967 .error_set_type => |x| x.names,
5485 // Work around coercion problems2968 .inferred_error_set_type => |index| {
5486 const tmp: *const [1][]const u8 = &ty.castTag(.error_set_single).?.data;2969 const inferred_error_set = mod.inferredErrorSetPtr(index);
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;
5493 assert(inferred_error_set.is_resolved);2970 assert(inferred_error_set.is_resolved);
5494 assert(!inferred_error_set.is_anyerror);2971 assert(!inferred_error_set.is_anyerror);
5495 return inferred_error_set.errors.keys();2972 return inferred_error_set.errors.keys();
...@@ -5498,133 +2975,43 @@ pub const Type = extern union {...@@ -5498,133 +2975,43 @@ pub const Type = extern union {
5498 };2975 };
5499 }2976 }
55002977
5501 /// Merge lhs with rhs.2978 pub fn enumFields(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
5502 /// Asserts that lhs and rhs are both error sets and are resolved.2979 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names;
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 };
5539 }2980 }
55402981
5541 pub fn enumFieldCount(ty: Type) usize {2982 pub fn enumFieldCount(ty: Type, mod: *Module) usize {
5542 return ty.enumFields().count();2983 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names.len;
5543 }2984 }
55442985
5545 pub fn enumFieldName(ty: Type, field_index: usize) []const u8 {2986 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
5546 return ty.enumFields().keys()[field_index];2987 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names[field_index];
5547 }2988 }
55482989
5549 pub fn enumFieldIndex(ty: Type, field_name: []const u8) ?usize {2990 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
5550 return ty.enumFields().getIndex(field_name);2991 const ip = &mod.intern_pool;
2992 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
2993 return enum_type.nameIndex(ip, field_name);
5551 }2994 }
55522995
5553 /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or2996 /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or
5554 /// an integer which represents the enum value. Returns the field index in2997 /// an integer which represents the enum value. Returns the field index in
5555 /// declaration order, or `null` if `enum_tag` does not match any field.2998 /// declaration order, or `null` if `enum_tag` does not match any field.
5556 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?usize {2999 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
5557 if (enum_tag.castTag(.enum_field_index)) |payload| {3000 const ip = &mod.intern_pool;
5558 return @as(usize, payload.data);3001 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
5559 }3002 const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {
5560 const S = struct {3003 .int => enum_tag.toIntern(),
5561 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {3004 .enum_tag => |info| info.int,
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"),
5619 else => unreachable,3005 else => unreachable,
5620 }3006 };
3007 assert(ip.typeOf(int_tag) == enum_type.tag_ty);
3008 return enum_type.tagValueIndex(ip, int_tag);
5621 }3009 }
56223010
5623 pub fn structFields(ty: Type) Module.Struct.Fields {3011 pub fn structFields(ty: Type, mod: *Module) Module.Struct.Fields {
5624 switch (ty.tag()) {3012 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5625 .empty_struct, .empty_struct_literal => return .{},3013 .struct_type => |struct_type| {
5626 .@"struct" => {3014 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .{};
5627 const struct_obj = ty.castTag(.@"struct").?.data;
5628 assert(struct_obj.haveFieldTypes());3015 assert(struct_obj.haveFieldTypes());
5629 return struct_obj.fields;3016 return struct_obj.fields;
5630 },3017 },
...@@ -5632,141 +3019,122 @@ pub const Type = extern union {...@@ -5632,141 +3019,122 @@ pub const Type = extern union {
5632 }3019 }
5633 }3020 }
56343021
5635 pub fn structFieldName(ty: Type, field_index: usize) []const u8 {3022 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
5636 switch (ty.tag()) {3023 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5637 .@"struct" => {3024 .struct_type => |struct_type| {
5638 const struct_obj = ty.castTag(.@"struct").?.data;3025 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5639 assert(struct_obj.haveFieldTypes());3026 assert(struct_obj.haveFieldTypes());
5640 return struct_obj.fields.keys()[field_index];3027 return struct_obj.fields.keys()[field_index];
5641 },3028 },
5642 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],3029 .anon_struct_type => |anon_struct| anon_struct.names[field_index],
5643 else => unreachable,3030 else => unreachable,
5644 }3031 };
5645 }3032 }
56463033
5647 pub fn structFieldCount(ty: Type) usize {3034 pub fn structFieldCount(ty: Type, mod: *Module) usize {
5648 switch (ty.tag()) {3035 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5649 .@"struct" => {3036 .struct_type => |struct_type| {
5650 const struct_obj = ty.castTag(.@"struct").?.data;3037 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
5651 assert(struct_obj.haveFieldTypes());3038 assert(struct_obj.haveFieldTypes());
5652 return struct_obj.fields.count();3039 return struct_obj.fields.count();
5653 },3040 },
5654 .empty_struct, .empty_struct_literal => return 0,3041 .anon_struct_type => |anon_struct| anon_struct.types.len,
5655 .tuple => return ty.castTag(.tuple).?.data.types.len,
5656 .anon_struct => return ty.castTag(.anon_struct).?.data.types.len,
5657 else => unreachable,3042 else => unreachable,
5658 }3043 };
5659 }3044 }
56603045
5661 /// Supports structs and unions.3046 /// Supports structs and unions.
5662 pub fn structFieldType(ty: Type, index: usize) Type {3047 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
5663 switch (ty.tag()) {3048 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5664 .@"struct" => {3049 .struct_type => |struct_type| {
5665 const struct_obj = ty.castTag(.@"struct").?.data;3050 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5666 return struct_obj.fields.values()[index].ty;3051 return struct_obj.fields.values()[index].ty;
5667 },3052 },
5668 .@"union", .union_safety_tagged, .union_tagged => {3053 .union_type => |union_type| {
5669 const union_obj = ty.cast(Payload.Union).?.data;3054 const union_obj = mod.unionPtr(union_type.index);
5670 return union_obj.fields.values()[index].ty;3055 return union_obj.fields.values()[index].ty;
5671 },3056 },
5672 .tuple => return ty.castTag(.tuple).?.data.types[index],3057 .anon_struct_type => |anon_struct| anon_struct.types[index].toType(),
5673 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
5674 else => unreachable,3058 else => unreachable,
5675 }3059 };
5676 }3060 }
56773061
5678 pub fn structFieldAlign(ty: Type, index: usize, target: Target) u32 {3062 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {
5679 switch (ty.tag()) {3063 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5680 .@"struct" => {3064 .struct_type => |struct_type| {
5681 const struct_obj = ty.castTag(.@"struct").?.data;3065 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5682 assert(struct_obj.layout != .Packed);3066 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);
5684 },3071 },
5685 .@"union", .union_safety_tagged, .union_tagged => {3072 .union_type => |union_type| {
5686 const union_obj = ty.cast(Payload.Union).?.data;3073 const union_obj = mod.unionPtr(union_type.index);
5687 return union_obj.fields.values()[index].normalAlignment(target);3074 return union_obj.fields.values()[index].normalAlignment(mod);
5688 },3075 },
5689 .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(target),
5690 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(target),
5691 else => unreachable,3076 else => unreachable,
5692 }3077 }
5693 }3078 }
56943079
5695 pub fn structFieldDefaultValue(ty: Type, index: usize) Value {3080 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
5696 switch (ty.tag()) {3081 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5697 .@"struct" => {3082 .struct_type => |struct_type| {
5698 const struct_obj = ty.castTag(.@"struct").?.data;3083 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5699 return struct_obj.fields.values()[index].default_val;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();
5700 },3088 },
5701 .tuple => {3089 .anon_struct_type => |anon_struct| {
5702 const tuple = ty.castTag(.tuple).?.data;3090 const val = anon_struct.values[index];
5703 return tuple.values[index];3091 // TODO: avoid using `unreachable` to indicate this.
5704 },3092 if (val == .none) return Value.@"unreachable";
5705 .anon_struct => {3093 return val.toValue();
5706 const struct_obj = ty.castTag(.anon_struct).?.data;
5707 return struct_obj.values[index];
5708 },3094 },
5709 else => unreachable,3095 else => unreachable,
5710 }3096 }
5711 }3097 }
57123098
5713 pub fn structFieldValueComptime(ty: Type, index: usize) ?Value {3099 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
5714 switch (ty.tag()) {3100 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5715 .@"struct" => {3101 .struct_type => |struct_type| {
5716 const struct_obj = ty.castTag(.@"struct").?.data;3102 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5717 const field = struct_obj.fields.values()[index];3103 const field = struct_obj.fields.values()[index];
5718 if (field.is_comptime) {3104 if (field.is_comptime) {
5719 return field.default_val;3105 return field.default_val.toValue();
5720 } else {3106 } else {
5721 return field.ty.onePossibleValue();3107 return field.ty.onePossibleValue(mod);
5722 }3108 }
5723 },3109 },
5724 .tuple => {3110 .anon_struct_type => |tuple| {
5725 const tuple = ty.castTag(.tuple).?.data;
5726 const val = tuple.values[index];3111 const val = tuple.values[index];
5727 if (val.tag() == .unreachable_value) {3112 if (val == .none) {
5728 return tuple.types[index].onePossibleValue();3113 return tuple.types[index].toType().onePossibleValue(mod);
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();
5738 } else {3114 } else {
5739 return val;3115 return val.toValue();
5740 }3116 }
5741 },3117 },
5742 else => unreachable,3118 else => unreachable,
5743 }3119 }
5744 }3120 }
57453121
5746 pub fn structFieldIsComptime(ty: Type, index: usize) bool {3122 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
5747 switch (ty.tag()) {3123 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5748 .@"struct" => {3124 .struct_type => |struct_type| {
5749 const struct_obj = ty.castTag(.@"struct").?.data;3125 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5750 if (struct_obj.layout == .Packed) return false;3126 if (struct_obj.layout == .Packed) return false;
5751 const field = struct_obj.fields.values()[index];3127 const field = struct_obj.fields.values()[index];
5752 return field.is_comptime;3128 return field.is_comptime;
5753 },3129 },
5754 .tuple => {3130 .anon_struct_type => |anon_struct| anon_struct.values[index] != .none,
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 },
5764 else => unreachable,3131 else => unreachable,
5765 }3132 };
5766 }3133 }
57673134
5768 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {3135 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
5769 const struct_obj = ty.castTag(.@"struct").?.data;3136 const struct_type = mod.intern_pool.indexToKey(ty.toIntern()).struct_type;
3137 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5770 assert(struct_obj.layout == .Packed);3138 assert(struct_obj.layout == .Packed);
5771 comptime assert(Type.packed_struct_layout_version == 2);3139 comptime assert(Type.packed_struct_layout_version == 2);
57723140
...@@ -5774,9 +3142,9 @@ pub const Type = extern union {...@@ -5774,9 +3142,9 @@ pub const Type = extern union {
5774 var elem_size_bits: u16 = undefined;3142 var elem_size_bits: u16 = undefined;
5775 var running_bits: u16 = 0;3143 var running_bits: u16 = 0;
5776 for (struct_obj.fields.values(), 0..) |f, i| {3144 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));
5780 if (i == field_index) {3148 if (i == field_index) {
5781 bit_offset = running_bits;3149 bit_offset = running_bits;
5782 elem_size_bits = field_bits;3150 elem_size_bits = field_bits;
...@@ -5797,9 +3165,10 @@ pub const Type = extern union {...@@ -5797,9 +3165,10 @@ pub const Type = extern union {
5797 offset: u64 = 0,3165 offset: u64 = 0,
5798 big_align: u32 = 0,3166 big_align: u32 = 0,
5799 struct_obj: *Module.Struct,3167 struct_obj: *Module.Struct,
5800 target: Target,3168 module: *Module,
58013169
5802 pub fn next(it: *StructOffsetIterator) ?FieldOffset {3170 pub fn next(it: *StructOffsetIterator) ?FieldOffset {
3171 const mod = it.module;
5803 var i = it.field;3172 var i = it.field;
5804 if (it.struct_obj.fields.count() <= i)3173 if (it.struct_obj.fields.count() <= i)
5805 return null;3174 return null;
...@@ -5811,35 +3180,36 @@ pub const Type = extern union {...@@ -5811,35 +3180,36 @@ pub const Type = extern union {
5811 const field = it.struct_obj.fields.values()[i];3180 const field = it.struct_obj.fields.values()[i];
5812 it.field += 1;3181 it.field += 1;
58133182
5814 if (field.is_comptime or !field.ty.hasRuntimeBits()) {3183 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) {
5815 return FieldOffset{ .field = i, .offset = it.offset };3184 return FieldOffset{ .field = i, .offset = it.offset };
5816 }3185 }
58173186
5818 const field_align = field.alignment(it.target, it.struct_obj.layout);3187 const field_align = field.alignment(mod, it.struct_obj.layout);
5819 it.big_align = @max(it.big_align, field_align);3188 it.big_align = @max(it.big_align, field_align);
5820 const field_offset = std.mem.alignForwardGeneric(u64, it.offset, field_align);3189 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);
5822 return FieldOffset{ .field = i, .offset = field_offset };3191 return FieldOffset{ .field = i, .offset = field_offset };
5823 }3192 }
5824 };3193 };
58253194
5826 /// Get an iterator that iterates over all the struct field, returning the field and3195 /// Get an iterator that iterates over all the struct field, returning the field and
5827 /// offset of that field. Asserts that the type is a non-packed struct.3196 /// offset of that field. Asserts that the type is a non-packed struct.
5828 pub fn iterateStructOffsets(ty: Type, target: Target) StructOffsetIterator {3197 pub fn iterateStructOffsets(ty: Type, mod: *Module) StructOffsetIterator {
5829 const struct_obj = ty.castTag(.@"struct").?.data;3198 const struct_type = mod.intern_pool.indexToKey(ty.toIntern()).struct_type;
3199 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5830 assert(struct_obj.haveLayout());3200 assert(struct_obj.haveLayout());
5831 assert(struct_obj.layout != .Packed);3201 assert(struct_obj.layout != .Packed);
5832 return .{ .struct_obj = struct_obj, .target = target };3202 return .{ .struct_obj = struct_obj, .module = mod };
5833 }3203 }
58343204
5835 /// Supports structs and unions.3205 /// Supports structs and unions.
5836 pub fn structFieldOffset(ty: Type, index: usize, target: Target) u64 {3206 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
5837 switch (ty.tag()) {3207 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5838 .@"struct" => {3208 .struct_type => |struct_type| {
5839 const struct_obj = ty.castTag(.@"struct").?.data;3209 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
5840 assert(struct_obj.haveLayout());3210 assert(struct_obj.haveLayout());
5841 assert(struct_obj.layout != .Packed);3211 assert(struct_obj.layout != .Packed);
5842 var it = ty.iterateStructOffsets(target);3212 var it = ty.iterateStructOffsets(mod);
5843 while (it.next()) |field_offset| {3213 while (it.next()) |field_offset| {
5844 if (index == field_offset.field)3214 if (index == field_offset.field)
5845 return field_offset.offset;3215 return field_offset.offset;
...@@ -5848,34 +3218,32 @@ pub const Type = extern union {...@@ -5848,34 +3218,32 @@ pub const Type = extern union {
5848 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));3218 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
5849 },3219 },
58503220
5851 .tuple, .anon_struct => {3221 .anon_struct_type => |tuple| {
5852 const tuple = ty.tupleFields();
5853
5854 var offset: u64 = 0;3222 var offset: u64 = 0;
5855 var big_align: u32 = 0;3223 var big_align: u32 = 0;
58563224
5857 for (tuple.types, 0..) |field_ty, i| {3225 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
5858 const field_val = tuple.values[i];3226 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {
5859 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) {
5860 // comptime field3227 // comptime field
5861 if (i == index) return offset;3228 if (i == index) return offset;
5862 continue;3229 continue;
5863 }3230 }
58643231
5865 const field_align = field_ty.abiAlignment(target);3232 const field_align = field_ty.toType().abiAlignment(mod);
5866 big_align = @max(big_align, field_align);3233 big_align = @max(big_align, field_align);
5867 offset = std.mem.alignForwardGeneric(u64, offset, field_align);3234 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
5868 if (i == index) return offset;3235 if (i == index) return offset;
5869 offset += field_ty.abiSize(target);3236 offset += field_ty.toType().abiSize(mod);
5870 }3237 }
5871 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));3238 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
5872 return offset;3239 return offset;
5873 },3240 },
58743241
5875 .@"union" => return 0,3242 .union_type => |union_type| {
5876 .union_safety_tagged, .union_tagged => {3243 if (!union_type.hasTag())
5877 const union_obj = ty.cast(Payload.Union).?.data;3244 return 0;
5878 const layout = union_obj.getLayout(target, true);3245 const union_obj = mod.unionPtr(union_type.index);
3246 const layout = union_obj.getLayout(mod, true);
5879 if (layout.tag_align >= layout.payload_align) {3247 if (layout.tag_align >= layout.payload_align) {
5880 // {Tag, Payload}3248 // {Tag, Payload}
5881 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);3249 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
...@@ -5884,6 +3252,7 @@ pub const Type = extern union {...@@ -5884,6 +3252,7 @@ pub const Type = extern union {
5884 return 0;3252 return 0;
5885 }3253 }
5886 },3254 },
3255
5887 else => unreachable,3256 else => unreachable,
5888 }3257 }
5889 }3258 }
...@@ -5893,507 +3262,92 @@ pub const Type = extern union {...@@ -5893,507 +3262,92 @@ pub const Type = extern union {
5893 }3262 }
58943263
5895 pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {3264 pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {
5896 switch (ty.tag()) {3265 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5897 .enum_full, .enum_nonexhaustive => {3266 .struct_type => |struct_type| {
5898 const enum_full = ty.cast(Payload.EnumFull).?.data;3267 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
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;
5911 return struct_obj.srcLoc(mod);3268 return struct_obj.srcLoc(mod);
5912 },3269 },
5913 .error_set => {3270 .union_type => |union_type| {
5914 const error_set = ty.castTag(.error_set).?.data;3271 const union_obj = mod.unionPtr(union_type.index);
5915 return error_set.srcLoc(mod);
5916 },
5917 .@"union", .union_safety_tagged, .union_tagged => {
5918 const union_obj = ty.cast(Payload.Union).?.data;
5919 return union_obj.srcLoc(mod);3272 return union_obj.srcLoc(mod);
5920 },3273 },
5921 .@"opaque" => {3274 .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type),
5922 const opaque_obj = ty.cast(Payload.Opaque).?.data;3275 .enum_type => |enum_type| mod.declPtr(enum_type.decl).srcLoc(mod),
5923 return opaque_obj.srcLoc(mod);3276 else => null,
5924 },3277 };
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 }
5940 }3278 }
59413279
5942 pub fn getOwnerDecl(ty: Type) Module.Decl.Index {3280 pub fn getOwnerDecl(ty: Type, mod: *Module) Module.Decl.Index {
5943 return ty.getOwnerDeclOrNull() orelse unreachable;3281 return ty.getOwnerDeclOrNull(mod) orelse unreachable;
5944 }3282 }
59453283
5946 pub fn getOwnerDeclOrNull(ty: Type) ?Module.Decl.Index {3284 pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?Module.Decl.Index {
5947 switch (ty.tag()) {3285 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
5948 .enum_full, .enum_nonexhaustive => {3286 .struct_type => |struct_type| {
5949 const enum_full = ty.cast(Payload.EnumFull).?.data;3287 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return null;
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;
5959 return struct_obj.owner_decl;3288 return struct_obj.owner_decl;
5960 },3289 },
5961 .error_set => {3290 .union_type => |union_type| {
5962 const error_set = ty.castTag(.error_set).?.data;3291 const union_obj = mod.unionPtr(union_type.index);
5963 return error_set.owner_decl;
5964 },
5965 .@"union", .union_safety_tagged, .union_tagged => {
5966 const union_obj = ty.cast(Payload.Union).?.data;
5967 return union_obj.owner_decl;3292 return union_obj.owner_decl;
5968 },3293 },
5969 .@"opaque" => {3294 .opaque_type => |opaque_type| opaque_type.decl,
5970 const opaque_obj = ty.cast(Payload.Opaque).?.data;3295 .enum_type => |enum_type| enum_type.decl,
5971 return opaque_obj.owner_decl;3296 else => null,
5972 },3297 };
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 }
5988 }3298 }
59893299
5990 /// This enum does not directly correspond to `std.builtin.TypeId` because3300 pub fn isGenericPoison(ty: Type) bool {
5991 /// it has extra enum tags in it, as a way of using less memory. For example,3301 return ty.toIntern() == .generic_poison_type;
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 };
6258 }3302 }
62593303
6260 pub fn isAnonStruct(ty: Type) bool {3304 pub fn isTuple(ty: Type, mod: *Module) bool {
6261 return switch (ty.tag()) {3305 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
6262 .anon_struct, .empty_struct_literal => true,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,
6263 else => false,3311 else => false,
6264 };3312 };
6265 }3313 }
62663314
6267 pub fn isTupleOrAnonStruct(ty: Type) bool {3315 pub fn isAnonStruct(ty: Type, mod: *Module) bool {
6268 return switch (ty.tag()) {3316 if (ty.toIntern() == .empty_struct_type) return true;
6269 .tuple, .empty_struct_literal, .anon_struct => true,3317 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
6270 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,3318 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len > 0,
6271 else => false,3319 else => false,
6272 };3320 };
6273 }3321 }
62743322
6275 pub fn isSimpleTuple(ty: Type) bool {3323 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
6276 return switch (ty.tag()) {3324 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
6277 .tuple, .empty_struct_literal => true,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,
6278 else => false,3330 else => false,
6279 };3331 };
6280 }3332 }
62813333
6282 pub fn isSimpleTupleOrAnonStruct(ty: Type) bool {3334 pub fn isSimpleTuple(ty: Type, mod: *Module) bool {
6283 return switch (ty.tag()) {3335 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
6284 .tuple, .empty_struct_literal, .anon_struct => true,3336 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
6285 else => false,3337 else => false,
6286 };3338 };
6287 }3339 }
62883340
6289 // Only allowed for simple tuple types3341 pub fn isSimpleTupleOrAnonStruct(ty: Type, mod: *Module) bool {
6290 pub fn tupleFields(ty: Type) Payload.Tuple.Data {3342 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
6291 return switch (ty.tag()) {3343 .anon_struct_type => true,
6292 .tuple => ty.castTag(.tuple).?.data,3344 else => false,
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,
6299 };3345 };
6300 }3346 }
63013347
6302 /// The sub-types are named after what fields they contain.
6303 pub const Payload = struct {3348 pub const Payload = struct {
6304 tag: Tag,3349 /// TODO: remove this data structure since we have `InternPool.Key.PtrType`.
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
6391 pub const Pointer = struct {3350 pub const Pointer = struct {
6392 pub const base_tag = Tag.pointer;
6393
6394 base: Payload = Payload{ .tag = base_tag },
6395 data: Data,
6396
6397 pub const Data = struct {3351 pub const Data = struct {
6398 pointee_type: Type,3352 pointee_type: Type,
6399 sentinel: ?Value = null,3353 sentinel: ?Value = null,
...@@ -6417,145 +3371,103 @@ pub const Type = extern union {...@@ -6417,145 +3371,103 @@ pub const Type = extern union {
6417 @"volatile": bool = false,3371 @"volatile": bool = false,
6418 size: std.builtin.Type.Pointer.Size = .One,3372 size: std.builtin.Type.Pointer.Size = .One,
64193373
6420 pub const VectorIndex = enum(u32) {3374 pub const VectorIndex = InternPool.Key.PtrType.VectorIndex;
6421 none = std.math.maxInt(u32),
6422 runtime = std.math.maxInt(u32) - 1,
6423 _,
6424 };
64253375
6426 pub fn alignment(data: Data, target: Target) u32 {3376 pub fn alignment(data: Data, mod: *Module) u32 {
6427 if (data.@"align" != 0) return data.@"align";3377 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 };
6429 }3395 }
6430 };3396 };
6431 };3397 };
3398 };
64323399
6433 pub const ErrorUnion = struct {3400 pub const @"u1": Type = .{ .ip_index = .u1_type };
6434 pub const base_tag = Tag.error_union;3401 pub const @"u8": Type = .{ .ip_index = .u8_type };
64353402 pub const @"u16": Type = .{ .ip_index = .u16_type };
6436 base: Payload = Payload{ .tag = base_tag },3403 pub const @"u29": Type = .{ .ip_index = .u29_type };
6437 data: struct {3404 pub const @"u32": Type = .{ .ip_index = .u32_type };
6438 error_set: Type,3405 pub const @"u64": Type = .{ .ip_index = .u64_type };
6439 payload: Type,3406 pub const @"u128": Type = .{ .ip_index = .u128_type };
6440 },3407
6441 };3408 pub const @"i8": Type = .{ .ip_index = .i8_type };
64423409 pub const @"i16": Type = .{ .ip_index = .i16_type };
6443 pub const Decl = struct {3410 pub const @"i32": Type = .{ .ip_index = .i32_type };
6444 base: Payload,3411 pub const @"i64": Type = .{ .ip_index = .i64_type };
6445 data: *Module.Decl,3412 pub const @"i128": Type = .{ .ip_index = .i128_type };
6446 };3413
64473414 pub const @"f16": Type = .{ .ip_index = .f16_type };
6448 pub const Name = struct {3415 pub const @"f32": Type = .{ .ip_index = .f32_type };
6449 base: Payload,3416 pub const @"f64": Type = .{ .ip_index = .f64_type };
6450 /// memory is owned by `Module`3417 pub const @"f80": Type = .{ .ip_index = .f80_type };
6451 data: []const u8,3418 pub const @"f128": Type = .{ .ip_index = .f128_type };
6452 };3419
64533420 pub const @"bool": Type = .{ .ip_index = .bool_type };
6454 /// Mostly used for namespace like structs with zero fields.3421 pub const @"usize": Type = .{ .ip_index = .usize_type };
6455 /// Most commonly used for files.3422 pub const @"isize": Type = .{ .ip_index = .isize_type };
6456 pub const ContainerScope = struct {3423 pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type };
6457 base: Payload,3424 pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type };
6458 data: *Module.Namespace,3425 pub const @"void": Type = .{ .ip_index = .void_type };
6459 };3426 pub const @"type": Type = .{ .ip_index = .type_type };
64603427 pub const @"anyerror": Type = .{ .ip_index = .anyerror_type };
6461 pub const Opaque = struct {3428 pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type };
6462 base: Payload = .{ .tag = .@"opaque" },3429 pub const @"anyframe": Type = .{ .ip_index = .anyframe_type };
6463 data: *Module.Opaque,3430 pub const @"null": Type = .{ .ip_index = .null_type };
6464 };3431 pub const @"undefined": Type = .{ .ip_index = .undefined_type };
64653432 pub const @"noreturn": Type = .{ .ip_index = .noreturn_type };
6466 pub const Struct = struct {3433
6467 base: Payload = .{ .tag = .@"struct" },3434 pub const @"c_char": Type = .{ .ip_index = .c_char_type };
6468 data: *Module.Struct,3435 pub const @"c_short": Type = .{ .ip_index = .c_short_type };
6469 };3436 pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type };
64703437 pub const @"c_int": Type = .{ .ip_index = .c_int_type };
6471 pub const Tuple = struct {3438 pub const @"c_uint": Type = .{ .ip_index = .c_uint_type };
6472 base: Payload = .{ .tag = .tuple },3439 pub const @"c_long": Type = .{ .ip_index = .c_long_type };
6473 data: Data,3440 pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type };
64743441 pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type };
6475 pub const Data = struct {3442 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
6476 types: []Type,3443 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
6477 /// unreachable_value elements are used to indicate runtime-known.3444
6478 values: []Value,3445 pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
6479 };3446 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
6480 };3447 pub const single_const_pointer_to_comptime_int: Type = .{
64813448 .ip_index = .single_const_pointer_to_comptime_int_type,
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 };
6513 };3449 };
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);3453 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
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);
65403454
6541 pub const err_int = Type.u16;3455 pub const err_int = Type.u16;
65423456
6543 pub fn ptr(arena: Allocator, mod: *Module, data: Payload.Pointer.Data) !Type {3457 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
6546 var d = data;3462 var d = data;
65473463
6548 if (d.size == .C) {
6549 d.@"allowzero" = true;
6550 }
6551
6552 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee3464 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
6553 // type, we change it to 0 here. If this causes an assertion trip because the3465 // type, we change it to 0 here. If this causes an assertion trip because the
6554 // pointee type needs to be resolved more, that needs to be done before calling3466 // pointee type needs to be resolved more, that needs to be done before calling
6555 // this ptr() function.3467 // this ptr() function.
6556 if (d.@"align" != 0) canonicalize: {3468 if (d.@"align" != 0) canonicalize: {
6557 if (!d.pointee_type.layoutIsResolved()) break :canonicalize;3469 if (!d.pointee_type.layoutIsResolved(mod)) break :canonicalize;
6558 if (d.@"align" == d.pointee_type.abiAlignment(target)) {3470 if (d.@"align" == d.pointee_type.abiAlignment(mod)) {
6559 d.@"align" = 0;3471 d.@"align" = 0;
6560 }3472 }
6561 }3473 }
...@@ -6565,57 +3477,29 @@ pub const Type = extern union {...@@ -6565,57 +3477,29 @@ pub const Type = extern union {
6565 // needs to be resolved before calling this ptr() function.3477 // needs to be resolved before calling this ptr() function.
6566 if (d.host_size != 0) {3478 if (d.host_size != 0) {
6567 assert(d.bit_offset < d.host_size * 8);3479 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)) {
6569 assert(d.bit_offset == 0);3481 assert(d.bit_offset == 0);
6570 d.host_size = 0;3482 d.host_size = 0;
6571 }3483 }
6572 }3484 }
65733485
6574 if (d.@"align" == 0 and d.@"addrspace" == .generic and3486 return mod.ptrType(.{
6575 d.bit_offset == 0 and d.host_size == 0 and d.vector_index == .none and3487 .child = d.pointee_type.ip_index,
6576 !d.@"allowzero" and !d.@"volatile")3488 .sentinel = if (d.sentinel) |s| s.ip_index else .none,
6577 {3489 .flags = .{
6578 if (d.sentinel) |sent| {3490 .alignment = InternPool.Alignment.fromByteUnits(d.@"align"),
6579 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {3491 .vector_index = d.vector_index,
6580 switch (d.size) {3492 .size = d.size,
6581 .Slice => {3493 .is_const = !d.mutable,
6582 if (sent.compareAllWithZero(.eq, mod)) {3494 .is_volatile = d.@"volatile",
6583 return Type.initTag(.const_slice_u8_sentinel_0);3495 .is_allowzero = d.@"allowzero",
6584 }3496 .address_space = d.@"addrspace",
6585 },3497 },
6586 .Many => {3498 .packed_offset = .{
6587 if (sent.compareAllWithZero(.eq, mod)) {3499 .host_size = d.host_size,
6588 return Type.initTag(.manyptr_const_u8_sentinel_0);3500 .bit_offset = d.bit_offset,
6589 }3501 },
6590 },3502 });
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);
6619 }3503 }
66203504
6621 pub fn array(3505 pub fn array(
...@@ -6625,68 +3509,23 @@ pub const Type = extern union {...@@ -6625,68 +3509,23 @@ pub const Type = extern union {
6625 elem_type: Type,3509 elem_type: Type,
6626 mod: *Module,3510 mod: *Module,
6627 ) Allocator.Error!Type {3511 ) Allocator.Error!Type {
6628 if (elem_type.eql(Type.u8, mod)) {3512 // TODO: update callsites of this function to directly call mod.arrayType
6629 if (sent) |some| {3513 // and then delete this function.
6630 if (some.eql(Value.zero, elem_type, mod)) {3514 _ = arena;
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 }
66513515
6652 pub fn vector(arena: Allocator, len: u64, elem_type: Type) Allocator.Error!Type {3516 return mod.arrayType(.{
6653 return Tag.vector.create(arena, .{
6654 .len = len,3517 .len = len,
6655 .elem_type = elem_type,3518 .child = elem_type.ip_index,
3519 .sentinel = if (sent) |s| s.ip_index else .none,
6656 });3520 });
6657 }3521 }
66583522
6659 pub fn optional(arena: Allocator, child_type: Type) Allocator.Error!Type {3523 pub fn optional(arena: Allocator, child_type: Type, mod: *Module) Allocator.Error!Type {
6660 switch (child_type.tag()) {3524 // TODO: update callsites of this function to directly call
6661 .single_const_pointer => return Type.Tag.optional_single_const_pointer.create(3525 // mod.optionalType and then delete this function.
6662 arena,3526 _ = 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 }
66853527
6686 return Type.Tag.error_union.create(arena, .{3528 return mod.optionalType(child_type.ip_index);
6687 .error_set = error_set,
6688 .payload = payload,
6689 });
6690 }3529 }
66913530
6692 pub fn smallestUnsignedBits(max: u64) u16 {3531 pub fn smallestUnsignedBits(max: u64) u16 {
...@@ -6696,113 +3535,7 @@ pub const Type = extern union {...@@ -6696,113 +3535,7 @@ pub const Type = extern union {
6696 return @intCast(u16, base + @boolToInt(upper < max));3535 return @intCast(u16, base + @boolToInt(upper < max));
6697 }3536 }
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
6776 /// This is only used for comptime asserts. Bump this number when you make a change3538 /// This is only used for comptime asserts. Bump this number when you make a change
6777 /// to packed struct layout to find out all the places in the codebase you need to edit!3539 /// to packed struct layout to find out all the places in the codebase you need to edit!
6778 pub const packed_struct_layout_version = 2;3540 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 }
6808};3541};
src/value.zig+2265-3741
...@@ -11,147 +11,27 @@ const Module = @import("Module.zig");...@@ -11,147 +11,27 @@ const Module = @import("Module.zig");
11const Air = @import("Air.zig");11const Air = @import("Air.zig");
12const TypedValue = @import("TypedValue.zig");12const TypedValue = @import("TypedValue.zig");
13const Sema = @import("Sema.zig");13const Sema = @import("Sema.zig");
1414const InternPool = @import("InternPool.zig");
15/// This is the raw data, with no bookkeeping, no memory awareness,15
16/// no de-duplication, and no type system awareness.16pub const Value = struct {
17/// It's important for this type to be small.17 /// We are migrating towards using this for every Value object. However, many
18/// This union takes advantage of the fact that the first page of memory18 /// values are still represented the legacy way. This is indicated by using
19/// is unmapped, giving us 4096 possible enum tags that have no payload.19 /// InternPool.Index.none.
20pub const Value = extern union {20 ip_index: InternPool.Index,
21 /// If the tag value is less than Tag.no_payload_count, then no pointer21
22 /// dereference is needed.22 /// This is the raw data, with no bookkeeping, no memory awareness,
23 tag_if_small_enough: Tag,23 /// no de-duplication, and no type system awareness.
24 ptr_otherwise: *Payload,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
26 // Keep in sync with tools/stage2_pretty_printers_common.py30 // Keep in sync with tools/stage2_pretty_printers_common.py
27 pub const Tag = enum(usize) {31 pub const Tag = enum(usize) {
28 // The first section of this enum are tags that require no payload.32 // 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.
108 // After this, the tag requires a payload.33 // 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",
155 /// When the type is error union:35 /// When the type is error union:
156 /// * If the tag is `.@"error"`, the error union is an error.36 /// * If the tag is `.@"error"`, the error union is an error.
157 /// * If the tag is `.eu_payload`, the error union is a payload.37 /// * If the tag is `.eu_payload`, the error union is a payload.
...@@ -159,8 +39,6 @@ pub const Value = extern union {...@@ -159,8 +39,6 @@ pub const Value = extern union {
159 /// is non-error, but the inner error union is an error, is represented as39 /// is non-error, but the inner error union is an error, is represented as
160 /// a tag of `.eu_payload`, with a sub-tag of `.@"error"`.40 /// a tag of `.eu_payload`, with a sub-tag of `.@"error"`.
161 eu_payload,41 eu_payload,
162 /// A pointer to the payload of an error union, based on a pointer to an error union.
163 eu_payload_ptr,
164 /// When the type is optional:42 /// When the type is optional:
165 /// * If the tag is `.null_value`, the optional is null.43 /// * If the tag is `.null_value`, the optional is null.
166 /// * If the tag is `.opt_payload`, the optional is a payload.44 /// * If the tag is `.opt_payload`, the optional is a payload.
...@@ -168,8 +46,13 @@ pub const Value = extern union {...@@ -168,8 +46,13 @@ pub const Value = extern union {
168 /// is non-null, but the inner optional is null, is represented as46 /// is non-null, but the inner optional is null, is represented as
169 /// a tag of `.opt_payload`, with a sub-tag of `.null_value`.47 /// a tag of `.opt_payload`, with a sub-tag of `.null_value`.
170 opt_payload,48 opt_payload,
171 /// A pointer to the payload of an optional, based on a pointer to an optional.49 /// Pointer and length as sub `Value` objects.
172 opt_payload_ptr,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,
173 /// An instance of a struct, array, or vector.56 /// An instance of a struct, array, or vector.
174 /// Each element/field stored as a `Value`.57 /// Each element/field stored as a `Value`.
175 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,58 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
...@@ -177,152 +60,17 @@ pub const Value = extern union {...@@ -177,152 +60,17 @@ pub const Value = extern union {
177 aggregate,60 aggregate,
178 /// An instance of a union.61 /// An instance of a union.
179 @"union",62 @"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
194 pub fn Type(comptime t: Tag) type {64 pub fn Type(comptime t: Tag) type {
195 return switch (t) {65 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,
283 .eu_payload,66 .eu_payload,
284 .opt_payload,67 .opt_payload,
285 .empty_array_sentinel,68 .repeated,
286 .runtime_value,
287 => Payload.SubValue,69 => 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,
298 .slice => Payload.Slice,70 .slice => Payload.Slice,
29971 .bytes => Payload.Bytes,
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,
323 .aggregate => Payload.Aggregate,72 .aggregate => Payload.Aggregate,
324 .@"union" => Payload.Union,73 .@"union" => Payload.Union,
325 .comptime_field_ptr => Payload.ComptimeFieldPtr,
326 };74 };
327 }75 }
32876
...@@ -332,7 +80,10 @@ pub const Value = extern union {...@@ -332,7 +80,10 @@ pub const Value = extern union {
332 .base = .{ .tag = t },80 .base = .{ .tag = t },
333 .data = data,81 .data = data,
334 };82 };
335 return Value{ .ptr_otherwise = &ptr.base };83 return Value{
84 .ip_index = .none,
85 .legacy = .{ .ptr_otherwise = &ptr.base },
86 };
336 }87 }
33788
338 pub fn Data(comptime t: Tag) type {89 pub fn Data(comptime t: Tag) type {
...@@ -340,39 +91,31 @@ pub const Value = extern union {...@@ -340,39 +91,31 @@ pub const Value = extern union {
340 }91 }
341 };92 };
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
348 pub fn initPayload(payload: *Payload) Value {94 pub fn initPayload(payload: *Payload) Value {
349 assert(@enumToInt(payload.tag) >= Tag.no_payload_count);95 return Value{
350 return .{ .ptr_otherwise = payload };96 .ip_index = .none,
97 .legacy = .{ .ptr_otherwise = payload },
98 };
351 }99 }
352100
353 pub fn tag(self: Value) Tag {101 pub fn tag(self: Value) Tag {
354 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {102 assert(self.ip_index == .none);
355 return self.tag_if_small_enough;103 return self.legacy.ptr_otherwise.tag;
356 } else {
357 return self.ptr_otherwise.tag;
358 }
359 }104 }
360105
361 /// Prefer `castTag` to this.106 /// Prefer `castTag` to this.
362 pub fn cast(self: Value, comptime T: type) ?*T {107 pub fn cast(self: Value, comptime T: type) ?*T {
108 if (self.ip_index != .none) {
109 return null;
110 }
363 if (@hasField(T, "base_tag")) {111 if (@hasField(T, "base_tag")) {
364 return self.castTag(T.base_tag);112 return self.castTag(T.base_tag);
365 }113 }
366 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {
367 return null;
368 }
369 inline for (@typeInfo(Tag).Enum.fields) |field| {114 inline for (@typeInfo(Tag).Enum.fields) |field| {
370 if (field.value < Tag.no_payload_count)
371 continue;
372 const t = @intToEnum(Tag, field.value);115 const t = @intToEnum(Tag, field.value);
373 if (self.ptr_otherwise.tag == t) {116 if (self.legacy.ptr_otherwise.tag == t) {
374 if (T == t.Type()) {117 if (T == t.Type()) {
375 return @fieldParentPtr(T, "base", self.ptr_otherwise);118 return @fieldParentPtr(T, "base", self.legacy.ptr_otherwise);
376 }119 }
377 return null;120 return null;
378 }121 }
...@@ -381,11 +124,10 @@ pub const Value = extern union {...@@ -381,11 +124,10 @@ pub const Value = extern union {
381 }124 }
382125
383 pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() {126 pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() {
384 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count)127 if (self.ip_index != .none) return null;
385 return null;
386128
387 if (self.ptr_otherwise.tag == t)129 if (self.legacy.ptr_otherwise.tag == t)
388 return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise);130 return @fieldParentPtr(t.Type(), "base", self.legacy.ptr_otherwise);
389131
390 return null;132 return null;
391 }133 }
...@@ -393,165 +135,10 @@ pub const Value = extern union {...@@ -393,165 +135,10 @@ pub const Value = extern union {
393 /// It's intentional that this function is not passed a corresponding Type, so that135 /// It's intentional that this function is not passed a corresponding Type, so that
394 /// a Value can be copied from a Sema to a Decl prior to resolving struct/union field types.136 /// a Value can be copied from a Sema to a Decl prior to resolving struct/union field types.
395 pub fn copy(self: Value, arena: Allocator) error{OutOfMemory}!Value {137 pub fn copy(self: Value, arena: Allocator) error{OutOfMemory}!Value {
396 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {138 if (self.ip_index != .none) {
397 return Value{ .tag_if_small_enough = self.tag_if_small_enough };139 return Value{ .ip_index = self.ip_index, .legacy = undefined };
398 } else switch (self.ptr_otherwise.tag) {140 }
399 .u1_type,141 switch (self.legacy.ptr_otherwise.tag) {
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 },
555 .bytes => {142 .bytes => {
556 const bytes = self.castTag(.bytes).?.data;143 const bytes = self.castTag(.bytes).?.data;
557 const new_payload = try arena.create(Payload.Bytes);144 const new_payload = try arena.create(Payload.Bytes);
...@@ -559,14 +146,14 @@ pub const Value = extern union {...@@ -559,14 +146,14 @@ pub const Value = extern union {
559 .base = .{ .tag = .bytes },146 .base = .{ .tag = .bytes },
560 .data = try arena.dupe(u8, bytes),147 .data = try arena.dupe(u8, bytes),
561 };148 };
562 return Value{ .ptr_otherwise = &new_payload.base };149 return Value{
150 .ip_index = .none,
151 .legacy = .{ .ptr_otherwise = &new_payload.base },
152 };
563 },153 },
564 .str_lit => return self.copyPayloadShallow(arena, Payload.StrLit),
565 .repeated,
566 .eu_payload,154 .eu_payload,
567 .opt_payload,155 .opt_payload,
568 .empty_array_sentinel,156 .repeated,
569 .runtime_value,
570 => {157 => {
571 const payload = self.cast(Payload.SubValue).?;158 const payload = self.cast(Payload.SubValue).?;
572 const new_payload = try arena.create(Payload.SubValue);159 const new_payload = try arena.create(Payload.SubValue);
...@@ -574,7 +161,10 @@ pub const Value = extern union {...@@ -574,7 +161,10 @@ pub const Value = extern union {
574 .base = payload.base,161 .base = payload.base,
575 .data = try payload.data.copy(arena),162 .data = try payload.data.copy(arena),
576 };163 };
577 return Value{ .ptr_otherwise = &new_payload.base };164 return Value{
165 .ip_index = .none,
166 .legacy = .{ .ptr_otherwise = &new_payload.base },
167 };
578 },168 },
579 .slice => {169 .slice => {
580 const payload = self.castTag(.slice).?;170 const payload = self.castTag(.slice).?;
...@@ -586,25 +176,11 @@ pub const Value = extern union {...@@ -586,25 +176,11 @@ pub const Value = extern union {
586 .len = try payload.data.len.copy(arena),176 .len = try payload.data.len.copy(arena),
587 },177 },
588 };178 };
589 return Value{ .ptr_otherwise = &new_payload.base };179 return Value{
590 },180 .ip_index = .none,
591 .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16),181 .legacy = .{ .ptr_otherwise = &new_payload.base },
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),
602 };182 };
603 return Value{ .ptr_otherwise = &new_payload.base };
604 },183 },
605 .enum_field_index => return self.copyPayloadShallow(arena, Payload.U32),
606 .@"error" => return self.copyPayloadShallow(arena, Payload.Error),
607
608 .aggregate => {184 .aggregate => {
609 const payload = self.castTag(.aggregate).?;185 const payload = self.castTag(.aggregate).?;
610 const new_payload = try arena.create(Payload.Aggregate);186 const new_payload = try arena.create(Payload.Aggregate);
...@@ -615,9 +191,11 @@ pub const Value = extern union {...@@ -615,9 +191,11 @@ pub const Value = extern union {
615 for (new_payload.data, 0..) |*elem, i| {191 for (new_payload.data, 0..) |*elem, i| {
616 elem.* = try payload.data[i].copy(arena);192 elem.* = try payload.data[i].copy(arena);
617 }193 }
618 return Value{ .ptr_otherwise = &new_payload.base };194 return Value{
195 .ip_index = .none,
196 .legacy = .{ .ptr_otherwise = &new_payload.base },
197 };
619 },198 },
620
621 .@"union" => {199 .@"union" => {
622 const tag_and_val = self.castTag(.@"union").?.data;200 const tag_and_val = self.castTag(.@"union").?.data;
623 const new_payload = try arena.create(Payload.Union);201 const new_payload = try arena.create(Payload.Union);
...@@ -628,11 +206,11 @@ pub const Value = extern union {...@@ -628,11 +206,11 @@ pub const Value = extern union {
628 .val = try tag_and_val.val.copy(arena),206 .val = try tag_and_val.val.copy(arena),
629 },207 },
630 };208 };
631 return Value{ .ptr_otherwise = &new_payload.base };209 return Value{
210 .ip_index = .none,
211 .legacy = .{ .ptr_otherwise = &new_payload.base },
212 };
632 },213 },
633
634 .inferred_alloc => unreachable,
635 .inferred_alloc_comptime => unreachable,
636 }214 }
637 }215 }
638216
...@@ -640,7 +218,10 @@ pub const Value = extern union {...@@ -640,7 +218,10 @@ pub const Value = extern union {
640 const payload = self.cast(T).?;218 const payload = self.cast(T).?;
641 const new_payload = try arena.create(T);219 const new_payload = try arena.create(T);
642 new_payload.* = payload.*;220 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 };
644 }225 }
645226
646 pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {227 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 {...@@ -656,181 +237,36 @@ pub const Value = extern union {
656 pub fn dump(237 pub fn dump(
657 start_val: Value,238 start_val: Value,
658 comptime fmt: []const u8,239 comptime fmt: []const u8,
659 options: std.fmt.FormatOptions,240 _: std.fmt.FormatOptions,
660 out_stream: anytype,241 out_stream: anytype,
661 ) !void {242 ) !void {
662 comptime assert(fmt.len == 0);243 comptime assert(fmt.len == 0);
244 if (start_val.ip_index != .none) {
245 try out_stream.print("(interned: {})", .{start_val.toIntern()});
246 return;
247 }
663 var val = start_val;248 var val = start_val;
664 while (true) switch (val.tag()) {249 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 {}{}"),
732 .aggregate => {250 .aggregate => {
733 return out_stream.writeAll("(aggregate)");251 return out_stream.writeAll("(aggregate)");
734 },252 },
735 .@"union" => {253 .@"union" => {
736 return out_stream.writeAll("(union value)");254 return out_stream.writeAll("(union value)");
737 },255 },
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}),
797 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),256 .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 },
804 .repeated => {257 .repeated => {
805 try out_stream.writeAll("(repeated) ");258 try out_stream.writeAll("(repeated) ");
806 val = val.castTag(.repeated).?.data;259 val = val.castTag(.repeated).?.data;
807 },260 },
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}),
816 .eu_payload => {261 .eu_payload => {
817 try out_stream.writeAll("(eu_payload) ");262 try out_stream.writeAll("(eu_payload) ");
818 val = val.castTag(.eu_payload).?.data;263 val = val.castTag(.repeated).?.data;
819 },264 },
820 .opt_payload => {265 .opt_payload => {
821 try out_stream.writeAll("(opt_payload) ");266 try out_stream.writeAll("(opt_payload) ");
822 val = val.castTag(.opt_payload).?.data;267 val = val.castTag(.repeated).?.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;
833 },268 },
269 .slice => return out_stream.writeAll("(slice)"),
834 };270 };
835 }271 }
836272
...@@ -845,421 +281,404 @@ pub const Value = extern union {...@@ -845,421 +281,404 @@ pub const Value = extern union {
845 } };281 } };
846 }282 }
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
848 /// Asserts that the value is representable as an array of bytes.308 /// Asserts that the value is representable as an array of bytes.
849 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.309 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.
850 pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 {310 pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 {
851 const target = mod.getTarget();311 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
852 switch (val.tag()) {312 .enum_literal => |enum_literal| allocator.dupe(u8, mod.intern_pool.stringToSlice(enum_literal)),
853 .bytes => {313 .ptr => |ptr| switch (ptr.len) {
854 const bytes = val.castTag(.bytes).?.data;314 .none => unreachable,
855 const adjusted_len = bytes.len - @boolToInt(ty.sentinel() != null);315 else => try arrayToAllocatedBytes(val, ptr.len.toValue().toUnsignedInt(mod), allocator, mod),
856 const adjusted_bytes = bytes[0..adjusted_len];316 },
857 return allocator.dupe(u8, adjusted_bytes);317 .aggregate => |aggregate| switch (aggregate.storage) {
858 },318 .bytes => |bytes| try allocator.dupe(u8, bytes),
859 .str_lit => {319 .elems => try arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod),
860 const str_lit = val.castTag(.str_lit).?.data;320 .repeated_elem => |elem| {
861 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];321 const byte = @intCast(u8, elem.toValue().toUnsignedInt(mod));
862 return allocator.dupe(u8, bytes);322 const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen(mod)));
863 },323 @memset(result, byte);
864 .enum_literal => return allocator.dupe(u8, val.castTag(.enum_literal).?.data),324 return result;
865 .repeated => {325 },
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);
881 },326 },
882 else => return arrayToAllocatedBytes(val, ty.arrayLen(), allocator, mod),327 else => unreachable,
883 }328 };
884 }329 }
885330
886 fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, mod: *Module) ![]u8 {331 fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, mod: *Module) ![]u8 {
887 const result = try allocator.alloc(u8, @intCast(usize, len));332 const result = try allocator.alloc(u8, @intCast(usize, len));
888 var elem_value_buf: ElemValueBuffer = undefined;
889 for (result, 0..) |*elem, i| {333 for (result, 0..) |*elem, i| {
890 const elem_val = val.elemValueBuffer(mod, i, &elem_value_buf);334 const elem_val = try val.elemValue(mod, i);
891 elem.* = @intCast(u8, elem_val.toUnsignedInt(mod.getTarget()));335 elem.* = @intCast(u8, elem_val.toUnsignedInt(mod));
892 }336 }
893 return result;337 return result;
894 }338 }
895339
896 pub const ToTypeBuffer = Type.Payload.Bits;340 fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTerminatedString {
897341 const gpa = mod.gpa;
898 /// Asserts that the value is representable as a type.342 const ip = &mod.intern_pool;
899 pub fn toType(self: Value, buffer: *ToTypeBuffer) Type {343 const len = @intCast(usize, len_u64);
900 return switch (self.tag()) {344 try ip.string_bytes.ensureUnusedCapacity(gpa, len);
901 .ty => self.castTag(.ty).?.data,345 for (0..len) |i| {
902 .u1_type => Type.initTag(.u1),346 // I don't think elemValue has the possibility to affect ip.string_bytes. Let's
903 .u8_type => Type.initTag(.u8),347 // assert just to be sure.
904 .i8_type => Type.initTag(.i8),348 const prev = ip.string_bytes.items.len;
905 .u16_type => Type.initTag(.u16),349 const elem_val = try val.elemValue(mod, i);
906 .i16_type => Type.initTag(.i16),350 assert(ip.string_bytes.items.len == prev);
907 .u29_type => Type.initTag(.u29),351 const byte = @intCast(u8, elem_val.toUnsignedInt(mod));
908 .u32_type => Type.initTag(.u32),352 ip.string_bytes.appendAssumeCapacity(byte);
909 .i32_type => Type.initTag(.i32),353 }
910 .u64_type => Type.initTag(.u64),354 return ip.getOrPutTrailingString(gpa, len);
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 };
980 }355 }
981356
982 /// Asserts the type is an enum type.357 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
983 pub fn toEnum(val: Value, comptime E: type) E {358 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
984 switch (val.tag()) {359 switch (val.tag()) {
985 .enum_field_index => {360 .eu_payload => {
986 const field_index = val.castTag(.enum_field_index).?.data;361 const pl = val.castTag(.eu_payload).?.data;
987 return @intToEnum(E, field_index);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 } });
988 },373 },
989 .the_only_possible_value => {374 .slice => {
990 const fields = std.meta.fields(E);375 const pl = val.castTag(.slice).?.data;
991 assert(fields.len == 1);376 const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);
992 return @intToEnum(E, fields[0].value);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 } });
993 },422 },
994 else => unreachable,
995 }423 }
996 }424 }
997425
998 pub fn enumToInt(val: Value, ty: Type, buffer: *Payload.U64) Value {426 pub fn unintern(val: Value, arena: Allocator, mod: *Module) Allocator.Error!Value {
999 const field_index = switch (val.tag()) {427 return if (val.ip_index == .none) val else switch (mod.intern_pool.indexToKey(val.toIntern())) {
1000 .enum_field_index => val.castTag(.enum_field_index).?.data,428 .int_type,
1001 .the_only_possible_value => blk: {429 .ptr_type,
1002 assert(ty.enumFieldCount() == 1);430 .array_type,
1003 break :blk 0;431 .vector_type,
1004 },432 .opt_type,
1005 .enum_literal => i: {433 .anyframe_type,
1006 const name = val.castTag(.enum_literal).?.data;434 .error_union_type,
1007 break :i ty.enumFieldIndex(name).?;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()),
1008 },462 },
1009 // Assume it is already an integer and return it directly.
1010 else => return val,
1011 };
1012463
1013 switch (ty.tag()) {464 .ptr => |ptr| switch (ptr.len) {
1014 .enum_full, .enum_nonexhaustive => {465 .none => val,
1015 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;466 else => |len| Tag.slice.create(arena, .{
1016 if (enum_full.values.count() != 0) {467 .ptr = val.slicePtr(mod),
1017 return enum_full.values.keys()[field_index];468 .len = len.toValue(),
1018 } else {469 }),
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 }
1026 },470 },
1027 .enum_numbered => {471
1028 const enum_obj = ty.castTag(.enum_numbered).?.data;472 .opt => |opt| switch (opt.val) {
1029 if (enum_obj.values.count() != 0) {473 .none => val,
1030 return enum_obj.values.keys()[field_index];474 else => |payload| Tag.opt_payload.create(arena, payload.toValue()),
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 }
1039 },475 },
1040 .enum_simple => {476
1041 // Field index and integer values are the same.477 .aggregate => |aggregate| switch (aggregate.storage) {
1042 buffer.* = .{478 .bytes => |bytes| Tag.bytes.create(arena, try arena.dupe(u8, bytes)),
1043 .base = .{ .tag = .int_u64 },479 .elems => |old_elems| {
1044 .data = field_index,480 const new_elems = try arena.alloc(Value, old_elems.len);
1045 };481 for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = old_elem.toValue();
1046 return Value.initPayload(&buffer.base);482 return Tag.aggregate.create(arena, new_elems);
483 },
484 .repeated_elem => |elem| Tag.repeated.create(arena, elem.toValue()),
1047 },485 },
1048 else => unreachable,486
1049 }487 .un => |un| Tag.@"union".create(arena, .{
488 .tag = un.tag.toValue(),
489 .val = un.val.toValue(),
490 }),
491
492 .memoized_call => unreachable,
493 };
1050 }494 }
1051495
1052 pub fn tagName(val: Value, ty: Type, mod: *Module) []const u8 {496 pub fn toIntern(val: Value) InternPool.Index {
1053 if (ty.zigTypeTag() == .Union) return val.unionTag().tagName(ty.unionTagTypeHypothetical(), mod);497 assert(val.ip_index != .none);
498 return val.ip_index;
499 }
1054500
1055 const field_index = switch (val.tag()) {501 /// Asserts that the value is representable as a type.
1056 .enum_field_index => val.castTag(.enum_field_index).?.data,502 pub fn toType(self: Value) Type {
1057 .the_only_possible_value => blk: {503 return self.toIntern().toType();
1058 assert(ty.enumFieldCount() == 1);504 }
1059 break :blk 0;505
1060 },506 pub fn enumToInt(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {
1061 .enum_literal => return val.castTag(.enum_literal).?.data,507 const ip = &mod.intern_pool;
1062 else => field_index: {508 return switch (ip.indexToKey(ip.typeOf(val.toIntern()))) {
1063 const values = switch (ty.tag()) {509 // Assume it is already an integer and return it directly.
1064 .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.values,510 .simple_type, .int_type => val,
1065 .enum_numbered => ty.castTag(.enum_numbered).?.data.values,511 .enum_literal => |enum_literal| {
1066 .enum_simple => Module.EnumFull.ValueMap{},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),
1067 else => unreachable,520 else => unreachable,
1068 };521 };
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 }).?);
1076 },522 },
1077 };523 .enum_type => |enum_type| try mod.getCoerced(val, enum_type.tag_ty.toType()),
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,
1083 else => unreachable,524 else => unreachable,
1084 };525 };
1085 return fields.keys()[field_index];
1086 }526 }
1087527
1088 /// Asserts the value is an integer.528 /// Asserts the value is an integer.
1089 pub fn toBigInt(val: Value, space: *BigIntSpace, target: Target) BigIntConst {529 pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *Module) BigIntConst {
1090 return val.toBigIntAdvanced(space, target, null) catch unreachable;530 return val.toBigIntAdvanced(space, mod, null) catch unreachable;
1091 }531 }
1092532
1093 /// Asserts the value is an integer.533 /// Asserts the value is an integer.
1094 pub fn toBigIntAdvanced(534 pub fn toBigIntAdvanced(
1095 val: Value,535 val: Value,
1096 space: *BigIntSpace,536 space: *BigIntSpace,
1097 target: Target,537 mod: *Module,
1098 opt_sema: ?*Sema,538 opt_sema: ?*Sema,
1099 ) Module.CompileError!BigIntConst {539 ) Module.CompileError!BigIntConst {
1100 switch (val.tag()) {540 return switch (val.toIntern()) {
1101 .null_value,541 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
1102 .zero,542 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
1103 .bool_false,543 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
1104 .the_only_possible_value, // i0, u0544 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1105 => return BigIntMutable.init(&space.limbs, 0).toConst(),545 .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),
1106546 .int => |int| switch (int.storage) {
1107 .one,547 .u64, .i64, .big_int => int.storage.toBigInt(space),
1108 .bool_true,548 .lazy_align, .lazy_size => |ty| {
1109 => return BigIntMutable.init(&space.limbs, 1).toConst(),549 if (opt_sema) |sema| try sema.resolveTypeLayout(ty.toType());
1110550 const x = switch (int.storage) {
1111 .enum_field_index => {551 else => unreachable,
1112 const index = val.castTag(.enum_field_index).?.data;552 .lazy_align => ty.toType().abiAlignment(mod),
1113 return BigIntMutable.init(&space.limbs, index).toConst();553 .lazy_size => ty.toType().abiSize(mod),
1114 },554 };
1115 .runtime_value => {555 return BigIntMutable.init(&space.limbs, x).toConst();
1116 const sub_val = val.castTag(.runtime_value).?.data;556 },
1117 return sub_val.toBigIntAdvanced(space, target, opt_sema);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,
1118 },564 },
1119 .int_u64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_u64).?.data).toConst(),565 };
1120 .int_i64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_i64).?.data).toConst(),566 }
1121 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(),
1122 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(),
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 => {572 pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {
1127 const ty = val.castTag(.lazy_align).?.data;573 return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;
1128 if (opt_sema) |sema| {574 }
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 },
1142575
1143 .elem_ptr => {576 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
1144 const elem_ptr = val.castTag(.elem_ptr).?.data;577 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) {
1145 const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(target, opt_sema)).?;578 .extern_func => |extern_func| extern_func,
1146 const elem_size = elem_ptr.elem_ty.abiSize(target);579 else => null,
1147 const new_addr = array_addr + elem_size * elem_ptr.index;580 } else null;
1148 return BigIntMutable.init(&space.limbs, new_addr).toConst();581 }
1149 },
1150582
1151 else => unreachable,583 pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable {
1152 }584 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) {
585 .variable => |variable| variable,
586 else => null,
587 } else null;
1153 }588 }
1154589
1155 /// If the value fits in a u64, return it, otherwise null.590 /// If the value fits in a u64, return it, otherwise null.
1156 /// Asserts not undefined.591 /// Asserts not undefined.
1157 pub fn getUnsignedInt(val: Value, target: Target) ?u64 {592 pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 {
1158 return getUnsignedIntAdvanced(val, target, null) catch unreachable;593 return getUnsignedIntAdvanced(val, mod, null) catch unreachable;
1159 }594 }
1160595
1161 /// If the value fits in a u64, return it, otherwise null.596 /// If the value fits in a u64, return it, otherwise null.
1162 /// Asserts not undefined.597 /// Asserts not undefined.
1163 pub fn getUnsignedIntAdvanced(val: Value, target: Target, opt_sema: ?*Sema) !?u64 {598 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {
1164 switch (val.tag()) {599 return switch (val.toIntern()) {
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
1179 .undef => unreachable,600 .undef => unreachable,
1180601 .bool_false => 0,
1181 .lazy_align => {602 .bool_true => 1,
1182 const ty = val.castTag(.lazy_align).?.data;603 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1183 if (opt_sema) |sema| {604 .undef => unreachable,
1184 return (try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar;605 .int => |int| switch (int.storage) {
1185 } else {606 .big_int => |big_int| big_int.to(u64) catch null,
1186 return ty.abiAlignment(target);607 .u64 => |x| x,
1187 }608 .i64 => |x| std.math.cast(u64, x),
1188 },609 .lazy_align => |ty| if (opt_sema) |sema|
1189 .lazy_size => {610 (try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar
1190 const ty = val.castTag(.lazy_size).?.data;611 else
1191 if (opt_sema) |sema| {612 ty.toType().abiAlignment(mod),
1192 return (try ty.abiSizeAdvanced(target, .{ .sema = sema })).scalar;613 .lazy_size => |ty| if (opt_sema) |sema|
1193 } else {614 (try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar
1194 return ty.abiSize(target);615 else
1195 }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,
1196 },638 },
1197639 };
1198 else => return null,
1199 }
1200 }640 }
1201641
1202 /// Asserts the value is an integer and it fits in a u64642 /// Asserts the value is an integer and it fits in a u64
1203 pub fn toUnsignedInt(val: Value, target: Target) u64 {643 pub fn toUnsignedInt(val: Value, mod: *Module) u64 {
1204 return getUnsignedInt(val, target).?;644 return getUnsignedInt(val, mod).?;
1205 }645 }
1206646
1207 /// Asserts the value is an integer and it fits in a i64647 /// Asserts the value is an integer and it fits in a i64
1208 pub fn toSignedInt(val: Value, target: Target) i64 {648 pub fn toSignedInt(val: Value, mod: *Module) i64 {
1209 switch (val.tag()) {649 return switch (val.toIntern()) {
1210 .zero,650 .bool_false => 0,
1211 .bool_false,651 .bool_true => 1,
1212 .the_only_possible_value, // i0, u0652 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1213 => return 0,653 .int => |int| switch (int.storage) {
1214654 .big_int => |big_int| big_int.to(i64) catch unreachable,
1215 .one,655 .i64 => |x| x,
1216 .bool_true,656 .u64 => |x| @intCast(i64, x),
1217 => return 1,657 .lazy_align => |ty| @intCast(i64, ty.toType().abiAlignment(mod)),
1218658 .lazy_size => |ty| @intCast(i64, ty.toType().abiSize(mod)),
1219 .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data),659 },
1220 .int_i64 => return val.castTag(.int_i64).?.data,660 else => unreachable,
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));
1231 },661 },
1232662 };
1233 .undef => unreachable,
1234 else => unreachable,
1235 }
1236 }663 }
1237664
1238 pub fn toBool(self: Value) bool {665 pub fn toBool(val: Value) bool {
1239 return switch (self.tag()) {666 return switch (val.toIntern()) {
1240 .bool_true, .one => true,667 .bool_true => true,
1241 .bool_false, .zero => false,668 .bool_false => 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 },
1252 else => unreachable,669 else => unreachable,
1253 };670 };
1254 }671 }
1255672
1256 fn isDeclRef(val: Value) bool {673 fn isDeclRef(val: Value, mod: *Module) bool {
1257 var check = val;674 var check = val;
1258 while (true) switch (check.tag()) {675 while (true) switch (mod.intern_pool.indexToKey(check.toIntern())) {
1259 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return true,676 .ptr => |ptr| switch (ptr.addr) {
1260 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,677 .decl, .mut_decl, .comptime_field => return true,
1261 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,678 .eu_payload, .opt_payload => |base| check = base.toValue(),
1262 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,679 .elem, .field => |base_index| check = base_index.base.toValue(),
680 else => return false,
681 },
1263 else => return false,682 else => return false,
1264 };683 };
1265 }684 }
...@@ -1272,62 +691,45 @@ pub const Value = extern union {...@@ -1272,62 +691,45 @@ pub const Value = extern union {
1272 ReinterpretDeclRef,691 ReinterpretDeclRef,
1273 IllDefinedMemoryLayout,692 IllDefinedMemoryLayout,
1274 Unimplemented,693 Unimplemented,
694 OutOfMemory,
1275 }!void {695 }!void {
1276 const target = mod.getTarget();696 const target = mod.getTarget();
1277 const endian = target.cpu.arch.endian();697 const endian = target.cpu.arch.endian();
1278 if (val.isUndef()) {698 if (val.isUndef(mod)) {
1279 const size = @intCast(usize, ty.abiSize(target));699 const size = @intCast(usize, ty.abiSize(mod));
1280 @memset(buffer[0..size], 0xaa);700 @memset(buffer[0..size], 0xaa);
1281 return;701 return;
1282 }702 }
1283 switch (ty.zigTypeTag()) {703 switch (ty.zigTypeTag(mod)) {
1284 .Void => {},704 .Void => {},
1285 .Bool => {705 .Bool => {
1286 buffer[0] = @boolToInt(val.toBool());706 buffer[0] = @boolToInt(val.toBool());
1287 },707 },
1288 .Int, .Enum => {708 .Int, .Enum => {
1289 const int_info = ty.intInfo(target);709 const int_info = ty.intInfo(mod);
1290 const bits = int_info.bits;710 const bits = int_info.bits;
1291 const byte_count = (bits + 7) / 8;711 const byte_count = (bits + 7) / 8;
1292712
1293 var enum_buffer: Payload.U64 = undefined;713 var bigint_buffer: BigIntSpace = undefined;
1294 const int_val = val.enumToInt(ty, &enum_buffer);714 const bigint = val.toBigInt(&bigint_buffer, mod);
1295715 bigint.writeTwosComplement(buffer[0..byte_count], endian);
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 }
1313 },716 },
1314 .Float => switch (ty.floatBits(target)) {717 .Float => switch (ty.floatBits(target)) {
1315 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(u16, val.toFloat(f16)), endian),718 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(u16, val.toFloat(f16, mod)), endian),
1316 32 => std.mem.writeInt(u32, buffer[0..4], @bitCast(u32, val.toFloat(f32)), endian),719 32 => std.mem.writeInt(u32, buffer[0..4], @bitCast(u32, val.toFloat(f32, mod)), endian),
1317 64 => std.mem.writeInt(u64, buffer[0..8], @bitCast(u64, val.toFloat(f64)), endian),720 64 => std.mem.writeInt(u64, buffer[0..8], @bitCast(u64, val.toFloat(f64, mod)), endian),
1318 80 => std.mem.writeInt(u80, buffer[0..10], @bitCast(u80, val.toFloat(f80)), endian),721 80 => std.mem.writeInt(u80, buffer[0..10], @bitCast(u80, val.toFloat(f80, mod)), endian),
1319 128 => std.mem.writeInt(u128, buffer[0..16], @bitCast(u128, val.toFloat(f128)), endian),722 128 => std.mem.writeInt(u128, buffer[0..16], @bitCast(u128, val.toFloat(f128, mod)), endian),
1320 else => unreachable,723 else => unreachable,
1321 },724 },
1322 .Array => {725 .Array => {
1323 const len = ty.arrayLen();726 const len = ty.arrayLen(mod);
1324 const elem_ty = ty.childType();727 const elem_ty = ty.childType(mod);
1325 const elem_size = @intCast(usize, elem_ty.abiSize(target));728 const elem_size = @intCast(usize, elem_ty.abiSize(mod));
1326 var elem_i: usize = 0;729 var elem_i: usize = 0;
1327 var elem_value_buf: ElemValueBuffer = undefined;
1328 var buf_off: usize = 0;730 var buf_off: usize = 0;
1329 while (elem_i < len) : (elem_i += 1) {731 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);
1331 try elem_val.writeToMemory(elem_ty, mod, buffer[buf_off..]);733 try elem_val.writeToMemory(elem_ty, mod, buffer[buf_off..]);
1332 buf_off += elem_size;734 buf_off += elem_size;
1333 }735 }
...@@ -1335,52 +737,63 @@ pub const Value = extern union {...@@ -1335,52 +737,63 @@ pub const Value = extern union {
1335 .Vector => {737 .Vector => {
1336 // We use byte_count instead of abi_size here, so that any padding bytes738 // We use byte_count instead of abi_size here, so that any padding bytes
1337 // follow the data bytes, on both big- and little-endian systems.739 // 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;
1339 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);741 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1340 },742 },
1341 .Struct => switch (ty.containerLayout()) {743 .Struct => switch (ty.containerLayout(mod)) {
1342 .Auto => return error.IllDefinedMemoryLayout,744 .Auto => return error.IllDefinedMemoryLayout,
1343 .Extern => {745 .Extern => for (ty.structFields(mod).values(), 0..) |field, i| {
1344 const fields = ty.structFields().values();746 const off = @intCast(usize, ty.structFieldOffset(i, mod));
1345 const field_vals = val.castTag(.aggregate).?.data;747 const field_val = switch (val.ip_index) {
1346 for (fields, 0..) |field, i| {748 .none => val.castTag(.aggregate).?.data[i],
1347 const off = @intCast(usize, ty.structFieldOffset(i, target));749 else => switch (mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage) {
1348 try writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);750 .bytes => |bytes| {
1349 }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..]);
1350 },759 },
1351 .Packed => {760 .Packed => {
1352 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;761 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1353 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);762 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1354 },763 },
1355 },764 },
1356 .ErrorSet => {765 .ErrorSet => {
1357 // TODO revisit this when we have the concept of the error tag type766 // TODO revisit this when we have the concept of the error tag type
1358 const Int = u16;767 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).?);
1360 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);774 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);
1361 },775 },
1362 .Union => switch (ty.containerLayout()) {776 .Union => switch (ty.containerLayout(mod)) {
1363 .Auto => return error.IllDefinedMemoryLayout,777 .Auto => return error.IllDefinedMemoryLayout,
1364 .Extern => return error.Unimplemented,778 .Extern => return error.Unimplemented,
1365 .Packed => {779 .Packed => {
1366 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;780 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1367 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);781 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1368 },782 },
1369 },783 },
1370 .Pointer => {784 .Pointer => {
1371 if (ty.isSlice()) return error.IllDefinedMemoryLayout;785 if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;
1372 if (val.isDeclRef()) return error.ReinterpretDeclRef;786 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1373 return val.writeToMemory(Type.usize, mod, buffer);787 return val.writeToMemory(Type.usize, mod, buffer);
1374 },788 },
1375 .Optional => {789 .Optional => {
1376 if (!ty.isPtrLikeOptional()) return error.IllDefinedMemoryLayout;790 if (!ty.isPtrLikeOptional(mod)) return error.IllDefinedMemoryLayout;
1377 var buf: Type.Payload.ElemType = undefined;791 const child = ty.optionalChild(mod);
1378 const child = ty.optionalChild(&buf);792 const opt_val = val.optionalValue(mod);
1379 const opt_val = val.optionalValue();
1380 if (opt_val) |some| {793 if (opt_val) |some| {
1381 return some.writeToMemory(child, mod, buffer);794 return some.writeToMemory(child, mod, buffer);
1382 } else {795 } else {
1383 return writeToMemory(Value.zero, Type.usize, mod, buffer);796 return writeToMemory(try mod.intValue(Type.usize, 0), Type.usize, mod, buffer);
1384 }797 }
1385 },798 },
1386 else => return error.Unimplemented,799 else => return error.Unimplemented,
...@@ -1391,15 +804,21 @@ pub const Value = extern union {...@@ -1391,15 +804,21 @@ pub const Value = extern union {
1391 ///804 ///
1392 /// Both the start and the end of the provided buffer must be tight, since805 /// Both the start and the end of the provided buffer must be tight, since
1393 /// big-endian packed memory layouts start at the end of the buffer.806 /// 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 {
1395 const target = mod.getTarget();814 const target = mod.getTarget();
1396 const endian = target.cpu.arch.endian();815 const endian = target.cpu.arch.endian();
1397 if (val.isUndef()) {816 if (val.isUndef(mod)) {
1398 const bit_size = @intCast(usize, ty.bitSize(target));817 const bit_size = @intCast(usize, ty.bitSize(mod));
1399 std.mem.writeVarPackedInt(buffer, bit_offset, bit_size, @as(u1, 0), endian);818 std.mem.writeVarPackedInt(buffer, bit_offset, bit_size, @as(u1, 0), endian);
1400 return;819 return;
1401 }820 }
1402 switch (ty.zigTypeTag()) {821 switch (ty.zigTypeTag(mod)) {
1403 .Void => {},822 .Void => {},
1404 .Bool => {823 .Bool => {
1405 const byte_index = switch (endian) {824 const byte_index = switch (endian) {
...@@ -1413,91 +832,82 @@ pub const Value = extern union {...@@ -1413,91 +832,82 @@ pub const Value = extern union {
1413 }832 }
1414 },833 },
1415 .Int, .Enum => {834 .Int, .Enum => {
1416 const bits = ty.intInfo(target).bits;835 if (buffer.len == 0) return;
1417 const abi_size = @intCast(usize, ty.abiSize(target));836 const bits = ty.intInfo(mod).bits;
1418837 if (bits == 0) return;
1419 var enum_buffer: Payload.U64 = undefined;838
1420 const int_val = val.enumToInt(ty, &enum_buffer);839 switch (mod.intern_pool.indexToKey((try val.enumToInt(ty, mod)).toIntern()).int.storage) {
1421840 inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian),
1422 if (abi_size == 0) return;841 .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian),
1423 if (abi_size <= @sizeOf(u64)) {842 else => unreachable,
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);
1436 }843 }
1437 },844 },
1438 .Float => switch (ty.floatBits(target)) {845 .Float => switch (ty.floatBits(target)) {
1439 16 => std.mem.writePackedInt(u16, buffer, bit_offset, @bitCast(u16, val.toFloat(f16)), endian),846 16 => std.mem.writePackedInt(u16, buffer, bit_offset, @bitCast(u16, val.toFloat(f16, mod)), endian),
1440 32 => std.mem.writePackedInt(u32, buffer, bit_offset, @bitCast(u32, val.toFloat(f32)), endian),847 32 => std.mem.writePackedInt(u32, buffer, bit_offset, @bitCast(u32, val.toFloat(f32, mod)), endian),
1441 64 => std.mem.writePackedInt(u64, buffer, bit_offset, @bitCast(u64, val.toFloat(f64)), endian),848 64 => std.mem.writePackedInt(u64, buffer, bit_offset, @bitCast(u64, val.toFloat(f64, mod)), endian),
1442 80 => std.mem.writePackedInt(u80, buffer, bit_offset, @bitCast(u80, val.toFloat(f80)), endian),849 80 => std.mem.writePackedInt(u80, buffer, bit_offset, @bitCast(u80, val.toFloat(f80, mod)), endian),
1443 128 => std.mem.writePackedInt(u128, buffer, bit_offset, @bitCast(u128, val.toFloat(f128)), endian),850 128 => std.mem.writePackedInt(u128, buffer, bit_offset, @bitCast(u128, val.toFloat(f128, mod)), endian),
1444 else => unreachable,851 else => unreachable,
1445 },852 },
1446 .Vector => {853 .Vector => {
1447 const elem_ty = ty.childType();854 const elem_ty = ty.childType(mod);
1448 const elem_bit_size = @intCast(u16, elem_ty.bitSize(target));855 const elem_bit_size = @intCast(u16, elem_ty.bitSize(mod));
1449 const len = @intCast(usize, ty.arrayLen());856 const len = @intCast(usize, ty.arrayLen(mod));
1450857
1451 var bits: u16 = 0;858 var bits: u16 = 0;
1452 var elem_i: usize = 0;859 var elem_i: usize = 0;
1453 var elem_value_buf: ElemValueBuffer = undefined;
1454 while (elem_i < len) : (elem_i += 1) {860 while (elem_i < len) : (elem_i += 1) {
1455 // On big-endian systems, LLVM reverses the element order of vectors by default861 // On big-endian systems, LLVM reverses the element order of vectors by default
1456 const tgt_elem_i = if (endian == .Big) len - elem_i - 1 else elem_i;862 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);
1458 try elem_val.writeToPackedMemory(elem_ty, mod, buffer, bit_offset + bits);864 try elem_val.writeToPackedMemory(elem_ty, mod, buffer, bit_offset + bits);
1459 bits += elem_bit_size;865 bits += elem_bit_size;
1460 }866 }
1461 },867 },
1462 .Struct => switch (ty.containerLayout()) {868 .Struct => switch (ty.containerLayout(mod)) {
1463 .Auto => unreachable, // Sema is supposed to have emitted a compile error already869 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1464 .Extern => unreachable, // Handled in non-packed writeToMemory870 .Extern => unreachable, // Handled in non-packed writeToMemory
1465 .Packed => {871 .Packed => {
1466 var bits: u16 = 0;872 var bits: u16 = 0;
1467 const fields = ty.structFields().values();873 const fields = ty.structFields(mod).values();
1468 const field_vals = val.castTag(.aggregate).?.data;874 const storage = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage;
1469 for (fields, 0..) |field, i| {875 for (fields, 0..) |field, i| {
1470 const field_bits = @intCast(u16, field.ty.bitSize(target));876 const field_bits = @intCast(u16, field.ty.bitSize(mod));
1471 try field_vals[i].writeToPackedMemory(field.ty, mod, buffer, bit_offset + bits);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);
1472 bits += field_bits;883 bits += field_bits;
1473 }884 }
1474 },885 },
1475 },886 },
1476 .Union => switch (ty.containerLayout()) {887 .Union => switch (ty.containerLayout(mod)) {
1477 .Auto => unreachable, // Sema is supposed to have emitted a compile error already888 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1478 .Extern => unreachable, // Handled in non-packed writeToMemory889 .Extern => unreachable, // Handled in non-packed writeToMemory
1479 .Packed => {890 .Packed => {
1480 const field_index = ty.unionTagFieldIndex(val.unionTag(), mod);891 const field_index = ty.unionTagFieldIndex(val.unionTag(mod), mod);
1481 const field_type = ty.unionFields().values()[field_index.?].ty;892 const field_type = ty.unionFields(mod).values()[field_index.?].ty;
1482 const field_val = val.fieldValue(field_type, field_index.?);893 const field_val = try val.fieldValue(mod, field_index.?);
1483894
1484 return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);895 return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
1485 },896 },
1486 },897 },
1487 .Pointer => {898 .Pointer => {
1488 assert(!ty.isSlice()); // No well defined layout.899 assert(!ty.isSlice(mod)); // No well defined layout.
1489 if (val.isDeclRef()) return error.ReinterpretDeclRef;900 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1490 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);901 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);
1491 },902 },
1492 .Optional => {903 .Optional => {
1493 assert(ty.isPtrLikeOptional());904 assert(ty.isPtrLikeOptional(mod));
1494 var buf: Type.Payload.ElemType = undefined;905 const child = ty.optionalChild(mod);
1495 const child = ty.optionalChild(&buf);906 const opt_val = val.optionalValue(mod);
1496 const opt_val = val.optionalValue();
1497 if (opt_val) |some| {907 if (opt_val) |some| {
1498 return some.writeToPackedMemory(child, mod, buffer, bit_offset);908 return some.writeToPackedMemory(child, mod, buffer, bit_offset);
1499 } else {909 } 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);
1501 }911 }
1502 },912 },
1503 else => @panic("TODO implement writeToPackedMemory for more types"),913 else => @panic("TODO implement writeToPackedMemory for more types"),
...@@ -1516,7 +926,7 @@ pub const Value = extern union {...@@ -1516,7 +926,7 @@ pub const Value = extern union {
1516 ) Allocator.Error!Value {926 ) Allocator.Error!Value {
1517 const target = mod.getTarget();927 const target = mod.getTarget();
1518 const endian = target.cpu.arch.endian();928 const endian = target.cpu.arch.endian();
1519 switch (ty.zigTypeTag()) {929 switch (ty.zigTypeTag(mod)) {
1520 .Void => return Value.void,930 .Void => return Value.void,
1521 .Bool => {931 .Bool => {
1522 if (buffer[0] == 0) {932 if (buffer[0] == 0) {
...@@ -1525,20 +935,27 @@ pub const Value = extern union {...@@ -1525,20 +935,27 @@ pub const Value = extern union {
1525 return Value.true;935 return Value.true;
1526 }936 }
1527 },937 },
1528 .Int, .Enum => {938 .Int, .Enum => |ty_tag| {
1529 const int_info = ty.intInfo(target);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);
1530 const bits = int_info.bits;945 const bits = int_info.bits;
1531 const byte_count = (bits + 7) / 8;946 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
1534 if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64949 if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
1535 .signed => {950 .signed => {
1536 const val = std.mem.readVarInt(i64, buffer[0..byte_count], endian);951 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);
1538 },954 },
1539 .unsigned => {955 .unsigned => {
1540 const val = std.mem.readVarInt(u64, buffer[0..byte_count], endian);956 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);
1542 },959 },
1543 } else { // Slow path, we have to construct a big-int960 } else { // Slow path, we have to construct a big-int
1544 const Limb = std.math.big.Limb;961 const Limb = std.math.big.Limb;
...@@ -1547,48 +964,57 @@ pub const Value = extern union {...@@ -1547,48 +964,57 @@ pub const Value = extern union {
1547964
1548 var bigint = BigIntMutable.init(limbs_buffer, 0);965 var bigint = BigIntMutable.init(limbs_buffer, 0);
1549 bigint.readTwosComplement(buffer[0..byte_count], bits, endian, int_info.signedness);966 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);
1551 }968 }
1552 },969 },
1553 .Float => switch (ty.floatBits(target)) {970 .Float => return (try mod.intern(.{ .float = .{
1554 16 => return Value.Tag.float_16.create(arena, @bitCast(f16, std.mem.readInt(u16, buffer[0..2], endian))),971 .ty = ty.toIntern(),
1555 32 => return Value.Tag.float_32.create(arena, @bitCast(f32, std.mem.readInt(u32, buffer[0..4], endian))),972 .storage = switch (ty.floatBits(target)) {
1556 64 => return Value.Tag.float_64.create(arena, @bitCast(f64, std.mem.readInt(u64, buffer[0..8], endian))),973 16 => .{ .f16 = @bitCast(f16, std.mem.readInt(u16, buffer[0..2], endian)) },
1557 80 => return Value.Tag.float_80.create(arena, @bitCast(f80, std.mem.readInt(u80, buffer[0..10], endian))),974 32 => .{ .f32 = @bitCast(f32, std.mem.readInt(u32, buffer[0..4], endian)) },
1558 128 => return Value.Tag.float_128.create(arena, @bitCast(f128, std.mem.readInt(u128, buffer[0..16], endian))),975 64 => .{ .f64 = @bitCast(f64, std.mem.readInt(u64, buffer[0..8], endian)) },
1559 else => unreachable,976 80 => .{ .f80 = @bitCast(f80, std.mem.readInt(u80, buffer[0..10], endian)) },
1560 },977 128 => .{ .f128 = @bitCast(f128, std.mem.readInt(u128, buffer[0..16], endian)) },
978 else => unreachable,
979 },
980 } })).toValue(),
1561 .Array => {981 .Array => {
1562 const elem_ty = ty.childType();982 const elem_ty = ty.childType(mod);
1563 const elem_size = elem_ty.abiSize(target);983 const elem_size = elem_ty.abiSize(mod);
1564 const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));984 const elems = try arena.alloc(InternPool.Index, @intCast(usize, ty.arrayLen(mod)));
1565 var offset: usize = 0;985 var offset: usize = 0;
1566 for (elems) |*elem| {986 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);
1568 offset += @intCast(usize, elem_size);988 offset += @intCast(usize, elem_size);
1569 }989 }
1570 return Tag.aggregate.create(arena, elems);990 return (try mod.intern(.{ .aggregate = .{
991 .ty = ty.toIntern(),
992 .storage = .{ .elems = elems },
993 } })).toValue();
1571 },994 },
1572 .Vector => {995 .Vector => {
1573 // We use byte_count instead of abi_size here, so that any padding bytes996 // We use byte_count instead of abi_size here, so that any padding bytes
1574 // follow the data bytes, on both big- and little-endian systems.997 // 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;
1576 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);999 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);
1577 },1000 },
1578 .Struct => switch (ty.containerLayout()) {1001 .Struct => switch (ty.containerLayout(mod)) {
1579 .Auto => unreachable, // Sema is supposed to have emitted a compile error already1002 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1580 .Extern => {1003 .Extern => {
1581 const fields = ty.structFields().values();1004 const fields = ty.structFields(mod).values();
1582 const field_vals = try arena.alloc(Value, fields.len);1005 const field_vals = try arena.alloc(InternPool.Index, fields.len);
1583 for (fields, 0..) |field, i| {1006 for (field_vals, fields, 0..) |*field_val, field, i| {
1584 const off = @intCast(usize, ty.structFieldOffset(i, target));1007 const off = @intCast(usize, ty.structFieldOffset(i, mod));
1585 const sz = @intCast(usize, ty.structFieldType(i).abiSize(target));1008 const sz = @intCast(usize, field.ty.abiSize(mod));
1586 field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena);1009 field_val.* = try (try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena)).intern(field.ty, mod);
1587 }1010 }
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();
1589 },1015 },
1590 .Packed => {1016 .Packed => {
1591 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;1017 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1592 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);1018 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);
1593 },1019 },
1594 },1020 },
...@@ -1596,22 +1022,19 @@ pub const Value = extern union {...@@ -1596,22 +1022,19 @@ pub const Value = extern union {
1596 // TODO revisit this when we have the concept of the error tag type1022 // TODO revisit this when we have the concept of the error tag type
1597 const Int = u16;1023 const Int = u16;
1598 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);1024 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);
15991025 const name = mod.global_error_set.keys()[@intCast(usize, int)];
1600 const payload = try arena.create(Value.Payload.Error);1026 return (try mod.intern(.{ .err = .{
1601 payload.* = .{1027 .ty = ty.toIntern(),
1602 .base = .{ .tag = .@"error" },1028 .name = name,
1603 .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] },1029 } })).toValue();
1604 };
1605 return Value.initPayload(&payload.base);
1606 },1030 },
1607 .Pointer => {1031 .Pointer => {
1608 assert(!ty.isSlice()); // No well defined layout.1032 assert(!ty.isSlice(mod)); // No well defined layout.
1609 return readFromMemory(Type.usize, mod, buffer, arena);1033 return readFromMemory(Type.usize, mod, buffer, arena);
1610 },1034 },
1611 .Optional => {1035 .Optional => {
1612 assert(ty.isPtrLikeOptional());1036 assert(ty.isPtrLikeOptional(mod));
1613 var buf: Type.Payload.ElemType = undefined;1037 const child = ty.optionalChild(mod);
1614 const child = ty.optionalChild(&buf);
1615 return readFromMemory(child, mod, buffer, arena);1038 return readFromMemory(child, mod, buffer, arena);
1616 },1039 },
1617 else => @panic("TODO implement readFromMemory for more types"),1040 else => @panic("TODO implement readFromMemory for more types"),
...@@ -1631,7 +1054,7 @@ pub const Value = extern union {...@@ -1631,7 +1054,7 @@ pub const Value = extern union {
1631 ) Allocator.Error!Value {1054 ) Allocator.Error!Value {
1632 const target = mod.getTarget();1055 const target = mod.getTarget();
1633 const endian = target.cpu.arch.endian();1056 const endian = target.cpu.arch.endian();
1634 switch (ty.zigTypeTag()) {1057 switch (ty.zigTypeTag(mod)) {
1635 .Void => return Value.void,1058 .Void => return Value.void,
1636 .Bool => {1059 .Bool => {
1637 const byte = switch (endian) {1060 const byte = switch (endian) {
...@@ -1644,71 +1067,94 @@ pub const Value = extern union {...@@ -1644,71 +1067,94 @@ pub const Value = extern union {
1644 return Value.true;1067 return Value.true;
1645 }1068 }
1646 },1069 },
1647 .Int, .Enum => {1070 .Int, .Enum => |ty_tag| {
1648 if (buffer.len == 0) return Value.zero;1071 if (buffer.len == 0) return mod.intValue(ty, 0);
1649 const int_info = ty.intInfo(target);1072 const int_info = ty.intInfo(mod);
1650 const abi_size = @intCast(usize, ty.abiSize(target));
1651
1652 const bits = int_info.bits;1073 const bits = int_info.bits;
1653 if (bits == 0) return Value.zero;1074 if (bits == 0) return mod.intValue(ty, 0);
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);
16611075
1662 var bigint = BigIntMutable.init(limbs_buffer, 0);1076 // Fast path for integers <= u64
1663 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);1077 if (bits <= 64) {
1664 return fromBigInt(arena, bigint.toConst());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);
1665 }1093 }
1666 },1094
1667 .Float => switch (ty.floatBits(target)) {1095 // Slow path, we have to construct a big-int
1668 16 => return Value.Tag.float_16.create(arena, @bitCast(f16, std.mem.readPackedInt(u16, buffer, bit_offset, endian))),1096 const abi_size = @intCast(usize, ty.abiSize(mod));
1669 32 => return Value.Tag.float_32.create(arena, @bitCast(f32, std.mem.readPackedInt(u32, buffer, bit_offset, endian))),1097 const Limb = std.math.big.Limb;
1670 64 => return Value.Tag.float_64.create(arena, @bitCast(f64, std.mem.readPackedInt(u64, buffer, bit_offset, endian))),1098 const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb);
1671 80 => return Value.Tag.float_80.create(arena, @bitCast(f80, std.mem.readPackedInt(u80, buffer, bit_offset, endian))),1099 const limbs_buffer = try arena.alloc(Limb, limb_count);
1672 128 => return Value.Tag.float_128.create(arena, @bitCast(f128, std.mem.readPackedInt(u128, buffer, bit_offset, endian))),1100
1673 else => unreachable,1101 var bigint = BigIntMutable.init(limbs_buffer, 0);
1674 },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(),
1675 .Vector => {1116 .Vector => {
1676 const elem_ty = ty.childType();1117 const elem_ty = ty.childType(mod);
1677 const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));1118 const elems = try arena.alloc(InternPool.Index, @intCast(usize, ty.arrayLen(mod)));
16781119
1679 var bits: u16 = 0;1120 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));
1681 for (elems, 0..) |_, i| {1122 for (elems, 0..) |_, i| {
1682 // On big-endian systems, LLVM reverses the element order of vectors by default1123 // On big-endian systems, LLVM reverses the element order of vectors by default
1683 const tgt_elem_i = if (endian == .Big) elems.len - i - 1 else i;1124 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);
1685 bits += elem_bit_size;1126 bits += elem_bit_size;
1686 }1127 }
1687 return Tag.aggregate.create(arena, elems);1128 return (try mod.intern(.{ .aggregate = .{
1129 .ty = ty.toIntern(),
1130 .storage = .{ .elems = elems },
1131 } })).toValue();
1688 },1132 },
1689 .Struct => switch (ty.containerLayout()) {1133 .Struct => switch (ty.containerLayout(mod)) {
1690 .Auto => unreachable, // Sema is supposed to have emitted a compile error already1134 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1691 .Extern => unreachable, // Handled by non-packed readFromMemory1135 .Extern => unreachable, // Handled by non-packed readFromMemory
1692 .Packed => {1136 .Packed => {
1693 var bits: u16 = 0;1137 var bits: u16 = 0;
1694 const fields = ty.structFields().values();1138 const fields = ty.structFields(mod).values();
1695 const field_vals = try arena.alloc(Value, fields.len);1139 const field_vals = try arena.alloc(InternPool.Index, fields.len);
1696 for (fields, 0..) |field, i| {1140 for (fields, 0..) |field, i| {
1697 const field_bits = @intCast(u16, field.ty.bitSize(target));1141 const field_bits = @intCast(u16, field.ty.bitSize(mod));
1698 field_vals[i] = try readFromPackedMemory(field.ty, mod, buffer, bit_offset + bits, arena);1142 field_vals[i] = try (try readFromPackedMemory(field.ty, mod, buffer, bit_offset + bits, arena)).intern(field.ty, mod);
1699 bits += field_bits;1143 bits += field_bits;
1700 }1144 }
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();
1702 },1149 },
1703 },1150 },
1704 .Pointer => {1151 .Pointer => {
1705 assert(!ty.isSlice()); // No well defined layout.1152 assert(!ty.isSlice(mod)); // No well defined layout.
1706 return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena);1153 return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena);
1707 },1154 },
1708 .Optional => {1155 .Optional => {
1709 assert(ty.isPtrLikeOptional());1156 assert(ty.isPtrLikeOptional(mod));
1710 var buf: Type.Payload.ElemType = undefined;1157 const child = ty.optionalChild(mod);
1711 const child = ty.optionalChild(&buf);
1712 return readFromPackedMemory(child, mod, buffer, bit_offset, arena);1158 return readFromPackedMemory(child, mod, buffer, bit_offset, arena);
1713 },1159 },
1714 else => @panic("TODO implement readFromPackedMemory for more types"),1160 else => @panic("TODO implement readFromPackedMemory for more types"),
...@@ -1716,31 +1162,22 @@ pub const Value = extern union {...@@ -1716,31 +1162,22 @@ pub const Value = extern union {
1716 }1162 }
17171163
1718 /// Asserts that the value is a float or an integer.1164 /// Asserts that the value is a float or an integer.
1719 pub fn toFloat(val: Value, comptime T: type) T {1165 pub fn toFloat(val: Value, comptime T: type, mod: *Module) T {
1720 return switch (val.tag()) {1166 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1721 .float_16 => @floatCast(T, val.castTag(.float_16).?.data),1167 .int => |int| switch (int.storage) {
1722 .float_32 => @floatCast(T, val.castTag(.float_32).?.data),1168 .big_int => |big_int| @floatCast(T, bigIntToFloat(big_int.limbs, big_int.positive)),
1723 .float_64 => @floatCast(T, val.castTag(.float_64).?.data),1169 inline .u64, .i64 => |x| {
1724 .float_80 => @floatCast(T, val.castTag(.float_80).?.data),1170 if (T == f80) {
1725 .float_128 => @floatCast(T, val.castTag(.float_128).?.data),1171 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
17261172 }
1727 .zero => 0,1173 return @intToFloat(T, x);
1728 .one => 1,1174 },
1729 .int_u64 => {1175 .lazy_align => |ty| @intToFloat(T, ty.toType().abiAlignment(mod)),
1730 if (T == f80) {1176 .lazy_size => |ty| @intToFloat(T, ty.toType().abiSize(mod)),
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);
1734 },1177 },
1735 .int_i64 => {1178 .float => |float| switch (float.storage) {
1736 if (T == f80) {1179 inline else => |x| @floatCast(T, x),
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);
1740 },1180 },
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)),
1744 else => unreachable,1181 else => unreachable,
1745 };1182 };
1746 }1183 }
...@@ -1764,103 +1201,29 @@ pub const Value = extern union {...@@ -1764,103 +1201,29 @@ pub const Value = extern union {
1764 }1201 }
1765 }1202 }
17661203
1767 pub fn clz(val: Value, ty: Type, target: Target) u64 {1204 pub fn clz(val: Value, ty: Type, mod: *Module) u64 {
1768 const ty_bits = ty.intInfo(target).bits;1205 var bigint_buf: BigIntSpace = undefined;
1769 switch (val.tag()) {1206 const bigint = val.toBigInt(&bigint_buf, mod);
1770 .zero, .bool_false => return ty_bits,1207 return bigint.clz(ty.intInfo(mod).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 }
1801 }1208 }
18021209
1803 pub fn ctz(val: Value, ty: Type, target: Target) u64 {1210 pub fn ctz(val: Value, ty: Type, mod: *Module) u64 {
1804 const ty_bits = ty.intInfo(target).bits;1211 var bigint_buf: BigIntSpace = undefined;
1805 switch (val.tag()) {1212 const bigint = val.toBigInt(&bigint_buf, mod);
1806 .zero, .bool_false => return ty_bits,1213 return bigint.ctz(ty.intInfo(mod).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 }
1837 }1214 }
18381215
1839 pub fn popCount(val: Value, ty: Type, target: Target) u64 {1216 pub fn popCount(val: Value, ty: Type, mod: *Module) u64 {
1840 assert(!val.isUndef());1217 var bigint_buf: BigIntSpace = undefined;
1841 switch (val.tag()) {1218 const bigint = val.toBigInt(&bigint_buf, mod);
1842 .zero, .bool_false => return 0,1219 return @intCast(u64, bigint.popCount(ty.intInfo(mod).bits));
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 }
1855 }1220 }
18561221
1857 pub fn bitReverse(val: Value, ty: Type, target: Target, arena: Allocator) !Value {1222 pub fn bitReverse(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1858 assert(!val.isUndef());1223 const info = ty.intInfo(mod);
1859
1860 const info = ty.intInfo(target);
18611224
1862 var buffer: Value.BigIntSpace = undefined;1225 var buffer: Value.BigIntSpace = undefined;
1863 const operand_bigint = val.toBigInt(&buffer, target);1226 const operand_bigint = val.toBigInt(&buffer, mod);
18641227
1865 const limbs = try arena.alloc(1228 const limbs = try arena.alloc(
1866 std.math.big.Limb,1229 std.math.big.Limb,
...@@ -1869,19 +1232,17 @@ pub const Value = extern union {...@@ -1869,19 +1232,17 @@ pub const Value = extern union {
1869 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };1232 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
1870 result_bigint.bitReverse(operand_bigint, info.signedness, info.bits);1233 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());
1873 }1236 }
18741237
1875 pub fn byteSwap(val: Value, ty: Type, target: Target, arena: Allocator) !Value {1238 pub fn byteSwap(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1876 assert(!val.isUndef());1239 const info = ty.intInfo(mod);
1877
1878 const info = ty.intInfo(target);
18791240
1880 // Bit count must be evenly divisible by 81241 // Bit count must be evenly divisible by 8
1881 assert(info.bits % 8 == 0);1242 assert(info.bits % 8 == 0);
18821243
1883 var buffer: Value.BigIntSpace = undefined;1244 var buffer: Value.BigIntSpace = undefined;
1884 const operand_bigint = val.toBigInt(&buffer, target);1245 const operand_bigint = val.toBigInt(&buffer, mod);
18851246
1886 const limbs = try arena.alloc(1247 const limbs = try arena.alloc(
1887 std.math.big.Limb,1248 std.math.big.Limb,
...@@ -1890,176 +1251,98 @@ pub const Value = extern union {...@@ -1890,176 +1251,98 @@ pub const Value = extern union {
1890 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };1251 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
1891 result_bigint.byteSwap(operand_bigint, info.signedness, info.bits / 8);1252 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());
1894 }1255 }
18951256
1896 /// Asserts the value is an integer and not undefined.1257 /// Asserts the value is an integer and not undefined.
1897 /// Returns the number of bits the value requires to represent stored in twos complement form.1258 /// Returns the number of bits the value requires to represent stored in twos complement form.
1898 pub fn intBitCountTwosComp(self: Value, target: Target) usize {1259 pub fn intBitCountTwosComp(self: Value, mod: *Module) usize {
1899 switch (self.tag()) {1260 var buffer: BigIntSpace = undefined;
1900 .zero,1261 const big_int = self.toBigInt(&buffer, mod);
1901 .bool_false,1262 return big_int.bitCountTwosComp();
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 }
1932 }1263 }
19331264
1934 /// Converts an integer or a float to a float. May result in a loss of information.1265 /// Converts an integer or a float to a float. May result in a loss of information.
1935 /// Caller can find out by equality checking the result against the operand.1266 /// 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 {1267 pub fn floatCast(self: Value, dest_ty: Type, mod: *Module) !Value {
1937 switch (dest_ty.floatBits(target)) {1268 const target = mod.getTarget();
1938 16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),1269 return (try mod.intern(.{ .float = .{
1939 32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),1270 .ty = dest_ty.toIntern(),
1940 64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),1271 .storage = switch (dest_ty.floatBits(target)) {
1941 80 => return Value.Tag.float_80.create(arena, self.toFloat(f80)),1272 16 => .{ .f16 = self.toFloat(f16, mod) },
1942 128 => return Value.Tag.float_128.create(arena, self.toFloat(f128)),1273 32 => .{ .f32 = self.toFloat(f32, mod) },
1943 else => unreachable,1274 64 => .{ .f64 = self.toFloat(f64, mod) },
1944 }1275 80 => .{ .f80 = self.toFloat(f80, mod) },
1276 128 => .{ .f128 = self.toFloat(f128, mod) },
1277 else => unreachable,
1278 },
1279 } })).toValue();
1945 }1280 }
19461281
1947 /// Asserts the value is a float1282 /// Asserts the value is a float
1948 pub fn floatHasFraction(self: Value) bool {1283 pub fn floatHasFraction(self: Value, mod: *const Module) bool {
1949 return switch (self.tag()) {1284 return switch (mod.intern_pool.indexToKey(self.toIntern())) {
1950 .zero,1285 .float => |float| switch (float.storage) {
1951 .one,1286 inline else => |x| @rem(x, 1) != 0,
1952 => false,1287 },
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
1961 else => unreachable,1288 else => unreachable,
1962 };1289 };
1963 }1290 }
19641291
1965 pub fn orderAgainstZero(lhs: Value) std.math.Order {1292 pub fn orderAgainstZero(lhs: Value, mod: *Module) std.math.Order {
1966 return orderAgainstZeroAdvanced(lhs, null) catch unreachable;1293 return orderAgainstZeroAdvanced(lhs, mod, null) catch unreachable;
1967 }1294 }
19681295
1969 pub fn orderAgainstZeroAdvanced(1296 pub fn orderAgainstZeroAdvanced(
1970 lhs: Value,1297 lhs: Value,
1298 mod: *Module,
1971 opt_sema: ?*Sema,1299 opt_sema: ?*Sema,
1972 ) Module.CompileError!std.math.Order {1300 ) Module.CompileError!std.math.Order {
1973 return switch (lhs.tag()) {1301 return switch (lhs.toIntern()) {
1974 .zero,1302 .bool_false => .eq,
1975 .bool_false,1303 .bool_true => .gt,
1976 .the_only_possible_value,1304 else => switch (mod.intern_pool.indexToKey(lhs.toIntern())) {
1977 => .eq,1305 .ptr => |ptr| switch (ptr.addr) {
19781306 .decl, .mut_decl, .comptime_field => .gt,
1979 .one,1307 .int => |int| int.toValue().orderAgainstZeroAdvanced(mod, opt_sema),
1980 .bool_true,1308 .elem => |elem| switch (try elem.base.toValue().orderAgainstZeroAdvanced(mod, opt_sema)) {
1981 .decl_ref,1309 .lt => unreachable,
1982 .decl_ref_mut,1310 .gt => .gt,
1983 .comptime_field_ptr,1311 .eq => if (elem.index == 0) .eq else .gt,
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 }
2043 },1312 },
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,
2045 },1332 },
2046
2047 else => unreachable,
2048 };1333 };
2049 }1334 }
20501335
2051 /// Asserts the value is comparable.1336 /// Asserts the value is comparable.
2052 pub fn order(lhs: Value, rhs: Value, target: Target) std.math.Order {1337 pub fn order(lhs: Value, rhs: Value, mod: *Module) std.math.Order {
2053 return orderAdvanced(lhs, rhs, target, null) catch unreachable;1338 return orderAdvanced(lhs, rhs, mod, null) catch unreachable;
2054 }1339 }
20551340
2056 /// Asserts the value is comparable.1341 /// Asserts the value is comparable.
2057 /// If opt_sema is null then this function asserts things are resolved and cannot fail.1342 /// 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 {1343 pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, opt_sema: ?*Sema) !std.math.Order {
2059 const lhs_tag = lhs.tag();1344 const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(mod, opt_sema);
2060 const rhs_tag = rhs.tag();1345 const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(mod, opt_sema);
2061 const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(opt_sema);
2062 const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(opt_sema);
2063 switch (lhs_against_zero) {1346 switch (lhs_against_zero) {
2064 .lt => if (rhs_against_zero != .lt) return .lt,1347 .lt => if (rhs_against_zero != .lt) return .lt,
2065 .eq => return rhs_against_zero.invert(),1348 .eq => return rhs_against_zero.invert(),
...@@ -2071,48 +1354,34 @@ pub const Value = extern union {...@@ -2071,48 +1354,34 @@ pub const Value = extern union {
2071 .gt => {},1354 .gt => {},
2072 }1355 }
20731356
2074 const lhs_float = lhs.isFloat();1357 if (lhs.isFloat(mod) or rhs.isFloat(mod)) {
2075 const rhs_float = rhs.isFloat();1358 const lhs_f128 = lhs.toFloat(f128, mod);
2076 if (lhs_float and rhs_float) {1359 const rhs_f128 = rhs.toFloat(f128, mod);
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);
2091 return std.math.order(lhs_f128, rhs_f128);1360 return std.math.order(lhs_f128, rhs_f128);
2092 }1361 }
20931362
2094 var lhs_bigint_space: BigIntSpace = undefined;1363 var lhs_bigint_space: BigIntSpace = undefined;
2095 var rhs_bigint_space: BigIntSpace = undefined;1364 var rhs_bigint_space: BigIntSpace = undefined;
2096 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, target, opt_sema);1365 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, mod, opt_sema);
2097 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, target, opt_sema);1366 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, mod, opt_sema);
2098 return lhs_bigint.order(rhs_bigint);1367 return lhs_bigint.order(rhs_bigint);
2099 }1368 }
21001369
2101 /// Asserts the value is comparable. Does not take a type parameter because it supports1370 /// Asserts the value is comparable. Does not take a type parameter because it supports
2102 /// comparisons between heterogeneous types.1371 /// comparisons between heterogeneous types.
2103 pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, target: Target) bool {1372 pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *Module) bool {
2104 return compareHeteroAdvanced(lhs, op, rhs, target, null) catch unreachable;1373 return compareHeteroAdvanced(lhs, op, rhs, mod, null) catch unreachable;
2105 }1374 }
21061375
2107 pub fn compareHeteroAdvanced(1376 pub fn compareHeteroAdvanced(
2108 lhs: Value,1377 lhs: Value,
2109 op: std.math.CompareOperator,1378 op: std.math.CompareOperator,
2110 rhs: Value,1379 rhs: Value,
2111 target: Target,1380 mod: *Module,
2112 opt_sema: ?*Sema,1381 opt_sema: ?*Sema,
2113 ) !bool {1382 ) !bool {
2114 if (lhs.pointerDecl()) |lhs_decl| {1383 if (lhs.pointerDecl(mod)) |lhs_decl| {
2115 if (rhs.pointerDecl()) |rhs_decl| {1384 if (rhs.pointerDecl(mod)) |rhs_decl| {
2116 switch (op) {1385 switch (op) {
2117 .eq => return lhs_decl == rhs_decl,1386 .eq => return lhs_decl == rhs_decl,
2118 .neq => return lhs_decl != rhs_decl,1387 .neq => return lhs_decl != rhs_decl,
...@@ -2125,27 +1394,25 @@ pub const Value = extern union {...@@ -2125,27 +1394,25 @@ pub const Value = extern union {
2125 else => {},1394 else => {},
2126 }1395 }
2127 }1396 }
2128 } else if (rhs.pointerDecl()) |_| {1397 } else if (rhs.pointerDecl(mod)) |_| {
2129 switch (op) {1398 switch (op) {
2130 .eq => return false,1399 .eq => return false,
2131 .neq => return true,1400 .neq => return true,
2132 else => {},1401 else => {},
2133 }1402 }
2134 }1403 }
2135 return (try orderAdvanced(lhs, rhs, target, opt_sema)).compare(op);1404 return (try orderAdvanced(lhs, rhs, mod, opt_sema)).compare(op);
2136 }1405 }
21371406
2138 /// Asserts the values are comparable. Both operands have type `ty`.1407 /// Asserts the values are comparable. Both operands have type `ty`.
2139 /// For vectors, returns true if comparison is true for ALL elements.1408 /// 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 {1409 pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) !bool {
2141 if (ty.zigTypeTag() == .Vector) {1410 if (ty.zigTypeTag(mod) == .Vector) {
2142 var i: usize = 0;1411 const scalar_ty = ty.scalarType(mod);
2143 while (i < ty.vectorLen()) : (i += 1) {1412 for (0..ty.vectorLen(mod)) |i| {
2144 var lhs_buf: Value.ElemValueBuffer = undefined;1413 const lhs_elem = try lhs.elemValue(mod, i);
2145 var rhs_buf: Value.ElemValueBuffer = undefined;1414 const rhs_elem = try rhs.elemValue(mod, i);
2146 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);1415 if (!compareScalar(lhs_elem, op, rhs_elem, scalar_ty, mod)) {
2147 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
2148 if (!compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(), mod)) {
2149 return false;1416 return false;
2150 }1417 }
2151 }1418 }
...@@ -2165,7 +1432,7 @@ pub const Value = extern union {...@@ -2165,7 +1432,7 @@ pub const Value = extern union {
2165 return switch (op) {1432 return switch (op) {
2166 .eq => lhs.eql(rhs, ty, mod),1433 .eq => lhs.eql(rhs, ty, mod),
2167 .neq => !lhs.eql(rhs, ty, mod),1434 .neq => !lhs.eql(rhs, ty, mod),
2168 else => compareHetero(lhs, op, rhs, mod.getTarget()),1435 else => compareHetero(lhs, op, rhs, mod),
2169 };1436 };
2170 }1437 }
21711438
...@@ -2191,47 +1458,31 @@ pub const Value = extern union {...@@ -2191,47 +1458,31 @@ pub const Value = extern union {
2191 mod: *Module,1458 mod: *Module,
2192 opt_sema: ?*Sema,1459 opt_sema: ?*Sema,
2193 ) Module.CompileError!bool {1460 ) Module.CompileError!bool {
2194 if (lhs.isInf()) {1461 if (lhs.isInf(mod)) {
2195 switch (op) {1462 switch (op) {
2196 .neq => return true,1463 .neq => return true,
2197 .eq => return false,1464 .eq => return false,
2198 .gt, .gte => return !lhs.isNegativeInf(),1465 .gt, .gte => return !lhs.isNegativeInf(mod),
2199 .lt, .lte => return lhs.isNegativeInf(),1466 .lt, .lte => return lhs.isNegativeInf(mod),
2200 }1467 }
2201 }1468 }
22021469
2203 switch (lhs.tag()) {1470 switch (mod.intern_pool.indexToKey(lhs.toIntern())) {
2204 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema),1471 .float => |float| switch (float.storage) {
2205 .aggregate => {1472 inline else => |x| if (std.math.isNan(x)) return op == .neq,
2206 for (lhs.castTag(.aggregate).?.data) |elem_val| {
2207 if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false;
2208 }
2209 return true;
2210 },1473 },
2211 .empty_array => return true,1474 .aggregate => |aggregate| return switch (aggregate.storage) {
2212 .str_lit => {1475 .bytes => |bytes| for (bytes) |byte| {
2213 const str_lit = lhs.castTag(.str_lit).?.data;1476 if (!std.math.order(byte, 0).compare(op)) break false;
2214 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];1477 } else true,
2215 for (bytes) |byte| {1478 .elems => |elems| for (elems) |elem| {
2216 if (!std.math.compare(byte, op, 0)) return false;1479 if (!try elem.toValue().compareAllWithZeroAdvancedExtra(op, mod, opt_sema)) break false;
2217 }1480 } else true,
2218 return true;1481 .repeated_elem => |elem| elem.toValue().compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
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;
2226 },1482 },
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,
2232 else => {},1483 else => {},
2233 }1484 }
2234 return (try orderAgainstZeroAdvanced(lhs, opt_sema)).compare(op);1485 return (try orderAgainstZeroAdvanced(lhs, mod, opt_sema)).compare(op);
2235 }1486 }
22361487
2237 pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {1488 pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {
...@@ -2255,109 +1506,42 @@ pub const Value = extern union {...@@ -2255,109 +1506,42 @@ pub const Value = extern union {
2255 mod: *Module,1506 mod: *Module,
2256 opt_sema: ?*Sema,1507 opt_sema: ?*Sema,
2257 ) Module.CompileError!bool {1508 ) Module.CompileError!bool {
1509 if (a.ip_index != .none or b.ip_index != .none) return a.ip_index == b.ip_index;
1510
2258 const target = mod.getTarget();1511 const target = mod.getTarget();
2259 const a_tag = a.tag();1512 const a_tag = a.tag();
2260 const b_tag = b.tag();1513 const b_tag = b.tag();
2261 if (a_tag == b_tag) switch (a_tag) {1514 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 },
2333 .aggregate => {1515 .aggregate => {
2334 const a_field_vals = a.castTag(.aggregate).?.data;1516 const a_field_vals = a.castTag(.aggregate).?.data;
2335 const b_field_vals = b.castTag(.aggregate).?.data;1517 const b_field_vals = b.castTag(.aggregate).?.data;
2336 assert(a_field_vals.len == b_field_vals.len);1518 assert(a_field_vals.len == b_field_vals.len);
23371519
2338 if (ty.isSimpleTupleOrAnonStruct()) {1520 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2339 const types = ty.tupleFields().types;1521 .anon_struct_type => |anon_struct| {
2340 assert(types.len == a_field_vals.len);1522 assert(anon_struct.types.len == a_field_vals.len);
2341 for (types, 0..) |field_ty, i| {1523 for (anon_struct.types, 0..) |field_ty, i| {
2342 if (!(try eqlAdvanced(a_field_vals[i], field_ty, b_field_vals[i], field_ty, mod, opt_sema))) {1524 if (!(try eqlAdvanced(a_field_vals[i], field_ty.toType(), b_field_vals[i], field_ty.toType(), mod, opt_sema))) {
2343 return false;1525 return false;
1526 }
2344 }1527 }
2345 }1528 return true;
2346 return true;1529 },
2347 }1530 .struct_type => |struct_type| {
23481531 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
2349 if (ty.zigTypeTag() == .Struct) {1532 const fields = struct_obj.fields.values();
2350 const fields = ty.structFields().values();1533 assert(fields.len == a_field_vals.len);
2351 assert(fields.len == a_field_vals.len);1534 for (fields, 0..) |field, i| {
2352 for (fields, 0..) |field, i| {1535 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {
2353 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {1536 return false;
2354 return false;1537 }
2355 }1538 }
2356 }1539 return true;
2357 return true;1540 },
1541 else => {},
2358 }1542 }
23591543
2360 const elem_ty = ty.childType();1544 const elem_ty = ty.childType(mod);
2361 for (a_field_vals, 0..) |a_elem, i| {1545 for (a_field_vals, 0..) |a_elem, i| {
2362 const b_elem = b_field_vals[i];1546 const b_elem = b_field_vals[i];
23631547
...@@ -2370,9 +1554,9 @@ pub const Value = extern union {...@@ -2370,9 +1554,9 @@ pub const Value = extern union {
2370 .@"union" => {1554 .@"union" => {
2371 const a_union = a.castTag(.@"union").?.data;1555 const a_union = a.castTag(.@"union").?.data;
2372 const b_union = b.castTag(.@"union").?.data;1556 const b_union = b.castTag(.@"union").?.data;
2373 switch (ty.containerLayout()) {1557 switch (ty.containerLayout(mod)) {
2374 .Packed, .Extern => {1558 .Packed, .Extern => {
2375 const tag_ty = ty.unionTagTypeHypothetical();1559 const tag_ty = ty.unionTagTypeHypothetical(mod);
2376 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {1560 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {
2377 // In this case, we must disregard mismatching tags and compare1561 // In this case, we must disregard mismatching tags and compare
2378 // based on the in-memory bytes of the payloads.1562 // based on the in-memory bytes of the payloads.
...@@ -2380,7 +1564,7 @@ pub const Value = extern union {...@@ -2380,7 +1564,7 @@ pub const Value = extern union {
2380 }1564 }
2381 },1565 },
2382 .Auto => {1566 .Auto => {
2383 const tag_ty = ty.unionTagTypeHypothetical();1567 const tag_ty = ty.unionTagTypeHypothetical(mod);
2384 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {1568 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {
2385 return false;1569 return false;
2386 }1570 }
...@@ -2390,122 +1574,91 @@ pub const Value = extern union {...@@ -2390,122 +1574,91 @@ pub const Value = extern union {
2390 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);1574 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);
2391 },1575 },
2392 else => {},1576 else => {},
2393 } else if (b_tag == .null_value or b_tag == .@"error") {1577 };
2394 return false;
2395 } else if (a_tag == .undef or b_tag == .undef) {
2396 return false;
2397 }
23981578
2399 if (a.pointerDecl()) |a_decl| {1579 if (a.pointerDecl(mod)) |a_decl| {
2400 if (b.pointerDecl()) |b_decl| {1580 if (b.pointerDecl(mod)) |b_decl| {
2401 return a_decl == b_decl;1581 return a_decl == b_decl;
2402 } else {1582 } else {
2403 return false;1583 return false;
2404 }1584 }
2405 } else if (b.pointerDecl()) |_| {1585 } else if (b.pointerDecl(mod)) |_| {
2406 return false;1586 return false;
2407 }1587 }
24081588
2409 switch (ty.zigTypeTag()) {1589 switch (ty.zigTypeTag(mod)) {
2410 .Type => {1590 .Type => {
2411 var buf_a: ToTypeBuffer = undefined;1591 const a_type = a.toType();
2412 var buf_b: ToTypeBuffer = undefined;1592 const b_type = b.toType();
2413 const a_type = a.toType(&buf_a);
2414 const b_type = b.toType(&buf_b);
2415 return a_type.eql(b_type, mod);1593 return a_type.eql(b_type, mod);
2416 },1594 },
2417 .Enum => {1595 .Enum => {
2418 var buf_a: Payload.U64 = undefined;1596 const a_val = try a.enumToInt(ty, mod);
2419 var buf_b: Payload.U64 = undefined;1597 const b_val = try b.enumToInt(ty, mod);
2420 const a_val = a.enumToInt(ty, &buf_a);1598 const int_ty = ty.intTagType(mod);
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);
2424 return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, opt_sema);1599 return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, opt_sema);
2425 },1600 },
2426 .Array, .Vector => {1601 .Array, .Vector => {
2427 const len = ty.arrayLen();1602 const len = ty.arrayLen(mod);
2428 const elem_ty = ty.childType();1603 const elem_ty = ty.childType(mod);
2429 var i: usize = 0;1604 var i: usize = 0;
2430 var a_buf: ElemValueBuffer = undefined;
2431 var b_buf: ElemValueBuffer = undefined;
2432 while (i < len) : (i += 1) {1605 while (i < len) : (i += 1) {
2433 const a_elem = elemValueBuffer(a, mod, i, &a_buf);1606 const a_elem = try elemValue(a, mod, i);
2434 const b_elem = elemValueBuffer(b, mod, i, &b_buf);1607 const b_elem = try elemValue(b, mod, i);
2435 if (!(try eqlAdvanced(a_elem, elem_ty, b_elem, elem_ty, mod, opt_sema))) {1608 if (!(try eqlAdvanced(a_elem, elem_ty, b_elem, elem_ty, mod, opt_sema))) {
2436 return false;1609 return false;
2437 }1610 }
2438 }1611 }
2439 return true;1612 return true;
2440 },1613 },
2441 .Pointer => switch (ty.ptrSize()) {1614 .Pointer => switch (ty.ptrSize(mod)) {
2442 .Slice => {1615 .Slice => {
2443 const a_len = switch (a_ty.ptrSize()) {1616 const a_len = switch (a_ty.ptrSize(mod)) {
2444 .Slice => a.sliceLen(mod),1617 .Slice => a.sliceLen(mod),
2445 .One => a_ty.childType().arrayLen(),1618 .One => a_ty.childType(mod).arrayLen(mod),
2446 else => unreachable,1619 else => unreachable,
2447 };1620 };
2448 if (a_len != b.sliceLen(mod)) {1621 if (a_len != b.sliceLen(mod)) {
2449 return false;1622 return false;
2450 }1623 }
24511624
2452 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;1625 const ptr_ty = ty.slicePtrFieldType(mod);
2453 const ptr_ty = ty.slicePtrFieldType(&ptr_buf);1626 const a_ptr = switch (a_ty.ptrSize(mod)) {
2454 const a_ptr = switch (a_ty.ptrSize()) {1627 .Slice => a.slicePtr(mod),
2455 .Slice => a.slicePtr(),
2456 .One => a,1628 .One => a,
2457 else => unreachable,1629 else => unreachable,
2458 };1630 };
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);
2460 },1632 },
2461 .Many, .C, .One => {},1633 .Many, .C, .One => {},
2462 },1634 },
2463 .Struct => {1635 .Struct => {
2464 // A struct can be represented with one of:1636 // A struct can be represented with one of:
2465 // .empty_struct_value,
2466 // .the_one_possible_value,1637 // .the_one_possible_value,
2467 // .aggregate,1638 // .aggregate,
2468 // Note that we already checked above for matching tags, e.g. both .aggregate.1639 // 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;
2470 },1641 },
2471 .Union => {1642 .Union => {
2472 // Here we have to check for value equality, as-if `a` has been coerced to `ty`.1643 // 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) {
2474 return true;1645 return true;
2475 }1646 }
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 }
2494 return false;1647 return false;
2495 },1648 },
2496 .Float => {1649 .Float => {
2497 switch (ty.floatBits(target)) {1650 switch (ty.floatBits(target)) {
2498 16 => return @bitCast(u16, a.toFloat(f16)) == @bitCast(u16, b.toFloat(f16)),1651 16 => return @bitCast(u16, a.toFloat(f16, mod)) == @bitCast(u16, b.toFloat(f16, mod)),
2499 32 => return @bitCast(u32, a.toFloat(f32)) == @bitCast(u32, b.toFloat(f32)),1652 32 => return @bitCast(u32, a.toFloat(f32, mod)) == @bitCast(u32, b.toFloat(f32, mod)),
2500 64 => return @bitCast(u64, a.toFloat(f64)) == @bitCast(u64, b.toFloat(f64)),1653 64 => return @bitCast(u64, a.toFloat(f64, mod)) == @bitCast(u64, b.toFloat(f64, mod)),
2501 80 => return @bitCast(u80, a.toFloat(f80)) == @bitCast(u80, b.toFloat(f80)),1654 80 => return @bitCast(u80, a.toFloat(f80, mod)) == @bitCast(u80, b.toFloat(f80, mod)),
2502 128 => return @bitCast(u128, a.toFloat(f128)) == @bitCast(u128, b.toFloat(f128)),1655 128 => return @bitCast(u128, a.toFloat(f128, mod)) == @bitCast(u128, b.toFloat(f128, mod)),
2503 else => unreachable,1656 else => unreachable,
2504 }1657 }
2505 },1658 },
2506 .ComptimeFloat => {1659 .ComptimeFloat => {
2507 const a_float = a.toFloat(f128);1660 const a_float = a.toFloat(f128, mod);
2508 const b_float = b.toFloat(f128);1661 const b_float = b.toFloat(f128, mod);
25091662
2510 const a_nan = std.math.isNan(a_float);1663 const a_nan = std.math.isNan(a_float);
2511 const b_nan = std.math.isNan(b_float);1664 const b_nan = std.math.isNan(b_float);
...@@ -2514,570 +1667,215 @@ pub const Value = extern union {...@@ -2514,570 +1667,215 @@ pub const Value = extern union {
2514 if (a_nan) return true;1667 if (a_nan) return true;
2515 return a_float == b_float;1668 return a_float == b_float;
2516 },1669 },
2517 .Optional => if (a_tag != .null_value and b_tag == .opt_payload) {1670 .Optional,
2518 var sub_pl: Payload.SubValue = .{1671 .ErrorUnion,
2519 .base = .{ .tag = b.tag() },1672 => unreachable, // handled by InternPool
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 },
2533 else => {},1673 else => {},
2534 }1674 }
2535 if (a_tag == .null_value or a_tag == .@"error") return false;1675 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
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 }
2683 }1676 }
26841677
2685 /// This is a more conservative hash function that produces equal hashes for values1678 pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool {
2686 /// that can coerce into each other.1679 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2687 /// This function is used by hash maps and so treats floating-point NaNs as equal1680 .ptr => |ptr| switch (ptr.addr) {
2688 /// to each other, and not equal to other floating-point values.1681 .mut_decl, .comptime_field => true,
2689 pub fn hashUncoerced(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {1682 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isComptimeMutablePtr(mod),
2690 if (val.isUndef()) return;1683 .elem, .field => |base_index| base_index.base.toValue().isComptimeMutablePtr(mod),
2691 // The value is runtime-known and shouldn't affect the hash.1684 else => false,
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);
2734 },1685 },
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
2785 else => false,1686 else => false,
2786 };1687 };
2787 }1688 }
27881689
2789 pub fn canMutateComptimeVarState(val: Value) bool {1690 pub fn canMutateComptimeVarState(val: Value, mod: *Module) bool {
2790 if (val.isComptimeMutablePtr()) return true;1691 return val.isComptimeMutablePtr(mod) or switch (val.toIntern()) {
2791 switch (val.tag()) {1692 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
2792 .repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(),1693 .error_union => |error_union| switch (error_union.val) {
2793 .eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(),1694 .err_name => false,
2794 .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),1695 .payload => |payload| payload.toValue().canMutateComptimeVarState(mod),
2795 .opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(),1696 },
2796 .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),1697 .ptr => |ptr| switch (ptr.addr) {
2797 .aggregate => {1698 .eu_payload, .opt_payload => |base| base.toValue().canMutateComptimeVarState(mod),
2798 const fields = val.castTag(.aggregate).?.data;1699 else => false,
2799 for (fields) |field| {1700 },
2800 if (field.canMutateComptimeVarState()) return true;1701 .opt => |opt| switch (opt.val) {
2801 }1702 .none => false,
2802 return 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,
2803 },1710 },
2804 .@"union" => return val.cast(Payload.Union).?.data.val.canMutateComptimeVarState(),1711 };
2805 .slice => return val.castTag(.slice).?.data.ptr.canMutateComptimeVarState(),
2806 else => return false,
2807 }
2808 }1712 }
28091713
2810 /// Gets the decl referenced by this pointer. If the pointer does not point1714 /// Gets the decl referenced by this pointer. If the pointer does not point
2811 /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),1715 /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),
2812 /// this function returns null.1716 /// this function returns null.
2813 pub fn pointerDecl(val: Value) ?Module.Decl.Index {1717 pub fn pointerDecl(val: Value, mod: *Module) ?Module.Decl.Index {
2814 return switch (val.tag()) {1718 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2815 .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl_index,1719 .variable => |variable| variable.decl,
2816 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,1720 .extern_func => |extern_func| extern_func.decl,
2817 .function => val.castTag(.function).?.data.owner_decl,1721 .func => |func| mod.funcPtr(func.index).owner_decl,
2818 .variable => val.castTag(.variable).?.data.owner_decl,1722 .ptr => |ptr| switch (ptr.addr) {
2819 .decl_ref => val.cast(Payload.Decl).?.data,1723 .decl => |decl| decl,
1724 .mut_decl => |mut_decl| mut_decl.decl,
1725 else => null,
1726 },
2820 else => null,1727 else => null,
2821 };1728 };
2822 }1729 }
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 {
2825 var buffer: BigIntSpace = undefined;1732 var buffer: BigIntSpace = undefined;
2826 const big = int_val.toBigInt(&buffer, target);1733 const big = int_val.toBigInt(&buffer, mod);
2827 std.hash.autoHash(hasher, big.positive);1734 std.hash.autoHash(hasher, big.positive);
2828 for (big.limbs) |limb| {1735 for (big.limbs) |limb| {
2829 std.hash.autoHash(hasher, limb);1736 std.hash.autoHash(hasher, limb);
2830 }1737 }
2831 }1738 }
28321739
2833 fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, target: Target) void {1740 pub const slice_ptr_index = 0;
2834 switch (ptr_val.tag()) {1741 pub const slice_len_index = 1;
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),
28841742
2885 else => unreachable,1743 pub fn slicePtr(val: Value, mod: *Module) Value {
2886 }1744 return mod.intern_pool.slicePtr(val.toIntern()).toValue();
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 };
2896 }1745 }
28971746
2898 pub fn sliceLen(val: Value, mod: *Module) u64 {1747 pub fn sliceLen(val: Value, mod: *Module) u64 {
2899 return switch (val.tag()) {1748 const ptr = mod.intern_pool.indexToKey(val.toIntern()).ptr;
2900 .slice => val.castTag(.slice).?.data.len.toUnsignedInt(mod.getTarget()),1749 return switch (ptr.len) {
2901 .decl_ref => {1750 .none => switch (mod.intern_pool.indexToKey(switch (ptr.addr) {
2902 const decl_index = val.castTag(.decl_ref).?.data;1751 .decl => |decl| mod.declPtr(decl).ty.toIntern(),
2903 const decl = mod.declPtr(decl_index);1752 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(),
2904 if (decl.ty.zigTypeTag() == .Array) {1753 .comptime_field => |comptime_field| mod.intern_pool.typeOf(comptime_field),
2905 return decl.ty.arrayLen();1754 else => unreachable,
2906 } else {1755 })) {
2907 return 1;1756 .array_type => |array_type| array_type.len,
2908 }1757 else => 1,
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 }
2926 },1758 },
2927 else => unreachable,1759 else => ptr.len.toValue().toUnsignedInt(mod),
2928 };1760 };
2929 }1761 }
29301762
2931 /// Asserts the value is a single-item pointer to an array, or an array,1763 /// Asserts the value is a single-item pointer to an array, or an array,
2932 /// or an unknown-length pointer, and returns the element value at the index.1764 /// 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 {1765 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {
2934 return elemValueAdvanced(val, mod, index, arena, undefined);1766 return switch (val.ip_index) {
2935 }1767 .none => switch (val.tag()) {
29361768 .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]),
2937 pub const ElemValueBuffer = Payload.U64;1769 .repeated => val.castTag(.repeated).?.data,
29381770 .aggregate => val.castTag(.aggregate).?.data[index],
2939 pub fn elemValueBuffer(val: Value, mod: *Module, index: usize, buffer: *ElemValueBuffer) Value {1771 .slice => val.castTag(.slice).?.data.ptr.elemValue(mod, index),
2940 return elemValueAdvanced(val, mod, index, null, buffer) catch unreachable;1772 else => 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);
3000 },1773 },
3001 .field_ptr => {1774 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
3002 const data = val.castTag(.field_ptr).?.data;1775 .undef => |ty| (try mod.intern(.{
3003 if (data.container_ptr.pointerDecl()) |decl_index| {1776 .undef = ty.toType().elemType2(mod).toIntern(),
3004 const container_decl = mod.declPtr(decl_index);1777 })).toValue(),
3005 const field_type = data.container_ty.structFieldType(data.field_index);1778 .ptr => |ptr| switch (ptr.addr) {
3006 const field_val = container_decl.val.fieldValue(field_type, data.field_index);1779 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
3007 return field_val.elemValueAdvanced(mod, index, arena, buffer);1780 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
3008 } else unreachable;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,
3009 },1807 },
1808 };
1809 }
30101810
3011 // The child type of arrays which have only one possible value need1811 pub fn isLazyAlign(val: Value, mod: *Module) bool {
3012 // to have only one possible value itself.1812 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
3013 .the_only_possible_value => return val,1813 .int => |int| int.storage == .lazy_align,
30141814 else => false,
3015 .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),1815 };
3016 .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),1816 }
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),
30201817
3021 // These values will implicitly be treated as `repeated`.1818 pub fn isLazySize(val: Value, mod: *Module) bool {
3022 .zero,1819 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
3023 .one,1820 .int => |int| int.storage == .lazy_size,
3024 .bool_false,1821 else => false,
3025 .bool_true,1822 };
3026 .int_i64,1823 }
3027 .int_u64,
3028 => return val,
30291824
3030 else => unreachable,1825 pub fn isRuntimeValue(val: Value, mod: *Module) bool {
3031 }1826 return mod.intern_pool.indexToKey(val.toIntern()) == .runtime_value;
3032 }1827 }
30331828
3034 /// Returns true if a Value is backed by a variable1829 /// Returns true if a Value is backed by a variable
3035 pub fn isVariable(1830 pub fn isVariable(val: Value, mod: *Module) bool {
3036 val: Value,1831 return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) {
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
3057 .variable => true,1832 .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 },
3058 else => false,1849 else => false,
3059 };1850 };
3060 }1851 }
30611852
3062 pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool {1853 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())) {
3064 .variable => false,1855 .variable => false,
3065 else => val.isPtrToThreadLocalInner(mod),1856 else => val.isPtrToThreadLocalInner(mod),
3066 };1857 };
3067 }1858 }
30681859
3069 fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {1860 pub fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {
3070 return switch (val.tag()) {1861 return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) {
3071 .slice => val.castTag(.slice).?.data.ptr.isPtrToThreadLocalInner(mod),1862 .variable => |variable| variable.is_threadlocal,
3072 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isPtrToThreadLocalInner(mod),1863 .ptr => |ptr| switch (ptr.addr) {
3073 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isPtrToThreadLocalInner(mod),1864 .decl => |decl_index| {
3074 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),1865 const decl = mod.declPtr(decl_index);
3075 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),1866 assert(decl.has_tv);
3076 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),1867 return decl.val.isPtrToThreadLocalInner(mod);
3077 .decl_ref => mod.declPtr(val.castTag(.decl_ref).?.data).val.isPtrToThreadLocalInner(mod),1868 },
3078 .decl_ref_mut => mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.isPtrToThreadLocalInner(mod),1869 .mut_decl => |mut_decl| {
30791870 const decl = mod.declPtr(mut_decl.decl);
3080 .variable => val.castTag(.variable).?.data.is_threadlocal,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 },
3081 else => false,1879 else => false,
3082 };1880 };
3083 }1881 }
...@@ -3090,238 +1888,239 @@ pub const Value = extern union {...@@ -3090,238 +1888,239 @@ pub const Value = extern union {
3090 start: usize,1888 start: usize,
3091 end: usize,1889 end: usize,
3092 ) error{OutOfMemory}!Value {1890 ) error{OutOfMemory}!Value {
3093 return switch (val.tag()) {1891 // TODO: write something like getCoercedInts to avoid needing to dupe
3094 .empty_array_sentinel => if (start == 0 and end == 1) val else Value.initTag(.empty_array),1892 return switch (val.ip_index) {
3095 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),1893 .none => switch (val.tag()) {
3096 .str_lit => {1894 .slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
3097 const str_lit = val.castTag(.str_lit).?.data;1895 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
3098 return Tag.str_lit.create(arena, .{1896 .repeated => val,
3099 .index = @intCast(u32, str_lit.index + start),1897 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),
3100 .len = @intCast(u32, end - start),1898 else => unreachable,
3101 });
3102 },1899 },
3103 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),1900 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
3104 .slice => sliceArray(val.castTag(.slice).?.data.ptr, mod, arena, start, end),1901 .ptr => |ptr| switch (ptr.addr) {
31051902 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
3106 .decl_ref => sliceArray(mod.declPtr(val.castTag(.decl_ref).?.data).val, mod, arena, start, end),1903 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()
3107 .decl_ref_mut => sliceArray(mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val, mod, arena, start, end),1904 .sliceArray(mod, arena, start, end),
3108 .comptime_field_ptr => sliceArray(val.castTag(.comptime_field_ptr).?.data.field_val, mod, arena, start, end),1905 .comptime_field => |comptime_field| comptime_field.toValue()
3109 .elem_ptr => blk: {1906 .sliceArray(mod, arena, start, end),
3110 const elem_ptr = val.castTag(.elem_ptr).?.data;1907 .elem => |elem| elem.base.toValue()
3111 break :blk sliceArray(elem_ptr.array_ptr, mod, arena, start + elem_ptr.index, end + elem_ptr.index);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,
3112 },1931 },
3113
3114 .repeated,
3115 .the_only_possible_value,
3116 => val,
3117
3118 else => unreachable,
3119 };1932 };
3120 }1933 }
31211934
3122 pub fn fieldValue(val: Value, ty: Type, index: usize) Value {1935 pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {
3123 switch (val.tag()) {1936 return switch (val.ip_index) {
3124 .aggregate => {1937 .none => switch (val.tag()) {
3125 const field_values = val.castTag(.aggregate).?.data;1938 .aggregate => {
3126 return field_values[index];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,
3127 },1948 },
3128 .@"union" => {1949 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
3129 const payload = val.castTag(.@"union").?.data;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(),
3130 // TODO assert the tag is correct1961 // TODO assert the tag is correct
3131 return payload.val;1962 .un => |un| un.val.toValue(),
3132 },1963 else => unreachable,
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;
3145 },1964 },
3146 .undef => return Value.undef,1965 };
3147
3148 else => unreachable,
3149 }
3150 }1966 }
31511967
3152 pub fn unionTag(val: Value) Value {1968 pub fn unionTag(val: Value, mod: *Module) Value {
3153 switch (val.tag()) {1969 if (val.ip_index == .none) return val.castTag(.@"union").?.data.tag;
3154 .undef, .enum_field_index => return val,1970 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
3155 .@"union" => return val.castTag(.@"union").?.data.tag,1971 .undef, .enum_tag => val,
1972 .un => |un| un.tag.toValue(),
3156 else => unreachable,1973 else => unreachable,
3157 }1974 };
3158 }1975 }
31591976
3160 /// Returns a pointer to the element value at the index.1977 /// Returns a pointer to the element value at the index.
3161 pub fn elemPtr(1978 pub fn elemPtr(
3162 val: Value,1979 val: Value,
3163 ty: Type,1980 elem_ptr_ty: Type,
3164 arena: Allocator,
3165 index: usize,1981 index: usize,
3166 mod: *Module,1982 mod: *Module,
3167 ) Allocator.Error!Value {1983 ) Allocator.Error!Value {
3168 const elem_ty = ty.elemType2();1984 const elem_ty = elem_ptr_ty.childType(mod);
3169 const ptr_val = switch (val.tag()) {1985 const ptr_val = switch (mod.intern_pool.indexToKey(val.toIntern())) {
3170 .slice => val.castTag(.slice).?.data.ptr,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 },
3171 else => val,2003 else => val,
3172 };2004 };
31732005 var ptr_ty_key = mod.intern_pool.indexToKey(elem_ptr_ty.toIntern()).ptr_type;
3174 if (ptr_val.tag() == .elem_ptr) {2006 assert(ptr_ty_key.flags.size != .Slice);
3175 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;2007 ptr_ty_key.flags.size = .Many;
3176 if (elem_ptr.elem_ty.eql(elem_ty, mod)) {2008 return (try mod.intern(.{ .ptr = .{
3177 return Tag.elem_ptr.create(arena, .{2009 .ty = elem_ptr_ty.toIntern(),
3178 .array_ptr = elem_ptr.array_ptr,2010 .addr = .{ .elem = .{
3179 .elem_ty = elem_ptr.elem_ty,2011 .base = (try mod.getCoerced(ptr_val, try mod.ptrType(ptr_ty_key))).toIntern(),
3180 .index = elem_ptr.index + index,2012 .index = index,
3181 });2013 } },
3182 }2014 } })).toValue();
3183 }2015 }
3184 return Tag.elem_ptr.create(arena, .{2016
3185 .array_ptr = ptr_val,2017 pub fn isUndef(val: Value, mod: *Module) bool {
3186 .elem_ty = elem_ty,2018 if (val.ip_index == .none) return false;
3187 .index = index,2019 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
3188 });2020 .undef => true,
3189 }2021 .simple_value => |v| v == .undefined,
31902022 else => false,
3191 pub fn isUndef(self: Value) bool {2023 };
3192 return self.tag() == .undef;
3193 }2024 }
31942025
3195 /// TODO: check for cases such as array that is not marked undef but all the element2026 /// TODO: check for cases such as array that is not marked undef but all the element
3196 /// values are marked undef, or struct that is not marked undef but all fields are marked2027 /// values are marked undef, or struct that is not marked undef but all fields are marked
3197 /// undef, etc.2028 /// undef, etc.
3198 pub fn isUndefDeep(self: Value) bool {2029 pub fn isUndefDeep(val: Value, mod: *Module) bool {
3199 return self.isUndef();2030 return val.isUndef(mod);
3200 }2031 }
32012032
3202 /// Returns true if any value contained in `self` is undefined.2033 /// 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 element2034 pub fn anyUndef(val: Value, mod: *Module) !bool {
3204 /// values are marked undef, or struct that is not marked undef but all fields are marked2035 if (val.ip_index == .none) return false;
3205 /// undef, etc.2036 return switch (val.toIntern()) {
3206 pub fn anyUndef(self: Value, mod: *Module) bool {2037 .undef => true,
3207 switch (self.tag()) {2038 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
3208 .slice => {2039 .undef => true,
3209 const payload = self.castTag(.slice).?;2040 .simple_value => |v| v == .undefined,
3210 const len = payload.data.len.toUnsignedInt(mod.getTarget());2041 .ptr => |ptr| switch (ptr.len) {
32112042 .none => false,
3212 var elem_value_buf: ElemValueBuffer = undefined;2043 else => for (0..@intCast(usize, ptr.len.toValue().toUnsignedInt(mod))) |index| {
3213 var i: usize = 0;2044 if (try (try val.elemValue(mod, index)).anyUndef(mod)) break true;
3214 while (i < len) : (i += 1) {2045 } else false,
3215 const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf);2046 },
3216 if (elem_val.anyUndef(mod)) return true;2047 .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| {
3217 }2048 const elem = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.values()[i];
3218 },2049 if (try anyUndef(elem.toValue(), mod)) break true;
32192050 } else false,
3220 .aggregate => {2051 else => false,
3221 const payload = self.castTag(.aggregate).?;
3222 for (payload.data) |val| {
3223 if (val.anyUndef(mod)) return true;
3224 }
3225 },2052 },
32262053 };
3227 .undef => return true,
3228 else => {},
3229 }
3230
3231 return false;
3232 }2054 }
32332055
3234 /// Asserts the value is not undefined and not unreachable.2056 /// Asserts the value is not undefined and not unreachable.
3235 /// Integer value 0 is considered null because of C pointers.2057 /// C pointers with an integer value of 0 are also considered null.
3236 pub fn isNull(self: Value) bool {2058 pub fn isNull(val: Value, mod: *Module) bool {
3237 return switch (self.tag()) {2059 return switch (val.toIntern()) {
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
3259 .undef => unreachable,2060 .undef => unreachable,
3260 .unreachable_value => unreachable,2061 .unreachable_value => unreachable,
3261 .inferred_alloc => unreachable,2062 .null_value => true,
3262 .inferred_alloc_comptime => unreachable,2063 else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {
32632064 .undef => unreachable,
3264 else => false,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 },
3265 };2075 };
3266 }2076 }
32672077
3268 /// Valid only for error (union) types. Asserts the value is not undefined and not2078 /// Valid only for error (union) types. Asserts the value is not undefined and not unreachable.
3269 /// unreachable. For error unions, prefer `errorUnionIsPayload` to find out whether2079 pub fn getErrorName(val: Value, mod: *const Module) InternPool.OptionalNullTerminatedString {
3270 /// something is an error or not because it works without having to figure out the2080 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
3271 /// string.2081 .err => |err| err.name.toOptional(),
3272 pub fn getError(self: Value) ?[]const u8 {2082 .error_union => |error_union| switch (error_union.val) {
3273 return switch (self.tag()) {2083 .err_name => |err_name| err_name.toOptional(),
3274 .@"error" => self.castTag(.@"error").?.data.name,2084 .payload => .none,
3275 .int_u64 => @panic("TODO"),2085 },
3276 .int_i64 => @panic("TODO"),2086 else => unreachable,
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,
3286 };2087 };
3287 }2088 }
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
3289 /// Assumes the type is an error union. Returns true if and only if the value is2097 /// Assumes the type is an error union. Returns true if and only if the value is
3290 /// the error union payload, not an error.2098 /// the error union payload, not an error.
3291 pub fn errorUnionIsPayload(val: Value) bool {2099 pub fn errorUnionIsPayload(val: Value, mod: *const Module) bool {
3292 return switch (val.tag()) {2100 return mod.intern_pool.indexToKey(val.toIntern()).error_union.val == .payload;
3293 .eu_payload => true,
3294 else => false,
3295
3296 .undef => unreachable,
3297 .inferred_alloc => unreachable,
3298 .inferred_alloc_comptime => unreachable,
3299 };
3300 }2101 }
33012102
3302 /// Value of the optional, null if optional has no payload.2103 /// Value of the optional, null if optional has no payload.
3303 pub fn optionalValue(val: Value) ?Value {2104 pub fn optionalValue(val: Value, mod: *const Module) ?Value {
3304 if (val.isNull()) return null;2105 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
33052106 .opt => |opt| switch (opt.val) {
3306 // Valid for optional representation to be the direct value2107 .none => null,
3307 // and not use opt_payload.2108 else => |payload| payload.toValue(),
3308 return if (val.castTag(.opt_payload)) |p| p.data else val;2109 },
2110 .ptr => val,
2111 else => unreachable,
2112 };
3309 }2113 }
33102114
3311 /// Valid for all types. Asserts the value is not undefined.2115 /// Valid for all types. Asserts the value is not undefined.
3312 pub fn isFloat(self: Value) bool {2116 pub fn isFloat(self: Value, mod: *const Module) bool {
3313 return switch (self.tag()) {2117 return switch (self.toIntern()) {
3314 .undef => unreachable,2118 .undef => unreachable,
3315 .inferred_alloc => unreachable,2119 else => switch (mod.intern_pool.indexToKey(self.toIntern())) {
3316 .inferred_alloc_comptime => unreachable,2120 .undef => unreachable,
33172121 .float => true,
3318 .float_16,2122 else => false,
3319 .float_32,2123 },
3320 .float_64,
3321 .float_80,
3322 .float_128,
3323 => true,
3324 else => false,
3325 };2124 };
3326 }2125 }
33272126
...@@ -3333,79 +2132,59 @@ pub const Value = extern union {...@@ -3333,79 +2132,59 @@ pub const Value = extern union {
3333 }2132 }
33342133
3335 pub fn intToFloatAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {2134 pub fn intToFloatAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
3336 const target = mod.getTarget();2135 if (int_ty.zigTypeTag(mod) == .Vector) {
3337 if (int_ty.zigTypeTag() == .Vector) {2136 const result_data = try arena.alloc(InternPool.Index, int_ty.vectorLen(mod));
3338 const result_data = try arena.alloc(Value, int_ty.vectorLen());2137 const scalar_ty = float_ty.scalarType(mod);
3339 for (result_data, 0..) |*scalar, i| {2138 for (result_data, 0..) |*scalar, i| {
3340 var buf: Value.ElemValueBuffer = undefined;2139 const elem_val = try val.elemValue(mod, i);
3341 const elem_val = val.elemValueBuffer(mod, i, &buf);2140 scalar.* = try (try intToFloatScalar(elem_val, scalar_ty, mod, opt_sema)).intern(scalar_ty, mod);
3342 scalar.* = try intToFloatScalar(elem_val, arena, float_ty.scalarType(), target, opt_sema);
3343 }2141 }
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();
3345 }2146 }
3346 return intToFloatScalar(val, arena, float_ty, target, opt_sema);2147 return intToFloatScalar(val, float_ty, mod, opt_sema);
3347 }2148 }
33482149
3349 pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, target: Target, opt_sema: ?*Sema) !Value {2150 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
3350 switch (val.tag()) {2151 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
3351 .undef, .zero, .one => return val,2152 .undef => (try mod.intern(.{ .undef = float_ty.toIntern() })).toValue(),
3352 .the_only_possible_value => return Value.initTag(.zero), // for i0, u02153 .int => |int| switch (int.storage) {
3353 .int_u64 => {2154 .big_int => |big_int| {
3354 return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);2155 const float = bigIntToFloat(big_int.limbs, big_int.positive);
3355 },2156 return mod.floatValue(float_ty, float);
3356 .int_i64 => {2157 },
3357 return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);2158 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),
3358 },2159 .lazy_align => |ty| if (opt_sema) |sema| {
3359 .int_big_positive => {2160 return intToFloatInner((try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
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);
3373 } else {2161 } else {
3374 return intToFloatInner(ty.abiAlignment(target), arena, float_ty, target);2162 return intToFloatInner(ty.toType().abiAlignment(mod), float_ty, mod);
3375 }2163 },
3376 },2164 .lazy_size => |ty| if (opt_sema) |sema| {
3377 .lazy_size => {2165 return intToFloatInner((try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
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);
3381 } else {2166 } else {
3382 return intToFloatInner(ty.abiSize(target), arena, float_ty, target);2167 return intToFloatInner(ty.toType().abiSize(mod), float_ty, mod);
3383 }2168 },
3384 },2169 },
3385 else => unreachable,2170 else => unreachable,
3386 }2171 };
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 }
3398 }2172 }
33992173
3400 pub fn floatToValue(float: f128, arena: Allocator, dest_ty: Type, target: Target) !Value {2174 fn intToFloatInner(x: anytype, dest_ty: Type, mod: *Module) !Value {
3401 switch (dest_ty.floatBits(target)) {2175 const target = mod.getTarget();
3402 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),2176 const storage: InternPool.Key.Float.Storage = switch (dest_ty.floatBits(target)) {
3403 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),2177 16 => .{ .f16 = @intToFloat(f16, x) },
3404 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),2178 32 => .{ .f32 = @intToFloat(f32, x) },
3405 80 => return Value.Tag.float_80.create(arena, @floatCast(f80, float)),2179 64 => .{ .f64 = @intToFloat(f64, x) },
3406 128 => return Value.Tag.float_128.create(arena, float),2180 80 => .{ .f80 = @intToFloat(f80, x) },
2181 128 => .{ .f128 = @intToFloat(f128, x) },
3407 else => unreachable,2182 else => unreachable,
3408 }2183 };
2184 return (try mod.intern(.{ .float = .{
2185 .ty = dest_ty.toIntern(),
2186 .storage = storage,
2187 } })).toValue();
3409 }2188 }
34102189
3411 fn calcLimbLenFloat(scalar: anytype) usize {2190 fn calcLimbLenFloat(scalar: anytype) usize {
...@@ -3422,22 +2201,6 @@ pub const Value = extern union {...@@ -3422,22 +2201,6 @@ pub const Value = extern union {
3422 wrapped_result: Value,2201 wrapped_result: Value,
3423 };2202 };
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
3441 /// Supports (vectors of) integers only; asserts neither operand is undefined.2204 /// Supports (vectors of) integers only; asserts neither operand is undefined.
3442 pub fn intAddSat(2205 pub fn intAddSat(
3443 lhs: Value,2206 lhs: Value,
...@@ -3446,19 +2209,20 @@ pub const Value = extern union {...@@ -3446,19 +2209,20 @@ pub const Value = extern union {
3446 arena: Allocator,2209 arena: Allocator,
3447 mod: *Module,2210 mod: *Module,
3448 ) !Value {2211 ) !Value {
3449 const target = mod.getTarget();2212 if (ty.zigTypeTag(mod) == .Vector) {
3450 if (ty.zigTypeTag() == .Vector) {2213 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3451 const result_data = try arena.alloc(Value, ty.vectorLen());2214 const scalar_ty = ty.scalarType(mod);
3452 for (result_data, 0..) |*scalar, i| {2215 for (result_data, 0..) |*scalar, i| {
3453 var lhs_buf: Value.ElemValueBuffer = undefined;2216 const lhs_elem = try lhs.elemValue(mod, i);
3454 var rhs_buf: Value.ElemValueBuffer = undefined;2217 const rhs_elem = try rhs.elemValue(mod, i);
3455 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2218 scalar.* = try (try intAddSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
3456 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3457 scalar.* = try intAddSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
3458 }2219 }
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();
3460 }2224 }
3461 return intAddSatScalar(lhs, rhs, ty, arena, target);2225 return intAddSatScalar(lhs, rhs, ty, arena, mod);
3462 }2226 }
34632227
3464 /// Supports integers only; asserts neither operand is undefined.2228 /// Supports integers only; asserts neither operand is undefined.
...@@ -3467,24 +2231,24 @@ pub const Value = extern union {...@@ -3467,24 +2231,24 @@ pub const Value = extern union {
3467 rhs: Value,2231 rhs: Value,
3468 ty: Type,2232 ty: Type,
3469 arena: Allocator,2233 arena: Allocator,
3470 target: Target,2234 mod: *Module,
3471 ) !Value {2235 ) !Value {
3472 assert(!lhs.isUndef());2236 assert(!lhs.isUndef(mod));
3473 assert(!rhs.isUndef());2237 assert(!rhs.isUndef(mod));
34742238
3475 const info = ty.intInfo(target);2239 const info = ty.intInfo(mod);
34762240
3477 var lhs_space: Value.BigIntSpace = undefined;2241 var lhs_space: Value.BigIntSpace = undefined;
3478 var rhs_space: Value.BigIntSpace = undefined;2242 var rhs_space: Value.BigIntSpace = undefined;
3479 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2243 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3480 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2244 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3481 const limbs = try arena.alloc(2245 const limbs = try arena.alloc(
3482 std.math.big.Limb,2246 std.math.big.Limb,
3483 std.math.big.int.calcTwosCompLimbCount(info.bits),2247 std.math.big.int.calcTwosCompLimbCount(info.bits),
3484 );2248 );
3485 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };2249 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3486 result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);2250 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());
3488 }2252 }
34892253
3490 /// Supports (vectors of) integers only; asserts neither operand is undefined.2254 /// Supports (vectors of) integers only; asserts neither operand is undefined.
...@@ -3495,19 +2259,20 @@ pub const Value = extern union {...@@ -3495,19 +2259,20 @@ pub const Value = extern union {
3495 arena: Allocator,2259 arena: Allocator,
3496 mod: *Module,2260 mod: *Module,
3497 ) !Value {2261 ) !Value {
3498 const target = mod.getTarget();2262 if (ty.zigTypeTag(mod) == .Vector) {
3499 if (ty.zigTypeTag() == .Vector) {2263 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3500 const result_data = try arena.alloc(Value, ty.vectorLen());2264 const scalar_ty = ty.scalarType(mod);
3501 for (result_data, 0..) |*scalar, i| {2265 for (result_data, 0..) |*scalar, i| {
3502 var lhs_buf: Value.ElemValueBuffer = undefined;2266 const lhs_elem = try lhs.elemValue(mod, i);
3503 var rhs_buf: Value.ElemValueBuffer = undefined;2267 const rhs_elem = try rhs.elemValue(mod, i);
3504 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2268 scalar.* = try (try intSubSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
3505 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3506 scalar.* = try intSubSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
3507 }2269 }
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();
3509 }2274 }
3510 return intSubSatScalar(lhs, rhs, ty, arena, target);2275 return intSubSatScalar(lhs, rhs, ty, arena, mod);
3511 }2276 }
35122277
3513 /// Supports integers only; asserts neither operand is undefined.2278 /// Supports integers only; asserts neither operand is undefined.
...@@ -3516,24 +2281,24 @@ pub const Value = extern union {...@@ -3516,24 +2281,24 @@ pub const Value = extern union {
3516 rhs: Value,2281 rhs: Value,
3517 ty: Type,2282 ty: Type,
3518 arena: Allocator,2283 arena: Allocator,
3519 target: Target,2284 mod: *Module,
3520 ) !Value {2285 ) !Value {
3521 assert(!lhs.isUndef());2286 assert(!lhs.isUndef(mod));
3522 assert(!rhs.isUndef());2287 assert(!rhs.isUndef(mod));
35232288
3524 const info = ty.intInfo(target);2289 const info = ty.intInfo(mod);
35252290
3526 var lhs_space: Value.BigIntSpace = undefined;2291 var lhs_space: Value.BigIntSpace = undefined;
3527 var rhs_space: Value.BigIntSpace = undefined;2292 var rhs_space: Value.BigIntSpace = undefined;
3528 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2293 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3529 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2294 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3530 const limbs = try arena.alloc(2295 const limbs = try arena.alloc(
3531 std.math.big.Limb,2296 std.math.big.Limb,
3532 std.math.big.int.calcTwosCompLimbCount(info.bits),2297 std.math.big.int.calcTwosCompLimbCount(info.bits),
3533 );2298 );
3534 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };2299 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3535 result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);2300 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());
3537 }2302 }
35382303
3539 pub fn intMulWithOverflow(2304 pub fn intMulWithOverflow(
...@@ -3543,25 +2308,30 @@ pub const Value = extern union {...@@ -3543,25 +2308,30 @@ pub const Value = extern union {
3543 arena: Allocator,2308 arena: Allocator,
3544 mod: *Module,2309 mod: *Module,
3545 ) !OverflowArithmeticResult {2310 ) !OverflowArithmeticResult {
3546 const target = mod.getTarget();2311 if (ty.zigTypeTag(mod) == .Vector) {
3547 if (ty.zigTypeTag() == .Vector) {2312 const vec_len = ty.vectorLen(mod);
3548 const overflowed_data = try arena.alloc(Value, ty.vectorLen());2313 const overflowed_data = try arena.alloc(InternPool.Index, vec_len);
3549 const result_data = try arena.alloc(Value, ty.vectorLen());2314 const result_data = try arena.alloc(InternPool.Index, vec_len);
3550 for (result_data, 0..) |*scalar, i| {2315 const scalar_ty = ty.scalarType(mod);
3551 var lhs_buf: Value.ElemValueBuffer = undefined;2316 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
3552 var rhs_buf: Value.ElemValueBuffer = undefined;2317 const lhs_elem = try lhs.elemValue(mod, i);
3553 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2318 const rhs_elem = try rhs.elemValue(mod, i);
3554 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);2319 const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod);
3555 const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);2320 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
3556 overflowed_data[i] = of_math_result.overflow_bit;2321 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
3557 scalar.* = of_math_result.wrapped_result;
3558 }2322 }
3559 return OverflowArithmeticResult{2323 return OverflowArithmeticResult{
3560 .overflow_bit = try Value.Tag.aggregate.create(arena, overflowed_data),2324 .overflow_bit = (try mod.intern(.{ .aggregate = .{
3561 .wrapped_result = try Value.Tag.aggregate.create(arena, result_data),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(),
3562 };2332 };
3563 }2333 }
3564 return intMulWithOverflowScalar(lhs, rhs, ty, arena, target);2334 return intMulWithOverflowScalar(lhs, rhs, ty, arena, mod);
3565 }2335 }
35662336
3567 pub fn intMulWithOverflowScalar(2337 pub fn intMulWithOverflowScalar(
...@@ -3569,14 +2339,14 @@ pub const Value = extern union {...@@ -3569,14 +2339,14 @@ pub const Value = extern union {
3569 rhs: Value,2339 rhs: Value,
3570 ty: Type,2340 ty: Type,
3571 arena: Allocator,2341 arena: Allocator,
3572 target: Target,2342 mod: *Module,
3573 ) !OverflowArithmeticResult {2343 ) !OverflowArithmeticResult {
3574 const info = ty.intInfo(target);2344 const info = ty.intInfo(mod);
35752345
3576 var lhs_space: Value.BigIntSpace = undefined;2346 var lhs_space: Value.BigIntSpace = undefined;
3577 var rhs_space: Value.BigIntSpace = undefined;2347 var rhs_space: Value.BigIntSpace = undefined;
3578 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2348 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3579 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2349 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3580 const limbs = try arena.alloc(2350 const limbs = try arena.alloc(
3581 std.math.big.Limb,2351 std.math.big.Limb,
3582 lhs_bigint.limbs.len + rhs_bigint.limbs.len,2352 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
...@@ -3594,8 +2364,8 @@ pub const Value = extern union {...@@ -3594,8 +2364,8 @@ pub const Value = extern union {
3594 }2364 }
35952365
3596 return OverflowArithmeticResult{2366 return OverflowArithmeticResult{
3597 .overflow_bit = boolToInt(overflowed),2367 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
3598 .wrapped_result = try fromBigInt(arena, result_bigint.toConst()),2368 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
3599 };2369 };
3600 }2370 }
36012371
...@@ -3607,16 +2377,18 @@ pub const Value = extern union {...@@ -3607,16 +2377,18 @@ pub const Value = extern union {
3607 arena: Allocator,2377 arena: Allocator,
3608 mod: *Module,2378 mod: *Module,
3609 ) !Value {2379 ) !Value {
3610 if (ty.zigTypeTag() == .Vector) {2380 if (ty.zigTypeTag(mod) == .Vector) {
3611 const result_data = try arena.alloc(Value, ty.vectorLen());2381 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2382 const scalar_ty = ty.scalarType(mod);
3612 for (result_data, 0..) |*scalar, i| {2383 for (result_data, 0..) |*scalar, i| {
3613 var lhs_buf: Value.ElemValueBuffer = undefined;2384 const lhs_elem = try lhs.elemValue(mod, i);
3614 var rhs_buf: Value.ElemValueBuffer = undefined;2385 const rhs_elem = try rhs.elemValue(mod, i);
3615 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2386 scalar.* = try (try numberMulWrapScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
3616 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3617 scalar.* = try numberMulWrapScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod);
3618 }2387 }
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();
3620 }2392 }
3621 return numberMulWrapScalar(lhs, rhs, ty, arena, mod);2393 return numberMulWrapScalar(lhs, rhs, ty, arena, mod);
3622 }2394 }
...@@ -3629,10 +2401,10 @@ pub const Value = extern union {...@@ -3629,10 +2401,10 @@ pub const Value = extern union {
3629 arena: Allocator,2401 arena: Allocator,
3630 mod: *Module,2402 mod: *Module,
3631 ) !Value {2403 ) !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) {2406 if (ty.zigTypeTag(mod) == .ComptimeInt) {
3635 return intMul(lhs, rhs, ty, arena, mod);2407 return intMul(lhs, rhs, ty, undefined, arena, mod);
3636 }2408 }
36372409
3638 if (ty.isAnyFloat()) {2410 if (ty.isAnyFloat()) {
...@@ -3651,19 +2423,20 @@ pub const Value = extern union {...@@ -3651,19 +2423,20 @@ pub const Value = extern union {
3651 arena: Allocator,2423 arena: Allocator,
3652 mod: *Module,2424 mod: *Module,
3653 ) !Value {2425 ) !Value {
3654 const target = mod.getTarget();2426 if (ty.zigTypeTag(mod) == .Vector) {
3655 if (ty.zigTypeTag() == .Vector) {2427 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3656 const result_data = try arena.alloc(Value, ty.vectorLen());2428 const scalar_ty = ty.scalarType(mod);
3657 for (result_data, 0..) |*scalar, i| {2429 for (result_data, 0..) |*scalar, i| {
3658 var lhs_buf: Value.ElemValueBuffer = undefined;2430 const lhs_elem = try lhs.elemValue(mod, i);
3659 var rhs_buf: Value.ElemValueBuffer = undefined;2431 const rhs_elem = try rhs.elemValue(mod, i);
3660 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2432 scalar.* = try (try intMulSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
3661 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3662 scalar.* = try intMulSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
3663 }2433 }
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();
3665 }2438 }
3666 return intMulSatScalar(lhs, rhs, ty, arena, target);2439 return intMulSatScalar(lhs, rhs, ty, arena, mod);
3667 }2440 }
36682441
3669 /// Supports (vectors of) integers only; asserts neither operand is undefined.2442 /// Supports (vectors of) integers only; asserts neither operand is undefined.
...@@ -3672,17 +2445,17 @@ pub const Value = extern union {...@@ -3672,17 +2445,17 @@ pub const Value = extern union {
3672 rhs: Value,2445 rhs: Value,
3673 ty: Type,2446 ty: Type,
3674 arena: Allocator,2447 arena: Allocator,
3675 target: Target,2448 mod: *Module,
3676 ) !Value {2449 ) !Value {
3677 assert(!lhs.isUndef());2450 assert(!lhs.isUndef(mod));
3678 assert(!rhs.isUndef());2451 assert(!rhs.isUndef(mod));
36792452
3680 const info = ty.intInfo(target);2453 const info = ty.intInfo(mod);
36812454
3682 var lhs_space: Value.BigIntSpace = undefined;2455 var lhs_space: Value.BigIntSpace = undefined;
3683 var rhs_space: Value.BigIntSpace = undefined;2456 var rhs_space: Value.BigIntSpace = undefined;
3684 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2457 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3685 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2458 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3686 const limbs = try arena.alloc(2459 const limbs = try arena.alloc(
3687 std.math.big.Limb,2460 std.math.big.Limb,
3688 std.math.max(2461 std.math.max(
...@@ -3698,28 +2471,28 @@ pub const Value = extern union {...@@ -3698,28 +2471,28 @@ pub const Value = extern union {
3698 );2471 );
3699 result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, arena);2472 result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, arena);
3700 result_bigint.saturate(result_bigint.toConst(), info.signedness, info.bits);2473 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());
3702 }2475 }
37032476
3704 /// Supports both floats and ints; handles undefined.2477 /// Supports both floats and ints; handles undefined.
3705 pub fn numberMax(lhs: Value, rhs: Value, target: Target) Value {2478 pub fn numberMax(lhs: Value, rhs: Value, mod: *Module) Value {
3706 if (lhs.isUndef() or rhs.isUndef()) return undef;2479 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return undef;
3707 if (lhs.isNan()) return rhs;2480 if (lhs.isNan(mod)) return rhs;
3708 if (rhs.isNan()) return lhs;2481 if (rhs.isNan(mod)) return lhs;
37092482
3710 return switch (order(lhs, rhs, target)) {2483 return switch (order(lhs, rhs, mod)) {
3711 .lt => rhs,2484 .lt => rhs,
3712 .gt, .eq => lhs,2485 .gt, .eq => lhs,
3713 };2486 };
3714 }2487 }
37152488
3716 /// Supports both floats and ints; handles undefined.2489 /// Supports both floats and ints; handles undefined.
3717 pub fn numberMin(lhs: Value, rhs: Value, target: Target) Value {2490 pub fn numberMin(lhs: Value, rhs: Value, mod: *Module) Value {
3718 if (lhs.isUndef() or rhs.isUndef()) return undef;2491 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return undef;
3719 if (lhs.isNan()) return rhs;2492 if (lhs.isNan(mod)) return rhs;
3720 if (rhs.isNan()) return lhs;2493 if (rhs.isNan(mod)) return lhs;
37212494
3722 return switch (order(lhs, rhs, target)) {2495 return switch (order(lhs, rhs, mod)) {
3723 .lt => lhs,2496 .lt => lhs,
3724 .gt, .eq => rhs,2497 .gt, .eq => rhs,
3725 };2498 };
...@@ -3727,24 +2500,27 @@ pub const Value = extern union {...@@ -3727,24 +2500,27 @@ pub const Value = extern union {
37272500
3728 /// operands must be (vectors of) integers; handles undefined scalars.2501 /// operands must be (vectors of) integers; handles undefined scalars.
3729 pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2502 pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3730 const target = mod.getTarget();2503 if (ty.zigTypeTag(mod) == .Vector) {
3731 if (ty.zigTypeTag() == .Vector) {2504 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3732 const result_data = try arena.alloc(Value, ty.vectorLen());2505 const scalar_ty = ty.scalarType(mod);
3733 for (result_data, 0..) |*scalar, i| {2506 for (result_data, 0..) |*scalar, i| {
3734 var buf: Value.ElemValueBuffer = undefined;2507 const elem_val = try val.elemValue(mod, i);
3735 const elem_val = val.elemValueBuffer(mod, i, &buf);2508 scalar.* = try (try bitwiseNotScalar(elem_val, scalar_ty, arena, mod)).intern(scalar_ty, mod);
3736 scalar.* = try bitwiseNotScalar(elem_val, ty.scalarType(), arena, target);
3737 }2509 }
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();
3739 }2514 }
3740 return bitwiseNotScalar(val, ty, arena, target);2515 return bitwiseNotScalar(val, ty, arena, mod);
3741 }2516 }
37422517
3743 /// operands must be integers; handles undefined.2518 /// operands must be integers; handles undefined.
3744 pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, target: Target) !Value {2519 pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3745 if (val.isUndef()) return Value.initTag(.undef);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
3749 if (info.bits == 0) {2525 if (info.bits == 0) {
3750 return val;2526 return val;
...@@ -3753,7 +2529,7 @@ pub const Value = extern union {...@@ -3753,7 +2529,7 @@ pub const Value = extern union {
3753 // TODO is this a performance issue? maybe we should try the operation without2529 // TODO is this a performance issue? maybe we should try the operation without
3754 // resorting to BigInt first.2530 // resorting to BigInt first.
3755 var val_space: Value.BigIntSpace = undefined;2531 var val_space: Value.BigIntSpace = undefined;
3756 const val_bigint = val.toBigInt(&val_space, target);2532 const val_bigint = val.toBigInt(&val_space, mod);
3757 const limbs = try arena.alloc(2533 const limbs = try arena.alloc(
3758 std.math.big.Limb,2534 std.math.big.Limb,
3759 std.math.big.int.calcTwosCompLimbCount(info.bits),2535 std.math.big.int.calcTwosCompLimbCount(info.bits),
...@@ -3761,36 +2537,38 @@ pub const Value = extern union {...@@ -3761,36 +2537,38 @@ pub const Value = extern union {
37612537
3762 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };2538 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3763 result_bigint.bitNotWrap(val_bigint, info.signedness, info.bits);2539 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());
3765 }2541 }
37662542
3767 /// operands must be (vectors of) integers; handles undefined scalars.2543 /// operands must be (vectors of) integers; handles undefined scalars.
3768 pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {2544 pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3769 const target = mod.getTarget();2545 if (ty.zigTypeTag(mod) == .Vector) {
3770 if (ty.zigTypeTag() == .Vector) {2546 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3771 const result_data = try allocator.alloc(Value, ty.vectorLen());2547 const scalar_ty = ty.scalarType(mod);
3772 for (result_data, 0..) |*scalar, i| {2548 for (result_data, 0..) |*scalar, i| {
3773 var lhs_buf: Value.ElemValueBuffer = undefined;2549 const lhs_elem = try lhs.elemValue(mod, i);
3774 var rhs_buf: Value.ElemValueBuffer = undefined;2550 const rhs_elem = try rhs.elemValue(mod, i);
3775 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2551 scalar.* = try (try bitwiseAndScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
3776 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3777 scalar.* = try bitwiseAndScalar(lhs_elem, rhs_elem, allocator, target);
3778 }2552 }
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();
3780 }2557 }
3781 return bitwiseAndScalar(lhs, rhs, allocator, target);2558 return bitwiseAndScalar(lhs, rhs, ty, allocator, mod);
3782 }2559 }
37832560
3784 /// operands must be integers; handles undefined.2561 /// operands must be integers; handles undefined.
3785 pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value {2562 pub fn bitwiseAndScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3786 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);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
3788 // TODO is this a performance issue? maybe we should try the operation without2566 // TODO is this a performance issue? maybe we should try the operation without
3789 // resorting to BigInt first.2567 // resorting to BigInt first.
3790 var lhs_space: Value.BigIntSpace = undefined;2568 var lhs_space: Value.BigIntSpace = undefined;
3791 var rhs_space: Value.BigIntSpace = undefined;2569 var rhs_space: Value.BigIntSpace = undefined;
3792 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2570 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3793 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2571 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3794 const limbs = try arena.alloc(2572 const limbs = try arena.alloc(
3795 std.math.big.Limb,2573 std.math.big.Limb,
3796 // + 1 for negatives2574 // + 1 for negatives
...@@ -3798,102 +2576,104 @@ pub const Value = extern union {...@@ -3798,102 +2576,104 @@ pub const Value = extern union {
3798 );2576 );
3799 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };2577 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3800 result_bigint.bitAnd(lhs_bigint, rhs_bigint);2578 result_bigint.bitAnd(lhs_bigint, rhs_bigint);
3801 return fromBigInt(arena, result_bigint.toConst());2579 return mod.intValue_big(ty, result_bigint.toConst());
3802 }2580 }
38032581
3804 /// operands must be (vectors of) integers; handles undefined scalars.2582 /// operands must be (vectors of) integers; handles undefined scalars.
3805 pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2583 pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3806 if (ty.zigTypeTag() == .Vector) {2584 if (ty.zigTypeTag(mod) == .Vector) {
3807 const result_data = try arena.alloc(Value, ty.vectorLen());2585 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2586 const scalar_ty = ty.scalarType(mod);
3808 for (result_data, 0..) |*scalar, i| {2587 for (result_data, 0..) |*scalar, i| {
3809 var lhs_buf: Value.ElemValueBuffer = undefined;2588 const lhs_elem = try lhs.elemValue(mod, i);
3810 var rhs_buf: Value.ElemValueBuffer = undefined;2589 const rhs_elem = try rhs.elemValue(mod, i);
3811 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2590 scalar.* = try (try bitwiseNandScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
3812 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3813 scalar.* = try bitwiseNandScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod);
3814 }2591 }
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();
3816 }2596 }
3817 return bitwiseNandScalar(lhs, rhs, ty, arena, mod);2597 return bitwiseNandScalar(lhs, rhs, ty, arena, mod);
3818 }2598 }
38192599
3820 /// operands must be integers; handles undefined.2600 /// operands must be integers; handles undefined.
3821 pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2601 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
3824 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);2605 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
38252606 const all_ones = if (ty.isSignedInt(mod)) try mod.intValue(ty, -1) else try ty.maxIntScalar(mod, ty);
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
3831 return bitwiseXor(anded, all_ones, ty, arena, mod);2607 return bitwiseXor(anded, all_ones, ty, arena, mod);
3832 }2608 }
38332609
3834 /// operands must be (vectors of) integers; handles undefined scalars.2610 /// operands must be (vectors of) integers; handles undefined scalars.
3835 pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {2611 pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3836 const target = mod.getTarget();2612 if (ty.zigTypeTag(mod) == .Vector) {
3837 if (ty.zigTypeTag() == .Vector) {2613 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3838 const result_data = try allocator.alloc(Value, ty.vectorLen());2614 const scalar_ty = ty.scalarType(mod);
3839 for (result_data, 0..) |*scalar, i| {2615 for (result_data, 0..) |*scalar, i| {
3840 var lhs_buf: Value.ElemValueBuffer = undefined;2616 const lhs_elem = try lhs.elemValue(mod, i);
3841 var rhs_buf: Value.ElemValueBuffer = undefined;2617 const rhs_elem = try rhs.elemValue(mod, i);
3842 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2618 scalar.* = try (try bitwiseOrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
3843 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3844 scalar.* = try bitwiseOrScalar(lhs_elem, rhs_elem, allocator, target);
3845 }2619 }
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();
3847 }2624 }
3848 return bitwiseOrScalar(lhs, rhs, allocator, target);2625 return bitwiseOrScalar(lhs, rhs, ty, allocator, mod);
3849 }2626 }
38502627
3851 /// operands must be integers; handles undefined.2628 /// operands must be integers; handles undefined.
3852 pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value {2629 pub fn bitwiseOrScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3853 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);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
3855 // TODO is this a performance issue? maybe we should try the operation without2633 // TODO is this a performance issue? maybe we should try the operation without
3856 // resorting to BigInt first.2634 // resorting to BigInt first.
3857 var lhs_space: Value.BigIntSpace = undefined;2635 var lhs_space: Value.BigIntSpace = undefined;
3858 var rhs_space: Value.BigIntSpace = undefined;2636 var rhs_space: Value.BigIntSpace = undefined;
3859 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2637 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3860 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2638 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3861 const limbs = try arena.alloc(2639 const limbs = try arena.alloc(
3862 std.math.big.Limb,2640 std.math.big.Limb,
3863 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),2641 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
3864 );2642 );
3865 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };2643 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3866 result_bigint.bitOr(lhs_bigint, rhs_bigint);2644 result_bigint.bitOr(lhs_bigint, rhs_bigint);
3867 return fromBigInt(arena, result_bigint.toConst());2645 return mod.intValue_big(ty, result_bigint.toConst());
3868 }2646 }
38692647
3870 /// operands must be (vectors of) integers; handles undefined scalars.2648 /// operands must be (vectors of) integers; handles undefined scalars.
3871 pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {2649 pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3872 const target = mod.getTarget();2650 if (ty.zigTypeTag(mod) == .Vector) {
3873 if (ty.zigTypeTag() == .Vector) {2651 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3874 const result_data = try allocator.alloc(Value, ty.vectorLen());2652 const scalar_ty = ty.scalarType(mod);
3875 for (result_data, 0..) |*scalar, i| {2653 for (result_data, 0..) |*scalar, i| {
3876 var lhs_buf: Value.ElemValueBuffer = undefined;2654 const lhs_elem = try lhs.elemValue(mod, i);
3877 var rhs_buf: Value.ElemValueBuffer = undefined;2655 const rhs_elem = try rhs.elemValue(mod, i);
3878 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2656 scalar.* = try (try bitwiseXorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
3879 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3880 scalar.* = try bitwiseXorScalar(lhs_elem, rhs_elem, allocator, target);
3881 }2657 }
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();
3883 }2662 }
3884 return bitwiseXorScalar(lhs, rhs, allocator, target);2663 return bitwiseXorScalar(lhs, rhs, ty, allocator, mod);
3885 }2664 }
38862665
3887 /// operands must be integers; handles undefined.2666 /// operands must be integers; handles undefined.
3888 pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value {2667 pub fn bitwiseXorScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3889 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);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
3891 // TODO is this a performance issue? maybe we should try the operation without2671 // TODO is this a performance issue? maybe we should try the operation without
3892 // resorting to BigInt first.2672 // resorting to BigInt first.
3893 var lhs_space: Value.BigIntSpace = undefined;2673 var lhs_space: Value.BigIntSpace = undefined;
3894 var rhs_space: Value.BigIntSpace = undefined;2674 var rhs_space: Value.BigIntSpace = undefined;
3895 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2675 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3896 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2676 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3897 const limbs = try arena.alloc(2677 const limbs = try arena.alloc(
3898 std.math.big.Limb,2678 std.math.big.Limb,
3899 // + 1 for negatives2679 // + 1 for negatives
...@@ -3901,32 +2681,61 @@ pub const Value = extern union {...@@ -3901,32 +2681,61 @@ pub const Value = extern union {
3901 );2681 );
3902 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };2682 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3903 result_bigint.bitXor(lhs_bigint, rhs_bigint);2683 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 };
3905 }2706 }
39062707
3907 pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {2708 fn intDivInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator: Allocator, mod: *Module) !Value {
3908 const target = mod.getTarget();2709 if (ty.zigTypeTag(mod) == .Vector) {
3909 if (ty.zigTypeTag() == .Vector) {2710 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3910 const result_data = try allocator.alloc(Value, ty.vectorLen());2711 const scalar_ty = ty.scalarType(mod);
3911 for (result_data, 0..) |*scalar, i| {2712 for (result_data, 0..) |*scalar, i| {
3912 var lhs_buf: Value.ElemValueBuffer = undefined;2713 const lhs_elem = try lhs.elemValue(mod, i);
3913 var rhs_buf: Value.ElemValueBuffer = undefined;2714 const rhs_elem = try rhs.elemValue(mod, i);
3914 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2715 const val = intDivScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod) catch |err| switch (err) {
3915 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);2716 error.Overflow => {
3916 scalar.* = try intDivScalar(lhs_elem, rhs_elem, allocator, target);2717 overflow_idx.* = i;
2718 return error.Overflow;
2719 },
2720 else => |e| return e,
2721 };
2722 scalar.* = try val.intern(scalar_ty, mod);
3917 }2723 }
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();
3919 }2728 }
3920 return intDivScalar(lhs, rhs, allocator, target);2729 return intDivScalar(lhs, rhs, ty, allocator, mod);
3921 }2730 }
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 {
3924 // TODO is this a performance issue? maybe we should try the operation without2733 // TODO is this a performance issue? maybe we should try the operation without
3925 // resorting to BigInt first.2734 // resorting to BigInt first.
3926 var lhs_space: Value.BigIntSpace = undefined;2735 var lhs_space: Value.BigIntSpace = undefined;
3927 var rhs_space: Value.BigIntSpace = undefined;2736 var rhs_space: Value.BigIntSpace = undefined;
3928 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2737 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3929 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2738 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3930 const limbs_q = try allocator.alloc(2739 const limbs_q = try allocator.alloc(
3931 std.math.big.Limb,2740 std.math.big.Limb,
3932 lhs_bigint.limbs.len,2741 lhs_bigint.limbs.len,
...@@ -3942,32 +2751,39 @@ pub const Value = extern union {...@@ -3942,32 +2751,39 @@ pub const Value = extern union {
3942 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };2751 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
3943 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };2752 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
3944 result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);2753 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());
3946 }2761 }
39472762
3948 pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {2763 pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3949 const target = mod.getTarget();2764 if (ty.zigTypeTag(mod) == .Vector) {
3950 if (ty.zigTypeTag() == .Vector) {2765 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3951 const result_data = try allocator.alloc(Value, ty.vectorLen());2766 const scalar_ty = ty.scalarType(mod);
3952 for (result_data, 0..) |*scalar, i| {2767 for (result_data, 0..) |*scalar, i| {
3953 var lhs_buf: Value.ElemValueBuffer = undefined;2768 const lhs_elem = try lhs.elemValue(mod, i);
3954 var rhs_buf: Value.ElemValueBuffer = undefined;2769 const rhs_elem = try rhs.elemValue(mod, i);
3955 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2770 scalar.* = try (try intDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
3956 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3957 scalar.* = try intDivFloorScalar(lhs_elem, rhs_elem, allocator, target);
3958 }2771 }
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();
3960 }2776 }
3961 return intDivFloorScalar(lhs, rhs, allocator, target);2777 return intDivFloorScalar(lhs, rhs, ty, allocator, mod);
3962 }2778 }
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 {
3965 // TODO is this a performance issue? maybe we should try the operation without2781 // TODO is this a performance issue? maybe we should try the operation without
3966 // resorting to BigInt first.2782 // resorting to BigInt first.
3967 var lhs_space: Value.BigIntSpace = undefined;2783 var lhs_space: Value.BigIntSpace = undefined;
3968 var rhs_space: Value.BigIntSpace = undefined;2784 var rhs_space: Value.BigIntSpace = undefined;
3969 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2785 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3970 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2786 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
3971 const limbs_q = try allocator.alloc(2787 const limbs_q = try allocator.alloc(
3972 std.math.big.Limb,2788 std.math.big.Limb,
3973 lhs_bigint.limbs.len,2789 lhs_bigint.limbs.len,
...@@ -3983,32 +2799,33 @@ pub const Value = extern union {...@@ -3983,32 +2799,33 @@ pub const Value = extern union {
3983 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };2799 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
3984 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };2800 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
3985 result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);2801 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());
3987 }2803 }
39882804
3989 pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {2805 pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3990 const target = mod.getTarget();2806 if (ty.zigTypeTag(mod) == .Vector) {
3991 if (ty.zigTypeTag() == .Vector) {2807 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3992 const result_data = try allocator.alloc(Value, ty.vectorLen());2808 const scalar_ty = ty.scalarType(mod);
3993 for (result_data, 0..) |*scalar, i| {2809 for (result_data, 0..) |*scalar, i| {
3994 var lhs_buf: Value.ElemValueBuffer = undefined;2810 const lhs_elem = try lhs.elemValue(mod, i);
3995 var rhs_buf: Value.ElemValueBuffer = undefined;2811 const rhs_elem = try rhs.elemValue(mod, i);
3996 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2812 scalar.* = try (try intModScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
3997 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3998 scalar.* = try intModScalar(lhs_elem, rhs_elem, allocator, target);
3999 }2813 }
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();
4001 }2818 }
4002 return intModScalar(lhs, rhs, allocator, target);2819 return intModScalar(lhs, rhs, ty, allocator, mod);
4003 }2820 }
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 {
4006 // TODO is this a performance issue? maybe we should try the operation without2823 // TODO is this a performance issue? maybe we should try the operation without
4007 // resorting to BigInt first.2824 // resorting to BigInt first.
4008 var lhs_space: Value.BigIntSpace = undefined;2825 var lhs_space: Value.BigIntSpace = undefined;
4009 var rhs_space: Value.BigIntSpace = undefined;2826 var rhs_space: Value.BigIntSpace = undefined;
4010 const lhs_bigint = lhs.toBigInt(&lhs_space, target);2827 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
4011 const rhs_bigint = rhs.toBigInt(&rhs_space, target);2828 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
4012 const limbs_q = try allocator.alloc(2829 const limbs_q = try allocator.alloc(
4013 std.math.big.Limb,2830 std.math.big.Limb,
4014 lhs_bigint.limbs.len,2831 lhs_bigint.limbs.len,
...@@ -4024,161 +2841,164 @@ pub const Value = extern union {...@@ -4024,161 +2841,164 @@ pub const Value = extern union {
4024 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };2841 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
4025 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };2842 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
4026 result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);2843 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());
4028 }2845 }
40292846
4030 /// Returns true if the value is a floating point type and is NaN. Returns false otherwise.2847 /// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
4031 pub fn isNan(val: Value) bool {2848 pub fn isNan(val: Value, mod: *const Module) bool {
4032 return switch (val.tag()) {2849 if (val.ip_index == .none) return false;
4033 .float_16 => std.math.isNan(val.castTag(.float_16).?.data),2850 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
4034 .float_32 => std.math.isNan(val.castTag(.float_32).?.data),2851 .float => |float| switch (float.storage) {
4035 .float_64 => std.math.isNan(val.castTag(.float_64).?.data),2852 inline else => |x| std.math.isNan(x),
4036 .float_80 => std.math.isNan(val.castTag(.float_80).?.data),2853 },
4037 .float_128 => std.math.isNan(val.castTag(.float_128).?.data),
4038 else => false,2854 else => false,
4039 };2855 };
4040 }2856 }
40412857
4042 /// Returns true if the value is a floating point type and is infinite. Returns false otherwise.2858 /// Returns true if the value is a floating point type and is infinite. Returns false otherwise.
4043 pub fn isInf(val: Value) bool {2859 pub fn isInf(val: Value, mod: *const Module) bool {
4044 return switch (val.tag()) {2860 if (val.ip_index == .none) return false;
4045 .float_16 => std.math.isInf(val.castTag(.float_16).?.data),2861 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
4046 .float_32 => std.math.isInf(val.castTag(.float_32).?.data),2862 .float => |float| switch (float.storage) {
4047 .float_64 => std.math.isInf(val.castTag(.float_64).?.data),2863 inline else => |x| std.math.isInf(x),
4048 .float_80 => std.math.isInf(val.castTag(.float_80).?.data),2864 },
4049 .float_128 => std.math.isInf(val.castTag(.float_128).?.data),
4050 else => false,2865 else => false,
4051 };2866 };
4052 }2867 }
40532868
4054 pub fn isNegativeInf(val: Value) bool {2869 pub fn isNegativeInf(val: Value, mod: *const Module) bool {
4055 return switch (val.tag()) {2870 if (val.ip_index == .none) return false;
4056 .float_16 => std.math.isNegativeInf(val.castTag(.float_16).?.data),2871 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
4057 .float_32 => std.math.isNegativeInf(val.castTag(.float_32).?.data),2872 .float => |float| switch (float.storage) {
4058 .float_64 => std.math.isNegativeInf(val.castTag(.float_64).?.data),2873 inline else => |x| std.math.isNegativeInf(x),
4059 .float_80 => std.math.isNegativeInf(val.castTag(.float_80).?.data),2874 },
4060 .float_128 => std.math.isNegativeInf(val.castTag(.float_128).?.data),
4061 else => false,2875 else => false,
4062 };2876 };
4063 }2877 }
40642878
4065 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {2879 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4066 const target = mod.getTarget();2880 if (float_type.zigTypeTag(mod) == .Vector) {
4067 if (float_type.zigTypeTag() == .Vector) {2881 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4068 const result_data = try arena.alloc(Value, float_type.vectorLen());2882 const scalar_ty = float_type.scalarType(mod);
4069 for (result_data, 0..) |*scalar, i| {2883 for (result_data, 0..) |*scalar, i| {
4070 var lhs_buf: Value.ElemValueBuffer = undefined;2884 const lhs_elem = try lhs.elemValue(mod, i);
4071 var rhs_buf: Value.ElemValueBuffer = undefined;2885 const rhs_elem = try rhs.elemValue(mod, i);
4072 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2886 scalar.* = try (try floatRemScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
4073 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4074 scalar.* = try floatRemScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
4075 }2887 }
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();
4077 }2892 }
4078 return floatRemScalar(lhs, rhs, float_type, arena, target);2893 return floatRemScalar(lhs, rhs, float_type, mod);
4079 }2894 }
40802895
4081 pub fn floatRemScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {2896 pub fn floatRemScalar(lhs: Value, rhs: Value, float_type: Type, mod: *Module) !Value {
4082 switch (float_type.floatBits(target)) {2897 const target = mod.getTarget();
4083 16 => {2898 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4084 const lhs_val = lhs.toFloat(f16);2899 16 => .{ .f16 = @rem(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
4085 const rhs_val = rhs.toFloat(f16);2900 32 => .{ .f32 = @rem(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
4086 return Value.Tag.float_16.create(arena, @rem(lhs_val, rhs_val));2901 64 => .{ .f64 = @rem(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
4087 },2902 80 => .{ .f80 = @rem(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
4088 32 => {2903 128 => .{ .f128 = @rem(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
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 },
4108 else => unreachable,2904 else => unreachable,
4109 }2905 };
2906 return (try mod.intern(.{ .float = .{
2907 .ty = float_type.toIntern(),
2908 .storage = storage,
2909 } })).toValue();
4110 }2910 }
41112911
4112 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {2912 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4113 const target = mod.getTarget();2913 if (float_type.zigTypeTag(mod) == .Vector) {
4114 if (float_type.zigTypeTag() == .Vector) {2914 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4115 const result_data = try arena.alloc(Value, float_type.vectorLen());2915 const scalar_ty = float_type.scalarType(mod);
4116 for (result_data, 0..) |*scalar, i| {2916 for (result_data, 0..) |*scalar, i| {
4117 var lhs_buf: Value.ElemValueBuffer = undefined;2917 const lhs_elem = try lhs.elemValue(mod, i);
4118 var rhs_buf: Value.ElemValueBuffer = undefined;2918 const rhs_elem = try rhs.elemValue(mod, i);
4119 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2919 scalar.* = try (try floatModScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
4120 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4121 scalar.* = try floatModScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
4122 }2920 }
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();
4124 }2925 }
4125 return floatModScalar(lhs, rhs, float_type, arena, target);2926 return floatModScalar(lhs, rhs, float_type, mod);
4126 }2927 }
41272928
4128 pub fn floatModScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {2929 pub fn floatModScalar(lhs: Value, rhs: Value, float_type: Type, mod: *Module) !Value {
4129 switch (float_type.floatBits(target)) {2930 const target = mod.getTarget();
4130 16 => {2931 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4131 const lhs_val = lhs.toFloat(f16);2932 16 => .{ .f16 = @mod(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
4132 const rhs_val = rhs.toFloat(f16);2933 32 => .{ .f32 = @mod(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
4133 return Value.Tag.float_16.create(arena, @mod(lhs_val, rhs_val));2934 64 => .{ .f64 = @mod(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
4134 },2935 80 => .{ .f80 = @mod(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
4135 32 => {2936 128 => .{ .f128 = @mod(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
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 },
4155 else => unreachable,2937 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 };
4157 }2964 }
41582965
4159 pub fn intMul(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {2966 fn intMulInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator: Allocator, mod: *Module) !Value {
4160 const target = mod.getTarget();2967 if (ty.zigTypeTag(mod) == .Vector) {
4161 if (ty.zigTypeTag() == .Vector) {2968 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
4162 const result_data = try allocator.alloc(Value, ty.vectorLen());2969 const scalar_ty = ty.scalarType(mod);
4163 for (result_data, 0..) |*scalar, i| {2970 for (result_data, 0..) |*scalar, i| {
4164 var lhs_buf: Value.ElemValueBuffer = undefined;2971 const lhs_elem = try lhs.elemValue(mod, i);
4165 var rhs_buf: Value.ElemValueBuffer = undefined;2972 const rhs_elem = try rhs.elemValue(mod, i);
4166 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);2973 const val = intMulScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod) catch |err| switch (err) {
4167 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);2974 error.Overflow => {
4168 scalar.* = try intMulScalar(lhs_elem, rhs_elem, allocator, target);2975 overflow_idx.* = i;
2976 return error.Overflow;
2977 },
2978 else => |e| return e,
2979 };
2980 scalar.* = try val.intern(scalar_ty, mod);
4169 }2981 }
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();
4171 }2986 }
4172 return intMulScalar(lhs, rhs, allocator, target);2987 return intMulScalar(lhs, rhs, ty, allocator, mod);
4173 }2988 }
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 }
4176 // TODO is this a performance issue? maybe we should try the operation without2996 // TODO is this a performance issue? maybe we should try the operation without
4177 // resorting to BigInt first.2997 // resorting to BigInt first.
4178 var lhs_space: Value.BigIntSpace = undefined;2998 var lhs_space: Value.BigIntSpace = undefined;
4179 var rhs_space: Value.BigIntSpace = undefined;2999 var rhs_space: Value.BigIntSpace = undefined;
4180 const lhs_bigint = lhs.toBigInt(&lhs_space, target);3000 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
4181 const rhs_bigint = rhs.toBigInt(&rhs_space, target);3001 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
4182 const limbs = try allocator.alloc(3002 const limbs = try allocator.alloc(
4183 std.math.big.Limb,3003 std.math.big.Limb,
4184 lhs_bigint.limbs.len + rhs_bigint.limbs.len,3004 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
...@@ -4190,21 +3010,23 @@ pub const Value = extern union {...@@ -4190,21 +3010,23 @@ pub const Value = extern union {
4190 );3010 );
4191 defer allocator.free(limbs_buffer);3011 defer allocator.free(limbs_buffer);
4192 result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, allocator);3012 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());
4194 }3014 }
41953015
4196 pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, mod: *Module) !Value {3016 pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, mod: *Module) !Value {
4197 const target = mod.getTarget();3017 if (ty.zigTypeTag(mod) == .Vector) {
4198 if (ty.zigTypeTag() == .Vector) {3018 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
4199 const result_data = try allocator.alloc(Value, ty.vectorLen());3019 const scalar_ty = ty.scalarType(mod);
4200 for (result_data, 0..) |*scalar, i| {3020 for (result_data, 0..) |*scalar, i| {
4201 var buf: Value.ElemValueBuffer = undefined;3021 const elem_val = try val.elemValue(mod, i);
4202 const elem_val = val.elemValueBuffer(mod, i, &buf);3022 scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, bits, mod)).intern(scalar_ty, mod);
4203 scalar.* = try intTruncScalar(elem_val, allocator, signedness, bits, target);
4204 }3023 }
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();
4206 }3028 }
4207 return intTruncScalar(val, allocator, signedness, bits, target);3029 return intTruncScalar(val, ty, allocator, signedness, bits, mod);
4208 }3030 }
42093031
4210 /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`.3032 /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`.
...@@ -4216,26 +3038,34 @@ pub const Value = extern union {...@@ -4216,26 +3038,34 @@ pub const Value = extern union {
4216 bits: Value,3038 bits: Value,
4217 mod: *Module,3039 mod: *Module,
4218 ) !Value {3040 ) !Value {
4219 const target = mod.getTarget();3041 if (ty.zigTypeTag(mod) == .Vector) {
4220 if (ty.zigTypeTag() == .Vector) {3042 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
4221 const result_data = try allocator.alloc(Value, ty.vectorLen());3043 const scalar_ty = ty.scalarType(mod);
4222 for (result_data, 0..) |*scalar, i| {3044 for (result_data, 0..) |*scalar, i| {
4223 var buf: Value.ElemValueBuffer = undefined;3045 const elem_val = try val.elemValue(mod, i);
4224 const elem_val = val.elemValueBuffer(mod, i, &buf);3046 const bits_elem = try bits.elemValue(mod, i);
4225 var bits_buf: Value.ElemValueBuffer = undefined;3047 scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @intCast(u16, bits_elem.toUnsignedInt(mod)), mod)).intern(scalar_ty, mod);
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);
4228 }3048 }
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();
4230 }3053 }
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);
4232 }3055 }
42333056
4234 pub fn intTruncScalar(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, target: Target) !Value {3057 pub fn intTruncScalar(
4235 if (bits == 0) return Value.zero;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
4237 var val_space: Value.BigIntSpace = undefined;3067 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
4240 const limbs = try allocator.alloc(3070 const limbs = try allocator.alloc(
4241 std.math.big.Limb,3071 std.math.big.Limb,
...@@ -4244,31 +3074,32 @@ pub const Value = extern union {...@@ -4244,31 +3074,32 @@ pub const Value = extern union {
4244 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };3074 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
42453075
4246 result_bigint.truncate(val_bigint, signedness, bits);3076 result_bigint.truncate(val_bigint, signedness, bits);
4247 return fromBigInt(allocator, result_bigint.toConst());3077 return mod.intValue_big(ty, result_bigint.toConst());
4248 }3078 }
42493079
4250 pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {3080 pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
4251 const target = mod.getTarget();3081 if (ty.zigTypeTag(mod) == .Vector) {
4252 if (ty.zigTypeTag() == .Vector) {3082 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
4253 const result_data = try allocator.alloc(Value, ty.vectorLen());3083 const scalar_ty = ty.scalarType(mod);
4254 for (result_data, 0..) |*scalar, i| {3084 for (result_data, 0..) |*scalar, i| {
4255 var lhs_buf: Value.ElemValueBuffer = undefined;3085 const lhs_elem = try lhs.elemValue(mod, i);
4256 var rhs_buf: Value.ElemValueBuffer = undefined;3086 const rhs_elem = try rhs.elemValue(mod, i);
4257 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3087 scalar.* = try (try shlScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
4258 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4259 scalar.* = try shlScalar(lhs_elem, rhs_elem, allocator, target);
4260 }3088 }
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();
4262 }3093 }
4263 return shlScalar(lhs, rhs, allocator, target);3094 return shlScalar(lhs, rhs, ty, allocator, mod);
4264 }3095 }
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 {
4267 // TODO is this a performance issue? maybe we should try the operation without3098 // TODO is this a performance issue? maybe we should try the operation without
4268 // resorting to BigInt first.3099 // resorting to BigInt first.
4269 var lhs_space: Value.BigIntSpace = undefined;3100 var lhs_space: Value.BigIntSpace = undefined;
4270 const lhs_bigint = lhs.toBigInt(&lhs_space, target);3101 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
4271 const shift = @intCast(usize, rhs.toUnsignedInt(target));3102 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
4272 const limbs = try allocator.alloc(3103 const limbs = try allocator.alloc(
4273 std.math.big.Limb,3104 std.math.big.Limb,
4274 lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1,3105 lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1,
...@@ -4279,7 +3110,12 @@ pub const Value = extern union {...@@ -4279,7 +3110,12 @@ pub const Value = extern union {
4279 .len = undefined,3110 .len = undefined,
4280 };3111 };
4281 result_bigint.shiftLeft(lhs_bigint, shift);3112 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());
4283 }3119 }
42843120
4285 pub fn shlWithOverflow(3121 pub fn shlWithOverflow(
...@@ -4289,25 +3125,30 @@ pub const Value = extern union {...@@ -4289,25 +3125,30 @@ pub const Value = extern union {
4289 allocator: Allocator,3125 allocator: Allocator,
4290 mod: *Module,3126 mod: *Module,
4291 ) !OverflowArithmeticResult {3127 ) !OverflowArithmeticResult {
4292 const target = mod.getTarget();3128 if (ty.zigTypeTag(mod) == .Vector) {
4293 if (ty.zigTypeTag() == .Vector) {3129 const vec_len = ty.vectorLen(mod);
4294 const overflowed_data = try allocator.alloc(Value, ty.vectorLen());3130 const overflowed_data = try allocator.alloc(InternPool.Index, vec_len);
4295 const result_data = try allocator.alloc(Value, ty.vectorLen());3131 const result_data = try allocator.alloc(InternPool.Index, vec_len);
4296 for (result_data, 0..) |*scalar, i| {3132 const scalar_ty = ty.scalarType(mod);
4297 var lhs_buf: Value.ElemValueBuffer = undefined;3133 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
4298 var rhs_buf: Value.ElemValueBuffer = undefined;3134 const lhs_elem = try lhs.elemValue(mod, i);
4299 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3135 const rhs_elem = try rhs.elemValue(mod, i);
4300 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);3136 const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod);
4301 const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), allocator, target);3137 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
4302 overflowed_data[i] = of_math_result.overflow_bit;3138 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
4303 scalar.* = of_math_result.wrapped_result;
4304 }3139 }
4305 return OverflowArithmeticResult{3140 return OverflowArithmeticResult{
4306 .overflow_bit = try Value.Tag.aggregate.create(allocator, overflowed_data),3141 .overflow_bit = (try mod.intern(.{ .aggregate = .{
4307 .wrapped_result = try Value.Tag.aggregate.create(allocator, result_data),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(),
4308 };3149 };
4309 }3150 }
4310 return shlWithOverflowScalar(lhs, rhs, ty, allocator, target);3151 return shlWithOverflowScalar(lhs, rhs, ty, allocator, mod);
4311 }3152 }
43123153
4313 pub fn shlWithOverflowScalar(3154 pub fn shlWithOverflowScalar(
...@@ -4315,12 +3156,12 @@ pub const Value = extern union {...@@ -4315,12 +3156,12 @@ pub const Value = extern union {
4315 rhs: Value,3156 rhs: Value,
4316 ty: Type,3157 ty: Type,
4317 allocator: Allocator,3158 allocator: Allocator,
4318 target: Target,3159 mod: *Module,
4319 ) !OverflowArithmeticResult {3160 ) !OverflowArithmeticResult {
4320 const info = ty.intInfo(target);3161 const info = ty.intInfo(mod);
4321 var lhs_space: Value.BigIntSpace = undefined;3162 var lhs_space: Value.BigIntSpace = undefined;
4322 const lhs_bigint = lhs.toBigInt(&lhs_space, target);3163 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
4323 const shift = @intCast(usize, rhs.toUnsignedInt(target));3164 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
4324 const limbs = try allocator.alloc(3165 const limbs = try allocator.alloc(
4325 std.math.big.Limb,3166 std.math.big.Limb,
4326 lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1,3167 lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1,
...@@ -4336,8 +3177,8 @@ pub const Value = extern union {...@@ -4336,8 +3177,8 @@ pub const Value = extern union {
4336 result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits);3177 result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits);
4337 }3178 }
4338 return OverflowArithmeticResult{3179 return OverflowArithmeticResult{
4339 .overflow_bit = boolToInt(overflowed),3180 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
4340 .wrapped_result = try fromBigInt(allocator, result_bigint.toConst()),3181 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
4341 };3182 };
4342 }3183 }
43433184
...@@ -4348,19 +3189,20 @@ pub const Value = extern union {...@@ -4348,19 +3189,20 @@ pub const Value = extern union {
4348 arena: Allocator,3189 arena: Allocator,
4349 mod: *Module,3190 mod: *Module,
4350 ) !Value {3191 ) !Value {
4351 const target = mod.getTarget();3192 if (ty.zigTypeTag(mod) == .Vector) {
4352 if (ty.zigTypeTag() == .Vector) {3193 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
4353 const result_data = try arena.alloc(Value, ty.vectorLen());3194 const scalar_ty = ty.scalarType(mod);
4354 for (result_data, 0..) |*scalar, i| {3195 for (result_data, 0..) |*scalar, i| {
4355 var lhs_buf: Value.ElemValueBuffer = undefined;3196 const lhs_elem = try lhs.elemValue(mod, i);
4356 var rhs_buf: Value.ElemValueBuffer = undefined;3197 const rhs_elem = try rhs.elemValue(mod, i);
4357 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3198 scalar.* = try (try shlSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
4358 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4359 scalar.* = try shlSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
4360 }3199 }
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();
4362 }3204 }
4363 return shlSatScalar(lhs, rhs, ty, arena, target);3205 return shlSatScalar(lhs, rhs, ty, arena, mod);
4364 }3206 }
43653207
4366 pub fn shlSatScalar(3208 pub fn shlSatScalar(
...@@ -4368,15 +3210,15 @@ pub const Value = extern union {...@@ -4368,15 +3210,15 @@ pub const Value = extern union {
4368 rhs: Value,3210 rhs: Value,
4369 ty: Type,3211 ty: Type,
4370 arena: Allocator,3212 arena: Allocator,
4371 target: Target,3213 mod: *Module,
4372 ) !Value {3214 ) !Value {
4373 // TODO is this a performance issue? maybe we should try the operation without3215 // TODO is this a performance issue? maybe we should try the operation without
4374 // resorting to BigInt first.3216 // resorting to BigInt first.
4375 const info = ty.intInfo(target);3217 const info = ty.intInfo(mod);
43763218
4377 var lhs_space: Value.BigIntSpace = undefined;3219 var lhs_space: Value.BigIntSpace = undefined;
4378 const lhs_bigint = lhs.toBigInt(&lhs_space, target);3220 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
4379 const shift = @intCast(usize, rhs.toUnsignedInt(target));3221 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
4380 const limbs = try arena.alloc(3222 const limbs = try arena.alloc(
4381 std.math.big.Limb,3223 std.math.big.Limb,
4382 std.math.big.int.calcTwosCompLimbCount(info.bits) + 1,3224 std.math.big.int.calcTwosCompLimbCount(info.bits) + 1,
...@@ -4387,7 +3229,7 @@ pub const Value = extern union {...@@ -4387,7 +3229,7 @@ pub const Value = extern union {
4387 .len = undefined,3229 .len = undefined,
4388 };3230 };
4389 result_bigint.shiftLeftSat(lhs_bigint, shift, info.signedness, info.bits);3231 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());
4391 }3233 }
43923234
4393 pub fn shlTrunc(3235 pub fn shlTrunc(
...@@ -4397,16 +3239,18 @@ pub const Value = extern union {...@@ -4397,16 +3239,18 @@ pub const Value = extern union {
4397 arena: Allocator,3239 arena: Allocator,
4398 mod: *Module,3240 mod: *Module,
4399 ) !Value {3241 ) !Value {
4400 if (ty.zigTypeTag() == .Vector) {3242 if (ty.zigTypeTag(mod) == .Vector) {
4401 const result_data = try arena.alloc(Value, ty.vectorLen());3243 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3244 const scalar_ty = ty.scalarType(mod);
4402 for (result_data, 0..) |*scalar, i| {3245 for (result_data, 0..) |*scalar, i| {
4403 var lhs_buf: Value.ElemValueBuffer = undefined;3246 const lhs_elem = try lhs.elemValue(mod, i);
4404 var rhs_buf: Value.ElemValueBuffer = undefined;3247 const rhs_elem = try rhs.elemValue(mod, i);
4405 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3248 scalar.* = try (try shlTruncScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
4406 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4407 scalar.* = try shlTruncScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod);
4408 }3249 }
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();
4410 }3254 }
4411 return shlTruncScalar(lhs, rhs, ty, arena, mod);3255 return shlTruncScalar(lhs, rhs, ty, arena, mod);
4412 }3256 }
...@@ -4419,42 +3263,43 @@ pub const Value = extern union {...@@ -4419,42 +3263,43 @@ pub const Value = extern union {
4419 mod: *Module,3263 mod: *Module,
4420 ) !Value {3264 ) !Value {
4421 const shifted = try lhs.shl(rhs, ty, arena, mod);3265 const shifted = try lhs.shl(rhs, ty, arena, mod);
4422 const int_info = ty.intInfo(mod.getTarget());3266 const int_info = ty.intInfo(mod);
4423 const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits, mod);3267 const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits, mod);
4424 return truncated;3268 return truncated;
4425 }3269 }
44263270
4427 pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {3271 pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
4428 const target = mod.getTarget();3272 if (ty.zigTypeTag(mod) == .Vector) {
4429 if (ty.zigTypeTag() == .Vector) {3273 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
4430 const result_data = try allocator.alloc(Value, ty.vectorLen());3274 const scalar_ty = ty.scalarType(mod);
4431 for (result_data, 0..) |*scalar, i| {3275 for (result_data, 0..) |*scalar, i| {
4432 var lhs_buf: Value.ElemValueBuffer = undefined;3276 const lhs_elem = try lhs.elemValue(mod, i);
4433 var rhs_buf: Value.ElemValueBuffer = undefined;3277 const rhs_elem = try rhs.elemValue(mod, i);
4434 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3278 scalar.* = try (try shrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
4435 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4436 scalar.* = try shrScalar(lhs_elem, rhs_elem, allocator, target);
4437 }3279 }
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();
4439 }3284 }
4440 return shrScalar(lhs, rhs, allocator, target);3285 return shrScalar(lhs, rhs, ty, allocator, mod);
4441 }3286 }
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 {
4444 // TODO is this a performance issue? maybe we should try the operation without3289 // TODO is this a performance issue? maybe we should try the operation without
4445 // resorting to BigInt first.3290 // resorting to BigInt first.
4446 var lhs_space: Value.BigIntSpace = undefined;3291 var lhs_space: Value.BigIntSpace = undefined;
4447 const lhs_bigint = lhs.toBigInt(&lhs_space, target);3292 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
4448 const shift = @intCast(usize, rhs.toUnsignedInt(target));3293 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
44493294
4450 const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8));3295 const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8));
4451 if (result_limbs == 0) {3296 if (result_limbs == 0) {
4452 // The shift is enough to remove all the bits from the number, which means the3297 // The shift is enough to remove all the bits from the number, which means the
4453 // result is 0 or -1 depending on the sign.3298 // result is 0 or -1 depending on the sign.
4454 if (lhs_bigint.positive) {3299 if (lhs_bigint.positive) {
4455 return Value.zero;3300 return mod.intValue(ty, 0);
4456 } else {3301 } else {
4457 return Value.negative_one;3302 return mod.intValue(ty, -1);
4458 }3303 }
4459 }3304 }
44603305
...@@ -4468,7 +3313,7 @@ pub const Value = extern union {...@@ -4468,7 +3313,7 @@ pub const Value = extern union {
4468 .len = undefined,3313 .len = undefined,
4469 };3314 };
4470 result_bigint.shiftRight(lhs_bigint, shift);3315 result_bigint.shiftRight(lhs_bigint, shift);
4471 return fromBigInt(allocator, result_bigint.toConst());3316 return mod.intValue_big(ty, result_bigint.toConst());
4472 }3317 }
44733318
4474 pub fn floatNeg(3319 pub fn floatNeg(
...@@ -4477,33 +3322,127 @@ pub const Value = extern union {...@@ -4477,33 +3322,127 @@ pub const Value = extern union {
4477 arena: Allocator,3322 arena: Allocator,
4478 mod: *Module,3323 mod: *Module,
4479 ) !Value {3324 ) !Value {
4480 const target = mod.getTarget();3325 if (float_type.zigTypeTag(mod) == .Vector) {
4481 if (float_type.zigTypeTag() == .Vector) {3326 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4482 const result_data = try arena.alloc(Value, float_type.vectorLen());3327 const scalar_ty = float_type.scalarType(mod);
4483 for (result_data, 0..) |*scalar, i| {3328 for (result_data, 0..) |*scalar, i| {
4484 var buf: Value.ElemValueBuffer = undefined;3329 const elem_val = try val.elemValue(mod, i);
4485 const elem_val = val.elemValueBuffer(mod, i, &buf);3330 scalar.* = try (try floatNegScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4486 scalar.* = try floatNegScalar(elem_val, float_type.scalarType(), arena, target);
4487 }3331 }
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();
4489 }3336 }
4490 return floatNegScalar(val, float_type, arena, target);3337 return floatNegScalar(val, float_type, mod);
4491 }3338 }
44923339
4493 pub fn floatNegScalar(3340 pub fn floatNegScalar(
4494 val: Value,3341 val: Value,
4495 float_type: Type,3342 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,
4496 arena: Allocator,3364 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,
4498 ) !Value {3388 ) !Value {
4499 switch (float_type.floatBits(target)) {3389 const target = mod.getTarget();
4500 16 => return Value.Tag.float_16.create(arena, -val.toFloat(f16)),3390 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4501 32 => return Value.Tag.float_32.create(arena, -val.toFloat(f32)),3391 16 => .{ .f16 = lhs.toFloat(f16, mod) + rhs.toFloat(f16, mod) },
4502 64 => return Value.Tag.float_64.create(arena, -val.toFloat(f64)),3392 32 => .{ .f32 = lhs.toFloat(f32, mod) + rhs.toFloat(f32, mod) },
4503 80 => return Value.Tag.float_80.create(arena, -val.toFloat(f80)),3393 64 => .{ .f64 = lhs.toFloat(f64, mod) + rhs.toFloat(f64, mod) },
4504 128 => return Value.Tag.float_128.create(arena, -val.toFloat(f128)),3394 80 => .{ .f80 = lhs.toFloat(f80, mod) + rhs.toFloat(f80, mod) },
3395 128 => .{ .f128 = lhs.toFloat(f128, mod) + rhs.toFloat(f128, mod) },
4505 else => unreachable,3396 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();
4506 }3423 }
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();
4507 }3446 }
45083447
4509 pub fn floatDiv(3448 pub fn floatDiv(
...@@ -4513,56 +3452,41 @@ pub const Value = extern union {...@@ -4513,56 +3452,41 @@ pub const Value = extern union {
4513 arena: Allocator,3452 arena: Allocator,
4514 mod: *Module,3453 mod: *Module,
4515 ) !Value {3454 ) !Value {
4516 const target = mod.getTarget();3455 if (float_type.zigTypeTag(mod) == .Vector) {
4517 if (float_type.zigTypeTag() == .Vector) {3456 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4518 const result_data = try arena.alloc(Value, float_type.vectorLen());3457 const scalar_ty = float_type.scalarType(mod);
4519 for (result_data, 0..) |*scalar, i| {3458 for (result_data, 0..) |*scalar, i| {
4520 var lhs_buf: Value.ElemValueBuffer = undefined;3459 const lhs_elem = try lhs.elemValue(mod, i);
4521 var rhs_buf: Value.ElemValueBuffer = undefined;3460 const rhs_elem = try rhs.elemValue(mod, i);
4522 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3461 scalar.* = try (try floatDivScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
4523 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4524 scalar.* = try floatDivScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
4525 }3462 }
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();
4527 }3467 }
4528 return floatDivScalar(lhs, rhs, float_type, arena, target);3468 return floatDivScalar(lhs, rhs, float_type, mod);
4529 }3469 }
45303470
4531 pub fn floatDivScalar(3471 pub fn floatDivScalar(
4532 lhs: Value,3472 lhs: Value,
4533 rhs: Value,3473 rhs: Value,
4534 float_type: Type,3474 float_type: Type,
4535 arena: Allocator,3475 mod: *Module,
4536 target: Target,
4537 ) !Value {3476 ) !Value {
4538 switch (float_type.floatBits(target)) {3477 const target = mod.getTarget();
4539 16 => {3478 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4540 const lhs_val = lhs.toFloat(f16);3479 16 => .{ .f16 = lhs.toFloat(f16, mod) / rhs.toFloat(f16, mod) },
4541 const rhs_val = rhs.toFloat(f16);3480 32 => .{ .f32 = lhs.toFloat(f32, mod) / rhs.toFloat(f32, mod) },
4542 return Value.Tag.float_16.create(arena, lhs_val / rhs_val);3481 64 => .{ .f64 = lhs.toFloat(f64, mod) / rhs.toFloat(f64, mod) },
4543 },3482 80 => .{ .f80 = lhs.toFloat(f80, mod) / rhs.toFloat(f80, mod) },
4544 32 => {3483 128 => .{ .f128 = lhs.toFloat(f128, mod) / rhs.toFloat(f128, mod) },
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 },
4564 else => unreachable,3484 else => unreachable,
4565 }3485 };
3486 return (try mod.intern(.{ .float = .{
3487 .ty = float_type.toIntern(),
3488 .storage = storage,
3489 } })).toValue();
4566 }3490 }
45673491
4568 pub fn floatDivFloor(3492 pub fn floatDivFloor(
...@@ -4572,56 +3496,41 @@ pub const Value = extern union {...@@ -4572,56 +3496,41 @@ pub const Value = extern union {
4572 arena: Allocator,3496 arena: Allocator,
4573 mod: *Module,3497 mod: *Module,
4574 ) !Value {3498 ) !Value {
4575 const target = mod.getTarget();3499 if (float_type.zigTypeTag(mod) == .Vector) {
4576 if (float_type.zigTypeTag() == .Vector) {3500 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4577 const result_data = try arena.alloc(Value, float_type.vectorLen());3501 const scalar_ty = float_type.scalarType(mod);
4578 for (result_data, 0..) |*scalar, i| {3502 for (result_data, 0..) |*scalar, i| {
4579 var lhs_buf: Value.ElemValueBuffer = undefined;3503 const lhs_elem = try lhs.elemValue(mod, i);
4580 var rhs_buf: Value.ElemValueBuffer = undefined;3504 const rhs_elem = try rhs.elemValue(mod, i);
4581 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3505 scalar.* = try (try floatDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
4582 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4583 scalar.* = try floatDivFloorScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
4584 }3506 }
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();
4586 }3511 }
4587 return floatDivFloorScalar(lhs, rhs, float_type, arena, target);3512 return floatDivFloorScalar(lhs, rhs, float_type, mod);
4588 }3513 }
45893514
4590 pub fn floatDivFloorScalar(3515 pub fn floatDivFloorScalar(
4591 lhs: Value,3516 lhs: Value,
4592 rhs: Value,3517 rhs: Value,
4593 float_type: Type,3518 float_type: Type,
4594 arena: Allocator,3519 mod: *Module,
4595 target: Target,
4596 ) !Value {3520 ) !Value {
4597 switch (float_type.floatBits(target)) {3521 const target = mod.getTarget();
4598 16 => {3522 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4599 const lhs_val = lhs.toFloat(f16);3523 16 => .{ .f16 = @divFloor(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
4600 const rhs_val = rhs.toFloat(f16);3524 32 => .{ .f32 = @divFloor(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
4601 return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));3525 64 => .{ .f64 = @divFloor(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
4602 },3526 80 => .{ .f80 = @divFloor(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
4603 32 => {3527 128 => .{ .f128 = @divFloor(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
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 },
4623 else => unreachable,3528 else => unreachable,
4624 }3529 };
3530 return (try mod.intern(.{ .float = .{
3531 .ty = float_type.toIntern(),
3532 .storage = storage,
3533 } })).toValue();
4625 }3534 }
46263535
4627 pub fn floatDivTrunc(3536 pub fn floatDivTrunc(
...@@ -4631,56 +3540,41 @@ pub const Value = extern union {...@@ -4631,56 +3540,41 @@ pub const Value = extern union {
4631 arena: Allocator,3540 arena: Allocator,
4632 mod: *Module,3541 mod: *Module,
4633 ) !Value {3542 ) !Value {
4634 const target = mod.getTarget();3543 if (float_type.zigTypeTag(mod) == .Vector) {
4635 if (float_type.zigTypeTag() == .Vector) {3544 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4636 const result_data = try arena.alloc(Value, float_type.vectorLen());3545 const scalar_ty = float_type.scalarType(mod);
4637 for (result_data, 0..) |*scalar, i| {3546 for (result_data, 0..) |*scalar, i| {
4638 var lhs_buf: Value.ElemValueBuffer = undefined;3547 const lhs_elem = try lhs.elemValue(mod, i);
4639 var rhs_buf: Value.ElemValueBuffer = undefined;3548 const rhs_elem = try rhs.elemValue(mod, i);
4640 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3549 scalar.* = try (try floatDivTruncScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
4641 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4642 scalar.* = try floatDivTruncScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
4643 }3550 }
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();
4645 }3555 }
4646 return floatDivTruncScalar(lhs, rhs, float_type, arena, target);3556 return floatDivTruncScalar(lhs, rhs, float_type, mod);
4647 }3557 }
46483558
4649 pub fn floatDivTruncScalar(3559 pub fn floatDivTruncScalar(
4650 lhs: Value,3560 lhs: Value,
4651 rhs: Value,3561 rhs: Value,
4652 float_type: Type,3562 float_type: Type,
4653 arena: Allocator,3563 mod: *Module,
4654 target: Target,
4655 ) !Value {3564 ) !Value {
4656 switch (float_type.floatBits(target)) {3565 const target = mod.getTarget();
4657 16 => {3566 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4658 const lhs_val = lhs.toFloat(f16);3567 16 => .{ .f16 = @divTrunc(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
4659 const rhs_val = rhs.toFloat(f16);3568 32 => .{ .f32 = @divTrunc(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
4660 return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));3569 64 => .{ .f64 = @divTrunc(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
4661 },3570 80 => .{ .f80 = @divTrunc(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
4662 32 => {3571 128 => .{ .f128 = @divTrunc(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
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 },
4682 else => unreachable,3572 else => unreachable,
4683 }3573 };
3574 return (try mod.intern(.{ .float = .{
3575 .ty = float_type.toIntern(),
3576 .storage = storage,
3577 } })).toValue();
4684 }3578 }
46853579
4686 pub fn floatMul(3580 pub fn floatMul(
...@@ -4690,616 +3584,489 @@ pub const Value = extern union {...@@ -4690,616 +3584,489 @@ pub const Value = extern union {
4690 arena: Allocator,3584 arena: Allocator,
4691 mod: *Module,3585 mod: *Module,
4692 ) !Value {3586 ) !Value {
4693 const target = mod.getTarget();3587 if (float_type.zigTypeTag(mod) == .Vector) {
4694 if (float_type.zigTypeTag() == .Vector) {3588 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4695 const result_data = try arena.alloc(Value, float_type.vectorLen());3589 const scalar_ty = float_type.scalarType(mod);
4696 for (result_data, 0..) |*scalar, i| {3590 for (result_data, 0..) |*scalar, i| {
4697 var lhs_buf: Value.ElemValueBuffer = undefined;3591 const lhs_elem = try lhs.elemValue(mod, i);
4698 var rhs_buf: Value.ElemValueBuffer = undefined;3592 const rhs_elem = try rhs.elemValue(mod, i);
4699 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);3593 scalar.* = try (try floatMulScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
4700 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4701 scalar.* = try floatMulScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
4702 }3594 }
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();
4704 }3599 }
4705 return floatMulScalar(lhs, rhs, float_type, arena, target);3600 return floatMulScalar(lhs, rhs, float_type, mod);
4706 }3601 }
47073602
4708 pub fn floatMulScalar(3603 pub fn floatMulScalar(
4709 lhs: Value,3604 lhs: Value,
4710 rhs: Value,3605 rhs: Value,
4711 float_type: Type,3606 float_type: Type,
4712 arena: Allocator,3607 mod: *Module,
4713 target: Target,
4714 ) !Value {3608 ) !Value {
4715 switch (float_type.floatBits(target)) {3609 const target = mod.getTarget();
4716 16 => {3610 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4717 const lhs_val = lhs.toFloat(f16);3611 16 => .{ .f16 = lhs.toFloat(f16, mod) * rhs.toFloat(f16, mod) },
4718 const rhs_val = rhs.toFloat(f16);3612 32 => .{ .f32 = lhs.toFloat(f32, mod) * rhs.toFloat(f32, mod) },
4719 return Value.Tag.float_16.create(arena, lhs_val * rhs_val);3613 64 => .{ .f64 = lhs.toFloat(f64, mod) * rhs.toFloat(f64, mod) },
4720 },3614 80 => .{ .f80 = lhs.toFloat(f80, mod) * rhs.toFloat(f80, mod) },
4721 32 => {3615 128 => .{ .f128 = lhs.toFloat(f128, mod) * rhs.toFloat(f128, mod) },
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 },
4741 else => unreachable,3616 else => unreachable,
4742 }3617 };
3618 return (try mod.intern(.{ .float = .{
3619 .ty = float_type.toIntern(),
3620 .storage = storage,
3621 } })).toValue();
4743 }3622 }
47443623
4745 pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3624 pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4746 const target = mod.getTarget();3625 if (float_type.zigTypeTag(mod) == .Vector) {
4747 if (float_type.zigTypeTag() == .Vector) {3626 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4748 const result_data = try arena.alloc(Value, float_type.vectorLen());3627 const scalar_ty = float_type.scalarType(mod);
4749 for (result_data, 0..) |*scalar, i| {3628 for (result_data, 0..) |*scalar, i| {
4750 var buf: Value.ElemValueBuffer = undefined;3629 const elem_val = try val.elemValue(mod, i);
4751 const elem_val = val.elemValueBuffer(mod, i, &buf);3630 scalar.* = try (try sqrtScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4752 scalar.* = try sqrtScalar(elem_val, float_type.scalarType(), arena, target);
4753 }3631 }
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();
4755 }3636 }
4756 return sqrtScalar(val, float_type, arena, target);3637 return sqrtScalar(val, float_type, mod);
4757 }3638 }
47583639
4759 pub fn sqrtScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3640 pub fn sqrtScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4760 switch (float_type.floatBits(target)) {3641 const target = mod.getTarget();
4761 16 => {3642 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4762 const f = val.toFloat(f16);3643 16 => .{ .f16 = @sqrt(val.toFloat(f16, mod)) },
4763 return Value.Tag.float_16.create(arena, @sqrt(f));3644 32 => .{ .f32 = @sqrt(val.toFloat(f32, mod)) },
4764 },3645 64 => .{ .f64 = @sqrt(val.toFloat(f64, mod)) },
4765 32 => {3646 80 => .{ .f80 = @sqrt(val.toFloat(f80, mod)) },
4766 const f = val.toFloat(f32);3647 128 => .{ .f128 = @sqrt(val.toFloat(f128, mod)) },
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 },
4781 else => unreachable,3648 else => unreachable,
4782 }3649 };
3650 return (try mod.intern(.{ .float = .{
3651 .ty = float_type.toIntern(),
3652 .storage = storage,
3653 } })).toValue();
4783 }3654 }
47843655
4785 pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3656 pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4786 const target = mod.getTarget();3657 if (float_type.zigTypeTag(mod) == .Vector) {
4787 if (float_type.zigTypeTag() == .Vector) {3658 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4788 const result_data = try arena.alloc(Value, float_type.vectorLen());3659 const scalar_ty = float_type.scalarType(mod);
4789 for (result_data, 0..) |*scalar, i| {3660 for (result_data, 0..) |*scalar, i| {
4790 var buf: Value.ElemValueBuffer = undefined;3661 const elem_val = try val.elemValue(mod, i);
4791 const elem_val = val.elemValueBuffer(mod, i, &buf);3662 scalar.* = try (try sinScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4792 scalar.* = try sinScalar(elem_val, float_type.scalarType(), arena, target);
4793 }3663 }
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();
4795 }3668 }
4796 return sinScalar(val, float_type, arena, target);3669 return sinScalar(val, float_type, mod);
4797 }3670 }
47983671
4799 pub fn sinScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3672 pub fn sinScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4800 switch (float_type.floatBits(target)) {3673 const target = mod.getTarget();
4801 16 => {3674 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4802 const f = val.toFloat(f16);3675 16 => .{ .f16 = @sin(val.toFloat(f16, mod)) },
4803 return Value.Tag.float_16.create(arena, @sin(f));3676 32 => .{ .f32 = @sin(val.toFloat(f32, mod)) },
4804 },3677 64 => .{ .f64 = @sin(val.toFloat(f64, mod)) },
4805 32 => {3678 80 => .{ .f80 = @sin(val.toFloat(f80, mod)) },
4806 const f = val.toFloat(f32);3679 128 => .{ .f128 = @sin(val.toFloat(f128, mod)) },
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 },
4821 else => unreachable,3680 else => unreachable,
4822 }3681 };
3682 return (try mod.intern(.{ .float = .{
3683 .ty = float_type.toIntern(),
3684 .storage = storage,
3685 } })).toValue();
4823 }3686 }
48243687
4825 pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3688 pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4826 const target = mod.getTarget();3689 if (float_type.zigTypeTag(mod) == .Vector) {
4827 if (float_type.zigTypeTag() == .Vector) {3690 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4828 const result_data = try arena.alloc(Value, float_type.vectorLen());3691 const scalar_ty = float_type.scalarType(mod);
4829 for (result_data, 0..) |*scalar, i| {3692 for (result_data, 0..) |*scalar, i| {
4830 var buf: Value.ElemValueBuffer = undefined;3693 const elem_val = try val.elemValue(mod, i);
4831 const elem_val = val.elemValueBuffer(mod, i, &buf);3694 scalar.* = try (try cosScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4832 scalar.* = try cosScalar(elem_val, float_type.scalarType(), arena, target);
4833 }3695 }
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();
4835 }3700 }
4836 return cosScalar(val, float_type, arena, target);3701 return cosScalar(val, float_type, mod);
4837 }3702 }
48383703
4839 pub fn cosScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3704 pub fn cosScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4840 switch (float_type.floatBits(target)) {3705 const target = mod.getTarget();
4841 16 => {3706 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4842 const f = val.toFloat(f16);3707 16 => .{ .f16 = @cos(val.toFloat(f16, mod)) },
4843 return Value.Tag.float_16.create(arena, @cos(f));3708 32 => .{ .f32 = @cos(val.toFloat(f32, mod)) },
4844 },3709 64 => .{ .f64 = @cos(val.toFloat(f64, mod)) },
4845 32 => {3710 80 => .{ .f80 = @cos(val.toFloat(f80, mod)) },
4846 const f = val.toFloat(f32);3711 128 => .{ .f128 = @cos(val.toFloat(f128, mod)) },
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 },
4861 else => unreachable,3712 else => unreachable,
4862 }3713 };
3714 return (try mod.intern(.{ .float = .{
3715 .ty = float_type.toIntern(),
3716 .storage = storage,
3717 } })).toValue();
4863 }3718 }
48643719
4865 pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3720 pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4866 const target = mod.getTarget();3721 if (float_type.zigTypeTag(mod) == .Vector) {
4867 if (float_type.zigTypeTag() == .Vector) {3722 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4868 const result_data = try arena.alloc(Value, float_type.vectorLen());3723 const scalar_ty = float_type.scalarType(mod);
4869 for (result_data, 0..) |*scalar, i| {3724 for (result_data, 0..) |*scalar, i| {
4870 var buf: Value.ElemValueBuffer = undefined;3725 const elem_val = try val.elemValue(mod, i);
4871 const elem_val = val.elemValueBuffer(mod, i, &buf);3726 scalar.* = try (try tanScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4872 scalar.* = try tanScalar(elem_val, float_type.scalarType(), arena, target);
4873 }3727 }
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();
4875 }3732 }
4876 return tanScalar(val, float_type, arena, target);3733 return tanScalar(val, float_type, mod);
4877 }3734 }
48783735
4879 pub fn tanScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3736 pub fn tanScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4880 switch (float_type.floatBits(target)) {3737 const target = mod.getTarget();
4881 16 => {3738 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4882 const f = val.toFloat(f16);3739 16 => .{ .f16 = @tan(val.toFloat(f16, mod)) },
4883 return Value.Tag.float_16.create(arena, @tan(f));3740 32 => .{ .f32 = @tan(val.toFloat(f32, mod)) },
4884 },3741 64 => .{ .f64 = @tan(val.toFloat(f64, mod)) },
4885 32 => {3742 80 => .{ .f80 = @tan(val.toFloat(f80, mod)) },
4886 const f = val.toFloat(f32);3743 128 => .{ .f128 = @tan(val.toFloat(f128, mod)) },
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 },
4901 else => unreachable,3744 else => unreachable,
4902 }3745 };
3746 return (try mod.intern(.{ .float = .{
3747 .ty = float_type.toIntern(),
3748 .storage = storage,
3749 } })).toValue();
4903 }3750 }
49043751
4905 pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3752 pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4906 const target = mod.getTarget();3753 if (float_type.zigTypeTag(mod) == .Vector) {
4907 if (float_type.zigTypeTag() == .Vector) {3754 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4908 const result_data = try arena.alloc(Value, float_type.vectorLen());3755 const scalar_ty = float_type.scalarType(mod);
4909 for (result_data, 0..) |*scalar, i| {3756 for (result_data, 0..) |*scalar, i| {
4910 var buf: Value.ElemValueBuffer = undefined;3757 const elem_val = try val.elemValue(mod, i);
4911 const elem_val = val.elemValueBuffer(mod, i, &buf);3758 scalar.* = try (try expScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4912 scalar.* = try expScalar(elem_val, float_type.scalarType(), arena, target);
4913 }3759 }
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();
4915 }3764 }
4916 return expScalar(val, float_type, arena, target);3765 return expScalar(val, float_type, mod);
4917 }3766 }
49183767
4919 pub fn expScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3768 pub fn expScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4920 switch (float_type.floatBits(target)) {3769 const target = mod.getTarget();
4921 16 => {3770 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4922 const f = val.toFloat(f16);3771 16 => .{ .f16 = @exp(val.toFloat(f16, mod)) },
4923 return Value.Tag.float_16.create(arena, @exp(f));3772 32 => .{ .f32 = @exp(val.toFloat(f32, mod)) },
4924 },3773 64 => .{ .f64 = @exp(val.toFloat(f64, mod)) },
4925 32 => {3774 80 => .{ .f80 = @exp(val.toFloat(f80, mod)) },
4926 const f = val.toFloat(f32);3775 128 => .{ .f128 = @exp(val.toFloat(f128, mod)) },
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 },
4941 else => unreachable,3776 else => unreachable,
4942 }3777 };
3778 return (try mod.intern(.{ .float = .{
3779 .ty = float_type.toIntern(),
3780 .storage = storage,
3781 } })).toValue();
4943 }3782 }
49443783
4945 pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3784 pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4946 const target = mod.getTarget();3785 if (float_type.zigTypeTag(mod) == .Vector) {
4947 if (float_type.zigTypeTag() == .Vector) {3786 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4948 const result_data = try arena.alloc(Value, float_type.vectorLen());3787 const scalar_ty = float_type.scalarType(mod);
4949 for (result_data, 0..) |*scalar, i| {3788 for (result_data, 0..) |*scalar, i| {
4950 var buf: Value.ElemValueBuffer = undefined;3789 const elem_val = try val.elemValue(mod, i);
4951 const elem_val = val.elemValueBuffer(mod, i, &buf);3790 scalar.* = try (try exp2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4952 scalar.* = try exp2Scalar(elem_val, float_type.scalarType(), arena, target);
4953 }3791 }
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();
4955 }3796 }
4956 return exp2Scalar(val, float_type, arena, target);3797 return exp2Scalar(val, float_type, mod);
4957 }3798 }
49583799
4959 pub fn exp2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3800 pub fn exp2Scalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4960 switch (float_type.floatBits(target)) {3801 const target = mod.getTarget();
4961 16 => {3802 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4962 const f = val.toFloat(f16);3803 16 => .{ .f16 = @exp2(val.toFloat(f16, mod)) },
4963 return Value.Tag.float_16.create(arena, @exp2(f));3804 32 => .{ .f32 = @exp2(val.toFloat(f32, mod)) },
4964 },3805 64 => .{ .f64 = @exp2(val.toFloat(f64, mod)) },
4965 32 => {3806 80 => .{ .f80 = @exp2(val.toFloat(f80, mod)) },
4966 const f = val.toFloat(f32);3807 128 => .{ .f128 = @exp2(val.toFloat(f128, mod)) },
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 },
4981 else => unreachable,3808 else => unreachable,
4982 }3809 };
3810 return (try mod.intern(.{ .float = .{
3811 .ty = float_type.toIntern(),
3812 .storage = storage,
3813 } })).toValue();
4983 }3814 }
49843815
4985 pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3816 pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4986 const target = mod.getTarget();3817 if (float_type.zigTypeTag(mod) == .Vector) {
4987 if (float_type.zigTypeTag() == .Vector) {3818 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4988 const result_data = try arena.alloc(Value, float_type.vectorLen());3819 const scalar_ty = float_type.scalarType(mod);
4989 for (result_data, 0..) |*scalar, i| {3820 for (result_data, 0..) |*scalar, i| {
4990 var buf: Value.ElemValueBuffer = undefined;3821 const elem_val = try val.elemValue(mod, i);
4991 const elem_val = val.elemValueBuffer(mod, i, &buf);3822 scalar.* = try (try logScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
4992 scalar.* = try logScalar(elem_val, float_type.scalarType(), arena, target);
4993 }3823 }
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();
4995 }3828 }
4996 return logScalar(val, float_type, arena, target);3829 return logScalar(val, float_type, mod);
4997 }3830 }
49983831
4999 pub fn logScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3832 pub fn logScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5000 switch (float_type.floatBits(target)) {3833 const target = mod.getTarget();
5001 16 => {3834 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5002 const f = val.toFloat(f16);3835 16 => .{ .f16 = @log(val.toFloat(f16, mod)) },
5003 return Value.Tag.float_16.create(arena, @log(f));3836 32 => .{ .f32 = @log(val.toFloat(f32, mod)) },
5004 },3837 64 => .{ .f64 = @log(val.toFloat(f64, mod)) },
5005 32 => {3838 80 => .{ .f80 = @log(val.toFloat(f80, mod)) },
5006 const f = val.toFloat(f32);3839 128 => .{ .f128 = @log(val.toFloat(f128, mod)) },
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 },
5021 else => unreachable,3840 else => unreachable,
5022 }3841 };
3842 return (try mod.intern(.{ .float = .{
3843 .ty = float_type.toIntern(),
3844 .storage = storage,
3845 } })).toValue();
5023 }3846 }
50243847
5025 pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3848 pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5026 const target = mod.getTarget();3849 if (float_type.zigTypeTag(mod) == .Vector) {
5027 if (float_type.zigTypeTag() == .Vector) {3850 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5028 const result_data = try arena.alloc(Value, float_type.vectorLen());3851 const scalar_ty = float_type.scalarType(mod);
5029 for (result_data, 0..) |*scalar, i| {3852 for (result_data, 0..) |*scalar, i| {
5030 var buf: Value.ElemValueBuffer = undefined;3853 const elem_val = try val.elemValue(mod, i);
5031 const elem_val = val.elemValueBuffer(mod, i, &buf);3854 scalar.* = try (try log2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
5032 scalar.* = try log2Scalar(elem_val, float_type.scalarType(), arena, target);
5033 }3855 }
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();
5035 }3860 }
5036 return log2Scalar(val, float_type, arena, target);3861 return log2Scalar(val, float_type, mod);
5037 }3862 }
50383863
5039 pub fn log2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3864 pub fn log2Scalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5040 switch (float_type.floatBits(target)) {3865 const target = mod.getTarget();
5041 16 => {3866 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5042 const f = val.toFloat(f16);3867 16 => .{ .f16 = @log2(val.toFloat(f16, mod)) },
5043 return Value.Tag.float_16.create(arena, @log2(f));3868 32 => .{ .f32 = @log2(val.toFloat(f32, mod)) },
5044 },3869 64 => .{ .f64 = @log2(val.toFloat(f64, mod)) },
5045 32 => {3870 80 => .{ .f80 = @log2(val.toFloat(f80, mod)) },
5046 const f = val.toFloat(f32);3871 128 => .{ .f128 = @log2(val.toFloat(f128, mod)) },
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 },
5061 else => unreachable,3872 else => unreachable,
5062 }3873 };
3874 return (try mod.intern(.{ .float = .{
3875 .ty = float_type.toIntern(),
3876 .storage = storage,
3877 } })).toValue();
5063 }3878 }
50643879
5065 pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3880 pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5066 const target = mod.getTarget();3881 if (float_type.zigTypeTag(mod) == .Vector) {
5067 if (float_type.zigTypeTag() == .Vector) {3882 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5068 const result_data = try arena.alloc(Value, float_type.vectorLen());3883 const scalar_ty = float_type.scalarType(mod);
5069 for (result_data, 0..) |*scalar, i| {3884 for (result_data, 0..) |*scalar, i| {
5070 var buf: Value.ElemValueBuffer = undefined;3885 const elem_val = try val.elemValue(mod, i);
5071 const elem_val = val.elemValueBuffer(mod, i, &buf);3886 scalar.* = try (try log10Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
5072 scalar.* = try log10Scalar(elem_val, float_type.scalarType(), arena, target);
5073 }3887 }
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();
5075 }3892 }
5076 return log10Scalar(val, float_type, arena, target);3893 return log10Scalar(val, float_type, mod);
5077 }3894 }
50783895
5079 pub fn log10Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3896 pub fn log10Scalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5080 switch (float_type.floatBits(target)) {3897 const target = mod.getTarget();
5081 16 => {3898 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5082 const f = val.toFloat(f16);3899 16 => .{ .f16 = @log10(val.toFloat(f16, mod)) },
5083 return Value.Tag.float_16.create(arena, @log10(f));3900 32 => .{ .f32 = @log10(val.toFloat(f32, mod)) },
5084 },3901 64 => .{ .f64 = @log10(val.toFloat(f64, mod)) },
5085 32 => {3902 80 => .{ .f80 = @log10(val.toFloat(f80, mod)) },
5086 const f = val.toFloat(f32);3903 128 => .{ .f128 = @log10(val.toFloat(f128, mod)) },
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 },
5101 else => unreachable,3904 else => unreachable,
5102 }3905 };
3906 return (try mod.intern(.{ .float = .{
3907 .ty = float_type.toIntern(),
3908 .storage = storage,
3909 } })).toValue();
5103 }3910 }
51043911
5105 pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3912 pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5106 const target = mod.getTarget();3913 if (float_type.zigTypeTag(mod) == .Vector) {
5107 if (float_type.zigTypeTag() == .Vector) {3914 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5108 const result_data = try arena.alloc(Value, float_type.vectorLen());3915 const scalar_ty = float_type.scalarType(mod);
5109 for (result_data, 0..) |*scalar, i| {3916 for (result_data, 0..) |*scalar, i| {
5110 var buf: Value.ElemValueBuffer = undefined;3917 const elem_val = try val.elemValue(mod, i);
5111 const elem_val = val.elemValueBuffer(mod, i, &buf);3918 scalar.* = try (try fabsScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
5112 scalar.* = try fabsScalar(elem_val, float_type.scalarType(), arena, target);
5113 }3919 }
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();
5115 }3924 }
5116 return fabsScalar(val, float_type, arena, target);3925 return fabsScalar(val, float_type, mod);
5117 }3926 }
51183927
5119 pub fn fabsScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3928 pub fn fabsScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5120 switch (float_type.floatBits(target)) {3929 const target = mod.getTarget();
5121 16 => {3930 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5122 const f = val.toFloat(f16);3931 16 => .{ .f16 = @fabs(val.toFloat(f16, mod)) },
5123 return Value.Tag.float_16.create(arena, @fabs(f));3932 32 => .{ .f32 = @fabs(val.toFloat(f32, mod)) },
5124 },3933 64 => .{ .f64 = @fabs(val.toFloat(f64, mod)) },
5125 32 => {3934 80 => .{ .f80 = @fabs(val.toFloat(f80, mod)) },
5126 const f = val.toFloat(f32);3935 128 => .{ .f128 = @fabs(val.toFloat(f128, mod)) },
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 },
5141 else => unreachable,3936 else => unreachable,
5142 }3937 };
3938 return (try mod.intern(.{ .float = .{
3939 .ty = float_type.toIntern(),
3940 .storage = storage,
3941 } })).toValue();
5143 }3942 }
51443943
5145 pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3944 pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5146 const target = mod.getTarget();3945 if (float_type.zigTypeTag(mod) == .Vector) {
5147 if (float_type.zigTypeTag() == .Vector) {3946 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5148 const result_data = try arena.alloc(Value, float_type.vectorLen());3947 const scalar_ty = float_type.scalarType(mod);
5149 for (result_data, 0..) |*scalar, i| {3948 for (result_data, 0..) |*scalar, i| {
5150 var buf: Value.ElemValueBuffer = undefined;3949 const elem_val = try val.elemValue(mod, i);
5151 const elem_val = val.elemValueBuffer(mod, i, &buf);3950 scalar.* = try (try floorScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
5152 scalar.* = try floorScalar(elem_val, float_type.scalarType(), arena, target);
5153 }3951 }
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();
5155 }3956 }
5156 return floorScalar(val, float_type, arena, target);3957 return floorScalar(val, float_type, mod);
5157 }3958 }
51583959
5159 pub fn floorScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3960 pub fn floorScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5160 switch (float_type.floatBits(target)) {3961 const target = mod.getTarget();
5161 16 => {3962 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5162 const f = val.toFloat(f16);3963 16 => .{ .f16 = @floor(val.toFloat(f16, mod)) },
5163 return Value.Tag.float_16.create(arena, @floor(f));3964 32 => .{ .f32 = @floor(val.toFloat(f32, mod)) },
5164 },3965 64 => .{ .f64 = @floor(val.toFloat(f64, mod)) },
5165 32 => {3966 80 => .{ .f80 = @floor(val.toFloat(f80, mod)) },
5166 const f = val.toFloat(f32);3967 128 => .{ .f128 = @floor(val.toFloat(f128, mod)) },
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 },
5181 else => unreachable,3968 else => unreachable,
5182 }3969 };
3970 return (try mod.intern(.{ .float = .{
3971 .ty = float_type.toIntern(),
3972 .storage = storage,
3973 } })).toValue();
5183 }3974 }
51843975
5185 pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3976 pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5186 const target = mod.getTarget();3977 if (float_type.zigTypeTag(mod) == .Vector) {
5187 if (float_type.zigTypeTag() == .Vector) {3978 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5188 const result_data = try arena.alloc(Value, float_type.vectorLen());3979 const scalar_ty = float_type.scalarType(mod);
5189 for (result_data, 0..) |*scalar, i| {3980 for (result_data, 0..) |*scalar, i| {
5190 var buf: Value.ElemValueBuffer = undefined;3981 const elem_val = try val.elemValue(mod, i);
5191 const elem_val = val.elemValueBuffer(mod, i, &buf);3982 scalar.* = try (try ceilScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
5192 scalar.* = try ceilScalar(elem_val, float_type.scalarType(), arena, target);
5193 }3983 }
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();
5195 }3988 }
5196 return ceilScalar(val, float_type, arena, target);3989 return ceilScalar(val, float_type, mod);
5197 }3990 }
51983991
5199 pub fn ceilScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {3992 pub fn ceilScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5200 switch (float_type.floatBits(target)) {3993 const target = mod.getTarget();
5201 16 => {3994 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5202 const f = val.toFloat(f16);3995 16 => .{ .f16 = @ceil(val.toFloat(f16, mod)) },
5203 return Value.Tag.float_16.create(arena, @ceil(f));3996 32 => .{ .f32 = @ceil(val.toFloat(f32, mod)) },
5204 },3997 64 => .{ .f64 = @ceil(val.toFloat(f64, mod)) },
5205 32 => {3998 80 => .{ .f80 = @ceil(val.toFloat(f80, mod)) },
5206 const f = val.toFloat(f32);3999 128 => .{ .f128 = @ceil(val.toFloat(f128, mod)) },
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 },
5221 else => unreachable,4000 else => unreachable,
5222 }4001 };
4002 return (try mod.intern(.{ .float = .{
4003 .ty = float_type.toIntern(),
4004 .storage = storage,
4005 } })).toValue();
5223 }4006 }
52244007
5225 pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {4008 pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5226 const target = mod.getTarget();4009 if (float_type.zigTypeTag(mod) == .Vector) {
5227 if (float_type.zigTypeTag() == .Vector) {4010 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5228 const result_data = try arena.alloc(Value, float_type.vectorLen());4011 const scalar_ty = float_type.scalarType(mod);
5229 for (result_data, 0..) |*scalar, i| {4012 for (result_data, 0..) |*scalar, i| {
5230 var buf: Value.ElemValueBuffer = undefined;4013 const elem_val = try val.elemValue(mod, i);
5231 const elem_val = val.elemValueBuffer(mod, i, &buf);4014 scalar.* = try (try roundScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
5232 scalar.* = try roundScalar(elem_val, float_type.scalarType(), arena, target);
5233 }4015 }
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();
5235 }4020 }
5236 return roundScalar(val, float_type, arena, target);4021 return roundScalar(val, float_type, mod);
5237 }4022 }
52384023
5239 pub fn roundScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4024 pub fn roundScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5240 switch (float_type.floatBits(target)) {4025 const target = mod.getTarget();
5241 16 => {4026 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5242 const f = val.toFloat(f16);4027 16 => .{ .f16 = @round(val.toFloat(f16, mod)) },
5243 return Value.Tag.float_16.create(arena, @round(f));4028 32 => .{ .f32 = @round(val.toFloat(f32, mod)) },
5244 },4029 64 => .{ .f64 = @round(val.toFloat(f64, mod)) },
5245 32 => {4030 80 => .{ .f80 = @round(val.toFloat(f80, mod)) },
5246 const f = val.toFloat(f32);4031 128 => .{ .f128 = @round(val.toFloat(f128, mod)) },
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 },
5261 else => unreachable,4032 else => unreachable,
5262 }4033 };
4034 return (try mod.intern(.{ .float = .{
4035 .ty = float_type.toIntern(),
4036 .storage = storage,
4037 } })).toValue();
5263 }4038 }
52644039
5265 pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {4040 pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5266 const target = mod.getTarget();4041 if (float_type.zigTypeTag(mod) == .Vector) {
5267 if (float_type.zigTypeTag() == .Vector) {4042 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5268 const result_data = try arena.alloc(Value, float_type.vectorLen());4043 const scalar_ty = float_type.scalarType(mod);
5269 for (result_data, 0..) |*scalar, i| {4044 for (result_data, 0..) |*scalar, i| {
5270 var buf: Value.ElemValueBuffer = undefined;4045 const elem_val = try val.elemValue(mod, i);
5271 const elem_val = val.elemValueBuffer(mod, i, &buf);4046 scalar.* = try (try truncScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
5272 scalar.* = try truncScalar(elem_val, float_type.scalarType(), arena, target);
5273 }4047 }
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();
5275 }4052 }
5276 return truncScalar(val, float_type, arena, target);4053 return truncScalar(val, float_type, mod);
5277 }4054 }
52784055
5279 pub fn truncScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {4056 pub fn truncScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
5280 switch (float_type.floatBits(target)) {4057 const target = mod.getTarget();
5281 16 => {4058 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5282 const f = val.toFloat(f16);4059 16 => .{ .f16 = @trunc(val.toFloat(f16, mod)) },
5283 return Value.Tag.float_16.create(arena, @trunc(f));4060 32 => .{ .f32 = @trunc(val.toFloat(f32, mod)) },
5284 },4061 64 => .{ .f64 = @trunc(val.toFloat(f64, mod)) },
5285 32 => {4062 80 => .{ .f80 = @trunc(val.toFloat(f80, mod)) },
5286 const f = val.toFloat(f32);4063 128 => .{ .f128 = @trunc(val.toFloat(f128, mod)) },
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 },
5301 else => unreachable,4064 else => unreachable,
5302 }4065 };
4066 return (try mod.intern(.{ .float = .{
4067 .ty = float_type.toIntern(),
4068 .storage = storage,
4069 } })).toValue();
5303 }4070 }
53044071
5305 pub fn mulAdd(4072 pub fn mulAdd(
...@@ -5310,28 +4077,21 @@ pub const Value = extern union {...@@ -5310,28 +4077,21 @@ pub const Value = extern union {
5310 arena: Allocator,4077 arena: Allocator,
5311 mod: *Module,4078 mod: *Module,
5312 ) !Value {4079 ) !Value {
5313 const target = mod.getTarget();4080 if (float_type.zigTypeTag(mod) == .Vector) {
5314 if (float_type.zigTypeTag() == .Vector) {4081 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
5315 const result_data = try arena.alloc(Value, float_type.vectorLen());4082 const scalar_ty = float_type.scalarType(mod);
5316 for (result_data, 0..) |*scalar, i| {4083 for (result_data, 0..) |*scalar, i| {
5317 var mulend1_buf: Value.ElemValueBuffer = undefined;4084 const mulend1_elem = try mulend1.elemValue(mod, i);
5318 const mulend1_elem = mulend1.elemValueBuffer(mod, i, &mulend1_buf);4085 const mulend2_elem = try mulend2.elemValue(mod, i);
5319 var mulend2_buf: Value.ElemValueBuffer = undefined;4086 const addend_elem = try addend.elemValue(mod, i);
5320 const mulend2_elem = mulend2.elemValueBuffer(mod, i, &mulend2_buf);4087 scalar.* = try (try mulAddScalar(scalar_ty, mulend1_elem, mulend2_elem, addend_elem, mod)).intern(scalar_ty, mod);
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 );
5331 }4088 }
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();
5333 }4093 }
5334 return mulAddScalar(float_type, mulend1, mulend2, addend, arena, target);4094 return mulAddScalar(float_type, mulend1, mulend2, addend, mod);
5335 }4095 }
53364096
5337 pub fn mulAddScalar(4097 pub fn mulAddScalar(
...@@ -5339,54 +4099,33 @@ pub const Value = extern union {...@@ -5339,54 +4099,33 @@ pub const Value = extern union {
5339 mulend1: Value,4099 mulend1: Value,
5340 mulend2: Value,4100 mulend2: Value,
5341 addend: Value,4101 addend: Value,
5342 arena: Allocator,4102 mod: *Module,
5343 target: Target,
5344 ) Allocator.Error!Value {4103 ) Allocator.Error!Value {
5345 switch (float_type.floatBits(target)) {4104 const target = mod.getTarget();
5346 16 => {4105 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
5347 const m1 = mulend1.toFloat(f16);4106 16 => .{ .f16 = @mulAdd(f16, mulend1.toFloat(f16, mod), mulend2.toFloat(f16, mod), addend.toFloat(f16, mod)) },
5348 const m2 = mulend2.toFloat(f16);4107 32 => .{ .f32 = @mulAdd(f32, mulend1.toFloat(f32, mod), mulend2.toFloat(f32, mod), addend.toFloat(f32, mod)) },
5349 const a = addend.toFloat(f16);4108 64 => .{ .f64 = @mulAdd(f64, mulend1.toFloat(f64, mod), mulend2.toFloat(f64, mod), addend.toFloat(f64, mod)) },
5350 return Value.Tag.float_16.create(arena, @mulAdd(f16, m1, m2, a));4109 80 => .{ .f80 = @mulAdd(f80, mulend1.toFloat(f80, mod), mulend2.toFloat(f80, mod), addend.toFloat(f80, mod)) },
5351 },4110 128 => .{ .f128 = @mulAdd(f128, mulend1.toFloat(f128, mod), mulend2.toFloat(f128, mod), addend.toFloat(f128, mod)) },
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 },
5376 else => unreachable,4111 else => unreachable,
5377 }4112 };
4113 return (try mod.intern(.{ .float = .{
4114 .ty = float_type.toIntern(),
4115 .storage = storage,
4116 } })).toValue();
5378 }4117 }
53794118
5380 /// If the value is represented in-memory as a series of bytes that all4119 /// If the value is represented in-memory as a series of bytes that all
5381 /// have the same value, return that byte value, otherwise null.4120 /// 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 {4121 pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module) !?Value {
5383 const target = mod.getTarget();4122 const abi_size = std.math.cast(usize, ty.abiSize(mod)) orelse return null;
5384 const abi_size = std.math.cast(usize, ty.abiSize(target)) orelse return null;
5385 assert(abi_size >= 1);4123 assert(abi_size >= 1);
5386 const byte_buffer = try mod.gpa.alloc(u8, abi_size);4124 const byte_buffer = try mod.gpa.alloc(u8, abi_size);
5387 defer mod.gpa.free(byte_buffer);4125 defer mod.gpa.free(byte_buffer);
53884126
5389 writeToMemory(val, ty, mod, byte_buffer) catch |err| switch (err) {4127 writeToMemory(val, ty, mod, byte_buffer) catch |err| switch (err) {
4128 error.OutOfMemory => return error.OutOfMemory,
5390 error.ReinterpretDeclRef => return null,4129 error.ReinterpretDeclRef => return null,
5391 // TODO: The writeToMemory function was originally created for the purpose4130 // TODO: The writeToMemory function was originally created for the purpose
5392 // of comptime pointer casting. However, it is now additionally being used4131 // of comptime pointer casting. However, it is now additionally being used
...@@ -5400,118 +4139,22 @@ pub const Value = extern union {...@@ -5400,118 +4139,22 @@ pub const Value = extern union {
5400 for (byte_buffer[1..]) |byte| {4139 for (byte_buffer[1..]) |byte| {
5401 if (byte != first_byte) return null;4140 if (byte != first_byte) return null;
5402 }4141 }
5403 value_buffer.* = .{4142 return try mod.intValue(Type.u8, first_byte);
5404 .base = .{ .tag = .int_u64 },4143 }
5405 .data = first_byte,4144
5406 };4145 pub fn isGenericPoison(val: Value) bool {
5407 return initPayload(&value_buffer.base);4146 return val.toIntern() == .generic_poison;
5408 }4147 }
54094148
5410 /// This type is not copyable since it may contain pointers to its inner data.4149 /// This type is not copyable since it may contain pointers to its inner data.
5411 pub const Payload = struct {4150 pub const Payload = struct {
5412 tag: Tag,4151 tag: Tag,
54134152
5414 pub const U32 = struct {4153 pub const Slice = 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 {
5489 base: Payload,4154 base: Payload,
5490 data: struct {4155 data: struct {
5491 field_val: Value,4156 ptr: Value,
5492 field_ty: Type,4157 len: Value,
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,
5515 },4158 },
5516 };4159 };
55174160
...@@ -5521,9 +4164,9 @@ pub const Value = extern union {...@@ -5521,9 +4164,9 @@ pub const Value = extern union {
5521 data: []const u8,4164 data: []const u8,
5522 };4165 };
55234166
5524 pub const StrLit = struct {4167 pub const SubValue = struct {
5525 base: Payload,4168 base: Payload,
5526 data: Module.StringLiteralContext.Key,4169 data: Value,
5527 };4170 };
55284171
5529 pub const Aggregate = struct {4172 pub const Aggregate = struct {
...@@ -5533,156 +4176,42 @@ pub const Value = extern union {...@@ -5533,156 +4176,42 @@ pub const Value = extern union {
5533 data: []Value,4176 data: []Value,
5534 };4177 };
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
5642 pub const Union = struct {4179 pub const Union = struct {
5643 pub const base_tag = Tag.@"union";4180 pub const base_tag = Tag.@"union";
56444181
5645 base: Payload = .{ .tag = base_tag },4182 base: Payload = .{ .tag = base_tag },
5646 data: struct {4183 data: Data,
4184
4185 pub const Data = struct {
5647 tag: Value,4186 tag: Value,
5648 val: Value,4187 val: Value,
5649 },4188 };
5650 };4189 };
5651 };4190 };
56524191
5653 /// Big enough to fit any non-BigInt value4192 pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace;
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 };
56594193
5660 pub const zero = initTag(.zero);4194 pub const zero_usize: Value = .{ .ip_index = .zero_usize, .legacy = undefined };
5661 pub const one = initTag(.one);4195 pub const zero_u8: Value = .{ .ip_index = .zero_u8, .legacy = undefined };
5662 pub const negative_one: Value = .{ .ptr_otherwise = &negative_one_payload.base };4196 pub const zero_comptime_int: Value = .{ .ip_index = .zero, .legacy = undefined };
5663 pub const undef = initTag(.undef);4197 pub const one_comptime_int: Value = .{ .ip_index = .one, .legacy = undefined };
5664 pub const @"void" = initTag(.void_value);4198 pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one, .legacy = undefined };
5665 pub const @"null" = initTag(.null_value);4199 pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined };
5666 pub const @"false" = initTag(.bool_false);4200 pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined };
5667 pub const @"true" = initTag(.bool_true);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
5669 pub fn makeBool(x: bool) Value {4210 pub fn makeBool(x: bool) Value {
5670 return if (x) Value.true else Value.false;4211 return if (x) Value.true else Value.false;
5671 }4212 }
56724213
5673 pub fn boolToInt(x: bool) Value {4214 pub const RuntimeIndex = InternPool.RuntimeIndex;
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 };
56864215
5687 /// This function is used in the debugger pretty formatters in tools/ to fetch the4216 /// This function is used in the debugger pretty formatters in tools/ to fetch the
5688 /// Tag to Payload mapping to facilitate fancy debug printing for this type.4217 /// Tag to Payload mapping to facilitate fancy debug printing for this type.
...@@ -5691,7 +4220,7 @@ pub const Value = extern union {...@@ -5691,7 +4220,7 @@ pub const Value = extern union {
5691 var fields: [tags.len]std.builtin.Type.StructField = undefined;4220 var fields: [tags.len]std.builtin.Type.StructField = undefined;
5692 for (&fields, tags) |*field, t| field.* = .{4221 for (&fields, tags) |*field, t| field.* = .{
5693 .name = t.name,4222 .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(),
5695 .default_value = null,4224 .default_value = null,
5696 .is_comptime = false,4225 .is_comptime = false,
5697 .alignment = 0,4226 .alignment = 0,
...@@ -5713,8 +4242,3 @@ pub const Value = extern union {...@@ -5713,8 +4242,3 @@ pub const Value = extern union {
5713 }4242 }
5714 }4243 }
5715};4244};
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" {...@@ -17,6 +17,7 @@ test "union that needs padding bytes inside an array" {
17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
2021
21 var as = [_]A{22 var as = [_]A{
22 A{ .B = B{ .D = 1 } },23 A{ .B = B{ .D = 1 } },
test/behavior/bugs/6456.zig+1-1
...@@ -24,7 +24,7 @@ test "issue 6456" {...@@ -24,7 +24,7 @@ test "issue 6456" {
24 .alignment = 0,24 .alignment = 0,
25 .name = name,25 .name = name,
26 .type = usize,26 .type = usize,
27 .default_value = &@as(?usize, null),27 .default_value = null,
28 .is_comptime = false,28 .is_comptime = false,
29 }};29 }};
30 }30 }
test/behavior/cast.zig+8-8
...@@ -746,8 +746,8 @@ test "peer type resolution: disjoint error sets" {...@@ -746,8 +746,8 @@ test "peer type resolution: disjoint error sets" {
746 try expect(error_set_info == .ErrorSet);746 try expect(error_set_info == .ErrorSet);
747 try expect(error_set_info.ErrorSet.?.len == 3);747 try expect(error_set_info.ErrorSet.?.len == 3);
748 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));748 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"));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, "Two"));750 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
751 }751 }
752752
753 {753 {
...@@ -756,8 +756,8 @@ test "peer type resolution: disjoint error sets" {...@@ -756,8 +756,8 @@ test "peer type resolution: disjoint error sets" {
756 try expect(error_set_info == .ErrorSet);756 try expect(error_set_info == .ErrorSet);
757 try expect(error_set_info.ErrorSet.?.len == 3);757 try expect(error_set_info.ErrorSet.?.len == 3);
758 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));758 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"));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, "Two"));760 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
761 }761 }
762}762}
763763
...@@ -778,8 +778,8 @@ test "peer type resolution: error union and error set" {...@@ -778,8 +778,8 @@ test "peer type resolution: error union and error set" {
778 const error_set_info = @typeInfo(info.ErrorUnion.error_set);778 const error_set_info = @typeInfo(info.ErrorUnion.error_set);
779 try expect(error_set_info.ErrorSet.?.len == 3);779 try expect(error_set_info.ErrorSet.?.len == 3);
780 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));780 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"));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, "Two"));782 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
783 }783 }
784784
785 {785 {
...@@ -790,8 +790,8 @@ test "peer type resolution: error union and error set" {...@@ -790,8 +790,8 @@ test "peer type resolution: error union and error set" {
790 const error_set_info = @typeInfo(info.ErrorUnion.error_set);790 const error_set_info = @typeInfo(info.ErrorUnion.error_set);
791 try expect(error_set_info.ErrorSet.?.len == 3);791 try expect(error_set_info.ErrorSet.?.len == 3);
792 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));792 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"));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, "Two"));794 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
795 }795 }
796}796}
797797
test/behavior/type_info.zig+2-2
...@@ -214,8 +214,8 @@ test "type info: error set merged" {...@@ -214,8 +214,8 @@ test "type info: error set merged" {
214 try expect(error_set_info == .ErrorSet);214 try expect(error_set_info == .ErrorSet);
215 try expect(error_set_info.ErrorSet.?.len == 3);215 try expect(error_set_info.ErrorSet.?.len == 3);
216 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));216 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"));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, "Two"));218 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
219}219}
220220
221test "type info: enum info" {221test "type info: enum info" {
test/cases/compile_errors/access_non-existent_member_of_error_set.zig-1
...@@ -9,4 +9,3 @@ comptime {...@@ -9,4 +9,3 @@ comptime {
9// target=native9// target=native
10//10//
11// :3:18: error: no error named 'Bar' in 'error{A}'11// :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 {...@@ -14,4 +14,4 @@ export fn entry() void {
14// :2:5: error: found compile log statement14// :2:5: error: found compile log statement
15//15//
16// Compile Log Output:16// 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 @@...@@ -1,5 +1,5 @@
1const Set1 = error {A, B};1const Set1 = error{ A, B };
2const Set2 = error {A, C};2const Set2 = error{ A, C };
3comptime {3comptime {
4 var x = Set1.B;4 var x = Set1.B;
5 var y = @errSetCast(Set2, x);5 var y = @errSetCast(Set2, x);
...@@ -10,5 +10,4 @@ comptime {...@@ -10,5 +10,4 @@ comptime {
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
13// :5:13: error: 'error.B' not a member of error set 'error{A,C}'13// :5:13: error: 'error.B' not a member of error set 'error{C,A}'
14// :2:14: note: error set declared here
test/cases/compile_errors/implicit_cast_of_error_set_not_a_subset.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const Set1 = error{A, B};1const Set1 = error{ A, B };
2const Set2 = error{A, C};2const Set2 = error{ A, C };
3export fn entry() void {3export fn entry() void {
4 foo(Set1.B);4 foo(Set1.B);
5}5}
...@@ -12,5 +12,5 @@ fn foo(set1: Set1) void {...@@ -12,5 +12,5 @@ fn foo(set1: Set1) void {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
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}'
16// :7:19: note: 'error.B' not a member of destination error set16// :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 {...@@ -16,5 +16,4 @@ comptime {
16// backend=llvm16// backend=llvm
17// target=native17// target=native
18//18//
19// :11:13: error: 'error.B' not a member of error set 'error{A,C}'19// :11:13: error: 'error.B' not a member of error set 'error{C,A}'
20// :5:14: note: error set declared here
test/cases/compile_errors/invalid_non-exhaustive_enum_to_union.zig+1-1
...@@ -24,5 +24,5 @@ export fn bar() void {...@@ -24,5 +24,5 @@ export fn bar() void {
24//24//
25// :12:16: error: runtime coercion to union 'tmp.U' from non-exhaustive enum25// :12:16: error: runtime coercion to union 'tmp.U' from non-exhaustive enum
26// :1:11: note: enum declared here26// :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)'
28// :6:11: note: union declared here28// :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 {...@@ -16,9 +16,9 @@ comptime {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
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"}'
20// :2:29: note: cast discards const qualifier20// :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"}'
22// :6:31: note: cast discards const qualifier22// :6:31: note: cast discards const qualifier
23// :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}'23// :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}'
24// :11:19: note: cast discards const qualifier24// :11:19: note: cast discards const qualifier
test/cases/compile_errors/return_invalid_type_from_test.zig+4-2
...@@ -1,8 +1,10 @@...@@ -1,8 +1,10 @@
1test "example" { return 1; }1test "example" {
2 return 1;
3}
24
3// error5// error
4// backend=stage26// backend=stage2
5// target=native7// target=native
6// is_test=18// is_test=1
7//9//
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 @@...@@ -1,5 +1,5 @@
1test "enum" {1test "enum" {
2 const E = enum(u8) {A, B, _};2 const E = enum(u8) { A, B, _ };
3 _ = @tagName(@intToEnum(E, 5));3 _ = @tagName(@intToEnum(E, 5));
4}4}
55
...@@ -8,5 +8,5 @@ test "enum" {...@@ -8,5 +8,5 @@ test "enum" {
8// target=native8// target=native
9// is_test=19// is_test=1
10//10//
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'
12// :2:15: note: declared here12// :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 {...@@ -41,4 +41,4 @@ pub export fn entry5() void {
41// :12:14: error: missing tuple field with index 141// :12:14: error: missing tuple field with index 1
42// :17:14: error: missing tuple field with index 142// :17:14: error: missing tuple field with index 1
43// :29:14: error: expected at most 2 tuple fields; found 343// :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 {...@@ -7,4 +7,4 @@ export fn entry() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
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:...@@ -115,7 +115,7 @@ class zig_Slice_SynthProvider:
115 try: return int(name.removeprefix('[').removesuffix(']'))115 try: return int(name.removeprefix('[').removesuffix(']'))
116 except: return -1116 except: return -1
117 def get_child_at_index(self, index):117 def get_child_at_index(self, index):
118 if index < 0 or index >= self.len: return None118 if index not in range(self.len): return None
119 try: return self.ptr.CreateChildAtOffset('[%d]' % index, index * self.elem_size, self.elem_type)119 try: return self.ptr.CreateChildAtOffset('[%d]' % index, index * self.elem_size, self.elem_type)
120 except: return None120 except: return None
121121
...@@ -176,7 +176,7 @@ class zig_TaggedUnion_SynthProvider:...@@ -176,7 +176,7 @@ class zig_TaggedUnion_SynthProvider:
176 def get_child_index(self, name):176 def get_child_index(self, name):
177 try: return ('tag', 'payload').index(name)177 try: return ('tag', 'payload').index(name)
178 except: return -1178 except: return -1
179 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None179 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None
180180
181# Define Zig Standard Library181# Define Zig Standard Library
182182
...@@ -196,7 +196,7 @@ class std_SegmentedList_SynthProvider:...@@ -196,7 +196,7 @@ class std_SegmentedList_SynthProvider:
196 except: return -1196 except: return -1
197 def get_child_at_index(self, index):197 def get_child_at_index(self, index):
198 try:198 try:
199 if index < 0 or index >= self.len: return None199 if index not in range(self.len): return None
200 prealloc_item_count = len(self.prealloc_segment)200 prealloc_item_count = len(self.prealloc_segment)
201 if index < prealloc_item_count: return self.prealloc_segment.child[index]201 if index < prealloc_item_count: return self.prealloc_segment.child[index]
202 prealloc_exp = prealloc_item_count.bit_length() - 1202 prealloc_exp = prealloc_item_count.bit_length() - 1
...@@ -231,7 +231,7 @@ class std_MultiArrayList_SynthProvider:...@@ -231,7 +231,7 @@ class std_MultiArrayList_SynthProvider:
231 except: return -1231 except: return -1
232 def get_child_at_index(self, index):232 def get_child_at_index(self, index):
233 try:233 try:
234 if index < 0 or index >= self.len: return None234 if index not in range(self.len): return None
235 offset = 0235 offset = 0
236 data = lldb.SBData()236 data = lldb.SBData()
237 for field in self.entry_type.fields:237 for field in self.entry_type.fields:
...@@ -266,7 +266,7 @@ class std_MultiArrayList_Slice_SynthProvider:...@@ -266,7 +266,7 @@ class std_MultiArrayList_Slice_SynthProvider:
266 except: return -1266 except: return -1
267 def get_child_at_index(self, index):267 def get_child_at_index(self, index):
268 try:268 try:
269 if index < 0 or index >= self.len: return None269 if index not in range(self.len): return None
270 data = lldb.SBData()270 data = lldb.SBData()
271 for field in self.entry_type.fields:271 for field in self.entry_type.fields:
272 field_type = field.type.GetPointeeType()272 field_type = field.type.GetPointeeType()
...@@ -328,7 +328,7 @@ class std_Entry_SynthProvider:...@@ -328,7 +328,7 @@ class std_Entry_SynthProvider:
328 def has_children(self): return self.num_children() != 0328 def has_children(self): return self.num_children() != 0
329 def num_children(self): return len(self.children)329 def num_children(self): return len(self.children)
330 def get_child_index(self, name): return self.indices.get(name)330 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 None331 def get_child_at_index(self, index): return self.children[index].deref if index in range(len(self.children)) else None
332332
333# Define Zig Stage2 Compiler333# Define Zig Stage2 Compiler
334334
...@@ -345,11 +345,17 @@ class TagAndPayload_SynthProvider:...@@ -345,11 +345,17 @@ class TagAndPayload_SynthProvider:
345 def get_child_index(self, name):345 def get_child_index(self, name):
346 try: return ('tag', 'payload').index(name)346 try: return ('tag', 'payload').index(name)
347 except: return -1347 except: return -1
348 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None348 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):
351 members = value.type.enum_members351 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
354class Module_Decl__Module_Decl_Index_SynthProvider:360class Module_Decl__Module_Decl_Index_SynthProvider:
355 def __init__(self, value, _=None): self.value = value361 def __init__(self, value, _=None): self.value = value
...@@ -359,7 +365,7 @@ class Module_Decl__Module_Decl_Index_SynthProvider:...@@ -359,7 +365,7 @@ class Module_Decl__Module_Decl_Index_SynthProvider:
359 mod = frame.FindVariable('mod') or frame.FindVariable('module')365 mod = frame.FindVariable('mod') or frame.FindVariable('module')
360 if mod: break366 if mod: break
361 else: return367 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')
363 except: pass369 except: pass
364 def has_children(self): return True370 def has_children(self): return True
365 def num_children(self): return 1371 def num_children(self): return 1
...@@ -392,7 +398,7 @@ class TagOrPayloadPtr_SynthProvider:...@@ -392,7 +398,7 @@ class TagOrPayloadPtr_SynthProvider:
392 def get_child_index(self, name):398 def get_child_index(self, name):
393 try: return ('tag', 'payload').index(name)399 try: return ('tag', 'payload').index(name)
394 except: return -1400 except: return -1
395 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None401 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None
396402
397def Module_Decl_name(decl):403def Module_Decl_name(decl):
398 error = lldb.SBError()404 error = lldb.SBError()
...@@ -407,6 +413,89 @@ def Module_Decl_RenderFullyQualifiedName(decl): return '.'.join((Module_Namespac...@@ -407,6 +413,89 @@ def Module_Decl_RenderFullyQualifiedName(decl): return '.'.join((Module_Namespac
407413
408def OwnerDecl_RenderFullyQualifiedName(payload): return Module_Decl_RenderFullyQualifiedName(payload.GetChildMemberWithName('owner_decl').GetChildMemberWithName('decl'))414def 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
410def type_Type_pointer(payload):499def type_Type_pointer(payload):
411 pointee_type = payload.GetChildMemberWithName('pointee_type')500 pointee_type = payload.GetChildMemberWithName('pointee_type')
412 sentinel = payload.GetChildMemberWithName('sentinel').GetChildMemberWithName('child')501 sentinel = payload.GetChildMemberWithName('sentinel').GetChildMemberWithName('child')
...@@ -468,8 +557,8 @@ type_tag_handlers = {...@@ -468,8 +557,8 @@ type_tag_handlers = {
468 'empty_struct_literal': lambda payload: '@TypeOf(.{})',557 'empty_struct_literal': lambda payload: '@TypeOf(.{})',
469558
470 'anyerror_void_error_union': lambda payload: 'anyerror!void',559 'anyerror_void_error_union': lambda payload: 'anyerror!void',
471 'const_slice_u8': lambda payload: '[]const u8',560 'slice_const_u8': lambda payload: '[]const u8',
472 'const_slice_u8_sentinel_0': lambda payload: '[:0]const u8',561 'slice_const_u8_sentinel_0': lambda payload: '[:0]const u8',
473 'fn_noreturn_no_args': lambda payload: 'fn() noreturn',562 'fn_noreturn_no_args': lambda payload: 'fn() noreturn',
474 'fn_void_no_args': lambda payload: 'fn() void',563 'fn_void_no_args': lambda payload: 'fn() void',
475 'fn_naked_noreturn_no_args': lambda payload: 'fn() callconv(.Naked) noreturn',564 'fn_naked_noreturn_no_args': lambda payload: 'fn() callconv(.Naked) noreturn',
...@@ -495,7 +584,7 @@ type_tag_handlers = {...@@ -495,7 +584,7 @@ type_tag_handlers = {
495 'many_mut_pointer': lambda payload: '[*]%s' % type_Type_SummaryProvider(payload),584 'many_mut_pointer': lambda payload: '[*]%s' % type_Type_SummaryProvider(payload),
496 'c_const_pointer': lambda payload: '[*c]const %s' % type_Type_SummaryProvider(payload),585 'c_const_pointer': lambda payload: '[*c]const %s' % type_Type_SummaryProvider(payload),
497 'c_mut_pointer': lambda payload: '[*c]%s' % type_Type_SummaryProvider(payload),586 '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),
499 'mut_slice': lambda payload: '[]%s' % type_Type_SummaryProvider(payload),588 'mut_slice': lambda payload: '[]%s' % type_Type_SummaryProvider(payload),
500 'int_signed': lambda payload: 'i%d' % payload.unsigned,589 'int_signed': lambda payload: 'i%d' % payload.unsigned,
501 'int_unsigned': lambda payload: 'u%d' % payload.unsigned,590 'int_unsigned': lambda payload: 'u%d' % payload.unsigned,
...@@ -611,13 +700,19 @@ def __lldb_init_module(debugger, _=None):...@@ -611,13 +700,19 @@ def __lldb_init_module(debugger, _=None):
611 add(debugger, category='zig.stage2', type='Zir.Inst', identifier='TagAndPayload', synth=True, inline_children=True, summary=True)700 add(debugger, category='zig.stage2', type='Zir.Inst', identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
612 add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Zir\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True)701 add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Zir\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
613 add(debugger, category='zig.stage2', regex=True, type='^Zir\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True)702 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)
615 add(debugger, category='zig.stage2', type='Air.Inst', identifier='TagAndPayload', synth=True, inline_children=True, summary=True)704 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)
616 add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True)706 add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
617 add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True)707 add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True)
618 add(debugger, category='zig.stage2', type='Module.Decl::Module.Decl.Index', synth=True)708 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)709 add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True)
620 add(debugger, category='zig.stage2', type='type.Type', summary=True)710 add(debugger, category='zig.stage2', type='InternPool.Index', synth=True)
621 add(debugger, category='zig.stage2', type='value.Value', identifier='TagOrPayloadPtr', synth=True)711 add(debugger, category='zig.stage2', type='InternPool.NullTerminatedString', summary=True)
622 add(debugger, category='zig.stage2', type='value.Value', 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)
623 add(debugger, category='zig.stage2', type='arch.x86_64.CodeGen.MCValue', identifier='zig_TaggedUnion', synth=True, inline_children=True, summary=True)718 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:...@@ -18,7 +18,7 @@ class TypePrinter:
18 'many_mut_pointer': 'Type.Payload.ElemType',18 'many_mut_pointer': 'Type.Payload.ElemType',
19 'c_const_pointer': 'Type.Payload.ElemType',19 'c_const_pointer': 'Type.Payload.ElemType',
20 'c_mut_pointer': 'Type.Payload.ElemType',20 'c_mut_pointer': 'Type.Payload.ElemType',
21 'const_slice': 'Type.Payload.ElemType',21 'slice_const': 'Type.Payload.ElemType',
22 'mut_slice': 'Type.Payload.ElemType',22 'mut_slice': 'Type.Payload.ElemType',
23 'optional': 'Type.Payload.ElemType',23 'optional': 'Type.Payload.ElemType',
24 'optional_single_mut_pointer': 'Type.Payload.ElemType',24 'optional_single_mut_pointer': 'Type.Payload.ElemType',