| author | |
| committer | |
| log | 0aacb6369fdf3762b7ab6069955684abb63f1459 |
| tree | 8a84783f2dd008e3e0aef59cbe6b9ad0e36c0831 |
| parent | 70c71935c7c9f20353dc2a50b497b752d70d3452 |
| parent | d5d067211b55a9afbbe3ac52daa0f09d37e5f335 |
| signature |
rework generic function calls43 files changed, 3840 insertions(+), 2923 deletions(-)
lib/std/array_hash_map.zig+6-4| ... | @@ -1669,8 +1669,9 @@ pub fn ArrayHashMapUnmanaged( | ... | @@ -1669,8 +1669,9 @@ pub fn ArrayHashMapUnmanaged( |
| 1669 | 1669 | ||
| 1670 | inline fn checkedHash(ctx: anytype, key: anytype) u32 { | 1670 | inline fn checkedHash(ctx: anytype, key: anytype) u32 { |
| 1671 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(key), K, u32, true); | 1671 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(key), K, u32, true); |
| 1672 | // If you get a compile error on the next line, it means that | 1672 | // If you get a compile error on the next line, it means that your |
| 1673 | const hash = ctx.hash(key); // your generic hash function doesn't accept your key | 1673 | // generic hash function doesn't accept your key. |
| 1674 | const hash = ctx.hash(key); | ||
| 1674 | if (@TypeOf(hash) != u32) { | 1675 | if (@TypeOf(hash) != u32) { |
| 1675 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++ | 1676 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++ |
| 1676 | @typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash))); | 1677 | @typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash))); |
| ... | @@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged( | ... | @@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged( |
| 1679 | } | 1680 | } |
| 1680 | inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool { | 1681 | inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool { |
| 1681 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(a), K, u32, true); | 1682 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(a), K, u32, true); |
| 1682 | // If you get a compile error on the next line, it means that | 1683 | // If you get a compile error on the next line, it means that your |
| 1683 | const eql = ctx.eql(a, b, b_index); // your generic eql function doesn't accept (self, adapt key, K, index) | 1684 | // generic eql function doesn't accept (self, adapt key, K, index). |
| 1685 | const eql = ctx.eql(a, b, b_index); | ||
| 1684 | if (@TypeOf(eql) != bool) { | 1686 | if (@TypeOf(eql) != bool) { |
| 1685 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++ | 1687 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++ |
| 1686 | @typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql))); | 1688 | @typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql))); |
src/Air.zig+3-2| ... | @@ -946,6 +946,7 @@ pub const Inst = struct { | ... | @@ -946,6 +946,7 @@ pub const Inst = struct { |
| 946 | slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type), | 946 | slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type), |
| 947 | optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type), | 947 | optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type), |
| 948 | anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type), | 948 | anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type), |
| 949 | adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type), | ||
| 949 | generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type), | 950 | generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type), |
| 950 | empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type), | 951 | empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type), |
| 951 | undef = @intFromEnum(InternPool.Index.undef), | 952 | undef = @intFromEnum(InternPool.Index.undef), |
| ... | @@ -1003,7 +1004,7 @@ pub const Inst = struct { | ... | @@ -1003,7 +1004,7 @@ pub const Inst = struct { |
| 1003 | }, | 1004 | }, |
| 1004 | ty_fn: struct { | 1005 | ty_fn: struct { |
| 1005 | ty: Ref, | 1006 | ty: Ref, |
| 1006 | func: Module.Fn.Index, | 1007 | func: InternPool.Index, |
| 1007 | }, | 1008 | }, |
| 1008 | br: struct { | 1009 | br: struct { |
| 1009 | block_inst: Index, | 1010 | block_inst: Index, |
| ... | @@ -1436,7 +1437,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) | ... | @@ -1436,7 +1437,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1436 | 1437 | ||
| 1437 | .call, .call_always_tail, .call_never_tail, .call_never_inline => { | 1438 | .call, .call_always_tail, .call_never_tail, .call_never_inline => { |
| 1438 | const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip); | 1439 | const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip); |
| 1439 | return ip.funcReturnType(callee_ty.toIntern()).toType(); | 1440 | return ip.funcTypeReturnType(callee_ty.toIntern()).toType(); |
| 1440 | }, | 1441 | }, |
| 1441 | 1442 | ||
| 1442 | .slice_elem_val, .ptr_elem_val, .array_elem_val => { | 1443 | .slice_elem_val, .ptr_elem_val, .array_elem_val => { |
src/AstGen.zig+4-1| ... | @@ -12095,7 +12095,10 @@ const GenZir = struct { | ... | @@ -12095,7 +12095,10 @@ const GenZir = struct { |
| 12095 | return gz.addAsIndex(.{ | 12095 | return gz.addAsIndex(.{ |
| 12096 | .tag = .save_err_ret_index, | 12096 | .tag = .save_err_ret_index, |
| 12097 | .data = .{ .save_err_ret_index = .{ | 12097 | .data = .{ .save_err_ret_index = .{ |
| 12098 | .operand = if (cond == .if_of_error_type) cond.if_of_error_type else .none, | 12098 | .operand = switch (cond) { |
| 12099 | .if_of_error_type => |x| x, | ||
| 12100 | else => .none, | ||
| 12101 | }, | ||
| 12099 | } }, | 12102 | } }, |
| 12100 | }); | 12103 | }); |
| 12101 | } | 12104 | } |
src/Autodoc.zig+1| ... | @@ -281,6 +281,7 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -281,6 +281,7 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 281 | // Poison and special tag | 281 | // Poison and special tag |
| 282 | .generic_poison_type, | 282 | .generic_poison_type, |
| 283 | .var_args_param_type, | 283 | .var_args_param_type, |
| 284 | .adhoc_inferred_error_set_type, | ||
| 284 | => .{ | 285 | => .{ |
| 285 | .Type = .{ .name = try tmpbuf.toOwnedSlice() }, | 286 | .Type = .{ .name = try tmpbuf.toOwnedSlice() }, |
| 286 | }, | 287 | }, |
src/Compilation.zig+5-10| ... | @@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig"); | ... | @@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig"); |
| 29 | const fatal = @import("main.zig").fatal; | 29 | const fatal = @import("main.zig").fatal; |
| 30 | const clangMain = @import("main.zig").clangMain; | 30 | const clangMain = @import("main.zig").clangMain; |
| 31 | const Module = @import("Module.zig"); | 31 | const Module = @import("Module.zig"); |
| 32 | const InternPool = @import("InternPool.zig"); | ||
| 32 | const BuildId = std.Build.CompileStep.BuildId; | 33 | const BuildId = std.Build.CompileStep.BuildId; |
| 33 | const Cache = std.Build.Cache; | 34 | const Cache = std.Build.Cache; |
| 34 | const translate_c = @import("translate_c.zig"); | 35 | const translate_c = @import("translate_c.zig"); |
| ... | @@ -227,7 +228,8 @@ const Job = union(enum) { | ... | @@ -227,7 +228,8 @@ const Job = union(enum) { |
| 227 | /// Write the constant value for a Decl to the output file. | 228 | /// Write the constant value for a Decl to the output file. |
| 228 | codegen_decl: Module.Decl.Index, | 229 | codegen_decl: Module.Decl.Index, |
| 229 | /// Write the machine code for a function to the output file. | 230 | /// Write the machine code for a function to the output file. |
| 230 | codegen_func: Module.Fn.Index, | 231 | /// This will either be a non-generic `func_decl` or a `func_instance`. |
| 232 | codegen_func: InternPool.Index, | ||
| 231 | /// Render the .h file snippet for the Decl. | 233 | /// Render the .h file snippet for the Decl. |
| 232 | emit_h_decl: Module.Decl.Index, | 234 | emit_h_decl: Module.Decl.Index, |
| 233 | /// The Decl needs to be analyzed and possibly export itself. | 235 | /// The Decl needs to be analyzed and possibly export itself. |
| ... | @@ -2053,15 +2055,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void | ... | @@ -2053,15 +2055,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void |
| 2053 | const decl = module.declPtr(decl_index); | 2055 | const decl = module.declPtr(decl_index); |
| 2054 | assert(decl.deletion_flag); | 2056 | assert(decl.deletion_flag); |
| 2055 | assert(decl.dependants.count() == 0); | 2057 | assert(decl.dependants.count() == 0); |
| 2056 | const is_anon = if (decl.zir_decl_index == 0) blk: { | 2058 | assert(decl.zir_decl_index != 0); |
| 2057 | break :blk module.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index); | ||
| 2058 | } else false; | ||
| 2059 | 2059 | ||
| 2060 | try module.clearDecl(decl_index, null); | 2060 | try module.clearDecl(decl_index, null); |
| 2061 | |||
| 2062 | if (is_anon) { | ||
| 2063 | module.destroyDecl(decl_index); | ||
| 2064 | } | ||
| 2065 | } | 2061 | } |
| 2066 | 2062 | ||
| 2067 | try module.processExports(); | 2063 | try module.processExports(); |
| ... | @@ -3216,8 +3212,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3216,8 +3212,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3216 | // Tests are always emitted in test binaries. The decl_refs are created by | 3212 | // Tests are always emitted in test binaries. The decl_refs are created by |
| 3217 | // Module.populateTestFunctions, but this will not queue body analysis, so do | 3213 | // Module.populateTestFunctions, but this will not queue body analysis, so do |
| 3218 | // that now. | 3214 | // that now. |
| 3219 | const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?; | 3215 | try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern()); |
| 3220 | try module.ensureFuncBodyAnalysisQueued(func_index); | ||
| 3221 | } | 3216 | } |
| 3222 | }, | 3217 | }, |
| 3223 | .update_embed_file => |embed_file| { | 3218 | .update_embed_file => |embed_file| { |
src/InternPool.zig+1679-574| ... | @@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{}, | ... | @@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{}, |
| 20 | /// `string_bytes` array is agnostic to either usage. | 20 | /// `string_bytes` array is agnostic to either usage. |
| 21 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, | 21 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 22 | 22 | ||
| 23 | /// Rather than allocating Decl objects with an Allocator, we instead allocate | ||
| 24 | /// them with this SegmentedList. This provides four advantages: | ||
| 25 | /// * Stable memory so that one thread can access a Decl object while another | ||
| 26 | /// thread allocates additional Decl objects from this list. | ||
| 27 | /// * It allows us to use u32 indexes to reference Decl objects rather than | ||
| 28 | /// pointers, saving memory in Type, Value, and dependency sets. | ||
| 29 | /// * Using integers to reference Decl objects rather than pointers makes | ||
| 30 | /// serialization trivial. | ||
| 31 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding | ||
| 32 | /// multi-threaded contention on an atomic counter. | ||
| 33 | allocated_decls: std.SegmentedList(Module.Decl, 0) = .{}, | ||
| 34 | /// When a Decl object is freed from `allocated_decls`, it is pushed into this stack. | ||
| 35 | decls_free_list: std.ArrayListUnmanaged(Module.Decl.Index) = .{}, | ||
| 36 | |||
| 37 | /// Same pattern as with `allocated_decls`. | ||
| 38 | allocated_namespaces: std.SegmentedList(Module.Namespace, 0) = .{}, | ||
| 39 | /// Same pattern as with `decls_free_list`. | ||
| 40 | namespaces_free_list: std.ArrayListUnmanaged(Module.Namespace.Index) = .{}, | ||
| 41 | |||
| 23 | /// Struct objects are stored in this data structure because: | 42 | /// Struct objects are stored in this data structure because: |
| 24 | /// * They contain pointers such as the field maps. | 43 | /// * They contain pointers such as the field maps. |
| 25 | /// * They need to be mutated after creation. | 44 | /// * They need to be mutated after creation. |
| ... | @@ -34,25 +53,11 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, | ... | @@ -34,25 +53,11 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, |
| 34 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. | 53 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. |
| 35 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, | 54 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, |
| 36 | 55 | ||
| 37 | /// Fn objects are stored in this data structure because: | ||
| 38 | /// * They need to be mutated after creation. | ||
| 39 | allocated_funcs: std.SegmentedList(Module.Fn, 0) = .{}, | ||
| 40 | /// When a Fn object is freed from `allocated_funcs`, it is pushed into this stack. | ||
| 41 | funcs_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. | ||
| 46 | allocated_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. | ||
| 49 | inferred_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 | 56 | /// 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 | 57 | /// 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, | 58 | /// field names and values directly, relying on one of these maps, stored separately, |
| 54 | /// to provide lookup. | 59 | /// to provide lookup. |
| 55 | maps: std.ArrayListUnmanaged(std.AutoArrayHashMapUnmanaged(void, void)) = .{}, | 60 | maps: std.ArrayListUnmanaged(FieldMap) = .{}, |
| 56 | 61 | ||
| 57 | /// Used for finding the index inside `string_bytes`. | 62 | /// Used for finding the index inside `string_bytes`. |
| 58 | string_table: std.HashMapUnmanaged( | 63 | string_table: std.HashMapUnmanaged( |
| ... | @@ -62,6 +67,10 @@ string_table: std.HashMapUnmanaged( | ... | @@ -62,6 +67,10 @@ string_table: std.HashMapUnmanaged( |
| 62 | std.hash_map.default_max_load_percentage, | 67 | std.hash_map.default_max_load_percentage, |
| 63 | ) = .{}, | 68 | ) = .{}, |
| 64 | 69 | ||
| 70 | /// TODO: after https://github.com/ziglang/zig/issues/10618 is solved, | ||
| 71 | /// change store_hash to false. | ||
| 72 | const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), true); | ||
| 73 | |||
| 65 | const builtin = @import("builtin"); | 74 | const builtin = @import("builtin"); |
| 66 | const std = @import("std"); | 75 | const std = @import("std"); |
| 67 | const Allocator = std.mem.Allocator; | 76 | const Allocator = std.mem.Allocator; |
| ... | @@ -73,6 +82,7 @@ const Hash = std.hash.Wyhash; | ... | @@ -73,6 +82,7 @@ const Hash = std.hash.Wyhash; |
| 73 | 82 | ||
| 74 | const InternPool = @This(); | 83 | const InternPool = @This(); |
| 75 | const Module = @import("Module.zig"); | 84 | const Module = @import("Module.zig"); |
| 85 | const Zir = @import("Zir.zig"); | ||
| 76 | const Sema = @import("Sema.zig"); | 86 | const Sema = @import("Sema.zig"); |
| 77 | 87 | ||
| 78 | const KeyAdapter = struct { | 88 | const KeyAdapter = struct { |
| ... | @@ -129,12 +139,24 @@ pub const NullTerminatedString = enum(u32) { | ... | @@ -129,12 +139,24 @@ pub const NullTerminatedString = enum(u32) { |
| 129 | empty = 0, | 139 | empty = 0, |
| 130 | _, | 140 | _, |
| 131 | 141 | ||
| 142 | /// An array of `NullTerminatedString` existing within the `extra` array. | ||
| 143 | /// This type exists to provide a struct with lifetime that is | ||
| 144 | /// not invalidated when items are added to the `InternPool`. | ||
| 145 | pub const Slice = struct { | ||
| 146 | start: u32, | ||
| 147 | len: u32, | ||
| 148 | |||
| 149 | pub fn get(slice: Slice, ip: *const InternPool) []NullTerminatedString { | ||
| 150 | return @ptrCast(ip.extra.items[slice.start..][0..slice.len]); | ||
| 151 | } | ||
| 152 | }; | ||
| 153 | |||
| 132 | pub fn toString(self: NullTerminatedString) String { | 154 | pub fn toString(self: NullTerminatedString) String { |
| 133 | return @as(String, @enumFromInt(@intFromEnum(self))); | 155 | return @enumFromInt(@intFromEnum(self)); |
| 134 | } | 156 | } |
| 135 | 157 | ||
| 136 | pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString { | 158 | pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString { |
| 137 | return @as(OptionalNullTerminatedString, @enumFromInt(@intFromEnum(self))); | 159 | return @enumFromInt(@intFromEnum(self)); |
| 138 | } | 160 | } |
| 139 | 161 | ||
| 140 | const Adapter = struct { | 162 | const Adapter = struct { |
| ... | @@ -224,7 +246,8 @@ pub const Key = union(enum) { | ... | @@ -224,7 +246,8 @@ pub const Key = union(enum) { |
| 224 | enum_type: EnumType, | 246 | enum_type: EnumType, |
| 225 | func_type: FuncType, | 247 | func_type: FuncType, |
| 226 | error_set_type: ErrorSetType, | 248 | error_set_type: ErrorSetType, |
| 227 | inferred_error_set_type: Module.Fn.InferredErrorSet.Index, | 249 | /// The payload is the function body, either a `func_decl` or `func_instance`. |
| 250 | inferred_error_set_type: Index, | ||
| 228 | 251 | ||
| 229 | /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented | 252 | /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented |
| 230 | /// via `simple_value` and has a named `Index` tag for it. | 253 | /// via `simple_value` and has a named `Index` tag for it. |
| ... | @@ -273,16 +296,16 @@ pub const Key = union(enum) { | ... | @@ -273,16 +296,16 @@ pub const Key = union(enum) { |
| 273 | 296 | ||
| 274 | pub const ErrorSetType = struct { | 297 | pub const ErrorSetType = struct { |
| 275 | /// Set of error names, sorted by null terminated string index. | 298 | /// Set of error names, sorted by null terminated string index. |
| 276 | names: []const NullTerminatedString, | 299 | names: NullTerminatedString.Slice, |
| 277 | /// This is ignored by `get` but will always be provided by `indexToKey`. | 300 | /// This is ignored by `get` but will always be provided by `indexToKey`. |
| 278 | names_map: OptionalMapIndex = .none, | 301 | names_map: OptionalMapIndex = .none, |
| 279 | 302 | ||
| 280 | /// Look up field index based on field name. | 303 | /// Look up field index based on field name. |
| 281 | pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | 304 | pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 { |
| 282 | const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)]; | 305 | const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)]; |
| 283 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.names }; | 306 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) }; |
| 284 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | 307 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; |
| 285 | return @as(u32, @intCast(field_index)); | 308 | return @intCast(field_index); |
| 286 | } | 309 | } |
| 287 | }; | 310 | }; |
| 288 | 311 | ||
| ... | @@ -487,7 +510,7 @@ pub const Key = union(enum) { | ... | @@ -487,7 +510,7 @@ pub const Key = union(enum) { |
| 487 | }; | 510 | }; |
| 488 | 511 | ||
| 489 | pub const FuncType = struct { | 512 | pub const FuncType = struct { |
| 490 | param_types: []Index, | 513 | param_types: Index.Slice, |
| 491 | return_type: Index, | 514 | return_type: Index, |
| 492 | /// Tells whether a parameter is comptime. See `paramIsComptime` helper | 515 | /// Tells whether a parameter is comptime. See `paramIsComptime` helper |
| 493 | /// method for accessing this. | 516 | /// method for accessing this. |
| ... | @@ -518,6 +541,32 @@ pub const Key = union(enum) { | ... | @@ -518,6 +541,32 @@ pub const Key = union(enum) { |
| 518 | assert(i < self.param_types.len); | 541 | assert(i < self.param_types.len); |
| 519 | return @as(u1, @truncate(self.noalias_bits >> i)) != 0; | 542 | return @as(u1, @truncate(self.noalias_bits >> i)) != 0; |
| 520 | } | 543 | } |
| 544 | |||
| 545 | pub fn eql(a: FuncType, b: FuncType, ip: *const InternPool) bool { | ||
| 546 | return std.mem.eql(Index, a.param_types.get(ip), b.param_types.get(ip)) and | ||
| 547 | a.return_type == b.return_type and | ||
| 548 | a.comptime_bits == b.comptime_bits and | ||
| 549 | a.noalias_bits == b.noalias_bits and | ||
| 550 | a.alignment == b.alignment and | ||
| 551 | a.cc == b.cc and | ||
| 552 | a.is_var_args == b.is_var_args and | ||
| 553 | a.is_generic == b.is_generic and | ||
| 554 | a.is_noinline == b.is_noinline; | ||
| 555 | } | ||
| 556 | |||
| 557 | pub fn hash(self: FuncType, hasher: *Hash, ip: *const InternPool) void { | ||
| 558 | for (self.param_types.get(ip)) |param_type| { | ||
| 559 | std.hash.autoHash(hasher, param_type); | ||
| 560 | } | ||
| 561 | std.hash.autoHash(hasher, self.return_type); | ||
| 562 | std.hash.autoHash(hasher, self.comptime_bits); | ||
| 563 | std.hash.autoHash(hasher, self.noalias_bits); | ||
| 564 | std.hash.autoHash(hasher, self.alignment); | ||
| 565 | std.hash.autoHash(hasher, self.cc); | ||
| 566 | std.hash.autoHash(hasher, self.is_var_args); | ||
| 567 | std.hash.autoHash(hasher, self.is_generic); | ||
| 568 | std.hash.autoHash(hasher, self.is_noinline); | ||
| 569 | } | ||
| 521 | }; | 570 | }; |
| 522 | 571 | ||
| 523 | pub const Variable = struct { | 572 | pub const Variable = struct { |
| ... | @@ -541,10 +590,73 @@ pub const Key = union(enum) { | ... | @@ -541,10 +590,73 @@ pub const Key = union(enum) { |
| 541 | lib_name: OptionalNullTerminatedString, | 590 | lib_name: OptionalNullTerminatedString, |
| 542 | }; | 591 | }; |
| 543 | 592 | ||
| 544 | /// Extern so it can be hashed by reinterpreting memory. | 593 | pub const Func = struct { |
| 545 | pub const Func = extern struct { | 594 | /// In the case of a generic function, this type will potentially have fewer parameters |
| 595 | /// than the generic owner's type, because the comptime parameters will be deleted. | ||
| 546 | ty: Index, | 596 | ty: Index, |
| 547 | index: Module.Fn.Index, | 597 | /// Index into extra array of the `FuncAnalysis` corresponding to this function. |
| 598 | /// Used for mutating that data. | ||
| 599 | analysis_extra_index: u32, | ||
| 600 | /// Index into extra array of the `zir_body_inst` corresponding to this function. | ||
| 601 | /// Used for mutating that data. | ||
| 602 | zir_body_inst_extra_index: u32, | ||
| 603 | /// Index into extra array of the resolved inferred error set for this function. | ||
| 604 | /// Used for mutating that data. | ||
| 605 | /// 0 when the function does not have an inferred error set. | ||
| 606 | resolved_error_set_extra_index: u32, | ||
| 607 | /// When a generic function is instantiated, branch_quota is inherited from the | ||
| 608 | /// active Sema context. Importantly, this value is also updated when an existing | ||
| 609 | /// generic function instantiation is found and called. | ||
| 610 | /// This field contains the index into the extra array of this value, | ||
| 611 | /// so that it can be mutated. | ||
| 612 | /// This will be 0 when the function is not a generic function instantiation. | ||
| 613 | branch_quota_extra_index: u32, | ||
| 614 | /// The Decl that corresponds to the function itself. | ||
| 615 | owner_decl: Module.Decl.Index, | ||
| 616 | /// The ZIR instruction that is a function instruction. Use this to find | ||
| 617 | /// the body. We store this rather than the body directly so that when ZIR | ||
| 618 | /// is regenerated on update(), we can map this to the new corresponding | ||
| 619 | /// ZIR instruction. | ||
| 620 | zir_body_inst: Zir.Inst.Index, | ||
| 621 | /// Relative to owner Decl. | ||
| 622 | lbrace_line: u32, | ||
| 623 | /// Relative to owner Decl. | ||
| 624 | rbrace_line: u32, | ||
| 625 | lbrace_column: u32, | ||
| 626 | rbrace_column: u32, | ||
| 627 | |||
| 628 | /// The `func_decl` which is the generic function from whence this instance was spawned. | ||
| 629 | /// If this is `none` it means the function is not a generic instantiation. | ||
| 630 | generic_owner: Index, | ||
| 631 | /// If this is a generic function instantiation, this will be non-empty. | ||
| 632 | /// Corresponds to the parameters of the `generic_owner` type, which | ||
| 633 | /// may have more parameters than `ty`. | ||
| 634 | /// Each element is the comptime-known value the generic function was instantiated with, | ||
| 635 | /// or `none` if the element is runtime-known. | ||
| 636 | /// TODO: as a follow-up optimization, don't store `none` values here since that data | ||
| 637 | /// is redundant with `comptime_bits` stored elsewhere. | ||
| 638 | comptime_args: Index.Slice, | ||
| 639 | |||
| 640 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. | ||
| 641 | pub fn analysis(func: *const Func, ip: *const InternPool) *FuncAnalysis { | ||
| 642 | return @ptrCast(&ip.extra.items[func.analysis_extra_index]); | ||
| 643 | } | ||
| 644 | |||
| 645 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. | ||
| 646 | pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *Zir.Inst.Index { | ||
| 647 | return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]); | ||
| 648 | } | ||
| 649 | |||
| 650 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. | ||
| 651 | pub fn branchQuota(func: *const Func, ip: *const InternPool) *u32 { | ||
| 652 | return &ip.extra.items[func.branch_quota_extra_index]; | ||
| 653 | } | ||
| 654 | |||
| 655 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. | ||
| 656 | pub fn resolvedErrorSet(func: *const Func, ip: *const InternPool) *Index { | ||
| 657 | assert(func.analysis(ip).inferred_error_set); | ||
| 658 | return @ptrCast(&ip.extra.items[func.resolved_error_set_extra_index]); | ||
| 659 | } | ||
| 548 | }; | 660 | }; |
| 549 | 661 | ||
| 550 | pub const Int = struct { | 662 | pub const Int = struct { |
| ... | @@ -679,13 +791,13 @@ pub const Key = union(enum) { | ... | @@ -679,13 +791,13 @@ pub const Key = union(enum) { |
| 679 | }; | 791 | }; |
| 680 | 792 | ||
| 681 | pub const MemoizedCall = struct { | 793 | pub const MemoizedCall = struct { |
| 682 | func: Module.Fn.Index, | 794 | func: Index, |
| 683 | arg_values: []const Index, | 795 | arg_values: []const Index, |
| 684 | result: Index, | 796 | result: Index, |
| 685 | }; | 797 | }; |
| 686 | 798 | ||
| 687 | pub fn hash32(key: Key, ip: *const InternPool) u32 { | 799 | pub fn hash32(key: Key, ip: *const InternPool) u32 { |
| 688 | return @as(u32, @truncate(key.hash64(ip))); | 800 | return @truncate(key.hash64(ip)); |
| 689 | } | 801 | } |
| 690 | 802 | ||
| 691 | pub fn hash64(key: Key, ip: *const InternPool) u64 { | 803 | pub fn hash64(key: Key, ip: *const InternPool) u64 { |
| ... | @@ -695,7 +807,6 @@ pub const Key = union(enum) { | ... | @@ -695,7 +807,6 @@ pub const Key = union(enum) { |
| 695 | return switch (key) { | 807 | return switch (key) { |
| 696 | // TODO: assert no padding in these types | 808 | // TODO: assert no padding in these types |
| 697 | inline .ptr_type, | 809 | inline .ptr_type, |
| 698 | .func, | ||
| 699 | .array_type, | 810 | .array_type, |
| 700 | .vector_type, | 811 | .vector_type, |
| 701 | .opt_type, | 812 | .opt_type, |
| ... | @@ -723,20 +834,11 @@ pub const Key = union(enum) { | ... | @@ -723,20 +834,11 @@ pub const Key = union(enum) { |
| 723 | }, | 834 | }, |
| 724 | 835 | ||
| 725 | .runtime_value => |x| Hash.hash(seed, asBytes(&x.val)), | 836 | .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 | 837 | ||
| 734 | .variable => |variable| { | 838 | inline .opaque_type, |
| 735 | var hasher = Hash.init(seed); | 839 | .enum_type, |
| 736 | std.hash.autoHash(&hasher, variable.decl); | 840 | .variable, |
| 737 | return hasher.final(); | 841 | => |x| Hash.hash(seed, asBytes(&x.decl)), |
| 738 | }, | ||
| 739 | .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)), | ||
| 740 | 842 | ||
| 741 | .int => |int| { | 843 | .int => |int| { |
| 742 | var hasher = Hash.init(seed); | 844 | var hasher = Hash.init(seed); |
| ... | @@ -859,11 +961,7 @@ pub const Key = union(enum) { | ... | @@ -859,11 +961,7 @@ pub const Key = union(enum) { |
| 859 | return hasher.final(); | 961 | return hasher.final(); |
| 860 | }, | 962 | }, |
| 861 | 963 | ||
| 862 | .error_set_type => |error_set_type| { | 964 | .error_set_type => |x| Hash.hash(seed, std.mem.sliceAsBytes(x.names.get(ip))), |
| 863 | var hasher = Hash.init(seed); | ||
| 864 | for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem); | ||
| 865 | return hasher.final(); | ||
| 866 | }, | ||
| 867 | 965 | ||
| 868 | .anon_struct_type => |anon_struct_type| { | 966 | .anon_struct_type => |anon_struct_type| { |
| 869 | var hasher = Hash.init(seed); | 967 | var hasher = Hash.init(seed); |
| ... | @@ -875,15 +973,7 @@ pub const Key = union(enum) { | ... | @@ -875,15 +973,7 @@ pub const Key = union(enum) { |
| 875 | 973 | ||
| 876 | .func_type => |func_type| { | 974 | .func_type => |func_type| { |
| 877 | var hasher = Hash.init(seed); | 975 | var hasher = Hash.init(seed); |
| 878 | for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type); | 976 | func_type.hash(&hasher, ip); |
| 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(); | 977 | return hasher.final(); |
| 888 | }, | 978 | }, |
| 889 | 979 | ||
| ... | @@ -893,6 +983,30 @@ pub const Key = union(enum) { | ... | @@ -893,6 +983,30 @@ pub const Key = union(enum) { |
| 893 | for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg); | 983 | for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg); |
| 894 | return hasher.final(); | 984 | return hasher.final(); |
| 895 | }, | 985 | }, |
| 986 | |||
| 987 | .func => |func| { | ||
| 988 | // In the case of a function with an inferred error set, we | ||
| 989 | // must not include the inferred error set type in the hash, | ||
| 990 | // otherwise we would get false negatives for interning generic | ||
| 991 | // function instances which have inferred error sets. | ||
| 992 | |||
| 993 | if (func.generic_owner == .none and func.resolved_error_set_extra_index == 0) | ||
| 994 | return Hash.hash(seed, asBytes(&func.owner_decl) ++ asBytes(&func.ty)); | ||
| 995 | |||
| 996 | var hasher = Hash.init(seed); | ||
| 997 | std.hash.autoHash(&hasher, func.generic_owner); | ||
| 998 | for (func.comptime_args.get(ip)) |arg| std.hash.autoHash(&hasher, arg); | ||
| 999 | if (func.resolved_error_set_extra_index == 0) { | ||
| 1000 | std.hash.autoHash(&hasher, func.ty); | ||
| 1001 | } else { | ||
| 1002 | var ty_info = ip.indexToFuncType(func.ty).?; | ||
| 1003 | ty_info.return_type = ip.errorUnionPayload(ty_info.return_type); | ||
| 1004 | ty_info.hash(&hasher, ip); | ||
| 1005 | } | ||
| 1006 | return hasher.final(); | ||
| 1007 | }, | ||
| 1008 | |||
| 1009 | .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)), | ||
| 896 | }; | 1010 | }; |
| 897 | } | 1011 | } |
| 898 | 1012 | ||
| ... | @@ -993,7 +1107,41 @@ pub const Key = union(enum) { | ... | @@ -993,7 +1107,41 @@ pub const Key = union(enum) { |
| 993 | }, | 1107 | }, |
| 994 | .func => |a_info| { | 1108 | .func => |a_info| { |
| 995 | const b_info = b.func; | 1109 | const b_info = b.func; |
| 996 | return a_info.ty == b_info.ty and a_info.index == b_info.index; | 1110 | |
| 1111 | if (a_info.generic_owner != b_info.generic_owner) | ||
| 1112 | return false; | ||
| 1113 | |||
| 1114 | if (a_info.generic_owner == .none) { | ||
| 1115 | if (a_info.owner_decl != b_info.owner_decl) | ||
| 1116 | return false; | ||
| 1117 | } else { | ||
| 1118 | if (!std.mem.eql( | ||
| 1119 | Index, | ||
| 1120 | a_info.comptime_args.get(ip), | ||
| 1121 | b_info.comptime_args.get(ip), | ||
| 1122 | )) return false; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | if (a_info.ty == b_info.ty) | ||
| 1126 | return true; | ||
| 1127 | |||
| 1128 | // There is one case where the types may be inequal but we | ||
| 1129 | // still want to find the same function body instance. In the | ||
| 1130 | // case of the functions having an inferred error set, the key | ||
| 1131 | // used to find an existing function body will necessarily have | ||
| 1132 | // a unique inferred error set type, because it refers to the | ||
| 1133 | // function body InternPool Index. To make this case work we | ||
| 1134 | // omit the inferred error set from the equality check. | ||
| 1135 | if (a_info.resolved_error_set_extra_index == 0 or | ||
| 1136 | b_info.resolved_error_set_extra_index == 0) | ||
| 1137 | { | ||
| 1138 | return false; | ||
| 1139 | } | ||
| 1140 | var a_ty_info = ip.indexToFuncType(a_info.ty).?; | ||
| 1141 | a_ty_info.return_type = ip.errorUnionPayload(a_ty_info.return_type); | ||
| 1142 | var b_ty_info = ip.indexToFuncType(b_info.ty).?; | ||
| 1143 | b_ty_info.return_type = ip.errorUnionPayload(b_ty_info.return_type); | ||
| 1144 | return a_ty_info.eql(b_ty_info, ip); | ||
| 997 | }, | 1145 | }, |
| 998 | 1146 | ||
| 999 | .ptr => |a_info| { | 1147 | .ptr => |a_info| { |
| ... | @@ -1145,7 +1293,7 @@ pub const Key = union(enum) { | ... | @@ -1145,7 +1293,7 @@ pub const Key = union(enum) { |
| 1145 | }, | 1293 | }, |
| 1146 | .error_set_type => |a_info| { | 1294 | .error_set_type => |a_info| { |
| 1147 | const b_info = b.error_set_type; | 1295 | const b_info = b.error_set_type; |
| 1148 | return std.mem.eql(NullTerminatedString, a_info.names, b_info.names); | 1296 | return std.mem.eql(NullTerminatedString, a_info.names.get(ip), b_info.names.get(ip)); |
| 1149 | }, | 1297 | }, |
| 1150 | .inferred_error_set_type => |a_info| { | 1298 | .inferred_error_set_type => |a_info| { |
| 1151 | const b_info = b.inferred_error_set_type; | 1299 | const b_info = b.inferred_error_set_type; |
| ... | @@ -1154,16 +1302,7 @@ pub const Key = union(enum) { | ... | @@ -1154,16 +1302,7 @@ pub const Key = union(enum) { |
| 1154 | 1302 | ||
| 1155 | .func_type => |a_info| { | 1303 | .func_type => |a_info| { |
| 1156 | const b_info = b.func_type; | 1304 | const b_info = b.func_type; |
| 1157 | 1305 | return Key.FuncType.eql(a_info, b_info, ip); | |
| 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 | }, | 1306 | }, |
| 1168 | 1307 | ||
| 1169 | .memoized_call => |a_info| { | 1308 | .memoized_call => |a_info| { |
| ... | @@ -1311,6 +1450,8 @@ pub const Index = enum(u32) { | ... | @@ -1311,6 +1450,8 @@ pub const Index = enum(u32) { |
| 1311 | slice_const_u8_sentinel_0_type, | 1450 | slice_const_u8_sentinel_0_type, |
| 1312 | optional_noreturn_type, | 1451 | optional_noreturn_type, |
| 1313 | anyerror_void_error_union_type, | 1452 | anyerror_void_error_union_type, |
| 1453 | /// Used for the inferred error set of inline/comptime function calls. | ||
| 1454 | adhoc_inferred_error_set_type, | ||
| 1314 | generic_poison_type, | 1455 | generic_poison_type, |
| 1315 | /// `@TypeOf(.{})` | 1456 | /// `@TypeOf(.{})` |
| 1316 | empty_struct_type, | 1457 | empty_struct_type, |
| ... | @@ -1360,6 +1501,18 @@ pub const Index = enum(u32) { | ... | @@ -1360,6 +1501,18 @@ pub const Index = enum(u32) { |
| 1360 | 1501 | ||
| 1361 | _, | 1502 | _, |
| 1362 | 1503 | ||
| 1504 | /// An array of `Index` existing within the `extra` array. | ||
| 1505 | /// This type exists to provide a struct with lifetime that is | ||
| 1506 | /// not invalidated when items are added to the `InternPool`. | ||
| 1507 | pub const Slice = struct { | ||
| 1508 | start: u32, | ||
| 1509 | len: u32, | ||
| 1510 | |||
| 1511 | pub fn get(slice: Slice, ip: *const InternPool) []Index { | ||
| 1512 | return @ptrCast(ip.extra.items[slice.start..][0..slice.len]); | ||
| 1513 | } | ||
| 1514 | }; | ||
| 1515 | |||
| 1363 | pub fn toType(i: Index) @import("type.zig").Type { | 1516 | pub fn toType(i: Index) @import("type.zig").Type { |
| 1364 | assert(i != .none); | 1517 | assert(i != .none); |
| 1365 | return .{ .ip_index = i }; | 1518 | return .{ .ip_index = i }; |
| ... | @@ -1390,6 +1543,7 @@ pub const Index = enum(u32) { | ... | @@ -1390,6 +1543,7 @@ pub const Index = enum(u32) { |
| 1390 | 1543 | ||
| 1391 | /// This function is used in the debugger pretty formatters in tools/ to fetch the | 1544 | /// This function is used in the debugger pretty formatters in tools/ to fetch the |
| 1392 | /// Tag to encoding mapping to facilitate fancy debug printing for this type. | 1545 | /// Tag to encoding mapping to facilitate fancy debug printing for this type. |
| 1546 | /// TODO merge this with `Tag.Payload`. | ||
| 1393 | fn dbHelper(self: *Index, tag_to_encoding_map: *struct { | 1547 | fn dbHelper(self: *Index, tag_to_encoding_map: *struct { |
| 1394 | const DataIsIndex = struct { data: Index }; | 1548 | const DataIsIndex = struct { data: Index }; |
| 1395 | const DataIsExtraIndexOfEnumExplicit = struct { | 1549 | const DataIsExtraIndexOfEnumExplicit = struct { |
| ... | @@ -1425,13 +1579,14 @@ pub const Index = enum(u32) { | ... | @@ -1425,13 +1579,14 @@ pub const Index = enum(u32) { |
| 1425 | type_optional: DataIsIndex, | 1579 | type_optional: DataIsIndex, |
| 1426 | type_anyframe: DataIsIndex, | 1580 | type_anyframe: DataIsIndex, |
| 1427 | type_error_union: struct { data: *Key.ErrorUnionType }, | 1581 | type_error_union: struct { data: *Key.ErrorUnionType }, |
| 1582 | type_anyerror_union: DataIsIndex, | ||
| 1428 | type_error_set: struct { | 1583 | type_error_set: struct { |
| 1429 | const @"data.names_len" = opaque {}; | 1584 | const @"data.names_len" = opaque {}; |
| 1430 | data: *ErrorSet, | 1585 | data: *Tag.ErrorSet, |
| 1431 | @"trailing.names.len": *@"data.names_len", | 1586 | @"trailing.names.len": *@"data.names_len", |
| 1432 | trailing: struct { names: []NullTerminatedString }, | 1587 | trailing: struct { names: []NullTerminatedString }, |
| 1433 | }, | 1588 | }, |
| 1434 | type_inferred_error_set: struct { data: Module.Fn.InferredErrorSet.Index }, | 1589 | type_inferred_error_set: DataIsIndex, |
| 1435 | type_enum_auto: struct { | 1590 | type_enum_auto: struct { |
| 1436 | const @"data.fields_len" = opaque {}; | 1591 | const @"data.fields_len" = opaque {}; |
| 1437 | data: *EnumAuto, | 1592 | data: *EnumAuto, |
| ... | @@ -1450,10 +1605,14 @@ pub const Index = enum(u32) { | ... | @@ -1450,10 +1605,14 @@ pub const Index = enum(u32) { |
| 1450 | type_union_untagged: struct { data: Module.Union.Index }, | 1605 | type_union_untagged: struct { data: Module.Union.Index }, |
| 1451 | type_union_safety: struct { data: Module.Union.Index }, | 1606 | type_union_safety: struct { data: Module.Union.Index }, |
| 1452 | type_function: struct { | 1607 | type_function: struct { |
| 1608 | const @"data.flags.has_comptime_bits" = opaque {}; | ||
| 1609 | const @"data.flags.has_noalias_bits" = opaque {}; | ||
| 1453 | const @"data.params_len" = opaque {}; | 1610 | const @"data.params_len" = opaque {}; |
| 1454 | data: *TypeFunction, | 1611 | data: *Tag.TypeFunction, |
| 1612 | @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits", | ||
| 1613 | @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits", | ||
| 1455 | @"trailing.param_types.len": *@"data.params_len", | 1614 | @"trailing.param_types.len": *@"data.params_len", |
| 1456 | trailing: struct { param_types: []Index }, | 1615 | trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index }, |
| 1457 | }, | 1616 | }, |
| 1458 | 1617 | ||
| 1459 | undef: DataIsIndex, | 1618 | undef: DataIsIndex, |
| ... | @@ -1497,7 +1656,23 @@ pub const Index = enum(u32) { | ... | @@ -1497,7 +1656,23 @@ pub const Index = enum(u32) { |
| 1497 | float_comptime_float: struct { data: *Float128 }, | 1656 | float_comptime_float: struct { data: *Float128 }, |
| 1498 | variable: struct { data: *Tag.Variable }, | 1657 | variable: struct { data: *Tag.Variable }, |
| 1499 | extern_func: struct { data: *Key.ExternFunc }, | 1658 | extern_func: struct { data: *Key.ExternFunc }, |
| 1500 | func: struct { data: *Tag.Func }, | 1659 | func_decl: struct { |
| 1660 | const @"data.analysis.inferred_error_set" = opaque {}; | ||
| 1661 | data: *Tag.FuncDecl, | ||
| 1662 | @"trailing.resolved_error_set.len": *@"data.analysis.inferred_error_set", | ||
| 1663 | trailing: struct { resolved_error_set: []Index }, | ||
| 1664 | }, | ||
| 1665 | func_instance: struct { | ||
| 1666 | const @"data.analysis.inferred_error_set" = opaque {}; | ||
| 1667 | const @"data.generic_owner.data.ty.data.params_len" = opaque {}; | ||
| 1668 | data: *Tag.FuncInstance, | ||
| 1669 | @"trailing.resolved_error_set.len": *@"data.analysis.inferred_error_set", | ||
| 1670 | @"trailing.comptime_args.len": *@"data.generic_owner.data.ty.data.params_len", | ||
| 1671 | trailing: struct { resolved_error_set: []Index, comptime_args: []Index }, | ||
| 1672 | }, | ||
| 1673 | func_coerced: struct { | ||
| 1674 | data: *Tag.FuncCoerced, | ||
| 1675 | }, | ||
| 1501 | only_possible_value: DataIsIndex, | 1676 | only_possible_value: DataIsIndex, |
| 1502 | union_value: struct { data: *Key.Union }, | 1677 | union_value: struct { data: *Key.Union }, |
| 1503 | bytes: struct { data: *Bytes }, | 1678 | bytes: struct { data: *Bytes }, |
| ... | @@ -1716,6 +1891,8 @@ pub const static_keys = [_]Key{ | ... | @@ -1716,6 +1891,8 @@ pub const static_keys = [_]Key{ |
| 1716 | .payload_type = .void_type, | 1891 | .payload_type = .void_type, |
| 1717 | } }, | 1892 | } }, |
| 1718 | 1893 | ||
| 1894 | // adhoc_inferred_error_set_type | ||
| 1895 | .{ .simple_type = .adhoc_inferred_error_set }, | ||
| 1719 | // generic_poison_type | 1896 | // generic_poison_type |
| 1720 | .{ .simple_type = .generic_poison }, | 1897 | .{ .simple_type = .generic_poison }, |
| 1721 | 1898 | ||
| ... | @@ -1822,11 +1999,14 @@ pub const Tag = enum(u8) { | ... | @@ -1822,11 +1999,14 @@ pub const Tag = enum(u8) { |
| 1822 | /// An error union type. | 1999 | /// An error union type. |
| 1823 | /// data is payload to `Key.ErrorUnionType`. | 2000 | /// data is payload to `Key.ErrorUnionType`. |
| 1824 | type_error_union, | 2001 | type_error_union, |
| 2002 | /// An error union type of the form `anyerror!T`. | ||
| 2003 | /// data is `Index` of payload type. | ||
| 2004 | type_anyerror_union, | ||
| 1825 | /// An error set type. | 2005 | /// An error set type. |
| 1826 | /// data is payload to `ErrorSet`. | 2006 | /// data is payload to `ErrorSet`. |
| 1827 | type_error_set, | 2007 | type_error_set, |
| 1828 | /// The inferred error set type of a function. | 2008 | /// The inferred error set type of a function. |
| 1829 | /// data is `Module.Fn.InferredErrorSet.Index`. | 2009 | /// data is `Index` of a `func_decl` or `func_instance`. |
| 1830 | type_inferred_error_set, | 2010 | type_inferred_error_set, |
| 1831 | /// An enum type with auto-numbered tag values. | 2011 | /// An enum type with auto-numbered tag values. |
| 1832 | /// The enum is exhaustive. | 2012 | /// The enum is exhaustive. |
| ... | @@ -2005,11 +2185,19 @@ pub const Tag = enum(u8) { | ... | @@ -2005,11 +2185,19 @@ pub const Tag = enum(u8) { |
| 2005 | /// data is extra index to Variable. | 2185 | /// data is extra index to Variable. |
| 2006 | variable, | 2186 | variable, |
| 2007 | /// An extern function. | 2187 | /// An extern function. |
| 2008 | /// data is extra index to Key.ExternFunc. | 2188 | /// data is extra index to ExternFunc. |
| 2009 | extern_func, | 2189 | extern_func, |
| 2010 | /// A regular function. | 2190 | /// A non-extern function corresponding directly to the AST node from whence it originated. |
| 2011 | /// data is extra index to Func. | 2191 | /// data is extra index to `FuncDecl`. |
| 2012 | func, | 2192 | /// Only the owner Decl is used for hashing and equality because the other |
| 2193 | /// fields can get patched up during incremental compilation. | ||
| 2194 | func_decl, | ||
| 2195 | /// A generic function instantiation. | ||
| 2196 | /// data is extra index to `FuncInstance`. | ||
| 2197 | func_instance, | ||
| 2198 | /// A `func_decl` or a `func_instance` that has been coerced to a different type. | ||
| 2199 | /// data is extra index to `FuncCoerced`. | ||
| 2200 | func_coerced, | ||
| 2013 | /// This represents the only possible value for *some* types which have | 2201 | /// This represents the only possible value for *some* types which have |
| 2014 | /// only one possible value. Not all only-possible-values are encoded this way; | 2202 | /// only one possible value. Not all only-possible-values are encoded this way; |
| 2015 | /// for example structs which have all comptime fields are not encoded this way. | 2203 | /// for example structs which have all comptime fields are not encoded this way. |
| ... | @@ -2041,7 +2229,6 @@ pub const Tag = enum(u8) { | ... | @@ -2041,7 +2229,6 @@ pub const Tag = enum(u8) { |
| 2041 | const Error = Key.Error; | 2229 | const Error = Key.Error; |
| 2042 | const EnumTag = Key.EnumTag; | 2230 | const EnumTag = Key.EnumTag; |
| 2043 | const ExternFunc = Key.ExternFunc; | 2231 | const ExternFunc = Key.ExternFunc; |
| 2044 | const Func = Key.Func; | ||
| 2045 | const Union = Key.Union; | 2232 | const Union = Key.Union; |
| 2046 | const TypePointer = Key.PtrType; | 2233 | const TypePointer = Key.PtrType; |
| 2047 | 2234 | ||
| ... | @@ -2057,6 +2244,7 @@ pub const Tag = enum(u8) { | ... | @@ -2057,6 +2244,7 @@ pub const Tag = enum(u8) { |
| 2057 | .type_optional => unreachable, | 2244 | .type_optional => unreachable, |
| 2058 | .type_anyframe => unreachable, | 2245 | .type_anyframe => unreachable, |
| 2059 | .type_error_union => ErrorUnionType, | 2246 | .type_error_union => ErrorUnionType, |
| 2247 | .type_anyerror_union => unreachable, | ||
| 2060 | .type_error_set => ErrorSet, | 2248 | .type_error_set => ErrorSet, |
| 2061 | .type_inferred_error_set => unreachable, | 2249 | .type_inferred_error_set => unreachable, |
| 2062 | .type_enum_auto => EnumAuto, | 2250 | .type_enum_auto => EnumAuto, |
| ... | @@ -2114,7 +2302,9 @@ pub const Tag = enum(u8) { | ... | @@ -2114,7 +2302,9 @@ pub const Tag = enum(u8) { |
| 2114 | .float_comptime_float => unreachable, | 2302 | .float_comptime_float => unreachable, |
| 2115 | .variable => Variable, | 2303 | .variable => Variable, |
| 2116 | .extern_func => ExternFunc, | 2304 | .extern_func => ExternFunc, |
| 2117 | .func => Func, | 2305 | .func_decl => FuncDecl, |
| 2306 | .func_instance => FuncInstance, | ||
| 2307 | .func_coerced => FuncCoerced, | ||
| 2118 | .only_possible_value => unreachable, | 2308 | .only_possible_value => unreachable, |
| 2119 | .union_value => Union, | 2309 | .union_value => Union, |
| 2120 | .bytes => Bytes, | 2310 | .bytes => Bytes, |
| ... | @@ -2150,36 +2340,107 @@ pub const Tag = enum(u8) { | ... | @@ -2150,36 +2340,107 @@ pub const Tag = enum(u8) { |
| 2150 | /// The type of the aggregate. | 2340 | /// The type of the aggregate. |
| 2151 | ty: Index, | 2341 | ty: Index, |
| 2152 | }; | 2342 | }; |
| 2153 | }; | ||
| 2154 | 2343 | ||
| 2155 | /// Trailing: | 2344 | /// Trailing: |
| 2156 | /// 0. name: NullTerminatedString for each names_len | 2345 | /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which |
| 2157 | pub const ErrorSet = struct { | 2346 | /// is a regular error set corresponding to the finished inferred error set. |
| 2158 | names_len: u32, | 2347 | /// A `none` value marks that the inferred error set is not resolved yet. |
| 2159 | /// Maps error names to declaration index. | 2348 | pub const FuncDecl = struct { |
| 2160 | names_map: MapIndex, | 2349 | analysis: FuncAnalysis, |
| 2161 | }; | 2350 | owner_decl: Module.Decl.Index, |
| 2351 | ty: Index, | ||
| 2352 | zir_body_inst: Zir.Inst.Index, | ||
| 2353 | lbrace_line: u32, | ||
| 2354 | rbrace_line: u32, | ||
| 2355 | lbrace_column: u32, | ||
| 2356 | rbrace_column: u32, | ||
| 2357 | }; | ||
| 2162 | 2358 | ||
| 2163 | /// Trailing: | 2359 | /// Trailing: |
| 2164 | /// 0. param_type: Index for each params_len | 2360 | /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which |
| 2165 | pub const TypeFunction = struct { | 2361 | /// is a regular error set corresponding to the finished inferred error set. |
| 2166 | params_len: u32, | 2362 | /// A `none` value marks that the inferred error set is not resolved yet. |
| 2167 | return_type: Index, | 2363 | /// 1. For each parameter of generic_owner: `Index` if comptime, otherwise `none` |
| 2168 | comptime_bits: u32, | 2364 | pub const FuncInstance = struct { |
| 2169 | noalias_bits: u32, | 2365 | analysis: FuncAnalysis, |
| 2170 | flags: Flags, | 2366 | // Needed by the linker for codegen. Not part of hashing or equality. |
| 2367 | owner_decl: Module.Decl.Index, | ||
| 2368 | ty: Index, | ||
| 2369 | branch_quota: u32, | ||
| 2370 | /// Points to a `FuncDecl`. | ||
| 2371 | generic_owner: Index, | ||
| 2372 | }; | ||
| 2171 | 2373 | ||
| 2172 | pub const Flags = packed struct(u32) { | 2374 | pub const FuncCoerced = struct { |
| 2173 | alignment: Alignment, | 2375 | ty: Index, |
| 2174 | cc: std.builtin.CallingConvention, | 2376 | func: Index, |
| 2175 | is_var_args: bool, | 2377 | }; |
| 2176 | is_generic: bool, | 2378 | |
| 2177 | is_noinline: bool, | 2379 | /// Trailing: |
| 2178 | align_is_generic: bool, | 2380 | /// 0. name: NullTerminatedString for each names_len |
| 2179 | cc_is_generic: bool, | 2381 | pub const ErrorSet = struct { |
| 2180 | section_is_generic: bool, | 2382 | names_len: u32, |
| 2181 | addrspace_is_generic: bool, | 2383 | /// Maps error names to declaration index. |
| 2182 | _: u11 = 0, | 2384 | names_map: MapIndex, |
| 2385 | }; | ||
| 2386 | |||
| 2387 | /// Trailing: | ||
| 2388 | /// 0. comptime_bits: u32, // if has_comptime_bits | ||
| 2389 | /// 1. noalias_bits: u32, // if has_noalias_bits | ||
| 2390 | /// 2. param_type: Index for each params_len | ||
| 2391 | pub const TypeFunction = struct { | ||
| 2392 | params_len: u32, | ||
| 2393 | return_type: Index, | ||
| 2394 | flags: Flags, | ||
| 2395 | |||
| 2396 | pub const Flags = packed struct(u32) { | ||
| 2397 | alignment: Alignment, | ||
| 2398 | cc: std.builtin.CallingConvention, | ||
| 2399 | is_var_args: bool, | ||
| 2400 | is_generic: bool, | ||
| 2401 | has_comptime_bits: bool, | ||
| 2402 | has_noalias_bits: bool, | ||
| 2403 | is_noinline: bool, | ||
| 2404 | align_is_generic: bool, | ||
| 2405 | cc_is_generic: bool, | ||
| 2406 | section_is_generic: bool, | ||
| 2407 | addrspace_is_generic: bool, | ||
| 2408 | _: u9 = 0, | ||
| 2409 | }; | ||
| 2410 | }; | ||
| 2411 | }; | ||
| 2412 | |||
| 2413 | /// State that is mutable during semantic analysis. This data is not used for | ||
| 2414 | /// equality or hashing, except for `inferred_error_set` which is considered | ||
| 2415 | /// to be part of the type of the function. | ||
| 2416 | pub const FuncAnalysis = packed struct(u32) { | ||
| 2417 | state: State, | ||
| 2418 | is_cold: bool, | ||
| 2419 | is_noinline: bool, | ||
| 2420 | calls_or_awaits_errorable_fn: bool, | ||
| 2421 | stack_alignment: Alignment, | ||
| 2422 | |||
| 2423 | /// True if this function has an inferred error set. | ||
| 2424 | inferred_error_set: bool, | ||
| 2425 | |||
| 2426 | _: u14 = 0, | ||
| 2427 | |||
| 2428 | pub const State = enum(u8) { | ||
| 2429 | /// This function has not yet undergone analysis, because we have not | ||
| 2430 | /// seen a potential runtime call. It may be analyzed in future. | ||
| 2431 | none, | ||
| 2432 | /// Analysis for this function has been queued, but not yet completed. | ||
| 2433 | queued, | ||
| 2434 | /// This function intentionally only has ZIR generated because it is marked | ||
| 2435 | /// inline, which means no runtime version of the function will be generated. | ||
| 2436 | inline_only, | ||
| 2437 | in_progress, | ||
| 2438 | /// There will be a corresponding ErrorMsg in Module.failed_decls | ||
| 2439 | sema_failure, | ||
| 2440 | /// This function might be OK but it depends on another Decl which did not | ||
| 2441 | /// successfully complete semantic analysis. | ||
| 2442 | dependency_failure, | ||
| 2443 | success, | ||
| 2183 | }; | 2444 | }; |
| 2184 | }; | 2445 | }; |
| 2185 | 2446 | ||
| ... | @@ -2251,6 +2512,7 @@ pub const SimpleType = enum(u32) { | ... | @@ -2251,6 +2512,7 @@ pub const SimpleType = enum(u32) { |
| 2251 | extern_options, | 2512 | extern_options, |
| 2252 | type_info, | 2513 | type_info, |
| 2253 | 2514 | ||
| 2515 | adhoc_inferred_error_set, | ||
| 2254 | generic_poison, | 2516 | generic_poison, |
| 2255 | }; | 2517 | }; |
| 2256 | 2518 | ||
| ... | @@ -2499,7 +2761,7 @@ pub const Float128 = struct { | ... | @@ -2499,7 +2761,7 @@ pub const Float128 = struct { |
| 2499 | /// Trailing: | 2761 | /// Trailing: |
| 2500 | /// 0. arg value: Index for each args_len | 2762 | /// 0. arg value: Index for each args_len |
| 2501 | pub const MemoizedCall = struct { | 2763 | pub const MemoizedCall = struct { |
| 2502 | func: Module.Fn.Index, | 2764 | func: Index, |
| 2503 | args_len: u32, | 2765 | args_len: u32, |
| 2504 | result: Index, | 2766 | result: Index, |
| 2505 | }; | 2767 | }; |
| ... | @@ -2553,11 +2815,11 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { | ... | @@ -2553,11 +2815,11 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 2553 | ip.unions_free_list.deinit(gpa); | 2815 | ip.unions_free_list.deinit(gpa); |
| 2554 | ip.allocated_unions.deinit(gpa); | 2816 | ip.allocated_unions.deinit(gpa); |
| 2555 | 2817 | ||
| 2556 | ip.funcs_free_list.deinit(gpa); | 2818 | ip.decls_free_list.deinit(gpa); |
| 2557 | ip.allocated_funcs.deinit(gpa); | 2819 | ip.allocated_decls.deinit(gpa); |
| 2558 | 2820 | ||
| 2559 | ip.inferred_error_sets_free_list.deinit(gpa); | 2821 | ip.namespaces_free_list.deinit(gpa); |
| 2560 | ip.allocated_inferred_error_sets.deinit(gpa); | 2822 | ip.allocated_namespaces.deinit(gpa); |
| 2561 | 2823 | ||
| 2562 | for (ip.maps.items) |*map| map.deinit(gpa); | 2824 | for (ip.maps.items) |*map| map.deinit(gpa); |
| 2563 | ip.maps.deinit(gpa); | 2825 | ip.maps.deinit(gpa); |
| ... | @@ -2620,26 +2882,22 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -2620,26 +2882,22 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2620 | return .{ .ptr_type = ptr_info }; | 2882 | return .{ .ptr_type = ptr_info }; |
| 2621 | }, | 2883 | }, |
| 2622 | 2884 | ||
| 2623 | .type_optional => .{ .opt_type = @as(Index, @enumFromInt(data)) }, | 2885 | .type_optional => .{ .opt_type = @enumFromInt(data) }, |
| 2624 | .type_anyframe => .{ .anyframe_type = @as(Index, @enumFromInt(data)) }, | 2886 | .type_anyframe => .{ .anyframe_type = @enumFromInt(data) }, |
| 2625 | 2887 | ||
| 2626 | .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) }, | 2888 | .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) }, |
| 2627 | .type_error_set => { | 2889 | .type_anyerror_union => .{ .error_union_type = .{ |
| 2628 | const error_set = ip.extraDataTrail(ErrorSet, data); | 2890 | .error_set_type = .anyerror_type, |
| 2629 | const names_len = error_set.data.names_len; | 2891 | .payload_type = @enumFromInt(data), |
| 2630 | const names = ip.extra.items[error_set.end..][0..names_len]; | 2892 | } }, |
| 2631 | return .{ .error_set_type = .{ | 2893 | .type_error_set => .{ .error_set_type = ip.extraErrorSet(data) }, |
| 2632 | .names = @as([]const NullTerminatedString, @ptrCast(names)), | ||
| 2633 | .names_map = error_set.data.names_map.toOptional(), | ||
| 2634 | } }; | ||
| 2635 | }, | ||
| 2636 | .type_inferred_error_set => .{ | 2894 | .type_inferred_error_set => .{ |
| 2637 | .inferred_error_set_type = @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(data)), | 2895 | .inferred_error_set_type = @enumFromInt(data), |
| 2638 | }, | 2896 | }, |
| 2639 | 2897 | ||
| 2640 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, | 2898 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, |
| 2641 | .type_struct => { | 2899 | .type_struct => { |
| 2642 | const struct_index = @as(Module.Struct.OptionalIndex, @enumFromInt(data)); | 2900 | const struct_index: Module.Struct.OptionalIndex = @enumFromInt(data); |
| 2643 | const namespace = if (struct_index.unwrap()) |i| | 2901 | const namespace = if (struct_index.unwrap()) |i| |
| 2644 | ip.structPtrConst(i).namespace.toOptional() | 2902 | ip.structPtrConst(i).namespace.toOptional() |
| 2645 | else | 2903 | else |
| ... | @@ -2661,9 +2919,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -2661,9 +2919,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2661 | const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len]; | 2919 | const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len]; |
| 2662 | const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len]; | 2920 | const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len]; |
| 2663 | return .{ .anon_struct_type = .{ | 2921 | return .{ .anon_struct_type = .{ |
| 2664 | .types = @as([]const Index, @ptrCast(types)), | 2922 | .types = @ptrCast(types), |
| 2665 | .values = @as([]const Index, @ptrCast(values)), | 2923 | .values = @ptrCast(values), |
| 2666 | .names = @as([]const NullTerminatedString, @ptrCast(names)), | 2924 | .names = @ptrCast(names), |
| 2667 | } }; | 2925 | } }; |
| 2668 | }, | 2926 | }, |
| 2669 | .type_tuple_anon => { | 2927 | .type_tuple_anon => { |
| ... | @@ -2672,8 +2930,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -2672,8 +2930,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2672 | const types = ip.extra.items[type_struct_anon.end..][0..fields_len]; | 2930 | const types = ip.extra.items[type_struct_anon.end..][0..fields_len]; |
| 2673 | const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len]; | 2931 | const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len]; |
| 2674 | return .{ .anon_struct_type = .{ | 2932 | return .{ .anon_struct_type = .{ |
| 2675 | .types = @as([]const Index, @ptrCast(types)), | 2933 | .types = @ptrCast(types), |
| 2676 | .values = @as([]const Index, @ptrCast(values)), | 2934 | .values = @ptrCast(values), |
| 2677 | .names = &.{}, | 2935 | .names = &.{}, |
| 2678 | } }; | 2936 | } }; |
| 2679 | }, | 2937 | }, |
| ... | @@ -2710,7 +2968,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -2710,7 +2968,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2710 | }, | 2968 | }, |
| 2711 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), | 2969 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), |
| 2712 | .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive), | 2970 | .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive), |
| 2713 | .type_function => .{ .func_type = ip.indexToKeyFuncType(data) }, | 2971 | .type_function => .{ .func_type = ip.extraFuncType(data) }, |
| 2714 | 2972 | ||
| 2715 | .undef => .{ .undef = @as(Index, @enumFromInt(data)) }, | 2973 | .undef => .{ .undef = @as(Index, @enumFromInt(data)) }, |
| 2716 | .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) }, | 2974 | .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) }, |
| ... | @@ -2957,7 +3215,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -2957,7 +3215,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2957 | } }; | 3215 | } }; |
| 2958 | }, | 3216 | }, |
| 2959 | .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) }, | 3217 | .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) }, |
| 2960 | .func => .{ .func = ip.extraData(Tag.Func, data) }, | 3218 | .func_instance => .{ .func = ip.extraFuncInstance(data) }, |
| 3219 | .func_decl => .{ .func = ip.extraFuncDecl(data) }, | ||
| 3220 | .func_coerced => .{ .func = ip.extraFuncCoerced(data) }, | ||
| 2961 | .only_possible_value => { | 3221 | .only_possible_value => { |
| 2962 | const ty = @as(Index, @enumFromInt(data)); | 3222 | const ty = @as(Index, @enumFromInt(data)); |
| 2963 | const ty_item = ip.items.get(@intFromEnum(ty)); | 3223 | const ty_item = ip.items.get(@intFromEnum(ty)); |
| ... | @@ -3062,27 +3322,104 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3062,27 +3322,104 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3062 | }; | 3322 | }; |
| 3063 | } | 3323 | } |
| 3064 | 3324 | ||
| 3065 | fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType { | 3325 | fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType { |
| 3066 | const type_function = ip.extraDataTrail(TypeFunction, data); | 3326 | const error_set = ip.extraDataTrail(Tag.ErrorSet, extra_index); |
| 3067 | const param_types = @as( | 3327 | return .{ |
| 3068 | []Index, | 3328 | .names = .{ |
| 3069 | @ptrCast(ip.extra.items[type_function.end..][0..type_function.data.params_len]), | 3329 | .start = @intCast(error_set.end), |
| 3070 | ); | 3330 | .len = error_set.data.names_len, |
| 3331 | }, | ||
| 3332 | .names_map = error_set.data.names_map.toOptional(), | ||
| 3333 | }; | ||
| 3334 | } | ||
| 3335 | |||
| 3336 | fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType { | ||
| 3337 | const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index); | ||
| 3338 | var index: usize = type_function.end; | ||
| 3339 | const comptime_bits: u32 = if (!type_function.data.flags.has_comptime_bits) 0 else b: { | ||
| 3340 | const x = ip.extra.items[index]; | ||
| 3341 | index += 1; | ||
| 3342 | break :b x; | ||
| 3343 | }; | ||
| 3344 | const noalias_bits: u32 = if (!type_function.data.flags.has_noalias_bits) 0 else b: { | ||
| 3345 | const x = ip.extra.items[index]; | ||
| 3346 | index += 1; | ||
| 3347 | break :b x; | ||
| 3348 | }; | ||
| 3071 | return .{ | 3349 | return .{ |
| 3072 | .param_types = param_types, | 3350 | .param_types = .{ |
| 3351 | .start = @intCast(index), | ||
| 3352 | .len = type_function.data.params_len, | ||
| 3353 | }, | ||
| 3073 | .return_type = type_function.data.return_type, | 3354 | .return_type = type_function.data.return_type, |
| 3074 | .comptime_bits = type_function.data.comptime_bits, | 3355 | .comptime_bits = comptime_bits, |
| 3075 | .noalias_bits = type_function.data.noalias_bits, | 3356 | .noalias_bits = noalias_bits, |
| 3076 | .alignment = type_function.data.flags.alignment, | 3357 | .alignment = type_function.data.flags.alignment, |
| 3077 | .cc = type_function.data.flags.cc, | 3358 | .cc = type_function.data.flags.cc, |
| 3078 | .is_var_args = type_function.data.flags.is_var_args, | 3359 | .is_var_args = type_function.data.flags.is_var_args, |
| 3079 | .is_generic = type_function.data.flags.is_generic, | ||
| 3080 | .is_noinline = type_function.data.flags.is_noinline, | 3360 | .is_noinline = type_function.data.flags.is_noinline, |
| 3081 | .align_is_generic = type_function.data.flags.align_is_generic, | 3361 | .align_is_generic = type_function.data.flags.align_is_generic, |
| 3082 | .cc_is_generic = type_function.data.flags.cc_is_generic, | 3362 | .cc_is_generic = type_function.data.flags.cc_is_generic, |
| 3083 | .section_is_generic = type_function.data.flags.section_is_generic, | 3363 | .section_is_generic = type_function.data.flags.section_is_generic, |
| 3084 | .addrspace_is_generic = type_function.data.flags.addrspace_is_generic, | 3364 | .addrspace_is_generic = type_function.data.flags.addrspace_is_generic, |
| 3365 | .is_generic = type_function.data.flags.is_generic, | ||
| 3366 | }; | ||
| 3367 | } | ||
| 3368 | |||
| 3369 | fn extraFuncDecl(ip: *const InternPool, extra_index: u32) Key.Func { | ||
| 3370 | const P = Tag.FuncDecl; | ||
| 3371 | const func_decl = ip.extraDataTrail(P, extra_index); | ||
| 3372 | return .{ | ||
| 3373 | .ty = func_decl.data.ty, | ||
| 3374 | .analysis_extra_index = extra_index + std.meta.fieldIndex(P, "analysis").?, | ||
| 3375 | .zir_body_inst_extra_index = extra_index + std.meta.fieldIndex(P, "zir_body_inst").?, | ||
| 3376 | .resolved_error_set_extra_index = if (func_decl.data.analysis.inferred_error_set) func_decl.end else 0, | ||
| 3377 | .branch_quota_extra_index = 0, | ||
| 3378 | .owner_decl = func_decl.data.owner_decl, | ||
| 3379 | .zir_body_inst = func_decl.data.zir_body_inst, | ||
| 3380 | .lbrace_line = func_decl.data.lbrace_line, | ||
| 3381 | .rbrace_line = func_decl.data.rbrace_line, | ||
| 3382 | .lbrace_column = func_decl.data.lbrace_column, | ||
| 3383 | .rbrace_column = func_decl.data.rbrace_column, | ||
| 3384 | .generic_owner = .none, | ||
| 3385 | .comptime_args = .{ .start = 0, .len = 0 }, | ||
| 3386 | }; | ||
| 3387 | } | ||
| 3388 | |||
| 3389 | fn extraFuncInstance(ip: *const InternPool, extra_index: u32) Key.Func { | ||
| 3390 | const P = Tag.FuncInstance; | ||
| 3391 | const fi = ip.extraDataTrail(P, extra_index); | ||
| 3392 | const func_decl = ip.funcDeclInfo(fi.data.generic_owner); | ||
| 3393 | return .{ | ||
| 3394 | .ty = fi.data.ty, | ||
| 3395 | .analysis_extra_index = extra_index + std.meta.fieldIndex(P, "analysis").?, | ||
| 3396 | .zir_body_inst_extra_index = func_decl.zir_body_inst_extra_index, | ||
| 3397 | .resolved_error_set_extra_index = if (fi.data.analysis.inferred_error_set) fi.end else 0, | ||
| 3398 | .branch_quota_extra_index = extra_index + std.meta.fieldIndex(P, "branch_quota").?, | ||
| 3399 | .owner_decl = fi.data.owner_decl, | ||
| 3400 | .zir_body_inst = func_decl.zir_body_inst, | ||
| 3401 | .lbrace_line = func_decl.lbrace_line, | ||
| 3402 | .rbrace_line = func_decl.rbrace_line, | ||
| 3403 | .lbrace_column = func_decl.lbrace_column, | ||
| 3404 | .rbrace_column = func_decl.rbrace_column, | ||
| 3405 | .generic_owner = fi.data.generic_owner, | ||
| 3406 | .comptime_args = .{ | ||
| 3407 | .start = fi.end + @intFromBool(fi.data.analysis.inferred_error_set), | ||
| 3408 | .len = ip.funcTypeParamsLen(func_decl.ty), | ||
| 3409 | }, | ||
| 3410 | }; | ||
| 3411 | } | ||
| 3412 | |||
| 3413 | fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func { | ||
| 3414 | const func_coerced = ip.extraData(Tag.FuncCoerced, extra_index); | ||
| 3415 | const sub_item = ip.items.get(@intFromEnum(func_coerced.func)); | ||
| 3416 | var func: Key.Func = switch (sub_item.tag) { | ||
| 3417 | .func_instance => ip.extraFuncInstance(sub_item.data), | ||
| 3418 | .func_decl => ip.extraFuncDecl(sub_item.data), | ||
| 3419 | else => unreachable, | ||
| 3085 | }; | 3420 | }; |
| 3421 | func.ty = func_coerced.ty; | ||
| 3422 | return func; | ||
| 3086 | } | 3423 | } |
| 3087 | 3424 | ||
| 3088 | fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key { | 3425 | fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key { |
| ... | @@ -3122,7 +3459,7 @@ fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key | ... | @@ -3122,7 +3459,7 @@ fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key |
| 3122 | pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | 3459 | pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3123 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 3460 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 3124 | const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); | 3461 | const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); |
| 3125 | if (gop.found_existing) return @as(Index, @enumFromInt(gop.index)); | 3462 | if (gop.found_existing) return @enumFromInt(gop.index); |
| 3126 | try ip.items.ensureUnusedCapacity(gpa, 1); | 3463 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 3127 | switch (key) { | 3464 | switch (key) { |
| 3128 | .int_type => |int_type| { | 3465 | .int_type => |int_type| { |
| ... | @@ -3213,26 +3550,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -3213,26 +3550,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3213 | }); | 3550 | }); |
| 3214 | }, | 3551 | }, |
| 3215 | .error_union_type => |error_union_type| { | 3552 | .error_union_type => |error_union_type| { |
| 3216 | ip.items.appendAssumeCapacity(.{ | 3553 | ip.items.appendAssumeCapacity(if (error_union_type.error_set_type == .anyerror_type) .{ |
| 3554 | .tag = .type_anyerror_union, | ||
| 3555 | .data = @intFromEnum(error_union_type.payload_type), | ||
| 3556 | } else .{ | ||
| 3217 | .tag = .type_error_union, | 3557 | .tag = .type_error_union, |
| 3218 | .data = try ip.addExtra(gpa, error_union_type), | 3558 | .data = try ip.addExtra(gpa, error_union_type), |
| 3219 | }); | 3559 | }); |
| 3220 | }, | 3560 | }, |
| 3221 | .error_set_type => |error_set_type| { | 3561 | .error_set_type => |error_set_type| { |
| 3222 | assert(error_set_type.names_map == .none); | 3562 | assert(error_set_type.names_map == .none); |
| 3223 | assert(std.sort.isSorted(NullTerminatedString, error_set_type.names, {}, NullTerminatedString.indexLessThan)); | 3563 | assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan)); |
| 3224 | const names_map = try ip.addMap(gpa); | 3564 | const names_map = try ip.addMap(gpa); |
| 3225 | try addStringsToMap(ip, gpa, names_map, error_set_type.names); | 3565 | try addStringsToMap(ip, gpa, names_map, error_set_type.names.get(ip)); |
| 3226 | const names_len = @as(u32, @intCast(error_set_type.names.len)); | 3566 | const names_len = error_set_type.names.len; |
| 3227 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(ErrorSet).Struct.fields.len + names_len); | 3567 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names_len); |
| 3228 | ip.items.appendAssumeCapacity(.{ | 3568 | ip.items.appendAssumeCapacity(.{ |
| 3229 | .tag = .type_error_set, | 3569 | .tag = .type_error_set, |
| 3230 | .data = ip.addExtraAssumeCapacity(ErrorSet{ | 3570 | .data = ip.addExtraAssumeCapacity(Tag.ErrorSet{ |
| 3231 | .names_len = names_len, | 3571 | .names_len = names_len, |
| 3232 | .names_map = names_map, | 3572 | .names_map = names_map, |
| 3233 | }), | 3573 | }), |
| 3234 | }); | 3574 | }); |
| 3235 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(error_set_type.names))); | 3575 | ip.extra.appendSliceAssumeCapacity(@ptrCast(error_set_type.names.get(ip))); |
| 3236 | }, | 3576 | }, |
| 3237 | .inferred_error_set_type => |ies_index| { | 3577 | .inferred_error_set_type => |ies_index| { |
| 3238 | ip.items.appendAssumeCapacity(.{ | 3578 | ip.items.appendAssumeCapacity(.{ |
| ... | @@ -3369,36 +3709,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -3369,36 +3709,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3369 | } | 3709 | } |
| 3370 | }, | 3710 | }, |
| 3371 | 3711 | ||
| 3372 | .func_type => |func_type| { | 3712 | .func_type => unreachable, // use getFuncType() instead |
| 3373 | assert(func_type.return_type != .none); | 3713 | .extern_func => unreachable, // use getExternFunc() instead |
| 3374 | for (func_type.param_types) |param_type| assert(param_type != .none); | 3714 | .func => unreachable, // use getFuncInstance() or getFuncDecl() instead |
| 3375 | |||
| 3376 | const params_len = @as(u32, @intCast(func_type.param_types.len)); | ||
| 3377 | |||
| 3378 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(TypeFunction).Struct.fields.len + | ||
| 3379 | params_len); | ||
| 3380 | ip.items.appendAssumeCapacity(.{ | ||
| 3381 | .tag = .type_function, | ||
| 3382 | .data = ip.addExtraAssumeCapacity(TypeFunction{ | ||
| 3383 | .params_len = params_len, | ||
| 3384 | .return_type = func_type.return_type, | ||
| 3385 | .comptime_bits = func_type.comptime_bits, | ||
| 3386 | .noalias_bits = func_type.noalias_bits, | ||
| 3387 | .flags = .{ | ||
| 3388 | .alignment = func_type.alignment, | ||
| 3389 | .cc = func_type.cc, | ||
| 3390 | .is_var_args = func_type.is_var_args, | ||
| 3391 | .is_generic = func_type.is_generic, | ||
| 3392 | .is_noinline = func_type.is_noinline, | ||
| 3393 | .align_is_generic = func_type.align_is_generic, | ||
| 3394 | .cc_is_generic = func_type.cc_is_generic, | ||
| 3395 | .section_is_generic = func_type.section_is_generic, | ||
| 3396 | .addrspace_is_generic = func_type.addrspace_is_generic, | ||
| 3397 | }, | ||
| 3398 | }), | ||
| 3399 | }); | ||
| 3400 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(func_type.param_types))); | ||
| 3401 | }, | ||
| 3402 | 3715 | ||
| 3403 | .variable => |variable| { | 3716 | .variable => |variable| { |
| 3404 | const has_init = variable.init != .none; | 3717 | const has_init = variable.init != .none; |
| ... | @@ -3420,16 +3733,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -3420,16 +3733,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3420 | }); | 3733 | }); |
| 3421 | }, | 3734 | }, |
| 3422 | 3735 | ||
| 3423 | .extern_func => |extern_func| ip.items.appendAssumeCapacity(.{ | ||
| 3424 | .tag = .extern_func, | ||
| 3425 | .data = try ip.addExtra(gpa, @as(Tag.ExternFunc, extern_func)), | ||
| 3426 | }), | ||
| 3427 | |||
| 3428 | .func => |func| ip.items.appendAssumeCapacity(.{ | ||
| 3429 | .tag = .func, | ||
| 3430 | .data = try ip.addExtra(gpa, @as(Tag.Func, func)), | ||
| 3431 | }), | ||
| 3432 | |||
| 3433 | .ptr => |ptr| { | 3736 | .ptr => |ptr| { |
| 3434 | const ptr_type = ip.indexToKey(ptr.ty).ptr_type; | 3737 | const ptr_type = ip.indexToKey(ptr.ty).ptr_type; |
| 3435 | switch (ptr.len) { | 3738 | switch (ptr.len) { |
| ... | @@ -4065,108 +4368,705 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -4065,108 +4368,705 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 4065 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values))); | 4368 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values))); |
| 4066 | }, | 4369 | }, |
| 4067 | } | 4370 | } |
| 4068 | return @as(Index, @enumFromInt(ip.items.len - 1)); | 4371 | return @enumFromInt(ip.items.len - 1); |
| 4069 | } | 4372 | } |
| 4070 | 4373 | ||
| 4071 | /// Provides API for completing an enum type after calling `getIncompleteEnum`. | 4374 | /// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`. |
| 4072 | pub const IncompleteEnumType = struct { | 4375 | pub const GetFuncTypeKey = struct { |
| 4073 | index: Index, | 4376 | param_types: []Index, |
| 4074 | tag_ty_index: u32, | 4377 | return_type: Index, |
| 4075 | names_map: MapIndex, | 4378 | comptime_bits: u32, |
| 4076 | names_start: u32, | 4379 | noalias_bits: u32, |
| 4077 | values_map: OptionalMapIndex, | 4380 | /// `null` means generic. |
| 4078 | values_start: u32, | 4381 | alignment: ?Alignment, |
| 4382 | /// `null` means generic. | ||
| 4383 | cc: ?std.builtin.CallingConvention, | ||
| 4384 | is_var_args: bool, | ||
| 4385 | is_generic: bool, | ||
| 4386 | is_noinline: bool, | ||
| 4387 | section_is_generic: bool, | ||
| 4388 | addrspace_is_generic: bool, | ||
| 4389 | }; | ||
| 4079 | 4390 | ||
| 4080 | pub fn setTagType(self: @This(), ip: *InternPool, tag_ty: Index) void { | 4391 | pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocator.Error!Index { |
| 4081 | assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty)); | 4392 | // Validate input parameters. |
| 4082 | ip.extra.items[self.tag_ty_index] = @intFromEnum(tag_ty); | 4393 | assert(key.return_type != .none); |
| 4083 | } | 4394 | for (key.param_types) |param_type| assert(param_type != .none); |
| 4395 | |||
| 4396 | // The strategy here is to add the function type unconditionally, then to | ||
| 4397 | // ask if it already exists, and if so, revert the lengths of the mutated | ||
| 4398 | // arrays. This is similar to what `getOrPutTrailingString` does. | ||
| 4399 | const prev_extra_len = ip.extra.items.len; | ||
| 4400 | const params_len: u32 = @intCast(key.param_types.len); | ||
| 4401 | |||
| 4402 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeFunction).Struct.fields.len + | ||
| 4403 | @intFromBool(key.comptime_bits != 0) + | ||
| 4404 | @intFromBool(key.noalias_bits != 0) + | ||
| 4405 | params_len); | ||
| 4406 | try ip.items.ensureUnusedCapacity(gpa, 1); | ||
| 4084 | 4407 | ||
| 4085 | /// Returns the already-existing field with the same name, if any. | 4408 | const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{ |
| 4086 | pub fn addFieldName( | 4409 | .params_len = params_len, |
| 4087 | self: @This(), | 4410 | .return_type = key.return_type, |
| 4088 | ip: *InternPool, | 4411 | .flags = .{ |
| 4089 | gpa: Allocator, | 4412 | .alignment = key.alignment orelse .none, |
| 4090 | name: NullTerminatedString, | 4413 | .cc = key.cc orelse .Unspecified, |
| 4091 | ) Allocator.Error!?u32 { | 4414 | .is_var_args = key.is_var_args, |
| 4092 | const map = &ip.maps.items[@intFromEnum(self.names_map)]; | 4415 | .has_comptime_bits = key.comptime_bits != 0, |
| 4093 | const field_index = map.count(); | 4416 | .has_noalias_bits = key.noalias_bits != 0, |
| 4094 | const strings = ip.extra.items[self.names_start..][0..field_index]; | 4417 | .is_generic = key.is_generic, |
| 4095 | const adapter: NullTerminatedString.Adapter = .{ | 4418 | .is_noinline = key.is_noinline, |
| 4096 | .strings = @as([]const NullTerminatedString, @ptrCast(strings)), | 4419 | .align_is_generic = key.alignment == null, |
| 4097 | }; | 4420 | .cc_is_generic = key.cc == null, |
| 4098 | const gop = try map.getOrPutAdapted(gpa, name, adapter); | 4421 | .section_is_generic = key.section_is_generic, |
| 4099 | if (gop.found_existing) return @as(u32, @intCast(gop.index)); | 4422 | .addrspace_is_generic = key.addrspace_is_generic, |
| 4100 | ip.extra.items[self.names_start + field_index] = @intFromEnum(name); | 4423 | }, |
| 4101 | return null; | 4424 | }); |
| 4102 | } | ||
| 4103 | 4425 | ||
| 4104 | /// Returns the already-existing field with the same value, if any. | 4426 | if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits); |
| 4105 | /// Make sure the type of the value has the integer tag type of the enum. | 4427 | if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits); |
| 4106 | pub fn addFieldValue( | 4428 | ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types)); |
| 4107 | self: @This(), | ||
| 4108 | ip: *InternPool, | ||
| 4109 | gpa: Allocator, | ||
| 4110 | value: Index, | ||
| 4111 | ) Allocator.Error!?u32 { | ||
| 4112 | assert(ip.typeOf(value) == @as(Index, @enumFromInt(ip.extra.items[self.tag_ty_index]))); | ||
| 4113 | const map = &ip.maps.items[@intFromEnum(self.values_map.unwrap().?)]; | ||
| 4114 | const field_index = map.count(); | ||
| 4115 | const indexes = ip.extra.items[self.values_start..][0..field_index]; | ||
| 4116 | const adapter: Index.Adapter = .{ | ||
| 4117 | .indexes = @as([]const Index, @ptrCast(indexes)), | ||
| 4118 | }; | ||
| 4119 | const gop = try map.getOrPutAdapted(gpa, value, adapter); | ||
| 4120 | if (gop.found_existing) return @as(u32, @intCast(gop.index)); | ||
| 4121 | ip.extra.items[self.values_start + field_index] = @intFromEnum(value); | ||
| 4122 | return null; | ||
| 4123 | } | ||
| 4124 | }; | ||
| 4125 | 4429 | ||
| 4126 | /// This is used to create an enum type in the `InternPool`, with the ability | 4430 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 4127 | /// to update the tag type, field names, and field values later. | 4431 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ |
| 4128 | pub fn getIncompleteEnum( | 4432 | .func_type = extraFuncType(ip, func_type_extra_index), |
| 4129 | ip: *InternPool, | 4433 | }, adapter); |
| 4130 | gpa: Allocator, | 4434 | if (gop.found_existing) { |
| 4131 | enum_type: Key.IncompleteEnumType, | 4435 | ip.extra.items.len = prev_extra_len; |
| 4132 | ) Allocator.Error!IncompleteEnumType { | 4436 | return @enumFromInt(gop.index); |
| 4133 | switch (enum_type.tag_mode) { | ||
| 4134 | .auto => return getIncompleteEnumAuto(ip, gpa, enum_type), | ||
| 4135 | .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit), | ||
| 4136 | .nonexhaustive => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_nonexhaustive), | ||
| 4137 | } | 4437 | } |
| 4138 | } | ||
| 4139 | 4438 | ||
| 4140 | fn getIncompleteEnumAuto( | 4439 | ip.items.appendAssumeCapacity(.{ |
| 4141 | ip: *InternPool, | 4440 | .tag = .type_function, |
| 4142 | gpa: Allocator, | 4441 | .data = func_type_extra_index, |
| 4143 | enum_type: Key.IncompleteEnumType, | 4442 | }); |
| 4144 | ) Allocator.Error!IncompleteEnumType { | 4443 | return @enumFromInt(ip.items.len - 1); |
| 4145 | const int_tag_type = if (enum_type.tag_ty != .none) | 4444 | } |
| 4146 | enum_type.tag_ty | ||
| 4147 | else | ||
| 4148 | try ip.get(gpa, .{ .int_type = .{ | ||
| 4149 | .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len), | ||
| 4150 | .signedness = .unsigned, | ||
| 4151 | } }); | ||
| 4152 | 4445 | ||
| 4153 | // We must keep the map in sync with `items`. The hash and equality functions | 4446 | pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Allocator.Error!Index { |
| 4154 | // for enum types only look at the decl field, which is present even in | ||
| 4155 | // an `IncompleteEnumType`. | ||
| 4156 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 4447 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 4157 | const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter); | 4448 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ .extern_func = key }, adapter); |
| 4158 | assert(!gop.found_existing); | 4449 | if (gop.found_existing) return @enumFromInt(gop.index); |
| 4450 | errdefer _ = ip.map.pop(); | ||
| 4451 | const prev_extra_len = ip.extra.items.len; | ||
| 4452 | const extra_index = try ip.addExtra(gpa, @as(Tag.ExternFunc, key)); | ||
| 4453 | errdefer ip.extra.items.len = prev_extra_len; | ||
| 4454 | try ip.items.append(gpa, .{ | ||
| 4455 | .tag = .extern_func, | ||
| 4456 | .data = extra_index, | ||
| 4457 | }); | ||
| 4458 | errdefer ip.items.len -= 1; | ||
| 4459 | return @enumFromInt(ip.items.len - 1); | ||
| 4460 | } | ||
| 4159 | 4461 | ||
| 4160 | const names_map = try ip.addMap(gpa); | 4462 | pub const GetFuncDeclKey = struct { |
| 4463 | owner_decl: Module.Decl.Index, | ||
| 4464 | ty: Index, | ||
| 4465 | zir_body_inst: Zir.Inst.Index, | ||
| 4466 | lbrace_line: u32, | ||
| 4467 | rbrace_line: u32, | ||
| 4468 | lbrace_column: u32, | ||
| 4469 | rbrace_column: u32, | ||
| 4470 | cc: ?std.builtin.CallingConvention, | ||
| 4471 | is_noinline: bool, | ||
| 4472 | }; | ||
| 4161 | 4473 | ||
| 4162 | const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len; | 4474 | pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index { |
| 4163 | try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len); | 4475 | // The strategy here is to add the function type unconditionally, then to |
| 4476 | // ask if it already exists, and if so, revert the lengths of the mutated | ||
| 4477 | // arrays. This is similar to what `getOrPutTrailingString` does. | ||
| 4478 | const prev_extra_len = ip.extra.items.len; | ||
| 4479 | |||
| 4480 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncDecl).Struct.fields.len); | ||
| 4164 | try ip.items.ensureUnusedCapacity(gpa, 1); | 4481 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 4482 | try ip.map.ensureUnusedCapacity(gpa, 1); | ||
| 4483 | |||
| 4484 | const func_decl_extra_index = ip.addExtraAssumeCapacity(Tag.FuncDecl{ | ||
| 4485 | .analysis = .{ | ||
| 4486 | .state = if (key.cc == .Inline) .inline_only else .none, | ||
| 4487 | .is_cold = false, | ||
| 4488 | .is_noinline = key.is_noinline, | ||
| 4489 | .calls_or_awaits_errorable_fn = false, | ||
| 4490 | .stack_alignment = .none, | ||
| 4491 | .inferred_error_set = false, | ||
| 4492 | }, | ||
| 4493 | .owner_decl = key.owner_decl, | ||
| 4494 | .ty = key.ty, | ||
| 4495 | .zir_body_inst = key.zir_body_inst, | ||
| 4496 | .lbrace_line = key.lbrace_line, | ||
| 4497 | .rbrace_line = key.rbrace_line, | ||
| 4498 | .lbrace_column = key.lbrace_column, | ||
| 4499 | .rbrace_column = key.rbrace_column, | ||
| 4500 | }); | ||
| 4165 | 4501 | ||
| 4166 | const extra_index = ip.addExtraAssumeCapacity(EnumAuto{ | 4502 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 4167 | .decl = enum_type.decl, | 4503 | const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{ |
| 4168 | .namespace = enum_type.namespace, | 4504 | .func = extraFuncDecl(ip, func_decl_extra_index), |
| 4169 | .int_tag_type = int_tag_type, | 4505 | }, adapter); |
| 4506 | |||
| 4507 | if (gop.found_existing) { | ||
| 4508 | ip.extra.items.len = prev_extra_len; | ||
| 4509 | return @enumFromInt(gop.index); | ||
| 4510 | } | ||
| 4511 | |||
| 4512 | ip.items.appendAssumeCapacity(.{ | ||
| 4513 | .tag = .func_decl, | ||
| 4514 | .data = func_decl_extra_index, | ||
| 4515 | }); | ||
| 4516 | return @enumFromInt(ip.items.len - 1); | ||
| 4517 | } | ||
| 4518 | |||
| 4519 | pub const GetFuncDeclIesKey = struct { | ||
| 4520 | owner_decl: Module.Decl.Index, | ||
| 4521 | param_types: []Index, | ||
| 4522 | noalias_bits: u32, | ||
| 4523 | comptime_bits: u32, | ||
| 4524 | bare_return_type: Index, | ||
| 4525 | /// null means generic. | ||
| 4526 | cc: ?std.builtin.CallingConvention, | ||
| 4527 | /// null means generic. | ||
| 4528 | alignment: ?Alignment, | ||
| 4529 | section_is_generic: bool, | ||
| 4530 | addrspace_is_generic: bool, | ||
| 4531 | is_var_args: bool, | ||
| 4532 | is_generic: bool, | ||
| 4533 | is_noinline: bool, | ||
| 4534 | zir_body_inst: Zir.Inst.Index, | ||
| 4535 | lbrace_line: u32, | ||
| 4536 | rbrace_line: u32, | ||
| 4537 | lbrace_column: u32, | ||
| 4538 | rbrace_column: u32, | ||
| 4539 | }; | ||
| 4540 | |||
| 4541 | pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) Allocator.Error!Index { | ||
| 4542 | // Validate input parameters. | ||
| 4543 | assert(key.bare_return_type != .none); | ||
| 4544 | for (key.param_types) |param_type| assert(param_type != .none); | ||
| 4545 | |||
| 4546 | // The strategy here is to add the function decl unconditionally, then to | ||
| 4547 | // ask if it already exists, and if so, revert the lengths of the mutated | ||
| 4548 | // arrays. This is similar to what `getOrPutTrailingString` does. | ||
| 4549 | const prev_extra_len = ip.extra.items.len; | ||
| 4550 | const params_len: u32 = @intCast(key.param_types.len); | ||
| 4551 | |||
| 4552 | try ip.map.ensureUnusedCapacity(gpa, 4); | ||
| 4553 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncDecl).Struct.fields.len + | ||
| 4554 | 1 + // inferred_error_set | ||
| 4555 | @typeInfo(Tag.ErrorUnionType).Struct.fields.len + | ||
| 4556 | @typeInfo(Tag.TypeFunction).Struct.fields.len + | ||
| 4557 | @intFromBool(key.comptime_bits != 0) + | ||
| 4558 | @intFromBool(key.noalias_bits != 0) + | ||
| 4559 | params_len); | ||
| 4560 | try ip.items.ensureUnusedCapacity(gpa, 4); | ||
| 4561 | |||
| 4562 | const func_decl_extra_index = ip.addExtraAssumeCapacity(Tag.FuncDecl{ | ||
| 4563 | .analysis = .{ | ||
| 4564 | .state = if (key.cc == .Inline) .inline_only else .none, | ||
| 4565 | .is_cold = false, | ||
| 4566 | .is_noinline = key.is_noinline, | ||
| 4567 | .calls_or_awaits_errorable_fn = false, | ||
| 4568 | .stack_alignment = .none, | ||
| 4569 | .inferred_error_set = true, | ||
| 4570 | }, | ||
| 4571 | .owner_decl = key.owner_decl, | ||
| 4572 | .ty = @enumFromInt(ip.items.len + 3), | ||
| 4573 | .zir_body_inst = key.zir_body_inst, | ||
| 4574 | .lbrace_line = key.lbrace_line, | ||
| 4575 | .rbrace_line = key.rbrace_line, | ||
| 4576 | .lbrace_column = key.lbrace_column, | ||
| 4577 | .rbrace_column = key.rbrace_column, | ||
| 4578 | }); | ||
| 4579 | |||
| 4580 | ip.items.appendAssumeCapacity(.{ | ||
| 4581 | .tag = .func_decl, | ||
| 4582 | .data = func_decl_extra_index, | ||
| 4583 | }); | ||
| 4584 | ip.extra.appendAssumeCapacity(@intFromEnum(Index.none)); | ||
| 4585 | |||
| 4586 | ip.items.appendAssumeCapacity(.{ | ||
| 4587 | .tag = .type_error_union, | ||
| 4588 | .data = ip.addExtraAssumeCapacity(Tag.ErrorUnionType{ | ||
| 4589 | .error_set_type = @enumFromInt(ip.items.len + 1), | ||
| 4590 | .payload_type = key.bare_return_type, | ||
| 4591 | }), | ||
| 4592 | }); | ||
| 4593 | |||
| 4594 | ip.items.appendAssumeCapacity(.{ | ||
| 4595 | .tag = .type_inferred_error_set, | ||
| 4596 | .data = @intCast(ip.items.len - 2), | ||
| 4597 | }); | ||
| 4598 | |||
| 4599 | const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{ | ||
| 4600 | .params_len = params_len, | ||
| 4601 | .return_type = @enumFromInt(ip.items.len - 2), | ||
| 4602 | .flags = .{ | ||
| 4603 | .alignment = key.alignment orelse .none, | ||
| 4604 | .cc = key.cc orelse .Unspecified, | ||
| 4605 | .is_var_args = key.is_var_args, | ||
| 4606 | .has_comptime_bits = key.comptime_bits != 0, | ||
| 4607 | .has_noalias_bits = key.noalias_bits != 0, | ||
| 4608 | .is_generic = key.is_generic, | ||
| 4609 | .is_noinline = key.is_noinline, | ||
| 4610 | .align_is_generic = key.alignment == null, | ||
| 4611 | .cc_is_generic = key.cc == null, | ||
| 4612 | .section_is_generic = key.section_is_generic, | ||
| 4613 | .addrspace_is_generic = key.addrspace_is_generic, | ||
| 4614 | }, | ||
| 4615 | }); | ||
| 4616 | if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits); | ||
| 4617 | if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits); | ||
| 4618 | ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types)); | ||
| 4619 | |||
| 4620 | ip.items.appendAssumeCapacity(.{ | ||
| 4621 | .tag = .type_function, | ||
| 4622 | .data = func_type_extra_index, | ||
| 4623 | }); | ||
| 4624 | |||
| 4625 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 4626 | const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4627 | .func = extraFuncDecl(ip, func_decl_extra_index), | ||
| 4628 | }, adapter); | ||
| 4629 | if (!gop.found_existing) { | ||
| 4630 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ .error_union_type = .{ | ||
| 4631 | .error_set_type = @enumFromInt(ip.items.len - 2), | ||
| 4632 | .payload_type = key.bare_return_type, | ||
| 4633 | } }, adapter).found_existing); | ||
| 4634 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4635 | .inferred_error_set_type = @enumFromInt(ip.items.len - 4), | ||
| 4636 | }, adapter).found_existing); | ||
| 4637 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4638 | .func_type = extraFuncType(ip, func_type_extra_index), | ||
| 4639 | }, adapter).found_existing); | ||
| 4640 | return @enumFromInt(ip.items.len - 4); | ||
| 4641 | } | ||
| 4642 | |||
| 4643 | // An existing function type was found; undo the additions to our two arrays. | ||
| 4644 | ip.items.len -= 4; | ||
| 4645 | ip.extra.items.len = prev_extra_len; | ||
| 4646 | return @enumFromInt(gop.index); | ||
| 4647 | } | ||
| 4648 | |||
| 4649 | pub fn getErrorSetType( | ||
| 4650 | ip: *InternPool, | ||
| 4651 | gpa: Allocator, | ||
| 4652 | names: []const NullTerminatedString, | ||
| 4653 | ) Allocator.Error!Index { | ||
| 4654 | assert(std.sort.isSorted(NullTerminatedString, names, {}, NullTerminatedString.indexLessThan)); | ||
| 4655 | |||
| 4656 | // The strategy here is to add the type unconditionally, then to ask if it | ||
| 4657 | // already exists, and if so, revert the lengths of the mutated arrays. | ||
| 4658 | // This is similar to what `getOrPutTrailingString` does. | ||
| 4659 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names.len); | ||
| 4660 | |||
| 4661 | const prev_extra_len = ip.extra.items.len; | ||
| 4662 | errdefer ip.extra.items.len = prev_extra_len; | ||
| 4663 | |||
| 4664 | const predicted_names_map: MapIndex = @enumFromInt(ip.maps.items.len); | ||
| 4665 | |||
| 4666 | const error_set_extra_index = ip.addExtraAssumeCapacity(Tag.ErrorSet{ | ||
| 4667 | .names_len = @intCast(names.len), | ||
| 4668 | .names_map = predicted_names_map, | ||
| 4669 | }); | ||
| 4670 | ip.extra.appendSliceAssumeCapacity(@ptrCast(names)); | ||
| 4671 | |||
| 4672 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 4673 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ | ||
| 4674 | .error_set_type = extraErrorSet(ip, error_set_extra_index), | ||
| 4675 | }, adapter); | ||
| 4676 | errdefer _ = ip.map.pop(); | ||
| 4677 | |||
| 4678 | if (gop.found_existing) { | ||
| 4679 | ip.extra.items.len = prev_extra_len; | ||
| 4680 | return @enumFromInt(gop.index); | ||
| 4681 | } | ||
| 4682 | |||
| 4683 | try ip.items.append(gpa, .{ | ||
| 4684 | .tag = .type_error_set, | ||
| 4685 | .data = error_set_extra_index, | ||
| 4686 | }); | ||
| 4687 | errdefer ip.items.len -= 1; | ||
| 4688 | |||
| 4689 | const names_map = try ip.addMap(gpa); | ||
| 4690 | errdefer _ = ip.maps.pop(); | ||
| 4691 | |||
| 4692 | try addStringsToMap(ip, gpa, names_map, names); | ||
| 4693 | |||
| 4694 | return @enumFromInt(ip.items.len - 1); | ||
| 4695 | } | ||
| 4696 | |||
| 4697 | pub const GetFuncInstanceKey = struct { | ||
| 4698 | /// Has the length of the instance function (may be lesser than | ||
| 4699 | /// comptime_args). | ||
| 4700 | param_types: []Index, | ||
| 4701 | /// Has the length of generic_owner's parameters (may be greater than | ||
| 4702 | /// param_types). | ||
| 4703 | comptime_args: []const Index, | ||
| 4704 | noalias_bits: u32, | ||
| 4705 | bare_return_type: Index, | ||
| 4706 | cc: std.builtin.CallingConvention, | ||
| 4707 | alignment: Alignment, | ||
| 4708 | section: OptionalNullTerminatedString, | ||
| 4709 | is_noinline: bool, | ||
| 4710 | generic_owner: Index, | ||
| 4711 | inferred_error_set: bool, | ||
| 4712 | generation: u32, | ||
| 4713 | }; | ||
| 4714 | |||
| 4715 | pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index { | ||
| 4716 | if (arg.inferred_error_set) | ||
| 4717 | return getFuncInstanceIes(ip, gpa, arg); | ||
| 4718 | |||
| 4719 | const func_ty = try ip.getFuncType(gpa, .{ | ||
| 4720 | .param_types = arg.param_types, | ||
| 4721 | .return_type = arg.bare_return_type, | ||
| 4722 | .comptime_bits = 0, | ||
| 4723 | .noalias_bits = arg.noalias_bits, | ||
| 4724 | .alignment = arg.alignment, | ||
| 4725 | .cc = arg.cc, | ||
| 4726 | .is_var_args = false, | ||
| 4727 | .is_generic = false, | ||
| 4728 | .is_noinline = arg.is_noinline, | ||
| 4729 | .section_is_generic = false, | ||
| 4730 | .addrspace_is_generic = false, | ||
| 4731 | }); | ||
| 4732 | |||
| 4733 | const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); | ||
| 4734 | |||
| 4735 | assert(arg.comptime_args.len == ip.funcTypeParamsLen(ip.typeOf(generic_owner))); | ||
| 4736 | |||
| 4737 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncInstance).Struct.fields.len + | ||
| 4738 | arg.comptime_args.len); | ||
| 4739 | const prev_extra_len = ip.extra.items.len; | ||
| 4740 | errdefer ip.extra.items.len = prev_extra_len; | ||
| 4741 | |||
| 4742 | const func_extra_index = ip.addExtraAssumeCapacity(Tag.FuncInstance{ | ||
| 4743 | .analysis = .{ | ||
| 4744 | .state = if (arg.cc == .Inline) .inline_only else .none, | ||
| 4745 | .is_cold = false, | ||
| 4746 | .is_noinline = arg.is_noinline, | ||
| 4747 | .calls_or_awaits_errorable_fn = false, | ||
| 4748 | .stack_alignment = .none, | ||
| 4749 | .inferred_error_set = false, | ||
| 4750 | }, | ||
| 4751 | // This is populated after we create the Decl below. It is not read | ||
| 4752 | // by equality or hashing functions. | ||
| 4753 | .owner_decl = undefined, | ||
| 4754 | .ty = func_ty, | ||
| 4755 | .branch_quota = 0, | ||
| 4756 | .generic_owner = generic_owner, | ||
| 4757 | }); | ||
| 4758 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args)); | ||
| 4759 | |||
| 4760 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ | ||
| 4761 | .func = extraFuncInstance(ip, func_extra_index), | ||
| 4762 | }, KeyAdapter{ .intern_pool = ip }); | ||
| 4763 | errdefer _ = ip.map.pop(); | ||
| 4764 | |||
| 4765 | if (gop.found_existing) { | ||
| 4766 | ip.extra.items.len = prev_extra_len; | ||
| 4767 | return @enumFromInt(gop.index); | ||
| 4768 | } | ||
| 4769 | |||
| 4770 | const func_index: Index = @enumFromInt(ip.items.len); | ||
| 4771 | |||
| 4772 | try ip.items.append(gpa, .{ | ||
| 4773 | .tag = .func_instance, | ||
| 4774 | .data = func_extra_index, | ||
| 4775 | }); | ||
| 4776 | errdefer ip.items.len -= 1; | ||
| 4777 | |||
| 4778 | return finishFuncInstance( | ||
| 4779 | ip, | ||
| 4780 | gpa, | ||
| 4781 | generic_owner, | ||
| 4782 | func_index, | ||
| 4783 | func_extra_index, | ||
| 4784 | arg.generation, | ||
| 4785 | func_ty, | ||
| 4786 | arg.section, | ||
| 4787 | ); | ||
| 4788 | } | ||
| 4789 | |||
| 4790 | /// This function exists separately than `getFuncInstance` because it needs to | ||
| 4791 | /// create 4 new items in the InternPool atomically before it can look for an | ||
| 4792 | /// existing item in the map. | ||
| 4793 | pub fn getFuncInstanceIes( | ||
| 4794 | ip: *InternPool, | ||
| 4795 | gpa: Allocator, | ||
| 4796 | arg: GetFuncInstanceKey, | ||
| 4797 | ) Allocator.Error!Index { | ||
| 4798 | // Validate input parameters. | ||
| 4799 | assert(arg.inferred_error_set); | ||
| 4800 | assert(arg.bare_return_type != .none); | ||
| 4801 | for (arg.param_types) |param_type| assert(param_type != .none); | ||
| 4802 | |||
| 4803 | // The strategy here is to add the function decl unconditionally, then to | ||
| 4804 | // ask if it already exists, and if so, revert the lengths of the mutated | ||
| 4805 | // arrays. This is similar to what `getOrPutTrailingString` does. | ||
| 4806 | const prev_extra_len = ip.extra.items.len; | ||
| 4807 | const params_len: u32 = @intCast(arg.param_types.len); | ||
| 4808 | |||
| 4809 | try ip.map.ensureUnusedCapacity(gpa, 4); | ||
| 4810 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncInstance).Struct.fields.len + | ||
| 4811 | 1 + // inferred_error_set | ||
| 4812 | arg.comptime_args.len + | ||
| 4813 | @typeInfo(Tag.ErrorUnionType).Struct.fields.len + | ||
| 4814 | @typeInfo(Tag.TypeFunction).Struct.fields.len + | ||
| 4815 | @intFromBool(arg.noalias_bits != 0) + | ||
| 4816 | params_len); | ||
| 4817 | try ip.items.ensureUnusedCapacity(gpa, 4); | ||
| 4818 | |||
| 4819 | const func_index: Index = @enumFromInt(ip.items.len); | ||
| 4820 | const error_union_type: Index = @enumFromInt(ip.items.len + 1); | ||
| 4821 | const error_set_type: Index = @enumFromInt(ip.items.len + 2); | ||
| 4822 | const func_ty: Index = @enumFromInt(ip.items.len + 3); | ||
| 4823 | |||
| 4824 | const func_extra_index = ip.addExtraAssumeCapacity(Tag.FuncInstance{ | ||
| 4825 | .analysis = .{ | ||
| 4826 | .state = if (arg.cc == .Inline) .inline_only else .none, | ||
| 4827 | .is_cold = false, | ||
| 4828 | .is_noinline = arg.is_noinline, | ||
| 4829 | .calls_or_awaits_errorable_fn = false, | ||
| 4830 | .stack_alignment = .none, | ||
| 4831 | .inferred_error_set = true, | ||
| 4832 | }, | ||
| 4833 | // This is populated after we create the Decl below. It is not read | ||
| 4834 | // by equality or hashing functions. | ||
| 4835 | .owner_decl = undefined, | ||
| 4836 | .ty = func_ty, | ||
| 4837 | .branch_quota = 0, | ||
| 4838 | .generic_owner = arg.generic_owner, | ||
| 4839 | }); | ||
| 4840 | ip.extra.appendAssumeCapacity(@intFromEnum(Index.none)); // resolved error set | ||
| 4841 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args)); | ||
| 4842 | |||
| 4843 | const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{ | ||
| 4844 | .params_len = params_len, | ||
| 4845 | .return_type = error_union_type, | ||
| 4846 | .flags = .{ | ||
| 4847 | .alignment = arg.alignment, | ||
| 4848 | .cc = arg.cc, | ||
| 4849 | .is_var_args = false, | ||
| 4850 | .has_comptime_bits = false, | ||
| 4851 | .has_noalias_bits = arg.noalias_bits != 0, | ||
| 4852 | .is_generic = false, | ||
| 4853 | .is_noinline = arg.is_noinline, | ||
| 4854 | .align_is_generic = false, | ||
| 4855 | .cc_is_generic = false, | ||
| 4856 | .section_is_generic = false, | ||
| 4857 | .addrspace_is_generic = false, | ||
| 4858 | }, | ||
| 4859 | }); | ||
| 4860 | // no comptime_bits because has_comptime_bits is false | ||
| 4861 | if (arg.noalias_bits != 0) ip.extra.appendAssumeCapacity(arg.noalias_bits); | ||
| 4862 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.param_types)); | ||
| 4863 | |||
| 4864 | // TODO: add appendSliceAssumeCapacity to MultiArrayList. | ||
| 4865 | ip.items.appendAssumeCapacity(.{ | ||
| 4866 | .tag = .func_instance, | ||
| 4867 | .data = func_extra_index, | ||
| 4868 | }); | ||
| 4869 | ip.items.appendAssumeCapacity(.{ | ||
| 4870 | .tag = .type_error_union, | ||
| 4871 | .data = ip.addExtraAssumeCapacity(Tag.ErrorUnionType{ | ||
| 4872 | .error_set_type = error_set_type, | ||
| 4873 | .payload_type = arg.bare_return_type, | ||
| 4874 | }), | ||
| 4875 | }); | ||
| 4876 | ip.items.appendAssumeCapacity(.{ | ||
| 4877 | .tag = .type_inferred_error_set, | ||
| 4878 | .data = @intFromEnum(func_index), | ||
| 4879 | }); | ||
| 4880 | ip.items.appendAssumeCapacity(.{ | ||
| 4881 | .tag = .type_function, | ||
| 4882 | .data = func_type_extra_index, | ||
| 4883 | }); | ||
| 4884 | |||
| 4885 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 4886 | const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4887 | .func = extraFuncInstance(ip, func_extra_index), | ||
| 4888 | }, adapter); | ||
| 4889 | if (gop.found_existing) { | ||
| 4890 | // Hot path: undo the additions to our two arrays. | ||
| 4891 | ip.items.len -= 4; | ||
| 4892 | ip.extra.items.len = prev_extra_len; | ||
| 4893 | return @enumFromInt(gop.index); | ||
| 4894 | } | ||
| 4895 | |||
| 4896 | // Synchronize the map with items. | ||
| 4897 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ .error_union_type = .{ | ||
| 4898 | .error_set_type = error_set_type, | ||
| 4899 | .payload_type = arg.bare_return_type, | ||
| 4900 | } }, adapter).found_existing); | ||
| 4901 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4902 | .inferred_error_set_type = func_index, | ||
| 4903 | }, adapter).found_existing); | ||
| 4904 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4905 | .func_type = extraFuncType(ip, func_type_extra_index), | ||
| 4906 | }, adapter).found_existing); | ||
| 4907 | |||
| 4908 | return finishFuncInstance( | ||
| 4909 | ip, | ||
| 4910 | gpa, | ||
| 4911 | arg.generic_owner, | ||
| 4912 | func_index, | ||
| 4913 | func_extra_index, | ||
| 4914 | arg.generation, | ||
| 4915 | func_ty, | ||
| 4916 | arg.section, | ||
| 4917 | ); | ||
| 4918 | } | ||
| 4919 | |||
| 4920 | fn finishFuncInstance( | ||
| 4921 | ip: *InternPool, | ||
| 4922 | gpa: Allocator, | ||
| 4923 | generic_owner: Index, | ||
| 4924 | func_index: Index, | ||
| 4925 | func_extra_index: u32, | ||
| 4926 | generation: u32, | ||
| 4927 | func_ty: Index, | ||
| 4928 | section: OptionalNullTerminatedString, | ||
| 4929 | ) Allocator.Error!Index { | ||
| 4930 | const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner)); | ||
| 4931 | const decl_index = try ip.createDecl(gpa, .{ | ||
| 4932 | .name = undefined, | ||
| 4933 | .src_namespace = fn_owner_decl.src_namespace, | ||
| 4934 | .src_node = fn_owner_decl.src_node, | ||
| 4935 | .src_line = fn_owner_decl.src_line, | ||
| 4936 | .has_tv = true, | ||
| 4937 | .owns_tv = true, | ||
| 4938 | .ty = func_ty.toType(), | ||
| 4939 | .val = func_index.toValue(), | ||
| 4940 | .alignment = .none, | ||
| 4941 | .@"linksection" = section, | ||
| 4942 | .@"addrspace" = fn_owner_decl.@"addrspace", | ||
| 4943 | .analysis = .complete, | ||
| 4944 | .deletion_flag = false, | ||
| 4945 | .zir_decl_index = fn_owner_decl.zir_decl_index, | ||
| 4946 | .src_scope = fn_owner_decl.src_scope, | ||
| 4947 | .generation = generation, | ||
| 4948 | .is_pub = fn_owner_decl.is_pub, | ||
| 4949 | .is_exported = fn_owner_decl.is_exported, | ||
| 4950 | .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace, | ||
| 4951 | .has_align = fn_owner_decl.has_align, | ||
| 4952 | .alive = true, | ||
| 4953 | .kind = .anon, | ||
| 4954 | }); | ||
| 4955 | errdefer ip.destroyDecl(gpa, decl_index); | ||
| 4956 | |||
| 4957 | // Populate the owner_decl field which was left undefined until now. | ||
| 4958 | ip.extra.items[ | ||
| 4959 | func_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_decl").? | ||
| 4960 | ] = @intFromEnum(decl_index); | ||
| 4961 | |||
| 4962 | // TODO: improve this name | ||
| 4963 | const decl = ip.declPtr(decl_index); | ||
| 4964 | decl.name = try ip.getOrPutStringFmt(gpa, "{}__anon_{d}", .{ | ||
| 4965 | fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), | ||
| 4966 | }); | ||
| 4967 | |||
| 4968 | return func_index; | ||
| 4969 | } | ||
| 4970 | |||
| 4971 | /// Provides API for completing an enum type after calling `getIncompleteEnum`. | ||
| 4972 | pub const IncompleteEnumType = struct { | ||
| 4973 | index: Index, | ||
| 4974 | tag_ty_index: u32, | ||
| 4975 | names_map: MapIndex, | ||
| 4976 | names_start: u32, | ||
| 4977 | values_map: OptionalMapIndex, | ||
| 4978 | values_start: u32, | ||
| 4979 | |||
| 4980 | pub fn setTagType(self: @This(), ip: *InternPool, tag_ty: Index) void { | ||
| 4981 | assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty)); | ||
| 4982 | ip.extra.items[self.tag_ty_index] = @intFromEnum(tag_ty); | ||
| 4983 | } | ||
| 4984 | |||
| 4985 | /// Returns the already-existing field with the same name, if any. | ||
| 4986 | pub fn addFieldName( | ||
| 4987 | self: @This(), | ||
| 4988 | ip: *InternPool, | ||
| 4989 | gpa: Allocator, | ||
| 4990 | name: NullTerminatedString, | ||
| 4991 | ) Allocator.Error!?u32 { | ||
| 4992 | const map = &ip.maps.items[@intFromEnum(self.names_map)]; | ||
| 4993 | const field_index = map.count(); | ||
| 4994 | const strings = ip.extra.items[self.names_start..][0..field_index]; | ||
| 4995 | const adapter: NullTerminatedString.Adapter = .{ | ||
| 4996 | .strings = @as([]const NullTerminatedString, @ptrCast(strings)), | ||
| 4997 | }; | ||
| 4998 | const gop = try map.getOrPutAdapted(gpa, name, adapter); | ||
| 4999 | if (gop.found_existing) return @as(u32, @intCast(gop.index)); | ||
| 5000 | ip.extra.items[self.names_start + field_index] = @intFromEnum(name); | ||
| 5001 | return null; | ||
| 5002 | } | ||
| 5003 | |||
| 5004 | /// Returns the already-existing field with the same value, if any. | ||
| 5005 | /// Make sure the type of the value has the integer tag type of the enum. | ||
| 5006 | pub fn addFieldValue( | ||
| 5007 | self: @This(), | ||
| 5008 | ip: *InternPool, | ||
| 5009 | gpa: Allocator, | ||
| 5010 | value: Index, | ||
| 5011 | ) Allocator.Error!?u32 { | ||
| 5012 | assert(ip.typeOf(value) == @as(Index, @enumFromInt(ip.extra.items[self.tag_ty_index]))); | ||
| 5013 | const map = &ip.maps.items[@intFromEnum(self.values_map.unwrap().?)]; | ||
| 5014 | const field_index = map.count(); | ||
| 5015 | const indexes = ip.extra.items[self.values_start..][0..field_index]; | ||
| 5016 | const adapter: Index.Adapter = .{ | ||
| 5017 | .indexes = @as([]const Index, @ptrCast(indexes)), | ||
| 5018 | }; | ||
| 5019 | const gop = try map.getOrPutAdapted(gpa, value, adapter); | ||
| 5020 | if (gop.found_existing) return @as(u32, @intCast(gop.index)); | ||
| 5021 | ip.extra.items[self.values_start + field_index] = @intFromEnum(value); | ||
| 5022 | return null; | ||
| 5023 | } | ||
| 5024 | }; | ||
| 5025 | |||
| 5026 | /// This is used to create an enum type in the `InternPool`, with the ability | ||
| 5027 | /// to update the tag type, field names, and field values later. | ||
| 5028 | pub fn getIncompleteEnum( | ||
| 5029 | ip: *InternPool, | ||
| 5030 | gpa: Allocator, | ||
| 5031 | enum_type: Key.IncompleteEnumType, | ||
| 5032 | ) Allocator.Error!IncompleteEnumType { | ||
| 5033 | switch (enum_type.tag_mode) { | ||
| 5034 | .auto => return getIncompleteEnumAuto(ip, gpa, enum_type), | ||
| 5035 | .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit), | ||
| 5036 | .nonexhaustive => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_nonexhaustive), | ||
| 5037 | } | ||
| 5038 | } | ||
| 5039 | |||
| 5040 | fn getIncompleteEnumAuto( | ||
| 5041 | ip: *InternPool, | ||
| 5042 | gpa: Allocator, | ||
| 5043 | enum_type: Key.IncompleteEnumType, | ||
| 5044 | ) Allocator.Error!IncompleteEnumType { | ||
| 5045 | const int_tag_type = if (enum_type.tag_ty != .none) | ||
| 5046 | enum_type.tag_ty | ||
| 5047 | else | ||
| 5048 | try ip.get(gpa, .{ .int_type = .{ | ||
| 5049 | .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len), | ||
| 5050 | .signedness = .unsigned, | ||
| 5051 | } }); | ||
| 5052 | |||
| 5053 | // We must keep the map in sync with `items`. The hash and equality functions | ||
| 5054 | // for enum types only look at the decl field, which is present even in | ||
| 5055 | // an `IncompleteEnumType`. | ||
| 5056 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 5057 | const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter); | ||
| 5058 | assert(!gop.found_existing); | ||
| 5059 | |||
| 5060 | const names_map = try ip.addMap(gpa); | ||
| 5061 | |||
| 5062 | const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len; | ||
| 5063 | try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len); | ||
| 5064 | try ip.items.ensureUnusedCapacity(gpa, 1); | ||
| 5065 | |||
| 5066 | const extra_index = ip.addExtraAssumeCapacity(EnumAuto{ | ||
| 5067 | .decl = enum_type.decl, | ||
| 5068 | .namespace = enum_type.namespace, | ||
| 5069 | .int_tag_type = int_tag_type, | ||
| 4170 | .names_map = names_map, | 5070 | .names_map = names_map, |
| 4171 | .fields_len = enum_type.fields_len, | 5071 | .fields_len = enum_type.fields_len, |
| 4172 | }); | 5072 | }); |
| ... | @@ -4265,15 +5165,15 @@ pub fn finishGetEnum( | ... | @@ -4265,15 +5165,15 @@ pub fn finishGetEnum( |
| 4265 | .values_map = values_map, | 5165 | .values_map = values_map, |
| 4266 | }), | 5166 | }), |
| 4267 | }); | 5167 | }); |
| 4268 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.names))); | 5168 | ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.names)); |
| 4269 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.values))); | 5169 | ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.values)); |
| 4270 | return @as(Index, @enumFromInt(ip.items.len - 1)); | 5170 | return @enumFromInt(ip.items.len - 1); |
| 4271 | } | 5171 | } |
| 4272 | 5172 | ||
| 4273 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { | 5173 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { |
| 4274 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 5174 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 4275 | const index = ip.map.getIndexAdapted(key, adapter) orelse return null; | 5175 | const index = ip.map.getIndexAdapted(key, adapter) orelse return null; |
| 4276 | return @as(Index, @enumFromInt(index)); | 5176 | return @enumFromInt(index); |
| 4277 | } | 5177 | } |
| 4278 | 5178 | ||
| 4279 | pub fn getAssumeExists(ip: *const InternPool, key: Key) Index { | 5179 | pub fn getAssumeExists(ip: *const InternPool, key: Key) Index { |
| ... | @@ -4311,7 +5211,7 @@ fn addIndexesToMap( | ... | @@ -4311,7 +5211,7 @@ fn addIndexesToMap( |
| 4311 | fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex { | 5211 | fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex { |
| 4312 | const ptr = try ip.maps.addOne(gpa); | 5212 | const ptr = try ip.maps.addOne(gpa); |
| 4313 | ptr.* = .{}; | 5213 | ptr.* = .{}; |
| 4314 | return @as(MapIndex, @enumFromInt(ip.maps.items.len - 1)); | 5214 | return @enumFromInt(ip.maps.items.len - 1); |
| 4315 | } | 5215 | } |
| 4316 | 5216 | ||
| 4317 | /// This operation only happens under compile error conditions. | 5217 | /// This operation only happens under compile error conditions. |
| ... | @@ -4342,24 +5242,28 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { | ... | @@ -4342,24 +5242,28 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 4342 | const result = @as(u32, @intCast(ip.extra.items.len)); | 5242 | const result = @as(u32, @intCast(ip.extra.items.len)); |
| 4343 | inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { | 5243 | inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { |
| 4344 | ip.extra.appendAssumeCapacity(switch (field.type) { | 5244 | ip.extra.appendAssumeCapacity(switch (field.type) { |
| 4345 | u32 => @field(extra, field.name), | 5245 | Index, |
| 4346 | Index => @intFromEnum(@field(extra, field.name)), | 5246 | Module.Decl.Index, |
| 4347 | Module.Decl.Index => @intFromEnum(@field(extra, field.name)), | 5247 | Module.Namespace.Index, |
| 4348 | Module.Namespace.Index => @intFromEnum(@field(extra, field.name)), | 5248 | Module.Namespace.OptionalIndex, |
| 4349 | Module.Namespace.OptionalIndex => @intFromEnum(@field(extra, field.name)), | 5249 | MapIndex, |
| 4350 | Module.Fn.Index => @intFromEnum(@field(extra, field.name)), | 5250 | OptionalMapIndex, |
| 4351 | MapIndex => @intFromEnum(@field(extra, field.name)), | 5251 | RuntimeIndex, |
| 4352 | OptionalMapIndex => @intFromEnum(@field(extra, field.name)), | 5252 | String, |
| 4353 | RuntimeIndex => @intFromEnum(@field(extra, field.name)), | 5253 | NullTerminatedString, |
| 4354 | String => @intFromEnum(@field(extra, field.name)), | 5254 | OptionalNullTerminatedString, |
| 4355 | NullTerminatedString => @intFromEnum(@field(extra, field.name)), | 5255 | Tag.TypePointer.VectorIndex, |
| 4356 | OptionalNullTerminatedString => @intFromEnum(@field(extra, field.name)), | 5256 | => @intFromEnum(@field(extra, field.name)), |
| 4357 | i32 => @as(u32, @bitCast(@field(extra, field.name))), | 5257 | |
| 4358 | Tag.TypePointer.Flags => @as(u32, @bitCast(@field(extra, field.name))), | 5258 | u32, |
| 4359 | TypeFunction.Flags => @as(u32, @bitCast(@field(extra, field.name))), | 5259 | i32, |
| 4360 | Tag.TypePointer.PackedOffset => @as(u32, @bitCast(@field(extra, field.name))), | 5260 | FuncAnalysis, |
| 4361 | Tag.TypePointer.VectorIndex => @intFromEnum(@field(extra, field.name)), | 5261 | Tag.TypePointer.Flags, |
| 4362 | Tag.Variable.Flags => @as(u32, @bitCast(@field(extra, field.name))), | 5262 | Tag.TypeFunction.Flags, |
| 5263 | Tag.TypePointer.PackedOffset, | ||
| 5264 | Tag.Variable.Flags, | ||
| 5265 | => @bitCast(@field(extra, field.name)), | ||
| 5266 | |||
| 4363 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 5267 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 4364 | }); | 5268 | }); |
| 4365 | } | 5269 | } |
| ... | @@ -4404,36 +5308,40 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void { | ... | @@ -4404,36 +5308,40 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void { |
| 4404 | } | 5308 | } |
| 4405 | } | 5309 | } |
| 4406 | 5310 | ||
| 4407 | fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct { data: T, end: usize } { | 5311 | fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct { data: T, end: u32 } { |
| 4408 | var result: T = undefined; | 5312 | var result: T = undefined; |
| 4409 | const fields = @typeInfo(T).Struct.fields; | 5313 | const fields = @typeInfo(T).Struct.fields; |
| 4410 | inline for (fields, 0..) |field, i| { | 5314 | inline for (fields, 0..) |field, i| { |
| 4411 | const int32 = ip.extra.items[i + index]; | 5315 | const int32 = ip.extra.items[i + index]; |
| 4412 | @field(result, field.name) = switch (field.type) { | 5316 | @field(result, field.name) = switch (field.type) { |
| 4413 | u32 => int32, | 5317 | Index, |
| 4414 | Index => @as(Index, @enumFromInt(int32)), | 5318 | Module.Decl.Index, |
| 4415 | Module.Decl.Index => @as(Module.Decl.Index, @enumFromInt(int32)), | 5319 | Module.Namespace.Index, |
| 4416 | Module.Namespace.Index => @as(Module.Namespace.Index, @enumFromInt(int32)), | 5320 | Module.Namespace.OptionalIndex, |
| 4417 | Module.Namespace.OptionalIndex => @as(Module.Namespace.OptionalIndex, @enumFromInt(int32)), | 5321 | MapIndex, |
| 4418 | Module.Fn.Index => @as(Module.Fn.Index, @enumFromInt(int32)), | 5322 | OptionalMapIndex, |
| 4419 | MapIndex => @as(MapIndex, @enumFromInt(int32)), | 5323 | RuntimeIndex, |
| 4420 | OptionalMapIndex => @as(OptionalMapIndex, @enumFromInt(int32)), | 5324 | String, |
| 4421 | RuntimeIndex => @as(RuntimeIndex, @enumFromInt(int32)), | 5325 | NullTerminatedString, |
| 4422 | String => @as(String, @enumFromInt(int32)), | 5326 | OptionalNullTerminatedString, |
| 4423 | NullTerminatedString => @as(NullTerminatedString, @enumFromInt(int32)), | 5327 | Tag.TypePointer.VectorIndex, |
| 4424 | OptionalNullTerminatedString => @as(OptionalNullTerminatedString, @enumFromInt(int32)), | 5328 | => @enumFromInt(int32), |
| 4425 | i32 => @as(i32, @bitCast(int32)), | 5329 | |
| 4426 | Tag.TypePointer.Flags => @as(Tag.TypePointer.Flags, @bitCast(int32)), | 5330 | u32, |
| 4427 | TypeFunction.Flags => @as(TypeFunction.Flags, @bitCast(int32)), | 5331 | i32, |
| 4428 | Tag.TypePointer.PackedOffset => @as(Tag.TypePointer.PackedOffset, @bitCast(int32)), | 5332 | Tag.TypePointer.Flags, |
| 4429 | Tag.TypePointer.VectorIndex => @as(Tag.TypePointer.VectorIndex, @enumFromInt(int32)), | 5333 | Tag.TypeFunction.Flags, |
| 4430 | Tag.Variable.Flags => @as(Tag.Variable.Flags, @bitCast(int32)), | 5334 | Tag.TypePointer.PackedOffset, |
| 5335 | Tag.Variable.Flags, | ||
| 5336 | FuncAnalysis, | ||
| 5337 | => @bitCast(int32), | ||
| 5338 | |||
| 4431 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 5339 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 4432 | }; | 5340 | }; |
| 4433 | } | 5341 | } |
| 4434 | return .{ | 5342 | return .{ |
| 4435 | .data = result, | 5343 | .data = result, |
| 4436 | .end = index + fields.len, | 5344 | .end = @intCast(index + fields.len), |
| 4437 | }; | 5345 | }; |
| 4438 | } | 5346 | } |
| 4439 | 5347 | ||
| ... | @@ -4603,206 +5511,226 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index { | ... | @@ -4603,206 +5511,226 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index { |
| 4603 | pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { | 5511 | pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { |
| 4604 | const old_ty = ip.typeOf(val); | 5512 | const old_ty = ip.typeOf(val); |
| 4605 | if (old_ty == new_ty) return val; | 5513 | if (old_ty == new_ty) return val; |
| 5514 | |||
| 5515 | const tags = ip.items.items(.tag); | ||
| 5516 | |||
| 4606 | switch (val) { | 5517 | switch (val) { |
| 4607 | .undef => return ip.get(gpa, .{ .undef = new_ty }), | 5518 | .undef => return ip.get(gpa, .{ .undef = new_ty }), |
| 4608 | .null_value => if (ip.isOptionalType(new_ty)) | 5519 | .null_value => { |
| 4609 | return ip.get(gpa, .{ .opt = .{ | 5520 | if (ip.isOptionalType(new_ty)) return ip.get(gpa, .{ .opt = .{ |
| 4610 | .ty = new_ty, | 5521 | .ty = new_ty, |
| 4611 | .val = .none, | 5522 | .val = .none, |
| 4612 | } }) | 5523 | } }); |
| 4613 | else if (ip.isPointerType(new_ty)) | 5524 | |
| 4614 | return ip.get(gpa, .{ .ptr = .{ | 5525 | if (ip.isPointerType(new_ty)) return ip.get(gpa, .{ .ptr = .{ |
| 4615 | .ty = new_ty, | 5526 | .ty = new_ty, |
| 4616 | .addr = .{ .int = .zero_usize }, | 5527 | .addr = .{ .int = .zero_usize }, |
| 4617 | .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) { | 5528 | .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) { |
| 4618 | .One, .Many, .C => .none, | 5529 | .One, .Many, .C => .none, |
| 4619 | .Slice => try ip.get(gpa, .{ .undef = .usize_type }), | 5530 | .Slice => try ip.get(gpa, .{ .undef = .usize_type }), |
| 4620 | }, | 5531 | }, |
| 5532 | } }); | ||
| 5533 | }, | ||
| 5534 | else => switch (tags[@intFromEnum(val)]) { | ||
| 5535 | .func_decl => return getCoercedFuncDecl(ip, gpa, val, new_ty), | ||
| 5536 | .func_instance => return getCoercedFuncInstance(ip, gpa, val, new_ty), | ||
| 5537 | .func_coerced => { | ||
| 5538 | const extra_index = ip.items.items(.data)[@intFromEnum(val)]; | ||
| 5539 | const func: Index = @enumFromInt( | ||
| 5540 | ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncCoerced, "func").?], | ||
| 5541 | ); | ||
| 5542 | switch (tags[@intFromEnum(func)]) { | ||
| 5543 | .func_decl => return getCoercedFuncDecl(ip, gpa, val, new_ty), | ||
| 5544 | .func_instance => return getCoercedFuncInstance(ip, gpa, val, new_ty), | ||
| 5545 | else => unreachable, | ||
| 5546 | } | ||
| 5547 | }, | ||
| 5548 | else => {}, | ||
| 5549 | }, | ||
| 5550 | } | ||
| 5551 | |||
| 5552 | switch (ip.indexToKey(val)) { | ||
| 5553 | .undef => return ip.get(gpa, .{ .undef = new_ty }), | ||
| 5554 | .extern_func => |extern_func| if (ip.isFunctionType(new_ty)) | ||
| 5555 | return ip.get(gpa, .{ .extern_func = .{ | ||
| 5556 | .ty = new_ty, | ||
| 5557 | .decl = extern_func.decl, | ||
| 5558 | .lib_name = extern_func.lib_name, | ||
| 4621 | } }), | 5559 | } }), |
| 4622 | else => switch (ip.indexToKey(val)) { | 5560 | |
| 4623 | .undef => return ip.get(gpa, .{ .undef = new_ty }), | 5561 | .func => unreachable, |
| 4624 | .extern_func => |extern_func| if (ip.isFunctionType(new_ty)) | 5562 | |
| 4625 | return ip.get(gpa, .{ .extern_func = .{ | 5563 | .int => |int| switch (ip.indexToKey(new_ty)) { |
| 4626 | .ty = new_ty, | 5564 | .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{ |
| 4627 | .decl = extern_func.decl, | 5565 | .ty = new_ty, |
| 4628 | .lib_name = extern_func.lib_name, | 5566 | .int = try ip.getCoerced(gpa, val, enum_type.tag_ty), |
| 4629 | } }), | 5567 | } }), |
| 4630 | .func => |func| if (ip.isFunctionType(new_ty)) | 5568 | .ptr_type => return ip.get(gpa, .{ .ptr = .{ |
| 4631 | return ip.get(gpa, .{ .func = .{ | 5569 | .ty = new_ty, |
| 4632 | .ty = new_ty, | 5570 | .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) }, |
| 4633 | .index = func.index, | 5571 | } }), |
| 4634 | } }), | 5572 | else => if (ip.isIntegerType(new_ty)) |
| 4635 | .int => |int| switch (ip.indexToKey(new_ty)) { | 5573 | return getCoercedInts(ip, gpa, int, new_ty), |
| 4636 | .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{ | 5574 | }, |
| 4637 | .ty = new_ty, | 5575 | .float => |float| switch (ip.indexToKey(new_ty)) { |
| 4638 | .int = try ip.getCoerced(gpa, val, enum_type.tag_ty), | 5576 | .simple_type => |simple| switch (simple) { |
| 4639 | } }), | 5577 | .f16, |
| 4640 | .ptr_type => return ip.get(gpa, .{ .ptr = .{ | 5578 | .f32, |
| 5579 | .f64, | ||
| 5580 | .f80, | ||
| 5581 | .f128, | ||
| 5582 | .c_longdouble, | ||
| 5583 | .comptime_float, | ||
| 5584 | => return ip.get(gpa, .{ .float = .{ | ||
| 4641 | .ty = new_ty, | 5585 | .ty = new_ty, |
| 4642 | .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) }, | 5586 | .storage = float.storage, |
| 4643 | } }), | 5587 | } }), |
| 4644 | else => if (ip.isIntegerType(new_ty)) | ||
| 4645 | return getCoercedInts(ip, gpa, int, new_ty), | ||
| 4646 | }, | ||
| 4647 | .float => |float| switch (ip.indexToKey(new_ty)) { | ||
| 4648 | .simple_type => |simple| switch (simple) { | ||
| 4649 | .f16, | ||
| 4650 | .f32, | ||
| 4651 | .f64, | ||
| 4652 | .f80, | ||
| 4653 | .f128, | ||
| 4654 | .c_longdouble, | ||
| 4655 | .comptime_float, | ||
| 4656 | => return ip.get(gpa, .{ .float = .{ | ||
| 4657 | .ty = new_ty, | ||
| 4658 | .storage = float.storage, | ||
| 4659 | } }), | ||
| 4660 | else => {}, | ||
| 4661 | }, | ||
| 4662 | else => {}, | 5588 | else => {}, |
| 4663 | }, | 5589 | }, |
| 4664 | .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty)) | 5590 | else => {}, |
| 4665 | return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty), | 5591 | }, |
| 4666 | .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) { | 5592 | .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty)) |
| 4667 | .enum_type => |enum_type| { | 5593 | return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty), |
| 4668 | const index = enum_type.nameIndex(ip, enum_literal).?; | 5594 | .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) { |
| 4669 | return ip.get(gpa, .{ .enum_tag = .{ | 5595 | .enum_type => |enum_type| { |
| 4670 | .ty = new_ty, | 5596 | const index = enum_type.nameIndex(ip, enum_literal).?; |
| 4671 | .int = if (enum_type.values.len != 0) | 5597 | return ip.get(gpa, .{ .enum_tag = .{ |
| 4672 | enum_type.values[index] | 5598 | .ty = new_ty, |
| 4673 | else | 5599 | .int = if (enum_type.values.len != 0) |
| 4674 | try ip.get(gpa, .{ .int = .{ | 5600 | enum_type.values[index] |
| 4675 | .ty = enum_type.tag_ty, | 5601 | else |
| 4676 | .storage = .{ .u64 = index }, | 5602 | try ip.get(gpa, .{ .int = .{ |
| 4677 | } }), | 5603 | .ty = enum_type.tag_ty, |
| 4678 | } }); | 5604 | .storage = .{ .u64 = index }, |
| 4679 | }, | 5605 | } }), |
| 5606 | } }); | ||
| 5607 | }, | ||
| 5608 | else => {}, | ||
| 5609 | }, | ||
| 5610 | .ptr => |ptr| if (ip.isPointerType(new_ty)) | ||
| 5611 | return ip.get(gpa, .{ .ptr = .{ | ||
| 5612 | .ty = new_ty, | ||
| 5613 | .addr = ptr.addr, | ||
| 5614 | .len = ptr.len, | ||
| 5615 | } }) | ||
| 5616 | else if (ip.isIntegerType(new_ty)) | ||
| 5617 | switch (ptr.addr) { | ||
| 5618 | .int => |int| return ip.getCoerced(gpa, int, new_ty), | ||
| 4680 | else => {}, | 5619 | else => {}, |
| 4681 | }, | 5620 | }, |
| 4682 | .ptr => |ptr| if (ip.isPointerType(new_ty)) | 5621 | .opt => |opt| switch (ip.indexToKey(new_ty)) { |
| 4683 | return ip.get(gpa, .{ .ptr = .{ | 5622 | .ptr_type => |ptr_type| return switch (opt.val) { |
| 5623 | .none => try ip.get(gpa, .{ .ptr = .{ | ||
| 4684 | .ty = new_ty, | 5624 | .ty = new_ty, |
| 4685 | .addr = ptr.addr, | 5625 | .addr = .{ .int = .zero_usize }, |
| 4686 | .len = ptr.len, | 5626 | .len = switch (ptr_type.flags.size) { |
| 4687 | } }) | 5627 | .One, .Many, .C => .none, |
| 4688 | else if (ip.isIntegerType(new_ty)) | 5628 | .Slice => try ip.get(gpa, .{ .undef = .usize_type }), |
| 4689 | switch (ptr.addr) { | ||
| 4690 | .int => |int| return ip.getCoerced(gpa, int, new_ty), | ||
| 4691 | else => {}, | ||
| 4692 | }, | ||
| 4693 | .opt => |opt| switch (ip.indexToKey(new_ty)) { | ||
| 4694 | .ptr_type => |ptr_type| return switch (opt.val) { | ||
| 4695 | .none => try ip.get(gpa, .{ .ptr = .{ | ||
| 4696 | .ty = new_ty, | ||
| 4697 | .addr = .{ .int = .zero_usize }, | ||
| 4698 | .len = switch (ptr_type.flags.size) { | ||
| 4699 | .One, .Many, .C => .none, | ||
| 4700 | .Slice => try ip.get(gpa, .{ .undef = .usize_type }), | ||
| 4701 | }, | ||
| 4702 | } }), | ||
| 4703 | else => |payload| try ip.getCoerced(gpa, payload, new_ty), | ||
| 4704 | }, | ||
| 4705 | .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{ | ||
| 4706 | .ty = new_ty, | ||
| 4707 | .val = switch (opt.val) { | ||
| 4708 | .none => .none, | ||
| 4709 | else => try ip.getCoerced(gpa, opt.val, child_type), | ||
| 4710 | }, | 5629 | }, |
| 4711 | } }), | 5630 | } }), |
| 4712 | else => {}, | 5631 | else => |payload| try ip.getCoerced(gpa, payload, new_ty), |
| 4713 | }, | 5632 | }, |
| 4714 | .err => |err| if (ip.isErrorSetType(new_ty)) | 5633 | .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{ |
| 4715 | return ip.get(gpa, .{ .err = .{ | 5634 | .ty = new_ty, |
| 4716 | .ty = new_ty, | 5635 | .val = switch (opt.val) { |
| 4717 | .name = err.name, | 5636 | .none => .none, |
| 4718 | } }) | 5637 | else => try ip.getCoerced(gpa, opt.val, child_type), |
| 4719 | else if (ip.isErrorUnionType(new_ty)) | 5638 | }, |
| 4720 | return ip.get(gpa, .{ .error_union = .{ | 5639 | } }), |
| 4721 | .ty = new_ty, | 5640 | else => {}, |
| 4722 | .val = .{ .err_name = err.name }, | 5641 | }, |
| 4723 | } }), | 5642 | .err => |err| if (ip.isErrorSetType(new_ty)) |
| 4724 | .error_union => |error_union| if (ip.isErrorUnionType(new_ty)) | 5643 | return ip.get(gpa, .{ .err = .{ |
| 4725 | return ip.get(gpa, .{ .error_union = .{ | 5644 | .ty = new_ty, |
| 4726 | .ty = new_ty, | 5645 | .name = err.name, |
| 4727 | .val = error_union.val, | 5646 | } }) |
| 4728 | } }), | 5647 | else if (ip.isErrorUnionType(new_ty)) |
| 4729 | .aggregate => |aggregate| { | 5648 | return ip.get(gpa, .{ .error_union = .{ |
| 4730 | const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty))); | 5649 | .ty = new_ty, |
| 4731 | direct: { | 5650 | .val = .{ .err_name = err.name }, |
| 4732 | const old_ty_child = switch (ip.indexToKey(old_ty)) { | 5651 | } }), |
| 4733 | inline .array_type, .vector_type => |seq_type| seq_type.child, | 5652 | .error_union => |error_union| if (ip.isErrorUnionType(new_ty)) |
| 4734 | .anon_struct_type, .struct_type => break :direct, | 5653 | return ip.get(gpa, .{ .error_union = .{ |
| 4735 | else => unreachable, | 5654 | .ty = new_ty, |
| 4736 | }; | 5655 | .val = error_union.val, |
| 4737 | const new_ty_child = switch (ip.indexToKey(new_ty)) { | 5656 | } }), |
| 4738 | inline .array_type, .vector_type => |seq_type| seq_type.child, | 5657 | .aggregate => |aggregate| { |
| 4739 | .anon_struct_type, .struct_type => break :direct, | 5658 | const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty))); |
| 4740 | else => unreachable, | 5659 | direct: { |
| 4741 | }; | 5660 | const old_ty_child = switch (ip.indexToKey(old_ty)) { |
| 4742 | if (old_ty_child != new_ty_child) break :direct; | 5661 | inline .array_type, .vector_type => |seq_type| seq_type.child, |
| 4743 | // TODO: write something like getCoercedInts to avoid needing to dupe here | 5662 | .anon_struct_type, .struct_type => break :direct, |
| 4744 | switch (aggregate.storage) { | 5663 | else => unreachable, |
| 4745 | .bytes => |bytes| { | 5664 | }; |
| 4746 | const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]); | 5665 | const new_ty_child = switch (ip.indexToKey(new_ty)) { |
| 4747 | defer gpa.free(bytes_copy); | 5666 | inline .array_type, .vector_type => |seq_type| seq_type.child, |
| 4748 | return ip.get(gpa, .{ .aggregate = .{ | 5667 | .anon_struct_type, .struct_type => break :direct, |
| 4749 | .ty = new_ty, | 5668 | else => unreachable, |
| 4750 | .storage = .{ .bytes = bytes_copy }, | 5669 | }; |
| 4751 | } }); | 5670 | if (old_ty_child != new_ty_child) break :direct; |
| 4752 | }, | 5671 | // TODO: write something like getCoercedInts to avoid needing to dupe here |
| 4753 | .elems => |elems| { | ||
| 4754 | const elems_copy = try gpa.dupe(InternPool.Index, elems[0..new_len]); | ||
| 4755 | defer gpa.free(elems_copy); | ||
| 4756 | return ip.get(gpa, .{ .aggregate = .{ | ||
| 4757 | .ty = new_ty, | ||
| 4758 | .storage = .{ .elems = elems_copy }, | ||
| 4759 | } }); | ||
| 4760 | }, | ||
| 4761 | .repeated_elem => |elem| { | ||
| 4762 | return ip.get(gpa, .{ .aggregate = .{ | ||
| 4763 | .ty = new_ty, | ||
| 4764 | .storage = .{ .repeated_elem = elem }, | ||
| 4765 | } }); | ||
| 4766 | }, | ||
| 4767 | } | ||
| 4768 | } | ||
| 4769 | // Direct approach failed - we must recursively coerce elems | ||
| 4770 | const agg_elems = try gpa.alloc(InternPool.Index, new_len); | ||
| 4771 | defer gpa.free(agg_elems); | ||
| 4772 | // First, fill the vector with the uncoerced elements. We do this to avoid key | ||
| 4773 | // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we | ||
| 4774 | // begin interning elems. | ||
| 4775 | switch (aggregate.storage) { | 5672 | switch (aggregate.storage) { |
| 4776 | .bytes => { | 5673 | .bytes => |bytes| { |
| 4777 | // We have to intern each value here, so unfortunately we can't easily avoid | 5674 | const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]); |
| 4778 | // the repeated indexToKey calls. | 5675 | defer gpa.free(bytes_copy); |
| 4779 | for (agg_elems, 0..) |*elem, i| { | 5676 | return ip.get(gpa, .{ .aggregate = .{ |
| 4780 | const x = ip.indexToKey(val).aggregate.storage.bytes[i]; | 5677 | .ty = new_ty, |
| 4781 | elem.* = try ip.get(gpa, .{ .int = .{ | 5678 | .storage = .{ .bytes = bytes_copy }, |
| 4782 | .ty = .u8_type, | 5679 | } }); |
| 4783 | .storage = .{ .u64 = x }, | 5680 | }, |
| 4784 | } }); | 5681 | .elems => |elems| { |
| 4785 | } | 5682 | const elems_copy = try gpa.dupe(Index, elems[0..new_len]); |
| 5683 | defer gpa.free(elems_copy); | ||
| 5684 | return ip.get(gpa, .{ .aggregate = .{ | ||
| 5685 | .ty = new_ty, | ||
| 5686 | .storage = .{ .elems = elems_copy }, | ||
| 5687 | } }); | ||
| 5688 | }, | ||
| 5689 | .repeated_elem => |elem| { | ||
| 5690 | return ip.get(gpa, .{ .aggregate = .{ | ||
| 5691 | .ty = new_ty, | ||
| 5692 | .storage = .{ .repeated_elem = elem }, | ||
| 5693 | } }); | ||
| 4786 | }, | 5694 | }, |
| 4787 | .elems => |elems| @memcpy(agg_elems, elems[0..new_len]), | ||
| 4788 | .repeated_elem => |elem| @memset(agg_elems, elem), | ||
| 4789 | } | ||
| 4790 | // Now, coerce each element to its new type. | ||
| 4791 | for (agg_elems, 0..) |*elem, i| { | ||
| 4792 | const new_elem_ty = switch (ip.indexToKey(new_ty)) { | ||
| 4793 | inline .array_type, .vector_type => |seq_type| seq_type.child, | ||
| 4794 | .anon_struct_type => |anon_struct_type| anon_struct_type.types[i], | ||
| 4795 | .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?) | ||
| 4796 | .fields.values()[i].ty.toIntern(), | ||
| 4797 | else => unreachable, | ||
| 4798 | }; | ||
| 4799 | elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty); | ||
| 4800 | } | 5695 | } |
| 4801 | return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } }); | 5696 | } |
| 4802 | }, | 5697 | // Direct approach failed - we must recursively coerce elems |
| 4803 | else => {}, | 5698 | const agg_elems = try gpa.alloc(Index, new_len); |
| 5699 | defer gpa.free(agg_elems); | ||
| 5700 | // First, fill the vector with the uncoerced elements. We do this to avoid key | ||
| 5701 | // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we | ||
| 5702 | // begin interning elems. | ||
| 5703 | switch (aggregate.storage) { | ||
| 5704 | .bytes => { | ||
| 5705 | // We have to intern each value here, so unfortunately we can't easily avoid | ||
| 5706 | // the repeated indexToKey calls. | ||
| 5707 | for (agg_elems, 0..) |*elem, i| { | ||
| 5708 | const x = ip.indexToKey(val).aggregate.storage.bytes[i]; | ||
| 5709 | elem.* = try ip.get(gpa, .{ .int = .{ | ||
| 5710 | .ty = .u8_type, | ||
| 5711 | .storage = .{ .u64 = x }, | ||
| 5712 | } }); | ||
| 5713 | } | ||
| 5714 | }, | ||
| 5715 | .elems => |elems| @memcpy(agg_elems, elems[0..new_len]), | ||
| 5716 | .repeated_elem => |elem| @memset(agg_elems, elem), | ||
| 5717 | } | ||
| 5718 | // Now, coerce each element to its new type. | ||
| 5719 | for (agg_elems, 0..) |*elem, i| { | ||
| 5720 | const new_elem_ty = switch (ip.indexToKey(new_ty)) { | ||
| 5721 | inline .array_type, .vector_type => |seq_type| seq_type.child, | ||
| 5722 | .anon_struct_type => |anon_struct_type| anon_struct_type.types[i], | ||
| 5723 | .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?) | ||
| 5724 | .fields.values()[i].ty.toIntern(), | ||
| 5725 | else => unreachable, | ||
| 5726 | }; | ||
| 5727 | elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty); | ||
| 5728 | } | ||
| 5729 | return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } }); | ||
| 4804 | }, | 5730 | }, |
| 5731 | else => {}, | ||
| 4805 | } | 5732 | } |
| 5733 | |||
| 4806 | switch (ip.indexToKey(new_ty)) { | 5734 | switch (ip.indexToKey(new_ty)) { |
| 4807 | .opt_type => |child_type| switch (val) { | 5735 | .opt_type => |child_type| switch (val) { |
| 4808 | .null_value => return ip.get(gpa, .{ .opt = .{ | 5736 | .null_value => return ip.get(gpa, .{ .opt = .{ |
| ... | @@ -4830,6 +5758,54 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al | ... | @@ -4830,6 +5758,54 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al |
| 4830 | unreachable; | 5758 | unreachable; |
| 4831 | } | 5759 | } |
| 4832 | 5760 | ||
| 5761 | fn getCoercedFuncDecl(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { | ||
| 5762 | const datas = ip.items.items(.data); | ||
| 5763 | const extra_index = datas[@intFromEnum(val)]; | ||
| 5764 | const prev_ty: Index = @enumFromInt( | ||
| 5765 | ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncDecl, "ty").?], | ||
| 5766 | ); | ||
| 5767 | if (new_ty == prev_ty) return val; | ||
| 5768 | return getCoercedFunc(ip, gpa, val, new_ty); | ||
| 5769 | } | ||
| 5770 | |||
| 5771 | fn getCoercedFuncInstance(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { | ||
| 5772 | const datas = ip.items.items(.data); | ||
| 5773 | const extra_index = datas[@intFromEnum(val)]; | ||
| 5774 | const prev_ty: Index = @enumFromInt( | ||
| 5775 | ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "ty").?], | ||
| 5776 | ); | ||
| 5777 | if (new_ty == prev_ty) return val; | ||
| 5778 | return getCoercedFunc(ip, gpa, val, new_ty); | ||
| 5779 | } | ||
| 5780 | |||
| 5781 | fn getCoercedFunc(ip: *InternPool, gpa: Allocator, func: Index, ty: Index) Allocator.Error!Index { | ||
| 5782 | const prev_extra_len = ip.extra.items.len; | ||
| 5783 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncCoerced).Struct.fields.len); | ||
| 5784 | try ip.items.ensureUnusedCapacity(gpa, 1); | ||
| 5785 | try ip.map.ensureUnusedCapacity(gpa, 1); | ||
| 5786 | |||
| 5787 | const extra_index = ip.addExtraAssumeCapacity(Tag.FuncCoerced{ | ||
| 5788 | .ty = ty, | ||
| 5789 | .func = func, | ||
| 5790 | }); | ||
| 5791 | |||
| 5792 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 5793 | const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 5794 | .func = extraFuncCoerced(ip, extra_index), | ||
| 5795 | }, adapter); | ||
| 5796 | |||
| 5797 | if (gop.found_existing) { | ||
| 5798 | ip.extra.items.len = prev_extra_len; | ||
| 5799 | return @enumFromInt(gop.index); | ||
| 5800 | } | ||
| 5801 | |||
| 5802 | ip.items.appendAssumeCapacity(.{ | ||
| 5803 | .tag = .func_coerced, | ||
| 5804 | .data = extra_index, | ||
| 5805 | }); | ||
| 5806 | return @enumFromInt(ip.items.len - 1); | ||
| 5807 | } | ||
| 5808 | |||
| 4833 | /// Asserts `val` has an integer type. | 5809 | /// Asserts `val` has an integer type. |
| 4834 | /// Assumes `new_ty` is an integer type. | 5810 | /// Assumes `new_ty` is an integer type. |
| 4835 | pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Index) Allocator.Error!Index { | 5811 | pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Index) Allocator.Error!Index { |
| ... | @@ -4881,27 +5857,11 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType { | ... | @@ -4881,27 +5857,11 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType { |
| 4881 | const tags = ip.items.items(.tag); | 5857 | const tags = ip.items.items(.tag); |
| 4882 | const datas = ip.items.items(.data); | 5858 | const datas = ip.items.items(.data); |
| 4883 | switch (tags[@intFromEnum(val)]) { | 5859 | switch (tags[@intFromEnum(val)]) { |
| 4884 | .type_function => return indexToKeyFuncType(ip, datas[@intFromEnum(val)]), | 5860 | .type_function => return extraFuncType(ip, datas[@intFromEnum(val)]), |
| 4885 | else => return null, | 5861 | else => return null, |
| 4886 | } | 5862 | } |
| 4887 | } | 5863 | } |
| 4888 | 5864 | ||
| 4889 | pub fn indexToFunc(ip: *const InternPool, val: Index) Module.Fn.OptionalIndex { | ||
| 4890 | assert(val != .none); | ||
| 4891 | const tags = ip.items.items(.tag); | ||
| 4892 | if (tags[@intFromEnum(val)] != .func) return .none; | ||
| 4893 | const datas = ip.items.items(.data); | ||
| 4894 | return ip.extraData(Tag.Func, datas[@intFromEnum(val)]).index.toOptional(); | ||
| 4895 | } | ||
| 4896 | |||
| 4897 | pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex { | ||
| 4898 | assert(val != .none); | ||
| 4899 | const tags = ip.items.items(.tag); | ||
| 4900 | if (tags[@intFromEnum(val)] != .type_inferred_error_set) return .none; | ||
| 4901 | const datas = ip.items.items(.data); | ||
| 4902 | return @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(datas[@intFromEnum(val)])).toOptional(); | ||
| 4903 | } | ||
| 4904 | |||
| 4905 | /// includes .comptime_int_type | 5865 | /// includes .comptime_int_type |
| 4906 | pub fn isIntegerType(ip: *const InternPool, ty: Index) bool { | 5866 | pub fn isIntegerType(ip: *const InternPool, ty: Index) bool { |
| 4907 | return switch (ty) { | 5867 | return switch (ty) { |
| ... | @@ -4952,14 +5912,17 @@ pub fn isOptionalType(ip: *const InternPool, ty: Index) bool { | ... | @@ -4952,14 +5912,17 @@ pub fn isOptionalType(ip: *const InternPool, ty: Index) bool { |
| 4952 | 5912 | ||
| 4953 | /// includes .inferred_error_set_type | 5913 | /// includes .inferred_error_set_type |
| 4954 | pub fn isErrorSetType(ip: *const InternPool, ty: Index) bool { | 5914 | pub fn isErrorSetType(ip: *const InternPool, ty: Index) bool { |
| 4955 | return ty == .anyerror_type or switch (ip.indexToKey(ty)) { | 5915 | return switch (ty) { |
| 4956 | .error_set_type, .inferred_error_set_type => true, | 5916 | .anyerror_type, .adhoc_inferred_error_set_type => true, |
| 4957 | else => false, | 5917 | else => switch (ip.indexToKey(ty)) { |
| 5918 | .error_set_type, .inferred_error_set_type => true, | ||
| 5919 | else => false, | ||
| 5920 | }, | ||
| 4958 | }; | 5921 | }; |
| 4959 | } | 5922 | } |
| 4960 | 5923 | ||
| 4961 | pub fn isInferredErrorSetType(ip: *const InternPool, ty: Index) bool { | 5924 | pub fn isInferredErrorSetType(ip: *const InternPool, ty: Index) bool { |
| 4962 | return ip.indexToKey(ty) == .inferred_error_set_type; | 5925 | return ty == .adhoc_inferred_error_set_type or ip.indexToKey(ty) == .inferred_error_set_type; |
| 4963 | } | 5926 | } |
| 4964 | 5927 | ||
| 4965 | pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool { | 5928 | pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool { |
| ... | @@ -4973,6 +5936,14 @@ pub fn isAggregateType(ip: *const InternPool, ty: Index) bool { | ... | @@ -4973,6 +5936,14 @@ pub fn isAggregateType(ip: *const InternPool, ty: Index) bool { |
| 4973 | }; | 5936 | }; |
| 4974 | } | 5937 | } |
| 4975 | 5938 | ||
| 5939 | pub fn errorUnionSet(ip: *const InternPool, ty: Index) Index { | ||
| 5940 | return ip.indexToKey(ty).error_union_type.error_set_type; | ||
| 5941 | } | ||
| 5942 | |||
| 5943 | pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index { | ||
| 5944 | return ip.indexToKey(ty).error_union_type.payload_type; | ||
| 5945 | } | ||
| 5946 | |||
| 4976 | /// The is only legal because the initializer is not part of the hash. | 5947 | /// The is only legal because the initializer is not part of the hash. |
| 4977 | pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void { | 5948 | pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void { |
| 4978 | const item = ip.items.get(@intFromEnum(index)); | 5949 | const item = ip.items.get(@intFromEnum(index)); |
| ... | @@ -4994,12 +5965,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -4994,12 +5965,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 4994 | (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl)); | 5965 | (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl)); |
| 4995 | const unions_size = ip.allocated_unions.len * | 5966 | const unions_size = ip.allocated_unions.len * |
| 4996 | (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl)); | 5967 | (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl)); |
| 4997 | const funcs_size = ip.allocated_funcs.len * | ||
| 4998 | (@sizeOf(Module.Fn) + @sizeOf(Module.Decl)); | ||
| 4999 | 5968 | ||
| 5000 | // TODO: map overhead size is not taken into account | 5969 | // TODO: map overhead size is not taken into account |
| 5001 | const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size + | 5970 | const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size + |
| 5002 | structs_size + unions_size + funcs_size; | 5971 | structs_size + unions_size; |
| 5003 | 5972 | ||
| 5004 | std.debug.print( | 5973 | std.debug.print( |
| 5005 | \\InternPool size: {d} bytes | 5974 | \\InternPool size: {d} bytes |
| ... | @@ -5008,7 +5977,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -5008,7 +5977,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 5008 | \\ {d} limbs: {d} bytes | 5977 | \\ {d} limbs: {d} bytes |
| 5009 | \\ {d} structs: {d} bytes | 5978 | \\ {d} structs: {d} bytes |
| 5010 | \\ {d} unions: {d} bytes | 5979 | \\ {d} unions: {d} bytes |
| 5011 | \\ {d} funcs: {d} bytes | ||
| 5012 | \\ | 5980 | \\ |
| 5013 | , .{ | 5981 | , .{ |
| 5014 | total_size, | 5982 | total_size, |
| ... | @@ -5022,8 +5990,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -5022,8 +5990,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 5022 | structs_size, | 5990 | structs_size, |
| 5023 | ip.allocated_unions.len, | 5991 | ip.allocated_unions.len, |
| 5024 | unions_size, | 5992 | unions_size, |
| 5025 | ip.allocated_funcs.len, | ||
| 5026 | funcs_size, | ||
| 5027 | }); | 5993 | }); |
| 5028 | 5994 | ||
| 5029 | const tags = ip.items.items(.tag); | 5995 | const tags = ip.items.items(.tag); |
| ... | @@ -5048,11 +6014,12 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -5048,11 +6014,12 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 5048 | .type_optional => 0, | 6014 | .type_optional => 0, |
| 5049 | .type_anyframe => 0, | 6015 | .type_anyframe => 0, |
| 5050 | .type_error_union => @sizeOf(Key.ErrorUnionType), | 6016 | .type_error_union => @sizeOf(Key.ErrorUnionType), |
| 6017 | .type_anyerror_union => 0, | ||
| 5051 | .type_error_set => b: { | 6018 | .type_error_set => b: { |
| 5052 | const info = ip.extraData(ErrorSet, data); | 6019 | const info = ip.extraData(Tag.ErrorSet, data); |
| 5053 | break :b @sizeOf(ErrorSet) + (@sizeOf(u32) * info.names_len); | 6020 | break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len); |
| 5054 | }, | 6021 | }, |
| 5055 | .type_inferred_error_set => @sizeOf(Module.Fn.InferredErrorSet), | 6022 | .type_inferred_error_set => 0, |
| 5056 | .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit), | 6023 | .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit), |
| 5057 | .type_enum_auto => @sizeOf(EnumAuto), | 6024 | .type_enum_auto => @sizeOf(EnumAuto), |
| 5058 | .type_opaque => @sizeOf(Key.OpaqueType), | 6025 | .type_opaque => @sizeOf(Key.OpaqueType), |
| ... | @@ -5080,8 +6047,11 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -5080,8 +6047,11 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 5080 | => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl), | 6047 | => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl), |
| 5081 | 6048 | ||
| 5082 | .type_function => b: { | 6049 | .type_function => b: { |
| 5083 | const info = ip.extraData(TypeFunction, data); | 6050 | const info = ip.extraData(Tag.TypeFunction, data); |
| 5084 | break :b @sizeOf(TypeFunction) + (@sizeOf(Index) * info.params_len); | 6051 | break :b @sizeOf(Tag.TypeFunction) + |
| 6052 | (@sizeOf(Index) * info.params_len) + | ||
| 6053 | (@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) + | ||
| 6054 | (@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits)); | ||
| 5085 | }, | 6055 | }, |
| 5086 | 6056 | ||
| 5087 | .undef => 0, | 6057 | .undef => 0, |
| ... | @@ -5130,7 +6100,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -5130,7 +6100,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 5130 | }, | 6100 | }, |
| 5131 | .aggregate => b: { | 6101 | .aggregate => b: { |
| 5132 | const info = ip.extraData(Tag.Aggregate, data); | 6102 | const info = ip.extraData(Tag.Aggregate, data); |
| 5133 | const fields_len = @as(u32, @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty))); | 6103 | const fields_len: u32 = @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty)); |
| 5134 | break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len); | 6104 | break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len); |
| 5135 | }, | 6105 | }, |
| 5136 | .repeated => @sizeOf(Repeated), | 6106 | .repeated => @sizeOf(Repeated), |
| ... | @@ -5145,7 +6115,15 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -5145,7 +6115,15 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 5145 | .float_comptime_float => @sizeOf(Float128), | 6115 | .float_comptime_float => @sizeOf(Float128), |
| 5146 | .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl), | 6116 | .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl), |
| 5147 | .extern_func => @sizeOf(Tag.ExternFunc) + @sizeOf(Module.Decl), | 6117 | .extern_func => @sizeOf(Tag.ExternFunc) + @sizeOf(Module.Decl), |
| 5148 | .func => @sizeOf(Tag.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl), | 6118 | .func_decl => @sizeOf(Tag.FuncDecl) + @sizeOf(Module.Decl), |
| 6119 | .func_instance => b: { | ||
| 6120 | const info = ip.extraData(Tag.FuncInstance, data); | ||
| 6121 | const ty = ip.typeOf(info.generic_owner); | ||
| 6122 | const params_len = ip.indexToKey(ty).func_type.param_types.len; | ||
| 6123 | break :b @sizeOf(Tag.FuncInstance) + @sizeOf(Index) * params_len + | ||
| 6124 | @sizeOf(Module.Decl); | ||
| 6125 | }, | ||
| 6126 | .func_coerced => @sizeOf(Tag.FuncCoerced), | ||
| 5149 | .only_possible_value => 0, | 6127 | .only_possible_value => 0, |
| 5150 | .union_value => @sizeOf(Key.Union), | 6128 | .union_value => @sizeOf(Key.Union), |
| 5151 | 6129 | ||
| ... | @@ -5193,6 +6171,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -5193,6 +6171,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 5193 | .type_optional, | 6171 | .type_optional, |
| 5194 | .type_anyframe, | 6172 | .type_anyframe, |
| 5195 | .type_error_union, | 6173 | .type_error_union, |
| 6174 | .type_anyerror_union, | ||
| 5196 | .type_error_set, | 6175 | .type_error_set, |
| 5197 | .type_inferred_error_set, | 6176 | .type_inferred_error_set, |
| 5198 | .type_enum_explicit, | 6177 | .type_enum_explicit, |
| ... | @@ -5249,7 +6228,9 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -5249,7 +6228,9 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 5249 | .float_comptime_float, | 6228 | .float_comptime_float, |
| 5250 | .variable, | 6229 | .variable, |
| 5251 | .extern_func, | 6230 | .extern_func, |
| 5252 | .func, | 6231 | .func_decl, |
| 6232 | .func_instance, | ||
| 6233 | .func_coerced, | ||
| 5253 | .union_value, | 6234 | .union_value, |
| 5254 | .memoized_call, | 6235 | .memoized_call, |
| 5255 | => try w.print("{d}", .{data}), | 6236 | => try w.print("{d}", .{data}), |
| ... | @@ -5284,20 +6265,12 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo | ... | @@ -5284,20 +6265,12 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo |
| 5284 | return ip.allocated_unions.at(@intFromEnum(index)); | 6265 | return ip.allocated_unions.at(@intFromEnum(index)); |
| 5285 | } | 6266 | } |
| 5286 | 6267 | ||
| 5287 | pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn { | 6268 | pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl { |
| 5288 | return ip.allocated_funcs.at(@intFromEnum(index)); | 6269 | return ip.allocated_decls.at(@intFromEnum(index)); |
| 5289 | } | ||
| 5290 | |||
| 5291 | pub fn funcPtrConst(ip: *const InternPool, index: Module.Fn.Index) *const Module.Fn { | ||
| 5292 | return ip.allocated_funcs.at(@intFromEnum(index)); | ||
| 5293 | } | 6270 | } |
| 5294 | 6271 | ||
| 5295 | pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet { | 6272 | pub fn namespacePtr(ip: *InternPool, index: Module.Namespace.Index) *Module.Namespace { |
| 5296 | return ip.allocated_inferred_error_sets.at(@intFromEnum(index)); | 6273 | return ip.allocated_namespaces.at(@intFromEnum(index)); |
| 5297 | } | ||
| 5298 | |||
| 5299 | pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.Fn.InferredErrorSet.Index) *const Module.Fn.InferredErrorSet { | ||
| 5300 | return ip.allocated_inferred_error_sets.at(@intFromEnum(index)); | ||
| 5301 | } | 6274 | } |
| 5302 | 6275 | ||
| 5303 | pub fn createStruct( | 6276 | pub fn createStruct( |
| ... | @@ -5344,47 +6317,47 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) | ... | @@ -5344,47 +6317,47 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) |
| 5344 | }; | 6317 | }; |
| 5345 | } | 6318 | } |
| 5346 | 6319 | ||
| 5347 | pub fn createFunc( | 6320 | pub fn createDecl( |
| 5348 | ip: *InternPool, | 6321 | ip: *InternPool, |
| 5349 | gpa: Allocator, | 6322 | gpa: Allocator, |
| 5350 | initialization: Module.Fn, | 6323 | initialization: Module.Decl, |
| 5351 | ) Allocator.Error!Module.Fn.Index { | 6324 | ) Allocator.Error!Module.Decl.Index { |
| 5352 | if (ip.funcs_free_list.popOrNull()) |index| { | 6325 | if (ip.decls_free_list.popOrNull()) |index| { |
| 5353 | ip.allocated_funcs.at(@intFromEnum(index)).* = initialization; | 6326 | ip.allocated_decls.at(@intFromEnum(index)).* = initialization; |
| 5354 | return index; | 6327 | return index; |
| 5355 | } | 6328 | } |
| 5356 | const ptr = try ip.allocated_funcs.addOne(gpa); | 6329 | const ptr = try ip.allocated_decls.addOne(gpa); |
| 5357 | ptr.* = initialization; | 6330 | ptr.* = initialization; |
| 5358 | return @as(Module.Fn.Index, @enumFromInt(ip.allocated_funcs.len - 1)); | 6331 | return @as(Module.Decl.Index, @enumFromInt(ip.allocated_decls.len - 1)); |
| 5359 | } | 6332 | } |
| 5360 | 6333 | ||
| 5361 | pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void { | 6334 | pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void { |
| 5362 | ip.funcPtr(index).* = undefined; | 6335 | ip.declPtr(index).* = undefined; |
| 5363 | ip.funcs_free_list.append(gpa, index) catch { | 6336 | ip.decls_free_list.append(gpa, index) catch { |
| 5364 | // In order to keep `destroyFunc` a non-fallible function, we ignore memory | 6337 | // In order to keep `destroyDecl` a non-fallible function, we ignore memory |
| 5365 | // allocation failures here, instead leaking the Fn until garbage collection. | 6338 | // allocation failures here, instead leaking the Decl until garbage collection. |
| 5366 | }; | 6339 | }; |
| 5367 | } | 6340 | } |
| 5368 | 6341 | ||
| 5369 | pub fn createInferredErrorSet( | 6342 | pub fn createNamespace( |
| 5370 | ip: *InternPool, | 6343 | ip: *InternPool, |
| 5371 | gpa: Allocator, | 6344 | gpa: Allocator, |
| 5372 | initialization: Module.Fn.InferredErrorSet, | 6345 | initialization: Module.Namespace, |
| 5373 | ) Allocator.Error!Module.Fn.InferredErrorSet.Index { | 6346 | ) Allocator.Error!Module.Namespace.Index { |
| 5374 | if (ip.inferred_error_sets_free_list.popOrNull()) |index| { | 6347 | if (ip.namespaces_free_list.popOrNull()) |index| { |
| 5375 | ip.allocated_inferred_error_sets.at(@intFromEnum(index)).* = initialization; | 6348 | ip.allocated_namespaces.at(@intFromEnum(index)).* = initialization; |
| 5376 | return index; | 6349 | return index; |
| 5377 | } | 6350 | } |
| 5378 | const ptr = try ip.allocated_inferred_error_sets.addOne(gpa); | 6351 | const ptr = try ip.allocated_namespaces.addOne(gpa); |
| 5379 | ptr.* = initialization; | 6352 | ptr.* = initialization; |
| 5380 | return @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(ip.allocated_inferred_error_sets.len - 1)); | 6353 | return @as(Module.Namespace.Index, @enumFromInt(ip.allocated_namespaces.len - 1)); |
| 5381 | } | 6354 | } |
| 5382 | 6355 | ||
| 5383 | pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.Fn.InferredErrorSet.Index) void { | 6356 | pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void { |
| 5384 | ip.inferredErrorSetPtr(index).* = undefined; | 6357 | ip.namespacePtr(index).* = undefined; |
| 5385 | ip.inferred_error_sets_free_list.append(gpa, index) catch { | 6358 | ip.namespaces_free_list.append(gpa, index) catch { |
| 5386 | // In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory | 6359 | // In order to keep `destroyNamespace` a non-fallible function, we ignore memory |
| 5387 | // allocation failures here, instead leaking the InferredErrorSet until garbage collection. | 6360 | // allocation failures here, instead leaking the Namespace until garbage collection. |
| 5388 | }; | 6361 | }; |
| 5389 | } | 6362 | } |
| 5390 | 6363 | ||
| ... | @@ -5547,6 +6520,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -5547,6 +6520,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 5547 | .slice_const_u8_sentinel_0_type, | 6520 | .slice_const_u8_sentinel_0_type, |
| 5548 | .optional_noreturn_type, | 6521 | .optional_noreturn_type, |
| 5549 | .anyerror_void_error_union_type, | 6522 | .anyerror_void_error_union_type, |
| 6523 | .adhoc_inferred_error_set_type, | ||
| 5550 | .generic_poison_type, | 6524 | .generic_poison_type, |
| 5551 | .empty_struct_type, | 6525 | .empty_struct_type, |
| 5552 | => .type_type, | 6526 | => .type_type, |
| ... | @@ -5576,6 +6550,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -5576,6 +6550,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 5576 | .type_optional, | 6550 | .type_optional, |
| 5577 | .type_anyframe, | 6551 | .type_anyframe, |
| 5578 | .type_error_union, | 6552 | .type_error_union, |
| 6553 | .type_anyerror_union, | ||
| 5579 | .type_error_set, | 6554 | .type_error_set, |
| 5580 | .type_inferred_error_set, | 6555 | .type_inferred_error_set, |
| 5581 | .type_enum_auto, | 6556 | .type_enum_auto, |
| ... | @@ -5596,7 +6571,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -5596,7 +6571,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 5596 | .undef, | 6571 | .undef, |
| 5597 | .opt_null, | 6572 | .opt_null, |
| 5598 | .only_possible_value, | 6573 | .only_possible_value, |
| 5599 | => @as(Index, @enumFromInt(ip.items.items(.data)[@intFromEnum(index)])), | 6574 | => @enumFromInt(ip.items.items(.data)[@intFromEnum(index)]), |
| 5600 | 6575 | ||
| 5601 | .simple_value => unreachable, // handled via Index above | 6576 | .simple_value => unreachable, // handled via Index above |
| 5602 | 6577 | ||
| ... | @@ -5620,7 +6595,9 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -5620,7 +6595,9 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 5620 | .enum_tag, | 6595 | .enum_tag, |
| 5621 | .variable, | 6596 | .variable, |
| 5622 | .extern_func, | 6597 | .extern_func, |
| 5623 | .func, | 6598 | .func_decl, |
| 6599 | .func_instance, | ||
| 6600 | .func_coerced, | ||
| 5624 | .union_value, | 6601 | .union_value, |
| 5625 | .bytes, | 6602 | .bytes, |
| 5626 | .aggregate, | 6603 | .aggregate, |
| ... | @@ -5628,7 +6605,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -5628,7 +6605,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 5628 | => |t| { | 6605 | => |t| { |
| 5629 | const extra_index = ip.items.items(.data)[@intFromEnum(index)]; | 6606 | const extra_index = ip.items.items(.data)[@intFromEnum(index)]; |
| 5630 | const field_index = std.meta.fieldIndex(t.Payload(), "ty").?; | 6607 | const field_index = std.meta.fieldIndex(t.Payload(), "ty").?; |
| 5631 | return @as(Index, @enumFromInt(ip.extra.items[extra_index + field_index])); | 6608 | return @enumFromInt(ip.extra.items[extra_index + field_index]); |
| 5632 | }, | 6609 | }, |
| 5633 | 6610 | ||
| 5634 | .int_u8 => .u8_type, | 6611 | .int_u8 => .u8_type, |
| ... | @@ -5693,7 +6670,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 { | ... | @@ -5693,7 +6670,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 { |
| 5693 | }; | 6670 | }; |
| 5694 | } | 6671 | } |
| 5695 | 6672 | ||
| 5696 | pub fn funcReturnType(ip: *const InternPool, ty: Index) Index { | 6673 | pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index { |
| 5697 | const item = ip.items.get(@intFromEnum(ty)); | 6674 | const item = ip.items.get(@intFromEnum(ty)); |
| 5698 | const child_item = switch (item.tag) { | 6675 | const child_item = switch (item.tag) { |
| 5699 | .type_pointer => ip.items.get(ip.extra.items[ | 6676 | .type_pointer => ip.items.get(ip.extra.items[ |
| ... | @@ -5704,7 +6681,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index { | ... | @@ -5704,7 +6681,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index { |
| 5704 | }; | 6681 | }; |
| 5705 | assert(child_item.tag == .type_function); | 6682 | assert(child_item.tag == .type_function); |
| 5706 | return @as(Index, @enumFromInt(ip.extra.items[ | 6683 | return @as(Index, @enumFromInt(ip.extra.items[ |
| 5707 | child_item.data + std.meta.fieldIndex(TypeFunction, "return_type").? | 6684 | child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").? |
| 5708 | ])); | 6685 | ])); |
| 5709 | } | 6686 | } |
| 5710 | 6687 | ||
| ... | @@ -5712,7 +6689,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool { | ... | @@ -5712,7 +6689,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool { |
| 5712 | return switch (ty) { | 6689 | return switch (ty) { |
| 5713 | .noreturn_type => true, | 6690 | .noreturn_type => true, |
| 5714 | else => switch (ip.items.items(.tag)[@intFromEnum(ty)]) { | 6691 | else => switch (ip.items.items(.tag)[@intFromEnum(ty)]) { |
| 5715 | .type_error_set => ip.extra.items[ip.items.items(.data)[@intFromEnum(ty)] + std.meta.fieldIndex(ErrorSet, "names_len").?] == 0, | 6692 | .type_error_set => ip.extra.items[ip.items.items(.data)[@intFromEnum(ty)] + std.meta.fieldIndex(Tag.ErrorSet, "names_len").?] == 0, |
| 5716 | else => false, | 6693 | else => false, |
| 5717 | }, | 6694 | }, |
| 5718 | }; | 6695 | }; |
| ... | @@ -5821,7 +6798,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -5821,7 +6798,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 5821 | .bool_type => .Bool, | 6798 | .bool_type => .Bool, |
| 5822 | .void_type => .Void, | 6799 | .void_type => .Void, |
| 5823 | .type_type => .Type, | 6800 | .type_type => .Type, |
| 5824 | .anyerror_type => .ErrorSet, | 6801 | .anyerror_type, .adhoc_inferred_error_set_type => .ErrorSet, |
| 5825 | .comptime_int_type => .ComptimeInt, | 6802 | .comptime_int_type => .ComptimeInt, |
| 5826 | .comptime_float_type => .ComptimeFloat, | 6803 | .comptime_float_type => .ComptimeFloat, |
| 5827 | .noreturn_type => .NoReturn, | 6804 | .noreturn_type => .NoReturn, |
| ... | @@ -5899,7 +6876,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -5899,7 +6876,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 5899 | 6876 | ||
| 5900 | .type_optional => .Optional, | 6877 | .type_optional => .Optional, |
| 5901 | .type_anyframe => .AnyFrame, | 6878 | .type_anyframe => .AnyFrame, |
| 5902 | .type_error_union => .ErrorUnion, | 6879 | |
| 6880 | .type_error_union, | ||
| 6881 | .type_anyerror_union, | ||
| 6882 | => .ErrorUnion, | ||
| 5903 | 6883 | ||
| 5904 | .type_error_set, | 6884 | .type_error_set, |
| 5905 | .type_inferred_error_set, | 6885 | .type_inferred_error_set, |
| ... | @@ -5969,7 +6949,9 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -5969,7 +6949,9 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 5969 | .float_comptime_float, | 6949 | .float_comptime_float, |
| 5970 | .variable, | 6950 | .variable, |
| 5971 | .extern_func, | 6951 | .extern_func, |
| 5972 | .func, | 6952 | .func_decl, |
| 6953 | .func_instance, | ||
| 6954 | .func_coerced, | ||
| 5973 | .only_possible_value, | 6955 | .only_possible_value, |
| 5974 | .union_value, | 6956 | .union_value, |
| 5975 | .bytes, | 6957 | .bytes, |
| ... | @@ -5982,3 +6964,126 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -5982,3 +6964,126 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 5982 | .none => unreachable, // special tag | 6964 | .none => unreachable, // special tag |
| 5983 | }; | 6965 | }; |
| 5984 | } | 6966 | } |
| 6967 | |||
| 6968 | pub fn isFuncBody(ip: *const InternPool, i: Index) bool { | ||
| 6969 | assert(i != .none); | ||
| 6970 | return switch (ip.items.items(.tag)[@intFromEnum(i)]) { | ||
| 6971 | .func_decl, .func_instance, .func_coerced => true, | ||
| 6972 | else => false, | ||
| 6973 | }; | ||
| 6974 | } | ||
| 6975 | |||
| 6976 | pub fn funcAnalysis(ip: *const InternPool, i: Index) *FuncAnalysis { | ||
| 6977 | assert(i != .none); | ||
| 6978 | const item = ip.items.get(@intFromEnum(i)); | ||
| 6979 | const extra_index = switch (item.tag) { | ||
| 6980 | .func_decl => item.data + std.meta.fieldIndex(Tag.FuncDecl, "analysis").?, | ||
| 6981 | .func_instance => item.data + std.meta.fieldIndex(Tag.FuncInstance, "analysis").?, | ||
| 6982 | .func_coerced => i: { | ||
| 6983 | const extra_index = item.data + std.meta.fieldIndex(Tag.FuncCoerced, "func").?; | ||
| 6984 | const func_index: Index = @enumFromInt(ip.extra.items[extra_index]); | ||
| 6985 | const sub_item = ip.items.get(@intFromEnum(func_index)); | ||
| 6986 | break :i switch (sub_item.tag) { | ||
| 6987 | .func_decl => sub_item.data + std.meta.fieldIndex(Tag.FuncDecl, "analysis").?, | ||
| 6988 | .func_instance => sub_item.data + std.meta.fieldIndex(Tag.FuncInstance, "analysis").?, | ||
| 6989 | else => unreachable, | ||
| 6990 | }; | ||
| 6991 | }, | ||
| 6992 | else => unreachable, | ||
| 6993 | }; | ||
| 6994 | return @ptrCast(&ip.extra.items[extra_index]); | ||
| 6995 | } | ||
| 6996 | |||
| 6997 | pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool { | ||
| 6998 | return funcAnalysis(ip, i).inferred_error_set; | ||
| 6999 | } | ||
| 7000 | |||
| 7001 | pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { | ||
| 7002 | assert(i != .none); | ||
| 7003 | const item = ip.items.get(@intFromEnum(i)); | ||
| 7004 | const zir_body_inst_field_index = std.meta.fieldIndex(Tag.FuncDecl, "zir_body_inst").?; | ||
| 7005 | const extra_index = switch (item.tag) { | ||
| 7006 | .func_decl => item.data + zir_body_inst_field_index, | ||
| 7007 | .func_instance => b: { | ||
| 7008 | const generic_owner_field_index = std.meta.fieldIndex(Tag.FuncInstance, "generic_owner").?; | ||
| 7009 | const func_decl_index = ip.extra.items[item.data + generic_owner_field_index]; | ||
| 7010 | assert(ip.items.items(.tag)[func_decl_index] == .func_decl); | ||
| 7011 | break :b ip.items.items(.data)[func_decl_index] + zir_body_inst_field_index; | ||
| 7012 | }, | ||
| 7013 | else => unreachable, | ||
| 7014 | }; | ||
| 7015 | return ip.extra.items[extra_index]; | ||
| 7016 | } | ||
| 7017 | |||
| 7018 | pub fn iesFuncIndex(ip: *const InternPool, ies_index: Index) Index { | ||
| 7019 | assert(ies_index != .none); | ||
| 7020 | const tags = ip.items.items(.tag); | ||
| 7021 | assert(tags[@intFromEnum(ies_index)] == .type_inferred_error_set); | ||
| 7022 | const func_index = ip.items.items(.data)[@intFromEnum(ies_index)]; | ||
| 7023 | switch (tags[func_index]) { | ||
| 7024 | .func_decl, .func_instance => {}, | ||
| 7025 | else => unreachable, // assertion failed | ||
| 7026 | } | ||
| 7027 | return @enumFromInt(func_index); | ||
| 7028 | } | ||
| 7029 | |||
| 7030 | /// Returns a mutable pointer to the resolved error set type of an inferred | ||
| 7031 | /// error set function. The returned pointer is invalidated when anything is | ||
| 7032 | /// added to `ip`. | ||
| 7033 | pub fn iesResolved(ip: *const InternPool, ies_index: Index) *Index { | ||
| 7034 | assert(ies_index != .none); | ||
| 7035 | const tags = ip.items.items(.tag); | ||
| 7036 | const datas = ip.items.items(.data); | ||
| 7037 | assert(tags[@intFromEnum(ies_index)] == .type_inferred_error_set); | ||
| 7038 | const func_index = datas[@intFromEnum(ies_index)]; | ||
| 7039 | return funcIesResolved(ip, func_index); | ||
| 7040 | } | ||
| 7041 | |||
| 7042 | /// Returns a mutable pointer to the resolved error set type of an inferred | ||
| 7043 | /// error set function. The returned pointer is invalidated when anything is | ||
| 7044 | /// added to `ip`. | ||
| 7045 | pub fn funcIesResolved(ip: *const InternPool, func_index: Index) *Index { | ||
| 7046 | const tags = ip.items.items(.tag); | ||
| 7047 | const datas = ip.items.items(.data); | ||
| 7048 | assert(funcHasInferredErrorSet(ip, func_index)); | ||
| 7049 | const func_start = datas[@intFromEnum(func_index)]; | ||
| 7050 | const extra_index = switch (tags[@intFromEnum(func_index)]) { | ||
| 7051 | .func_decl => func_start + @typeInfo(Tag.FuncDecl).Struct.fields.len, | ||
| 7052 | .func_instance => func_start + @typeInfo(Tag.FuncInstance).Struct.fields.len, | ||
| 7053 | else => unreachable, | ||
| 7054 | }; | ||
| 7055 | return @ptrCast(&ip.extra.items[extra_index]); | ||
| 7056 | } | ||
| 7057 | |||
| 7058 | pub fn funcDeclInfo(ip: *const InternPool, i: Index) Key.Func { | ||
| 7059 | const tags = ip.items.items(.tag); | ||
| 7060 | const datas = ip.items.items(.data); | ||
| 7061 | assert(tags[@intFromEnum(i)] == .func_decl); | ||
| 7062 | return extraFuncDecl(ip, datas[@intFromEnum(i)]); | ||
| 7063 | } | ||
| 7064 | |||
| 7065 | pub fn funcDeclOwner(ip: *const InternPool, i: Index) Module.Decl.Index { | ||
| 7066 | return funcDeclInfo(ip, i).owner_decl; | ||
| 7067 | } | ||
| 7068 | |||
| 7069 | pub fn funcTypeParamsLen(ip: *const InternPool, i: Index) u32 { | ||
| 7070 | const tags = ip.items.items(.tag); | ||
| 7071 | const datas = ip.items.items(.data); | ||
| 7072 | assert(tags[@intFromEnum(i)] == .type_function); | ||
| 7073 | const start = datas[@intFromEnum(i)]; | ||
| 7074 | return ip.extra.items[start + std.meta.fieldIndex(Tag.TypeFunction, "params_len").?]; | ||
| 7075 | } | ||
| 7076 | |||
| 7077 | fn unwrapCoercedFunc(ip: *const InternPool, i: Index) Index { | ||
| 7078 | const tags = ip.items.items(.tag); | ||
| 7079 | return switch (tags[@intFromEnum(i)]) { | ||
| 7080 | .func_coerced => { | ||
| 7081 | const datas = ip.items.items(.data); | ||
| 7082 | return @enumFromInt(ip.extra.items[ | ||
| 7083 | datas[@intFromEnum(i)] + std.meta.fieldIndex(Tag.FuncCoerced, "func").? | ||
| 7084 | ]); | ||
| 7085 | }, | ||
| 7086 | .func_instance, .func_decl => i, | ||
| 7087 | else => unreachable, | ||
| 7088 | }; | ||
| 7089 | } |
src/Module.zig+306-579| ... | @@ -87,7 +87,9 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{}, | ... | @@ -87,7 +87,9 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{}, |
| 87 | /// Keys are fully resolved file paths. This table owns the keys and values. | 87 | /// Keys are fully resolved file paths. This table owns the keys and values. |
| 88 | embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{}, | 88 | embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{}, |
| 89 | 89 | ||
| 90 | /// Stores all Type and Value objects; periodically garbage collected. | 90 | /// Stores all Type and Value objects. |
| 91 | /// The idea is that this will be periodically garbage-collected, but such logic | ||
| 92 | /// is not yet implemented. | ||
| 91 | intern_pool: InternPool = .{}, | 93 | intern_pool: InternPool = .{}, |
| 92 | 94 | ||
| 93 | /// To be eliminated in a future commit by moving more data into InternPool. | 95 | /// To be eliminated in a future commit by moving more data into InternPool. |
| ... | @@ -101,16 +103,6 @@ tmp_hack_arena: std.heap.ArenaAllocator, | ... | @@ -101,16 +103,6 @@ tmp_hack_arena: std.heap.ArenaAllocator, |
| 101 | /// This is currently only used for string literals. | 103 | /// This is currently only used for string literals. |
| 102 | memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{}, | 104 | memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{}, |
| 103 | 105 | ||
| 104 | monomorphed_func_keys: std.ArrayListUnmanaged(InternPool.Index) = .{}, | ||
| 105 | /// The set of all the generic function instantiations. This is used so that when a generic | ||
| 106 | /// function is called twice with the same comptime parameter arguments, both calls dispatch | ||
| 107 | /// to the same function. | ||
| 108 | monomorphed_funcs: MonomorphedFuncsSet = .{}, | ||
| 109 | /// Contains the values from `@setAlignStack`. A sparse table is used here | ||
| 110 | /// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while | ||
| 111 | /// functions are many. | ||
| 112 | align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{}, | ||
| 113 | |||
| 114 | /// We optimize memory usage for a compilation with no compile errors by storing the | 106 | /// We optimize memory usage for a compilation with no compile errors by storing the |
| 115 | /// error messages and mapping outside of `Decl`. | 107 | /// error messages and mapping outside of `Decl`. |
| 116 | /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator. | 108 | /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator. |
| ... | @@ -162,25 +154,6 @@ emit_h: ?*GlobalEmitH, | ... | @@ -162,25 +154,6 @@ emit_h: ?*GlobalEmitH, |
| 162 | 154 | ||
| 163 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | 155 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, |
| 164 | 156 | ||
| 165 | /// Rather than allocating Decl objects with an Allocator, we instead allocate | ||
| 166 | /// them with this SegmentedList. This provides four advantages: | ||
| 167 | /// * Stable memory so that one thread can access a Decl object while another | ||
| 168 | /// thread allocates additional Decl objects from this list. | ||
| 169 | /// * It allows us to use u32 indexes to reference Decl objects rather than | ||
| 170 | /// pointers, saving memory in Type, Value, and dependency sets. | ||
| 171 | /// * Using integers to reference Decl objects rather than pointers makes | ||
| 172 | /// serialization trivial. | ||
| 173 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding | ||
| 174 | /// multi-threaded contention on an atomic counter. | ||
| 175 | allocated_decls: std.SegmentedList(Decl, 0) = .{}, | ||
| 176 | /// When a Decl object is freed from `allocated_decls`, it is pushed into this stack. | ||
| 177 | decls_free_list: ArrayListUnmanaged(Decl.Index) = .{}, | ||
| 178 | |||
| 179 | /// Same pattern as with `allocated_decls`. | ||
| 180 | allocated_namespaces: std.SegmentedList(Namespace, 0) = .{}, | ||
| 181 | /// Same pattern as with `decls_free_list`. | ||
| 182 | namespaces_free_list: ArrayListUnmanaged(Namespace.Index) = .{}, | ||
| 183 | |||
| 184 | global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{}, | 157 | global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{}, |
| 185 | 158 | ||
| 186 | reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { | 159 | reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { |
| ... | @@ -189,7 +162,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { | ... | @@ -189,7 +162,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { |
| 189 | }) = .{}, | 162 | }) = .{}, |
| 190 | 163 | ||
| 191 | panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len, | 164 | panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len, |
| 192 | panic_func_index: Fn.OptionalIndex = .none, | 165 | /// The panic function body. |
| 166 | panic_func_index: InternPool.Index = .none, | ||
| 193 | null_stack_trace: InternPool.Index = .none, | 167 | null_stack_trace: InternPool.Index = .none, |
| 194 | 168 | ||
| 195 | pub const PanicId = enum { | 169 | pub const PanicId = enum { |
| ... | @@ -239,50 +213,6 @@ pub const CImportError = struct { | ... | @@ -239,50 +213,6 @@ pub const CImportError = struct { |
| 239 | } | 213 | } |
| 240 | }; | 214 | }; |
| 241 | 215 | ||
| 242 | pub const MonomorphedFuncKey = struct { func: Fn.Index, args_index: u32, args_len: u32 }; | ||
| 243 | |||
| 244 | pub const MonomorphedFuncAdaptedKey = struct { func: Fn.Index, args: []const InternPool.Index }; | ||
| 245 | |||
| 246 | pub const MonomorphedFuncsSet = std.HashMapUnmanaged( | ||
| 247 | MonomorphedFuncKey, | ||
| 248 | InternPool.Index, | ||
| 249 | MonomorphedFuncsContext, | ||
| 250 | std.hash_map.default_max_load_percentage, | ||
| 251 | ); | ||
| 252 | |||
| 253 | pub const MonomorphedFuncsContext = struct { | ||
| 254 | mod: *Module, | ||
| 255 | |||
| 256 | pub fn eql(_: @This(), a: MonomorphedFuncKey, b: MonomorphedFuncKey) bool { | ||
| 257 | return std.meta.eql(a, b); | ||
| 258 | } | ||
| 259 | |||
| 260 | pub fn hash(ctx: @This(), key: MonomorphedFuncKey) u64 { | ||
| 261 | const key_args = ctx.mod.monomorphed_func_keys.items[key.args_index..][0..key.args_len]; | ||
| 262 | return std.hash.Wyhash.hash(@intFromEnum(key.func), std.mem.sliceAsBytes(key_args)); | ||
| 263 | } | ||
| 264 | }; | ||
| 265 | |||
| 266 | pub const MonomorphedFuncsAdaptedContext = struct { | ||
| 267 | mod: *Module, | ||
| 268 | |||
| 269 | pub fn eql(ctx: @This(), adapted_key: MonomorphedFuncAdaptedKey, other_key: MonomorphedFuncKey) bool { | ||
| 270 | const other_key_args = ctx.mod.monomorphed_func_keys.items[other_key.args_index..][0..other_key.args_len]; | ||
| 271 | return adapted_key.func == other_key.func and std.mem.eql(InternPool.Index, adapted_key.args, other_key_args); | ||
| 272 | } | ||
| 273 | |||
| 274 | pub fn hash(_: @This(), adapted_key: MonomorphedFuncAdaptedKey) u64 { | ||
| 275 | return std.hash.Wyhash.hash(@intFromEnum(adapted_key.func), std.mem.sliceAsBytes(adapted_key.args)); | ||
| 276 | } | ||
| 277 | }; | ||
| 278 | |||
| 279 | pub const SetAlignStack = struct { | ||
| 280 | alignment: Alignment, | ||
| 281 | /// TODO: This needs to store a non-lazy source location for the case of an inline function | ||
| 282 | /// which does `@setAlignStack` (applying it to the caller). | ||
| 283 | src: LazySrcLoc, | ||
| 284 | }; | ||
| 285 | |||
| 286 | /// A `Module` has zero or one of these depending on whether `-femit-h` is enabled. | 216 | /// A `Module` has zero or one of these depending on whether `-femit-h` is enabled. |
| 287 | pub const GlobalEmitH = struct { | 217 | pub const GlobalEmitH = struct { |
| 288 | /// Where to put the output. | 218 | /// Where to put the output. |
| ... | @@ -366,6 +296,9 @@ pub const CaptureScope = struct { | ... | @@ -366,6 +296,9 @@ pub const CaptureScope = struct { |
| 366 | } | 296 | } |
| 367 | 297 | ||
| 368 | pub fn incRef(self: *CaptureScope) void { | 298 | pub fn incRef(self: *CaptureScope) void { |
| 299 | // TODO: wtf is reference counting doing in my beautiful codebase? 😠| ||
| 300 | // seriously though, let's change this to rely on InternPool garbage | ||
| 301 | // collection instead. | ||
| 369 | self.refs += 1; | 302 | self.refs += 1; |
| 370 | } | 303 | } |
| 371 | 304 | ||
| ... | @@ -625,13 +558,6 @@ pub const Decl = struct { | ... | @@ -625,13 +558,6 @@ pub const Decl = struct { |
| 625 | function_body, | 558 | function_body, |
| 626 | }; | 559 | }; |
| 627 | 560 | ||
| 628 | pub fn clearValues(decl: *Decl, mod: *Module) void { | ||
| 629 | if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| { | ||
| 630 | _ = mod.align_stack_fns.remove(func); | ||
| 631 | mod.destroyFunc(func); | ||
| 632 | } | ||
| 633 | } | ||
| 634 | |||
| 635 | /// This name is relative to the containing namespace of the decl. | 561 | /// This name is relative to the containing namespace of the decl. |
| 636 | /// The memory is owned by the containing File ZIR. | 562 | /// The memory is owned by the containing File ZIR. |
| 637 | pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 { | 563 | pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 { |
| ... | @@ -816,14 +742,18 @@ pub const Decl = struct { | ... | @@ -816,14 +742,18 @@ pub const Decl = struct { |
| 816 | return mod.typeToUnion(decl.val.toType()); | 742 | return mod.typeToUnion(decl.val.toType()); |
| 817 | } | 743 | } |
| 818 | 744 | ||
| 819 | /// If the Decl owns its value and it is a function, return it, | 745 | pub fn getOwnedFunction(decl: Decl, mod: *Module) ?InternPool.Key.Func { |
| 820 | /// otherwise null. | 746 | const i = decl.getOwnedFunctionIndex(); |
| 821 | pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn { | 747 | if (i == .none) return null; |
| 822 | return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod)); | 748 | return switch (mod.intern_pool.indexToKey(i)) { |
| 749 | .func => |func| func, | ||
| 750 | else => null, | ||
| 751 | }; | ||
| 823 | } | 752 | } |
| 824 | 753 | ||
| 825 | pub fn getOwnedFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex { | 754 | /// This returns an InternPool.Index even when the value is not a function. |
| 826 | return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none; | 755 | pub fn getOwnedFunctionIndex(decl: Decl) InternPool.Index { |
| 756 | return if (decl.owns_tv) decl.val.toIntern() else .none; | ||
| 827 | } | 757 | } |
| 828 | 758 | ||
| 829 | /// If the Decl owns its value and it is an extern function, returns it, | 759 | /// If the Decl owns its value and it is an extern function, returns it, |
| ... | @@ -1368,252 +1298,6 @@ pub const Union = struct { | ... | @@ -1368,252 +1298,6 @@ pub const Union = struct { |
| 1368 | } | 1298 | } |
| 1369 | }; | 1299 | }; |
| 1370 | 1300 | ||
| 1371 | /// Some extern function struct memory is owned by the Decl's TypedValue.Managed | ||
| 1372 | /// arena allocator. | ||
| 1373 | pub const ExternFn = struct { | ||
| 1374 | /// The Decl that corresponds to the function itself. | ||
| 1375 | owner_decl: Decl.Index, | ||
| 1376 | /// Library name if specified. | ||
| 1377 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. | ||
| 1378 | /// Allocated with Module's allocator; outlives the ZIR code. | ||
| 1379 | lib_name: ?[*:0]const u8, | ||
| 1380 | |||
| 1381 | pub fn deinit(extern_fn: *ExternFn, gpa: Allocator) void { | ||
| 1382 | if (extern_fn.lib_name) |lib_name| { | ||
| 1383 | gpa.free(mem.sliceTo(lib_name, 0)); | ||
| 1384 | } | ||
| 1385 | } | ||
| 1386 | }; | ||
| 1387 | |||
| 1388 | /// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. | ||
| 1389 | /// Extern functions do not have this data structure; they are represented by `ExternFn` | ||
| 1390 | /// instead. | ||
| 1391 | pub const Fn = struct { | ||
| 1392 | /// The Decl that corresponds to the function itself. | ||
| 1393 | owner_decl: Decl.Index, | ||
| 1394 | /// The ZIR instruction that is a function instruction. Use this to find | ||
| 1395 | /// the body. We store this rather than the body directly so that when ZIR | ||
| 1396 | /// is regenerated on update(), we can map this to the new corresponding | ||
| 1397 | /// ZIR instruction. | ||
| 1398 | zir_body_inst: Zir.Inst.Index, | ||
| 1399 | /// If this is not null, this function is a generic function instantiation, and | ||
| 1400 | /// there is a `TypedValue` here for each parameter of the function. | ||
| 1401 | /// Non-comptime parameters are marked with a `generic_poison` for the value. | ||
| 1402 | /// Non-anytype parameters are marked with a `generic_poison` for the type. | ||
| 1403 | /// These never have .generic_poison for the Type | ||
| 1404 | /// because the Type is needed to pass to `Type.eql` and for inserting comptime arguments | ||
| 1405 | /// into the inst_map when analyzing the body of a generic function instantiation. | ||
| 1406 | /// Instead, the is_anytype knowledge is communicated via `isAnytypeParam`. | ||
| 1407 | comptime_args: ?[*]TypedValue, | ||
| 1408 | |||
| 1409 | /// Precomputed hash for monomorphed_funcs. | ||
| 1410 | /// This is important because it may be accessed when resizing monomorphed_funcs | ||
| 1411 | /// while this Fn has already been added to the set, but does not have the | ||
| 1412 | /// owner_decl, comptime_args, or other fields populated yet. | ||
| 1413 | /// This field is undefined if comptime_args == null. | ||
| 1414 | hash: u64, | ||
| 1415 | |||
| 1416 | /// Relative to owner Decl. | ||
| 1417 | lbrace_line: u32, | ||
| 1418 | /// Relative to owner Decl. | ||
| 1419 | rbrace_line: u32, | ||
| 1420 | lbrace_column: u16, | ||
| 1421 | rbrace_column: u16, | ||
| 1422 | |||
| 1423 | /// When a generic function is instantiated, this value is inherited from the | ||
| 1424 | /// active Sema context. Importantly, this value is also updated when an existing | ||
| 1425 | /// generic function instantiation is found and called. | ||
| 1426 | branch_quota: u32, | ||
| 1427 | |||
| 1428 | /// If this is not none, this function is a generic function instantiation, and | ||
| 1429 | /// this is the generic function decl from which the instance was derived. | ||
| 1430 | /// This information is redundant with a combination of checking if comptime_args is | ||
| 1431 | /// not null and looking at the first decl dependency of owner_decl. This redundant | ||
| 1432 | /// information is useful for three reasons: | ||
| 1433 | /// 1. Improved perf of monomorphed_funcs when checking the eql() function because it | ||
| 1434 | /// can do two fewer pointer chases by grabbing the info from this field directly | ||
| 1435 | /// instead of accessing the decl and then the dependencies set. | ||
| 1436 | /// 2. While a generic function instantiation is being initialized, we need hash() | ||
| 1437 | /// and eql() to work before the initialization is complete. Completing the | ||
| 1438 | /// insertion into the decl dependency set has more fallible operations than simply | ||
| 1439 | /// setting this field. | ||
| 1440 | /// 3. I forgot what the third thing was while typing up the other two. | ||
| 1441 | generic_owner_decl: Decl.OptionalIndex, | ||
| 1442 | |||
| 1443 | state: Analysis, | ||
| 1444 | is_cold: bool = false, | ||
| 1445 | is_noinline: bool, | ||
| 1446 | calls_or_awaits_errorable_fn: bool = false, | ||
| 1447 | |||
| 1448 | pub const Index = enum(u32) { | ||
| 1449 | _, | ||
| 1450 | |||
| 1451 | pub fn toOptional(i: Index) OptionalIndex { | ||
| 1452 | return @as(OptionalIndex, @enumFromInt(@intFromEnum(i))); | ||
| 1453 | } | ||
| 1454 | }; | ||
| 1455 | |||
| 1456 | pub const OptionalIndex = enum(u32) { | ||
| 1457 | none = std.math.maxInt(u32), | ||
| 1458 | _, | ||
| 1459 | |||
| 1460 | pub fn init(oi: ?Index) OptionalIndex { | ||
| 1461 | return @as(OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none))); | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | pub fn unwrap(oi: OptionalIndex) ?Index { | ||
| 1465 | if (oi == .none) return null; | ||
| 1466 | return @as(Index, @enumFromInt(@intFromEnum(oi))); | ||
| 1467 | } | ||
| 1468 | }; | ||
| 1469 | |||
| 1470 | pub const Analysis = enum { | ||
| 1471 | /// This function has not yet undergone analysis, because we have not | ||
| 1472 | /// seen a potential runtime call. It may be analyzed in future. | ||
| 1473 | none, | ||
| 1474 | /// Analysis for this function has been queued, but not yet completed. | ||
| 1475 | queued, | ||
| 1476 | /// This function intentionally only has ZIR generated because it is marked | ||
| 1477 | /// inline, which means no runtime version of the function will be generated. | ||
| 1478 | inline_only, | ||
| 1479 | in_progress, | ||
| 1480 | /// There will be a corresponding ErrorMsg in Module.failed_decls | ||
| 1481 | sema_failure, | ||
| 1482 | /// This Fn might be OK but it depends on another Decl which did not | ||
| 1483 | /// successfully complete semantic analysis. | ||
| 1484 | dependency_failure, | ||
| 1485 | success, | ||
| 1486 | }; | ||
| 1487 | |||
| 1488 | /// This struct is used to keep track of any dependencies related to functions instances | ||
| 1489 | /// that return inferred error sets. Note that a function may be associated to | ||
| 1490 | /// multiple different error sets, for example an inferred error set which | ||
| 1491 | /// this function returns, but also any inferred error sets of called inline | ||
| 1492 | /// or comptime functions. | ||
| 1493 | pub const InferredErrorSet = struct { | ||
| 1494 | /// The function from which this error set originates. | ||
| 1495 | func: Fn.Index, | ||
| 1496 | |||
| 1497 | /// All currently known errors that this error set contains. This includes | ||
| 1498 | /// direct additions via `return error.Foo;`, and possibly also errors that | ||
| 1499 | /// are returned from any dependent functions. When the inferred error set is | ||
| 1500 | /// fully resolved, this map contains all the errors that the function might return. | ||
| 1501 | errors: NameMap = .{}, | ||
| 1502 | |||
| 1503 | /// Other inferred error sets which this inferred error set should include. | ||
| 1504 | inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{}, | ||
| 1505 | |||
| 1506 | /// Whether the function returned anyerror. This is true if either of | ||
| 1507 | /// the dependent functions returns anyerror. | ||
| 1508 | is_anyerror: bool = false, | ||
| 1509 | |||
| 1510 | /// Whether this error set is already fully resolved. If true, resolving | ||
| 1511 | /// can skip resolving any dependents of this inferred error set. | ||
| 1512 | is_resolved: bool = false, | ||
| 1513 | |||
| 1514 | pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void); | ||
| 1515 | |||
| 1516 | pub const Index = enum(u32) { | ||
| 1517 | _, | ||
| 1518 | |||
| 1519 | pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex { | ||
| 1520 | return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(i))); | ||
| 1521 | } | ||
| 1522 | }; | ||
| 1523 | |||
| 1524 | pub const OptionalIndex = enum(u32) { | ||
| 1525 | none = std.math.maxInt(u32), | ||
| 1526 | _, | ||
| 1527 | |||
| 1528 | pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex { | ||
| 1529 | return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none))); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index { | ||
| 1533 | if (oi == .none) return null; | ||
| 1534 | return @as(InferredErrorSet.Index, @enumFromInt(@intFromEnum(oi))); | ||
| 1535 | } | ||
| 1536 | }; | ||
| 1537 | |||
| 1538 | pub fn addErrorSet( | ||
| 1539 | self: *InferredErrorSet, | ||
| 1540 | err_set_ty: Type, | ||
| 1541 | ip: *InternPool, | ||
| 1542 | gpa: Allocator, | ||
| 1543 | ) !void { | ||
| 1544 | switch (err_set_ty.toIntern()) { | ||
| 1545 | .anyerror_type => { | ||
| 1546 | self.is_anyerror = true; | ||
| 1547 | }, | ||
| 1548 | else => switch (ip.indexToKey(err_set_ty.toIntern())) { | ||
| 1549 | .error_set_type => |error_set_type| { | ||
| 1550 | for (error_set_type.names) |name| { | ||
| 1551 | try self.errors.put(gpa, name, {}); | ||
| 1552 | } | ||
| 1553 | }, | ||
| 1554 | .inferred_error_set_type => |ies_index| { | ||
| 1555 | try self.inferred_error_sets.put(gpa, ies_index, {}); | ||
| 1556 | }, | ||
| 1557 | else => unreachable, | ||
| 1558 | }, | ||
| 1559 | } | ||
| 1560 | } | ||
| 1561 | }; | ||
| 1562 | |||
| 1563 | pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool { | ||
| 1564 | const file = mod.declPtr(func.owner_decl).getFileScope(mod); | ||
| 1565 | |||
| 1566 | const tags = file.zir.instructions.items(.tag); | ||
| 1567 | |||
| 1568 | const param_body = file.zir.getParamBody(func.zir_body_inst); | ||
| 1569 | const param = param_body[index]; | ||
| 1570 | |||
| 1571 | return switch (tags[param]) { | ||
| 1572 | .param, .param_comptime => false, | ||
| 1573 | .param_anytype, .param_anytype_comptime => true, | ||
| 1574 | else => unreachable, | ||
| 1575 | }; | ||
| 1576 | } | ||
| 1577 | |||
| 1578 | pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 { | ||
| 1579 | const file = mod.declPtr(func.owner_decl).getFileScope(mod); | ||
| 1580 | |||
| 1581 | const tags = file.zir.instructions.items(.tag); | ||
| 1582 | const data = file.zir.instructions.items(.data); | ||
| 1583 | |||
| 1584 | const param_body = file.zir.getParamBody(func.zir_body_inst); | ||
| 1585 | const param = param_body[index]; | ||
| 1586 | |||
| 1587 | return switch (tags[param]) { | ||
| 1588 | .param, .param_comptime => blk: { | ||
| 1589 | const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index); | ||
| 1590 | break :blk file.zir.nullTerminatedString(extra.data.name); | ||
| 1591 | }, | ||
| 1592 | .param_anytype, .param_anytype_comptime => blk: { | ||
| 1593 | const param_data = data[param].str_tok; | ||
| 1594 | break :blk param_data.get(file.zir); | ||
| 1595 | }, | ||
| 1596 | else => unreachable, | ||
| 1597 | }; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool { | ||
| 1601 | const owner_decl = mod.declPtr(func.owner_decl); | ||
| 1602 | const zir = owner_decl.getFileScope(mod).zir; | ||
| 1603 | const zir_tags = zir.instructions.items(.tag); | ||
| 1604 | switch (zir_tags[func.zir_body_inst]) { | ||
| 1605 | .func => return false, | ||
| 1606 | .func_inferred => return true, | ||
| 1607 | .func_fancy => { | ||
| 1608 | const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node; | ||
| 1609 | const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); | ||
| 1610 | return extra.data.bits.is_inferred_error; | ||
| 1611 | }, | ||
| 1612 | else => unreachable, | ||
| 1613 | } | ||
| 1614 | } | ||
| 1615 | }; | ||
| 1616 | |||
| 1617 | pub const DeclAdapter = struct { | 1301 | pub const DeclAdapter = struct { |
| 1618 | mod: *Module, | 1302 | mod: *Module, |
| 1619 | 1303 | ||
| ... | @@ -1638,12 +1322,10 @@ pub const Namespace = struct { | ... | @@ -1638,12 +1322,10 @@ pub const Namespace = struct { |
| 1638 | /// Direct children of the namespace. Used during an update to detect | 1322 | /// Direct children of the namespace. Used during an update to detect |
| 1639 | /// which decls have been added/removed from source. | 1323 | /// which decls have been added/removed from source. |
| 1640 | /// Declaration order is preserved via entry order. | 1324 | /// Declaration order is preserved via entry order. |
| 1641 | /// Key memory is owned by `decl.name`. | 1325 | /// These are only declarations named directly by the AST; anonymous |
| 1642 | /// Anonymous decls are not stored here; they are kept in `anon_decls` instead. | 1326 | /// declarations are not stored here. |
| 1643 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, | 1327 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, |
| 1644 | 1328 | ||
| 1645 | anon_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | ||
| 1646 | |||
| 1647 | /// Key is usingnamespace Decl itself. To find the namespace being included, | 1329 | /// Key is usingnamespace Decl itself. To find the namespace being included, |
| 1648 | /// the Decl Value has to be resolved as a Type which has a Namespace. | 1330 | /// the Decl Value has to be resolved as a Type which has a Namespace. |
| 1649 | /// Value is whether the usingnamespace decl is marked `pub`. | 1331 | /// Value is whether the usingnamespace decl is marked `pub`. |
| ... | @@ -1698,18 +1380,11 @@ pub const Namespace = struct { | ... | @@ -1698,18 +1380,11 @@ pub const Namespace = struct { |
| 1698 | var decls = ns.decls; | 1380 | var decls = ns.decls; |
| 1699 | ns.decls = .{}; | 1381 | ns.decls = .{}; |
| 1700 | 1382 | ||
| 1701 | var anon_decls = ns.anon_decls; | ||
| 1702 | ns.anon_decls = .{}; | ||
| 1703 | |||
| 1704 | for (decls.keys()) |decl_index| { | 1383 | for (decls.keys()) |decl_index| { |
| 1705 | mod.destroyDecl(decl_index); | 1384 | mod.destroyDecl(decl_index); |
| 1706 | } | 1385 | } |
| 1707 | decls.deinit(gpa); | 1386 | decls.deinit(gpa); |
| 1708 | 1387 | ||
| 1709 | for (anon_decls.keys()) |key| { | ||
| 1710 | mod.destroyDecl(key); | ||
| 1711 | } | ||
| 1712 | anon_decls.deinit(gpa); | ||
| 1713 | ns.usingnamespace_set.deinit(gpa); | 1388 | ns.usingnamespace_set.deinit(gpa); |
| 1714 | } | 1389 | } |
| 1715 | 1390 | ||
| ... | @@ -1723,9 +1398,6 @@ pub const Namespace = struct { | ... | @@ -1723,9 +1398,6 @@ pub const Namespace = struct { |
| 1723 | var decls = ns.decls; | 1398 | var decls = ns.decls; |
| 1724 | ns.decls = .{}; | 1399 | ns.decls = .{}; |
| 1725 | 1400 | ||
| 1726 | var anon_decls = ns.anon_decls; | ||
| 1727 | ns.anon_decls = .{}; | ||
| 1728 | |||
| 1729 | // TODO rework this code to not panic on OOM. | 1401 | // TODO rework this code to not panic on OOM. |
| 1730 | // (might want to coordinate with the clearDecl function) | 1402 | // (might want to coordinate with the clearDecl function) |
| 1731 | 1403 | ||
| ... | @@ -1735,12 +1407,6 @@ pub const Namespace = struct { | ... | @@ -1735,12 +1407,6 @@ pub const Namespace = struct { |
| 1735 | } | 1407 | } |
| 1736 | decls.deinit(gpa); | 1408 | decls.deinit(gpa); |
| 1737 | 1409 | ||
| 1738 | for (anon_decls.keys()) |child_decl| { | ||
| 1739 | mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); | ||
| 1740 | mod.destroyDecl(child_decl); | ||
| 1741 | } | ||
| 1742 | anon_decls.deinit(gpa); | ||
| 1743 | |||
| 1744 | ns.usingnamespace_set.deinit(gpa); | 1410 | ns.usingnamespace_set.deinit(gpa); |
| 1745 | } | 1411 | } |
| 1746 | 1412 | ||
| ... | @@ -2155,8 +1821,8 @@ pub const SrcLoc = struct { | ... | @@ -2155,8 +1821,8 @@ pub const SrcLoc = struct { |
| 2155 | return tree.firstToken(src_loc.parent_decl_node); | 1821 | return tree.firstToken(src_loc.parent_decl_node); |
| 2156 | } | 1822 | } |
| 2157 | 1823 | ||
| 2158 | pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.TokenIndex { | 1824 | pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index { |
| 2159 | return @as(Ast.Node.Index, @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node)))); | 1825 | return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node))); |
| 2160 | } | 1826 | } |
| 2161 | 1827 | ||
| 2162 | pub const Span = struct { | 1828 | pub const Span = struct { |
| ... | @@ -2468,6 +2134,37 @@ pub const SrcLoc = struct { | ... | @@ -2468,6 +2134,37 @@ pub const SrcLoc = struct { |
| 2468 | } | 2134 | } |
| 2469 | } else unreachable; | 2135 | } else unreachable; |
| 2470 | }, | 2136 | }, |
| 2137 | .call_arg => |call_arg| { | ||
| 2138 | const tree = try src_loc.file_scope.getTree(gpa); | ||
| 2139 | const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset); | ||
| 2140 | var buf: [1]Ast.Node.Index = undefined; | ||
| 2141 | const call_full = tree.fullCall(&buf, node).?; | ||
| 2142 | const src_node = call_full.ast.params[call_arg.arg_index]; | ||
| 2143 | return nodeToSpan(tree, src_node); | ||
| 2144 | }, | ||
| 2145 | .fn_proto_param => |fn_proto_param| { | ||
| 2146 | const tree = try src_loc.file_scope.getTree(gpa); | ||
| 2147 | const node = src_loc.declRelativeToNodeIndex(fn_proto_param.fn_proto_node_offset); | ||
| 2148 | var buf: [1]Ast.Node.Index = undefined; | ||
| 2149 | const full = tree.fullFnProto(&buf, node).?; | ||
| 2150 | var it = full.iterate(tree); | ||
| 2151 | var i: usize = 0; | ||
| 2152 | while (it.next()) |param| : (i += 1) { | ||
| 2153 | if (i == fn_proto_param.param_index) { | ||
| 2154 | if (param.anytype_ellipsis3) |token| return tokenToSpan(tree, token); | ||
| 2155 | const first_token = param.comptime_noalias orelse | ||
| 2156 | param.name_token orelse | ||
| 2157 | tree.firstToken(param.type_expr); | ||
| 2158 | return tokensToSpan( | ||
| 2159 | tree, | ||
| 2160 | first_token, | ||
| 2161 | tree.lastToken(param.type_expr), | ||
| 2162 | first_token, | ||
| 2163 | ); | ||
| 2164 | } | ||
| 2165 | } | ||
| 2166 | unreachable; | ||
| 2167 | }, | ||
| 2471 | .node_offset_bin_lhs => |node_off| { | 2168 | .node_offset_bin_lhs => |node_off| { |
| 2472 | const tree = try src_loc.file_scope.getTree(gpa); | 2169 | const tree = try src_loc.file_scope.getTree(gpa); |
| 2473 | const node = src_loc.declRelativeToNodeIndex(node_off); | 2170 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| ... | @@ -2820,6 +2517,10 @@ pub const SrcLoc = struct { | ... | @@ -2820,6 +2517,10 @@ pub const SrcLoc = struct { |
| 2820 | ); | 2517 | ); |
| 2821 | } | 2518 | } |
| 2822 | 2519 | ||
| 2520 | fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span { | ||
| 2521 | return tokensToSpan(tree, token, token, token); | ||
| 2522 | } | ||
| 2523 | |||
| 2823 | fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { | 2524 | fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { |
| 2824 | const token_starts = tree.tokens.items(.start); | 2525 | const token_starts = tree.tokens.items(.start); |
| 2825 | var start_tok = start; | 2526 | var start_tok = start; |
| ... | @@ -3146,6 +2847,21 @@ pub const LazySrcLoc = union(enum) { | ... | @@ -3146,6 +2847,21 @@ pub const LazySrcLoc = union(enum) { |
| 3146 | /// Next, navigate to the corresponding capture. | 2847 | /// Next, navigate to the corresponding capture. |
| 3147 | /// The Decl is determined contextually. | 2848 | /// The Decl is determined contextually. |
| 3148 | for_capture_from_input: i32, | 2849 | for_capture_from_input: i32, |
| 2850 | /// The source location points to the argument node of a function call. | ||
| 2851 | call_arg: struct { | ||
| 2852 | decl: Decl.Index, | ||
| 2853 | /// Points to the function call AST node. | ||
| 2854 | call_node_offset: i32, | ||
| 2855 | /// The index of the argument the source location points to. | ||
| 2856 | arg_index: u32, | ||
| 2857 | }, | ||
| 2858 | fn_proto_param: struct { | ||
| 2859 | decl: Decl.Index, | ||
| 2860 | /// Points to the function prototype AST node. | ||
| 2861 | fn_proto_node_offset: i32, | ||
| 2862 | /// The index of the parameter the source location points to. | ||
| 2863 | param_index: u32, | ||
| 2864 | }, | ||
| 3149 | 2865 | ||
| 3150 | pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; | 2866 | pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; |
| 3151 | 2867 | ||
| ... | @@ -3240,6 +2956,13 @@ pub const LazySrcLoc = union(enum) { | ... | @@ -3240,6 +2956,13 @@ pub const LazySrcLoc = union(enum) { |
| 3240 | .parent_decl_node = decl.src_node, | 2956 | .parent_decl_node = decl.src_node, |
| 3241 | .lazy = lazy, | 2957 | .lazy = lazy, |
| 3242 | }, | 2958 | }, |
| 2959 | inline .call_arg, | ||
| 2960 | .fn_proto_param, | ||
| 2961 | => |x| .{ | ||
| 2962 | .file_scope = decl.getFileScope(mod), | ||
| 2963 | .parent_decl_node = mod.declPtr(x.decl).src_node, | ||
| 2964 | .lazy = lazy, | ||
| 2965 | }, | ||
| 3243 | }; | 2966 | }; |
| 3244 | } | 2967 | } |
| 3245 | }; | 2968 | }; |
| ... | @@ -3373,17 +3096,10 @@ pub fn deinit(mod: *Module) void { | ... | @@ -3373,17 +3096,10 @@ pub fn deinit(mod: *Module) void { |
| 3373 | mod.global_error_set.deinit(gpa); | 3096 | mod.global_error_set.deinit(gpa); |
| 3374 | 3097 | ||
| 3375 | mod.test_functions.deinit(gpa); | 3098 | mod.test_functions.deinit(gpa); |
| 3376 | mod.align_stack_fns.deinit(gpa); | ||
| 3377 | mod.monomorphed_funcs.deinit(gpa); | ||
| 3378 | 3099 | ||
| 3379 | mod.decls_free_list.deinit(gpa); | ||
| 3380 | mod.allocated_decls.deinit(gpa); | ||
| 3381 | mod.global_assembly.deinit(gpa); | 3100 | mod.global_assembly.deinit(gpa); |
| 3382 | mod.reference_table.deinit(gpa); | 3101 | mod.reference_table.deinit(gpa); |
| 3383 | 3102 | ||
| 3384 | mod.namespaces_free_list.deinit(gpa); | ||
| 3385 | mod.allocated_namespaces.deinit(gpa); | ||
| 3386 | |||
| 3387 | mod.memoized_decls.deinit(gpa); | 3103 | mod.memoized_decls.deinit(gpa); |
| 3388 | mod.intern_pool.deinit(gpa); | 3104 | mod.intern_pool.deinit(gpa); |
| 3389 | mod.tmp_hack_arena.deinit(); | 3105 | mod.tmp_hack_arena.deinit(); |
| ... | @@ -3391,6 +3107,8 @@ pub fn deinit(mod: *Module) void { | ... | @@ -3391,6 +3107,8 @@ pub fn deinit(mod: *Module) void { |
| 3391 | 3107 | ||
| 3392 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | 3108 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 3393 | const gpa = mod.gpa; | 3109 | const gpa = mod.gpa; |
| 3110 | const ip = &mod.intern_pool; | ||
| 3111 | |||
| 3394 | { | 3112 | { |
| 3395 | const decl = mod.declPtr(decl_index); | 3113 | const decl = mod.declPtr(decl_index); |
| 3396 | _ = mod.test_functions.swapRemove(decl_index); | 3114 | _ = mod.test_functions.swapRemove(decl_index); |
| ... | @@ -3407,15 +3125,12 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | ... | @@ -3407,15 +3125,12 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 3407 | } | 3125 | } |
| 3408 | } | 3126 | } |
| 3409 | if (decl.src_scope) |scope| scope.decRef(gpa); | 3127 | if (decl.src_scope) |scope| scope.decRef(gpa); |
| 3410 | decl.clearValues(mod); | ||
| 3411 | decl.dependants.deinit(gpa); | 3128 | decl.dependants.deinit(gpa); |
| 3412 | decl.dependencies.deinit(gpa); | 3129 | decl.dependencies.deinit(gpa); |
| 3413 | decl.* = undefined; | ||
| 3414 | } | 3130 | } |
| 3415 | mod.decls_free_list.append(gpa, decl_index) catch { | 3131 | |
| 3416 | // In order to keep `destroyDecl` a non-fallible function, we ignore memory | 3132 | ip.destroyDecl(gpa, decl_index); |
| 3417 | // allocation failures here, instead leaking the Decl until garbage collection. | 3133 | |
| 3418 | }; | ||
| 3419 | if (mod.emit_h) |mod_emit_h| { | 3134 | if (mod.emit_h) |mod_emit_h| { |
| 3420 | const decl_emit_h = mod_emit_h.declPtr(decl_index); | 3135 | const decl_emit_h = mod_emit_h.declPtr(decl_index); |
| 3421 | decl_emit_h.fwd_decl.deinit(gpa); | 3136 | decl_emit_h.fwd_decl.deinit(gpa); |
| ... | @@ -3424,11 +3139,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | ... | @@ -3424,11 +3139,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 3424 | } | 3139 | } |
| 3425 | 3140 | ||
| 3426 | pub fn declPtr(mod: *Module, index: Decl.Index) *Decl { | 3141 | pub fn declPtr(mod: *Module, index: Decl.Index) *Decl { |
| 3427 | return mod.allocated_decls.at(@intFromEnum(index)); | 3142 | return mod.intern_pool.declPtr(index); |
| 3428 | } | 3143 | } |
| 3429 | 3144 | ||
| 3430 | pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace { | 3145 | pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace { |
| 3431 | return mod.allocated_namespaces.at(@intFromEnum(index)); | 3146 | return mod.intern_pool.namespacePtr(index); |
| 3432 | } | 3147 | } |
| 3433 | 3148 | ||
| 3434 | pub fn unionPtr(mod: *Module, index: Union.Index) *Union { | 3149 | pub fn unionPtr(mod: *Module, index: Union.Index) *Union { |
| ... | @@ -3439,14 +3154,6 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct { | ... | @@ -3439,14 +3154,6 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct { |
| 3439 | return mod.intern_pool.structPtr(index); | 3154 | return mod.intern_pool.structPtr(index); |
| 3440 | } | 3155 | } |
| 3441 | 3156 | ||
| 3442 | pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn { | ||
| 3443 | return mod.intern_pool.funcPtr(index); | ||
| 3444 | } | ||
| 3445 | |||
| 3446 | pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet { | ||
| 3447 | return mod.intern_pool.inferredErrorSetPtr(index); | ||
| 3448 | } | ||
| 3449 | |||
| 3450 | pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace { | 3157 | pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace { |
| 3451 | return mod.namespacePtr(index.unwrap() orelse return null); | 3158 | return mod.namespacePtr(index.unwrap() orelse return null); |
| 3452 | } | 3159 | } |
| ... | @@ -3457,10 +3164,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct { | ... | @@ -3457,10 +3164,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct { |
| 3457 | return mod.structPtr(index.unwrap() orelse return null); | 3164 | return mod.structPtr(index.unwrap() orelse return null); |
| 3458 | } | 3165 | } |
| 3459 | 3166 | ||
| 3460 | pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn { | ||
| 3461 | return mod.funcPtr(index.unwrap() orelse return null); | ||
| 3462 | } | ||
| 3463 | |||
| 3464 | /// Returns true if and only if the Decl is the top level struct associated with a File. | 3167 | /// Returns true if and only if the Decl is the top level struct associated with a File. |
| 3465 | pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { | 3168 | pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { |
| 3466 | const decl = mod.declPtr(decl_index); | 3169 | const decl = mod.declPtr(decl_index); |
| ... | @@ -3881,6 +3584,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { | ... | @@ -3881,6 +3584,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 3881 | // to re-generate ZIR for the File. | 3584 | // to re-generate ZIR for the File. |
| 3882 | try file.outdated_decls.append(gpa, root_decl); | 3585 | try file.outdated_decls.append(gpa, root_decl); |
| 3883 | 3586 | ||
| 3587 | const ip = &mod.intern_pool; | ||
| 3588 | |||
| 3884 | while (decl_stack.popOrNull()) |decl_index| { | 3589 | while (decl_stack.popOrNull()) |decl_index| { |
| 3885 | const decl = mod.declPtr(decl_index); | 3590 | const decl = mod.declPtr(decl_index); |
| 3886 | // Anonymous decls and the root decl have this set to 0. We still need | 3591 | // Anonymous decls and the root decl have this set to 0. We still need |
| ... | @@ -3918,7 +3623,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { | ... | @@ -3918,7 +3623,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 3918 | } | 3623 | } |
| 3919 | 3624 | ||
| 3920 | if (decl.getOwnedFunction(mod)) |func| { | 3625 | if (decl.getOwnedFunction(mod)) |func| { |
| 3921 | func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse { | 3626 | func.zirBodyInst(ip).* = inst_map.get(func.zir_body_inst) orelse { |
| 3922 | try file.deleted_decls.append(gpa, decl_index); | 3627 | try file.deleted_decls.append(gpa, decl_index); |
| 3923 | continue; | 3628 | continue; |
| 3924 | }; | 3629 | }; |
| ... | @@ -3928,9 +3633,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { | ... | @@ -3928,9 +3633,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 3928 | for (namespace.decls.keys()) |sub_decl| { | 3633 | for (namespace.decls.keys()) |sub_decl| { |
| 3929 | try decl_stack.append(gpa, sub_decl); | 3634 | try decl_stack.append(gpa, sub_decl); |
| 3930 | } | 3635 | } |
| 3931 | for (namespace.anon_decls.keys()) |sub_decl| { | ||
| 3932 | try decl_stack.append(gpa, sub_decl); | ||
| 3933 | } | ||
| 3934 | } | 3636 | } |
| 3935 | } | 3637 | } |
| 3936 | } | 3638 | } |
| ... | @@ -4101,11 +3803,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -4101,11 +3803,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 4101 | // prior to re-analysis. | 3803 | // prior to re-analysis. |
| 4102 | try mod.deleteDeclExports(decl_index); | 3804 | try mod.deleteDeclExports(decl_index); |
| 4103 | 3805 | ||
| 4104 | // Similarly, `@setAlignStack` invocations will be re-discovered. | ||
| 4105 | if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| { | ||
| 4106 | _ = mod.align_stack_fns.remove(func); | ||
| 4107 | } | ||
| 4108 | |||
| 4109 | // Dependencies will be re-discovered, so we remove them here prior to re-analysis. | 3806 | // Dependencies will be re-discovered, so we remove them here prior to re-analysis. |
| 4110 | for (decl.dependencies.keys()) |dep_index| { | 3807 | for (decl.dependencies.keys()) |dep_index| { |
| 4111 | const dep = mod.declPtr(dep_index); | 3808 | const dep = mod.declPtr(dep_index); |
| ... | @@ -4189,11 +3886,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -4189,11 +3886,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 4189 | } | 3886 | } |
| 4190 | } | 3887 | } |
| 4191 | 3888 | ||
| 4192 | pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void { | 3889 | pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void { |
| 4193 | const tracy = trace(@src()); | 3890 | const tracy = trace(@src()); |
| 4194 | defer tracy.end(); | 3891 | defer tracy.end(); |
| 4195 | 3892 | ||
| 4196 | const func = mod.funcPtr(func_index); | 3893 | const ip = &mod.intern_pool; |
| 3894 | const func = mod.funcInfo(func_index); | ||
| 4197 | const decl_index = func.owner_decl; | 3895 | const decl_index = func.owner_decl; |
| 4198 | const decl = mod.declPtr(decl_index); | 3896 | const decl = mod.declPtr(decl_index); |
| 4199 | 3897 | ||
| ... | @@ -4211,7 +3909,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void | ... | @@ -4211,7 +3909,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void |
| 4211 | => return error.AnalysisFail, | 3909 | => return error.AnalysisFail, |
| 4212 | 3910 | ||
| 4213 | .complete, .codegen_failure_retryable => { | 3911 | .complete, .codegen_failure_retryable => { |
| 4214 | switch (func.state) { | 3912 | switch (func.analysis(ip).state) { |
| 4215 | .sema_failure, .dependency_failure => return error.AnalysisFail, | 3913 | .sema_failure, .dependency_failure => return error.AnalysisFail, |
| 4216 | .none, .queued => {}, | 3914 | .none, .queued => {}, |
| 4217 | .in_progress => unreachable, | 3915 | .in_progress => unreachable, |
| ... | @@ -4227,11 +3925,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void | ... | @@ -4227,11 +3925,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void |
| 4227 | 3925 | ||
| 4228 | var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) { | 3926 | var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) { |
| 4229 | error.AnalysisFail => { | 3927 | error.AnalysisFail => { |
| 4230 | if (func.state == .in_progress) { | 3928 | if (func.analysis(ip).state == .in_progress) { |
| 4231 | // If this decl caused the compile error, the analysis field would | 3929 | // If this decl caused the compile error, the analysis field would |
| 4232 | // be changed to indicate it was this Decl's fault. Because this | 3930 | // be changed to indicate it was this Decl's fault. Because this |
| 4233 | // did not happen, we infer here that it was a dependency failure. | 3931 | // did not happen, we infer here that it was a dependency failure. |
| 4234 | func.state = .dependency_failure; | 3932 | func.analysis(ip).state = .dependency_failure; |
| 4235 | } | 3933 | } |
| 4236 | return error.AnalysisFail; | 3934 | return error.AnalysisFail; |
| 4237 | }, | 3935 | }, |
| ... | @@ -4251,14 +3949,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void | ... | @@ -4251,14 +3949,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void |
| 4251 | 3949 | ||
| 4252 | if (no_bin_file and !dump_air and !dump_llvm_ir) return; | 3950 | if (no_bin_file and !dump_air and !dump_llvm_ir) return; |
| 4253 | 3951 | ||
| 4254 | var liveness = try Liveness.analyze(gpa, air, &mod.intern_pool); | 3952 | var liveness = try Liveness.analyze(gpa, air, ip); |
| 4255 | defer liveness.deinit(gpa); | 3953 | defer liveness.deinit(gpa); |
| 4256 | 3954 | ||
| 4257 | if (dump_air) { | 3955 | if (dump_air) { |
| 4258 | const fqn = try decl.getFullyQualifiedName(mod); | 3956 | const fqn = try decl.getFullyQualifiedName(mod); |
| 4259 | std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(&mod.intern_pool)}); | 3957 | std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}); |
| 4260 | @import("print_air.zig").dump(mod, air, liveness); | 3958 | @import("print_air.zig").dump(mod, air, liveness); |
| 4261 | std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(&mod.intern_pool)}); | 3959 | std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}); |
| 4262 | } | 3960 | } |
| 4263 | 3961 | ||
| 4264 | if (std.debug.runtime_safety) { | 3962 | if (std.debug.runtime_safety) { |
| ... | @@ -4266,7 +3964,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void | ... | @@ -4266,7 +3964,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void |
| 4266 | .gpa = gpa, | 3964 | .gpa = gpa, |
| 4267 | .air = air, | 3965 | .air = air, |
| 4268 | .liveness = liveness, | 3966 | .liveness = liveness, |
| 4269 | .intern_pool = &mod.intern_pool, | 3967 | .intern_pool = ip, |
| 4270 | }; | 3968 | }; |
| 4271 | defer verify.deinit(); | 3969 | defer verify.deinit(); |
| 4272 | 3970 | ||
| ... | @@ -4321,8 +4019,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void | ... | @@ -4321,8 +4019,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void |
| 4321 | /// analyzed, and for ensuring it can exist at runtime (see | 4019 | /// analyzed, and for ensuring it can exist at runtime (see |
| 4322 | /// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body | 4020 | /// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body |
| 4323 | /// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`. | 4021 | /// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`. |
| 4324 | pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void { | 4022 | pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) !void { |
| 4325 | const func = mod.funcPtr(func_index); | 4023 | const ip = &mod.intern_pool; |
| 4024 | const func = mod.funcInfo(func_index); | ||
| 4326 | const decl_index = func.owner_decl; | 4025 | const decl_index = func.owner_decl; |
| 4327 | const decl = mod.declPtr(decl_index); | 4026 | const decl = mod.declPtr(decl_index); |
| 4328 | 4027 | ||
| ... | @@ -4348,7 +4047,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void { | ... | @@ -4348,7 +4047,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void { |
| 4348 | 4047 | ||
| 4349 | assert(decl.has_tv); | 4048 | assert(decl.has_tv); |
| 4350 | 4049 | ||
| 4351 | switch (func.state) { | 4050 | switch (func.analysis(ip).state) { |
| 4352 | .none => {}, | 4051 | .none => {}, |
| 4353 | .queued => return, | 4052 | .queued => return, |
| 4354 | // As above, we don't need to forward errors here. | 4053 | // As above, we don't need to forward errors here. |
| ... | @@ -4366,7 +4065,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void { | ... | @@ -4366,7 +4065,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void { |
| 4366 | // since the last update | 4065 | // since the last update |
| 4367 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); | 4066 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); |
| 4368 | } | 4067 | } |
| 4369 | func.state = .queued; | 4068 | func.analysis(ip).state = .queued; |
| 4370 | } | 4069 | } |
| 4371 | 4070 | ||
| 4372 | pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void { | 4071 | pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void { |
| ... | @@ -4490,10 +4189,9 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -4490,10 +4189,9 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4490 | .code = file.zir, | 4189 | .code = file.zir, |
| 4491 | .owner_decl = new_decl, | 4190 | .owner_decl = new_decl, |
| 4492 | .owner_decl_index = new_decl_index, | 4191 | .owner_decl_index = new_decl_index, |
| 4493 | .func = null, | ||
| 4494 | .func_index = .none, | 4192 | .func_index = .none, |
| 4495 | .fn_ret_ty = Type.void, | 4193 | .fn_ret_ty = Type.void, |
| 4496 | .owner_func = null, | 4194 | .fn_ret_ty_ies = null, |
| 4497 | .owner_func_index = .none, | 4195 | .owner_func_index = .none, |
| 4498 | .comptime_mutable_decls = &comptime_mutable_decls, | 4196 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 4499 | }; | 4197 | }; |
| ... | @@ -4573,10 +4271,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4573,10 +4271,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4573 | .code = zir, | 4271 | .code = zir, |
| 4574 | .owner_decl = decl, | 4272 | .owner_decl = decl, |
| 4575 | .owner_decl_index = decl_index, | 4273 | .owner_decl_index = decl_index, |
| 4576 | .func = null, | ||
| 4577 | .func_index = .none, | 4274 | .func_index = .none, |
| 4578 | .fn_ret_ty = Type.void, | 4275 | .fn_ret_ty = Type.void, |
| 4579 | .owner_func = null, | 4276 | .fn_ret_ty_ies = null, |
| 4580 | .owner_func_index = .none, | 4277 | .owner_func_index = .none, |
| 4581 | .comptime_mutable_decls = &comptime_mutable_decls, | 4278 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 4582 | }; | 4279 | }; |
| ... | @@ -4608,10 +4305,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4608,10 +4305,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4608 | .inlining = null, | 4305 | .inlining = null, |
| 4609 | .is_comptime = true, | 4306 | .is_comptime = true, |
| 4610 | }; | 4307 | }; |
| 4611 | defer { | 4308 | defer block_scope.instructions.deinit(gpa); |
| 4612 | block_scope.instructions.deinit(gpa); | ||
| 4613 | block_scope.params.deinit(gpa); | ||
| 4614 | } | ||
| 4615 | 4309 | ||
| 4616 | const zir_block_index = decl.zirBlockIndex(mod); | 4310 | const zir_block_index = decl.zirBlockIndex(mod); |
| 4617 | const inst_data = zir_datas[zir_block_index].pl_node; | 4311 | const inst_data = zir_datas[zir_block_index].pl_node; |
| ... | @@ -4658,48 +4352,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4658,48 +4352,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4658 | return true; | 4352 | return true; |
| 4659 | } | 4353 | } |
| 4660 | 4354 | ||
| 4661 | if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| { | 4355 | const ip = &mod.intern_pool; |
| 4662 | const func = mod.funcPtr(func_index); | 4356 | switch (ip.indexToKey(decl_tv.val.toIntern())) { |
| 4663 | const owns_tv = func.owner_decl == decl_index; | 4357 | .func => |func| { |
| 4664 | if (owns_tv) { | 4358 | const owns_tv = func.owner_decl == decl_index; |
| 4665 | var prev_type_has_bits = false; | 4359 | if (owns_tv) { |
| 4666 | var prev_is_inline = false; | 4360 | var prev_type_has_bits = false; |
| 4667 | var type_changed = true; | 4361 | var prev_is_inline = false; |
| 4668 | 4362 | var type_changed = true; | |
| 4669 | if (decl.has_tv) { | 4363 | |
| 4670 | prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod); | 4364 | if (decl.has_tv) { |
| 4671 | type_changed = !decl.ty.eql(decl_tv.ty, mod); | 4365 | prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod); |
| 4672 | if (decl.getOwnedFunction(mod)) |prev_func| { | 4366 | type_changed = !decl.ty.eql(decl_tv.ty, mod); |
| 4673 | prev_is_inline = prev_func.state == .inline_only; | 4367 | if (decl.getOwnedFunction(mod)) |prev_func| { |
| 4368 | prev_is_inline = prev_func.analysis(ip).state == .inline_only; | ||
| 4369 | } | ||
| 4674 | } | 4370 | } |
| 4675 | } | 4371 | |
| 4676 | decl.clearValues(mod); | 4372 | decl.ty = decl_tv.ty; |
| 4677 | 4373 | decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue(); | |
| 4678 | decl.ty = decl_tv.ty; | 4374 | // linksection, align, and addrspace were already set by Sema |
| 4679 | decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue(); | 4375 | decl.has_tv = true; |
| 4680 | // linksection, align, and addrspace were already set by Sema | 4376 | decl.owns_tv = owns_tv; |
| 4681 | decl.has_tv = true; | 4377 | decl.analysis = .complete; |
| 4682 | decl.owns_tv = owns_tv; | 4378 | decl.generation = mod.generation; |
| 4683 | decl.analysis = .complete; | 4379 | |
| 4684 | decl.generation = mod.generation; | 4380 | const is_inline = decl.ty.fnCallingConvention(mod) == .Inline; |
| 4685 | 4381 | if (decl.is_exported) { | |
| 4686 | const is_inline = decl.ty.fnCallingConvention(mod) == .Inline; | 4382 | const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) }; |
| 4687 | if (decl.is_exported) { | 4383 | if (is_inline) { |
| 4688 | const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) }; | 4384 | return sema.fail(&block_scope, export_src, "export of inline function", .{}); |
| 4689 | if (is_inline) { | 4385 | } |
| 4690 | return sema.fail(&block_scope, export_src, "export of inline function", .{}); | 4386 | // The scope needs to have the decl in it. |
| 4387 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); | ||
| 4691 | } | 4388 | } |
| 4692 | // The scope needs to have the decl in it. | 4389 | return type_changed or is_inline != prev_is_inline; |
| 4693 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); | ||
| 4694 | } | 4390 | } |
| 4695 | return type_changed or is_inline != prev_is_inline; | 4391 | }, |
| 4696 | } | 4392 | else => {}, |
| 4697 | } | 4393 | } |
| 4698 | var type_changed = true; | 4394 | var type_changed = true; |
| 4699 | if (decl.has_tv) { | 4395 | if (decl.has_tv) { |
| 4700 | type_changed = !decl.ty.eql(decl_tv.ty, mod); | 4396 | type_changed = !decl.ty.eql(decl_tv.ty, mod); |
| 4701 | } | 4397 | } |
| 4702 | decl.clearValues(mod); | ||
| 4703 | 4398 | ||
| 4704 | decl.owns_tv = false; | 4399 | decl.owns_tv = false; |
| 4705 | var queue_linker_work = false; | 4400 | var queue_linker_work = false; |
| ... | @@ -4707,7 +4402,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4707,7 +4402,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4707 | switch (decl_tv.val.toIntern()) { | 4402 | switch (decl_tv.val.toIntern()) { |
| 4708 | .generic_poison => unreachable, | 4403 | .generic_poison => unreachable, |
| 4709 | .unreachable_value => unreachable, | 4404 | .unreachable_value => unreachable, |
| 4710 | else => switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) { | 4405 | else => switch (ip.indexToKey(decl_tv.val.toIntern())) { |
| 4711 | .variable => |variable| if (variable.decl == decl_index) { | 4406 | .variable => |variable| if (variable.decl == decl_index) { |
| 4712 | decl.owns_tv = true; | 4407 | decl.owns_tv = true; |
| 4713 | queue_linker_work = true; | 4408 | queue_linker_work = true; |
| ... | @@ -4743,11 +4438,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4743,11 +4438,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4743 | } else if (bytes.len == 0) { | 4438 | } else if (bytes.len == 0) { |
| 4744 | return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); | 4439 | return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); |
| 4745 | } | 4440 | } |
| 4746 | const section = try mod.intern_pool.getOrPutString(gpa, bytes); | 4441 | const section = try ip.getOrPutString(gpa, bytes); |
| 4747 | break :blk section.toOptional(); | 4442 | break :blk section.toOptional(); |
| 4748 | }; | 4443 | }; |
| 4749 | decl.@"addrspace" = blk: { | 4444 | decl.@"addrspace" = blk: { |
| 4750 | const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) { | 4445 | const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) { |
| 4751 | .variable => .variable, | 4446 | .variable => .variable, |
| 4752 | .extern_func, .func => .function, | 4447 | .extern_func, .func => .function, |
| 4753 | else => .constant, | 4448 | else => .constant, |
| ... | @@ -5309,7 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -5309,7 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 5309 | decl.has_align = has_align; | 5004 | decl.has_align = has_align; |
| 5310 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | 5005 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; |
| 5311 | decl.zir_decl_index = @as(u32, @intCast(decl_sub_index)); | 5006 | decl.zir_decl_index = @as(u32, @intCast(decl_sub_index)); |
| 5312 | if (decl.getOwnedFunctionIndex(mod) != .none) { | 5007 | if (decl.getOwnedFunction(mod) != null) { |
| 5313 | switch (comp.bin_file.tag) { | 5008 | switch (comp.bin_file.tag) { |
| 5314 | .coff, .elf, .macho, .plan9 => { | 5009 | .coff, .elf, .macho, .plan9 => { |
| 5315 | // TODO Look into detecting when this would be unnecessary by storing enough state | 5010 | // TODO Look into detecting when this would be unnecessary by storing enough state |
| ... | @@ -5386,7 +5081,6 @@ pub fn clearDecl( | ... | @@ -5386,7 +5081,6 @@ pub fn clearDecl( |
| 5386 | try namespace.deleteAllDecls(mod, outdated_decls); | 5081 | try namespace.deleteAllDecls(mod, outdated_decls); |
| 5387 | } | 5082 | } |
| 5388 | } | 5083 | } |
| 5389 | decl.clearValues(mod); | ||
| 5390 | 5084 | ||
| 5391 | if (decl.deletion_flag) { | 5085 | if (decl.deletion_flag) { |
| 5392 | decl.deletion_flag = false; | 5086 | decl.deletion_flag = false; |
| ... | @@ -5397,21 +5091,19 @@ pub fn clearDecl( | ... | @@ -5397,21 +5091,19 @@ pub fn clearDecl( |
| 5397 | } | 5091 | } |
| 5398 | 5092 | ||
| 5399 | /// This function is exclusively called for anonymous decls. | 5093 | /// This function is exclusively called for anonymous decls. |
| 5094 | /// All resources referenced by anonymous decls are owned by InternPool | ||
| 5095 | /// so there is no cleanup to do here. | ||
| 5400 | pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { | 5096 | pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5401 | const decl = mod.declPtr(decl_index); | 5097 | const gpa = mod.gpa; |
| 5402 | 5098 | const ip = &mod.intern_pool; | |
| 5403 | assert(!mod.declIsRoot(decl_index)); | ||
| 5404 | assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index)); | ||
| 5405 | 5099 | ||
| 5406 | const dependants = decl.dependants.keys(); | 5100 | ip.destroyDecl(gpa, decl_index); |
| 5407 | for (dependants) |dep| { | ||
| 5408 | mod.declPtr(dep).removeDependency(decl_index); | ||
| 5409 | } | ||
| 5410 | 5101 | ||
| 5411 | for (decl.dependencies.keys()) |dep| { | 5102 | if (mod.emit_h) |mod_emit_h| { |
| 5412 | mod.declPtr(dep).removeDependant(decl_index); | 5103 | const decl_emit_h = mod_emit_h.declPtr(decl_index); |
| 5104 | decl_emit_h.fwd_decl.deinit(gpa); | ||
| 5105 | decl_emit_h.* = undefined; | ||
| 5413 | } | 5106 | } |
| 5414 | mod.destroyDecl(decl_index); | ||
| 5415 | } | 5107 | } |
| 5416 | 5108 | ||
| 5417 | /// We don't perform a deletion here, because this Decl or another one | 5109 | /// We don't perform a deletion here, because this Decl or another one |
| ... | @@ -5428,7 +5120,6 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { | ... | @@ -5428,7 +5120,6 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5428 | const decl = mod.declPtr(decl_index); | 5120 | const decl = mod.declPtr(decl_index); |
| 5429 | 5121 | ||
| 5430 | assert(!mod.declIsRoot(decl_index)); | 5122 | assert(!mod.declIsRoot(decl_index)); |
| 5431 | assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index)); | ||
| 5432 | 5123 | ||
| 5433 | // An aborted decl must not have dependants -- they must have | 5124 | // An aborted decl must not have dependants -- they must have |
| 5434 | // been aborted first and removed from this list. | 5125 | // been aborted first and removed from this list. |
| ... | @@ -5497,19 +5188,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void | ... | @@ -5497,19 +5188,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void |
| 5497 | export_owners.deinit(mod.gpa); | 5188 | export_owners.deinit(mod.gpa); |
| 5498 | } | 5189 | } |
| 5499 | 5190 | ||
| 5500 | pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaError!Air { | 5191 | pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air { |
| 5501 | const tracy = trace(@src()); | 5192 | const tracy = trace(@src()); |
| 5502 | defer tracy.end(); | 5193 | defer tracy.end(); |
| 5503 | 5194 | ||
| 5504 | const gpa = mod.gpa; | 5195 | const gpa = mod.gpa; |
| 5505 | const func = mod.funcPtr(func_index); | 5196 | const ip = &mod.intern_pool; |
| 5197 | const func = mod.funcInfo(func_index); | ||
| 5506 | const decl_index = func.owner_decl; | 5198 | const decl_index = func.owner_decl; |
| 5507 | const decl = mod.declPtr(decl_index); | 5199 | const decl = mod.declPtr(decl_index); |
| 5508 | 5200 | ||
| 5509 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); | 5201 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); |
| 5510 | defer comptime_mutable_decls.deinit(); | 5202 | defer comptime_mutable_decls.deinit(); |
| 5511 | 5203 | ||
| 5204 | // In the case of a generic function instance, this is the type of the | ||
| 5205 | // instance, which has comptime parameters elided. In other words, it is | ||
| 5206 | // the runtime-known parameters only, not to be confused with the | ||
| 5207 | // generic_owner function type, which potentially has more parameters, | ||
| 5208 | // including comptime parameters. | ||
| 5512 | const fn_ty = decl.ty; | 5209 | const fn_ty = decl.ty; |
| 5210 | const fn_ty_info = mod.typeToFunc(fn_ty).?; | ||
| 5513 | 5211 | ||
| 5514 | var sema: Sema = .{ | 5212 | var sema: Sema = .{ |
| 5515 | .mod = mod, | 5213 | .mod = mod, |
| ... | @@ -5518,18 +5216,23 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE | ... | @@ -5518,18 +5216,23 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE |
| 5518 | .code = decl.getFileScope(mod).zir, | 5216 | .code = decl.getFileScope(mod).zir, |
| 5519 | .owner_decl = decl, | 5217 | .owner_decl = decl, |
| 5520 | .owner_decl_index = decl_index, | 5218 | .owner_decl_index = decl_index, |
| 5521 | .func = func, | 5219 | .func_index = func_index, |
| 5522 | .func_index = func_index.toOptional(), | 5220 | .fn_ret_ty = fn_ty_info.return_type.toType(), |
| 5523 | .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(), | 5221 | .fn_ret_ty_ies = null, |
| 5524 | .owner_func = func, | 5222 | .owner_func_index = func_index, |
| 5525 | .owner_func_index = func_index.toOptional(), | 5223 | .branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota), |
| 5526 | .branch_quota = @max(func.branch_quota, Sema.default_branch_quota), | ||
| 5527 | .comptime_mutable_decls = &comptime_mutable_decls, | 5224 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 5528 | }; | 5225 | }; |
| 5529 | defer sema.deinit(); | 5226 | defer sema.deinit(); |
| 5530 | 5227 | ||
| 5228 | if (func.analysis(ip).inferred_error_set) { | ||
| 5229 | const ies = try arena.create(Sema.InferredErrorSet); | ||
| 5230 | ies.* = .{ .func = func_index }; | ||
| 5231 | sema.fn_ret_ty_ies = ies; | ||
| 5232 | } | ||
| 5233 | |||
| 5531 | // reset in case calls to errorable functions are removed. | 5234 | // reset in case calls to errorable functions are removed. |
| 5532 | func.calls_or_awaits_errorable_fn = false; | 5235 | func.analysis(ip).calls_or_awaits_errorable_fn = false; |
| 5533 | 5236 | ||
| 5534 | // First few indexes of extra are reserved and set at the end. | 5237 | // First few indexes of extra are reserved and set at the end. |
| 5535 | const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len; | 5238 | const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len; |
| ... | @@ -5551,8 +5254,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE | ... | @@ -5551,8 +5254,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE |
| 5551 | }; | 5254 | }; |
| 5552 | defer inner_block.instructions.deinit(gpa); | 5255 | defer inner_block.instructions.deinit(gpa); |
| 5553 | 5256 | ||
| 5554 | const fn_info = sema.code.getFnInfo(func.zir_body_inst); | 5257 | const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*); |
| 5555 | const zir_tags = sema.code.instructions.items(.tag); | ||
| 5556 | 5258 | ||
| 5557 | // Here we are performing "runtime semantic analysis" for a function body, which means | 5259 | // Here we are performing "runtime semantic analysis" for a function body, which means |
| 5558 | // we must map the parameter ZIR instructions to `arg` AIR instructions. | 5260 | // we must map the parameter ZIR instructions to `arg` AIR instructions. |
| ... | @@ -5560,35 +5262,36 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE | ... | @@ -5560,35 +5262,36 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE |
| 5560 | // This could be a generic function instantiation, however, in which case we need to | 5262 | // This could be a generic function instantiation, however, in which case we need to |
| 5561 | // map the comptime parameters to constant values and only emit arg AIR instructions | 5263 | // map the comptime parameters to constant values and only emit arg AIR instructions |
| 5562 | // for the runtime ones. | 5264 | // for the runtime ones. |
| 5563 | const runtime_params_len = @as(u32, @intCast(mod.typeToFunc(fn_ty).?.param_types.len)); | 5265 | const runtime_params_len = fn_ty_info.param_types.len; |
| 5564 | try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len); | 5266 | try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len); |
| 5565 | try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType` | 5267 | try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len); |
| 5566 | try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); | 5268 | try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); |
| 5567 | 5269 | ||
| 5568 | var runtime_param_index: usize = 0; | 5270 | // In the case of a generic function instance, pre-populate all the comptime args. |
| 5569 | var total_param_index: usize = 0; | 5271 | if (func.comptime_args.len != 0) { |
| 5570 | for (fn_info.param_body) |inst| { | 5272 | for ( |
| 5571 | switch (zir_tags[inst]) { | 5273 | fn_info.param_body[0..func.comptime_args.len], |
| 5572 | .param, .param_comptime, .param_anytype, .param_anytype_comptime => {}, | 5274 | func.comptime_args.get(ip), |
| 5573 | else => continue, | 5275 | ) |inst, comptime_arg| { |
| 5276 | if (comptime_arg == .none) continue; | ||
| 5277 | sema.inst_map.putAssumeCapacityNoClobber(inst, Air.internedToRef(comptime_arg)); | ||
| 5574 | } | 5278 | } |
| 5575 | const param_ty = if (func.comptime_args) |comptime_args| t: { | 5279 | } |
| 5576 | const arg_tv = comptime_args[total_param_index]; | 5280 | |
| 5577 | 5281 | const src_params_len = if (func.comptime_args.len != 0) | |
| 5578 | const arg_val = if (!arg_tv.val.isGenericPoison()) | 5282 | func.comptime_args.len |
| 5579 | arg_tv.val | 5283 | else |
| 5580 | else if (try arg_tv.ty.onePossibleValue(mod)) |opv| | 5284 | runtime_params_len; |
| 5581 | opv | 5285 | |
| 5582 | else | 5286 | var runtime_param_index: usize = 0; |
| 5583 | break :t arg_tv.ty; | 5287 | for (fn_info.param_body[0..src_params_len], 0..) |inst, src_param_index| { |
| 5584 | 5288 | const gop = sema.inst_map.getOrPutAssumeCapacity(inst); | |
| 5585 | const arg = try sema.addConstant(arg_val); | 5289 | if (gop.found_existing) continue; // provided above by comptime arg |
| 5586 | sema.inst_map.putAssumeCapacityNoClobber(inst, arg); | ||
| 5587 | total_param_index += 1; | ||
| 5588 | continue; | ||
| 5589 | } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType(); | ||
| 5590 | 5290 | ||
| 5591 | const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) { | 5291 | const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index]; |
| 5292 | runtime_param_index += 1; | ||
| 5293 | |||
| 5294 | const opt_opv = sema.typeHasOnePossibleValue(param_ty.toType()) catch |err| switch (err) { | ||
| 5592 | error.NeededSourceLocation => unreachable, | 5295 | error.NeededSourceLocation => unreachable, |
| 5593 | error.GenericPoison => unreachable, | 5296 | error.GenericPoison => unreachable, |
| 5594 | error.ComptimeReturn => unreachable, | 5297 | error.ComptimeReturn => unreachable, |
| ... | @@ -5596,28 +5299,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE | ... | @@ -5596,28 +5299,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE |
| 5596 | else => |e| return e, | 5299 | else => |e| return e, |
| 5597 | }; | 5300 | }; |
| 5598 | if (opt_opv) |opv| { | 5301 | if (opt_opv) |opv| { |
| 5599 | const arg = try sema.addConstant(opv); | 5302 | gop.value_ptr.* = Air.internedToRef(opv.toIntern()); |
| 5600 | sema.inst_map.putAssumeCapacityNoClobber(inst, arg); | ||
| 5601 | total_param_index += 1; | ||
| 5602 | runtime_param_index += 1; | ||
| 5603 | continue; | 5303 | continue; |
| 5604 | } | 5304 | } |
| 5605 | const air_ty = try sema.addType(param_ty); | 5305 | const arg_index: u32 = @intCast(sema.air_instructions.len); |
| 5606 | const arg_index = @as(u32, @intCast(sema.air_instructions.len)); | 5306 | gop.value_ptr.* = Air.indexToRef(arg_index); |
| 5607 | inner_block.instructions.appendAssumeCapacity(arg_index); | 5307 | inner_block.instructions.appendAssumeCapacity(arg_index); |
| 5608 | sema.air_instructions.appendAssumeCapacity(.{ | 5308 | sema.air_instructions.appendAssumeCapacity(.{ |
| 5609 | .tag = .arg, | 5309 | .tag = .arg, |
| 5610 | .data = .{ .arg = .{ | 5310 | .data = .{ .arg = .{ |
| 5611 | .ty = air_ty, | 5311 | .ty = Air.internedToRef(param_ty), |
| 5612 | .src_index = @as(u32, @intCast(total_param_index)), | 5312 | .src_index = @intCast(src_param_index), |
| 5613 | } }, | 5313 | } }, |
| 5614 | }); | 5314 | }); |
| 5615 | sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index)); | ||
| 5616 | total_param_index += 1; | ||
| 5617 | runtime_param_index += 1; | ||
| 5618 | } | 5315 | } |
| 5619 | 5316 | ||
| 5620 | func.state = .in_progress; | 5317 | func.analysis(ip).state = .in_progress; |
| 5621 | 5318 | ||
| 5622 | const last_arg_index = inner_block.instructions.items.len; | 5319 | const last_arg_index = inner_block.instructions.items.len; |
| 5623 | 5320 | ||
| ... | @@ -5648,7 +5345,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE | ... | @@ -5648,7 +5345,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE |
| 5648 | } | 5345 | } |
| 5649 | 5346 | ||
| 5650 | // If we don't get an error return trace from a caller, create our own. | 5347 | // If we don't get an error return trace from a caller, create our own. |
| 5651 | if (func.calls_or_awaits_errorable_fn and | 5348 | if (func.analysis(ip).calls_or_awaits_errorable_fn and |
| 5652 | mod.comp.bin_file.options.error_return_tracing and | 5349 | mod.comp.bin_file.options.error_return_tracing and |
| 5653 | !sema.fn_ret_ty.isError(mod)) | 5350 | !sema.fn_ret_ty.isError(mod)) |
| 5654 | { | 5351 | { |
| ... | @@ -5672,12 +5369,33 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE | ... | @@ -5672,12 +5369,33 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE |
| 5672 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + | 5369 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 5673 | inner_block.instructions.items.len); | 5370 | inner_block.instructions.items.len); |
| 5674 | const main_block_index = sema.addExtraAssumeCapacity(Air.Block{ | 5371 | const main_block_index = sema.addExtraAssumeCapacity(Air.Block{ |
| 5675 | .body_len = @as(u32, @intCast(inner_block.instructions.items.len)), | 5372 | .body_len = @intCast(inner_block.instructions.items.len), |
| 5676 | }); | 5373 | }); |
| 5677 | sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items); | 5374 | sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items); |
| 5678 | sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index; | 5375 | sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index; |
| 5679 | 5376 | ||
| 5680 | func.state = .success; | 5377 | // Resolving inferred error sets is done *before* setting the function |
| 5378 | // state to success, so that "unable to resolve inferred error set" errors | ||
| 5379 | // can be emitted here. | ||
| 5380 | if (sema.fn_ret_ty_ies) |ies| { | ||
| 5381 | sema.resolveInferredErrorSetPtr(&inner_block, LazySrcLoc.nodeOffset(0), ies) catch |err| switch (err) { | ||
| 5382 | error.NeededSourceLocation => unreachable, | ||
| 5383 | error.GenericPoison => unreachable, | ||
| 5384 | error.ComptimeReturn => unreachable, | ||
| 5385 | error.ComptimeBreak => unreachable, | ||
| 5386 | error.AnalysisFail => { | ||
| 5387 | // In this case our function depends on a type that had a compile error. | ||
| 5388 | // We should not try to lower this function. | ||
| 5389 | decl.analysis = .dependency_failure; | ||
| 5390 | return error.AnalysisFail; | ||
| 5391 | }, | ||
| 5392 | else => |e| return e, | ||
| 5393 | }; | ||
| 5394 | assert(ies.resolved != .none); | ||
| 5395 | ip.funcIesResolved(func_index).* = ies.resolved; | ||
| 5396 | } | ||
| 5397 | |||
| 5398 | func.analysis(ip).state = .success; | ||
| 5681 | 5399 | ||
| 5682 | // Finally we must resolve the return type and parameter types so that backends | 5400 | // Finally we must resolve the return type and parameter types so that backends |
| 5683 | // have full access to type information. | 5401 | // have full access to type information. |
| ... | @@ -5716,7 +5434,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE | ... | @@ -5716,7 +5434,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE |
| 5716 | }; | 5434 | }; |
| 5717 | } | 5435 | } |
| 5718 | 5436 | ||
| 5719 | return Air{ | 5437 | return .{ |
| 5720 | .instructions = sema.air_instructions.toOwnedSlice(), | 5438 | .instructions = sema.air_instructions.toOwnedSlice(), |
| 5721 | .extra = try sema.air_extra.toOwnedSlice(gpa), | 5439 | .extra = try sema.air_extra.toOwnedSlice(gpa), |
| 5722 | }; | 5440 | }; |
| ... | @@ -5731,9 +5449,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { | ... | @@ -5731,9 +5449,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { |
| 5731 | if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| { | 5449 | if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| { |
| 5732 | for (kv.value) |err| err.deinit(mod.gpa); | 5450 | for (kv.value) |err| err.deinit(mod.gpa); |
| 5733 | } | 5451 | } |
| 5734 | if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| { | ||
| 5735 | _ = mod.align_stack_fns.remove(func); | ||
| 5736 | } | ||
| 5737 | if (mod.emit_h) |emit_h| { | 5452 | if (mod.emit_h) |emit_h| { |
| 5738 | if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| { | 5453 | if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| { |
| 5739 | kv.value.destroy(mod.gpa); | 5454 | kv.value.destroy(mod.gpa); |
| ... | @@ -5744,21 +5459,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { | ... | @@ -5744,21 +5459,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { |
| 5744 | } | 5459 | } |
| 5745 | 5460 | ||
| 5746 | pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index { | 5461 | pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index { |
| 5747 | if (mod.namespaces_free_list.popOrNull()) |index| { | 5462 | return mod.intern_pool.createNamespace(mod.gpa, initialization); |
| 5748 | mod.allocated_namespaces.at(@intFromEnum(index)).* = initialization; | ||
| 5749 | return index; | ||
| 5750 | } | ||
| 5751 | const ptr = try mod.allocated_namespaces.addOne(mod.gpa); | ||
| 5752 | ptr.* = initialization; | ||
| 5753 | return @as(Namespace.Index, @enumFromInt(mod.allocated_namespaces.len - 1)); | ||
| 5754 | } | 5463 | } |
| 5755 | 5464 | ||
| 5756 | pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void { | 5465 | pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void { |
| 5757 | mod.namespacePtr(index).* = undefined; | 5466 | return mod.intern_pool.destroyNamespace(mod.gpa, index); |
| 5758 | mod.namespaces_free_list.append(mod.gpa, index) catch { | ||
| 5759 | // In order to keep `destroyNamespace` a non-fallible function, we ignore memory | ||
| 5760 | // allocation failures here, instead leaking the Namespace until garbage collection. | ||
| 5761 | }; | ||
| 5762 | } | 5467 | } |
| 5763 | 5468 | ||
| 5764 | pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index { | 5469 | pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index { |
| ... | @@ -5777,43 +5482,15 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void { | ... | @@ -5777,43 +5482,15 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void { |
| 5777 | return mod.intern_pool.destroyUnion(mod.gpa, index); | 5482 | return mod.intern_pool.destroyUnion(mod.gpa, index); |
| 5778 | } | 5483 | } |
| 5779 | 5484 | ||
| 5780 | pub fn createFunc(mod: *Module, initialization: Fn) Allocator.Error!Fn.Index { | ||
| 5781 | return mod.intern_pool.createFunc(mod.gpa, initialization); | ||
| 5782 | } | ||
| 5783 | |||
| 5784 | pub fn destroyFunc(mod: *Module, index: Fn.Index) void { | ||
| 5785 | return mod.intern_pool.destroyFunc(mod.gpa, index); | ||
| 5786 | } | ||
| 5787 | |||
| 5788 | pub fn allocateNewDecl( | 5485 | pub fn allocateNewDecl( |
| 5789 | mod: *Module, | 5486 | mod: *Module, |
| 5790 | namespace: Namespace.Index, | 5487 | namespace: Namespace.Index, |
| 5791 | src_node: Ast.Node.Index, | 5488 | src_node: Ast.Node.Index, |
| 5792 | src_scope: ?*CaptureScope, | 5489 | src_scope: ?*CaptureScope, |
| 5793 | ) !Decl.Index { | 5490 | ) !Decl.Index { |
| 5794 | const decl_and_index: struct { | 5491 | const ip = &mod.intern_pool; |
| 5795 | new_decl: *Decl, | 5492 | const gpa = mod.gpa; |
| 5796 | decl_index: Decl.Index, | 5493 | const decl_index = try ip.createDecl(gpa, .{ |
| 5797 | } = if (mod.decls_free_list.popOrNull()) |decl_index| d: { | ||
| 5798 | break :d .{ | ||
| 5799 | .new_decl = mod.declPtr(decl_index), | ||
| 5800 | .decl_index = decl_index, | ||
| 5801 | }; | ||
| 5802 | } else d: { | ||
| 5803 | const decl = try mod.allocated_decls.addOne(mod.gpa); | ||
| 5804 | errdefer mod.allocated_decls.shrinkRetainingCapacity(mod.allocated_decls.len - 1); | ||
| 5805 | if (mod.emit_h) |mod_emit_h| { | ||
| 5806 | const decl_emit_h = try mod_emit_h.allocated_emit_h.addOne(mod.gpa); | ||
| 5807 | decl_emit_h.* = .{}; | ||
| 5808 | } | ||
| 5809 | break :d .{ | ||
| 5810 | .new_decl = decl, | ||
| 5811 | .decl_index = @as(Decl.Index, @enumFromInt(mod.allocated_decls.len - 1)), | ||
| 5812 | }; | ||
| 5813 | }; | ||
| 5814 | |||
| 5815 | if (src_scope) |scope| scope.incRef(); | ||
| 5816 | decl_and_index.new_decl.* = .{ | ||
| 5817 | .name = undefined, | 5494 | .name = undefined, |
| 5818 | .src_namespace = namespace, | 5495 | .src_namespace = namespace, |
| 5819 | .src_node = src_node, | 5496 | .src_node = src_node, |
| ... | @@ -5836,9 +5513,18 @@ pub fn allocateNewDecl( | ... | @@ -5836,9 +5513,18 @@ pub fn allocateNewDecl( |
| 5836 | .has_align = false, | 5513 | .has_align = false, |
| 5837 | .alive = false, | 5514 | .alive = false, |
| 5838 | .kind = .anon, | 5515 | .kind = .anon, |
| 5839 | }; | 5516 | }); |
| 5517 | |||
| 5518 | if (mod.emit_h) |mod_emit_h| { | ||
| 5519 | if (@intFromEnum(decl_index) >= mod_emit_h.allocated_emit_h.len) { | ||
| 5520 | try mod_emit_h.allocated_emit_h.append(gpa, .{}); | ||
| 5521 | assert(@intFromEnum(decl_index) == mod_emit_h.allocated_emit_h.len); | ||
| 5522 | } | ||
| 5523 | } | ||
| 5524 | |||
| 5525 | if (src_scope) |scope| scope.incRef(); | ||
| 5840 | 5526 | ||
| 5841 | return decl_and_index.decl_index; | 5527 | return decl_index; |
| 5842 | } | 5528 | } |
| 5843 | 5529 | ||
| 5844 | pub fn getErrorValue( | 5530 | pub fn getErrorValue( |
| ... | @@ -5874,7 +5560,7 @@ pub fn createAnonymousDeclFromDecl( | ... | @@ -5874,7 +5560,7 @@ pub fn createAnonymousDeclFromDecl( |
| 5874 | const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ | 5560 | const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ |
| 5875 | src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), | 5561 | src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), |
| 5876 | }); | 5562 | }); |
| 5877 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name); | 5563 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, tv, name); |
| 5878 | return new_decl_index; | 5564 | return new_decl_index; |
| 5879 | } | 5565 | } |
| 5880 | 5566 | ||
| ... | @@ -5882,7 +5568,6 @@ pub fn initNewAnonDecl( | ... | @@ -5882,7 +5568,6 @@ pub fn initNewAnonDecl( |
| 5882 | mod: *Module, | 5568 | mod: *Module, |
| 5883 | new_decl_index: Decl.Index, | 5569 | new_decl_index: Decl.Index, |
| 5884 | src_line: u32, | 5570 | src_line: u32, |
| 5885 | namespace: Namespace.Index, | ||
| 5886 | typed_value: TypedValue, | 5571 | typed_value: TypedValue, |
| 5887 | name: InternPool.NullTerminatedString, | 5572 | name: InternPool.NullTerminatedString, |
| 5888 | ) Allocator.Error!void { | 5573 | ) Allocator.Error!void { |
| ... | @@ -5899,8 +5584,6 @@ pub fn initNewAnonDecl( | ... | @@ -5899,8 +5584,6 @@ pub fn initNewAnonDecl( |
| 5899 | new_decl.has_tv = true; | 5584 | new_decl.has_tv = true; |
| 5900 | new_decl.analysis = .complete; | 5585 | new_decl.analysis = .complete; |
| 5901 | new_decl.generation = mod.generation; | 5586 | new_decl.generation = mod.generation; |
| 5902 | |||
| 5903 | try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {}); | ||
| 5904 | } | 5587 | } |
| 5905 | 5588 | ||
| 5906 | pub fn errNoteNonLazy( | 5589 | pub fn errNoteNonLazy( |
| ... | @@ -6578,7 +6261,6 @@ pub fn populateTestFunctions( | ... | @@ -6578,7 +6261,6 @@ pub fn populateTestFunctions( |
| 6578 | 6261 | ||
| 6579 | // Since we are replacing the Decl's value we must perform cleanup on the | 6262 | // Since we are replacing the Decl's value we must perform cleanup on the |
| 6580 | // previous value. | 6263 | // previous value. |
| 6581 | decl.clearValues(mod); | ||
| 6582 | decl.ty = new_ty; | 6264 | decl.ty = new_ty; |
| 6583 | decl.val = new_val; | 6265 | decl.val = new_val; |
| 6584 | decl.has_tv = true; | 6266 | decl.has_tv = true; |
| ... | @@ -6657,7 +6339,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void { | ... | @@ -6657,7 +6339,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void { |
| 6657 | switch (mod.intern_pool.indexToKey(val.toIntern())) { | 6339 | switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 6658 | .variable => |variable| try mod.markDeclIndexAlive(variable.decl), | 6340 | .variable => |variable| try mod.markDeclIndexAlive(variable.decl), |
| 6659 | .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl), | 6341 | .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl), |
| 6660 | .func => |func| try mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl), | 6342 | .func => |func| try mod.markDeclIndexAlive(func.owner_decl), |
| 6661 | .error_union => |error_union| switch (error_union.val) { | 6343 | .error_union => |error_union| switch (error_union.val) { |
| 6662 | .err_name => {}, | 6344 | .err_name => {}, |
| 6663 | .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()), | 6345 | .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()), |
| ... | @@ -6851,8 +6533,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator | ... | @@ -6851,8 +6533,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator |
| 6851 | return mod.ptrType(info); | 6533 | return mod.ptrType(info); |
| 6852 | } | 6534 | } |
| 6853 | 6535 | ||
| 6854 | pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type { | 6536 | pub fn funcType(mod: *Module, key: InternPool.GetFuncTypeKey) Allocator.Error!Type { |
| 6855 | return (try intern(mod, .{ .func_type = info })).toType(); | 6537 | return (try mod.intern_pool.getFuncType(mod.gpa, key)).toType(); |
| 6856 | } | 6538 | } |
| 6857 | 6539 | ||
| 6858 | /// Use this for `anyframe->T` only. | 6540 | /// Use this for `anyframe->T` only. |
| ... | @@ -6870,7 +6552,8 @@ pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Alloca | ... | @@ -6870,7 +6552,8 @@ pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Alloca |
| 6870 | 6552 | ||
| 6871 | pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type { | 6553 | pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type { |
| 6872 | const names: *const [1]InternPool.NullTerminatedString = &name; | 6554 | const names: *const [1]InternPool.NullTerminatedString = &name; |
| 6873 | return (try mod.intern_pool.get(mod.gpa, .{ .error_set_type = .{ .names = names } })).toType(); | 6555 | const new_ty = try mod.intern_pool.getErrorSetType(mod.gpa, names); |
| 6556 | return new_ty.toType(); | ||
| 6874 | } | 6557 | } |
| 6875 | 6558 | ||
| 6876 | /// Sorts `names` in place. | 6559 | /// Sorts `names` in place. |
| ... | @@ -6884,7 +6567,7 @@ pub fn errorSetFromUnsortedNames( | ... | @@ -6884,7 +6567,7 @@ pub fn errorSetFromUnsortedNames( |
| 6884 | {}, | 6567 | {}, |
| 6885 | InternPool.NullTerminatedString.indexLessThan, | 6568 | InternPool.NullTerminatedString.indexLessThan, |
| 6886 | ); | 6569 | ); |
| 6887 | const new_ty = try mod.intern(.{ .error_set_type = .{ .names = names } }); | 6570 | const new_ty = try mod.intern_pool.getErrorSetType(mod.gpa, names); |
| 6888 | return new_ty.toType(); | 6571 | return new_ty.toType(); |
| 6889 | } | 6572 | } |
| 6890 | 6573 | ||
| ... | @@ -7231,14 +6914,20 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType { | ... | @@ -7231,14 +6914,20 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType { |
| 7231 | return mod.intern_pool.indexToFuncType(ty.toIntern()); | 6914 | return mod.intern_pool.indexToFuncType(ty.toIntern()); |
| 7232 | } | 6915 | } |
| 7233 | 6916 | ||
| 7234 | pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet { | 6917 | pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl { |
| 7235 | const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null; | 6918 | return mod.declPtr(mod.funcOwnerDeclIndex(func_index)); |
| 7236 | return mod.inferredErrorSetPtr(index); | 6919 | } |
| 6920 | |||
| 6921 | pub fn funcOwnerDeclIndex(mod: *Module, func_index: InternPool.Index) Decl.Index { | ||
| 6922 | return mod.funcInfo(func_index).owner_decl; | ||
| 6923 | } | ||
| 6924 | |||
| 6925 | pub fn iesFuncIndex(mod: *const Module, ies_index: InternPool.Index) InternPool.Index { | ||
| 6926 | return mod.intern_pool.iesFuncIndex(ies_index); | ||
| 7237 | } | 6927 | } |
| 7238 | 6928 | ||
| 7239 | pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex { | 6929 | pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func { |
| 7240 | if (ty.ip_index == .none) return .none; | 6930 | return mod.intern_pool.indexToKey(func_index).func; |
| 7241 | return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern()); | ||
| 7242 | } | 6931 | } |
| 7243 | 6932 | ||
| 7244 | pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc { | 6933 | pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc { |
| ... | @@ -7265,3 +6954,41 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu | ... | @@ -7265,3 +6954,41 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu |
| 7265 | pub fn toEnum(mod: *Module, comptime E: type, val: Value) E { | 6954 | pub fn toEnum(mod: *Module, comptime E: type, val: Value) E { |
| 7266 | return mod.intern_pool.toEnum(E, val.toIntern()); | 6955 | return mod.intern_pool.toEnum(E, val.toIntern()); |
| 7267 | } | 6956 | } |
| 6957 | |||
| 6958 | pub fn isAnytypeParam(mod: *Module, func: InternPool.Index, index: u32) bool { | ||
| 6959 | const file = mod.declPtr(func.owner_decl).getFileScope(mod); | ||
| 6960 | |||
| 6961 | const tags = file.zir.instructions.items(.tag); | ||
| 6962 | |||
| 6963 | const param_body = file.zir.getParamBody(func.zir_body_inst); | ||
| 6964 | const param = param_body[index]; | ||
| 6965 | |||
| 6966 | return switch (tags[param]) { | ||
| 6967 | .param, .param_comptime => false, | ||
| 6968 | .param_anytype, .param_anytype_comptime => true, | ||
| 6969 | else => unreachable, | ||
| 6970 | }; | ||
| 6971 | } | ||
| 6972 | |||
| 6973 | pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]const u8 { | ||
| 6974 | const func = mod.funcInfo(func_index); | ||
| 6975 | const file = mod.declPtr(func.owner_decl).getFileScope(mod); | ||
| 6976 | |||
| 6977 | const tags = file.zir.instructions.items(.tag); | ||
| 6978 | const data = file.zir.instructions.items(.data); | ||
| 6979 | |||
| 6980 | const param_body = file.zir.getParamBody(func.zir_body_inst); | ||
| 6981 | const param = param_body[index]; | ||
| 6982 | |||
| 6983 | return switch (tags[param]) { | ||
| 6984 | .param, .param_comptime => blk: { | ||
| 6985 | const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index); | ||
| 6986 | break :blk file.zir.nullTerminatedString(extra.data.name); | ||
| 6987 | }, | ||
| 6988 | .param_anytype, .param_anytype_comptime => blk: { | ||
| 6989 | const param_data = data[param].str_tok; | ||
| 6990 | break :blk param_data.get(file.zir); | ||
| 6991 | }, | ||
| 6992 | else => unreachable, | ||
| 6993 | }; | ||
| 6994 | } |
src/Sema.zig+1364-1345| ... | @@ -23,13 +23,13 @@ owner_decl: *Decl, | ... | @@ -23,13 +23,13 @@ owner_decl: *Decl, |
| 23 | owner_decl_index: Decl.Index, | 23 | owner_decl_index: Decl.Index, |
| 24 | /// For an inline or comptime function call, this will be the root parent function | 24 | /// For an inline or comptime function call, this will be the root parent function |
| 25 | /// which contains the callsite. Corresponds to `owner_decl`. | 25 | /// which contains the callsite. Corresponds to `owner_decl`. |
| 26 | owner_func: ?*Module.Fn, | 26 | /// This could be `none`, a `func_decl`, or a `func_instance`. |
| 27 | owner_func_index: Module.Fn.OptionalIndex, | 27 | owner_func_index: InternPool.Index, |
| 28 | /// 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. |
| 29 | /// This starts out the same as `owner_func` and then diverges in the case of | 29 | /// This starts out the same as `owner_func_index` and then diverges in the case of |
| 30 | /// an inline or comptime function call. | 30 | /// an inline or comptime function call. |
| 31 | func: ?*Module.Fn, | 31 | /// This could be `none`, a `func_decl`, or a `func_instance`. |
| 32 | func_index: Module.Fn.OptionalIndex, | 32 | func_index: InternPool.Index, |
| 33 | /// 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. |
| 34 | error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, | 34 | error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, |
| 35 | /// When semantic analysis needs to know the return type of the function whose body | 35 | /// When semantic analysis needs to know the return type of the function whose body |
| ... | @@ -38,6 +38,10 @@ error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, | ... | @@ -38,6 +38,10 @@ error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, |
| 38 | /// generic function which uses a type expression for the return type. | 38 | /// generic function which uses a type expression for the return type. |
| 39 | /// The type will be `void` in the case that `func` is `null`. | 39 | /// The type will be `void` in the case that `func` is `null`. |
| 40 | fn_ret_ty: Type, | 40 | fn_ret_ty: Type, |
| 41 | /// In case of the return type being an error union with an inferred error | ||
| 42 | /// set, this is the inferred error set. `null` otherwise. Allocated with | ||
| 43 | /// `Sema.arena`. | ||
| 44 | fn_ret_ty_ies: ?*InferredErrorSet, | ||
| 41 | branch_quota: u32 = default_branch_quota, | 45 | branch_quota: u32 = default_branch_quota, |
| 42 | branch_count: u32 = 0, | 46 | branch_count: u32 = 0, |
| 43 | /// Populated when returning `error.ComptimeBreak`. Used to communicate the | 47 | /// Populated when returning `error.ComptimeBreak`. Used to communicate the |
| ... | @@ -49,21 +53,23 @@ comptime_break_inst: Zir.Inst.Index = undefined, | ... | @@ -49,21 +53,23 @@ comptime_break_inst: Zir.Inst.Index = undefined, |
| 49 | /// contain a mapped source location. | 53 | /// contain a mapped source location. |
| 50 | src: LazySrcLoc = .{ .token_offset = 0 }, | 54 | src: LazySrcLoc = .{ .token_offset = 0 }, |
| 51 | decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{}, | 55 | decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{}, |
| 52 | /// When doing a generic function instantiation, this array collects a | 56 | /// When doing a generic function instantiation, this array collects a value |
| 53 | /// `Value` object for each parameter that is comptime-known and thus elided | 57 | /// for each parameter of the generic owner. `none` for non-comptime parameters. |
| 54 | /// from the generated function. This memory is allocated by a parent `Sema` and | 58 | /// This is a separate array from `block.params` so that it can be passed |
| 55 | /// owned by the values arena of the Sema owner_decl. | 59 | /// directly to `comptime_args` when calling `InternPool.getFuncInstance`. |
| 56 | comptime_args: []TypedValue = &.{}, | 60 | /// This memory is allocated by a parent `Sema` in the temporary arena, and is |
| 57 | /// Marks the function instruction that `comptime_args` applies to so that we | 61 | /// used only to add a `func_instance` into the `InternPool`. |
| 58 | /// don't accidentally apply it to a function prototype which is used in the | 62 | comptime_args: []InternPool.Index = &.{}, |
| 59 | /// type expression of a generic function parameter. | 63 | /// Used to communicate from a generic function instantiation to the logic that |
| 60 | comptime_args_fn_inst: Zir.Inst.Index = 0, | 64 | /// creates a generic function instantiation value in `funcCommon`. |
| 61 | /// When `comptime_args` is provided, this field is also provided. It was used as | 65 | generic_owner: InternPool.Index = .none, |
| 62 | /// the key in the `monomorphed_funcs` set. The `func` instruction is supposed | 66 | /// When `generic_owner` is not none, this contains the generic function |
| 63 | /// to use this instead of allocating a fresh one. This avoids an unnecessary | 67 | /// instantiation callsite so that compile errors on the parameter types of the |
| 64 | /// extra hash table lookup in the `monomorphed_funcs` set. | 68 | /// instantiation can point back to the instantiation site in addition to the |
| 65 | /// Sema will set this to null when it takes ownership. | 69 | /// declaration site. |
| 66 | preallocated_new_func: Module.Fn.OptionalIndex = .none, | 70 | generic_call_src: LazySrcLoc = .unneeded, |
| 71 | /// Corresponds to `generic_call_src`. | ||
| 72 | generic_call_decl: Decl.OptionalIndex = .none, | ||
| 67 | /// The key is types that must be fully resolved prior to machine code | 73 | /// The key is types that must be fully resolved prior to machine code |
| 68 | /// generation pass. Types are added to this set when resolving them | 74 | /// generation pass. Types are added to this set when resolving them |
| 69 | /// immediately could cause a dependency loop, but they do need to be resolved | 75 | /// immediately could cause a dependency loop, but they do need to be resolved |
| ... | @@ -79,8 +85,6 @@ types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}, | ... | @@ -79,8 +85,6 @@ types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}, |
| 79 | post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, | 85 | post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, |
| 80 | /// Populated with the last compile error created. | 86 | /// Populated with the last compile error created. |
| 81 | err: ?*Module.ErrorMsg = null, | 87 | err: ?*Module.ErrorMsg = null, |
| 82 | /// True when analyzing a generic instantiation. Used to suppress some errors. | ||
| 83 | is_generic_instantiation: bool = false, | ||
| 84 | /// Set to true when analyzing a func type instruction so that nested generic | 88 | /// Set to true when analyzing a func type instruction so that nested generic |
| 85 | /// function types will emit generic poison instead of a partial type. | 89 | /// function types will emit generic poison instead of a partial type. |
| 86 | no_partial_func_ty: bool = false, | 90 | no_partial_func_ty: bool = false, |
| ... | @@ -97,6 +101,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll | ... | @@ -97,6 +101,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll |
| 97 | /// involve transitioning comptime-mutable memory away from using Decls at all. | 101 | /// involve transitioning comptime-mutable memory away from using Decls at all. |
| 98 | comptime_mutable_decls: *std.ArrayList(Decl.Index), | 102 | comptime_mutable_decls: *std.ArrayList(Decl.Index), |
| 99 | 103 | ||
| 104 | /// This is populated when `@setAlignStack` occurs so that if there is a duplicate | ||
| 105 | /// one encountered, the conflicting source location can be shown. | ||
| 106 | prev_stack_alignment_src: ?LazySrcLoc = null, | ||
| 107 | |||
| 100 | const std = @import("std"); | 108 | const std = @import("std"); |
| 101 | const math = std.math; | 109 | const math = std.math; |
| 102 | const mem = std.mem; | 110 | const mem = std.mem; |
| ... | @@ -131,6 +139,49 @@ const Alignment = InternPool.Alignment; | ... | @@ -131,6 +139,49 @@ const Alignment = InternPool.Alignment; |
| 131 | pub const default_branch_quota = 1000; | 139 | pub const default_branch_quota = 1000; |
| 132 | pub const default_reference_trace_len = 2; | 140 | pub const default_reference_trace_len = 2; |
| 133 | 141 | ||
| 142 | pub const InferredErrorSet = struct { | ||
| 143 | /// The function body from which this error set originates. | ||
| 144 | /// This is `none` in the case of a comptime/inline function call, corresponding to | ||
| 145 | /// `InternPool.Index.adhoc_inferred_error_set_type`. | ||
| 146 | /// The function's resolved error set is not set until analysis of the | ||
| 147 | /// function body completes. | ||
| 148 | func: InternPool.Index, | ||
| 149 | /// All currently known errors that this error set contains. This includes | ||
| 150 | /// direct additions via `return error.Foo;`, and possibly also errors that | ||
| 151 | /// are returned from any dependent functions. | ||
| 152 | errors: NameMap = .{}, | ||
| 153 | /// Other inferred error sets which this inferred error set should include. | ||
| 154 | inferred_error_sets: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}, | ||
| 155 | /// The regular error set created by resolving this inferred error set. | ||
| 156 | resolved: InternPool.Index = .none, | ||
| 157 | |||
| 158 | pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void); | ||
| 159 | |||
| 160 | pub fn addErrorSet( | ||
| 161 | self: *InferredErrorSet, | ||
| 162 | err_set_ty: Type, | ||
| 163 | ip: *InternPool, | ||
| 164 | arena: Allocator, | ||
| 165 | ) !void { | ||
| 166 | switch (err_set_ty.toIntern()) { | ||
| 167 | .anyerror_type => self.resolved = .anyerror_type, | ||
| 168 | .adhoc_inferred_error_set_type => {}, // Adding an inferred error set to itself. | ||
| 169 | |||
| 170 | else => switch (ip.indexToKey(err_set_ty.toIntern())) { | ||
| 171 | .error_set_type => |error_set_type| { | ||
| 172 | for (error_set_type.names.get(ip)) |name| { | ||
| 173 | try self.errors.put(arena, name, {}); | ||
| 174 | } | ||
| 175 | }, | ||
| 176 | .inferred_error_set_type => { | ||
| 177 | try self.inferred_error_sets.put(arena, err_set_ty.toIntern(), {}); | ||
| 178 | }, | ||
| 179 | else => unreachable, | ||
| 180 | }, | ||
| 181 | } | ||
| 182 | } | ||
| 183 | }; | ||
| 184 | |||
| 134 | /// Stores the mapping from `Zir.Inst.Index -> Air.Inst.Ref`, which is used by sema to resolve | 185 | /// Stores the mapping from `Zir.Inst.Index -> Air.Inst.Ref`, which is used by sema to resolve |
| 135 | /// instructions during analysis. | 186 | /// instructions during analysis. |
| 136 | /// Instead of a hash table approach, InstMap is simply a slice that is indexed into using the | 187 | /// Instead of a hash table approach, InstMap is simply a slice that is indexed into using the |
| ... | @@ -243,7 +294,13 @@ pub const Block = struct { | ... | @@ -243,7 +294,13 @@ pub const Block = struct { |
| 243 | /// The AIR instructions generated for this block. | 294 | /// The AIR instructions generated for this block. |
| 244 | instructions: std.ArrayListUnmanaged(Air.Inst.Index), | 295 | instructions: std.ArrayListUnmanaged(Air.Inst.Index), |
| 245 | // `param` instructions are collected here to be used by the `func` instruction. | 296 | // `param` instructions are collected here to be used by the `func` instruction. |
| 246 | params: std.ArrayListUnmanaged(Param) = .{}, | 297 | /// When doing a generic function instantiation, this array collects a type |
| 298 | /// for each *runtime-known* parameter. This array corresponds to the instance | ||
| 299 | /// function type, while `Sema.comptime_args` corresponds to the generic owner | ||
| 300 | /// function type. | ||
| 301 | /// This memory is allocated by a parent `Sema` in the temporary arena, and is | ||
| 302 | /// used to add a `func_instance` into the `InternPool`. | ||
| 303 | params: std.MultiArrayList(Param) = .{}, | ||
| 247 | 304 | ||
| 248 | wip_capture_scope: *CaptureScope, | 305 | wip_capture_scope: *CaptureScope, |
| 249 | 306 | ||
| ... | @@ -323,10 +380,10 @@ pub const Block = struct { | ... | @@ -323,10 +380,10 @@ pub const Block = struct { |
| 323 | }; | 380 | }; |
| 324 | 381 | ||
| 325 | const Param = struct { | 382 | const Param = struct { |
| 326 | /// `noreturn` means `anytype`. | 383 | /// `none` means `anytype`. |
| 327 | ty: Type, | 384 | ty: InternPool.Index, |
| 328 | is_comptime: bool, | 385 | is_comptime: bool, |
| 329 | name: []const u8, | 386 | name: Zir.NullTerminatedString, |
| 330 | }; | 387 | }; |
| 331 | 388 | ||
| 332 | /// This `Block` maps a block ZIR instruction to the corresponding | 389 | /// This `Block` maps a block ZIR instruction to the corresponding |
| ... | @@ -342,7 +399,8 @@ pub const Block = struct { | ... | @@ -342,7 +399,8 @@ pub const Block = struct { |
| 342 | /// It is shared among all the blocks in an inline or comptime called | 399 | /// It is shared among all the blocks in an inline or comptime called |
| 343 | /// function. | 400 | /// function. |
| 344 | pub const Inlining = struct { | 401 | pub const Inlining = struct { |
| 345 | func: ?*Module.Fn, | 402 | /// Might be `none`. |
| 403 | func: InternPool.Index, | ||
| 346 | comptime_result: Air.Inst.Ref, | 404 | comptime_result: Air.Inst.Ref, |
| 347 | merges: Merges, | 405 | merges: Merges, |
| 348 | }; | 406 | }; |
| ... | @@ -906,7 +964,7 @@ fn analyzeBodyInner( | ... | @@ -906,7 +964,7 @@ fn analyzeBodyInner( |
| 906 | // We use a while (true) loop here to avoid a redundant way of breaking out of | 964 | // We use a while (true) loop here to avoid a redundant way of breaking out of |
| 907 | // the loop. The only way to break out of the loop is with a `noreturn` | 965 | // the loop. The only way to break out of the loop is with a `noreturn` |
| 908 | // instruction. | 966 | // instruction. |
| 909 | var i: usize = 0; | 967 | var i: u32 = 0; |
| 910 | const result = while (true) { | 968 | const result = while (true) { |
| 911 | crash_info.setBodyIndex(i); | 969 | crash_info.setBodyIndex(i); |
| 912 | const inst = body[i]; | 970 | const inst = body[i]; |
| ... | @@ -1116,7 +1174,7 @@ fn analyzeBodyInner( | ... | @@ -1116,7 +1174,7 @@ fn analyzeBodyInner( |
| 1116 | .shl_sat => try sema.zirShl(block, inst, .shl_sat), | 1174 | .shl_sat => try sema.zirShl(block, inst, .shl_sat), |
| 1117 | 1175 | ||
| 1118 | .ret_ptr => try sema.zirRetPtr(block), | 1176 | .ret_ptr => try sema.zirRetPtr(block), |
| 1119 | .ret_type => try sema.addType(sema.fn_ret_ty), | 1177 | .ret_type => Air.internedToRef(sema.fn_ret_ty.toIntern()), |
| 1120 | 1178 | ||
| 1121 | // Instructions that we know to *always* be noreturn based solely on their tag. | 1179 | // Instructions that we know to *always* be noreturn based solely on their tag. |
| 1122 | // These functions match the return type of analyzeBody so that we can | 1180 | // These functions match the return type of analyzeBody so that we can |
| ... | @@ -1338,22 +1396,22 @@ fn analyzeBodyInner( | ... | @@ -1338,22 +1396,22 @@ fn analyzeBodyInner( |
| 1338 | continue; | 1396 | continue; |
| 1339 | }, | 1397 | }, |
| 1340 | .param => { | 1398 | .param => { |
| 1341 | try sema.zirParam(block, inst, false); | 1399 | try sema.zirParam(block, inst, i, false); |
| 1342 | i += 1; | 1400 | i += 1; |
| 1343 | continue; | 1401 | continue; |
| 1344 | }, | 1402 | }, |
| 1345 | .param_comptime => { | 1403 | .param_comptime => { |
| 1346 | try sema.zirParam(block, inst, true); | 1404 | try sema.zirParam(block, inst, i, true); |
| 1347 | i += 1; | 1405 | i += 1; |
| 1348 | continue; | 1406 | continue; |
| 1349 | }, | 1407 | }, |
| 1350 | .param_anytype => { | 1408 | .param_anytype => { |
| 1351 | try sema.zirParamAnytype(block, inst, false); | 1409 | try sema.zirParamAnytype(block, inst, i, false); |
| 1352 | i += 1; | 1410 | i += 1; |
| 1353 | continue; | 1411 | continue; |
| 1354 | }, | 1412 | }, |
| 1355 | .param_anytype_comptime => { | 1413 | .param_anytype_comptime => { |
| 1356 | try sema.zirParamAnytype(block, inst, true); | 1414 | try sema.zirParamAnytype(block, inst, i, true); |
| 1357 | i += 1; | 1415 | i += 1; |
| 1358 | continue; | 1416 | continue; |
| 1359 | }, | 1417 | }, |
| ... | @@ -1493,10 +1551,7 @@ fn analyzeBodyInner( | ... | @@ -1493,10 +1551,7 @@ fn analyzeBodyInner( |
| 1493 | // Note: this probably needs to be resolved in a more general manner. | 1551 | // Note: this probably needs to be resolved in a more general manner. |
| 1494 | const prev_params = block.params; | 1552 | const prev_params = block.params; |
| 1495 | block.params = .{}; | 1553 | block.params = .{}; |
| 1496 | defer { | 1554 | defer block.params = prev_params; |
| 1497 | block.params.deinit(sema.gpa); | ||
| 1498 | block.params = prev_params; | ||
| 1499 | } | ||
| 1500 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse | 1555 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1501 | break always_noreturn; | 1556 | break always_noreturn; |
| 1502 | if (inst == break_data.block_inst) { | 1557 | if (inst == break_data.block_inst) { |
| ... | @@ -1532,7 +1587,6 @@ fn analyzeBodyInner( | ... | @@ -1532,7 +1587,6 @@ fn analyzeBodyInner( |
| 1532 | .merges = undefined, | 1587 | .merges = undefined, |
| 1533 | }; | 1588 | }; |
| 1534 | child_block.label = &label; | 1589 | child_block.label = &label; |
| 1535 | defer child_block.params.deinit(gpa); | ||
| 1536 | 1590 | ||
| 1537 | // Write these instructions directly into the parent block | 1591 | // Write these instructions directly into the parent block |
| 1538 | child_block.instructions = block.instructions; | 1592 | child_block.instructions = block.instructions; |
| ... | @@ -2008,10 +2062,7 @@ fn resolveDefinedValue( | ... | @@ -2008,10 +2062,7 @@ fn resolveDefinedValue( |
| 2008 | /// Value Tag `variable` causes this function to return `null`. | 2062 | /// Value Tag `variable` causes this function to return `null`. |
| 2009 | /// Value Tag `undef` causes this function to return the Value. | 2063 | /// Value Tag `undef` causes this function to return the Value. |
| 2010 | /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. | 2064 | /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. |
| 2011 | fn resolveMaybeUndefVal( | 2065 | fn resolveMaybeUndefVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { |
| 2012 | sema: *Sema, | ||
| 2013 | inst: Air.Inst.Ref, | ||
| 2014 | ) CompileError!?Value { | ||
| 2015 | const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; | 2066 | const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; |
| 2016 | if (val.isGenericPoison()) return error.GenericPoison; | 2067 | if (val.isGenericPoison()) return error.GenericPoison; |
| 2017 | if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null; | 2068 | if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null; |
| ... | @@ -2022,10 +2073,7 @@ fn resolveMaybeUndefVal( | ... | @@ -2022,10 +2073,7 @@ fn resolveMaybeUndefVal( |
| 2022 | /// Value Tag `undef` causes this function to return the Value. | 2073 | /// Value Tag `undef` causes this function to return the Value. |
| 2023 | /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. | 2074 | /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. |
| 2024 | /// Lazy values are recursively resolved. | 2075 | /// Lazy values are recursively resolved. |
| 2025 | fn resolveMaybeUndefLazyVal( | 2076 | fn resolveMaybeUndefLazyVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { |
| 2026 | sema: *Sema, | ||
| 2027 | inst: Air.Inst.Ref, | ||
| 2028 | ) CompileError!?Value { | ||
| 2029 | return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null); | 2077 | return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null); |
| 2030 | } | 2078 | } |
| 2031 | 2079 | ||
| ... | @@ -2034,10 +2082,7 @@ fn resolveMaybeUndefLazyVal( | ... | @@ -2034,10 +2082,7 @@ fn resolveMaybeUndefLazyVal( |
| 2034 | /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. | 2082 | /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. |
| 2035 | /// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`. | 2083 | /// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`. |
| 2036 | /// Lazy values are recursively resolved. | 2084 | /// Lazy values are recursively resolved. |
| 2037 | fn resolveMaybeUndefValIntable( | 2085 | fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { |
| 2038 | sema: *Sema, | ||
| 2039 | inst: Air.Inst.Ref, | ||
| 2040 | ) CompileError!?Value { | ||
| 2041 | const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; | 2086 | const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; |
| 2042 | if (val.isGenericPoison()) return error.GenericPoison; | 2087 | if (val.isGenericPoison()) return error.GenericPoison; |
| 2043 | if (val.ip_index == .none) return val; | 2088 | if (val.ip_index == .none) return val; |
| ... | @@ -2363,7 +2408,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { | ... | @@ -2363,7 +2408,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { |
| 2363 | break :blk default_reference_trace_len; | 2408 | break :blk default_reference_trace_len; |
| 2364 | }; | 2409 | }; |
| 2365 | 2410 | ||
| 2366 | var referenced_by = if (sema.func) |some| some.owner_decl else sema.owner_decl_index; | 2411 | var referenced_by = if (sema.func_index != .none) |
| 2412 | mod.funcOwnerDeclIndex(sema.func_index) | ||
| 2413 | else | ||
| 2414 | sema.owner_decl_index; | ||
| 2367 | var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa); | 2415 | var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa); |
| 2368 | defer reference_stack.deinit(); | 2416 | defer reference_stack.deinit(); |
| 2369 | 2417 | ||
| ... | @@ -2399,14 +2447,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { | ... | @@ -2399,14 +2447,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { |
| 2399 | } | 2447 | } |
| 2400 | err_msg.reference_trace = try reference_stack.toOwnedSlice(); | 2448 | err_msg.reference_trace = try reference_stack.toOwnedSlice(); |
| 2401 | } | 2449 | } |
| 2402 | if (sema.owner_func) |func| { | 2450 | const ip = &mod.intern_pool; |
| 2403 | func.state = .sema_failure; | 2451 | if (sema.owner_func_index != .none) { |
| 2452 | ip.funcAnalysis(sema.owner_func_index).state = .sema_failure; | ||
| 2404 | } else { | 2453 | } else { |
| 2405 | sema.owner_decl.analysis = .sema_failure; | 2454 | sema.owner_decl.analysis = .sema_failure; |
| 2406 | sema.owner_decl.generation = mod.generation; | 2455 | sema.owner_decl.generation = mod.generation; |
| 2407 | } | 2456 | } |
| 2408 | if (sema.func) |func| { | 2457 | if (sema.func_index != .none) { |
| 2409 | func.state = .sema_failure; | 2458 | ip.funcAnalysis(sema.func_index).state = .sema_failure; |
| 2410 | } | 2459 | } |
| 2411 | const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index); | 2460 | const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index); |
| 2412 | if (gop.found_existing) { | 2461 | if (gop.found_existing) { |
| ... | @@ -2866,6 +2915,7 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2866,6 +2915,7 @@ fn createAnonymousDeclTypeNamed( |
| 2866 | inst: ?Zir.Inst.Index, | 2915 | inst: ?Zir.Inst.Index, |
| 2867 | ) !Decl.Index { | 2916 | ) !Decl.Index { |
| 2868 | const mod = sema.mod; | 2917 | const mod = sema.mod; |
| 2918 | const ip = &mod.intern_pool; | ||
| 2869 | const gpa = sema.gpa; | 2919 | const gpa = sema.gpa; |
| 2870 | const namespace = block.namespace; | 2920 | const namespace = block.namespace; |
| 2871 | const src_scope = block.wip_capture_scope; | 2921 | const src_scope = block.wip_capture_scope; |
| ... | @@ -2886,16 +2936,16 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2886,16 +2936,16 @@ fn createAnonymousDeclTypeNamed( |
| 2886 | const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ | 2936 | const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ |
| 2887 | src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index), | 2937 | src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index), |
| 2888 | }) catch unreachable; | 2938 | }) catch unreachable; |
| 2889 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2939 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); |
| 2890 | return new_decl_index; | 2940 | return new_decl_index; |
| 2891 | }, | 2941 | }, |
| 2892 | .parent => { | 2942 | .parent => { |
| 2893 | const name = mod.declPtr(block.src_decl).name; | 2943 | const name = mod.declPtr(block.src_decl).name; |
| 2894 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2944 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); |
| 2895 | return new_decl_index; | 2945 | return new_decl_index; |
| 2896 | }, | 2946 | }, |
| 2897 | .func => { | 2947 | .func => { |
| 2898 | const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst); | 2948 | const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index)); |
| 2899 | const zir_tags = sema.code.instructions.items(.tag); | 2949 | const zir_tags = sema.code.instructions.items(.tag); |
| 2900 | 2950 | ||
| 2901 | var buf = std.ArrayList(u8).init(gpa); | 2951 | var buf = std.ArrayList(u8).init(gpa); |
| ... | @@ -2927,7 +2977,7 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2927,7 +2977,7 @@ fn createAnonymousDeclTypeNamed( |
| 2927 | 2977 | ||
| 2928 | try writer.writeByte(')'); | 2978 | try writer.writeByte(')'); |
| 2929 | const name = try mod.intern_pool.getOrPutString(gpa, buf.items); | 2979 | const name = try mod.intern_pool.getOrPutString(gpa, buf.items); |
| 2930 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2980 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); |
| 2931 | return new_decl_index; | 2981 | return new_decl_index; |
| 2932 | }, | 2982 | }, |
| 2933 | .dbg_var => { | 2983 | .dbg_var => { |
| ... | @@ -2943,7 +2993,7 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2943,7 +2993,7 @@ fn createAnonymousDeclTypeNamed( |
| 2943 | src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code), | 2993 | src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code), |
| 2944 | }); | 2994 | }); |
| 2945 | 2995 | ||
| 2946 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | 2996 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); |
| 2947 | return new_decl_index; | 2997 | return new_decl_index; |
| 2948 | }, | 2998 | }, |
| 2949 | else => {}, | 2999 | else => {}, |
| ... | @@ -3070,18 +3120,12 @@ fn zirEnumDecl( | ... | @@ -3070,18 +3120,12 @@ fn zirEnumDecl( |
| 3070 | sema.owner_decl_index = prev_owner_decl_index; | 3120 | sema.owner_decl_index = prev_owner_decl_index; |
| 3071 | } | 3121 | } |
| 3072 | 3122 | ||
| 3073 | const prev_owner_func = sema.owner_func; | ||
| 3074 | const prev_owner_func_index = sema.owner_func_index; | 3123 | const prev_owner_func_index = sema.owner_func_index; |
| 3075 | sema.owner_func = null; | ||
| 3076 | sema.owner_func_index = .none; | 3124 | sema.owner_func_index = .none; |
| 3077 | defer sema.owner_func = prev_owner_func; | ||
| 3078 | defer sema.owner_func_index = prev_owner_func_index; | 3125 | defer sema.owner_func_index = prev_owner_func_index; |
| 3079 | 3126 | ||
| 3080 | const prev_func = sema.func; | ||
| 3081 | const prev_func_index = sema.func_index; | 3127 | const prev_func_index = sema.func_index; |
| 3082 | sema.func = null; | ||
| 3083 | sema.func_index = .none; | 3128 | sema.func_index = .none; |
| 3084 | defer sema.func = prev_func; | ||
| 3085 | defer sema.func_index = prev_func_index; | 3129 | defer sema.func_index = prev_func_index; |
| 3086 | 3130 | ||
| 3087 | var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope); | 3131 | var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope); |
| ... | @@ -3393,7 +3437,7 @@ fn zirErrorSetDecl( | ... | @@ -3393,7 +3437,7 @@ fn zirErrorSetDecl( |
| 3393 | const src = inst_data.src(); | 3437 | const src = inst_data.src(); |
| 3394 | const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); | 3438 | const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); |
| 3395 | 3439 | ||
| 3396 | var names: Module.Fn.InferredErrorSet.NameMap = .{}; | 3440 | var names: InferredErrorSet.NameMap = .{}; |
| 3397 | try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len); | 3441 | try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len); |
| 3398 | 3442 | ||
| 3399 | var extra_index = @as(u32, @intCast(extra.end)); | 3443 | var extra_index = @as(u32, @intCast(extra.end)); |
| ... | @@ -5236,12 +5280,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v | ... | @@ -5236,12 +5280,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 5236 | // %b = store(%a, %c) | 5280 | // %b = store(%a, %c) |
| 5237 | // Where %c is an error union or error set. In such case we need to add | 5281 | // Where %c is an error union or error set. In such case we need to add |
| 5238 | // to the current function's inferred error set, if any. | 5282 | // to the current function's inferred error set, if any. |
| 5239 | if (is_ret and (sema.typeOf(operand).zigTypeTag(mod) == .ErrorUnion or | 5283 | if (is_ret and sema.fn_ret_ty_ies != null) switch (sema.typeOf(operand).zigTypeTag(mod)) { |
| 5240 | sema.typeOf(operand).zigTypeTag(mod) == .ErrorSet) and | 5284 | .ErrorUnion, .ErrorSet => try sema.addToInferredErrorSet(operand), |
| 5241 | sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) | 5285 | else => {}, |
| 5242 | { | 5286 | }; |
| 5243 | try sema.addToInferredErrorSet(operand); | ||
| 5244 | } | ||
| 5245 | 5287 | ||
| 5246 | const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node }; | 5288 | const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node }; |
| 5247 | const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node }; | 5289 | const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node }; |
| ... | @@ -5379,7 +5421,10 @@ fn zirCompileLog( | ... | @@ -5379,7 +5421,10 @@ fn zirCompileLog( |
| 5379 | } | 5421 | } |
| 5380 | try writer.print("\n", .{}); | 5422 | try writer.print("\n", .{}); |
| 5381 | 5423 | ||
| 5382 | const decl_index = if (sema.func) |some| some.owner_decl else sema.owner_decl_index; | 5424 | const decl_index = if (sema.func_index != .none) |
| 5425 | mod.funcOwnerDeclIndex(sema.func_index) | ||
| 5426 | else | ||
| 5427 | sema.owner_decl_index; | ||
| 5383 | const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index); | 5428 | const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index); |
| 5384 | if (!gop.found_existing) { | 5429 | if (!gop.found_existing) { |
| 5385 | gop.value_ptr.* = src_node; | 5430 | gop.value_ptr.* = src_node; |
| ... | @@ -5967,11 +6012,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -5967,11 +6012,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 5967 | alignment.toByteUnitsOptional().?, | 6012 | alignment.toByteUnitsOptional().?, |
| 5968 | }); | 6013 | }); |
| 5969 | } | 6014 | } |
| 5970 | const func_index = sema.func_index.unwrap() orelse | 6015 | if (sema.func_index == .none) { |
| 5971 | return sema.fail(block, src, "@setAlignStack outside function body", .{}); | 6016 | return sema.fail(block, src, "@setAlignStack outside function body", .{}); |
| 5972 | const func = mod.funcPtr(func_index); | 6017 | } |
| 5973 | 6018 | ||
| 5974 | const fn_owner_decl = mod.declPtr(func.owner_decl); | 6019 | const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index); |
| 5975 | switch (fn_owner_decl.ty.fnCallingConvention(mod)) { | 6020 | switch (fn_owner_decl.ty.fnCallingConvention(mod)) { |
| 5976 | .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), | 6021 | .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), |
| 5977 | .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}), | 6022 | .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}), |
| ... | @@ -5980,25 +6025,34 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -5980,25 +6025,34 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 5980 | }, | 6025 | }, |
| 5981 | } | 6026 | } |
| 5982 | 6027 | ||
| 5983 | const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index); | 6028 | if (sema.prev_stack_alignment_src) |prev_src| { |
| 5984 | if (gop.found_existing) { | ||
| 5985 | const msg = msg: { | 6029 | const msg = msg: { |
| 5986 | const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{}); | 6030 | const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{}); |
| 5987 | errdefer msg.destroy(sema.gpa); | 6031 | errdefer msg.destroy(sema.gpa); |
| 5988 | try sema.errNote(block, gop.value_ptr.src, msg, "other instance here", .{}); | 6032 | try sema.errNote(block, prev_src, msg, "other instance here", .{}); |
| 5989 | break :msg msg; | 6033 | break :msg msg; |
| 5990 | }; | 6034 | }; |
| 5991 | return sema.failWithOwnedErrorMsg(msg); | 6035 | return sema.failWithOwnedErrorMsg(msg); |
| 5992 | } | 6036 | } |
| 5993 | gop.value_ptr.* = .{ .alignment = alignment, .src = src }; | 6037 | |
| 6038 | const ip = &mod.intern_pool; | ||
| 6039 | const a = ip.funcAnalysis(sema.func_index); | ||
| 6040 | if (a.stack_alignment != .none) { | ||
| 6041 | a.stack_alignment = @enumFromInt(@max( | ||
| 6042 | @intFromEnum(alignment), | ||
| 6043 | @intFromEnum(a.stack_alignment), | ||
| 6044 | )); | ||
| 6045 | } | ||
| 5994 | } | 6046 | } |
| 5995 | 6047 | ||
| 5996 | fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | 6048 | fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 6049 | const mod = sema.mod; | ||
| 6050 | const ip = &mod.intern_pool; | ||
| 5997 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 6051 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 5998 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 6052 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 5999 | const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, "operand to @setCold must be comptime-known"); | 6053 | const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, "operand to @setCold must be comptime-known"); |
| 6000 | const func = sema.func orelse return; // does nothing outside a function | 6054 | if (sema.func_index == .none) return; // does nothing outside a function |
| 6001 | func.is_cold = is_cold; | 6055 | ip.funcAnalysis(sema.func_index).is_cold = is_cold; |
| 6002 | } | 6056 | } |
| 6003 | 6057 | ||
| 6004 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | 6058 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| ... | @@ -6308,7 +6362,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl { | ... | @@ -6308,7 +6362,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl { |
| 6308 | if (func_val.isUndef(mod)) return null; | 6362 | if (func_val.isUndef(mod)) return null; |
| 6309 | const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { | 6363 | const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { |
| 6310 | .extern_func => |extern_func| extern_func.decl, | 6364 | .extern_func => |extern_func| extern_func.decl, |
| 6311 | .func => |func| mod.funcPtr(func.index).owner_decl, | 6365 | .func => |func| func.owner_decl, |
| 6312 | .ptr => |ptr| switch (ptr.addr) { | 6366 | .ptr => |ptr| switch (ptr.addr) { |
| 6313 | .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl, | 6367 | .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl, |
| 6314 | else => return null, | 6368 | else => return null, |
| ... | @@ -6445,6 +6499,7 @@ fn zirCall( | ... | @@ -6445,6 +6499,7 @@ fn zirCall( |
| 6445 | defer tracy.end(); | 6499 | defer tracy.end(); |
| 6446 | 6500 | ||
| 6447 | const mod = sema.mod; | 6501 | const mod = sema.mod; |
| 6502 | const ip = &mod.intern_pool; | ||
| 6448 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 6503 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6449 | const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; | 6504 | const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; |
| 6450 | const call_src = inst_data.src(); | 6505 | const call_src = inst_data.src(); |
| ... | @@ -6493,9 +6548,10 @@ fn zirCall( | ... | @@ -6493,9 +6548,10 @@ fn zirCall( |
| 6493 | const args_body = sema.code.extra[extra.end..]; | 6548 | const args_body = sema.code.extra[extra.end..]; |
| 6494 | 6549 | ||
| 6495 | var input_is_error = false; | 6550 | var input_is_error = false; |
| 6496 | const block_index = @as(Air.Inst.Index, @intCast(block.instructions.items.len)); | 6551 | const block_index: Air.Inst.Index = @intCast(block.instructions.items.len); |
| 6497 | 6552 | ||
| 6498 | const fn_params_len = mod.typeToFunc(func_ty).?.param_types.len; | 6553 | const func_ty_info = mod.typeToFunc(func_ty).?; |
| 6554 | const fn_params_len = func_ty_info.param_types.len; | ||
| 6499 | const parent_comptime = block.is_comptime; | 6555 | const parent_comptime = block.is_comptime; |
| 6500 | // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument. | 6556 | // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument. |
| 6501 | var extra_index: usize = 0; | 6557 | var extra_index: usize = 0; |
| ... | @@ -6504,13 +6560,12 @@ fn zirCall( | ... | @@ -6504,13 +6560,12 @@ fn zirCall( |
| 6504 | extra_index += 1; | 6560 | extra_index += 1; |
| 6505 | arg_index += 1; | 6561 | arg_index += 1; |
| 6506 | }) { | 6562 | }) { |
| 6507 | const func_ty_info = mod.typeToFunc(func_ty).?; | ||
| 6508 | const arg_end = sema.code.extra[extra.end + extra_index]; | 6563 | const arg_end = sema.code.extra[extra.end + extra_index]; |
| 6509 | defer arg_start = arg_end; | 6564 | defer arg_start = arg_end; |
| 6510 | 6565 | ||
| 6511 | // Generate args to comptime params in comptime block. | 6566 | // Generate args to comptime params in comptime block. |
| 6512 | defer block.is_comptime = parent_comptime; | 6567 | defer block.is_comptime = parent_comptime; |
| 6513 | if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@as(u5, @intCast(arg_index)))) { | 6568 | if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@intCast(arg_index))) { |
| 6514 | block.is_comptime = true; | 6569 | block.is_comptime = true; |
| 6515 | // TODO set comptime_reason | 6570 | // TODO set comptime_reason |
| 6516 | } | 6571 | } |
| ... | @@ -6519,10 +6574,10 @@ fn zirCall( | ... | @@ -6519,10 +6574,10 @@ fn zirCall( |
| 6519 | if (arg_index >= fn_params_len) | 6574 | if (arg_index >= fn_params_len) |
| 6520 | break :inst Air.Inst.Ref.var_args_param_type; | 6575 | break :inst Air.Inst.Ref.var_args_param_type; |
| 6521 | 6576 | ||
| 6522 | if (func_ty_info.param_types[arg_index] == .generic_poison_type) | 6577 | if (func_ty_info.param_types.get(ip)[arg_index] == .generic_poison_type) |
| 6523 | break :inst Air.Inst.Ref.generic_poison_type; | 6578 | break :inst Air.Inst.Ref.generic_poison_type; |
| 6524 | 6579 | ||
| 6525 | break :inst try sema.addType(func_ty_info.param_types[arg_index].toType()); | 6580 | break :inst try sema.addType(func_ty_info.param_types.get(ip)[arg_index].toType()); |
| 6526 | }); | 6581 | }); |
| 6527 | 6582 | ||
| 6528 | const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); | 6583 | const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); |
| ... | @@ -6535,7 +6590,9 @@ fn zirCall( | ... | @@ -6535,7 +6590,9 @@ fn zirCall( |
| 6535 | } | 6590 | } |
| 6536 | resolved_args[arg_index] = resolved; | 6591 | resolved_args[arg_index] = resolved; |
| 6537 | } | 6592 | } |
| 6538 | if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn) { | 6593 | if (sema.owner_func_index == .none or |
| 6594 | !ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) | ||
| 6595 | { | ||
| 6539 | input_is_error = false; // input was an error type, but no errorable fn's were actually called | 6596 | input_is_error = false; // input was an error type, but no errorable fn's were actually called |
| 6540 | } | 6597 | } |
| 6541 | 6598 | ||
| ... | @@ -6702,6 +6759,7 @@ fn analyzeCall( | ... | @@ -6702,6 +6759,7 @@ fn analyzeCall( |
| 6702 | call_dbg_node: ?Zir.Inst.Index, | 6759 | call_dbg_node: ?Zir.Inst.Index, |
| 6703 | ) CompileError!Air.Inst.Ref { | 6760 | ) CompileError!Air.Inst.Ref { |
| 6704 | const mod = sema.mod; | 6761 | const mod = sema.mod; |
| 6762 | const ip = &mod.intern_pool; | ||
| 6705 | 6763 | ||
| 6706 | const callee_ty = sema.typeOf(func); | 6764 | const callee_ty = sema.typeOf(func); |
| 6707 | const func_ty_info = mod.typeToFunc(func_ty).?; | 6765 | const func_ty_info = mod.typeToFunc(func_ty).?; |
| ... | @@ -6749,20 +6807,17 @@ fn analyzeCall( | ... | @@ -6749,20 +6807,17 @@ fn analyzeCall( |
| 6749 | 6807 | ||
| 6750 | var is_generic_call = func_ty_info.is_generic; | 6808 | var is_generic_call = func_ty_info.is_generic; |
| 6751 | var is_comptime_call = block.is_comptime or modifier == .compile_time; | 6809 | var is_comptime_call = block.is_comptime or modifier == .compile_time; |
| 6752 | var comptime_reason_buf: Block.ComptimeReason = undefined; | ||
| 6753 | var comptime_reason: ?*const Block.ComptimeReason = null; | 6810 | var comptime_reason: ?*const Block.ComptimeReason = null; |
| 6754 | if (!is_comptime_call) { | 6811 | if (!is_comptime_call) { |
| 6755 | if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| { | 6812 | if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| { |
| 6756 | is_comptime_call = ct; | 6813 | is_comptime_call = ct; |
| 6757 | if (ct) { | 6814 | if (ct) { |
| 6758 | // stage1 can't handle doing this directly | 6815 | comptime_reason = &.{ .comptime_ret_ty = .{ |
| 6759 | comptime_reason_buf = .{ .comptime_ret_ty = .{ | ||
| 6760 | .block = block, | 6816 | .block = block, |
| 6761 | .func = func, | 6817 | .func = func, |
| 6762 | .func_src = func_src, | 6818 | .func_src = func_src, |
| 6763 | .return_ty = func_ty_info.return_type.toType(), | 6819 | .return_ty = func_ty_info.return_type.toType(), |
| 6764 | } }; | 6820 | } }; |
| 6765 | comptime_reason = &comptime_reason_buf; | ||
| 6766 | } | 6821 | } |
| 6767 | } else |err| switch (err) { | 6822 | } else |err| switch (err) { |
| 6768 | error.GenericPoison => is_generic_call = true, | 6823 | error.GenericPoison => is_generic_call = true, |
| ... | @@ -6778,7 +6833,6 @@ fn analyzeCall( | ... | @@ -6778,7 +6833,6 @@ fn analyzeCall( |
| 6778 | func, | 6833 | func, |
| 6779 | func_src, | 6834 | func_src, |
| 6780 | call_src, | 6835 | call_src, |
| 6781 | func_ty, | ||
| 6782 | ensure_result_used, | 6836 | ensure_result_used, |
| 6783 | uncasted_args, | 6837 | uncasted_args, |
| 6784 | call_tag, | 6838 | call_tag, |
| ... | @@ -6793,14 +6847,12 @@ fn analyzeCall( | ... | @@ -6793,14 +6847,12 @@ fn analyzeCall( |
| 6793 | error.ComptimeReturn => { | 6847 | error.ComptimeReturn => { |
| 6794 | is_inline_call = true; | 6848 | is_inline_call = true; |
| 6795 | is_comptime_call = true; | 6849 | is_comptime_call = true; |
| 6796 | // stage1 can't handle doing this directly | 6850 | comptime_reason = &.{ .comptime_ret_ty = .{ |
| 6797 | comptime_reason_buf = .{ .comptime_ret_ty = .{ | ||
| 6798 | .block = block, | 6851 | .block = block, |
| 6799 | .func = func, | 6852 | .func = func, |
| 6800 | .func_src = func_src, | 6853 | .func_src = func_src, |
| 6801 | .return_ty = func_ty_info.return_type.toType(), | 6854 | .return_ty = func_ty_info.return_type.toType(), |
| 6802 | } }; | 6855 | } }; |
| 6803 | comptime_reason = &comptime_reason_buf; | ||
| 6804 | }, | 6856 | }, |
| 6805 | else => |e| return e, | 6857 | else => |e| return e, |
| 6806 | } | 6858 | } |
| ... | @@ -6819,9 +6871,9 @@ fn analyzeCall( | ... | @@ -6819,9 +6871,9 @@ fn analyzeCall( |
| 6819 | .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{ | 6871 | .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{ |
| 6820 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), | 6872 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), |
| 6821 | }), | 6873 | }), |
| 6822 | .func => |function| function.index, | 6874 | .func => func_val.toIntern(), |
| 6823 | .ptr => |ptr| switch (ptr.addr) { | 6875 | .ptr => |ptr| switch (ptr.addr) { |
| 6824 | .decl => |decl| mod.declPtr(decl).val.getFunctionIndex(mod).unwrap().?, | 6876 | .decl => |decl| mod.declPtr(decl).val.toIntern(), |
| 6825 | else => { | 6877 | else => { |
| 6826 | assert(callee_ty.isPtrAtRuntime(mod)); | 6878 | assert(callee_ty.isPtrAtRuntime(mod)); |
| 6827 | return sema.fail(block, call_src, "{s} call of function pointer", .{ | 6879 | return sema.fail(block, call_src, "{s} call of function pointer", .{ |
| ... | @@ -6850,7 +6902,7 @@ fn analyzeCall( | ... | @@ -6850,7 +6902,7 @@ fn analyzeCall( |
| 6850 | // This one is shared among sub-blocks within the same callee, but not | 6902 | // This one is shared among sub-blocks within the same callee, but not |
| 6851 | // shared among the entire inline/comptime call stack. | 6903 | // shared among the entire inline/comptime call stack. |
| 6852 | var inlining: Block.Inlining = .{ | 6904 | var inlining: Block.Inlining = .{ |
| 6853 | .func = null, | 6905 | .func = .none, |
| 6854 | .comptime_result = undefined, | 6906 | .comptime_result = undefined, |
| 6855 | .merges = .{ | 6907 | .merges = .{ |
| 6856 | .src_locs = .{}, | 6908 | .src_locs = .{}, |
| ... | @@ -6862,7 +6914,7 @@ fn analyzeCall( | ... | @@ -6862,7 +6914,7 @@ fn analyzeCall( |
| 6862 | // In order to save a bit of stack space, directly modify Sema rather | 6914 | // In order to save a bit of stack space, directly modify Sema rather |
| 6863 | // than create a child one. | 6915 | // than create a child one. |
| 6864 | const parent_zir = sema.code; | 6916 | const parent_zir = sema.code; |
| 6865 | const module_fn = mod.funcPtr(module_fn_index); | 6917 | const module_fn = mod.funcInfo(module_fn_index); |
| 6866 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 6918 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); |
| 6867 | sema.code = fn_owner_decl.getFileScope(mod).zir; | 6919 | sema.code = fn_owner_decl.getFileScope(mod).zir; |
| 6868 | defer sema.code = parent_zir; | 6920 | defer sema.code = parent_zir; |
| ... | @@ -6877,11 +6929,8 @@ fn analyzeCall( | ... | @@ -6877,11 +6929,8 @@ fn analyzeCall( |
| 6877 | sema.inst_map = parent_inst_map; | 6929 | sema.inst_map = parent_inst_map; |
| 6878 | } | 6930 | } |
| 6879 | 6931 | ||
| 6880 | const parent_func = sema.func; | ||
| 6881 | const parent_func_index = sema.func_index; | 6932 | const parent_func_index = sema.func_index; |
| 6882 | sema.func = module_fn; | 6933 | sema.func_index = module_fn_index; |
| 6883 | sema.func_index = module_fn_index.toOptional(); | ||
| 6884 | defer sema.func = parent_func; | ||
| 6885 | defer sema.func_index = parent_func_index; | 6934 | defer sema.func_index = parent_func_index; |
| 6886 | 6935 | ||
| 6887 | const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry; | 6936 | const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry; |
| ... | @@ -6913,16 +6962,28 @@ fn analyzeCall( | ... | @@ -6913,16 +6962,28 @@ fn analyzeCall( |
| 6913 | 6962 | ||
| 6914 | try sema.emitBackwardBranch(block, call_src); | 6963 | try sema.emitBackwardBranch(block, call_src); |
| 6915 | 6964 | ||
| 6916 | // Whether this call should be memoized, set to false if the call can mutate comptime state. | 6965 | // Whether this call should be memoized, set to false if the call can |
| 6966 | // mutate comptime state. | ||
| 6917 | var should_memoize = true; | 6967 | var should_memoize = true; |
| 6918 | 6968 | ||
| 6919 | // If it's a comptime function call, we need to memoize it as long as no external | 6969 | // If it's a comptime function call, we need to memoize it as long as no external |
| 6920 | // comptime memory is mutated. | 6970 | // comptime memory is mutated. |
| 6921 | const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); | 6971 | const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); |
| 6922 | 6972 | ||
| 6923 | var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?; | 6973 | const owner_info = mod.typeToFunc(fn_owner_decl.ty).?; |
| 6924 | new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len); | 6974 | var new_fn_info: InternPool.GetFuncTypeKey = .{ |
| 6925 | new_fn_info.comptime_bits = 0; | 6975 | .param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len), |
| 6976 | .return_type = owner_info.return_type, | ||
| 6977 | .comptime_bits = 0, | ||
| 6978 | .noalias_bits = owner_info.noalias_bits, | ||
| 6979 | .alignment = if (owner_info.align_is_generic) null else owner_info.alignment, | ||
| 6980 | .cc = if (owner_info.cc_is_generic) null else owner_info.cc, | ||
| 6981 | .is_var_args = owner_info.is_var_args, | ||
| 6982 | .is_noinline = owner_info.is_noinline, | ||
| 6983 | .section_is_generic = owner_info.section_is_generic, | ||
| 6984 | .addrspace_is_generic = owner_info.addrspace_is_generic, | ||
| 6985 | .is_generic = owner_info.is_generic, | ||
| 6986 | }; | ||
| 6926 | 6987 | ||
| 6927 | // This will have return instructions analyzed as break instructions to | 6988 | // This will have return instructions analyzed as break instructions to |
| 6928 | // the block_inst above. Here we are performing "comptime/inline semantic analysis" | 6989 | // the block_inst above. Here we are performing "comptime/inline semantic analysis" |
| ... | @@ -6934,59 +6995,46 @@ fn analyzeCall( | ... | @@ -6934,59 +6995,46 @@ fn analyzeCall( |
| 6934 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body); | 6995 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body); |
| 6935 | 6996 | ||
| 6936 | var has_comptime_args = false; | 6997 | var has_comptime_args = false; |
| 6937 | var arg_i: usize = 0; | 6998 | var arg_i: u32 = 0; |
| 6938 | for (fn_info.param_body) |inst| { | 6999 | for (fn_info.param_body) |inst| { |
| 6939 | sema.analyzeInlineCallArg( | 7000 | const arg_src: LazySrcLoc = if (arg_i == 0 and bound_arg_src != null) |
| 7001 | bound_arg_src.? | ||
| 7002 | else | ||
| 7003 | .{ .call_arg = .{ | ||
| 7004 | .decl = block.src_decl, | ||
| 7005 | .call_node_offset = call_src.node_offset.x, | ||
| 7006 | .arg_index = arg_i - @intFromBool(bound_arg_src != null), | ||
| 7007 | } }; | ||
| 7008 | try sema.analyzeInlineCallArg( | ||
| 6940 | block, | 7009 | block, |
| 6941 | &child_block, | 7010 | &child_block, |
| 6942 | .unneeded, | 7011 | arg_src, |
| 6943 | inst, | 7012 | inst, |
| 6944 | &new_fn_info, | 7013 | new_fn_info.param_types, |
| 6945 | &arg_i, | 7014 | &arg_i, |
| 6946 | uncasted_args, | 7015 | uncasted_args, |
| 6947 | is_comptime_call, | 7016 | is_comptime_call, |
| 6948 | &should_memoize, | 7017 | &should_memoize, |
| 6949 | memoized_arg_values, | 7018 | memoized_arg_values, |
| 6950 | mod.typeToFunc(func_ty).?.param_types, | 7019 | func_ty_info.param_types, |
| 6951 | func, | 7020 | func, |
| 6952 | &has_comptime_args, | 7021 | &has_comptime_args, |
| 6953 | ) catch |err| switch (err) { | 7022 | ); |
| 6954 | error.NeededSourceLocation => { | ||
| 6955 | _ = sema.inst_map.remove(inst); | ||
| 6956 | const decl = mod.declPtr(block.src_decl); | ||
| 6957 | try sema.analyzeInlineCallArg( | ||
| 6958 | block, | ||
| 6959 | &child_block, | ||
| 6960 | mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src), | ||
| 6961 | inst, | ||
| 6962 | &new_fn_info, | ||
| 6963 | &arg_i, | ||
| 6964 | uncasted_args, | ||
| 6965 | is_comptime_call, | ||
| 6966 | &should_memoize, | ||
| 6967 | memoized_arg_values, | ||
| 6968 | mod.typeToFunc(func_ty).?.param_types, | ||
| 6969 | func, | ||
| 6970 | &has_comptime_args, | ||
| 6971 | ); | ||
| 6972 | unreachable; | ||
| 6973 | }, | ||
| 6974 | else => |e| return e, | ||
| 6975 | }; | ||
| 6976 | } | 7023 | } |
| 6977 | 7024 | ||
| 6978 | if (!has_comptime_args and module_fn.state == .sema_failure) return error.AnalysisFail; | 7025 | if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure) |
| 7026 | return error.AnalysisFail; | ||
| 6979 | 7027 | ||
| 6980 | const recursive_msg = "inline call is recursive"; | 7028 | const recursive_msg = "inline call is recursive"; |
| 6981 | var head = if (!has_comptime_args) block else null; | 7029 | var head = if (!has_comptime_args) block else null; |
| 6982 | while (head) |some| { | 7030 | while (head) |some| { |
| 6983 | const parent_inlining = some.inlining orelse break; | 7031 | const parent_inlining = some.inlining orelse break; |
| 6984 | if (parent_inlining.func == module_fn) { | 7032 | if (parent_inlining.func == module_fn_index) { |
| 6985 | return sema.fail(block, call_src, recursive_msg, .{}); | 7033 | return sema.fail(block, call_src, recursive_msg, .{}); |
| 6986 | } | 7034 | } |
| 6987 | head = some.parent; | 7035 | head = some.parent; |
| 6988 | } | 7036 | } |
| 6989 | if (!has_comptime_args) inlining.func = module_fn; | 7037 | if (!has_comptime_args) inlining.func = module_fn_index; |
| 6990 | 7038 | ||
| 6991 | // In case it is a generic function with an expression for the return type that depends | 7039 | // In case it is a generic function with an expression for the return type that depends |
| 6992 | // on parameters, we must now do the same for the return type as we just did with | 7040 | // on parameters, we must now do the same for the return type as we just did with |
| ... | @@ -6998,21 +7046,32 @@ fn analyzeCall( | ... | @@ -6998,21 +7046,32 @@ fn analyzeCall( |
| 6998 | try sema.resolveInst(fn_info.ret_ty_ref); | 7046 | try sema.resolveInst(fn_info.ret_ty_ref); |
| 6999 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | 7047 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 7000 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); | 7048 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); |
| 7001 | // Create a fresh inferred error set type for inline/comptime calls. | ||
| 7002 | const fn_ret_ty = blk: { | ||
| 7003 | if (module_fn.hasInferredErrorSet(mod)) { | ||
| 7004 | const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{ | ||
| 7005 | .func = module_fn_index, | ||
| 7006 | }); | ||
| 7007 | const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index }); | ||
| 7008 | break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type); | ||
| 7009 | } | ||
| 7010 | break :blk bare_return_type; | ||
| 7011 | }; | ||
| 7012 | new_fn_info.return_type = fn_ret_ty.toIntern(); | ||
| 7013 | const parent_fn_ret_ty = sema.fn_ret_ty; | 7049 | const parent_fn_ret_ty = sema.fn_ret_ty; |
| 7014 | sema.fn_ret_ty = fn_ret_ty; | 7050 | const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies; |
| 7051 | const parent_generic_owner = sema.generic_owner; | ||
| 7052 | const parent_generic_call_src = sema.generic_call_src; | ||
| 7053 | const parent_generic_call_decl = sema.generic_call_decl; | ||
| 7054 | sema.fn_ret_ty = bare_return_type; | ||
| 7055 | sema.fn_ret_ty_ies = null; | ||
| 7056 | sema.generic_owner = .none; | ||
| 7057 | sema.generic_call_src = .unneeded; | ||
| 7058 | sema.generic_call_decl = .none; | ||
| 7015 | defer sema.fn_ret_ty = parent_fn_ret_ty; | 7059 | defer sema.fn_ret_ty = parent_fn_ret_ty; |
| 7060 | defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies; | ||
| 7061 | defer sema.generic_owner = parent_generic_owner; | ||
| 7062 | defer sema.generic_call_src = parent_generic_call_src; | ||
| 7063 | defer sema.generic_call_decl = parent_generic_call_decl; | ||
| 7064 | |||
| 7065 | if (module_fn.analysis(ip).inferred_error_set) { | ||
| 7066 | // Create a fresh inferred error set type for inline/comptime calls. | ||
| 7067 | const ies = try sema.arena.create(InferredErrorSet); | ||
| 7068 | ies.* = .{ .func = .none }; | ||
| 7069 | sema.fn_ret_ty_ies = ies; | ||
| 7070 | sema.fn_ret_ty = (try ip.get(gpa, .{ .error_union_type = .{ | ||
| 7071 | .error_set_type = .adhoc_inferred_error_set_type, | ||
| 7072 | .payload_type = bare_return_type.toIntern(), | ||
| 7073 | } })).toType(); | ||
| 7074 | } | ||
| 7016 | 7075 | ||
| 7017 | // This `res2` is here instead of directly breaking from `res` due to a stage1 | 7076 | // This `res2` is here instead of directly breaking from `res` due to a stage1 |
| 7018 | // bug generating invalid LLVM IR. | 7077 | // bug generating invalid LLVM IR. |
| ... | @@ -7030,9 +7089,10 @@ fn analyzeCall( | ... | @@ -7030,9 +7089,10 @@ fn analyzeCall( |
| 7030 | } | 7089 | } |
| 7031 | } | 7090 | } |
| 7032 | 7091 | ||
| 7092 | new_fn_info.return_type = sema.fn_ret_ty.toIntern(); | ||
| 7033 | const new_func_resolved_ty = try mod.funcType(new_fn_info); | 7093 | const new_func_resolved_ty = try mod.funcType(new_fn_info); |
| 7034 | if (!is_comptime_call and !block.is_typeof) { | 7094 | if (!is_comptime_call and !block.is_typeof) { |
| 7035 | try sema.emitDbgInline(block, parent_func_index.unwrap().?, module_fn_index, new_func_resolved_ty, .dbg_inline_begin); | 7095 | try sema.emitDbgInline(block, parent_func_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin); |
| 7036 | 7096 | ||
| 7037 | const zir_tags = sema.code.instructions.items(.tag); | 7097 | const zir_tags = sema.code.instructions.items(.tag); |
| 7038 | for (fn_info.param_body) |param| switch (zir_tags[param]) { | 7098 | for (fn_info.param_body) |param| switch (zir_tags[param]) { |
| ... | @@ -7056,7 +7116,7 @@ fn analyzeCall( | ... | @@ -7056,7 +7116,7 @@ fn analyzeCall( |
| 7056 | } | 7116 | } |
| 7057 | 7117 | ||
| 7058 | if (is_comptime_call and ensure_result_used) { | 7118 | if (is_comptime_call and ensure_result_used) { |
| 7059 | try sema.ensureResultUsed(block, fn_ret_ty, call_src); | 7119 | try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); |
| 7060 | } | 7120 | } |
| 7061 | 7121 | ||
| 7062 | const result = result: { | 7122 | const result = result: { |
| ... | @@ -7074,26 +7134,47 @@ fn analyzeCall( | ... | @@ -7074,26 +7134,47 @@ fn analyzeCall( |
| 7074 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); | 7134 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); |
| 7075 | }; | 7135 | }; |
| 7076 | 7136 | ||
| 7077 | if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) { | 7137 | if (!is_comptime_call and !block.is_typeof and |
| 7138 | sema.typeOf(result).zigTypeTag(mod) != .NoReturn) | ||
| 7139 | { | ||
| 7078 | try sema.emitDbgInline( | 7140 | try sema.emitDbgInline( |
| 7079 | block, | 7141 | block, |
| 7080 | module_fn_index, | 7142 | module_fn_index, |
| 7081 | parent_func_index.unwrap().?, | 7143 | parent_func_index, |
| 7082 | mod.declPtr(parent_func.?.owner_decl).ty, | 7144 | mod.funcOwnerDeclPtr(parent_func_index).ty, |
| 7083 | .dbg_inline_end, | 7145 | .dbg_inline_end, |
| 7084 | ); | 7146 | ); |
| 7085 | } | 7147 | } |
| 7086 | 7148 | ||
| 7087 | if (should_memoize and is_comptime_call) { | 7149 | if (should_memoize and is_comptime_call) { |
| 7088 | const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, ""); | 7150 | const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, ""); |
| 7151 | const result_interned = try result_val.intern2(sema.fn_ret_ty, mod); | ||
| 7152 | |||
| 7153 | // Transform ad-hoc inferred error set types into concrete error sets. | ||
| 7154 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); | ||
| 7089 | 7155 | ||
| 7090 | // TODO: check whether any external comptime memory was mutated by the | 7156 | // TODO: check whether any external comptime memory was mutated by the |
| 7091 | // comptime function call. If so, then do not memoize the call here. | 7157 | // comptime function call. If so, then do not memoize the call here. |
| 7092 | _ = try mod.intern(.{ .memoized_call = .{ | 7158 | _ = try mod.intern(.{ .memoized_call = .{ |
| 7093 | .func = module_fn_index, | 7159 | .func = module_fn_index, |
| 7094 | .arg_values = memoized_arg_values, | 7160 | .arg_values = memoized_arg_values, |
| 7095 | .result = try result_val.intern(fn_ret_ty, mod), | 7161 | .result = result_transformed, |
| 7096 | } }); | 7162 | } }); |
| 7163 | |||
| 7164 | break :res2 Air.internedToRef(result_transformed); | ||
| 7165 | } | ||
| 7166 | |||
| 7167 | if (try sema.resolveMaybeUndefVal(result)) |result_val| { | ||
| 7168 | const result_interned = try result_val.intern2(sema.fn_ret_ty, mod); | ||
| 7169 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); | ||
| 7170 | break :res2 Air.internedToRef(result_transformed); | ||
| 7171 | } | ||
| 7172 | |||
| 7173 | const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern()); | ||
| 7174 | if (new_ty != .none) { | ||
| 7175 | // TODO: mutate in place the previous instruction if possible | ||
| 7176 | // rather than adding a bitcast instruction. | ||
| 7177 | break :res2 try block.addBitCast(new_ty.toType(), result); | ||
| 7097 | } | 7178 | } |
| 7098 | 7179 | ||
| 7099 | break :res2 result; | 7180 | break :res2 result; |
| ... | @@ -7110,9 +7191,9 @@ fn analyzeCall( | ... | @@ -7110,9 +7191,9 @@ fn analyzeCall( |
| 7110 | if (i < fn_params_len) { | 7191 | if (i < fn_params_len) { |
| 7111 | const opts: CoerceOpts = .{ .param_src = .{ | 7192 | const opts: CoerceOpts = .{ .param_src = .{ |
| 7112 | .func_inst = func, | 7193 | .func_inst = func, |
| 7113 | .param_i = @as(u32, @intCast(i)), | 7194 | .param_i = @intCast(i), |
| 7114 | } }; | 7195 | } }; |
| 7115 | const param_ty = mod.typeToFunc(func_ty).?.param_types[i].toType(); | 7196 | const param_ty = func_ty_info.param_types.get(ip)[i].toType(); |
| 7116 | args[i] = sema.analyzeCallArg( | 7197 | args[i] = sema.analyzeCallArg( |
| 7117 | block, | 7198 | block, |
| 7118 | .unneeded, | 7199 | .unneeded, |
| ... | @@ -7152,13 +7233,13 @@ fn analyzeCall( | ... | @@ -7152,13 +7233,13 @@ fn analyzeCall( |
| 7152 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); | 7233 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); |
| 7153 | 7234 | ||
| 7154 | try sema.queueFullTypeResolution(func_ty_info.return_type.toType()); | 7235 | try sema.queueFullTypeResolution(func_ty_info.return_type.toType()); |
| 7155 | if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) { | 7236 | if (sema.owner_func_index != .none and func_ty_info.return_type.toType().isError(mod)) { |
| 7156 | sema.owner_func.?.calls_or_awaits_errorable_fn = true; | 7237 | ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true; |
| 7157 | } | 7238 | } |
| 7158 | 7239 | ||
| 7159 | if (try sema.resolveMaybeUndefVal(func)) |func_val| { | 7240 | if (try sema.resolveMaybeUndefVal(func)) |func_val| { |
| 7160 | if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| { | 7241 | if (mod.intern_pool.isFuncBody(func_val.toIntern())) { |
| 7161 | try mod.ensureFuncBodyAnalysisQueued(func_index); | 7242 | try mod.ensureFuncBodyAnalysisQueued(func_val.toIntern()); |
| 7162 | } | 7243 | } |
| 7163 | } | 7244 | } |
| 7164 | 7245 | ||
| ... | @@ -7219,7 +7300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ | ... | @@ -7219,7 +7300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ |
| 7219 | @tagName(backend), @tagName(target.cpu.arch), | 7300 | @tagName(backend), @tagName(target.cpu.arch), |
| 7220 | }); | 7301 | }); |
| 7221 | } | 7302 | } |
| 7222 | const func_decl = mod.declPtr(sema.owner_func.?.owner_decl); | 7303 | const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index); |
| 7223 | if (!func_ty.eql(func_decl.ty, mod)) { | 7304 | if (!func_ty.eql(func_decl.ty, mod)) { |
| 7224 | return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{ | 7305 | return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{ |
| 7225 | func_ty.fmt(mod), func_decl.ty.fmt(mod), | 7306 | func_ty.fmt(mod), func_decl.ty.fmt(mod), |
| ... | @@ -7235,17 +7316,18 @@ fn analyzeInlineCallArg( | ... | @@ -7235,17 +7316,18 @@ fn analyzeInlineCallArg( |
| 7235 | param_block: *Block, | 7316 | param_block: *Block, |
| 7236 | arg_src: LazySrcLoc, | 7317 | arg_src: LazySrcLoc, |
| 7237 | inst: Zir.Inst.Index, | 7318 | inst: Zir.Inst.Index, |
| 7238 | new_fn_info: *InternPool.Key.FuncType, | 7319 | new_param_types: []InternPool.Index, |
| 7239 | arg_i: *usize, | 7320 | arg_i: *u32, |
| 7240 | uncasted_args: []const Air.Inst.Ref, | 7321 | uncasted_args: []const Air.Inst.Ref, |
| 7241 | is_comptime_call: bool, | 7322 | is_comptime_call: bool, |
| 7242 | should_memoize: *bool, | 7323 | should_memoize: *bool, |
| 7243 | memoized_arg_values: []InternPool.Index, | 7324 | memoized_arg_values: []InternPool.Index, |
| 7244 | raw_param_types: []const InternPool.Index, | 7325 | raw_param_types: InternPool.Index.Slice, |
| 7245 | func_inst: Air.Inst.Ref, | 7326 | func_inst: Air.Inst.Ref, |
| 7246 | has_comptime_args: *bool, | 7327 | has_comptime_args: *bool, |
| 7247 | ) !void { | 7328 | ) !void { |
| 7248 | const mod = sema.mod; | 7329 | const mod = sema.mod; |
| 7330 | const ip = &mod.intern_pool; | ||
| 7249 | const zir_tags = sema.code.instructions.items(.tag); | 7331 | const zir_tags = sema.code.instructions.items(.tag); |
| 7250 | switch (zir_tags[inst]) { | 7332 | switch (zir_tags[inst]) { |
| 7251 | .param_comptime, .param_anytype_comptime => has_comptime_args.* = true, | 7333 | .param_comptime, .param_anytype_comptime => has_comptime_args.* = true, |
| ... | @@ -7260,13 +7342,13 @@ fn analyzeInlineCallArg( | ... | @@ -7260,13 +7342,13 @@ fn analyzeInlineCallArg( |
| 7260 | const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index); | 7342 | const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index); |
| 7261 | const param_body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 7343 | const param_body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 7262 | const param_ty = param_ty: { | 7344 | const param_ty = param_ty: { |
| 7263 | const raw_param_ty = raw_param_types[arg_i.*]; | 7345 | const raw_param_ty = raw_param_types.get(ip)[arg_i.*]; |
| 7264 | if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty; | 7346 | if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty; |
| 7265 | const param_ty_inst = try sema.resolveBody(param_block, param_body, inst); | 7347 | const param_ty_inst = try sema.resolveBody(param_block, param_body, inst); |
| 7266 | const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst); | 7348 | const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst); |
| 7267 | break :param_ty param_ty.toIntern(); | 7349 | break :param_ty param_ty.toIntern(); |
| 7268 | }; | 7350 | }; |
| 7269 | new_fn_info.param_types[arg_i.*] = param_ty; | 7351 | new_param_types[arg_i.*] = param_ty; |
| 7270 | const uncasted_arg = uncasted_args[arg_i.*]; | 7352 | const uncasted_arg = uncasted_args[arg_i.*]; |
| 7271 | if (try sema.typeRequiresComptime(param_ty.toType())) { | 7353 | if (try sema.typeRequiresComptime(param_ty.toType())) { |
| 7272 | _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| { | 7354 | _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| { |
| ... | @@ -7278,7 +7360,7 @@ fn analyzeInlineCallArg( | ... | @@ -7278,7 +7360,7 @@ fn analyzeInlineCallArg( |
| 7278 | } | 7360 | } |
| 7279 | const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{ | 7361 | const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{ |
| 7280 | .func_inst = func_inst, | 7362 | .func_inst = func_inst, |
| 7281 | .param_i = @as(u32, @intCast(arg_i.*)), | 7363 | .param_i = @intCast(arg_i.*), |
| 7282 | } }) catch |err| switch (err) { | 7364 | } }) catch |err| switch (err) { |
| 7283 | error.NotCoercible => unreachable, | 7365 | error.NotCoercible => unreachable, |
| 7284 | else => |e| return e, | 7366 | else => |e| return e, |
| ... | @@ -7317,7 +7399,7 @@ fn analyzeInlineCallArg( | ... | @@ -7317,7 +7399,7 @@ fn analyzeInlineCallArg( |
| 7317 | .param_anytype, .param_anytype_comptime => { | 7399 | .param_anytype, .param_anytype_comptime => { |
| 7318 | // No coercion needed. | 7400 | // No coercion needed. |
| 7319 | const uncasted_arg = uncasted_args[arg_i.*]; | 7401 | const uncasted_arg = uncasted_args[arg_i.*]; |
| 7320 | new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern(); | 7402 | new_param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern(); |
| 7321 | 7403 | ||
| 7322 | if (is_comptime_call) { | 7404 | if (is_comptime_call) { |
| 7323 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); | 7405 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); |
| ... | @@ -7371,50 +7453,12 @@ fn analyzeCallArg( | ... | @@ -7371,50 +7453,12 @@ fn analyzeCallArg( |
| 7371 | }; | 7453 | }; |
| 7372 | } | 7454 | } |
| 7373 | 7455 | ||
| 7374 | fn analyzeGenericCallArg( | ||
| 7375 | sema: *Sema, | ||
| 7376 | block: *Block, | ||
| 7377 | arg_src: LazySrcLoc, | ||
| 7378 | uncasted_arg: Air.Inst.Ref, | ||
| 7379 | comptime_arg: TypedValue, | ||
| 7380 | runtime_args: []Air.Inst.Ref, | ||
| 7381 | new_fn_info: InternPool.Key.FuncType, | ||
| 7382 | runtime_i: *u32, | ||
| 7383 | ) !void { | ||
| 7384 | const mod = sema.mod; | ||
| 7385 | const is_runtime = comptime_arg.val.isGenericPoison() and | ||
| 7386 | comptime_arg.ty.hasRuntimeBits(mod) and | ||
| 7387 | !(try sema.typeRequiresComptime(comptime_arg.ty)); | ||
| 7388 | if (is_runtime) { | ||
| 7389 | const param_ty = new_fn_info.param_types[runtime_i.*].toType(); | ||
| 7390 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); | ||
| 7391 | try sema.queueFullTypeResolution(param_ty); | ||
| 7392 | runtime_args[runtime_i.*] = casted_arg; | ||
| 7393 | runtime_i.* += 1; | ||
| 7394 | } else if (try sema.typeHasOnePossibleValue(comptime_arg.ty)) |_| { | ||
| 7395 | _ = try sema.coerce(block, comptime_arg.ty, uncasted_arg, arg_src); | ||
| 7396 | } | ||
| 7397 | } | ||
| 7398 | |||
| 7399 | fn analyzeGenericCallArgVal( | ||
| 7400 | sema: *Sema, | ||
| 7401 | block: *Block, | ||
| 7402 | arg_src: LazySrcLoc, | ||
| 7403 | arg_ty: Type, | ||
| 7404 | uncasted_arg: Air.Inst.Ref, | ||
| 7405 | reason: []const u8, | ||
| 7406 | ) !Value { | ||
| 7407 | const casted_arg = try sema.coerce(block, arg_ty, uncasted_arg, arg_src); | ||
| 7408 | return sema.resolveLazyValue(try sema.resolveValue(block, arg_src, casted_arg, reason)); | ||
| 7409 | } | ||
| 7410 | |||
| 7411 | fn instantiateGenericCall( | 7456 | fn instantiateGenericCall( |
| 7412 | sema: *Sema, | 7457 | sema: *Sema, |
| 7413 | block: *Block, | 7458 | block: *Block, |
| 7414 | func: Air.Inst.Ref, | 7459 | func: Air.Inst.Ref, |
| 7415 | func_src: LazySrcLoc, | 7460 | func_src: LazySrcLoc, |
| 7416 | call_src: LazySrcLoc, | 7461 | call_src: LazySrcLoc, |
| 7417 | generic_func_ty: Type, | ||
| 7418 | ensure_result_used: bool, | 7462 | ensure_result_used: bool, |
| 7419 | uncasted_args: []const Air.Inst.Ref, | 7463 | uncasted_args: []const Air.Inst.Ref, |
| 7420 | call_tag: Air.Inst.Tag, | 7464 | call_tag: Air.Inst.Tag, |
| ... | @@ -7423,299 +7467,32 @@ fn instantiateGenericCall( | ... | @@ -7423,299 +7467,32 @@ fn instantiateGenericCall( |
| 7423 | ) CompileError!Air.Inst.Ref { | 7467 | ) CompileError!Air.Inst.Ref { |
| 7424 | const mod = sema.mod; | 7468 | const mod = sema.mod; |
| 7425 | const gpa = sema.gpa; | 7469 | const gpa = sema.gpa; |
| 7470 | const ip = &mod.intern_pool; | ||
| 7426 | 7471 | ||
| 7427 | const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known"); | 7472 | const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known"); |
| 7428 | const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { | 7473 | const generic_owner = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { |
| 7429 | .func => |function| function.index, | 7474 | .func => func_val.toIntern(), |
| 7430 | .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?, | 7475 | .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.toIntern(), |
| 7431 | else => unreachable, | 7476 | else => unreachable, |
| 7432 | }; | 7477 | }; |
| 7433 | const module_fn = mod.funcPtr(module_fn_index); | 7478 | const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func; |
| 7434 | // Check the Module's generic function map with an adapted context, so that we | 7479 | |
| 7435 | // can match against `uncasted_args` rather than doing the work below to create a | 7480 | // Even though there may already be a generic instantiation corresponding |
| 7436 | // generic Scope only to junk it if it matches an existing instantiation. | 7481 | // to this callsite, we must evaluate the expressions of the generic |
| 7437 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 7482 | // function signature with the values of the callsite plugged in. |
| 7483 | // Importantly, this may include type coercions that determine whether the | ||
| 7484 | // instantiation is a match of a previous instantiation. | ||
| 7485 | // The actual monomorphization happens via adding `func_instance` to | ||
| 7486 | // `InternPool`. | ||
| 7487 | |||
| 7488 | const fn_owner_decl = mod.declPtr(generic_owner_func.owner_decl); | ||
| 7438 | const namespace_index = fn_owner_decl.src_namespace; | 7489 | const namespace_index = fn_owner_decl.src_namespace; |
| 7439 | const namespace = mod.namespacePtr(namespace_index); | 7490 | const namespace = mod.namespacePtr(namespace_index); |
| 7440 | const fn_zir = namespace.file_scope.zir; | 7491 | const fn_zir = namespace.file_scope.zir; |
| 7441 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); | 7492 | const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst); |
| 7442 | const zir_tags = fn_zir.instructions.items(.tag); | ||
| 7443 | |||
| 7444 | const monomorphed_args = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(generic_func_ty).?.param_types.len); | ||
| 7445 | const callee_index = callee: { | ||
| 7446 | var arg_i: usize = 0; | ||
| 7447 | var monomorphed_arg_i: u32 = 0; | ||
| 7448 | var known_unique = false; | ||
| 7449 | for (fn_info.param_body) |inst| { | ||
| 7450 | const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?; | ||
| 7451 | var is_comptime = false; | ||
| 7452 | var is_anytype = false; | ||
| 7453 | switch (zir_tags[inst]) { | ||
| 7454 | .param => { | ||
| 7455 | is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i))); | ||
| 7456 | }, | ||
| 7457 | .param_comptime => { | ||
| 7458 | is_comptime = true; | ||
| 7459 | }, | ||
| 7460 | .param_anytype => { | ||
| 7461 | is_anytype = true; | ||
| 7462 | is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i))); | ||
| 7463 | }, | ||
| 7464 | .param_anytype_comptime => { | ||
| 7465 | is_anytype = true; | ||
| 7466 | is_comptime = true; | ||
| 7467 | }, | ||
| 7468 | else => continue, | ||
| 7469 | } | ||
| 7470 | |||
| 7471 | defer arg_i += 1; | ||
| 7472 | const param_ty = generic_func_ty_info.param_types[arg_i]; | ||
| 7473 | const is_generic = !is_anytype and param_ty == .generic_poison_type; | ||
| 7474 | 7493 | ||
| 7475 | if (known_unique) { | 7494 | const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len); |
| 7476 | if (is_comptime or is_anytype or is_generic) { | 7495 | @memset(comptime_args, .none); |
| 7477 | monomorphed_arg_i += 1; | ||
| 7478 | } | ||
| 7479 | continue; | ||
| 7480 | } | ||
| 7481 | |||
| 7482 | const uncasted_arg = uncasted_args[arg_i]; | ||
| 7483 | const arg_ty = if (is_generic) mod.monomorphed_funcs.getAdapted( | ||
| 7484 | Module.MonomorphedFuncAdaptedKey{ | ||
| 7485 | .func = module_fn_index, | ||
| 7486 | .args = monomorphed_args[0..monomorphed_arg_i], | ||
| 7487 | }, | ||
| 7488 | Module.MonomorphedFuncsAdaptedContext{ .mod = mod }, | ||
| 7489 | ) orelse { | ||
| 7490 | known_unique = true; | ||
| 7491 | monomorphed_arg_i += 1; | ||
| 7492 | continue; | ||
| 7493 | } else if (is_anytype) sema.typeOf(uncasted_arg).toIntern() else param_ty; | ||
| 7494 | const was_comptime = is_comptime; | ||
| 7495 | if (!is_comptime and try sema.typeRequiresComptime(arg_ty.toType())) is_comptime = true; | ||
| 7496 | if (is_comptime or is_anytype) { | ||
| 7497 | // Tuple default values are a part of the type and need to be | ||
| 7498 | // resolved to hash the type. | ||
| 7499 | try sema.resolveTupleLazyValues(block, call_src, arg_ty.toType()); | ||
| 7500 | } | ||
| 7501 | |||
| 7502 | if (is_comptime) { | ||
| 7503 | const casted_arg = sema.analyzeGenericCallArgVal(block, .unneeded, arg_ty.toType(), uncasted_arg, "") catch |err| switch (err) { | ||
| 7504 | error.NeededSourceLocation => { | ||
| 7505 | const decl = mod.declPtr(block.src_decl); | ||
| 7506 | const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src); | ||
| 7507 | _ = try sema.analyzeGenericCallArgVal( | ||
| 7508 | block, | ||
| 7509 | arg_src, | ||
| 7510 | arg_ty.toType(), | ||
| 7511 | uncasted_arg, | ||
| 7512 | if (was_comptime) | ||
| 7513 | "parameter is comptime" | ||
| 7514 | else | ||
| 7515 | "argument to parameter with comptime-only type must be comptime-known", | ||
| 7516 | ); | ||
| 7517 | unreachable; | ||
| 7518 | }, | ||
| 7519 | else => |e| return e, | ||
| 7520 | }; | ||
| 7521 | monomorphed_args[monomorphed_arg_i] = casted_arg.toIntern(); | ||
| 7522 | monomorphed_arg_i += 1; | ||
| 7523 | } else if (is_anytype or is_generic) { | ||
| 7524 | monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty }); | ||
| 7525 | monomorphed_arg_i += 1; | ||
| 7526 | } | ||
| 7527 | } | ||
| 7528 | |||
| 7529 | if (!known_unique) { | ||
| 7530 | if (mod.monomorphed_funcs.getAdapted( | ||
| 7531 | Module.MonomorphedFuncAdaptedKey{ | ||
| 7532 | .func = module_fn_index, | ||
| 7533 | .args = monomorphed_args[0..monomorphed_arg_i], | ||
| 7534 | }, | ||
| 7535 | Module.MonomorphedFuncsAdaptedContext{ .mod = mod }, | ||
| 7536 | )) |callee_func| break :callee mod.intern_pool.indexToKey(callee_func).func.index; | ||
| 7537 | } | ||
| 7538 | |||
| 7539 | const new_module_func_index = try mod.createFunc(undefined); | ||
| 7540 | const new_module_func = mod.funcPtr(new_module_func_index); | ||
| 7541 | |||
| 7542 | new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional(); | ||
| 7543 | new_module_func.comptime_args = null; | ||
| 7544 | |||
| 7545 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); | ||
| 7546 | |||
| 7547 | // Create a Decl for the new function. | ||
| 7548 | const src_decl_index = namespace.getDeclIndex(mod); | ||
| 7549 | const src_decl = mod.declPtr(src_decl_index); | ||
| 7550 | const new_decl_index = try mod.allocateNewDecl(namespace_index, fn_owner_decl.src_node, src_decl.src_scope); | ||
| 7551 | const new_decl = mod.declPtr(new_decl_index); | ||
| 7552 | // TODO better names for generic function instantiations | ||
| 7553 | const decl_name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}__anon_{d}", .{ | ||
| 7554 | fn_owner_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), | ||
| 7555 | }); | ||
| 7556 | new_decl.name = decl_name; | ||
| 7557 | new_decl.src_line = fn_owner_decl.src_line; | ||
| 7558 | new_decl.is_pub = fn_owner_decl.is_pub; | ||
| 7559 | new_decl.is_exported = fn_owner_decl.is_exported; | ||
| 7560 | new_decl.has_align = fn_owner_decl.has_align; | ||
| 7561 | new_decl.has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace; | ||
| 7562 | new_decl.@"linksection" = fn_owner_decl.@"linksection"; | ||
| 7563 | new_decl.@"addrspace" = fn_owner_decl.@"addrspace"; | ||
| 7564 | new_decl.zir_decl_index = fn_owner_decl.zir_decl_index; | ||
| 7565 | new_decl.alive = true; // This Decl is called at runtime. | ||
| 7566 | new_decl.analysis = .in_progress; | ||
| 7567 | new_decl.generation = mod.generation; | ||
| 7568 | |||
| 7569 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {}); | ||
| 7570 | |||
| 7571 | // The generic function Decl is guaranteed to be the first dependency | ||
| 7572 | // of each of its instantiations. | ||
| 7573 | assert(new_decl.dependencies.keys().len == 0); | ||
| 7574 | try mod.declareDeclDependencyType(new_decl_index, module_fn.owner_decl, .function_body); | ||
| 7575 | |||
| 7576 | const new_func = sema.resolveGenericInstantiationType( | ||
| 7577 | block, | ||
| 7578 | fn_zir, | ||
| 7579 | new_decl, | ||
| 7580 | new_decl_index, | ||
| 7581 | uncasted_args, | ||
| 7582 | monomorphed_arg_i, | ||
| 7583 | module_fn_index, | ||
| 7584 | new_module_func_index, | ||
| 7585 | namespace_index, | ||
| 7586 | generic_func_ty, | ||
| 7587 | call_src, | ||
| 7588 | bound_arg_src, | ||
| 7589 | ) catch |err| switch (err) { | ||
| 7590 | error.GenericPoison, error.ComptimeReturn => { | ||
| 7591 | // Resolving the new function type below will possibly declare more decl dependencies | ||
| 7592 | // and so we remove them all here in case of error. | ||
| 7593 | for (new_decl.dependencies.keys()) |dep_index| { | ||
| 7594 | const dep = mod.declPtr(dep_index); | ||
| 7595 | dep.removeDependant(new_decl_index); | ||
| 7596 | } | ||
| 7597 | assert(namespace.anon_decls.orderedRemove(new_decl_index)); | ||
| 7598 | mod.destroyDecl(new_decl_index); | ||
| 7599 | mod.destroyFunc(new_module_func_index); | ||
| 7600 | return err; | ||
| 7601 | }, | ||
| 7602 | else => { | ||
| 7603 | // TODO look up the compile error that happened here and attach a note to it | ||
| 7604 | // pointing here, at the generic instantiation callsite. | ||
| 7605 | if (sema.owner_func) |owner_func| { | ||
| 7606 | owner_func.state = .dependency_failure; | ||
| 7607 | } else { | ||
| 7608 | sema.owner_decl.analysis = .dependency_failure; | ||
| 7609 | } | ||
| 7610 | return err; | ||
| 7611 | }, | ||
| 7612 | }; | ||
| 7613 | |||
| 7614 | break :callee new_func; | ||
| 7615 | }; | ||
| 7616 | const callee = mod.funcPtr(callee_index); | ||
| 7617 | callee.branch_quota = @max(callee.branch_quota, sema.branch_quota); | ||
| 7618 | |||
| 7619 | const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl); | ||
| 7620 | |||
| 7621 | // Make a runtime call to the new function, making sure to omit the comptime args. | ||
| 7622 | const comptime_args = callee.comptime_args.?; | ||
| 7623 | const func_ty = mod.declPtr(callee.owner_decl).ty; | ||
| 7624 | const runtime_args_len = @as(u32, @intCast(mod.typeToFunc(func_ty).?.param_types.len)); | ||
| 7625 | const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len); | ||
| 7626 | { | ||
| 7627 | var runtime_i: u32 = 0; | ||
| 7628 | var total_i: u32 = 0; | ||
| 7629 | for (fn_info.param_body) |inst| { | ||
| 7630 | switch (zir_tags[inst]) { | ||
| 7631 | .param_comptime, .param_anytype_comptime, .param, .param_anytype => {}, | ||
| 7632 | else => continue, | ||
| 7633 | } | ||
| 7634 | sema.analyzeGenericCallArg( | ||
| 7635 | block, | ||
| 7636 | .unneeded, | ||
| 7637 | uncasted_args[total_i], | ||
| 7638 | comptime_args[total_i], | ||
| 7639 | runtime_args, | ||
| 7640 | mod.typeToFunc(func_ty).?, | ||
| 7641 | &runtime_i, | ||
| 7642 | ) catch |err| switch (err) { | ||
| 7643 | error.NeededSourceLocation => { | ||
| 7644 | const decl = mod.declPtr(block.src_decl); | ||
| 7645 | _ = try sema.analyzeGenericCallArg( | ||
| 7646 | block, | ||
| 7647 | mod.argSrc(call_src.node_offset.x, decl, total_i, bound_arg_src), | ||
| 7648 | uncasted_args[total_i], | ||
| 7649 | comptime_args[total_i], | ||
| 7650 | runtime_args, | ||
| 7651 | mod.typeToFunc(func_ty).?, | ||
| 7652 | &runtime_i, | ||
| 7653 | ); | ||
| 7654 | unreachable; | ||
| 7655 | }, | ||
| 7656 | else => |e| return e, | ||
| 7657 | }; | ||
| 7658 | total_i += 1; | ||
| 7659 | } | ||
| 7660 | |||
| 7661 | try sema.queueFullTypeResolution(mod.typeToFunc(func_ty).?.return_type.toType()); | ||
| 7662 | } | ||
| 7663 | |||
| 7664 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); | ||
| 7665 | |||
| 7666 | if (sema.owner_func != null and mod.typeToFunc(func_ty).?.return_type.toType().isError(mod)) { | ||
| 7667 | sema.owner_func.?.calls_or_awaits_errorable_fn = true; | ||
| 7668 | } | ||
| 7669 | |||
| 7670 | try mod.ensureFuncBodyAnalysisQueued(callee_index); | ||
| 7671 | |||
| 7672 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + | ||
| 7673 | runtime_args_len); | ||
| 7674 | const result = try block.addInst(.{ | ||
| 7675 | .tag = call_tag, | ||
| 7676 | .data = .{ .pl_op = .{ | ||
| 7677 | .operand = callee_inst, | ||
| 7678 | .payload = sema.addExtraAssumeCapacity(Air.Call{ | ||
| 7679 | .args_len = runtime_args_len, | ||
| 7680 | }), | ||
| 7681 | } }, | ||
| 7682 | }); | ||
| 7683 | sema.appendRefsAssumeCapacity(runtime_args); | ||
| 7684 | |||
| 7685 | if (ensure_result_used) { | ||
| 7686 | try sema.ensureResultUsed(block, sema.typeOf(result), call_src); | ||
| 7687 | } | ||
| 7688 | if (call_tag == .call_always_tail) { | ||
| 7689 | return sema.handleTailCall(block, call_src, func_ty, result); | ||
| 7690 | } | ||
| 7691 | if (func_ty.fnReturnType(mod).isNoReturn(mod)) { | ||
| 7692 | _ = try block.addNoOp(.unreach); | ||
| 7693 | return Air.Inst.Ref.unreachable_value; | ||
| 7694 | } | ||
| 7695 | return result; | ||
| 7696 | } | ||
| 7697 | |||
| 7698 | fn resolveGenericInstantiationType( | ||
| 7699 | sema: *Sema, | ||
| 7700 | block: *Block, | ||
| 7701 | fn_zir: Zir, | ||
| 7702 | new_decl: *Decl, | ||
| 7703 | new_decl_index: Decl.Index, | ||
| 7704 | uncasted_args: []const Air.Inst.Ref, | ||
| 7705 | monomorphed_args_len: u32, | ||
| 7706 | module_fn_index: Module.Fn.Index, | ||
| 7707 | new_module_func: Module.Fn.Index, | ||
| 7708 | namespace: Namespace.Index, | ||
| 7709 | generic_func_ty: Type, | ||
| 7710 | call_src: LazySrcLoc, | ||
| 7711 | bound_arg_src: ?LazySrcLoc, | ||
| 7712 | ) !Module.Fn.Index { | ||
| 7713 | const mod = sema.mod; | ||
| 7714 | const gpa = sema.gpa; | ||
| 7715 | |||
| 7716 | const zir_tags = fn_zir.instructions.items(.tag); | ||
| 7717 | const module_fn = mod.funcPtr(module_fn_index); | ||
| 7718 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); | ||
| 7719 | 7496 | ||
| 7720 | // Re-run the block that creates the function, with the comptime parameters | 7497 | // Re-run the block that creates the function, with the comptime parameters |
| 7721 | // pre-populated inside `inst_map`. This causes `param_comptime` and | 7498 | // pre-populated inside `inst_map`. This causes `param_comptime` and |
| ... | @@ -7726,205 +7503,145 @@ fn resolveGenericInstantiationType( | ... | @@ -7726,205 +7503,145 @@ fn resolveGenericInstantiationType( |
| 7726 | .gpa = gpa, | 7503 | .gpa = gpa, |
| 7727 | .arena = sema.arena, | 7504 | .arena = sema.arena, |
| 7728 | .code = fn_zir, | 7505 | .code = fn_zir, |
| 7729 | .owner_decl = new_decl, | 7506 | // We pass the generic callsite's owner decl here because whatever `Decl` |
| 7730 | .owner_decl_index = new_decl_index, | 7507 | // dependencies are chased at this point should be attached to the |
| 7731 | .func = null, | 7508 | // callsite, not the `Decl` associated with the `func_instance`. |
| 7732 | .func_index = .none, | 7509 | .owner_decl = sema.owner_decl, |
| 7510 | .owner_decl_index = sema.owner_decl_index, | ||
| 7511 | .func_index = sema.owner_func_index, | ||
| 7733 | .fn_ret_ty = Type.void, | 7512 | .fn_ret_ty = Type.void, |
| 7734 | .owner_func = null, | 7513 | .fn_ret_ty_ies = null, |
| 7735 | .owner_func_index = .none, | 7514 | .owner_func_index = .none, |
| 7736 | // TODO: fully migrate functions into InternPool | 7515 | .comptime_args = comptime_args, |
| 7737 | .comptime_args = try mod.tmp_hack_arena.allocator().alloc(TypedValue, uncasted_args.len), | 7516 | .generic_owner = generic_owner, |
| 7738 | .comptime_args_fn_inst = module_fn.zir_body_inst, | 7517 | .generic_call_src = call_src, |
| 7739 | .preallocated_new_func = new_module_func.toOptional(), | 7518 | .generic_call_decl = block.src_decl.toOptional(), |
| 7740 | .is_generic_instantiation = true, | ||
| 7741 | .branch_quota = sema.branch_quota, | 7519 | .branch_quota = sema.branch_quota, |
| 7742 | .branch_count = sema.branch_count, | 7520 | .branch_count = sema.branch_count, |
| 7743 | .comptime_mutable_decls = sema.comptime_mutable_decls, | 7521 | .comptime_mutable_decls = sema.comptime_mutable_decls, |
| 7744 | }; | 7522 | }; |
| 7745 | defer child_sema.deinit(); | 7523 | defer child_sema.deinit(); |
| 7746 | 7524 | ||
| 7747 | var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope); | 7525 | var wip_captures = try WipCaptureScope.init(gpa, sema.owner_decl.src_scope); |
| 7748 | defer wip_captures.deinit(); | 7526 | defer wip_captures.deinit(); |
| 7749 | 7527 | ||
| 7750 | var child_block: Block = .{ | 7528 | var child_block: Block = .{ |
| 7751 | .parent = null, | 7529 | .parent = null, |
| 7752 | .sema = &child_sema, | 7530 | .sema = &child_sema, |
| 7753 | .src_decl = new_decl_index, | 7531 | .src_decl = generic_owner_func.owner_decl, |
| 7754 | .namespace = namespace, | 7532 | .namespace = namespace_index, |
| 7755 | .wip_capture_scope = wip_captures.scope, | 7533 | .wip_capture_scope = wip_captures.scope, |
| 7756 | .instructions = .{}, | 7534 | .instructions = .{}, |
| 7757 | .inlining = null, | 7535 | .inlining = null, |
| 7758 | .is_comptime = true, | 7536 | .is_comptime = true, |
| 7759 | }; | 7537 | }; |
| 7760 | defer { | 7538 | defer child_block.instructions.deinit(gpa); |
| 7761 | child_block.instructions.deinit(gpa); | ||
| 7762 | child_block.params.deinit(gpa); | ||
| 7763 | } | ||
| 7764 | 7539 | ||
| 7765 | try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); | 7540 | try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); |
| 7766 | 7541 | ||
| 7767 | var arg_i: usize = 0; | 7542 | for (fn_info.param_body[0..uncasted_args.len], uncasted_args, 0..) |inst, arg, i| { |
| 7768 | for (fn_info.param_body) |inst| { | 7543 | // `child_sema` will use a different `inst_map` which means we have to |
| 7769 | const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?; | 7544 | // convert from parent-relative `Air.Inst.Ref` to child-relative here. |
| 7770 | var is_comptime = false; | 7545 | // Constants are simple; runtime-known values need a new instruction. |
| 7771 | var is_anytype = false; | 7546 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, if (try sema.resolveMaybeUndefVal(arg)) |val| |
| 7772 | switch (zir_tags[inst]) { | 7547 | Air.internedToRef(val.toIntern()) |
| 7773 | .param => { | 7548 | else |
| 7774 | is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i))); | 7549 | // We insert into the map an instruction which is runtime-known |
| 7775 | }, | 7550 | // but has the type of the argument. |
| 7776 | .param_comptime => { | 7551 | try child_block.addInst(.{ |
| 7777 | is_comptime = true; | 7552 | .tag = .arg, |
| 7778 | }, | 7553 | .data = .{ .arg = .{ |
| 7779 | .param_anytype => { | 7554 | .ty = Air.internedToRef(sema.typeOf(arg).toIntern()), |
| 7780 | is_anytype = true; | 7555 | .src_index = @intCast(i), |
| 7781 | is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i))); | 7556 | } }, |
| 7782 | }, | 7557 | })); |
| 7783 | .param_anytype_comptime => { | ||
| 7784 | is_anytype = true; | ||
| 7785 | is_comptime = true; | ||
| 7786 | }, | ||
| 7787 | else => continue, | ||
| 7788 | } | ||
| 7789 | const arg = uncasted_args[arg_i]; | ||
| 7790 | if (is_comptime) { | ||
| 7791 | const arg_val = (try sema.resolveMaybeUndefVal(arg)).?; | ||
| 7792 | const child_arg = try child_sema.addConstant(arg_val); | ||
| 7793 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); | ||
| 7794 | } else if (is_anytype) { | ||
| 7795 | const arg_ty = sema.typeOf(arg); | ||
| 7796 | if (try sema.typeRequiresComptime(arg_ty)) { | ||
| 7797 | const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) { | ||
| 7798 | error.NeededSourceLocation => { | ||
| 7799 | const decl = mod.declPtr(block.src_decl); | ||
| 7800 | const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src); | ||
| 7801 | _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known"); | ||
| 7802 | unreachable; | ||
| 7803 | }, | ||
| 7804 | else => |e| return e, | ||
| 7805 | }; | ||
| 7806 | const child_arg = try child_sema.addConstant(arg_val); | ||
| 7807 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); | ||
| 7808 | } else { | ||
| 7809 | // We insert into the map an instruction which is runtime-known | ||
| 7810 | // but has the type of the argument. | ||
| 7811 | const child_arg = try child_block.addInst(.{ | ||
| 7812 | .tag = .arg, | ||
| 7813 | .data = .{ .arg = .{ | ||
| 7814 | .ty = try child_sema.addType(arg_ty), | ||
| 7815 | .src_index = @as(u32, @intCast(arg_i)), | ||
| 7816 | } }, | ||
| 7817 | }); | ||
| 7818 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); | ||
| 7819 | } | ||
| 7820 | } | ||
| 7821 | arg_i += 1; | ||
| 7822 | } | 7558 | } |
| 7823 | 7559 | ||
| 7824 | // Save the error trace as our first action in the function. | ||
| 7825 | // If this is unnecessary after all, Liveness will clean it up for us. | ||
| 7826 | const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); | ||
| 7827 | child_sema.error_return_trace_index_on_fn_entry = error_return_trace_index; | ||
| 7828 | child_block.error_return_trace_index = error_return_trace_index; | ||
| 7829 | |||
| 7830 | const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst); | 7560 | const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst); |
| 7831 | const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable; | 7561 | const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern(); |
| 7832 | const new_func = new_func_val.getFunctionIndex(mod).unwrap().?; | ||
| 7833 | assert(new_func == new_module_func); | ||
| 7834 | |||
| 7835 | const monomorphed_args_index = @as(u32, @intCast(mod.monomorphed_func_keys.items.len)); | ||
| 7836 | const monomorphed_args = try mod.monomorphed_func_keys.addManyAsSlice(gpa, monomorphed_args_len); | ||
| 7837 | var monomorphed_arg_i: u32 = 0; | ||
| 7838 | try mod.monomorphed_funcs.ensureUnusedCapacityContext(gpa, monomorphed_args_len + 1, .{ .mod = mod }); | ||
| 7839 | |||
| 7840 | arg_i = 0; | ||
| 7841 | for (fn_info.param_body) |inst| { | ||
| 7842 | const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?; | ||
| 7843 | var is_comptime = false; | ||
| 7844 | var is_anytype = false; | ||
| 7845 | switch (zir_tags[inst]) { | ||
| 7846 | .param => { | ||
| 7847 | is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i))); | ||
| 7848 | }, | ||
| 7849 | .param_comptime => { | ||
| 7850 | is_comptime = true; | ||
| 7851 | }, | ||
| 7852 | .param_anytype => { | ||
| 7853 | is_anytype = true; | ||
| 7854 | is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i))); | ||
| 7855 | }, | ||
| 7856 | .param_anytype_comptime => { | ||
| 7857 | is_anytype = true; | ||
| 7858 | is_comptime = true; | ||
| 7859 | }, | ||
| 7860 | else => continue, | ||
| 7861 | } | ||
| 7862 | |||
| 7863 | const param_ty = generic_func_ty_info.param_types[arg_i]; | ||
| 7864 | const is_generic = !is_anytype and param_ty == .generic_poison_type; | ||
| 7865 | 7562 | ||
| 7866 | const arg = child_sema.inst_map.get(inst).?; | 7563 | const callee = mod.funcInfo(callee_index); |
| 7867 | const arg_ty = child_sema.typeOf(arg); | 7564 | callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota); |
| 7868 | |||
| 7869 | if (is_generic) if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{ | ||
| 7870 | .func = module_fn_index, | ||
| 7871 | .args_index = monomorphed_args_index, | ||
| 7872 | .args_len = monomorphed_arg_i, | ||
| 7873 | }, arg_ty.toIntern(), .{ .mod = mod })) |kv| assert(kv.value == arg_ty.toIntern()); | ||
| 7874 | if (!is_comptime and try sema.typeRequiresComptime(arg_ty)) is_comptime = true; | ||
| 7875 | |||
| 7876 | if (is_comptime) { | ||
| 7877 | const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?; | ||
| 7878 | monomorphed_args[monomorphed_arg_i] = arg_val.toIntern(); | ||
| 7879 | monomorphed_arg_i += 1; | ||
| 7880 | child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = arg_val }; | ||
| 7881 | } else { | ||
| 7882 | if (is_anytype or is_generic) { | ||
| 7883 | monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty.toIntern() }); | ||
| 7884 | monomorphed_arg_i += 1; | ||
| 7885 | } | ||
| 7886 | child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = Value.generic_poison }; | ||
| 7887 | } | ||
| 7888 | 7565 | ||
| 7889 | arg_i += 1; | 7566 | // Make a runtime call to the new function, making sure to omit the comptime args. |
| 7890 | } | 7567 | const func_ty = callee.ty.toType(); |
| 7568 | const func_ty_info = mod.typeToFunc(func_ty).?; | ||
| 7891 | 7569 | ||
| 7892 | try wip_captures.finalize(); | 7570 | try wip_captures.finalize(); |
| 7893 | 7571 | ||
| 7894 | // Populate the Decl ty/val with the function and its type. | ||
| 7895 | new_decl.ty = child_sema.typeOf(new_func_inst); | ||
| 7896 | // If the call evaluated to a return type that requires comptime, never mind | 7572 | // If the call evaluated to a return type that requires comptime, never mind |
| 7897 | // our generic instantiation. Instead we need to perform a comptime call. | 7573 | // our generic instantiation. Instead we need to perform a comptime call. |
| 7898 | const new_fn_info = mod.typeToFunc(new_decl.ty).?; | 7574 | if (try sema.typeRequiresComptime(func_ty_info.return_type.toType())) { |
| 7899 | if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) { | ||
| 7900 | return error.ComptimeReturn; | 7575 | return error.ComptimeReturn; |
| 7901 | } | 7576 | } |
| 7902 | // Similarly, if the call evaluated to a generic type we need to instead | 7577 | // Similarly, if the call evaluated to a generic type we need to instead |
| 7903 | // call it inline. | 7578 | // call it inline. |
| 7904 | if (new_fn_info.is_generic or new_fn_info.cc == .Inline) { | 7579 | if (func_ty_info.is_generic or func_ty_info.cc == .Inline) { |
| 7905 | return error.GenericPoison; | 7580 | return error.GenericPoison; |
| 7906 | } | 7581 | } |
| 7907 | 7582 | ||
| 7908 | new_decl.val = (try mod.intern(.{ .func = .{ | 7583 | const runtime_args_len: u32 = func_ty_info.param_types.len; |
| 7909 | .ty = new_decl.ty.toIntern(), | 7584 | const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len); |
| 7910 | .index = new_func, | 7585 | { |
| 7911 | } })).toValue(); | 7586 | var runtime_i: u32 = 0; |
| 7912 | new_decl.alignment = .none; | 7587 | for (uncasted_args, 0..) |uncasted_arg, total_i| { |
| 7913 | new_decl.has_tv = true; | 7588 | // In the case of a function call generated by the language, the LazySrcLoc |
| 7914 | new_decl.owns_tv = true; | 7589 | // provided for `call_src` may not point to anything interesting. |
| 7915 | new_decl.analysis = .complete; | 7590 | const arg_src: LazySrcLoc = if (total_i == 0 and bound_arg_src != null) |
| 7591 | bound_arg_src.? | ||
| 7592 | else if (call_src == .node_offset) .{ .call_arg = .{ | ||
| 7593 | .decl = block.src_decl, | ||
| 7594 | .call_node_offset = call_src.node_offset.x, | ||
| 7595 | .arg_index = @intCast(total_i), | ||
| 7596 | } } else .unneeded; | ||
| 7597 | |||
| 7598 | const comptime_arg = callee.comptime_args.get(ip)[total_i]; | ||
| 7599 | if (comptime_arg == .none) { | ||
| 7600 | const param_ty = func_ty_info.param_types.get(ip)[runtime_i].toType(); | ||
| 7601 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); | ||
| 7602 | try sema.queueFullTypeResolution(param_ty); | ||
| 7603 | runtime_args[runtime_i] = casted_arg; | ||
| 7604 | runtime_i += 1; | ||
| 7605 | } | ||
| 7606 | } | ||
| 7607 | |||
| 7608 | try sema.queueFullTypeResolution(func_ty_info.return_type.toType()); | ||
| 7609 | } | ||
| 7610 | |||
| 7611 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); | ||
| 7916 | 7612 | ||
| 7917 | mod.monomorphed_funcs.putAssumeCapacityNoClobberContext(.{ | 7613 | if (sema.owner_func_index != .none and |
| 7918 | .func = module_fn_index, | 7614 | func_ty_info.return_type.toType().isError(mod)) |
| 7919 | .args_index = monomorphed_args_index, | 7615 | { |
| 7920 | .args_len = monomorphed_arg_i, | 7616 | ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true; |
| 7921 | }, new_decl.val.toIntern(), .{ .mod = mod }); | 7617 | } |
| 7618 | |||
| 7619 | try mod.ensureFuncBodyAnalysisQueued(callee_index); | ||
| 7922 | 7620 | ||
| 7923 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field | 7621 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 7924 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR | 7622 | runtime_args_len); |
| 7925 | // parameters mapped appropriately. | 7623 | const result = try block.addInst(.{ |
| 7926 | try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func }); | 7624 | .tag = call_tag, |
| 7927 | return new_func; | 7625 | .data = .{ .pl_op = .{ |
| 7626 | .operand = Air.internedToRef(callee_index), | ||
| 7627 | .payload = sema.addExtraAssumeCapacity(Air.Call{ | ||
| 7628 | .args_len = runtime_args_len, | ||
| 7629 | }), | ||
| 7630 | } }, | ||
| 7631 | }); | ||
| 7632 | sema.appendRefsAssumeCapacity(runtime_args); | ||
| 7633 | |||
| 7634 | if (ensure_result_used) { | ||
| 7635 | try sema.ensureResultUsed(block, sema.typeOf(result), call_src); | ||
| 7636 | } | ||
| 7637 | if (call_tag == .call_always_tail) { | ||
| 7638 | return sema.handleTailCall(block, call_src, func_ty, result); | ||
| 7639 | } | ||
| 7640 | if (func_ty.fnReturnType(mod).isNoReturn(mod)) { | ||
| 7641 | _ = try block.addNoOp(.unreach); | ||
| 7642 | return Air.Inst.Ref.unreachable_value; | ||
| 7643 | } | ||
| 7644 | return result; | ||
| 7928 | } | 7645 | } |
| 7929 | 7646 | ||
| 7930 | fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { | 7647 | fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| ... | @@ -7944,8 +7661,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) | ... | @@ -7944,8 +7661,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) |
| 7944 | fn emitDbgInline( | 7661 | fn emitDbgInline( |
| 7945 | sema: *Sema, | 7662 | sema: *Sema, |
| 7946 | block: *Block, | 7663 | block: *Block, |
| 7947 | old_func: Module.Fn.Index, | 7664 | old_func: InternPool.Index, |
| 7948 | new_func: Module.Fn.Index, | 7665 | new_func: InternPool.Index, |
| 7949 | new_func_ty: Type, | 7666 | new_func_ty: Type, |
| 7950 | tag: Air.Inst.Tag, | 7667 | tag: Air.Inst.Tag, |
| 7951 | ) CompileError!void { | 7668 | ) CompileError!void { |
| ... | @@ -8149,6 +7866,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -8149,6 +7866,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 8149 | defer tracy.end(); | 7866 | defer tracy.end(); |
| 8150 | 7867 | ||
| 8151 | const mod = sema.mod; | 7868 | const mod = sema.mod; |
| 7869 | const ip = &mod.intern_pool; | ||
| 8152 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 7870 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 8153 | const src = LazySrcLoc.nodeOffset(extra.node); | 7871 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 8154 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 7872 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| ... | @@ -8159,7 +7877,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -8159,7 +7877,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 8159 | if (val.isUndef(mod)) { | 7877 | if (val.isUndef(mod)) { |
| 8160 | return sema.addConstUndef(Type.err_int); | 7878 | return sema.addConstUndef(Type.err_int); |
| 8161 | } | 7879 | } |
| 8162 | const err_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; | 7880 | const err_name = ip.indexToKey(val.toIntern()).err.name; |
| 8163 | return sema.addConstant(try mod.intValue( | 7881 | return sema.addConstant(try mod.intValue( |
| 8164 | Type.err_int, | 7882 | Type.err_int, |
| 8165 | try mod.getErrorValue(err_name), | 7883 | try mod.getErrorValue(err_name), |
| ... | @@ -8167,17 +7885,19 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -8167,17 +7885,19 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 8167 | } | 7885 | } |
| 8168 | 7886 | ||
| 8169 | const op_ty = sema.typeOf(uncasted_operand); | 7887 | const op_ty = sema.typeOf(uncasted_operand); |
| 8170 | try sema.resolveInferredErrorSetTy(block, src, op_ty); | 7888 | switch (try sema.resolveInferredErrorSetTy(block, src, op_ty.toIntern())) { |
| 8171 | if (!op_ty.isAnyError(mod)) { | 7889 | .anyerror_type => {}, |
| 8172 | const names = op_ty.errorSetNames(mod); | 7890 | else => |err_set_ty_index| { |
| 8173 | switch (names.len) { | 7891 | const names = ip.indexToKey(err_set_ty_index).error_set_type.names; |
| 8174 | 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)), | 7892 | switch (names.len) { |
| 8175 | 1 => { | 7893 | 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)), |
| 8176 | const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(names[0]).?)); | 7894 | 1 => { |
| 8177 | return sema.addIntUnsigned(Type.err_int, int); | 7895 | const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?); |
| 8178 | }, | 7896 | return sema.addIntUnsigned(Type.err_int, int); |
| 8179 | else => {}, | 7897 | }, |
| 8180 | } | 7898 | else => {}, |
| 7899 | } | ||
| 7900 | }, | ||
| 8181 | } | 7901 | } |
| 8182 | 7902 | ||
| 8183 | try sema.requireRuntimeBlock(block, src, operand_src); | 7903 | try sema.requireRuntimeBlock(block, src, operand_src); |
| ... | @@ -8226,6 +7946,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -8226,6 +7946,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8226 | defer tracy.end(); | 7946 | defer tracy.end(); |
| 8227 | 7947 | ||
| 8228 | const mod = sema.mod; | 7948 | const mod = sema.mod; |
| 7949 | const ip = &mod.intern_pool; | ||
| 8229 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 7950 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 8230 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 7951 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8231 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 7952 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| ... | @@ -8254,23 +7975,25 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -8254,23 +7975,25 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8254 | return Air.Inst.Ref.anyerror_type; | 7975 | return Air.Inst.Ref.anyerror_type; |
| 8255 | } | 7976 | } |
| 8256 | 7977 | ||
| 8257 | if (mod.typeToInferredErrorSetIndex(lhs_ty).unwrap()) |ies_index| { | 7978 | if (ip.isInferredErrorSetType(lhs_ty.toIntern())) { |
| 8258 | try sema.resolveInferredErrorSet(block, src, ies_index); | 7979 | switch (try sema.resolveInferredErrorSet(block, src, lhs_ty.toIntern())) { |
| 8259 | // isAnyError might have changed from a false negative to a true positive after resolution. | 7980 | // isAnyError might have changed from a false negative to a true |
| 8260 | if (lhs_ty.isAnyError(mod)) { | 7981 | // positive after resolution. |
| 8261 | return Air.Inst.Ref.anyerror_type; | 7982 | .anyerror_type => return .anyerror_type, |
| 7983 | else => {}, | ||
| 8262 | } | 7984 | } |
| 8263 | } | 7985 | } |
| 8264 | if (mod.typeToInferredErrorSetIndex(rhs_ty).unwrap()) |ies_index| { | 7986 | if (ip.isInferredErrorSetType(rhs_ty.toIntern())) { |
| 8265 | try sema.resolveInferredErrorSet(block, src, ies_index); | 7987 | switch (try sema.resolveInferredErrorSet(block, src, rhs_ty.toIntern())) { |
| 8266 | // isAnyError might have changed from a false negative to a true positive after resolution. | 7988 | // isAnyError might have changed from a false negative to a true |
| 8267 | if (rhs_ty.isAnyError(mod)) { | 7989 | // positive after resolution. |
| 8268 | return Air.Inst.Ref.anyerror_type; | 7990 | .anyerror_type => return .anyerror_type, |
| 7991 | else => {}, | ||
| 8269 | } | 7992 | } |
| 8270 | } | 7993 | } |
| 8271 | 7994 | ||
| 8272 | const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty); | 7995 | const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty); |
| 8273 | return sema.addType(err_set_ty); | 7996 | return Air.internedToRef(err_set_ty.toIntern()); |
| 8274 | } | 7997 | } |
| 8275 | 7998 | ||
| 8276 | fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 7999 | fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -8747,9 +8470,7 @@ fn zirFunc( | ... | @@ -8747,9 +8470,7 @@ fn zirFunc( |
| 8747 | inst: Zir.Inst.Index, | 8470 | inst: Zir.Inst.Index, |
| 8748 | inferred_error_set: bool, | 8471 | inferred_error_set: bool, |
| 8749 | ) CompileError!Air.Inst.Ref { | 8472 | ) CompileError!Air.Inst.Ref { |
| 8750 | const tracy = trace(@src()); | 8473 | const mod = sema.mod; |
| 8751 | defer tracy.end(); | ||
| 8752 | |||
| 8753 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 8474 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 8754 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); | 8475 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 8755 | const target = sema.mod.getTarget(); | 8476 | const target = sema.mod.getTarget(); |
| ... | @@ -8790,8 +8511,7 @@ fn zirFunc( | ... | @@ -8790,8 +8511,7 @@ fn zirFunc( |
| 8790 | // If this instruction has a body it means it's the type of the `owner_decl` | 8511 | // If this instruction has a body it means it's the type of the `owner_decl` |
| 8791 | // otherwise it's a function type without a `callconv` attribute and should | 8512 | // otherwise it's a function type without a `callconv` attribute and should |
| 8792 | // never be `.C`. | 8513 | // never be `.C`. |
| 8793 | // NOTE: revisit when doing #1717 | 8514 | const cc: std.builtin.CallingConvention = if (has_body and mod.declPtr(block.src_decl).is_exported) |
| 8794 | const cc: std.builtin.CallingConvention = if (sema.owner_decl.is_exported and has_body) | ||
| 8795 | .C | 8515 | .C |
| 8796 | else | 8516 | else |
| 8797 | .Unspecified; | 8517 | .Unspecified; |
| ... | @@ -8802,7 +8522,7 @@ fn zirFunc( | ... | @@ -8802,7 +8522,7 @@ fn zirFunc( |
| 8802 | inst, | 8522 | inst, |
| 8803 | .none, | 8523 | .none, |
| 8804 | target_util.defaultAddressSpace(target, .function), | 8524 | target_util.defaultAddressSpace(target, .function), |
| 8805 | FuncLinkSection.default, | 8525 | .default, |
| 8806 | cc, | 8526 | cc, |
| 8807 | ret_ty, | 8527 | ret_ty, |
| 8808 | false, | 8528 | false, |
| ... | @@ -8830,10 +8550,21 @@ fn resolveGenericBody( | ... | @@ -8830,10 +8550,21 @@ fn resolveGenericBody( |
| 8830 | const err = err: { | 8550 | const err = err: { |
| 8831 | // Make sure any nested param instructions don't clobber our work. | 8551 | // Make sure any nested param instructions don't clobber our work. |
| 8832 | const prev_params = block.params; | 8552 | const prev_params = block.params; |
| 8553 | const prev_no_partial_func_type = sema.no_partial_func_ty; | ||
| 8554 | const prev_generic_owner = sema.generic_owner; | ||
| 8555 | const prev_generic_call_src = sema.generic_call_src; | ||
| 8556 | const prev_generic_call_decl = sema.generic_call_decl; | ||
| 8833 | block.params = .{}; | 8557 | block.params = .{}; |
| 8558 | sema.no_partial_func_ty = true; | ||
| 8559 | sema.generic_owner = .none; | ||
| 8560 | sema.generic_call_src = .unneeded; | ||
| 8561 | sema.generic_call_decl = .none; | ||
| 8834 | defer { | 8562 | defer { |
| 8835 | block.params.deinit(sema.gpa); | ||
| 8836 | block.params = prev_params; | 8563 | block.params = prev_params; |
| 8564 | sema.no_partial_func_ty = prev_no_partial_func_type; | ||
| 8565 | sema.generic_owner = prev_generic_owner; | ||
| 8566 | sema.generic_call_src = prev_generic_call_src; | ||
| 8567 | sema.generic_call_decl = prev_generic_call_decl; | ||
| 8837 | } | 8568 | } |
| 8838 | 8569 | ||
| 8839 | const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err; | 8570 | const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err; |
| ... | @@ -8952,7 +8683,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: | ... | @@ -8952,7 +8683,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: |
| 8952 | } | 8683 | } |
| 8953 | } | 8684 | } |
| 8954 | 8685 | ||
| 8955 | const FuncLinkSection = union(enum) { | 8686 | const Section = union(enum) { |
| 8956 | generic, | 8687 | generic, |
| 8957 | default, | 8688 | default, |
| 8958 | explicit: InternPool.NullTerminatedString, | 8689 | explicit: InternPool.NullTerminatedString, |
| ... | @@ -8967,8 +8698,7 @@ fn funcCommon( | ... | @@ -8967,8 +8698,7 @@ fn funcCommon( |
| 8967 | alignment: ?Alignment, | 8698 | alignment: ?Alignment, |
| 8968 | /// null means generic poison | 8699 | /// null means generic poison |
| 8969 | address_space: ?std.builtin.AddressSpace, | 8700 | address_space: ?std.builtin.AddressSpace, |
| 8970 | /// outer null means generic poison; inner null means default link section | 8701 | section: Section, |
| 8971 | section: FuncLinkSection, | ||
| 8972 | /// null means generic poison | 8702 | /// null means generic poison |
| 8973 | cc: ?std.builtin.CallingConvention, | 8703 | cc: ?std.builtin.CallingConvention, |
| 8974 | /// this might be Type.generic_poison | 8704 | /// this might be Type.generic_poison |
| ... | @@ -8984,6 +8714,8 @@ fn funcCommon( | ... | @@ -8984,6 +8714,8 @@ fn funcCommon( |
| 8984 | ) CompileError!Air.Inst.Ref { | 8714 | ) CompileError!Air.Inst.Ref { |
| 8985 | const mod = sema.mod; | 8715 | const mod = sema.mod; |
| 8986 | const gpa = sema.gpa; | 8716 | const gpa = sema.gpa; |
| 8717 | const target = mod.getTarget(); | ||
| 8718 | const ip = &mod.intern_pool; | ||
| 8987 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; | 8719 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| 8988 | const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset }; | 8720 | const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset }; |
| 8989 | const func_src = LazySrcLoc.nodeOffset(src_node_offset); | 8721 | const func_src = LazySrcLoc.nodeOffset(src_node_offset); |
| ... | @@ -9001,226 +8733,150 @@ fn funcCommon( | ... | @@ -9001,226 +8733,150 @@ fn funcCommon( |
| 9001 | try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?); | 8733 | try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?); |
| 9002 | } | 8734 | } |
| 9003 | 8735 | ||
| 9004 | var destroy_fn_on_error = false; | 8736 | const is_source_decl = sema.generic_owner == .none; |
| 9005 | const new_func_index = new_func: { | ||
| 9006 | if (!has_body) break :new_func undefined; | ||
| 9007 | if (sema.comptime_args_fn_inst == func_inst) { | ||
| 9008 | const new_func_index = sema.preallocated_new_func.unwrap().?; | ||
| 9009 | sema.preallocated_new_func = .none; // take ownership | ||
| 9010 | break :new_func new_func_index; | ||
| 9011 | } | ||
| 9012 | destroy_fn_on_error = true; | ||
| 9013 | var new_func: Module.Fn = undefined; | ||
| 9014 | // Set this here so that the inferred return type can be printed correctly if it appears in an error. | ||
| 9015 | new_func.owner_decl = sema.owner_decl_index; | ||
| 9016 | const new_func_index = try mod.createFunc(new_func); | ||
| 9017 | break :new_func new_func_index; | ||
| 9018 | }; | ||
| 9019 | errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index); | ||
| 9020 | 8737 | ||
| 9021 | const target = mod.getTarget(); | 8738 | // In the case of generic calling convention, or generic alignment, we use |
| 9022 | const fn_ty: Type = fn_ty: { | 8739 | // default values which are only meaningful for the generic function, *not* |
| 9023 | // In the case of generic calling convention, or generic alignment, we use | 8740 | // the instantiation, which can depend on comptime parameters. |
| 9024 | // default values which are only meaningful for the generic function, *not* | 8741 | // Related proposal: https://github.com/ziglang/zig/issues/11834 |
| 9025 | // the instantiation, which can depend on comptime parameters. | 8742 | const cc_resolved = cc orelse .Unspecified; |
| 9026 | // Related proposal: https://github.com/ziglang/zig/issues/11834 | 8743 | var comptime_bits: u32 = 0; |
| 9027 | const cc_resolved = cc orelse .Unspecified; | 8744 | for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| { |
| 9028 | const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len); | 8745 | const param_ty = param_ty_ip.toType(); |
| 9029 | var comptime_bits: u32 = 0; | 8746 | const is_noalias = blk: { |
| 9030 | for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| { | 8747 | const index = std.math.cast(u5, i) orelse break :blk false; |
| 9031 | const is_noalias = blk: { | 8748 | break :blk @as(u1, @truncate(noalias_bits >> index)) != 0; |
| 9032 | const index = std.math.cast(u5, i) orelse break :blk false; | ||
| 9033 | break :blk @as(u1, @truncate(noalias_bits >> index)) != 0; | ||
| 9034 | }; | ||
| 9035 | dest_param_ty.* = param.ty.toIntern(); | ||
| 9036 | sema.analyzeParameter( | ||
| 9037 | block, | ||
| 9038 | .unneeded, | ||
| 9039 | param, | ||
| 9040 | &comptime_bits, | ||
| 9041 | i, | ||
| 9042 | &is_generic, | ||
| 9043 | cc_resolved, | ||
| 9044 | has_body, | ||
| 9045 | is_noalias, | ||
| 9046 | ) catch |err| switch (err) { | ||
| 9047 | error.NeededSourceLocation => { | ||
| 9048 | const decl = mod.declPtr(block.src_decl); | ||
| 9049 | try sema.analyzeParameter( | ||
| 9050 | block, | ||
| 9051 | Module.paramSrc(src_node_offset, mod, decl, i), | ||
| 9052 | param, | ||
| 9053 | &comptime_bits, | ||
| 9054 | i, | ||
| 9055 | &is_generic, | ||
| 9056 | cc_resolved, | ||
| 9057 | has_body, | ||
| 9058 | is_noalias, | ||
| 9059 | ); | ||
| 9060 | unreachable; | ||
| 9061 | }, | ||
| 9062 | else => |e| return e, | ||
| 9063 | }; | ||
| 9064 | } | ||
| 9065 | |||
| 9066 | var ret_ty_requires_comptime = false; | ||
| 9067 | const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: { | ||
| 9068 | ret_ty_requires_comptime = ret_comptime; | ||
| 9069 | break :rp bare_return_type.isGenericPoison(); | ||
| 9070 | } else |err| switch (err) { | ||
| 9071 | error.GenericPoison => rp: { | ||
| 9072 | is_generic = true; | ||
| 9073 | break :rp true; | ||
| 9074 | }, | ||
| 9075 | else => |e| return e, | ||
| 9076 | }; | 8749 | }; |
| 9077 | 8750 | const param_src: LazySrcLoc = .{ .fn_proto_param = .{ | |
| 9078 | const return_type: Type = if (!inferred_error_set or ret_poison) | 8751 | .decl = block.src_decl, |
| 9079 | bare_return_type | 8752 | .fn_proto_node_offset = src_node_offset, |
| 9080 | else blk: { | 8753 | .param_index = @intCast(i), |
| 9081 | try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); | 8754 | } }; |
| 9082 | const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{ | 8755 | const requires_comptime = try sema.typeRequiresComptime(param_ty); |
| 9083 | .func = new_func_index, | 8756 | if (param_is_comptime or requires_comptime) { |
| 9084 | }); | 8757 | comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error |
| 9085 | const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index }); | 8758 | } |
| 9086 | break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type); | 8759 | const this_generic = param_ty.isGenericPoison(); |
| 9087 | }; | 8760 | is_generic = is_generic or this_generic; |
| 9088 | 8761 | if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) { | |
| 9089 | if (!return_type.isValidReturnType(mod)) { | 8762 | return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)}); |
| 9090 | const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else ""; | 8763 | } |
| 8764 | if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) { | ||
| 8765 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)}); | ||
| 8766 | } | ||
| 8767 | if (!param_ty.isValidParamType(mod)) { | ||
| 8768 | const opaque_str = if (param_ty.zigTypeTag(mod) == .Opaque) "opaque " else ""; | ||
| 9091 | const msg = msg: { | 8769 | const msg = msg: { |
| 9092 | const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{ | 8770 | const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{ |
| 9093 | opaque_str, return_type.fmt(mod), | 8771 | opaque_str, param_ty.fmt(mod), |
| 9094 | }); | 8772 | }); |
| 9095 | errdefer msg.destroy(gpa); | 8773 | errdefer msg.destroy(sema.gpa); |
| 9096 | 8774 | ||
| 9097 | try sema.addDeclaredHereNote(msg, return_type); | 8775 | try sema.addDeclaredHereNote(msg, param_ty); |
| 9098 | break :msg msg; | 8776 | break :msg msg; |
| 9099 | }; | 8777 | }; |
| 9100 | return sema.failWithOwnedErrorMsg(msg); | 8778 | return sema.failWithOwnedErrorMsg(msg); |
| 9101 | } | 8779 | } |
| 9102 | if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and | 8780 | if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) { |
| 9103 | !try sema.validateExternType(return_type, .ret_ty)) | ||
| 9104 | { | ||
| 9105 | const msg = msg: { | 8781 | const msg = msg: { |
| 9106 | const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ | 8782 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ |
| 9107 | return_type.fmt(mod), @tagName(cc_resolved), | 8783 | param_ty.fmt(mod), @tagName(cc_resolved), |
| 9108 | }); | 8784 | }); |
| 9109 | errdefer msg.destroy(gpa); | 8785 | errdefer msg.destroy(sema.gpa); |
| 9110 | 8786 | ||
| 9111 | const src_decl = mod.declPtr(block.src_decl); | 8787 | const src_decl = mod.declPtr(block.src_decl); |
| 9112 | try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty); | 8788 | try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param_ty, .param_ty); |
| 9113 | 8789 | ||
| 9114 | try sema.addDeclaredHereNote(msg, return_type); | 8790 | try sema.addDeclaredHereNote(msg, param_ty); |
| 9115 | break :msg msg; | 8791 | break :msg msg; |
| 9116 | }; | 8792 | }; |
| 9117 | return sema.failWithOwnedErrorMsg(msg); | 8793 | return sema.failWithOwnedErrorMsg(msg); |
| 9118 | } | 8794 | } |
| 8795 | if (is_source_decl and requires_comptime and !param_is_comptime and has_body) { | ||
| 8796 | const msg = msg: { | ||
| 8797 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ | ||
| 8798 | param_ty.fmt(mod), | ||
| 8799 | }); | ||
| 8800 | errdefer msg.destroy(sema.gpa); | ||
| 9119 | 8801 | ||
| 9120 | // If the return type is comptime-only but not dependent on parameters then all parameter types also need to be comptime | 8802 | const src_decl = mod.declPtr(block.src_decl); |
| 9121 | if (!sema.is_generic_instantiation and has_body and ret_ty_requires_comptime) comptime_check: { | 8803 | try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param_ty); |
| 9122 | for (block.params.items) |param| { | ||
| 9123 | if (!param.is_comptime) break; | ||
| 9124 | } else break :comptime_check; | ||
| 9125 | 8804 | ||
| 9126 | const msg = try sema.errMsg( | 8805 | try sema.addDeclaredHereNote(msg, param_ty); |
| 9127 | block, | 8806 | break :msg msg; |
| 9128 | ret_ty_src, | 8807 | }; |
| 9129 | "function with comptime-only return type '{}' requires all parameters to be comptime", | ||
| 9130 | .{return_type.fmt(mod)}, | ||
| 9131 | ); | ||
| 9132 | try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type); | ||
| 9133 | |||
| 9134 | const tags = sema.code.instructions.items(.tag); | ||
| 9135 | const data = sema.code.instructions.items(.data); | ||
| 9136 | const param_body = sema.code.getParamBody(func_inst); | ||
| 9137 | for (block.params.items, 0..) |param, i| { | ||
| 9138 | if (!param.is_comptime) { | ||
| 9139 | const param_index = param_body[i]; | ||
| 9140 | const param_src = switch (tags[param_index]) { | ||
| 9141 | .param => data[param_index].pl_tok.src(), | ||
| 9142 | .param_anytype => data[param_index].str_tok.src(), | ||
| 9143 | else => unreachable, | ||
| 9144 | }; | ||
| 9145 | if (param.name.len != 0) { | ||
| 9146 | try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{param.name}); | ||
| 9147 | } else { | ||
| 9148 | try sema.errNote(block, param_src, msg, "param is required to be comptime", .{}); | ||
| 9149 | } | ||
| 9150 | } | ||
| 9151 | } | ||
| 9152 | return sema.failWithOwnedErrorMsg(msg); | 8808 | return sema.failWithOwnedErrorMsg(msg); |
| 9153 | } | 8809 | } |
| 9154 | 8810 | if (is_source_decl and !this_generic and is_noalias and | |
| 9155 | const arch = mod.getTarget().cpu.arch; | 8811 | !(param_ty.zigTypeTag(mod) == .Pointer or param_ty.isPtrLikeOptional(mod))) |
| 9156 | if (switch (cc_resolved) { | 8812 | { |
| 9157 | .Unspecified, .C, .Naked, .Async, .Inline => null, | 8813 | return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); |
| 9158 | .Interrupt => switch (arch) { | ||
| 9159 | .x86, .x86_64, .avr, .msp430 => null, | ||
| 9160 | else => @as([]const u8, "x86, x86_64, AVR, and MSP430"), | ||
| 9161 | }, | ||
| 9162 | .Signal => switch (arch) { | ||
| 9163 | .avr => null, | ||
| 9164 | else => @as([]const u8, "AVR"), | ||
| 9165 | }, | ||
| 9166 | .Stdcall, .Fastcall, .Thiscall => switch (arch) { | ||
| 9167 | .x86 => null, | ||
| 9168 | else => @as([]const u8, "x86"), | ||
| 9169 | }, | ||
| 9170 | .Vectorcall => switch (arch) { | ||
| 9171 | .x86, .aarch64, .aarch64_be, .aarch64_32 => null, | ||
| 9172 | else => @as([]const u8, "x86 and AArch64"), | ||
| 9173 | }, | ||
| 9174 | .APCS, .AAPCS, .AAPCSVFP => switch (arch) { | ||
| 9175 | .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32, .thumb, .thumbeb => null, | ||
| 9176 | else => @as([]const u8, "ARM"), | ||
| 9177 | }, | ||
| 9178 | .SysV, .Win64 => switch (arch) { | ||
| 9179 | .x86_64 => null, | ||
| 9180 | else => @as([]const u8, "x86_64"), | ||
| 9181 | }, | ||
| 9182 | .Kernel => switch (arch) { | ||
| 9183 | .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null, | ||
| 9184 | else => @as([]const u8, "nvptx, amdgcn and SPIR-V"), | ||
| 9185 | }, | ||
| 9186 | }) |allowed_platform| { | ||
| 9187 | return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{ | ||
| 9188 | @tagName(cc_resolved), | ||
| 9189 | allowed_platform, | ||
| 9190 | @tagName(arch), | ||
| 9191 | }); | ||
| 9192 | } | ||
| 9193 | |||
| 9194 | if (cc_resolved == .Inline and is_noinline) { | ||
| 9195 | return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{}); | ||
| 9196 | } | 8814 | } |
| 9197 | if (is_generic and sema.no_partial_func_ty) return error.GenericPoison; | 8815 | } |
| 9198 | is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime; | ||
| 9199 | 8816 | ||
| 9200 | if (!is_generic and sema.wantErrorReturnTracing(return_type)) { | 8817 | var ret_ty_requires_comptime = false; |
| 9201 | // Make sure that StackTrace's fields are resolved so that the backend can | 8818 | const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: { |
| 9202 | // lower this fn type. | 8819 | ret_ty_requires_comptime = ret_comptime; |
| 9203 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); | 8820 | break :rp bare_return_type.isGenericPoison(); |
| 9204 | _ = try sema.resolveTypeFields(unresolved_stack_trace_ty); | 8821 | } else |err| switch (err) { |
| 8822 | error.GenericPoison => rp: { | ||
| 8823 | is_generic = true; | ||
| 8824 | break :rp true; | ||
| 8825 | }, | ||
| 8826 | else => |e| return e, | ||
| 8827 | }; | ||
| 8828 | const final_is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime; | ||
| 8829 | |||
| 8830 | const param_types = block.params.items(.ty); | ||
| 8831 | |||
| 8832 | if (!is_source_decl) { | ||
| 8833 | assert(has_body); | ||
| 8834 | assert(!is_generic); | ||
| 8835 | assert(comptime_bits == 0); | ||
| 8836 | assert(cc != null); | ||
| 8837 | assert(section != .generic); | ||
| 8838 | assert(address_space != null); | ||
| 8839 | assert(!var_args); | ||
| 8840 | if (inferred_error_set) { | ||
| 8841 | try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); | ||
| 9205 | } | 8842 | } |
| 9206 | 8843 | const func_index = try ip.getFuncInstance(gpa, .{ | |
| 9207 | break :fn_ty try mod.funcType(.{ | ||
| 9208 | .param_types = param_types, | 8844 | .param_types = param_types, |
| 9209 | .noalias_bits = noalias_bits, | 8845 | .noalias_bits = noalias_bits, |
| 9210 | .comptime_bits = comptime_bits, | 8846 | .bare_return_type = bare_return_type.toIntern(), |
| 9211 | .return_type = return_type.toIntern(), | ||
| 9212 | .cc = cc_resolved, | 8847 | .cc = cc_resolved, |
| 9213 | .cc_is_generic = cc == null, | 8848 | .alignment = alignment.?, |
| 9214 | .alignment = alignment orelse .none, | 8849 | .section = switch (section) { |
| 9215 | .align_is_generic = alignment == null, | 8850 | .generic => unreachable, |
| 9216 | .section_is_generic = section == .generic, | 8851 | .default => .none, |
| 9217 | .addrspace_is_generic = address_space == null, | 8852 | .explicit => |x| x.toOptional(), |
| 9218 | .is_var_args = var_args, | 8853 | }, |
| 9219 | .is_generic = is_generic, | ||
| 9220 | .is_noinline = is_noinline, | 8854 | .is_noinline = is_noinline, |
| 8855 | .inferred_error_set = inferred_error_set, | ||
| 8856 | .generic_owner = sema.generic_owner, | ||
| 8857 | .comptime_args = sema.comptime_args, | ||
| 8858 | .generation = mod.generation, | ||
| 9221 | }); | 8859 | }); |
| 9222 | }; | 8860 | return finishFunc( |
| 8861 | sema, | ||
| 8862 | block, | ||
| 8863 | func_index, | ||
| 8864 | .none, | ||
| 8865 | ret_poison, | ||
| 8866 | bare_return_type, | ||
| 8867 | ret_ty_src, | ||
| 8868 | cc_resolved, | ||
| 8869 | is_source_decl, | ||
| 8870 | ret_ty_requires_comptime, | ||
| 8871 | func_inst, | ||
| 8872 | cc_src, | ||
| 8873 | is_noinline, | ||
| 8874 | is_generic, | ||
| 8875 | final_is_generic, | ||
| 8876 | ); | ||
| 8877 | } | ||
| 9223 | 8878 | ||
| 8879 | // extern_func and func_decl functions take ownership of `sema.owner_decl`. | ||
| 9224 | sema.owner_decl.@"linksection" = switch (section) { | 8880 | sema.owner_decl.@"linksection" = switch (section) { |
| 9225 | .generic => .none, | 8881 | .generic => .none, |
| 9226 | .default => .none, | 8882 | .default => .none, |
| ... | @@ -9229,9 +8885,73 @@ fn funcCommon( | ... | @@ -9229,9 +8885,73 @@ fn funcCommon( |
| 9229 | sema.owner_decl.alignment = alignment orelse .none; | 8885 | sema.owner_decl.alignment = alignment orelse .none; |
| 9230 | sema.owner_decl.@"addrspace" = address_space orelse .generic; | 8886 | sema.owner_decl.@"addrspace" = address_space orelse .generic; |
| 9231 | 8887 | ||
| 8888 | if (inferred_error_set) { | ||
| 8889 | assert(!is_extern); | ||
| 8890 | assert(has_body); | ||
| 8891 | if (!ret_poison) | ||
| 8892 | try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); | ||
| 8893 | const func_index = try ip.getFuncDeclIes(gpa, .{ | ||
| 8894 | .owner_decl = sema.owner_decl_index, | ||
| 8895 | |||
| 8896 | .param_types = param_types, | ||
| 8897 | .noalias_bits = noalias_bits, | ||
| 8898 | .comptime_bits = comptime_bits, | ||
| 8899 | .bare_return_type = bare_return_type.toIntern(), | ||
| 8900 | .cc = cc, | ||
| 8901 | .alignment = alignment, | ||
| 8902 | .section_is_generic = section == .generic, | ||
| 8903 | .addrspace_is_generic = address_space == null, | ||
| 8904 | .is_var_args = var_args, | ||
| 8905 | .is_generic = final_is_generic, | ||
| 8906 | .is_noinline = is_noinline, | ||
| 8907 | |||
| 8908 | .zir_body_inst = func_inst, | ||
| 8909 | .lbrace_line = src_locs.lbrace_line, | ||
| 8910 | .rbrace_line = src_locs.rbrace_line, | ||
| 8911 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), | ||
| 8912 | .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), | ||
| 8913 | }); | ||
| 8914 | return finishFunc( | ||
| 8915 | sema, | ||
| 8916 | block, | ||
| 8917 | func_index, | ||
| 8918 | .none, | ||
| 8919 | ret_poison, | ||
| 8920 | bare_return_type, | ||
| 8921 | ret_ty_src, | ||
| 8922 | cc_resolved, | ||
| 8923 | is_source_decl, | ||
| 8924 | ret_ty_requires_comptime, | ||
| 8925 | func_inst, | ||
| 8926 | cc_src, | ||
| 8927 | is_noinline, | ||
| 8928 | is_generic, | ||
| 8929 | final_is_generic, | ||
| 8930 | ); | ||
| 8931 | } | ||
| 8932 | |||
| 8933 | const func_ty = try ip.getFuncType(gpa, .{ | ||
| 8934 | .param_types = param_types, | ||
| 8935 | .noalias_bits = noalias_bits, | ||
| 8936 | .comptime_bits = comptime_bits, | ||
| 8937 | .return_type = bare_return_type.toIntern(), | ||
| 8938 | .cc = cc, | ||
| 8939 | .alignment = alignment, | ||
| 8940 | .section_is_generic = section == .generic, | ||
| 8941 | .addrspace_is_generic = address_space == null, | ||
| 8942 | .is_var_args = var_args, | ||
| 8943 | .is_generic = final_is_generic, | ||
| 8944 | .is_noinline = is_noinline, | ||
| 8945 | }); | ||
| 8946 | |||
| 9232 | if (is_extern) { | 8947 | if (is_extern) { |
| 9233 | return sema.addConstant((try mod.intern(.{ .extern_func = .{ | 8948 | assert(comptime_bits == 0); |
| 9234 | .ty = fn_ty.toIntern(), | 8949 | assert(cc != null); |
| 8950 | assert(section != .generic); | ||
| 8951 | assert(address_space != null); | ||
| 8952 | assert(!is_generic); | ||
| 8953 | const func_index = try ip.getExternFunc(gpa, .{ | ||
| 8954 | .ty = func_ty, | ||
| 9235 | .decl = sema.owner_decl_index, | 8955 | .decl = sema.owner_decl_index, |
| 9236 | .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString( | 8956 | .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString( |
| 9237 | gpa, | 8957 | gpa, |
| ... | @@ -9239,129 +8959,241 @@ fn funcCommon( | ... | @@ -9239,129 +8959,241 @@ fn funcCommon( |
| 9239 | .node_offset_lib_name = src_node_offset, | 8959 | .node_offset_lib_name = src_node_offset, |
| 9240 | }, lib_name), | 8960 | }, lib_name), |
| 9241 | )).toOptional() else .none, | 8961 | )).toOptional() else .none, |
| 9242 | } })).toValue()); | 8962 | }); |
| 8963 | return finishFunc( | ||
| 8964 | sema, | ||
| 8965 | block, | ||
| 8966 | func_index, | ||
| 8967 | func_ty, | ||
| 8968 | ret_poison, | ||
| 8969 | bare_return_type, | ||
| 8970 | ret_ty_src, | ||
| 8971 | cc_resolved, | ||
| 8972 | is_source_decl, | ||
| 8973 | ret_ty_requires_comptime, | ||
| 8974 | func_inst, | ||
| 8975 | cc_src, | ||
| 8976 | is_noinline, | ||
| 8977 | is_generic, | ||
| 8978 | final_is_generic, | ||
| 8979 | ); | ||
| 9243 | } | 8980 | } |
| 9244 | 8981 | ||
| 9245 | if (!has_body) { | 8982 | if (has_body) { |
| 9246 | return sema.addType(fn_ty); | 8983 | const func_index = try ip.getFuncDecl(gpa, .{ |
| 8984 | .owner_decl = sema.owner_decl_index, | ||
| 8985 | .ty = func_ty, | ||
| 8986 | .cc = cc, | ||
| 8987 | .is_noinline = is_noinline, | ||
| 8988 | .zir_body_inst = func_inst, | ||
| 8989 | .lbrace_line = src_locs.lbrace_line, | ||
| 8990 | .rbrace_line = src_locs.rbrace_line, | ||
| 8991 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), | ||
| 8992 | .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), | ||
| 8993 | }); | ||
| 8994 | return finishFunc( | ||
| 8995 | sema, | ||
| 8996 | block, | ||
| 8997 | func_index, | ||
| 8998 | func_ty, | ||
| 8999 | ret_poison, | ||
| 9000 | bare_return_type, | ||
| 9001 | ret_ty_src, | ||
| 9002 | cc_resolved, | ||
| 9003 | is_source_decl, | ||
| 9004 | ret_ty_requires_comptime, | ||
| 9005 | func_inst, | ||
| 9006 | cc_src, | ||
| 9007 | is_noinline, | ||
| 9008 | is_generic, | ||
| 9009 | final_is_generic, | ||
| 9010 | ); | ||
| 9247 | } | 9011 | } |
| 9248 | 9012 | ||
| 9249 | const is_inline = fn_ty.fnCallingConvention(mod) == .Inline; | 9013 | return finishFunc( |
| 9250 | const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none; | 9014 | sema, |
| 9251 | 9015 | block, | |
| 9252 | const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: { | 9016 | .none, |
| 9253 | break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr; | 9017 | func_ty, |
| 9254 | } else null; | 9018 | ret_poison, |
| 9255 | 9019 | bare_return_type, | |
| 9256 | const new_func = mod.funcPtr(new_func_index); | 9020 | ret_ty_src, |
| 9257 | const hash = new_func.hash; | 9021 | cc_resolved, |
| 9258 | const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl; | 9022 | is_source_decl, |
| 9259 | new_func.* = .{ | 9023 | ret_ty_requires_comptime, |
| 9260 | .state = anal_state, | 9024 | func_inst, |
| 9261 | .zir_body_inst = func_inst, | 9025 | cc_src, |
| 9262 | .owner_decl = sema.owner_decl_index, | 9026 | is_noinline, |
| 9263 | .generic_owner_decl = generic_owner_decl, | 9027 | is_generic, |
| 9264 | .comptime_args = comptime_args, | 9028 | final_is_generic, |
| 9265 | .hash = hash, | 9029 | ); |
| 9266 | .lbrace_line = src_locs.lbrace_line, | ||
| 9267 | .rbrace_line = src_locs.rbrace_line, | ||
| 9268 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), | ||
| 9269 | .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), | ||
| 9270 | .branch_quota = default_branch_quota, | ||
| 9271 | .is_noinline = is_noinline, | ||
| 9272 | }; | ||
| 9273 | return sema.addConstant((try mod.intern(.{ .func = .{ | ||
| 9274 | .ty = fn_ty.toIntern(), | ||
| 9275 | .index = new_func_index, | ||
| 9276 | } })).toValue()); | ||
| 9277 | } | 9030 | } |
| 9278 | 9031 | ||
| 9279 | fn analyzeParameter( | 9032 | fn finishFunc( |
| 9280 | sema: *Sema, | 9033 | sema: *Sema, |
| 9281 | block: *Block, | 9034 | block: *Block, |
| 9282 | param_src: LazySrcLoc, | 9035 | opt_func_index: InternPool.Index, |
| 9283 | param: Block.Param, | 9036 | func_ty: InternPool.Index, |
| 9284 | comptime_bits: *u32, | 9037 | ret_poison: bool, |
| 9285 | i: usize, | 9038 | bare_return_type: Type, |
| 9286 | is_generic: *bool, | 9039 | ret_ty_src: LazySrcLoc, |
| 9287 | cc: std.builtin.CallingConvention, | 9040 | cc_resolved: std.builtin.CallingConvention, |
| 9288 | has_body: bool, | 9041 | is_source_decl: bool, |
| 9289 | is_noalias: bool, | 9042 | ret_ty_requires_comptime: bool, |
| 9290 | ) !void { | 9043 | func_inst: Zir.Inst.Index, |
| 9044 | cc_src: LazySrcLoc, | ||
| 9045 | is_noinline: bool, | ||
| 9046 | is_generic: bool, | ||
| 9047 | final_is_generic: bool, | ||
| 9048 | ) CompileError!Air.Inst.Ref { | ||
| 9291 | const mod = sema.mod; | 9049 | const mod = sema.mod; |
| 9292 | const requires_comptime = try sema.typeRequiresComptime(param.ty); | 9050 | const ip = &mod.intern_pool; |
| 9293 | if (param.is_comptime or requires_comptime) { | 9051 | const gpa = sema.gpa; |
| 9294 | comptime_bits.* |= @as(u32, 1) << @as(u5, @intCast(i)); // TODO: handle cast error | ||
| 9295 | } | ||
| 9296 | const this_generic = param.ty.isGenericPoison(); | ||
| 9297 | is_generic.* = is_generic.* or this_generic; | ||
| 9298 | const target = mod.getTarget(); | 9052 | const target = mod.getTarget(); |
| 9299 | if (param.is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc)) { | 9053 | |
| 9300 | return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); | 9054 | const return_type: Type = if (opt_func_index == .none or ret_poison) |
| 9301 | } | 9055 | bare_return_type |
| 9302 | if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc)) { | 9056 | else |
| 9303 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); | 9057 | ip.funcTypeReturnType(ip.typeOf(opt_func_index)).toType(); |
| 9304 | } | 9058 | |
| 9305 | if (!param.ty.isValidParamType(mod)) { | 9059 | if (!return_type.isValidReturnType(mod)) { |
| 9306 | const opaque_str = if (param.ty.zigTypeTag(mod) == .Opaque) "opaque " else ""; | 9060 | const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else ""; |
| 9307 | const msg = msg: { | 9061 | const msg = msg: { |
| 9308 | const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{ | 9062 | const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{ |
| 9309 | opaque_str, param.ty.fmt(mod), | 9063 | opaque_str, return_type.fmt(mod), |
| 9310 | }); | 9064 | }); |
| 9311 | errdefer msg.destroy(sema.gpa); | 9065 | errdefer msg.destroy(gpa); |
| 9312 | 9066 | ||
| 9313 | try sema.addDeclaredHereNote(msg, param.ty); | 9067 | try sema.addDeclaredHereNote(msg, return_type); |
| 9314 | break :msg msg; | 9068 | break :msg msg; |
| 9315 | }; | 9069 | }; |
| 9316 | return sema.failWithOwnedErrorMsg(msg); | 9070 | return sema.failWithOwnedErrorMsg(msg); |
| 9317 | } | 9071 | } |
| 9318 | if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) { | 9072 | if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and |
| 9073 | !try sema.validateExternType(return_type, .ret_ty)) | ||
| 9074 | { | ||
| 9319 | const msg = msg: { | 9075 | const msg = msg: { |
| 9320 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ | 9076 | const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ |
| 9321 | param.ty.fmt(mod), @tagName(cc), | 9077 | return_type.fmt(mod), @tagName(cc_resolved), |
| 9322 | }); | 9078 | }); |
| 9323 | errdefer msg.destroy(sema.gpa); | 9079 | errdefer msg.destroy(gpa); |
| 9324 | 9080 | ||
| 9325 | const src_decl = mod.declPtr(block.src_decl); | 9081 | const src_decl = mod.declPtr(block.src_decl); |
| 9326 | try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param.ty, .param_ty); | 9082 | try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty); |
| 9327 | 9083 | ||
| 9328 | try sema.addDeclaredHereNote(msg, param.ty); | 9084 | try sema.addDeclaredHereNote(msg, return_type); |
| 9329 | break :msg msg; | 9085 | break :msg msg; |
| 9330 | }; | 9086 | }; |
| 9331 | return sema.failWithOwnedErrorMsg(msg); | 9087 | return sema.failWithOwnedErrorMsg(msg); |
| 9332 | } | 9088 | } |
| 9333 | if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) { | ||
| 9334 | const msg = msg: { | ||
| 9335 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ | ||
| 9336 | param.ty.fmt(mod), | ||
| 9337 | }); | ||
| 9338 | errdefer msg.destroy(sema.gpa); | ||
| 9339 | 9089 | ||
| 9340 | const src_decl = mod.declPtr(block.src_decl); | 9090 | // If the return type is comptime-only but not dependent on parameters then |
| 9341 | try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param.ty); | 9091 | // all parameter types also need to be comptime. |
| 9092 | if (is_source_decl and opt_func_index != .none and ret_ty_requires_comptime) comptime_check: { | ||
| 9093 | for (block.params.items(.is_comptime)) |is_comptime| { | ||
| 9094 | if (!is_comptime) break; | ||
| 9095 | } else break :comptime_check; | ||
| 9342 | 9096 | ||
| 9343 | try sema.addDeclaredHereNote(msg, param.ty); | 9097 | const msg = try sema.errMsg( |
| 9344 | break :msg msg; | 9098 | block, |
| 9345 | }; | 9099 | ret_ty_src, |
| 9100 | "function with comptime-only return type '{}' requires all parameters to be comptime", | ||
| 9101 | .{return_type.fmt(mod)}, | ||
| 9102 | ); | ||
| 9103 | try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type); | ||
| 9104 | |||
| 9105 | const tags = sema.code.instructions.items(.tag); | ||
| 9106 | const data = sema.code.instructions.items(.data); | ||
| 9107 | const param_body = sema.code.getParamBody(func_inst); | ||
| 9108 | for ( | ||
| 9109 | block.params.items(.is_comptime), | ||
| 9110 | block.params.items(.name), | ||
| 9111 | param_body[0..block.params.len], | ||
| 9112 | ) |is_comptime, name_nts, param_index| { | ||
| 9113 | if (!is_comptime) { | ||
| 9114 | const param_src = switch (tags[param_index]) { | ||
| 9115 | .param => data[param_index].pl_tok.src(), | ||
| 9116 | .param_anytype => data[param_index].str_tok.src(), | ||
| 9117 | else => unreachable, | ||
| 9118 | }; | ||
| 9119 | const name = sema.code.nullTerminatedString2(name_nts); | ||
| 9120 | if (name.len != 0) { | ||
| 9121 | try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{name}); | ||
| 9122 | } else { | ||
| 9123 | try sema.errNote(block, param_src, msg, "param is required to be comptime", .{}); | ||
| 9124 | } | ||
| 9125 | } | ||
| 9126 | } | ||
| 9346 | return sema.failWithOwnedErrorMsg(msg); | 9127 | return sema.failWithOwnedErrorMsg(msg); |
| 9347 | } | 9128 | } |
| 9348 | if (!sema.is_generic_instantiation and !this_generic and is_noalias and | 9129 | |
| 9349 | !(param.ty.zigTypeTag(mod) == .Pointer or param.ty.isPtrLikeOptional(mod))) | 9130 | const arch = target.cpu.arch; |
| 9350 | { | 9131 | if (switch (cc_resolved) { |
| 9351 | return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); | 9132 | .Unspecified, .C, .Naked, .Async, .Inline => null, |
| 9133 | .Interrupt => switch (arch) { | ||
| 9134 | .x86, .x86_64, .avr, .msp430 => null, | ||
| 9135 | else => @as([]const u8, "x86, x86_64, AVR, and MSP430"), | ||
| 9136 | }, | ||
| 9137 | .Signal => switch (arch) { | ||
| 9138 | .avr => null, | ||
| 9139 | else => @as([]const u8, "AVR"), | ||
| 9140 | }, | ||
| 9141 | .Stdcall, .Fastcall, .Thiscall => switch (arch) { | ||
| 9142 | .x86 => null, | ||
| 9143 | else => @as([]const u8, "x86"), | ||
| 9144 | }, | ||
| 9145 | .Vectorcall => switch (arch) { | ||
| 9146 | .x86, .aarch64, .aarch64_be, .aarch64_32 => null, | ||
| 9147 | else => @as([]const u8, "x86 and AArch64"), | ||
| 9148 | }, | ||
| 9149 | .APCS, .AAPCS, .AAPCSVFP => switch (arch) { | ||
| 9150 | .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32, .thumb, .thumbeb => null, | ||
| 9151 | else => @as([]const u8, "ARM"), | ||
| 9152 | }, | ||
| 9153 | .SysV, .Win64 => switch (arch) { | ||
| 9154 | .x86_64 => null, | ||
| 9155 | else => @as([]const u8, "x86_64"), | ||
| 9156 | }, | ||
| 9157 | .Kernel => switch (arch) { | ||
| 9158 | .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null, | ||
| 9159 | else => @as([]const u8, "nvptx, amdgcn and SPIR-V"), | ||
| 9160 | }, | ||
| 9161 | }) |allowed_platform| { | ||
| 9162 | return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{ | ||
| 9163 | @tagName(cc_resolved), | ||
| 9164 | allowed_platform, | ||
| 9165 | @tagName(arch), | ||
| 9166 | }); | ||
| 9352 | } | 9167 | } |
| 9168 | |||
| 9169 | if (cc_resolved == .Inline and is_noinline) { | ||
| 9170 | return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{}); | ||
| 9171 | } | ||
| 9172 | if (is_generic and sema.no_partial_func_ty) return error.GenericPoison; | ||
| 9173 | |||
| 9174 | if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) { | ||
| 9175 | // Make sure that StackTrace's fields are resolved so that the backend can | ||
| 9176 | // lower this fn type. | ||
| 9177 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); | ||
| 9178 | _ = try sema.resolveTypeFields(unresolved_stack_trace_ty); | ||
| 9179 | } | ||
| 9180 | |||
| 9181 | return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty); | ||
| 9353 | } | 9182 | } |
| 9354 | 9183 | ||
| 9355 | fn zirParam( | 9184 | fn zirParam( |
| 9356 | sema: *Sema, | 9185 | sema: *Sema, |
| 9357 | block: *Block, | 9186 | block: *Block, |
| 9358 | inst: Zir.Inst.Index, | 9187 | inst: Zir.Inst.Index, |
| 9188 | param_index: u32, | ||
| 9359 | comptime_syntax: bool, | 9189 | comptime_syntax: bool, |
| 9360 | ) CompileError!void { | 9190 | ) CompileError!void { |
| 9191 | const mod = sema.mod; | ||
| 9192 | const gpa = sema.gpa; | ||
| 9361 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; | 9193 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; |
| 9362 | const src = inst_data.src(); | 9194 | const src = inst_data.src(); |
| 9363 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); | 9195 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); |
| 9364 | const param_name = sema.code.nullTerminatedString(extra.data.name); | 9196 | const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name); |
| 9365 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 9197 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 9366 | 9198 | ||
| 9367 | // We could be in a generic function instantiation, or we could be evaluating a generic | 9199 | // We could be in a generic function instantiation, or we could be evaluating a generic |
| ... | @@ -9370,16 +9202,21 @@ fn zirParam( | ... | @@ -9370,16 +9202,21 @@ fn zirParam( |
| 9370 | const err = err: { | 9202 | const err = err: { |
| 9371 | // Make sure any nested param instructions don't clobber our work. | 9203 | // Make sure any nested param instructions don't clobber our work. |
| 9372 | const prev_params = block.params; | 9204 | const prev_params = block.params; |
| 9373 | const prev_preallocated_new_func = sema.preallocated_new_func; | ||
| 9374 | const prev_no_partial_func_type = sema.no_partial_func_ty; | 9205 | const prev_no_partial_func_type = sema.no_partial_func_ty; |
| 9206 | const prev_generic_owner = sema.generic_owner; | ||
| 9207 | const prev_generic_call_src = sema.generic_call_src; | ||
| 9208 | const prev_generic_call_decl = sema.generic_call_decl; | ||
| 9375 | block.params = .{}; | 9209 | block.params = .{}; |
| 9376 | sema.preallocated_new_func = .none; | ||
| 9377 | sema.no_partial_func_ty = true; | 9210 | sema.no_partial_func_ty = true; |
| 9211 | sema.generic_owner = .none; | ||
| 9212 | sema.generic_call_src = .unneeded; | ||
| 9213 | sema.generic_call_decl = .none; | ||
| 9378 | defer { | 9214 | defer { |
| 9379 | block.params.deinit(sema.gpa); | ||
| 9380 | block.params = prev_params; | 9215 | block.params = prev_params; |
| 9381 | sema.preallocated_new_func = prev_preallocated_new_func; | ||
| 9382 | sema.no_partial_func_ty = prev_no_partial_func_type; | 9216 | sema.no_partial_func_ty = prev_no_partial_func_type; |
| 9217 | sema.generic_owner = prev_generic_owner; | ||
| 9218 | sema.generic_call_src = prev_generic_call_src; | ||
| 9219 | sema.generic_call_decl = prev_generic_call_decl; | ||
| 9383 | } | 9220 | } |
| 9384 | 9221 | ||
| 9385 | if (sema.resolveBody(block, body, inst)) |param_ty_inst| { | 9222 | if (sema.resolveBody(block, body, inst)) |param_ty_inst| { |
| ... | @@ -9390,7 +9227,7 @@ fn zirParam( | ... | @@ -9390,7 +9227,7 @@ fn zirParam( |
| 9390 | }; | 9227 | }; |
| 9391 | switch (err) { | 9228 | switch (err) { |
| 9392 | error.GenericPoison => { | 9229 | error.GenericPoison => { |
| 9393 | if (sema.inst_map.get(inst)) |_| { | 9230 | if (sema.inst_map.contains(inst)) { |
| 9394 | // A generic function is about to evaluate to another generic function. | 9231 | // A generic function is about to evaluate to another generic function. |
| 9395 | // Return an error instead. | 9232 | // Return an error instead. |
| 9396 | return error.GenericPoison; | 9233 | return error.GenericPoison; |
| ... | @@ -9398,8 +9235,8 @@ fn zirParam( | ... | @@ -9398,8 +9235,8 @@ fn zirParam( |
| 9398 | // The type is not available until the generic instantiation. | 9235 | // The type is not available until the generic instantiation. |
| 9399 | // We result the param instruction with a poison value and | 9236 | // We result the param instruction with a poison value and |
| 9400 | // insert an anytype parameter. | 9237 | // insert an anytype parameter. |
| 9401 | try block.params.append(sema.gpa, .{ | 9238 | try block.params.append(sema.arena, .{ |
| 9402 | .ty = Type.generic_poison, | 9239 | .ty = .generic_poison_type, |
| 9403 | .is_comptime = comptime_syntax, | 9240 | .is_comptime = comptime_syntax, |
| 9404 | .name = param_name, | 9241 | .name = param_name, |
| 9405 | }); | 9242 | }); |
| ... | @@ -9409,9 +9246,10 @@ fn zirParam( | ... | @@ -9409,9 +9246,10 @@ fn zirParam( |
| 9409 | else => |e| return e, | 9246 | else => |e| return e, |
| 9410 | } | 9247 | } |
| 9411 | }; | 9248 | }; |
| 9249 | |||
| 9412 | const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) { | 9250 | const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) { |
| 9413 | error.GenericPoison => { | 9251 | error.GenericPoison => { |
| 9414 | if (sema.inst_map.get(inst)) |_| { | 9252 | if (sema.inst_map.contains(inst)) { |
| 9415 | // A generic function is about to evaluate to another generic function. | 9253 | // A generic function is about to evaluate to another generic function. |
| 9416 | // Return an error instead. | 9254 | // Return an error instead. |
| 9417 | return error.GenericPoison; | 9255 | return error.GenericPoison; |
| ... | @@ -9419,8 +9257,8 @@ fn zirParam( | ... | @@ -9419,8 +9257,8 @@ fn zirParam( |
| 9419 | // The type is not available until the generic instantiation. | 9257 | // The type is not available until the generic instantiation. |
| 9420 | // We result the param instruction with a poison value and | 9258 | // We result the param instruction with a poison value and |
| 9421 | // insert an anytype parameter. | 9259 | // insert an anytype parameter. |
| 9422 | try block.params.append(sema.gpa, .{ | 9260 | try block.params.append(sema.arena, .{ |
| 9423 | .ty = Type.generic_poison, | 9261 | .ty = .generic_poison_type, |
| 9424 | .is_comptime = comptime_syntax, | 9262 | .is_comptime = comptime_syntax, |
| 9425 | .name = param_name, | 9263 | .name = param_name, |
| 9426 | }); | 9264 | }); |
| ... | @@ -9429,8 +9267,9 @@ fn zirParam( | ... | @@ -9429,8 +9267,9 @@ fn zirParam( |
| 9429 | }, | 9267 | }, |
| 9430 | else => |e| return e, | 9268 | else => |e| return e, |
| 9431 | } or comptime_syntax; | 9269 | } or comptime_syntax; |
| 9270 | |||
| 9432 | if (sema.inst_map.get(inst)) |arg| { | 9271 | if (sema.inst_map.get(inst)) |arg| { |
| 9433 | if (is_comptime and sema.preallocated_new_func != .none) { | 9272 | if (is_comptime and sema.generic_owner != .none) { |
| 9434 | // We have a comptime value for this parameter so it should be elided from the | 9273 | // We have a comptime value for this parameter so it should be elided from the |
| 9435 | // function type of the function instruction in this block. | 9274 | // function type of the function instruction in this block. |
| 9436 | const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) { | 9275 | const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) { |
| ... | @@ -9440,32 +9279,53 @@ fn zirParam( | ... | @@ -9440,32 +9279,53 @@ fn zirParam( |
| 9440 | // have the callee source location return `GenericPoison` | 9279 | // have the callee source location return `GenericPoison` |
| 9441 | // so that the instantiation is failed and the coercion | 9280 | // so that the instantiation is failed and the coercion |
| 9442 | // is handled by comptime call logic instead. | 9281 | // is handled by comptime call logic instead. |
| 9443 | assert(sema.is_generic_instantiation); | 9282 | assert(sema.generic_owner != .none); |
| 9444 | return error.GenericPoison; | 9283 | return error.GenericPoison; |
| 9445 | }, | 9284 | }, |
| 9446 | else => return err, | 9285 | else => |e| return e, |
| 9447 | }; | 9286 | }; |
| 9448 | sema.inst_map.putAssumeCapacity(inst, coerced_arg); | 9287 | sema.inst_map.putAssumeCapacity(inst, coerced_arg); |
| 9449 | return; | 9288 | if (try sema.resolveMaybeUndefVal(coerced_arg)) |val| { |
| 9289 | sema.comptime_args[param_index] = val.toIntern(); | ||
| 9290 | return; | ||
| 9291 | } | ||
| 9292 | const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{ | ||
| 9293 | .decl = sema.generic_call_decl.unwrap().?, | ||
| 9294 | .call_node_offset = sema.generic_call_src.node_offset.x, | ||
| 9295 | .arg_index = param_index, | ||
| 9296 | } } else src; | ||
| 9297 | const msg = msg: { | ||
| 9298 | const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod); | ||
| 9299 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ | ||
| 9300 | @as([]const u8, "runtime-known argument passed to comptime parameter"), | ||
| 9301 | }); | ||
| 9302 | errdefer msg.destroy(gpa); | ||
| 9303 | |||
| 9304 | if (sema.generic_call_decl != .none) { | ||
| 9305 | try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")}); | ||
| 9306 | } | ||
| 9307 | break :msg msg; | ||
| 9308 | }; | ||
| 9309 | return sema.failWithOwnedErrorMsg(msg); | ||
| 9450 | } | 9310 | } |
| 9451 | // Even though a comptime argument is provided, the generic function wants to treat | 9311 | // Even though a comptime argument is provided, the generic function wants to treat |
| 9452 | // this as a runtime parameter. | 9312 | // this as a runtime parameter. |
| 9453 | assert(sema.inst_map.remove(inst)); | 9313 | assert(sema.inst_map.remove(inst)); |
| 9454 | } | 9314 | } |
| 9455 | 9315 | ||
| 9456 | if (sema.preallocated_new_func != .none) { | 9316 | if (sema.generic_owner != .none) { |
| 9457 | if (try sema.typeHasOnePossibleValue(param_ty)) |opv| { | 9317 | if (try sema.typeHasOnePossibleValue(param_ty)) |opv| { |
| 9458 | // In this case we are instantiating a generic function call with a non-comptime | 9318 | // In this case we are instantiating a generic function call with a non-comptime |
| 9459 | // non-anytype parameter that ended up being a one-possible-type. | 9319 | // non-anytype parameter that ended up being a one-possible-type. |
| 9460 | // We don't want the parameter to be part of the instantiated function type. | 9320 | // We don't want the parameter to be part of the instantiated function type. |
| 9461 | const result = try sema.addConstant(opv); | 9321 | sema.inst_map.putAssumeCapacity(inst, Air.internedToRef(opv.toIntern())); |
| 9462 | sema.inst_map.putAssumeCapacity(inst, result); | 9322 | sema.comptime_args[param_index] = opv.toIntern(); |
| 9463 | return; | 9323 | return; |
| 9464 | } | 9324 | } |
| 9465 | } | 9325 | } |
| 9466 | 9326 | ||
| 9467 | try block.params.append(sema.gpa, .{ | 9327 | try block.params.append(sema.arena, .{ |
| 9468 | .ty = param_ty, | 9328 | .ty = param_ty.toIntern(), |
| 9469 | .is_comptime = comptime_syntax, | 9329 | .is_comptime = comptime_syntax, |
| 9470 | .name = param_name, | 9330 | .name = param_name, |
| 9471 | }); | 9331 | }); |
| ... | @@ -9473,17 +9333,15 @@ fn zirParam( | ... | @@ -9473,17 +9333,15 @@ fn zirParam( |
| 9473 | if (is_comptime) { | 9333 | if (is_comptime) { |
| 9474 | // If this is a comptime parameter we can add a constant generic_poison | 9334 | // If this is a comptime parameter we can add a constant generic_poison |
| 9475 | // since this is also a generic parameter. | 9335 | // since this is also a generic parameter. |
| 9476 | const result = try sema.addConstant(Value.generic_poison); | 9336 | sema.inst_map.putAssumeCapacityNoClobber(inst, .generic_poison); |
| 9477 | sema.inst_map.putAssumeCapacityNoClobber(inst, result); | ||
| 9478 | } else { | 9337 | } else { |
| 9479 | // Otherwise we need a dummy runtime instruction. | 9338 | // Otherwise we need a dummy runtime instruction. |
| 9480 | const result_index = @as(Air.Inst.Index, @intCast(sema.air_instructions.len)); | 9339 | const result_index: Air.Inst.Index = @intCast(sema.air_instructions.len); |
| 9481 | try sema.air_instructions.append(sema.gpa, .{ | 9340 | try sema.air_instructions.append(sema.gpa, .{ |
| 9482 | .tag = .alloc, | 9341 | .tag = .alloc, |
| 9483 | .data = .{ .ty = param_ty }, | 9342 | .data = .{ .ty = param_ty }, |
| 9484 | }); | 9343 | }); |
| 9485 | const result = Air.indexToRef(result_index); | 9344 | sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(result_index)); |
| 9486 | sema.inst_map.putAssumeCapacityNoClobber(inst, result); | ||
| 9487 | } | 9345 | } |
| 9488 | } | 9346 | } |
| 9489 | 9347 | ||
| ... | @@ -9491,24 +9349,76 @@ fn zirParamAnytype( | ... | @@ -9491,24 +9349,76 @@ fn zirParamAnytype( |
| 9491 | sema: *Sema, | 9349 | sema: *Sema, |
| 9492 | block: *Block, | 9350 | block: *Block, |
| 9493 | inst: Zir.Inst.Index, | 9351 | inst: Zir.Inst.Index, |
| 9352 | param_index: u32, | ||
| 9494 | comptime_syntax: bool, | 9353 | comptime_syntax: bool, |
| 9495 | ) CompileError!void { | 9354 | ) CompileError!void { |
| 9355 | const mod = sema.mod; | ||
| 9356 | const gpa = sema.gpa; | ||
| 9496 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; | 9357 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; |
| 9497 | const param_name = inst_data.get(sema.code); | 9358 | const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start); |
| 9359 | const src = inst_data.src(); | ||
| 9498 | 9360 | ||
| 9499 | if (sema.inst_map.get(inst)) |air_ref| { | 9361 | if (sema.inst_map.get(inst)) |air_ref| { |
| 9500 | const param_ty = sema.typeOf(air_ref); | 9362 | const param_ty = sema.typeOf(air_ref); |
| 9501 | if (comptime_syntax or try sema.typeRequiresComptime(param_ty)) { | 9363 | // If we have a comptime value for this parameter, it should be elided |
| 9502 | // We have a comptime value for this parameter so it should be elided from the | 9364 | // from the function type of the function instruction in this block. |
| 9503 | // function type of the function instruction in this block. | 9365 | if (try sema.typeHasOnePossibleValue(param_ty)) |opv| { |
| 9366 | sema.comptime_args[param_index] = opv.toIntern(); | ||
| 9504 | return; | 9367 | return; |
| 9505 | } | 9368 | } |
| 9506 | if (null != try sema.typeHasOnePossibleValue(param_ty)) { | 9369 | const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{ |
| 9507 | return; | 9370 | .decl = sema.generic_call_decl.unwrap().?, |
| 9371 | .call_node_offset = sema.generic_call_src.node_offset.x, | ||
| 9372 | .arg_index = param_index, | ||
| 9373 | } } else src; | ||
| 9374 | |||
| 9375 | if (comptime_syntax) { | ||
| 9376 | if (try sema.resolveMaybeUndefVal(air_ref)) |val| { | ||
| 9377 | sema.comptime_args[param_index] = val.toIntern(); | ||
| 9378 | return; | ||
| 9379 | } | ||
| 9380 | const msg = msg: { | ||
| 9381 | const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod); | ||
| 9382 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ | ||
| 9383 | @as([]const u8, "runtime-known argument passed to comptime parameter"), | ||
| 9384 | }); | ||
| 9385 | errdefer msg.destroy(gpa); | ||
| 9386 | |||
| 9387 | if (sema.generic_call_decl != .none) { | ||
| 9388 | try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")}); | ||
| 9389 | } | ||
| 9390 | break :msg msg; | ||
| 9391 | }; | ||
| 9392 | return sema.failWithOwnedErrorMsg(msg); | ||
| 9508 | } | 9393 | } |
| 9394 | |||
| 9395 | if (try sema.typeRequiresComptime(param_ty)) { | ||
| 9396 | if (try sema.resolveMaybeUndefVal(air_ref)) |val| { | ||
| 9397 | sema.comptime_args[param_index] = val.toIntern(); | ||
| 9398 | return; | ||
| 9399 | } | ||
| 9400 | const msg = msg: { | ||
| 9401 | const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod); | ||
| 9402 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ | ||
| 9403 | @as([]const u8, "runtime-known argument passed to comptime-only type parameter"), | ||
| 9404 | }); | ||
| 9405 | errdefer msg.destroy(gpa); | ||
| 9406 | |||
| 9407 | if (sema.generic_call_decl != .none) { | ||
| 9408 | try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared here")}); | ||
| 9409 | } | ||
| 9410 | |||
| 9411 | try sema.explainWhyTypeIsComptime(msg, src_loc, param_ty); | ||
| 9412 | |||
| 9413 | break :msg msg; | ||
| 9414 | }; | ||
| 9415 | return sema.failWithOwnedErrorMsg(msg); | ||
| 9416 | } | ||
| 9417 | |||
| 9418 | // The parameter is runtime-known. | ||
| 9509 | // The map is already populated but we do need to add a runtime parameter. | 9419 | // The map is already populated but we do need to add a runtime parameter. |
| 9510 | try block.params.append(sema.gpa, .{ | 9420 | try block.params.append(sema.arena, .{ |
| 9511 | .ty = param_ty, | 9421 | .ty = param_ty.toIntern(), |
| 9512 | .is_comptime = false, | 9422 | .is_comptime = false, |
| 9513 | .name = param_name, | 9423 | .name = param_name, |
| 9514 | }); | 9424 | }); |
| ... | @@ -9517,8 +9427,8 @@ fn zirParamAnytype( | ... | @@ -9517,8 +9427,8 @@ fn zirParamAnytype( |
| 9517 | 9427 | ||
| 9518 | // We are evaluating a generic function without any comptime args provided. | 9428 | // We are evaluating a generic function without any comptime args provided. |
| 9519 | 9429 | ||
| 9520 | try block.params.append(sema.gpa, .{ | 9430 | try block.params.append(sema.arena, .{ |
| 9521 | .ty = Type.generic_poison, | 9431 | .ty = .generic_poison_type, |
| 9522 | .is_comptime = comptime_syntax, | 9432 | .is_comptime = comptime_syntax, |
| 9523 | .name = param_name, | 9433 | .name = param_name, |
| 9524 | }); | 9434 | }); |
| ... | @@ -10673,7 +10583,7 @@ const SwitchProngAnalysis = struct { | ... | @@ -10673,7 +10583,7 @@ const SwitchProngAnalysis = struct { |
| 10673 | return sema.bitCast(block, item_ty, spa.operand, operand_src, null); | 10583 | return sema.bitCast(block, item_ty, spa.operand, operand_src, null); |
| 10674 | } | 10584 | } |
| 10675 | 10585 | ||
| 10676 | var names: Module.Fn.InferredErrorSet.NameMap = .{}; | 10586 | var names: InferredErrorSet.NameMap = .{}; |
| 10677 | try names.ensureUnusedCapacity(sema.arena, case_vals.len); | 10587 | try names.ensureUnusedCapacity(sema.arena, case_vals.len); |
| 10678 | for (case_vals) |err| { | 10588 | for (case_vals) |err| { |
| 10679 | const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable; | 10589 | const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable; |
| ... | @@ -11041,97 +10951,100 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11041,97 +10951,100 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11041 | } | 10951 | } |
| 11042 | } | 10952 | } |
| 11043 | 10953 | ||
| 11044 | try sema.resolveInferredErrorSetTy(block, src, operand_ty); | 10954 | switch (try sema.resolveInferredErrorSetTy(block, src, operand_ty.toIntern())) { |
| 11045 | 10955 | .anyerror_type => { | |
| 11046 | if (operand_ty.isAnyError(mod)) { | 10956 | if (special_prong != .@"else") { |
| 11047 | if (special_prong != .@"else") { | 10957 | return sema.fail( |
| 11048 | return sema.fail( | 10958 | block, |
| 11049 | block, | 10959 | src, |
| 11050 | src, | 10960 | "else prong required when switching on type 'anyerror'", |
| 11051 | "else prong required when switching on type 'anyerror'", | 10961 | .{}, |
| 11052 | .{}, | 10962 | ); |
| 11053 | ); | 10963 | } |
| 11054 | } | 10964 | else_error_ty = Type.anyerror; |
| 11055 | else_error_ty = Type.anyerror; | 10965 | }, |
| 11056 | } else else_validation: { | 10966 | else => |err_set_ty_index| else_validation: { |
| 11057 | var maybe_msg: ?*Module.ErrorMsg = null; | 10967 | const error_names = ip.indexToKey(err_set_ty_index).error_set_type.names; |
| 11058 | errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa); | 10968 | var maybe_msg: ?*Module.ErrorMsg = null; |
| 10969 | errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa); | ||
| 10970 | |||
| 10971 | for (error_names.get(ip)) |error_name| { | ||
| 10972 | if (!seen_errors.contains(error_name) and special_prong != .@"else") { | ||
| 10973 | const msg = maybe_msg orelse blk: { | ||
| 10974 | maybe_msg = try sema.errMsg( | ||
| 10975 | block, | ||
| 10976 | src, | ||
| 10977 | "switch must handle all possibilities", | ||
| 10978 | .{}, | ||
| 10979 | ); | ||
| 10980 | break :blk maybe_msg.?; | ||
| 10981 | }; | ||
| 11059 | 10982 | ||
| 11060 | for (operand_ty.errorSetNames(mod)) |error_name| { | 10983 | try sema.errNote( |
| 11061 | if (!seen_errors.contains(error_name) and special_prong != .@"else") { | ||
| 11062 | const msg = maybe_msg orelse blk: { | ||
| 11063 | maybe_msg = try sema.errMsg( | ||
| 11064 | block, | 10984 | block, |
| 11065 | src, | 10985 | src, |
| 11066 | "switch must handle all possibilities", | 10986 | msg, |
| 11067 | .{}, | 10987 | "unhandled error value: 'error.{}'", |
| 10988 | .{error_name.fmt(ip)}, | ||
| 11068 | ); | 10989 | ); |
| 11069 | break :blk maybe_msg.?; | 10990 | } |
| 11070 | }; | ||
| 11071 | |||
| 11072 | try sema.errNote( | ||
| 11073 | block, | ||
| 11074 | src, | ||
| 11075 | msg, | ||
| 11076 | "unhandled error value: 'error.{}'", | ||
| 11077 | .{error_name.fmt(ip)}, | ||
| 11078 | ); | ||
| 11079 | } | 10991 | } |
| 11080 | } | ||
| 11081 | 10992 | ||
| 11082 | if (maybe_msg) |msg| { | 10993 | if (maybe_msg) |msg| { |
| 11083 | maybe_msg = null; | 10994 | maybe_msg = null; |
| 11084 | try sema.addDeclaredHereNote(msg, operand_ty); | 10995 | try sema.addDeclaredHereNote(msg, operand_ty); |
| 11085 | return sema.failWithOwnedErrorMsg(msg); | 10996 | return sema.failWithOwnedErrorMsg(msg); |
| 11086 | } | 10997 | } |
| 11087 | 10998 | ||
| 11088 | if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames(mod).len) { | 10999 | if (special_prong == .@"else" and |
| 11089 | // In order to enable common patterns for generic code allow simple else bodies | 11000 | seen_errors.count() == error_names.len) |
| 11090 | // else => unreachable, | 11001 | { |
| 11091 | // else => return, | 11002 | // In order to enable common patterns for generic code allow simple else bodies |
| 11092 | // else => |e| return e, | 11003 | // else => unreachable, |
| 11093 | // even if all the possible errors were already handled. | 11004 | // else => return, |
| 11094 | const tags = sema.code.instructions.items(.tag); | 11005 | // else => |e| return e, |
| 11095 | for (special.body) |else_inst| switch (tags[else_inst]) { | 11006 | // even if all the possible errors were already handled. |
| 11096 | .dbg_block_begin, | 11007 | const tags = sema.code.instructions.items(.tag); |
| 11097 | .dbg_block_end, | 11008 | for (special.body) |else_inst| switch (tags[else_inst]) { |
| 11098 | .dbg_stmt, | 11009 | .dbg_block_begin, |
| 11099 | .dbg_var_val, | 11010 | .dbg_block_end, |
| 11100 | .ret_type, | 11011 | .dbg_stmt, |
| 11101 | .as_node, | 11012 | .dbg_var_val, |
| 11102 | .ret_node, | 11013 | .ret_type, |
| 11103 | .@"unreachable", | 11014 | .as_node, |
| 11104 | .@"defer", | 11015 | .ret_node, |
| 11105 | .defer_err_code, | 11016 | .@"unreachable", |
| 11106 | .err_union_code, | 11017 | .@"defer", |
| 11107 | .ret_err_value_code, | 11018 | .defer_err_code, |
| 11108 | .restore_err_ret_index, | 11019 | .err_union_code, |
| 11109 | .is_non_err, | 11020 | .ret_err_value_code, |
| 11110 | .ret_is_non_err, | 11021 | .restore_err_ret_index, |
| 11111 | .condbr, | 11022 | .is_non_err, |
| 11112 | => {}, | 11023 | .ret_is_non_err, |
| 11113 | else => break, | 11024 | .condbr, |
| 11114 | } else break :else_validation; | 11025 | => {}, |
| 11026 | else => break, | ||
| 11027 | } else break :else_validation; | ||
| 11115 | 11028 | ||
| 11116 | return sema.fail( | 11029 | return sema.fail( |
| 11117 | block, | 11030 | block, |
| 11118 | special_prong_src, | 11031 | special_prong_src, |
| 11119 | "unreachable else prong; all cases already handled", | 11032 | "unreachable else prong; all cases already handled", |
| 11120 | .{}, | 11033 | .{}, |
| 11121 | ); | 11034 | ); |
| 11122 | } | 11035 | } |
| 11123 | 11036 | ||
| 11124 | const error_names = operand_ty.errorSetNames(mod); | 11037 | var names: InferredErrorSet.NameMap = .{}; |
| 11125 | var names: Module.Fn.InferredErrorSet.NameMap = .{}; | 11038 | try names.ensureUnusedCapacity(sema.arena, error_names.len); |
| 11126 | try names.ensureUnusedCapacity(sema.arena, error_names.len); | 11039 | for (error_names.get(ip)) |error_name| { |
| 11127 | for (error_names) |error_name| { | 11040 | if (seen_errors.contains(error_name)) continue; |
| 11128 | if (seen_errors.contains(error_name)) continue; | ||
| 11129 | 11041 | ||
| 11130 | names.putAssumeCapacityNoClobber(error_name, {}); | 11042 | names.putAssumeCapacityNoClobber(error_name, {}); |
| 11131 | } | 11043 | } |
| 11132 | // No need to keep the hash map metadata correct; here we | 11044 | // No need to keep the hash map metadata correct; here we |
| 11133 | // extract the (sorted) keys only. | 11045 | // extract the (sorted) keys only. |
| 11134 | else_error_ty = try mod.errorSetFromUnsortedNames(names.keys()); | 11046 | else_error_ty = try mod.errorSetFromUnsortedNames(names.keys()); |
| 11047 | }, | ||
| 11135 | } | 11048 | } |
| 11136 | }, | 11049 | }, |
| 11137 | .Int, .ComptimeInt => { | 11050 | .Int, .ComptimeInt => { |
| ... | @@ -16295,6 +16208,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -16295,6 +16208,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 16295 | 16208 | ||
| 16296 | fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 16209 | fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 16297 | const mod = sema.mod; | 16210 | const mod = sema.mod; |
| 16211 | const ip = &mod.intern_pool; | ||
| 16298 | const inst_data = sema.code.instructions.items(.data)[inst].inst_node; | 16212 | const inst_data = sema.code.instructions.items(.data)[inst].inst_node; |
| 16299 | var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?; | 16213 | var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?; |
| 16300 | // Note: The target closure must be in this scope list. | 16214 | // Note: The target closure must be in this scope list. |
| ... | @@ -16305,8 +16219,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -16305,8 +16219,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 16305 | 16219 | ||
| 16306 | // Fail this decl if a scope it depended on failed. | 16220 | // Fail this decl if a scope it depended on failed. |
| 16307 | if (scope.failed()) { | 16221 | if (scope.failed()) { |
| 16308 | if (sema.owner_func) |owner_func| { | 16222 | if (sema.owner_func_index != .none) { |
| 16309 | owner_func.state = .dependency_failure; | 16223 | ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure; |
| 16310 | } else { | 16224 | } else { |
| 16311 | sema.owner_decl.analysis = .dependency_failure; | 16225 | sema.owner_decl.analysis = .dependency_failure; |
| 16312 | } | 16226 | } |
| ... | @@ -16423,8 +16337,8 @@ fn zirBuiltinSrc( | ... | @@ -16423,8 +16337,8 @@ fn zirBuiltinSrc( |
| 16423 | const mod = sema.mod; | 16337 | const mod = sema.mod; |
| 16424 | const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; | 16338 | const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; |
| 16425 | const src = LazySrcLoc.nodeOffset(extra.node); | 16339 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 16426 | const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{}); | 16340 | if (sema.func_index == .none) return sema.fail(block, src, "@src outside function", .{}); |
| 16427 | const fn_owner_decl = mod.declPtr(func.owner_decl); | 16341 | const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index); |
| 16428 | 16342 | ||
| 16429 | const func_name_val = blk: { | 16343 | const func_name_val = blk: { |
| 16430 | var anon_decl = try block.startAnonDecl(); | 16344 | var anon_decl = try block.startAnonDecl(); |
| ... | @@ -16548,10 +16462,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16548,10 +16462,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16548 | const param_info_decl = mod.declPtr(param_info_decl_index); | 16462 | const param_info_decl = mod.declPtr(param_info_decl_index); |
| 16549 | const param_info_ty = param_info_decl.val.toType(); | 16463 | const param_info_ty = param_info_decl.val.toType(); |
| 16550 | 16464 | ||
| 16551 | const param_vals = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(ty).?.param_types.len); | 16465 | const func_ty_info = mod.typeToFunc(ty).?; |
| 16466 | const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); | ||
| 16552 | for (param_vals, 0..) |*param_val, i| { | 16467 | for (param_vals, 0..) |*param_val, i| { |
| 16553 | const info = mod.typeToFunc(ty).?; | 16468 | const param_ty = func_ty_info.param_types.get(ip)[i]; |
| 16554 | const param_ty = info.param_types[i]; | ||
| 16555 | const is_generic = param_ty == .generic_poison_type; | 16469 | const is_generic = param_ty == .generic_poison_type; |
| 16556 | const param_ty_val = try ip.get(gpa, .{ .opt = .{ | 16470 | const param_ty_val = try ip.get(gpa, .{ .opt = .{ |
| 16557 | .ty = try ip.get(gpa, .{ .opt_type = .type_type }), | 16471 | .ty = try ip.get(gpa, .{ .opt_type = .type_type }), |
| ... | @@ -16560,7 +16474,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16560,7 +16474,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16560 | 16474 | ||
| 16561 | const is_noalias = blk: { | 16475 | const is_noalias = blk: { |
| 16562 | const index = std.math.cast(u5, i) orelse break :blk false; | 16476 | const index = std.math.cast(u5, i) orelse break :blk false; |
| 16563 | break :blk @as(u1, @truncate(info.noalias_bits >> index)) != 0; | 16477 | break :blk @as(u1, @truncate(func_ty_info.noalias_bits >> index)) != 0; |
| 16564 | }; | 16478 | }; |
| 16565 | 16479 | ||
| 16566 | const param_fields = .{ | 16480 | const param_fields = .{ |
| ... | @@ -16603,23 +16517,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16603,23 +16517,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16603 | } }); | 16517 | } }); |
| 16604 | }; | 16518 | }; |
| 16605 | 16519 | ||
| 16606 | const info = mod.typeToFunc(ty).?; | ||
| 16607 | const ret_ty_opt = try mod.intern(.{ .opt = .{ | 16520 | const ret_ty_opt = try mod.intern(.{ .opt = .{ |
| 16608 | .ty = try ip.get(gpa, .{ .opt_type = .type_type }), | 16521 | .ty = try ip.get(gpa, .{ .opt_type = .type_type }), |
| 16609 | .val = if (info.return_type == .generic_poison_type) .none else info.return_type, | 16522 | .val = if (func_ty_info.return_type == .generic_poison_type) |
| 16523 | .none | ||
| 16524 | else | ||
| 16525 | func_ty_info.return_type, | ||
| 16610 | } }); | 16526 | } }); |
| 16611 | 16527 | ||
| 16612 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); | 16528 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); |
| 16613 | 16529 | ||
| 16614 | const field_values = .{ | 16530 | const field_values = .{ |
| 16615 | // calling_convention: CallingConvention, | 16531 | // calling_convention: CallingConvention, |
| 16616 | (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(info.cc))).toIntern(), | 16532 | (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(), |
| 16617 | // alignment: comptime_int, | 16533 | // alignment: comptime_int, |
| 16618 | (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(), | 16534 | (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(), |
| 16619 | // is_generic: bool, | 16535 | // is_generic: bool, |
| 16620 | Value.makeBool(info.is_generic).toIntern(), | 16536 | Value.makeBool(func_ty_info.is_generic).toIntern(), |
| 16621 | // is_var_args: bool, | 16537 | // is_var_args: bool, |
| 16622 | Value.makeBool(info.is_var_args).toIntern(), | 16538 | Value.makeBool(func_ty_info.is_var_args).toIntern(), |
| 16623 | // return_type: ?type, | 16539 | // return_type: ?type, |
| 16624 | ret_ty_opt, | 16540 | ret_ty_opt, |
| 16625 | // args: []const Fn.Param, | 16541 | // args: []const Fn.Param, |
| ... | @@ -16860,50 +16776,51 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16860,50 +16776,51 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16860 | 16776 | ||
| 16861 | try sema.queueFullTypeResolution(error_field_ty); | 16777 | try sema.queueFullTypeResolution(error_field_ty); |
| 16862 | 16778 | ||
| 16863 | // If the error set is inferred it must be resolved at this point | ||
| 16864 | try sema.resolveInferredErrorSetTy(block, src, ty); | ||
| 16865 | |||
| 16866 | // Build our list of Error values | 16779 | // Build our list of Error values |
| 16867 | // Optional value is only null if anyerror | 16780 | // Optional value is only null if anyerror |
| 16868 | // Value can be zero-length slice otherwise | 16781 | // Value can be zero-length slice otherwise |
| 16869 | const error_field_vals = if (ty.isAnyError(mod)) null else blk: { | 16782 | const error_field_vals = switch (try sema.resolveInferredErrorSetTy(block, src, ty.toIntern())) { |
| 16870 | const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len); | 16783 | .anyerror_type => null, |
| 16871 | for (vals, 0..) |*field_val, i| { | 16784 | else => |err_set_ty_index| blk: { |
| 16872 | // TODO: write something like getCoercedInts to avoid needing to dupe | 16785 | const names = ip.indexToKey(err_set_ty_index).error_set_type.names; |
| 16873 | const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i])); | 16786 | const vals = try sema.arena.alloc(InternPool.Index, names.len); |
| 16874 | const name_val = v: { | 16787 | for (vals, 0..) |*field_val, i| { |
| 16875 | var anon_decl = try block.startAnonDecl(); | 16788 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 16876 | defer anon_decl.deinit(); | 16789 | const name = try sema.arena.dupe(u8, ip.stringToSlice(names.get(ip)[i])); |
| 16877 | const new_decl_ty = try mod.arrayType(.{ | 16790 | const name_val = v: { |
| 16878 | .len = name.len, | 16791 | var anon_decl = try block.startAnonDecl(); |
| 16879 | .child = .u8_type, | 16792 | defer anon_decl.deinit(); |
| 16880 | }); | 16793 | const new_decl_ty = try mod.arrayType(.{ |
| 16881 | const new_decl = try anon_decl.finish( | 16794 | .len = name.len, |
| 16882 | new_decl_ty, | 16795 | .child = .u8_type, |
| 16883 | (try mod.intern(.{ .aggregate = .{ | 16796 | }); |
| 16884 | .ty = new_decl_ty.toIntern(), | 16797 | const new_decl = try anon_decl.finish( |
| 16885 | .storage = .{ .bytes = name }, | 16798 | new_decl_ty, |
| 16886 | } })).toValue(), | 16799 | (try mod.intern(.{ .aggregate = .{ |
| 16887 | .none, // default alignment | 16800 | .ty = new_decl_ty.toIntern(), |
| 16888 | ); | 16801 | .storage = .{ .bytes = name }, |
| 16889 | break :v try mod.intern(.{ .ptr = .{ | 16802 | } })).toValue(), |
| 16890 | .ty = .slice_const_u8_type, | 16803 | .none, // default alignment |
| 16891 | .addr = .{ .decl = new_decl }, | 16804 | ); |
| 16892 | .len = (try mod.intValue(Type.usize, name.len)).toIntern(), | 16805 | break :v try mod.intern(.{ .ptr = .{ |
| 16893 | } }); | 16806 | .ty = .slice_const_u8_type, |
| 16894 | }; | 16807 | .addr = .{ .decl = new_decl }, |
| 16808 | .len = (try mod.intValue(Type.usize, name.len)).toIntern(), | ||
| 16809 | } }); | ||
| 16810 | }; | ||
| 16895 | 16811 | ||
| 16896 | const error_field_fields = .{ | 16812 | const error_field_fields = .{ |
| 16897 | // name: []const u8, | 16813 | // name: []const u8, |
| 16898 | name_val, | 16814 | name_val, |
| 16899 | }; | 16815 | }; |
| 16900 | field_val.* = try mod.intern(.{ .aggregate = .{ | 16816 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 16901 | .ty = error_field_ty.toIntern(), | 16817 | .ty = error_field_ty.toIntern(), |
| 16902 | .storage = .{ .elems = &error_field_fields }, | 16818 | .storage = .{ .elems = &error_field_fields }, |
| 16903 | } }); | 16819 | } }); |
| 16904 | } | 16820 | } |
| 16905 | 16821 | ||
| 16906 | break :blk vals; | 16822 | break :blk vals; |
| 16823 | }, | ||
| 16907 | }; | 16824 | }; |
| 16908 | 16825 | ||
| 16909 | // Build our ?[]const Error value | 16826 | // Build our ?[]const Error value |
| ... | @@ -18425,9 +18342,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) | ... | @@ -18425,9 +18342,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) |
| 18425 | // This is only relevant at runtime. | 18342 | // This is only relevant at runtime. |
| 18426 | if (start_block.is_comptime or start_block.is_typeof) return; | 18343 | if (start_block.is_comptime or start_block.is_typeof) return; |
| 18427 | 18344 | ||
| 18428 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return; | 18345 | const mod = sema.mod; |
| 18429 | if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return; | 18346 | const ip = &mod.intern_pool; |
| 18430 | if (!sema.mod.comp.bin_file.options.error_return_tracing) return; | 18347 | |
| 18348 | if (!mod.backendSupportsFeature(.error_return_trace)) return; | ||
| 18349 | if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return; | ||
| 18350 | if (!mod.comp.bin_file.options.error_return_tracing) return; | ||
| 18431 | 18351 | ||
| 18432 | const tracy = trace(@src()); | 18352 | const tracy = trace(@src()); |
| 18433 | defer tracy.end(); | 18353 | defer tracy.end(); |
| ... | @@ -18464,17 +18384,30 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) | ... | @@ -18464,17 +18384,30 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) |
| 18464 | 18384 | ||
| 18465 | fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { | 18385 | fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { |
| 18466 | const mod = sema.mod; | 18386 | const mod = sema.mod; |
| 18467 | const gpa = sema.gpa; | ||
| 18468 | const ip = &mod.intern_pool; | 18387 | const ip = &mod.intern_pool; |
| 18469 | assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion); | 18388 | assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion); |
| 18389 | const err_set_ty = sema.fn_ret_ty.errorUnionSet(mod).toIntern(); | ||
| 18390 | switch (err_set_ty) { | ||
| 18391 | .adhoc_inferred_error_set_type => { | ||
| 18392 | const ies = sema.fn_ret_ty_ies.?; | ||
| 18393 | assert(ies.func == .none); | ||
| 18394 | try addToInferredErrorSetPtr(mod, ies, sema.typeOf(uncasted_operand)); | ||
| 18395 | }, | ||
| 18396 | else => if (ip.isInferredErrorSetType(err_set_ty)) { | ||
| 18397 | const ies = sema.fn_ret_ty_ies.?; | ||
| 18398 | assert(ies.func == sema.func_index); | ||
| 18399 | try addToInferredErrorSetPtr(mod, ies, sema.typeOf(uncasted_operand)); | ||
| 18400 | }, | ||
| 18401 | } | ||
| 18402 | } | ||
| 18470 | 18403 | ||
| 18471 | if (mod.typeToInferredErrorSet(sema.fn_ret_ty.errorUnionSet(mod))) |ies| { | 18404 | fn addToInferredErrorSetPtr(mod: *Module, ies: *InferredErrorSet, op_ty: Type) !void { |
| 18472 | const op_ty = sema.typeOf(uncasted_operand); | 18405 | const gpa = mod.gpa; |
| 18473 | switch (op_ty.zigTypeTag(mod)) { | 18406 | const ip = &mod.intern_pool; |
| 18474 | .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa), | 18407 | switch (op_ty.zigTypeTag(mod)) { |
| 18475 | .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa), | 18408 | .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa), |
| 18476 | else => {}, | 18409 | .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa), |
| 18477 | } | 18410 | else => {}, |
| 18478 | } | 18411 | } |
| 18479 | } | 18412 | } |
| 18480 | 18413 | ||
| ... | @@ -18488,7 +18421,7 @@ fn analyzeRet( | ... | @@ -18488,7 +18421,7 @@ fn analyzeRet( |
| 18488 | // add the error tag to the inferred error set of the in-scope function, so | 18421 | // add the error tag to the inferred error set of the in-scope function, so |
| 18489 | // that the coercion below works correctly. | 18422 | // that the coercion below works correctly. |
| 18490 | const mod = sema.mod; | 18423 | const mod = sema.mod; |
| 18491 | if (sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) { | 18424 | if (sema.fn_ret_ty_ies != null and sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) { |
| 18492 | try sema.addToInferredErrorSet(uncasted_operand); | 18425 | try sema.addToInferredErrorSet(uncasted_operand); |
| 18493 | } | 18426 | } |
| 18494 | const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) { | 18427 | const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) { |
| ... | @@ -19461,13 +19394,14 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { | ... | @@ -19461,13 +19394,14 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 19461 | 19394 | ||
| 19462 | fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { | 19395 | fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 19463 | const mod = sema.mod; | 19396 | const mod = sema.mod; |
| 19397 | const ip = &mod.intern_pool; | ||
| 19464 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); | 19398 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); |
| 19465 | const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); | 19399 | const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); |
| 19466 | const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty); | 19400 | const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty); |
| 19467 | const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern()); | 19401 | const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern()); |
| 19468 | 19402 | ||
| 19469 | if (sema.owner_func != null and | 19403 | if (sema.owner_func_index != .none and |
| 19470 | sema.owner_func.?.calls_or_awaits_errorable_fn and | 19404 | ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and |
| 19471 | mod.comp.bin_file.options.error_return_tracing and | 19405 | mod.comp.bin_file.options.error_return_tracing and |
| 19472 | mod.backendSupportsFeature(.error_return_trace)) | 19406 | mod.backendSupportsFeature(.error_return_trace)) |
| 19473 | { | 19407 | { |
| ... | @@ -19920,7 +19854,7 @@ fn zirReify( | ... | @@ -19920,7 +19854,7 @@ fn zirReify( |
| 19920 | return sema.addType(Type.anyerror); | 19854 | return sema.addType(Type.anyerror); |
| 19921 | 19855 | ||
| 19922 | const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod)); | 19856 | const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod)); |
| 19923 | var names: Module.Fn.InferredErrorSet.NameMap = .{}; | 19857 | var names: InferredErrorSet.NameMap = .{}; |
| 19924 | try names.ensureUnusedCapacity(sema.arena, len); | 19858 | try names.ensureUnusedCapacity(sema.arena, len); |
| 19925 | for (0..len) |i| { | 19859 | for (0..len) |i| { |
| 19926 | const elem_val = try payload_val.elemValue(mod, i); | 19860 | const elem_val = try payload_val.elemValue(mod, i); |
| ... | @@ -20431,8 +20365,6 @@ fn zirReify( | ... | @@ -20431,8 +20365,6 @@ fn zirReify( |
| 20431 | .is_var_args = is_var_args, | 20365 | .is_var_args = is_var_args, |
| 20432 | .is_generic = false, | 20366 | .is_generic = false, |
| 20433 | .is_noinline = false, | 20367 | .is_noinline = false, |
| 20434 | .align_is_generic = false, | ||
| 20435 | .cc_is_generic = false, | ||
| 20436 | .section_is_generic = false, | 20368 | .section_is_generic = false, |
| 20437 | .addrspace_is_generic = false, | 20369 | .addrspace_is_generic = false, |
| 20438 | }); | 20370 | }); |
| ... | @@ -20936,8 +20868,8 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -20936,8 +20868,8 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 20936 | break :disjoint true; | 20868 | break :disjoint true; |
| 20937 | } | 20869 | } |
| 20938 | 20870 | ||
| 20939 | try sema.resolveInferredErrorSetTy(block, src, dest_ty); | 20871 | _ = try sema.resolveInferredErrorSetTy(block, src, dest_ty.toIntern()); |
| 20940 | try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty); | 20872 | _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty.toIntern()); |
| 20941 | for (dest_ty.errorSetNames(mod)) |dest_err_name| { | 20873 | for (dest_ty.errorSetNames(mod)) |dest_err_name| { |
| 20942 | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) | 20874 | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) |
| 20943 | break :disjoint false; | 20875 | break :disjoint false; |
| ... | @@ -23917,7 +23849,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -23917,7 +23849,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 23917 | break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val); | 23849 | break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val); |
| 23918 | } else target_util.defaultAddressSpace(target, .function); | 23850 | } else target_util.defaultAddressSpace(target, .function); |
| 23919 | 23851 | ||
| 23920 | const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: { | 23852 | const section: Section = if (extra.data.bits.has_section_body) blk: { |
| 23921 | const body_len = sema.code.extra[extra_index]; | 23853 | const body_len = sema.code.extra[extra_index]; |
| 23922 | extra_index += 1; | 23854 | extra_index += 1; |
| 23923 | const body = sema.code.extra[extra_index..][0..body_len]; | 23855 | const body = sema.code.extra[extra_index..][0..body_len]; |
| ... | @@ -23926,20 +23858,20 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -23926,20 +23858,20 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 23926 | const ty = Type.slice_const_u8; | 23858 | const ty = Type.slice_const_u8; |
| 23927 | const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known"); | 23859 | const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known"); |
| 23928 | if (val.isGenericPoison()) { | 23860 | if (val.isGenericPoison()) { |
| 23929 | break :blk FuncLinkSection{ .generic = {} }; | 23861 | break :blk .generic; |
| 23930 | } | 23862 | } |
| 23931 | break :blk FuncLinkSection{ .explicit = try val.toIpString(ty, mod) }; | 23863 | break :blk .{ .explicit = try val.toIpString(ty, mod) }; |
| 23932 | } else if (extra.data.bits.has_section_ref) blk: { | 23864 | } else if (extra.data.bits.has_section_ref) blk: { |
| 23933 | const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index])); | 23865 | const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index])); |
| 23934 | extra_index += 1; | 23866 | extra_index += 1; |
| 23935 | const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) { | 23867 | const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) { |
| 23936 | error.GenericPoison => { | 23868 | error.GenericPoison => { |
| 23937 | break :blk FuncLinkSection{ .generic = {} }; | 23869 | break :blk .generic; |
| 23938 | }, | 23870 | }, |
| 23939 | else => |e| return e, | 23871 | else => |e| return e, |
| 23940 | }; | 23872 | }; |
| 23941 | break :blk FuncLinkSection{ .explicit = section_name }; | 23873 | break :blk .{ .explicit = section_name }; |
| 23942 | } else FuncLinkSection{ .default = {} }; | 23874 | } else .default; |
| 23943 | 23875 | ||
| 23944 | const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { | 23876 | const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { |
| 23945 | const body_len = sema.code.extra[extra_index]; | 23877 | const body_len = sema.code.extra[extra_index]; |
| ... | @@ -24013,7 +23945,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -24013,7 +23945,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 24013 | inst, | 23945 | inst, |
| 24014 | @"align", | 23946 | @"align", |
| 24015 | @"addrspace", | 23947 | @"addrspace", |
| 24016 | @"linksection", | 23948 | section, |
| 24017 | cc, | 23949 | cc, |
| 24018 | ret_ty, | 23950 | ret_ty, |
| 24019 | is_var_args, | 23951 | is_var_args, |
| ... | @@ -24846,9 +24778,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void { | ... | @@ -24846,9 +24778,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void { |
| 24846 | const tv = try mod.declPtr(decl_index).typedValue(); | 24778 | const tv = try mod.declPtr(decl_index).typedValue(); |
| 24847 | assert(tv.ty.zigTypeTag(mod) == .Fn); | 24779 | assert(tv.ty.zigTypeTag(mod) == .Fn); |
| 24848 | assert(try sema.fnHasRuntimeBits(tv.ty)); | 24780 | assert(try sema.fnHasRuntimeBits(tv.ty)); |
| 24849 | const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap().?; | 24781 | const func_index = tv.val.toIntern(); |
| 24850 | try mod.ensureFuncBodyAnalysisQueued(func_index); | 24782 | try mod.ensureFuncBodyAnalysisQueued(func_index); |
| 24851 | mod.panic_func_index = func_index.toOptional(); | 24783 | mod.panic_func_index = func_index; |
| 24852 | } | 24784 | } |
| 24853 | 24785 | ||
| 24854 | if (mod.null_stack_trace == .none) { | 24786 | if (mod.null_stack_trace == .none) { |
| ... | @@ -24982,7 +24914,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void { | ... | @@ -24982,7 +24914,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void { |
| 24982 | 24914 | ||
| 24983 | try sema.prepareSimplePanic(block); | 24915 | try sema.prepareSimplePanic(block); |
| 24984 | 24916 | ||
| 24985 | const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?; | 24917 | const panic_func = mod.funcInfo(mod.panic_func_index); |
| 24986 | const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl); | 24918 | const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl); |
| 24987 | const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue()); | 24919 | const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue()); |
| 24988 | 24920 | ||
| ... | @@ -25688,7 +25620,7 @@ fn fieldCallBind( | ... | @@ -25688,7 +25620,7 @@ fn fieldCallBind( |
| 25688 | if (mod.typeToFunc(decl_type)) |func_type| f: { | 25620 | if (mod.typeToFunc(decl_type)) |func_type| f: { |
| 25689 | if (func_type.param_types.len == 0) break :f; | 25621 | if (func_type.param_types.len == 0) break :f; |
| 25690 | 25622 | ||
| 25691 | const first_param_type = func_type.param_types[0].toType(); | 25623 | const first_param_type = func_type.param_types.get(ip)[0].toType(); |
| 25692 | // zig fmt: off | 25624 | // zig fmt: off |
| 25693 | if (first_param_type.isGenericPoison() or ( | 25625 | if (first_param_type.isGenericPoison() or ( |
| 25694 | first_param_type.zigTypeTag(mod) == .Pointer and | 25626 | first_param_type.zigTypeTag(mod) == .Pointer and |
| ... | @@ -27526,7 +27458,7 @@ fn coerceExtra( | ... | @@ -27526,7 +27458,7 @@ fn coerceExtra( |
| 27526 | errdefer msg.destroy(sema.gpa); | 27458 | errdefer msg.destroy(sema.gpa); |
| 27527 | 27459 | ||
| 27528 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | 27460 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 27529 | const src_decl = mod.declPtr(sema.func.?.owner_decl); | 27461 | const src_decl = mod.funcOwnerDeclPtr(sema.func_index); |
| 27530 | try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{}); | 27462 | try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{}); |
| 27531 | break :msg msg; | 27463 | break :msg msg; |
| 27532 | }; | 27464 | }; |
| ... | @@ -27556,9 +27488,11 @@ fn coerceExtra( | ... | @@ -27556,9 +27488,11 @@ fn coerceExtra( |
| 27556 | try in_memory_result.report(sema, block, inst_src, msg); | 27488 | try in_memory_result.report(sema, block, inst_src, msg); |
| 27557 | 27489 | ||
| 27558 | // Add notes about function return type | 27490 | // Add notes about function return type |
| 27559 | if (opts.is_ret and mod.test_functions.get(sema.func.?.owner_decl) == null) { | 27491 | if (opts.is_ret and |
| 27492 | mod.test_functions.get(mod.funcOwnerDeclIndex(sema.func_index)) == null) | ||
| 27493 | { | ||
| 27560 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | 27494 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 27561 | const src_decl = mod.declPtr(sema.func.?.owner_decl); | 27495 | const src_decl = mod.funcOwnerDeclPtr(sema.func_index); |
| 27562 | if (inst_ty.isError(mod) and !dest_ty.isError(mod)) { | 27496 | if (inst_ty.isError(mod) and !dest_ty.isError(mod)) { |
| 27563 | try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{}); | 27497 | try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{}); |
| 27564 | } else { | 27498 | } else { |
| ... | @@ -28160,42 +28094,29 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -28160,42 +28094,29 @@ fn coerceInMemoryAllowedErrorSets( |
| 28160 | return .ok; | 28094 | return .ok; |
| 28161 | } | 28095 | } |
| 28162 | 28096 | ||
| 28163 | if (mod.typeToInferredErrorSetIndex(dest_ty).unwrap()) |dst_ies_index| { | 28097 | if (dest_ty.toIntern() == .adhoc_inferred_error_set_type) { |
| 28164 | const dst_ies = mod.inferredErrorSetPtr(dst_ies_index); | 28098 | // We are trying to coerce an error set to the current function's |
| 28165 | // We will make an effort to return `ok` without resolving either error set, to | 28099 | // inferred error set. |
| 28166 | // avoid unnecessary "unable to resolve error set" dependency loop errors. | 28100 | const dst_ies = sema.fn_ret_ty_ies.?; |
| 28167 | switch (src_ty.toIntern()) { | 28101 | try dst_ies.addErrorSet(src_ty, ip, gpa); |
| 28168 | .anyerror_type => {}, | 28102 | return .ok; |
| 28169 | else => switch (ip.indexToKey(src_ty.toIntern())) { | 28103 | } |
| 28170 | .inferred_error_set_type => |src_index| { | ||
| 28171 | // If both are inferred error sets of functions, and | ||
| 28172 | // the dest includes the source function, the coercion is OK. | ||
| 28173 | // This check is important because it works without forcing a full resolution | ||
| 28174 | // of inferred error sets. | ||
| 28175 | if (dst_ies.inferred_error_sets.contains(src_index)) { | ||
| 28176 | return .ok; | ||
| 28177 | } | ||
| 28178 | }, | ||
| 28179 | .error_set_type => |error_set_type| { | ||
| 28180 | for (error_set_type.names) |name| { | ||
| 28181 | if (!dst_ies.errors.contains(name)) break; | ||
| 28182 | } else return .ok; | ||
| 28183 | }, | ||
| 28184 | else => unreachable, | ||
| 28185 | }, | ||
| 28186 | } | ||
| 28187 | 28104 | ||
| 28188 | if (dst_ies.func == sema.owner_func_index.unwrap()) { | 28105 | if (ip.isInferredErrorSetType(dest_ty.toIntern())) { |
| 28189 | // We are trying to coerce an error set to the current function's | 28106 | const dst_ies_func_index = ip.iesFuncIndex(dest_ty.toIntern()); |
| 28190 | // inferred error set. | 28107 | if (sema.fn_ret_ty_ies) |dst_ies| { |
| 28191 | try dst_ies.addErrorSet(src_ty, ip, gpa); | 28108 | if (dst_ies.func == dst_ies_func_index) { |
| 28192 | return .ok; | 28109 | // We are trying to coerce an error set to the current function's |
| 28110 | // inferred error set. | ||
| 28111 | try dst_ies.addErrorSet(src_ty, ip, gpa); | ||
| 28112 | return .ok; | ||
| 28113 | } | ||
| 28193 | } | 28114 | } |
| 28194 | 28115 | switch (try sema.resolveInferredErrorSet(block, dest_src, dest_ty.toIntern())) { | |
| 28195 | try sema.resolveInferredErrorSet(block, dest_src, dst_ies_index); | 28116 | // isAnyError might have changed from a false negative to a true |
| 28196 | // isAnyError might have changed from a false negative to a true positive after resolution. | 28117 | // positive after resolution. |
| 28197 | if (dest_ty.isAnyError(mod)) { | 28118 | .anyerror_type => return .ok, |
| 28198 | return .ok; | 28119 | else => {}, |
| 28199 | } | 28120 | } |
| 28200 | } | 28121 | } |
| 28201 | 28122 | ||
| ... | @@ -28210,17 +28131,15 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -28210,17 +28131,15 @@ fn coerceInMemoryAllowedErrorSets( |
| 28210 | }, | 28131 | }, |
| 28211 | 28132 | ||
| 28212 | else => switch (ip.indexToKey(src_ty.toIntern())) { | 28133 | else => switch (ip.indexToKey(src_ty.toIntern())) { |
| 28213 | .inferred_error_set_type => |src_index| { | 28134 | .inferred_error_set_type => { |
| 28214 | const src_data = mod.inferredErrorSetPtr(src_index); | 28135 | const resolved_src_ty = try sema.resolveInferredErrorSet(block, src_src, src_ty.toIntern()); |
| 28215 | |||
| 28216 | try sema.resolveInferredErrorSet(block, src_src, src_index); | ||
| 28217 | // src anyerror status might have changed after the resolution. | 28136 | // src anyerror status might have changed after the resolution. |
| 28218 | if (src_ty.isAnyError(mod)) { | 28137 | if (resolved_src_ty == .anyerror_type) { |
| 28219 | // dest_ty.isAnyError(mod) == true is already checked for at this point. | 28138 | // dest_ty.isAnyError(mod) == true is already checked for at this point. |
| 28220 | return .from_anyerror; | 28139 | return .from_anyerror; |
| 28221 | } | 28140 | } |
| 28222 | 28141 | ||
| 28223 | for (src_data.errors.keys()) |key| { | 28142 | for (ip.indexToKey(resolved_src_ty).error_set_type.names.get(ip)) |key| { |
| 28224 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) { | 28143 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) { |
| 28225 | try missing_error_buf.append(key); | 28144 | try missing_error_buf.append(key); |
| 28226 | } | 28145 | } |
| ... | @@ -28235,7 +28154,7 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -28235,7 +28154,7 @@ fn coerceInMemoryAllowedErrorSets( |
| 28235 | return .ok; | 28154 | return .ok; |
| 28236 | }, | 28155 | }, |
| 28237 | .error_set_type => |error_set_type| { | 28156 | .error_set_type => |error_set_type| { |
| 28238 | for (error_set_type.names) |name| { | 28157 | for (error_set_type.names.get(ip)) |name| { |
| 28239 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) { | 28158 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) { |
| 28240 | try missing_error_buf.append(name); | 28159 | try missing_error_buf.append(name); |
| 28241 | } | 28160 | } |
| ... | @@ -28264,11 +28183,12 @@ fn coerceInMemoryAllowedFns( | ... | @@ -28264,11 +28183,12 @@ fn coerceInMemoryAllowedFns( |
| 28264 | src_src: LazySrcLoc, | 28183 | src_src: LazySrcLoc, |
| 28265 | ) !InMemoryCoercionResult { | 28184 | ) !InMemoryCoercionResult { |
| 28266 | const mod = sema.mod; | 28185 | const mod = sema.mod; |
| 28186 | const ip = &mod.intern_pool; | ||
| 28267 | 28187 | ||
| 28268 | { | 28188 | const dest_info = mod.typeToFunc(dest_ty).?; |
| 28269 | const dest_info = mod.typeToFunc(dest_ty).?; | 28189 | const src_info = mod.typeToFunc(src_ty).?; |
| 28270 | const src_info = mod.typeToFunc(src_ty).?; | ||
| 28271 | 28190 | ||
| 28191 | { | ||
| 28272 | if (dest_info.is_var_args != src_info.is_var_args) { | 28192 | if (dest_info.is_var_args != src_info.is_var_args) { |
| 28273 | return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args }; | 28193 | return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args }; |
| 28274 | } | 28194 | } |
| ... | @@ -28302,9 +28222,6 @@ fn coerceInMemoryAllowedFns( | ... | @@ -28302,9 +28222,6 @@ fn coerceInMemoryAllowedFns( |
| 28302 | } | 28222 | } |
| 28303 | 28223 | ||
| 28304 | const params_len = params_len: { | 28224 | const params_len = params_len: { |
| 28305 | const dest_info = mod.typeToFunc(dest_ty).?; | ||
| 28306 | const src_info = mod.typeToFunc(src_ty).?; | ||
| 28307 | |||
| 28308 | if (dest_info.param_types.len != src_info.param_types.len) { | 28225 | if (dest_info.param_types.len != src_info.param_types.len) { |
| 28309 | return InMemoryCoercionResult{ .fn_param_count = .{ | 28226 | return InMemoryCoercionResult{ .fn_param_count = .{ |
| 28310 | .actual = src_info.param_types.len, | 28227 | .actual = src_info.param_types.len, |
| ... | @@ -28323,13 +28240,10 @@ fn coerceInMemoryAllowedFns( | ... | @@ -28323,13 +28240,10 @@ fn coerceInMemoryAllowedFns( |
| 28323 | }; | 28240 | }; |
| 28324 | 28241 | ||
| 28325 | for (0..params_len) |param_i| { | 28242 | for (0..params_len) |param_i| { |
| 28326 | const dest_info = mod.typeToFunc(dest_ty).?; | 28243 | const dest_param_ty = dest_info.param_types.get(ip)[param_i].toType(); |
| 28327 | const src_info = mod.typeToFunc(src_ty).?; | 28244 | const src_param_ty = src_info.param_types.get(ip)[param_i].toType(); |
| 28328 | |||
| 28329 | const dest_param_ty = dest_info.param_types[param_i].toType(); | ||
| 28330 | const src_param_ty = src_info.param_types[param_i].toType(); | ||
| 28331 | 28245 | ||
| 28332 | const param_i_small = @as(u5, @intCast(param_i)); | 28246 | const param_i_small: u5 = @intCast(param_i); |
| 28333 | if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) { | 28247 | if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) { |
| 28334 | return InMemoryCoercionResult{ .fn_param_comptime = .{ | 28248 | return InMemoryCoercionResult{ .fn_param_comptime = .{ |
| 28335 | .index = param_i, | 28249 | .index = param_i, |
| ... | @@ -30471,6 +30385,7 @@ fn addReferencedBy( | ... | @@ -30471,6 +30385,7 @@ fn addReferencedBy( |
| 30471 | 30385 | ||
| 30472 | fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { | 30386 | fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { |
| 30473 | const mod = sema.mod; | 30387 | const mod = sema.mod; |
| 30388 | const ip = &mod.intern_pool; | ||
| 30474 | const decl = mod.declPtr(decl_index); | 30389 | const decl = mod.declPtr(decl_index); |
| 30475 | if (decl.analysis == .in_progress) { | 30390 | if (decl.analysis == .in_progress) { |
| 30476 | const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{}); | 30391 | const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{}); |
| ... | @@ -30478,8 +30393,8 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { | ... | @@ -30478,8 +30393,8 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { |
| 30478 | } | 30393 | } |
| 30479 | 30394 | ||
| 30480 | mod.ensureDeclAnalyzed(decl_index) catch |err| { | 30395 | mod.ensureDeclAnalyzed(decl_index) catch |err| { |
| 30481 | if (sema.owner_func) |owner_func| { | 30396 | if (sema.owner_func_index != .none) { |
| 30482 | owner_func.state = .dependency_failure; | 30397 | ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure; |
| 30483 | } else { | 30398 | } else { |
| 30484 | sema.owner_decl.analysis = .dependency_failure; | 30399 | sema.owner_decl.analysis = .dependency_failure; |
| 30485 | } | 30400 | } |
| ... | @@ -30487,10 +30402,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { | ... | @@ -30487,10 +30402,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { |
| 30487 | }; | 30402 | }; |
| 30488 | } | 30403 | } |
| 30489 | 30404 | ||
| 30490 | fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void { | 30405 | fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void { |
| 30491 | sema.mod.ensureFuncBodyAnalyzed(func) catch |err| { | 30406 | const mod = sema.mod; |
| 30492 | if (sema.owner_func) |owner_func| { | 30407 | const ip = &mod.intern_pool; |
| 30493 | owner_func.state = .dependency_failure; | 30408 | mod.ensureFuncBodyAnalyzed(func) catch |err| { |
| 30409 | if (sema.owner_func_index != .none) { | ||
| 30410 | ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure; | ||
| 30494 | } else { | 30411 | } else { |
| 30495 | sema.owner_decl.analysis = .dependency_failure; | 30412 | sema.owner_decl.analysis = .dependency_failure; |
| 30496 | } | 30413 | } |
| ... | @@ -30566,7 +30483,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void { | ... | @@ -30566,7 +30483,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void { |
| 30566 | const tv = try decl.typedValue(); | 30483 | const tv = try decl.typedValue(); |
| 30567 | if (tv.ty.zigTypeTag(mod) != .Fn) return; | 30484 | if (tv.ty.zigTypeTag(mod) != .Fn) return; |
| 30568 | if (!try sema.fnHasRuntimeBits(tv.ty)) return; | 30485 | if (!try sema.fnHasRuntimeBits(tv.ty)) return; |
| 30569 | const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn | 30486 | const func_index = tv.val.toIntern(); |
| 30487 | if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function | ||
| 30570 | try mod.ensureFuncBodyAnalysisQueued(func_index); | 30488 | try mod.ensureFuncBodyAnalysisQueued(func_index); |
| 30571 | } | 30489 | } |
| 30572 | 30490 | ||
| ... | @@ -30582,7 +30500,7 @@ fn analyzeRef( | ... | @@ -30582,7 +30500,7 @@ fn analyzeRef( |
| 30582 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 30500 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 30583 | switch (mod.intern_pool.indexToKey(val.toIntern())) { | 30501 | switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 30584 | .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl), | 30502 | .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl), |
| 30585 | .func => |func| return sema.analyzeDeclRef(mod.funcPtr(func.index).owner_decl), | 30503 | .func => |func| return sema.analyzeDeclRef(func.owner_decl), |
| 30586 | else => {}, | 30504 | else => {}, |
| 30587 | } | 30505 | } |
| 30588 | var anon_decl = try block.startAnonDecl(); | 30506 | var anon_decl = try block.startAnonDecl(); |
| ... | @@ -30752,73 +30670,85 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -30752,73 +30670,85 @@ fn analyzeIsNonErrComptimeOnly( |
| 30752 | operand: Air.Inst.Ref, | 30670 | operand: Air.Inst.Ref, |
| 30753 | ) CompileError!Air.Inst.Ref { | 30671 | ) CompileError!Air.Inst.Ref { |
| 30754 | const mod = sema.mod; | 30672 | const mod = sema.mod; |
| 30673 | const ip = &mod.intern_pool; | ||
| 30755 | const operand_ty = sema.typeOf(operand); | 30674 | const operand_ty = sema.typeOf(operand); |
| 30756 | const ot = operand_ty.zigTypeTag(mod); | 30675 | const ot = operand_ty.zigTypeTag(mod); |
| 30757 | if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true; | 30676 | if (ot != .ErrorSet and ot != .ErrorUnion) return .bool_true; |
| 30758 | if (ot == .ErrorSet) return Air.Inst.Ref.bool_false; | 30677 | if (ot == .ErrorSet) return .bool_false; |
| 30759 | assert(ot == .ErrorUnion); | 30678 | assert(ot == .ErrorUnion); |
| 30760 | 30679 | ||
| 30761 | const payload_ty = operand_ty.errorUnionPayload(mod); | 30680 | const payload_ty = operand_ty.errorUnionPayload(mod); |
| 30762 | if (payload_ty.zigTypeTag(mod) == .NoReturn) { | 30681 | if (payload_ty.zigTypeTag(mod) == .NoReturn) { |
| 30763 | return Air.Inst.Ref.bool_false; | 30682 | return .bool_false; |
| 30764 | } | 30683 | } |
| 30765 | 30684 | ||
| 30766 | if (Air.refToIndex(operand)) |operand_inst| { | 30685 | if (Air.refToIndex(operand)) |operand_inst| { |
| 30767 | switch (sema.air_instructions.items(.tag)[operand_inst]) { | 30686 | switch (sema.air_instructions.items(.tag)[operand_inst]) { |
| 30768 | .wrap_errunion_payload => return Air.Inst.Ref.bool_true, | 30687 | .wrap_errunion_payload => return .bool_true, |
| 30769 | .wrap_errunion_err => return Air.Inst.Ref.bool_false, | 30688 | .wrap_errunion_err => return .bool_false, |
| 30770 | else => {}, | 30689 | else => {}, |
| 30771 | } | 30690 | } |
| 30772 | } else if (operand == .undef) { | 30691 | } else if (operand == .undef) { |
| 30773 | return sema.addConstUndef(Type.bool); | 30692 | return sema.addConstUndef(Type.bool); |
| 30774 | } else if (@intFromEnum(operand) < InternPool.static_len) { | 30693 | } else if (@intFromEnum(operand) < InternPool.static_len) { |
| 30775 | // None of the ref tags can be errors. | 30694 | // None of the ref tags can be errors. |
| 30776 | return Air.Inst.Ref.bool_true; | 30695 | return .bool_true; |
| 30777 | } | 30696 | } |
| 30778 | 30697 | ||
| 30779 | const maybe_operand_val = try sema.resolveMaybeUndefVal(operand); | 30698 | const maybe_operand_val = try sema.resolveMaybeUndefVal(operand); |
| 30780 | 30699 | ||
| 30781 | // exception if the error union error set is known to be empty, | 30700 | // exception if the error union error set is known to be empty, |
| 30782 | // we allow the comparison but always make it comptime-known. | 30701 | // we allow the comparison but always make it comptime-known. |
| 30783 | const set_ty = operand_ty.errorUnionSet(mod); | 30702 | const set_ty = ip.errorUnionSet(operand_ty.toIntern()); |
| 30784 | switch (set_ty.toIntern()) { | 30703 | switch (set_ty) { |
| 30785 | .anyerror_type => {}, | 30704 | .anyerror_type => {}, |
| 30786 | else => switch (mod.intern_pool.indexToKey(set_ty.toIntern())) { | 30705 | else => switch (ip.indexToKey(set_ty)) { |
| 30787 | .error_set_type => |error_set_type| { | 30706 | .error_set_type => |error_set_type| { |
| 30788 | if (error_set_type.names.len == 0) return Air.Inst.Ref.bool_true; | 30707 | if (error_set_type.names.len == 0) return .bool_true; |
| 30789 | }, | 30708 | }, |
| 30790 | .inferred_error_set_type => |ies_index| blk: { | 30709 | .inferred_error_set_type => |func_index| blk: { |
| 30791 | // If the error set is empty, we must return a comptime true or false. | 30710 | // If the error set is empty, we must return a comptime true or false. |
| 30792 | // However we want to avoid unnecessarily resolving an inferred error set | 30711 | // However we want to avoid unnecessarily resolving an inferred error set |
| 30793 | // in case it is already non-empty. | 30712 | // in case it is already non-empty. |
| 30794 | const ies = mod.inferredErrorSetPtr(ies_index); | 30713 | switch (ip.funcIesResolved(func_index).*) { |
| 30795 | if (ies.is_anyerror) break :blk; | 30714 | .anyerror_type => break :blk, |
| 30796 | if (ies.errors.count() != 0) break :blk; | 30715 | .none => {}, |
| 30716 | else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk, | ||
| 30717 | } | ||
| 30797 | if (maybe_operand_val == null) { | 30718 | if (maybe_operand_val == null) { |
| 30798 | // Try to avoid resolving inferred error set if possible. | 30719 | if (sema.fn_ret_ty_ies) |ies| { |
| 30799 | if (ies.errors.count() != 0) break :blk; | 30720 | if (set_ty == .adhoc_inferred_error_set_type or |
| 30800 | if (ies.is_anyerror) break :blk; | 30721 | ies.func == func_index) |
| 30801 | for (ies.inferred_error_sets.keys()) |other_ies_index| { | 30722 | { |
| 30802 | if (ies_index == other_ies_index) continue; | 30723 | // Try to avoid resolving inferred error set if possible. |
| 30803 | try sema.resolveInferredErrorSet(block, src, other_ies_index); | 30724 | if (ies.errors.count() != 0) return .none; |
| 30804 | const other_ies = mod.inferredErrorSetPtr(other_ies_index); | 30725 | switch (ies.resolved) { |
| 30805 | if (other_ies.is_anyerror) { | 30726 | .anyerror_type => return .none, |
| 30806 | ies.is_anyerror = true; | 30727 | .none => {}, |
| 30807 | ies.is_resolved = true; | 30728 | else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) { |
| 30808 | break :blk; | 30729 | 0 => return .bool_true, |
| 30730 | else => return .none, | ||
| 30731 | }, | ||
| 30732 | } | ||
| 30733 | for (ies.inferred_error_sets.keys()) |other_ies_index| { | ||
| 30734 | if (set_ty == other_ies_index) continue; | ||
| 30735 | const other_resolved = | ||
| 30736 | try sema.resolveInferredErrorSet(block, src, other_ies_index); | ||
| 30737 | if (other_resolved == .anyerror_type) { | ||
| 30738 | ies.resolved = .anyerror_type; | ||
| 30739 | return .none; | ||
| 30740 | } | ||
| 30741 | if (ip.indexToKey(other_resolved).error_set_type.names.len != 0) | ||
| 30742 | return .none; | ||
| 30743 | } | ||
| 30744 | return .bool_true; | ||
| 30809 | } | 30745 | } |
| 30810 | |||
| 30811 | if (other_ies.errors.count() != 0) break :blk; | ||
| 30812 | } | 30746 | } |
| 30813 | if (ies.func == sema.owner_func_index.unwrap()) { | 30747 | const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty); |
| 30814 | // We're checking the inferred errorset of the current function and none of | 30748 | if (resolved_ty == .anyerror_type) |
| 30815 | // its child inferred error sets contained any errors meaning that any value | 30749 | break :blk; |
| 30816 | // so far with this type can't contain errors either. | 30750 | if (ip.indexToKey(resolved_ty).error_set_type.names.len == 0) |
| 30817 | return Air.Inst.Ref.bool_true; | 30751 | return .bool_true; |
| 30818 | } | ||
| 30819 | try sema.resolveInferredErrorSet(block, src, ies_index); | ||
| 30820 | if (ies.is_anyerror) break :blk; | ||
| 30821 | if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true; | ||
| 30822 | } | 30752 | } |
| 30823 | }, | 30753 | }, |
| 30824 | else => unreachable, | 30754 | else => unreachable, |
| ... | @@ -30830,12 +30760,12 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -30830,12 +30760,12 @@ fn analyzeIsNonErrComptimeOnly( |
| 30830 | return sema.addConstUndef(Type.bool); | 30760 | return sema.addConstUndef(Type.bool); |
| 30831 | } | 30761 | } |
| 30832 | if (err_union.getErrorName(mod) == .none) { | 30762 | if (err_union.getErrorName(mod) == .none) { |
| 30833 | return Air.Inst.Ref.bool_true; | 30763 | return .bool_true; |
| 30834 | } else { | 30764 | } else { |
| 30835 | return Air.Inst.Ref.bool_false; | 30765 | return .bool_false; |
| 30836 | } | 30766 | } |
| 30837 | } | 30767 | } |
| 30838 | return Air.Inst.Ref.none; | 30768 | return .none; |
| 30839 | } | 30769 | } |
| 30840 | 30770 | ||
| 30841 | fn analyzeIsNonErr( | 30771 | fn analyzeIsNonErr( |
| ... | @@ -31768,24 +31698,39 @@ fn wrapErrorUnionSet( | ... | @@ -31768,24 +31698,39 @@ fn wrapErrorUnionSet( |
| 31768 | const inst_ty = sema.typeOf(inst); | 31698 | const inst_ty = sema.typeOf(inst); |
| 31769 | const dest_err_set_ty = dest_ty.errorUnionSet(mod); | 31699 | const dest_err_set_ty = dest_ty.errorUnionSet(mod); |
| 31770 | if (try sema.resolveMaybeUndefVal(inst)) |val| { | 31700 | if (try sema.resolveMaybeUndefVal(inst)) |val| { |
| 31701 | const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; | ||
| 31771 | switch (dest_err_set_ty.toIntern()) { | 31702 | switch (dest_err_set_ty.toIntern()) { |
| 31772 | .anyerror_type => {}, | 31703 | .anyerror_type => {}, |
| 31704 | .adhoc_inferred_error_set_type => ok: { | ||
| 31705 | const ies = sema.fn_ret_ty_ies.?; | ||
| 31706 | switch (ies.resolved) { | ||
| 31707 | .anyerror_type => break :ok, | ||
| 31708 | .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) { | ||
| 31709 | break :ok; | ||
| 31710 | }, | ||
| 31711 | else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) { | ||
| 31712 | break :ok; | ||
| 31713 | }, | ||
| 31714 | } | ||
| 31715 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); | ||
| 31716 | }, | ||
| 31773 | else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) { | 31717 | else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) { |
| 31774 | .error_set_type => |error_set_type| ok: { | 31718 | .error_set_type => |error_set_type| ok: { |
| 31775 | const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; | ||
| 31776 | if (error_set_type.nameIndex(ip, expected_name) != null) break :ok; | 31719 | if (error_set_type.nameIndex(ip, expected_name) != null) break :ok; |
| 31777 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); | 31720 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); |
| 31778 | }, | 31721 | }, |
| 31779 | .inferred_error_set_type => |ies_index| ok: { | 31722 | .inferred_error_set_type => |func_index| ok: { |
| 31780 | const ies = mod.inferredErrorSetPtr(ies_index); | ||
| 31781 | const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; | ||
| 31782 | |||
| 31783 | // We carefully do this in an order that avoids unnecessarily | 31723 | // We carefully do this in an order that avoids unnecessarily |
| 31784 | // resolving the destination error set type. | 31724 | // resolving the destination error set type. |
| 31785 | if (ies.is_anyerror) break :ok; | 31725 | switch (ip.funcIesResolved(func_index).*) { |
| 31786 | 31726 | .anyerror_type => break :ok, | |
| 31787 | if (ies.errors.contains(expected_name)) break :ok; | 31727 | .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) { |
| 31788 | if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok; | 31728 | break :ok; |
| 31729 | }, | ||
| 31730 | else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) { | ||
| 31731 | break :ok; | ||
| 31732 | }, | ||
| 31733 | } | ||
| 31789 | 31734 | ||
| 31790 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); | 31735 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); |
| 31791 | }, | 31736 | }, |
| ... | @@ -31794,9 +31739,7 @@ fn wrapErrorUnionSet( | ... | @@ -31794,9 +31739,7 @@ fn wrapErrorUnionSet( |
| 31794 | } | 31739 | } |
| 31795 | return sema.addConstant((try mod.intern(.{ .error_union = .{ | 31740 | return sema.addConstant((try mod.intern(.{ .error_union = .{ |
| 31796 | .ty = dest_ty.toIntern(), | 31741 | .ty = dest_ty.toIntern(), |
| 31797 | .val = .{ | 31742 | .val = .{ .err_name = expected_name }, |
| 31798 | .err_name = mod.intern_pool.indexToKey(try val.intern(dest_err_set_ty, mod)).err.name, | ||
| 31799 | }, | ||
| 31800 | } })).toValue()); | 31743 | } })).toValue()); |
| 31801 | } | 31744 | } |
| 31802 | 31745 | ||
| ... | @@ -33273,17 +33216,31 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { | ... | @@ -33273,17 +33216,31 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { |
| 33273 | }; | 33216 | }; |
| 33274 | } | 33217 | } |
| 33275 | 33218 | ||
| 33219 | pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void { | ||
| 33220 | const mod = sema.mod; | ||
| 33221 | const ip = &mod.intern_pool; | ||
| 33222 | |||
| 33223 | if (sema.fn_ret_ty_ies) |ies| { | ||
| 33224 | try sema.resolveInferredErrorSetPtr(block, src, ies); | ||
| 33225 | assert(ies.resolved != .none); | ||
| 33226 | ip.funcIesResolved(sema.func_index).* = ies.resolved; | ||
| 33227 | } | ||
| 33228 | } | ||
| 33229 | |||
| 33276 | pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void { | 33230 | pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void { |
| 33277 | const mod = sema.mod; | 33231 | const mod = sema.mod; |
| 33278 | try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.return_type.toType()); | 33232 | const ip = &mod.intern_pool; |
| 33233 | const fn_ty_info = mod.typeToFunc(fn_ty).?; | ||
| 33234 | |||
| 33235 | try sema.resolveTypeFully(fn_ty_info.return_type.toType()); | ||
| 33279 | 33236 | ||
| 33280 | if (mod.comp.bin_file.options.error_return_tracing and mod.typeToFunc(fn_ty).?.return_type.toType().isError(mod)) { | 33237 | if (mod.comp.bin_file.options.error_return_tracing and fn_ty_info.return_type.toType().isError(mod)) { |
| 33281 | // Ensure the type exists so that backends can assume that. | 33238 | // Ensure the type exists so that backends can assume that. |
| 33282 | _ = try sema.getBuiltinType("StackTrace"); | 33239 | _ = try sema.getBuiltinType("StackTrace"); |
| 33283 | } | 33240 | } |
| 33284 | 33241 | ||
| 33285 | for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| { | 33242 | for (0..fn_ty_info.param_types.len) |i| { |
| 33286 | try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType()); | 33243 | try sema.resolveTypeFully(fn_ty_info.param_types.get(ip)[i].toType()); |
| 33287 | } | 33244 | } |
| 33288 | } | 33245 | } |
| 33289 | 33246 | ||
| ... | @@ -33448,7 +33405,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -33448,7 +33405,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { |
| 33448 | // the function is instantiated. | 33405 | // the function is instantiated. |
| 33449 | return; | 33406 | return; |
| 33450 | } | 33407 | } |
| 33451 | for (info.param_types) |param_ty| { | 33408 | const ip = &mod.intern_pool; |
| 33409 | for (0..info.param_types.len) |i| { | ||
| 33410 | const param_ty = info.param_types.get(ip)[i]; | ||
| 33452 | try sema.resolveTypeLayout(param_ty.toType()); | 33411 | try sema.resolveTypeLayout(param_ty.toType()); |
| 33453 | } | 33412 | } |
| 33454 | try sema.resolveTypeLayout(info.return_type.toType()); | 33413 | try sema.resolveTypeLayout(info.return_type.toType()); |
| ... | @@ -33578,10 +33537,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi | ... | @@ -33578,10 +33537,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 33578 | .code = zir, | 33537 | .code = zir, |
| 33579 | .owner_decl = decl, | 33538 | .owner_decl = decl, |
| 33580 | .owner_decl_index = decl_index, | 33539 | .owner_decl_index = decl_index, |
| 33581 | .func = null, | ||
| 33582 | .func_index = .none, | 33540 | .func_index = .none, |
| 33583 | .fn_ret_ty = Type.void, | 33541 | .fn_ret_ty = Type.void, |
| 33584 | .owner_func = null, | 33542 | .fn_ret_ty_ies = null, |
| 33585 | .owner_func_index = .none, | 33543 | .owner_func_index = .none, |
| 33586 | .comptime_mutable_decls = &comptime_mutable_decls, | 33544 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 33587 | }; | 33545 | }; |
| ... | @@ -33600,10 +33558,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi | ... | @@ -33600,10 +33558,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 33600 | .inlining = null, | 33558 | .inlining = null, |
| 33601 | .is_comptime = true, | 33559 | .is_comptime = true, |
| 33602 | }; | 33560 | }; |
| 33603 | defer { | 33561 | defer assert(block.instructions.items.len == 0); |
| 33604 | assert(block.instructions.items.len == 0); | ||
| 33605 | block.params.deinit(gpa); | ||
| 33606 | } | ||
| 33607 | 33562 | ||
| 33608 | const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 }; | 33563 | const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 }; |
| 33609 | const backing_int_ty = blk: { | 33564 | const backing_int_ty = blk: { |
| ... | @@ -33633,10 +33588,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi | ... | @@ -33633,10 +33588,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 33633 | .code = zir, | 33588 | .code = zir, |
| 33634 | .owner_decl = decl, | 33589 | .owner_decl = decl, |
| 33635 | .owner_decl_index = decl_index, | 33590 | .owner_decl_index = decl_index, |
| 33636 | .func = null, | ||
| 33637 | .func_index = .none, | 33591 | .func_index = .none, |
| 33638 | .fn_ret_ty = Type.void, | 33592 | .fn_ret_ty = Type.void, |
| 33639 | .owner_func = null, | 33593 | .fn_ret_ty_ies = null, |
| 33640 | .owner_func_index = .none, | 33594 | .owner_func_index = .none, |
| 33641 | .comptime_mutable_decls = undefined, | 33595 | .comptime_mutable_decls = undefined, |
| 33642 | }; | 33596 | }; |
| ... | @@ -33808,6 +33762,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33808,6 +33762,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33808 | .bool, | 33762 | .bool, |
| 33809 | .void, | 33763 | .void, |
| 33810 | .anyerror, | 33764 | .anyerror, |
| 33765 | .adhoc_inferred_error_set, | ||
| 33811 | .noreturn, | 33766 | .noreturn, |
| 33812 | .generic_poison, | 33767 | .generic_poison, |
| 33813 | .atomic_order, | 33768 | .atomic_order, |
| ... | @@ -33943,7 +33898,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -33943,7 +33898,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { |
| 33943 | // the function is instantiated. | 33898 | // the function is instantiated. |
| 33944 | return; | 33899 | return; |
| 33945 | } | 33900 | } |
| 33946 | for (info.param_types) |param_ty| { | 33901 | const ip = &mod.intern_pool; |
| 33902 | for (0..info.param_types.len) |i| { | ||
| 33903 | const param_ty = info.param_types.get(ip)[i]; | ||
| 33947 | try sema.resolveTypeFully(param_ty.toType()); | 33904 | try sema.resolveTypeFully(param_ty.toType()); |
| 33948 | } | 33905 | } |
| 33949 | try sema.resolveTypeFully(info.return_type.toType()); | 33906 | try sema.resolveTypeFully(info.return_type.toType()); |
| ... | @@ -34056,6 +34013,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { | ... | @@ -34056,6 +34013,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { |
| 34056 | .void_type, | 34013 | .void_type, |
| 34057 | .type_type, | 34014 | .type_type, |
| 34058 | .anyerror_type, | 34015 | .anyerror_type, |
| 34016 | .adhoc_inferred_error_set_type, | ||
| 34059 | .comptime_int_type, | 34017 | .comptime_int_type, |
| 34060 | .comptime_float_type, | 34018 | .comptime_float_type, |
| 34061 | .noreturn_type, | 34019 | .noreturn_type, |
| ... | @@ -34209,29 +34167,28 @@ fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) Compi | ... | @@ -34209,29 +34167,28 @@ fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) Compi |
| 34209 | union_obj.status = .have_field_types; | 34167 | union_obj.status = .have_field_types; |
| 34210 | } | 34168 | } |
| 34211 | 34169 | ||
| 34170 | /// Returns a normal error set corresponding to the fully populated inferred | ||
| 34171 | /// error set. | ||
| 34212 | fn resolveInferredErrorSet( | 34172 | fn resolveInferredErrorSet( |
| 34213 | sema: *Sema, | 34173 | sema: *Sema, |
| 34214 | block: *Block, | 34174 | block: *Block, |
| 34215 | src: LazySrcLoc, | 34175 | src: LazySrcLoc, |
| 34216 | ies_index: Module.Fn.InferredErrorSet.Index, | 34176 | ies_index: InternPool.Index, |
| 34217 | ) CompileError!void { | 34177 | ) CompileError!InternPool.Index { |
| 34218 | const mod = sema.mod; | 34178 | const mod = sema.mod; |
| 34219 | const ies = mod.inferredErrorSetPtr(ies_index); | 34179 | const ip = &mod.intern_pool; |
| 34220 | 34180 | const func_index = ip.iesFuncIndex(ies_index); | |
| 34221 | if (ies.is_resolved) return; | 34181 | const func = mod.funcInfo(func_index); |
| 34222 | 34182 | const resolved_ty = func.resolvedErrorSet(ip).*; | |
| 34223 | const func = mod.funcPtr(ies.func); | 34183 | if (resolved_ty != .none) return resolved_ty; |
| 34224 | if (func.state == .in_progress) { | 34184 | if (func.analysis(ip).state == .in_progress) |
| 34225 | return sema.fail(block, src, "unable to resolve inferred error set", .{}); | 34185 | return sema.fail(block, src, "unable to resolve inferred error set", .{}); |
| 34226 | } | ||
| 34227 | 34186 | ||
| 34228 | // In order to ensure that all dependencies are properly added to the set, we | 34187 | // In order to ensure that all dependencies are properly added to the set, |
| 34229 | // need to ensure the function body is analyzed of the inferred error set. | 34188 | // we need to ensure the function body is analyzed of the inferred error |
| 34230 | // However, in the case of comptime/inline function calls with inferred error sets, | 34189 | // set. However, in the case of comptime/inline function calls with |
| 34231 | // each call gets a new InferredErrorSet object, which contains the same | 34190 | // inferred error sets, each call gets an adhoc InferredErrorSet object, which |
| 34232 | // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set | 34191 | // has no corresponding function body. |
| 34233 | // in this case, it may be a generic function which would cause an assertion failure | ||
| 34234 | // if we called `ensureFuncBodyAnalyzed` on it here. | ||
| 34235 | const ies_func_owner_decl = mod.declPtr(func.owner_decl); | 34192 | const ies_func_owner_decl = mod.declPtr(func.owner_decl); |
| 34236 | const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?; | 34193 | const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?; |
| 34237 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, | 34194 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, |
| ... | @@ -34239,7 +34196,7 @@ fn resolveInferredErrorSet( | ... | @@ -34239,7 +34196,7 @@ fn resolveInferredErrorSet( |
| 34239 | // so here we can simply skip this case. | 34196 | // so here we can simply skip this case. |
| 34240 | if (ies_func_info.return_type == .generic_poison_type) { | 34197 | if (ies_func_info.return_type == .generic_poison_type) { |
| 34241 | assert(ies_func_info.cc == .Inline); | 34198 | assert(ies_func_info.cc == .Inline); |
| 34242 | } else if (mod.typeToInferredErrorSet(ies_func_info.return_type.toType().errorUnionSet(mod)).? == ies) { | 34199 | } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { |
| 34243 | if (ies_func_info.is_generic) { | 34200 | if (ies_func_info.is_generic) { |
| 34244 | const msg = msg: { | 34201 | const msg = msg: { |
| 34245 | const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{}); | 34202 | const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{}); |
| ... | @@ -34252,33 +34209,101 @@ fn resolveInferredErrorSet( | ... | @@ -34252,33 +34209,101 @@ fn resolveInferredErrorSet( |
| 34252 | } | 34209 | } |
| 34253 | // In this case we are dealing with the actual InferredErrorSet object that | 34210 | // In this case we are dealing with the actual InferredErrorSet object that |
| 34254 | // corresponds to the function, not one created to track an inline/comptime call. | 34211 | // corresponds to the function, not one created to track an inline/comptime call. |
| 34255 | try sema.ensureFuncBodyAnalyzed(ies.func); | 34212 | try sema.ensureFuncBodyAnalyzed(func_index); |
| 34256 | } | 34213 | } |
| 34257 | 34214 | ||
| 34258 | ies.is_resolved = true; | 34215 | // This will now have been resolved by the logic at the end of `Module.analyzeFnBody` |
| 34216 | // which calls `resolveInferredErrorSetPtr`. | ||
| 34217 | const final_resolved_ty = func.resolvedErrorSet(ip).*; | ||
| 34218 | assert(final_resolved_ty != .none); | ||
| 34219 | return final_resolved_ty; | ||
| 34220 | } | ||
| 34221 | |||
| 34222 | pub fn resolveInferredErrorSetPtr( | ||
| 34223 | sema: *Sema, | ||
| 34224 | block: *Block, | ||
| 34225 | src: LazySrcLoc, | ||
| 34226 | ies: *InferredErrorSet, | ||
| 34227 | ) CompileError!void { | ||
| 34228 | const mod = sema.mod; | ||
| 34229 | const ip = &mod.intern_pool; | ||
| 34230 | |||
| 34231 | if (ies.resolved != .none) return; | ||
| 34232 | |||
| 34233 | const ies_index = ip.errorUnionSet(sema.fn_ret_ty.toIntern()); | ||
| 34259 | 34234 | ||
| 34260 | for (ies.inferred_error_sets.keys()) |other_ies_index| { | 34235 | for (ies.inferred_error_sets.keys()) |other_ies_index| { |
| 34261 | if (ies_index == other_ies_index) continue; | 34236 | if (ies_index == other_ies_index) continue; |
| 34262 | try sema.resolveInferredErrorSet(block, src, other_ies_index); | 34237 | switch (try sema.resolveInferredErrorSet(block, src, other_ies_index)) { |
| 34263 | 34238 | .anyerror_type => { | |
| 34264 | const other_ies = mod.inferredErrorSetPtr(other_ies_index); | 34239 | ies.resolved = .anyerror_type; |
| 34265 | for (other_ies.errors.keys()) |key| { | 34240 | return; |
| 34266 | try ies.errors.put(sema.gpa, key, {}); | 34241 | }, |
| 34242 | else => |error_set_ty_index| { | ||
| 34243 | const names = ip.indexToKey(error_set_ty_index).error_set_type.names; | ||
| 34244 | for (names.get(ip)) |name| { | ||
| 34245 | try ies.errors.put(sema.arena, name, {}); | ||
| 34246 | } | ||
| 34247 | }, | ||
| 34267 | } | 34248 | } |
| 34268 | if (other_ies.is_anyerror) | ||
| 34269 | ies.is_anyerror = true; | ||
| 34270 | } | 34249 | } |
| 34250 | |||
| 34251 | const resolved_error_set_ty = try mod.errorSetFromUnsortedNames(ies.errors.keys()); | ||
| 34252 | ies.resolved = resolved_error_set_ty.toIntern(); | ||
| 34253 | } | ||
| 34254 | |||
| 34255 | fn resolveAdHocInferredErrorSet( | ||
| 34256 | sema: *Sema, | ||
| 34257 | block: *Block, | ||
| 34258 | src: LazySrcLoc, | ||
| 34259 | value: InternPool.Index, | ||
| 34260 | ) CompileError!InternPool.Index { | ||
| 34261 | const mod = sema.mod; | ||
| 34262 | const gpa = sema.gpa; | ||
| 34263 | const ip = &mod.intern_pool; | ||
| 34264 | const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value)); | ||
| 34265 | if (new_ty == .none) return value; | ||
| 34266 | return ip.getCoerced(gpa, value, new_ty); | ||
| 34267 | } | ||
| 34268 | |||
| 34269 | fn resolveAdHocInferredErrorSetTy( | ||
| 34270 | sema: *Sema, | ||
| 34271 | block: *Block, | ||
| 34272 | src: LazySrcLoc, | ||
| 34273 | ty: InternPool.Index, | ||
| 34274 | ) CompileError!InternPool.Index { | ||
| 34275 | const ies = sema.fn_ret_ty_ies orelse return .none; | ||
| 34276 | const mod = sema.mod; | ||
| 34277 | const gpa = sema.gpa; | ||
| 34278 | const ip = &mod.intern_pool; | ||
| 34279 | const error_union_info = switch (ip.indexToKey(ty)) { | ||
| 34280 | .error_union_type => |x| x, | ||
| 34281 | else => return .none, | ||
| 34282 | }; | ||
| 34283 | if (error_union_info.error_set_type != .adhoc_inferred_error_set_type) | ||
| 34284 | return .none; | ||
| 34285 | |||
| 34286 | try sema.resolveInferredErrorSetPtr(block, src, ies); | ||
| 34287 | const new_ty = try ip.get(gpa, .{ .error_union_type = .{ | ||
| 34288 | .error_set_type = ies.resolved, | ||
| 34289 | .payload_type = error_union_info.payload_type, | ||
| 34290 | } }); | ||
| 34291 | return new_ty; | ||
| 34271 | } | 34292 | } |
| 34272 | 34293 | ||
| 34273 | fn resolveInferredErrorSetTy( | 34294 | fn resolveInferredErrorSetTy( |
| 34274 | sema: *Sema, | 34295 | sema: *Sema, |
| 34275 | block: *Block, | 34296 | block: *Block, |
| 34276 | src: LazySrcLoc, | 34297 | src: LazySrcLoc, |
| 34277 | ty: Type, | 34298 | ty: InternPool.Index, |
| 34278 | ) CompileError!void { | 34299 | ) CompileError!InternPool.Index { |
| 34279 | const mod = sema.mod; | 34300 | const mod = sema.mod; |
| 34280 | if (mod.typeToInferredErrorSetIndex(ty).unwrap()) |ies_index| { | 34301 | const ip = &mod.intern_pool; |
| 34281 | try sema.resolveInferredErrorSet(block, src, ies_index); | 34302 | if (ty == .anyerror_type) return ty; |
| 34303 | switch (ip.indexToKey(ty)) { | ||
| 34304 | .error_set_type => return ty, | ||
| 34305 | .inferred_error_set_type => return sema.resolveInferredErrorSet(block, src, ty), | ||
| 34306 | else => unreachable, | ||
| 34282 | } | 34307 | } |
| 34283 | } | 34308 | } |
| 34284 | 34309 | ||
| ... | @@ -34346,10 +34371,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -34346,10 +34371,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 34346 | .code = zir, | 34371 | .code = zir, |
| 34347 | .owner_decl = decl, | 34372 | .owner_decl = decl, |
| 34348 | .owner_decl_index = decl_index, | 34373 | .owner_decl_index = decl_index, |
| 34349 | .func = null, | ||
| 34350 | .func_index = .none, | 34374 | .func_index = .none, |
| 34351 | .fn_ret_ty = Type.void, | 34375 | .fn_ret_ty = Type.void, |
| 34352 | .owner_func = null, | 34376 | .fn_ret_ty_ies = null, |
| 34353 | .owner_func_index = .none, | 34377 | .owner_func_index = .none, |
| 34354 | .comptime_mutable_decls = &comptime_mutable_decls, | 34378 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 34355 | }; | 34379 | }; |
| ... | @@ -34368,10 +34392,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -34368,10 +34392,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 34368 | .inlining = null, | 34392 | .inlining = null, |
| 34369 | .is_comptime = true, | 34393 | .is_comptime = true, |
| 34370 | }; | 34394 | }; |
| 34371 | defer { | 34395 | defer assert(block_scope.instructions.items.len == 0); |
| 34372 | assert(block_scope.instructions.items.len == 0); | ||
| 34373 | block_scope.params.deinit(gpa); | ||
| 34374 | } | ||
| 34375 | 34396 | ||
| 34376 | struct_obj.fields = .{}; | 34397 | struct_obj.fields = .{}; |
| 34377 | try struct_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len); | 34398 | try struct_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len); |
| ... | @@ -34693,10 +34714,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -34693,10 +34714,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 34693 | .code = zir, | 34714 | .code = zir, |
| 34694 | .owner_decl = decl, | 34715 | .owner_decl = decl, |
| 34695 | .owner_decl_index = decl_index, | 34716 | .owner_decl_index = decl_index, |
| 34696 | .func = null, | ||
| 34697 | .func_index = .none, | 34717 | .func_index = .none, |
| 34698 | .fn_ret_ty = Type.void, | 34718 | .fn_ret_ty = Type.void, |
| 34699 | .owner_func = null, | 34719 | .fn_ret_ty_ies = null, |
| 34700 | .owner_func_index = .none, | 34720 | .owner_func_index = .none, |
| 34701 | .comptime_mutable_decls = &comptime_mutable_decls, | 34721 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 34702 | }; | 34722 | }; |
| ... | @@ -34715,10 +34735,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -34715,10 +34735,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 34715 | .inlining = null, | 34735 | .inlining = null, |
| 34716 | .is_comptime = true, | 34736 | .is_comptime = true, |
| 34717 | }; | 34737 | }; |
| 34718 | defer { | 34738 | defer assert(block_scope.instructions.items.len == 0); |
| 34719 | assert(block_scope.instructions.items.len == 0); | ||
| 34720 | block_scope.params.deinit(gpa); | ||
| 34721 | } | ||
| 34722 | 34739 | ||
| 34723 | if (body.len != 0) { | 34740 | if (body.len != 0) { |
| 34724 | try sema.analyzeBody(&block_scope, body); | 34741 | try sema.analyzeBody(&block_scope, body); |
| ... | @@ -35050,7 +35067,7 @@ fn generateUnionTagTypeNumbered( | ... | @@ -35050,7 +35067,7 @@ fn generateUnionTagTypeNumbered( |
| 35050 | errdefer mod.destroyDecl(new_decl_index); | 35067 | errdefer mod.destroyDecl(new_decl_index); |
| 35051 | const fqn = try union_obj.getFullyQualifiedName(mod); | 35068 | const fqn = try union_obj.getFullyQualifiedName(mod); |
| 35052 | const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)}); | 35069 | const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)}); |
| 35053 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{ | 35070 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ |
| 35054 | .ty = Type.noreturn, | 35071 | .ty = Type.noreturn, |
| 35055 | .val = Value.@"unreachable", | 35072 | .val = Value.@"unreachable", |
| 35056 | }, name); | 35073 | }, name); |
| ... | @@ -35101,7 +35118,7 @@ fn generateUnionTagTypeSimple( | ... | @@ -35101,7 +35118,7 @@ fn generateUnionTagTypeSimple( |
| 35101 | errdefer mod.destroyDecl(new_decl_index); | 35118 | errdefer mod.destroyDecl(new_decl_index); |
| 35102 | const fqn = try union_obj.getFullyQualifiedName(mod); | 35119 | const fqn = try union_obj.getFullyQualifiedName(mod); |
| 35103 | const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)}); | 35120 | const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)}); |
| 35104 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{ | 35121 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ |
| 35105 | .ty = Type.noreturn, | 35122 | .ty = Type.noreturn, |
| 35106 | .val = Value.@"unreachable", | 35123 | .val = Value.@"unreachable", |
| 35107 | }, name); | 35124 | }, name); |
| ... | @@ -35148,10 +35165,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { | ... | @@ -35148,10 +35165,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 35148 | .inlining = null, | 35165 | .inlining = null, |
| 35149 | .is_comptime = true, | 35166 | .is_comptime = true, |
| 35150 | }; | 35167 | }; |
| 35151 | defer { | 35168 | defer block.instructions.deinit(gpa); |
| 35152 | block.instructions.deinit(gpa); | ||
| 35153 | block.params.deinit(gpa); | ||
| 35154 | } | ||
| 35155 | 35169 | ||
| 35156 | const decl_index = try getBuiltinDecl(sema, &block, name); | 35170 | const decl_index = try getBuiltinDecl(sema, &block, name); |
| 35157 | return sema.analyzeDeclVal(&block, src, decl_index); | 35171 | return sema.analyzeDeclVal(&block, src, decl_index); |
| ... | @@ -35202,10 +35216,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { | ... | @@ -35202,10 +35216,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 35202 | .inlining = null, | 35216 | .inlining = null, |
| 35203 | .is_comptime = true, | 35217 | .is_comptime = true, |
| 35204 | }; | 35218 | }; |
| 35205 | defer { | 35219 | defer block.instructions.deinit(sema.gpa); |
| 35206 | block.instructions.deinit(sema.gpa); | ||
| 35207 | block.params.deinit(sema.gpa); | ||
| 35208 | } | ||
| 35209 | const src = LazySrcLoc.nodeOffset(0); | 35220 | const src = LazySrcLoc.nodeOffset(0); |
| 35210 | 35221 | ||
| 35211 | const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) { | 35222 | const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) { |
| ... | @@ -35261,6 +35272,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -35261,6 +35272,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 35261 | .bool_type, | 35272 | .bool_type, |
| 35262 | .type_type, | 35273 | .type_type, |
| 35263 | .anyerror_type, | 35274 | .anyerror_type, |
| 35275 | .adhoc_inferred_error_set_type, | ||
| 35264 | .comptime_int_type, | 35276 | .comptime_int_type, |
| 35265 | .comptime_float_type, | 35277 | .comptime_float_type, |
| 35266 | .enum_literal_type, | 35278 | .enum_literal_type, |
| ... | @@ -35314,6 +35326,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -35314,6 +35326,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 35314 | .var_args_param_type, | 35326 | .var_args_param_type, |
| 35315 | .none, | 35327 | .none, |
| 35316 | => unreachable, | 35328 | => unreachable, |
| 35329 | |||
| 35317 | _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) { | 35330 | _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) { |
| 35318 | .type_int_signed, // i0 handled above | 35331 | .type_int_signed, // i0 handled above |
| 35319 | .type_int_unsigned, // u0 handled above | 35332 | .type_int_unsigned, // u0 handled above |
| ... | @@ -35322,11 +35335,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -35322,11 +35335,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 35322 | .type_optional, // ?noreturn handled above | 35335 | .type_optional, // ?noreturn handled above |
| 35323 | .type_anyframe, | 35336 | .type_anyframe, |
| 35324 | .type_error_union, | 35337 | .type_error_union, |
| 35338 | .type_anyerror_union, | ||
| 35325 | .type_error_set, | 35339 | .type_error_set, |
| 35326 | .type_inferred_error_set, | 35340 | .type_inferred_error_set, |
| 35327 | .type_opaque, | 35341 | .type_opaque, |
| 35328 | .type_function, | 35342 | .type_function, |
| 35329 | => null, | 35343 | => null, |
| 35344 | |||
| 35330 | .simple_type, // handled above | 35345 | .simple_type, // handled above |
| 35331 | // values, not types | 35346 | // values, not types |
| 35332 | .undef, | 35347 | .undef, |
| ... | @@ -35370,7 +35385,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -35370,7 +35385,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 35370 | .float_comptime_float, | 35385 | .float_comptime_float, |
| 35371 | .variable, | 35386 | .variable, |
| 35372 | .extern_func, | 35387 | .extern_func, |
| 35373 | .func, | 35388 | .func_decl, |
| 35389 | .func_instance, | ||
| 35390 | .func_coerced, | ||
| 35374 | .only_possible_value, | 35391 | .only_possible_value, |
| 35375 | .union_value, | 35392 | .union_value, |
| 35376 | .bytes, | 35393 | .bytes, |
| ... | @@ -35379,6 +35396,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -35379,6 +35396,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 35379 | // memoized value, not types | 35396 | // memoized value, not types |
| 35380 | .memoized_call, | 35397 | .memoized_call, |
| 35381 | => unreachable, | 35398 | => unreachable, |
| 35399 | |||
| 35382 | .type_array_big, | 35400 | .type_array_big, |
| 35383 | .type_array_small, | 35401 | .type_array_small, |
| 35384 | .type_vector, | 35402 | .type_vector, |
| ... | @@ -35911,6 +35929,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -35911,6 +35929,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 35911 | .prefetch_options, | 35929 | .prefetch_options, |
| 35912 | .export_options, | 35930 | .export_options, |
| 35913 | .extern_options, | 35931 | .extern_options, |
| 35932 | .adhoc_inferred_error_set, | ||
| 35914 | => false, | 35933 | => false, |
| 35915 | 35934 | ||
| 35916 | .type, | 35935 | .type, |
| ... | @@ -36772,7 +36791,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { | ... | @@ -36772,7 +36791,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { |
| 36772 | const arena = sema.arena; | 36791 | const arena = sema.arena; |
| 36773 | const lhs_names = lhs.errorSetNames(mod); | 36792 | const lhs_names = lhs.errorSetNames(mod); |
| 36774 | const rhs_names = rhs.errorSetNames(mod); | 36793 | const rhs_names = rhs.errorSetNames(mod); |
| 36775 | var names: Module.Fn.InferredErrorSet.NameMap = .{}; | 36794 | var names: InferredErrorSet.NameMap = .{}; |
| 36776 | try names.ensureUnusedCapacity(arena, lhs_names.len); | 36795 | try names.ensureUnusedCapacity(arena, lhs_names.len); |
| 36777 | 36796 | ||
| 36778 | for (lhs_names) |name| { | 36797 | for (lhs_names) |name| { |
src/TypedValue.zig+1-1| ... | @@ -205,7 +205,7 @@ pub fn print( | ... | @@ -205,7 +205,7 @@ pub fn print( |
| 205 | mod.declPtr(extern_func.decl).name.fmt(ip), | 205 | mod.declPtr(extern_func.decl).name.fmt(ip), |
| 206 | }), | 206 | }), |
| 207 | .func => |func| return writer.print("(function '{}')", .{ | 207 | .func => |func| return writer.print("(function '{}')", .{ |
| 208 | mod.declPtr(mod.funcPtr(func.index).owner_decl).name.fmt(ip), | 208 | mod.declPtr(func.owner_decl).name.fmt(ip), |
| 209 | }), | 209 | }), |
| 210 | .int => |int| switch (int.storage) { | 210 | .int => |int| switch (int.storage) { |
| 211 | inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}), | 211 | inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}), |
src/Zir.zig+20-4| ... | @@ -65,9 +65,13 @@ pub const ExtraIndex = enum(u32) { | ... | @@ -65,9 +65,13 @@ pub const ExtraIndex = enum(u32) { |
| 65 | _, | 65 | _, |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | fn ExtraData(comptime T: type) type { | ||
| 69 | return struct { data: T, end: usize }; | ||
| 70 | } | ||
| 71 | |||
| 68 | /// Returns the requested data, as well as the new index which is at the start of the | 72 | /// Returns the requested data, as well as the new index which is at the start of the |
| 69 | /// trailers for the object. | 73 | /// trailers for the object. |
| 70 | pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, end: usize } { | 74 | pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 71 | const fields = @typeInfo(T).Struct.fields; | 75 | const fields = @typeInfo(T).Struct.fields; |
| 72 | var i: usize = index; | 76 | var i: usize = index; |
| 73 | var result: T = undefined; | 77 | var result: T = undefined; |
| ... | @@ -90,13 +94,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en | ... | @@ -90,13 +94,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en |
| 90 | }; | 94 | }; |
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | /// Given an index into `string_bytes` returns the null-terminated string found there. | 97 | /// TODO migrate to use this for type safety |
| 98 | pub const NullTerminatedString = enum(u32) { | ||
| 99 | _, | ||
| 100 | }; | ||
| 101 | |||
| 102 | /// TODO: migrate to nullTerminatedString2 for type safety | ||
| 94 | pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 { | 103 | pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 { |
| 95 | var end: usize = index; | 104 | return nullTerminatedString2(code, @enumFromInt(index)); |
| 105 | } | ||
| 106 | |||
| 107 | /// Given an index into `string_bytes` returns the null-terminated string found there. | ||
| 108 | pub fn nullTerminatedString2(code: Zir, index: NullTerminatedString) [:0]const u8 { | ||
| 109 | const start = @intFromEnum(index); | ||
| 110 | var end: u32 = start; | ||
| 96 | while (code.string_bytes[end] != 0) { | 111 | while (code.string_bytes[end] != 0) { |
| 97 | end += 1; | 112 | end += 1; |
| 98 | } | 113 | } |
| 99 | return code.string_bytes[index..end :0]; | 114 | return code.string_bytes[start..end :0]; |
| 100 | } | 115 | } |
| 101 | 116 | ||
| 102 | pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref { | 117 | pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref { |
| ... | @@ -2076,6 +2091,7 @@ pub const Inst = struct { | ... | @@ -2076,6 +2091,7 @@ pub const Inst = struct { |
| 2076 | slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type), | 2091 | slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type), |
| 2077 | optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type), | 2092 | optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type), |
| 2078 | anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type), | 2093 | anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type), |
| 2094 | adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type), | ||
| 2079 | generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type), | 2095 | generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type), |
| 2080 | empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type), | 2096 | empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type), |
| 2081 | undef = @intFromEnum(InternPool.Index.undef), | 2097 | undef = @intFromEnum(InternPool.Index.undef), |
src/arch/aarch64/CodeGen.zig+36-31| ... | @@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value; | ... | @@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value; |
| 13 | const TypedValue = @import("../../TypedValue.zig"); | 13 | const TypedValue = @import("../../TypedValue.zig"); |
| 14 | const link = @import("../../link.zig"); | 14 | const link = @import("../../link.zig"); |
| 15 | const Module = @import("../../Module.zig"); | 15 | const Module = @import("../../Module.zig"); |
| 16 | const InternPool = @import("../../InternPool.zig"); | ||
| 16 | const Compilation = @import("../../Compilation.zig"); | 17 | const Compilation = @import("../../Compilation.zig"); |
| 17 | const ErrorMsg = Module.ErrorMsg; | 18 | const ErrorMsg = Module.ErrorMsg; |
| 18 | const Target = std.Target; | 19 | const Target = std.Target; |
| ... | @@ -49,7 +50,8 @@ liveness: Liveness, | ... | @@ -49,7 +50,8 @@ liveness: Liveness, |
| 49 | bin_file: *link.File, | 50 | bin_file: *link.File, |
| 50 | debug_output: DebugInfoOutput, | 51 | debug_output: DebugInfoOutput, |
| 51 | target: *const std.Target, | 52 | target: *const std.Target, |
| 52 | mod_fn: *const Module.Fn, | 53 | func_index: InternPool.Index, |
| 54 | owner_decl: Module.Decl.Index, | ||
| 53 | err_msg: ?*ErrorMsg, | 55 | err_msg: ?*ErrorMsg, |
| 54 | args: []MCValue, | 56 | args: []MCValue, |
| 55 | ret_mcv: MCValue, | 57 | ret_mcv: MCValue, |
| ... | @@ -199,7 +201,7 @@ const DbgInfoReloc = struct { | ... | @@ -199,7 +201,7 @@ const DbgInfoReloc = struct { |
| 199 | else => unreachable, // not a possible argument | 201 | else => unreachable, // not a possible argument |
| 200 | 202 | ||
| 201 | }; | 203 | }; |
| 202 | try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc); | 204 | try dw.genArgDbgInfo(reloc.name, reloc.ty, function.owner_decl, loc); |
| 203 | }, | 205 | }, |
| 204 | .plan9 => {}, | 206 | .plan9 => {}, |
| 205 | .none => {}, | 207 | .none => {}, |
| ... | @@ -245,7 +247,7 @@ const DbgInfoReloc = struct { | ... | @@ -245,7 +247,7 @@ const DbgInfoReloc = struct { |
| 245 | break :blk .nop; | 247 | break :blk .nop; |
| 246 | }, | 248 | }, |
| 247 | }; | 249 | }; |
| 248 | try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc); | 250 | try dw.genVarDbgInfo(reloc.name, reloc.ty, function.owner_decl, is_ptr, loc); |
| 249 | }, | 251 | }, |
| 250 | .plan9 => {}, | 252 | .plan9 => {}, |
| 251 | .none => {}, | 253 | .none => {}, |
| ... | @@ -328,7 +330,7 @@ const Self = @This(); | ... | @@ -328,7 +330,7 @@ const Self = @This(); |
| 328 | pub fn generate( | 330 | pub fn generate( |
| 329 | bin_file: *link.File, | 331 | bin_file: *link.File, |
| 330 | src_loc: Module.SrcLoc, | 332 | src_loc: Module.SrcLoc, |
| 331 | module_fn_index: Module.Fn.Index, | 333 | func_index: InternPool.Index, |
| 332 | air: Air, | 334 | air: Air, |
| 333 | liveness: Liveness, | 335 | liveness: Liveness, |
| 334 | code: *std.ArrayList(u8), | 336 | code: *std.ArrayList(u8), |
| ... | @@ -339,8 +341,8 @@ pub fn generate( | ... | @@ -339,8 +341,8 @@ pub fn generate( |
| 339 | } | 341 | } |
| 340 | 342 | ||
| 341 | const mod = bin_file.options.module.?; | 343 | const mod = bin_file.options.module.?; |
| 342 | const module_fn = mod.funcPtr(module_fn_index); | 344 | const func = mod.funcInfo(func_index); |
| 343 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 345 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 344 | assert(fn_owner_decl.has_tv); | 346 | assert(fn_owner_decl.has_tv); |
| 345 | const fn_type = fn_owner_decl.ty; | 347 | const fn_type = fn_owner_decl.ty; |
| 346 | 348 | ||
| ... | @@ -359,7 +361,8 @@ pub fn generate( | ... | @@ -359,7 +361,8 @@ pub fn generate( |
| 359 | .debug_output = debug_output, | 361 | .debug_output = debug_output, |
| 360 | .target = &bin_file.options.target, | 362 | .target = &bin_file.options.target, |
| 361 | .bin_file = bin_file, | 363 | .bin_file = bin_file, |
| 362 | .mod_fn = module_fn, | 364 | .func_index = func_index, |
| 365 | .owner_decl = func.owner_decl, | ||
| 363 | .err_msg = null, | 366 | .err_msg = null, |
| 364 | .args = undefined, // populated after `resolveCallingConventionValues` | 367 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 365 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` | 368 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| ... | @@ -368,8 +371,8 @@ pub fn generate( | ... | @@ -368,8 +371,8 @@ pub fn generate( |
| 368 | .branch_stack = &branch_stack, | 371 | .branch_stack = &branch_stack, |
| 369 | .src_loc = src_loc, | 372 | .src_loc = src_loc, |
| 370 | .stack_align = undefined, | 373 | .stack_align = undefined, |
| 371 | .end_di_line = module_fn.rbrace_line, | 374 | .end_di_line = func.rbrace_line, |
| 372 | .end_di_column = module_fn.rbrace_column, | 375 | .end_di_column = func.rbrace_column, |
| 373 | }; | 376 | }; |
| 374 | defer function.stack.deinit(bin_file.allocator); | 377 | defer function.stack.deinit(bin_file.allocator); |
| 375 | defer function.blocks.deinit(bin_file.allocator); | 378 | defer function.blocks.deinit(bin_file.allocator); |
| ... | @@ -416,8 +419,8 @@ pub fn generate( | ... | @@ -416,8 +419,8 @@ pub fn generate( |
| 416 | .src_loc = src_loc, | 419 | .src_loc = src_loc, |
| 417 | .code = code, | 420 | .code = code, |
| 418 | .prev_di_pc = 0, | 421 | .prev_di_pc = 0, |
| 419 | .prev_di_line = module_fn.lbrace_line, | 422 | .prev_di_line = func.lbrace_line, |
| 420 | .prev_di_column = module_fn.lbrace_column, | 423 | .prev_di_column = func.lbrace_column, |
| 421 | .stack_size = function.max_end_stack, | 424 | .stack_size = function.max_end_stack, |
| 422 | .saved_regs_stack_space = function.saved_regs_stack_space, | 425 | .saved_regs_stack_space = function.saved_regs_stack_space, |
| 423 | }; | 426 | }; |
| ... | @@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 4011 | const atom_index = switch (self.bin_file.tag) { | 4014 | const atom_index = switch (self.bin_file.tag) { |
| 4012 | .macho => blk: { | 4015 | .macho => blk: { |
| 4013 | const macho_file = self.bin_file.cast(link.File.MachO).?; | 4016 | const macho_file = self.bin_file.cast(link.File.MachO).?; |
| 4014 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 4017 | const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl); |
| 4015 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; | 4018 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 4016 | }, | 4019 | }, |
| 4017 | .coff => blk: { | 4020 | .coff => blk: { |
| 4018 | const coff_file = self.bin_file.cast(link.File.Coff).?; | 4021 | const coff_file = self.bin_file.cast(link.File.Coff).?; |
| 4019 | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 4022 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); |
| 4020 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; | 4023 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 4021 | }, | 4024 | }, |
| 4022 | else => unreachable, // unsupported target format | 4025 | else => unreachable, // unsupported target format |
| ... | @@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 4190 | while (self.args[arg_index] == .none) arg_index += 1; | 4193 | while (self.args[arg_index] == .none) arg_index += 1; |
| 4191 | self.arg_index = arg_index + 1; | 4194 | self.arg_index = arg_index + 1; |
| 4192 | 4195 | ||
| 4196 | const mod = self.bin_file.options.module.?; | ||
| 4193 | const ty = self.typeOfIndex(inst); | 4197 | const ty = self.typeOfIndex(inst); |
| 4194 | const tag = self.air.instructions.items(.tag)[inst]; | 4198 | const tag = self.air.instructions.items(.tag)[inst]; |
| 4195 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; | 4199 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; |
| 4196 | const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index); | 4200 | const name = mod.getParamName(self.func_index, src_index); |
| 4197 | 4201 | ||
| 4198 | try self.dbg_info_relocs.append(self.gpa, .{ | 4202 | try self.dbg_info_relocs.append(self.gpa, .{ |
| 4199 | .tag = tag, | 4203 | .tag = tag, |
| ... | @@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4348 | const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); | 4352 | const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); |
| 4349 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 4353 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4350 | const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name); | 4354 | const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name); |
| 4351 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 4355 | const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl); |
| 4352 | const atom_index = macho_file.getAtom(atom).getSymbolIndex().?; | 4356 | const atom_index = macho_file.getAtom(atom).getSymbolIndex().?; |
| 4353 | _ = try self.addInst(.{ | 4357 | _ = try self.addInst(.{ |
| 4354 | .tag = .call_extern, | 4358 | .tag = .call_extern, |
| ... | @@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { |
| 4617 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 4621 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 4618 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; | 4622 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 4619 | const mod = self.bin_file.options.module.?; | 4623 | const mod = self.bin_file.options.module.?; |
| 4620 | const function = mod.funcPtr(ty_fn.func); | 4624 | const func = mod.funcInfo(ty_fn.func); |
| 4621 | // TODO emit debug info for function change | 4625 | // TODO emit debug info for function change |
| 4622 | _ = function; | 4626 | _ = func; |
| 4623 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | 4627 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); |
| 4624 | } | 4628 | } |
| 4625 | 4629 | ||
| ... | @@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5529 | const atom_index = switch (self.bin_file.tag) { | 5533 | const atom_index = switch (self.bin_file.tag) { |
| 5530 | .macho => blk: { | 5534 | .macho => blk: { |
| 5531 | const macho_file = self.bin_file.cast(link.File.MachO).?; | 5535 | const macho_file = self.bin_file.cast(link.File.MachO).?; |
| 5532 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 5536 | const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl); |
| 5533 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; | 5537 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 5534 | }, | 5538 | }, |
| 5535 | .coff => blk: { | 5539 | .coff => blk: { |
| 5536 | const coff_file = self.bin_file.cast(link.File.Coff).?; | 5540 | const coff_file = self.bin_file.cast(link.File.Coff).?; |
| 5537 | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 5541 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); |
| 5538 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; | 5542 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5539 | }, | 5543 | }, |
| 5540 | else => unreachable, // unsupported target format | 5544 | else => unreachable, // unsupported target format |
| ... | @@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5650 | const atom_index = switch (self.bin_file.tag) { | 5654 | const atom_index = switch (self.bin_file.tag) { |
| 5651 | .macho => blk: { | 5655 | .macho => blk: { |
| 5652 | const macho_file = self.bin_file.cast(link.File.MachO).?; | 5656 | const macho_file = self.bin_file.cast(link.File.MachO).?; |
| 5653 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 5657 | const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl); |
| 5654 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; | 5658 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 5655 | }, | 5659 | }, |
| 5656 | .coff => blk: { | 5660 | .coff => blk: { |
| 5657 | const coff_file = self.bin_file.cast(link.File.Coff).?; | 5661 | const coff_file = self.bin_file.cast(link.File.Coff).?; |
| 5658 | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 5662 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); |
| 5659 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; | 5663 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5660 | }, | 5664 | }, |
| 5661 | else => unreachable, // unsupported target format | 5665 | else => unreachable, // unsupported target format |
| ... | @@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 5847 | const atom_index = switch (self.bin_file.tag) { | 5851 | const atom_index = switch (self.bin_file.tag) { |
| 5848 | .macho => blk: { | 5852 | .macho => blk: { |
| 5849 | const macho_file = self.bin_file.cast(link.File.MachO).?; | 5853 | const macho_file = self.bin_file.cast(link.File.MachO).?; |
| 5850 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 5854 | const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl); |
| 5851 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; | 5855 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 5852 | }, | 5856 | }, |
| 5853 | .coff => blk: { | 5857 | .coff => blk: { |
| 5854 | const coff_file = self.bin_file.cast(link.File.Coff).?; | 5858 | const coff_file = self.bin_file.cast(link.File.Coff).?; |
| 5855 | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 5859 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); |
| 5856 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; | 5860 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5857 | }, | 5861 | }, |
| 5858 | else => unreachable, // unsupported target format | 5862 | else => unreachable, // unsupported target format |
| ... | @@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | ... | @@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 6164 | self.bin_file, | 6168 | self.bin_file, |
| 6165 | self.src_loc, | 6169 | self.src_loc, |
| 6166 | arg_tv, | 6170 | arg_tv, |
| 6167 | self.mod_fn.owner_decl, | 6171 | self.owner_decl, |
| 6168 | )) { | 6172 | )) { |
| 6169 | .mcv => |mcv| switch (mcv) { | 6173 | .mcv => |mcv| switch (mcv) { |
| 6170 | .none => .none, | 6174 | .none => .none, |
| ... | @@ -6198,6 +6202,7 @@ const CallMCValues = struct { | ... | @@ -6198,6 +6202,7 @@ const CallMCValues = struct { |
| 6198 | /// Caller must call `CallMCValues.deinit`. | 6202 | /// Caller must call `CallMCValues.deinit`. |
| 6199 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | 6203 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6200 | const mod = self.bin_file.options.module.?; | 6204 | const mod = self.bin_file.options.module.?; |
| 6205 | const ip = &mod.intern_pool; | ||
| 6201 | const fn_info = mod.typeToFunc(fn_ty).?; | 6206 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 6202 | const cc = fn_info.cc; | 6207 | const cc = fn_info.cc; |
| 6203 | var result: CallMCValues = .{ | 6208 | var result: CallMCValues = .{ |
| ... | @@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6240 | } | 6245 | } |
| 6241 | } | 6246 | } |
| 6242 | 6247 | ||
| 6243 | for (fn_info.param_types, 0..) |ty, i| { | 6248 | for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| { |
| 6244 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); | 6249 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); |
| 6245 | if (param_size == 0) { | 6250 | if (param_size == 0) { |
| 6246 | result.args[i] = .{ .none = {} }; | 6251 | result_arg.* = .{ .none = {} }; |
| 6247 | continue; | 6252 | continue; |
| 6248 | } | 6253 | } |
| 6249 | 6254 | ||
| ... | @@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6256 | 6261 | ||
| 6257 | if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) { | 6262 | if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) { |
| 6258 | if (param_size <= 8) { | 6263 | if (param_size <= 8) { |
| 6259 | result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) }; | 6264 | result_arg.* = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) }; |
| 6260 | ncrn += 1; | 6265 | ncrn += 1; |
| 6261 | } else { | 6266 | } else { |
| 6262 | return self.fail("TODO MCValues with multiple registers", .{}); | 6267 | return self.fail("TODO MCValues with multiple registers", .{}); |
| ... | @@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6273 | } | 6278 | } |
| 6274 | } | 6279 | } |
| 6275 | 6280 | ||
| 6276 | result.args[i] = .{ .stack_argument_offset = nsaa }; | 6281 | result_arg.* = .{ .stack_argument_offset = nsaa }; |
| 6277 | nsaa += param_size; | 6282 | nsaa += param_size; |
| 6278 | } | 6283 | } |
| 6279 | } | 6284 | } |
| ... | @@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6305 | 6310 | ||
| 6306 | var stack_offset: u32 = 0; | 6311 | var stack_offset: u32 = 0; |
| 6307 | 6312 | ||
| 6308 | for (fn_info.param_types, 0..) |ty, i| { | 6313 | for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| { |
| 6309 | if (ty.toType().abiSize(mod) > 0) { | 6314 | if (ty.toType().abiSize(mod) > 0) { |
| 6310 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); | 6315 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); |
| 6311 | const param_alignment = ty.toType().abiAlignment(mod); | 6316 | const param_alignment = ty.toType().abiAlignment(mod); |
| 6312 | 6317 | ||
| 6313 | stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment); | 6318 | stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment); |
| 6314 | result.args[i] = .{ .stack_argument_offset = stack_offset }; | 6319 | result_arg.* = .{ .stack_argument_offset = stack_offset }; |
| 6315 | stack_offset += param_size; | 6320 | stack_offset += param_size; |
| 6316 | } else { | 6321 | } else { |
| 6317 | result.args[i] = .{ .none = {} }; | 6322 | result_arg.* = .{ .none = {} }; |
| 6318 | } | 6323 | } |
| 6319 | } | 6324 | } |
| 6320 | 6325 |
src/arch/arm/CodeGen.zig+27-21| ... | @@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value; | ... | @@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value; |
| 13 | const TypedValue = @import("../../TypedValue.zig"); | 13 | const TypedValue = @import("../../TypedValue.zig"); |
| 14 | const link = @import("../../link.zig"); | 14 | const link = @import("../../link.zig"); |
| 15 | const Module = @import("../../Module.zig"); | 15 | const Module = @import("../../Module.zig"); |
| 16 | const InternPool = @import("../../InternPool.zig"); | ||
| 16 | const Compilation = @import("../../Compilation.zig"); | 17 | const Compilation = @import("../../Compilation.zig"); |
| 17 | const ErrorMsg = Module.ErrorMsg; | 18 | const ErrorMsg = Module.ErrorMsg; |
| 18 | const Target = std.Target; | 19 | const Target = std.Target; |
| ... | @@ -50,7 +51,7 @@ liveness: Liveness, | ... | @@ -50,7 +51,7 @@ liveness: Liveness, |
| 50 | bin_file: *link.File, | 51 | bin_file: *link.File, |
| 51 | debug_output: DebugInfoOutput, | 52 | debug_output: DebugInfoOutput, |
| 52 | target: *const std.Target, | 53 | target: *const std.Target, |
| 53 | mod_fn: *const Module.Fn, | 54 | func_index: InternPool.Index, |
| 54 | err_msg: ?*ErrorMsg, | 55 | err_msg: ?*ErrorMsg, |
| 55 | args: []MCValue, | 56 | args: []MCValue, |
| 56 | ret_mcv: MCValue, | 57 | ret_mcv: MCValue, |
| ... | @@ -258,6 +259,7 @@ const DbgInfoReloc = struct { | ... | @@ -258,6 +259,7 @@ const DbgInfoReloc = struct { |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { | 261 | fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { |
| 262 | const mod = function.bin_file.options.module.?; | ||
| 261 | switch (function.debug_output) { | 263 | switch (function.debug_output) { |
| 262 | .dwarf => |dw| { | 264 | .dwarf => |dw| { |
| 263 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { | 265 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { |
| ... | @@ -278,7 +280,7 @@ const DbgInfoReloc = struct { | ... | @@ -278,7 +280,7 @@ const DbgInfoReloc = struct { |
| 278 | else => unreachable, // not a possible argument | 280 | else => unreachable, // not a possible argument |
| 279 | }; | 281 | }; |
| 280 | 282 | ||
| 281 | try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc); | 283 | try dw.genArgDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), loc); |
| 282 | }, | 284 | }, |
| 283 | .plan9 => {}, | 285 | .plan9 => {}, |
| 284 | .none => {}, | 286 | .none => {}, |
| ... | @@ -286,6 +288,7 @@ const DbgInfoReloc = struct { | ... | @@ -286,6 +288,7 @@ const DbgInfoReloc = struct { |
| 286 | } | 288 | } |
| 287 | 289 | ||
| 288 | fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { | 290 | fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { |
| 291 | const mod = function.bin_file.options.module.?; | ||
| 289 | const is_ptr = switch (reloc.tag) { | 292 | const is_ptr = switch (reloc.tag) { |
| 290 | .dbg_var_ptr => true, | 293 | .dbg_var_ptr => true, |
| 291 | .dbg_var_val => false, | 294 | .dbg_var_val => false, |
| ... | @@ -321,7 +324,7 @@ const DbgInfoReloc = struct { | ... | @@ -321,7 +324,7 @@ const DbgInfoReloc = struct { |
| 321 | break :blk .nop; | 324 | break :blk .nop; |
| 322 | }, | 325 | }, |
| 323 | }; | 326 | }; |
| 324 | try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc); | 327 | try dw.genVarDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), is_ptr, loc); |
| 325 | }, | 328 | }, |
| 326 | .plan9 => {}, | 329 | .plan9 => {}, |
| 327 | .none => {}, | 330 | .none => {}, |
| ... | @@ -334,7 +337,7 @@ const Self = @This(); | ... | @@ -334,7 +337,7 @@ const Self = @This(); |
| 334 | pub fn generate( | 337 | pub fn generate( |
| 335 | bin_file: *link.File, | 338 | bin_file: *link.File, |
| 336 | src_loc: Module.SrcLoc, | 339 | src_loc: Module.SrcLoc, |
| 337 | module_fn_index: Module.Fn.Index, | 340 | func_index: InternPool.Index, |
| 338 | air: Air, | 341 | air: Air, |
| 339 | liveness: Liveness, | 342 | liveness: Liveness, |
| 340 | code: *std.ArrayList(u8), | 343 | code: *std.ArrayList(u8), |
| ... | @@ -345,8 +348,8 @@ pub fn generate( | ... | @@ -345,8 +348,8 @@ pub fn generate( |
| 345 | } | 348 | } |
| 346 | 349 | ||
| 347 | const mod = bin_file.options.module.?; | 350 | const mod = bin_file.options.module.?; |
| 348 | const module_fn = mod.funcPtr(module_fn_index); | 351 | const func = mod.funcInfo(func_index); |
| 349 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 352 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 350 | assert(fn_owner_decl.has_tv); | 353 | assert(fn_owner_decl.has_tv); |
| 351 | const fn_type = fn_owner_decl.ty; | 354 | const fn_type = fn_owner_decl.ty; |
| 352 | 355 | ||
| ... | @@ -365,7 +368,7 @@ pub fn generate( | ... | @@ -365,7 +368,7 @@ pub fn generate( |
| 365 | .target = &bin_file.options.target, | 368 | .target = &bin_file.options.target, |
| 366 | .bin_file = bin_file, | 369 | .bin_file = bin_file, |
| 367 | .debug_output = debug_output, | 370 | .debug_output = debug_output, |
| 368 | .mod_fn = module_fn, | 371 | .func_index = func_index, |
| 369 | .err_msg = null, | 372 | .err_msg = null, |
| 370 | .args = undefined, // populated after `resolveCallingConventionValues` | 373 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 371 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` | 374 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| ... | @@ -374,8 +377,8 @@ pub fn generate( | ... | @@ -374,8 +377,8 @@ pub fn generate( |
| 374 | .branch_stack = &branch_stack, | 377 | .branch_stack = &branch_stack, |
| 375 | .src_loc = src_loc, | 378 | .src_loc = src_loc, |
| 376 | .stack_align = undefined, | 379 | .stack_align = undefined, |
| 377 | .end_di_line = module_fn.rbrace_line, | 380 | .end_di_line = func.rbrace_line, |
| 378 | .end_di_column = module_fn.rbrace_column, | 381 | .end_di_column = func.rbrace_column, |
| 379 | }; | 382 | }; |
| 380 | defer function.stack.deinit(bin_file.allocator); | 383 | defer function.stack.deinit(bin_file.allocator); |
| 381 | defer function.blocks.deinit(bin_file.allocator); | 384 | defer function.blocks.deinit(bin_file.allocator); |
| ... | @@ -422,8 +425,8 @@ pub fn generate( | ... | @@ -422,8 +425,8 @@ pub fn generate( |
| 422 | .src_loc = src_loc, | 425 | .src_loc = src_loc, |
| 423 | .code = code, | 426 | .code = code, |
| 424 | .prev_di_pc = 0, | 427 | .prev_di_pc = 0, |
| 425 | .prev_di_line = module_fn.lbrace_line, | 428 | .prev_di_line = func.lbrace_line, |
| 426 | .prev_di_column = module_fn.lbrace_column, | 429 | .prev_di_column = func.lbrace_column, |
| 427 | .stack_size = function.max_end_stack, | 430 | .stack_size = function.max_end_stack, |
| 428 | .saved_regs_stack_space = function.saved_regs_stack_space, | 431 | .saved_regs_stack_space = function.saved_regs_stack_space, |
| 429 | }; | 432 | }; |
| ... | @@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 4163 | while (self.args[arg_index] == .none) arg_index += 1; | 4166 | while (self.args[arg_index] == .none) arg_index += 1; |
| 4164 | self.arg_index = arg_index + 1; | 4167 | self.arg_index = arg_index + 1; |
| 4165 | 4168 | ||
| 4169 | const mod = self.bin_file.options.module.?; | ||
| 4166 | const ty = self.typeOfIndex(inst); | 4170 | const ty = self.typeOfIndex(inst); |
| 4167 | const tag = self.air.instructions.items(.tag)[inst]; | 4171 | const tag = self.air.instructions.items(.tag)[inst]; |
| 4168 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; | 4172 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; |
| 4169 | const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index); | 4173 | const name = mod.getParamName(self.func_index, src_index); |
| 4170 | 4174 | ||
| 4171 | try self.dbg_info_relocs.append(self.gpa, .{ | 4175 | try self.dbg_info_relocs.append(self.gpa, .{ |
| 4172 | .tag = tag, | 4176 | .tag = tag, |
| ... | @@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { |
| 4569 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 4573 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 4570 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; | 4574 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 4571 | const mod = self.bin_file.options.module.?; | 4575 | const mod = self.bin_file.options.module.?; |
| 4572 | const function = mod.funcPtr(ty_fn.func); | 4576 | const func = mod.funcInfo(ty_fn.func); |
| 4573 | // TODO emit debug info for function change | 4577 | // TODO emit debug info for function change |
| 4574 | _ = function; | 4578 | _ = func; |
| 4575 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | 4579 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); |
| 4576 | } | 4580 | } |
| 4577 | 4581 | ||
| ... | @@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { | ... | @@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 6113 | } | 6117 | } |
| 6114 | 6118 | ||
| 6115 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | 6119 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 6120 | const mod = self.bin_file.options.module.?; | ||
| 6116 | const mcv: MCValue = switch (try codegen.genTypedValue( | 6121 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 6117 | self.bin_file, | 6122 | self.bin_file, |
| 6118 | self.src_loc, | 6123 | self.src_loc, |
| 6119 | arg_tv, | 6124 | arg_tv, |
| 6120 | self.mod_fn.owner_decl, | 6125 | mod.funcOwnerDeclIndex(self.func_index), |
| 6121 | )) { | 6126 | )) { |
| 6122 | .mcv => |mcv| switch (mcv) { | 6127 | .mcv => |mcv| switch (mcv) { |
| 6123 | .none => .none, | 6128 | .none => .none, |
| ... | @@ -6149,6 +6154,7 @@ const CallMCValues = struct { | ... | @@ -6149,6 +6154,7 @@ const CallMCValues = struct { |
| 6149 | /// Caller must call `CallMCValues.deinit`. | 6154 | /// Caller must call `CallMCValues.deinit`. |
| 6150 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | 6155 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6151 | const mod = self.bin_file.options.module.?; | 6156 | const mod = self.bin_file.options.module.?; |
| 6157 | const ip = &mod.intern_pool; | ||
| 6152 | const fn_info = mod.typeToFunc(fn_ty).?; | 6158 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 6153 | const cc = fn_info.cc; | 6159 | const cc = fn_info.cc; |
| 6154 | var result: CallMCValues = .{ | 6160 | var result: CallMCValues = .{ |
| ... | @@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6194 | } | 6200 | } |
| 6195 | } | 6201 | } |
| 6196 | 6202 | ||
| 6197 | for (fn_info.param_types, 0..) |ty, i| { | 6203 | for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| { |
| 6198 | if (ty.toType().abiAlignment(mod) == 8) | 6204 | if (ty.toType().abiAlignment(mod) == 8) |
| 6199 | ncrn = std.mem.alignForward(usize, ncrn, 2); | 6205 | ncrn = std.mem.alignForward(usize, ncrn, 2); |
| 6200 | 6206 | ||
| 6201 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); | 6207 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); |
| 6202 | if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) { | 6208 | if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) { |
| 6203 | if (param_size <= 4) { | 6209 | if (param_size <= 4) { |
| 6204 | result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] }; | 6210 | result_arg.* = .{ .register = c_abi_int_param_regs[ncrn] }; |
| 6205 | ncrn += 1; | 6211 | ncrn += 1; |
| 6206 | } else { | 6212 | } else { |
| 6207 | return self.fail("TODO MCValues with multiple registers", .{}); | 6213 | return self.fail("TODO MCValues with multiple registers", .{}); |
| ... | @@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6213 | if (ty.toType().abiAlignment(mod) == 8) | 6219 | if (ty.toType().abiAlignment(mod) == 8) |
| 6214 | nsaa = std.mem.alignForward(u32, nsaa, 8); | 6220 | nsaa = std.mem.alignForward(u32, nsaa, 8); |
| 6215 | 6221 | ||
| 6216 | result.args[i] = .{ .stack_argument_offset = nsaa }; | 6222 | result_arg.* = .{ .stack_argument_offset = nsaa }; |
| 6217 | nsaa += param_size; | 6223 | nsaa += param_size; |
| 6218 | } | 6224 | } |
| 6219 | } | 6225 | } |
| ... | @@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6244 | 6250 | ||
| 6245 | var stack_offset: u32 = 0; | 6251 | var stack_offset: u32 = 0; |
| 6246 | 6252 | ||
| 6247 | for (fn_info.param_types, 0..) |ty, i| { | 6253 | for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| { |
| 6248 | if (ty.toType().abiSize(mod) > 0) { | 6254 | if (ty.toType().abiSize(mod) > 0) { |
| 6249 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); | 6255 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); |
| 6250 | const param_alignment = ty.toType().abiAlignment(mod); | 6256 | const param_alignment = ty.toType().abiAlignment(mod); |
| 6251 | 6257 | ||
| 6252 | stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment); | 6258 | stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment); |
| 6253 | result.args[i] = .{ .stack_argument_offset = stack_offset }; | 6259 | result_arg.* = .{ .stack_argument_offset = stack_offset }; |
| 6254 | stack_offset += param_size; | 6260 | stack_offset += param_size; |
| 6255 | } else { | 6261 | } else { |
| 6256 | result.args[i] = .{ .none = {} }; | 6262 | result_arg.* = .{ .none = {} }; |
| 6257 | } | 6263 | } |
| 6258 | } | 6264 | } |
| 6259 | 6265 |
src/arch/riscv64/CodeGen.zig+46-37| ... | @@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value; | ... | @@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value; |
| 12 | const TypedValue = @import("../../TypedValue.zig"); | 12 | const TypedValue = @import("../../TypedValue.zig"); |
| 13 | const link = @import("../../link.zig"); | 13 | const link = @import("../../link.zig"); |
| 14 | const Module = @import("../../Module.zig"); | 14 | const Module = @import("../../Module.zig"); |
| 15 | const InternPool = @import("../../InternPool.zig"); | ||
| 15 | const Compilation = @import("../../Compilation.zig"); | 16 | const Compilation = @import("../../Compilation.zig"); |
| 16 | const ErrorMsg = Module.ErrorMsg; | 17 | const ErrorMsg = Module.ErrorMsg; |
| 17 | const Target = std.Target; | 18 | const Target = std.Target; |
| ... | @@ -43,7 +44,7 @@ air: Air, | ... | @@ -43,7 +44,7 @@ air: Air, |
| 43 | liveness: Liveness, | 44 | liveness: Liveness, |
| 44 | bin_file: *link.File, | 45 | bin_file: *link.File, |
| 45 | target: *const std.Target, | 46 | target: *const std.Target, |
| 46 | mod_fn: *const Module.Fn, | 47 | func_index: InternPool.Index, |
| 47 | code: *std.ArrayList(u8), | 48 | code: *std.ArrayList(u8), |
| 48 | debug_output: DebugInfoOutput, | 49 | debug_output: DebugInfoOutput, |
| 49 | err_msg: ?*ErrorMsg, | 50 | err_msg: ?*ErrorMsg, |
| ... | @@ -217,7 +218,7 @@ const Self = @This(); | ... | @@ -217,7 +218,7 @@ const Self = @This(); |
| 217 | pub fn generate( | 218 | pub fn generate( |
| 218 | bin_file: *link.File, | 219 | bin_file: *link.File, |
| 219 | src_loc: Module.SrcLoc, | 220 | src_loc: Module.SrcLoc, |
| 220 | module_fn_index: Module.Fn.Index, | 221 | func_index: InternPool.Index, |
| 221 | air: Air, | 222 | air: Air, |
| 222 | liveness: Liveness, | 223 | liveness: Liveness, |
| 223 | code: *std.ArrayList(u8), | 224 | code: *std.ArrayList(u8), |
| ... | @@ -228,8 +229,8 @@ pub fn generate( | ... | @@ -228,8 +229,8 @@ pub fn generate( |
| 228 | } | 229 | } |
| 229 | 230 | ||
| 230 | const mod = bin_file.options.module.?; | 231 | const mod = bin_file.options.module.?; |
| 231 | const module_fn = mod.funcPtr(module_fn_index); | 232 | const func = mod.funcInfo(func_index); |
| 232 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 233 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 233 | assert(fn_owner_decl.has_tv); | 234 | assert(fn_owner_decl.has_tv); |
| 234 | const fn_type = fn_owner_decl.ty; | 235 | const fn_type = fn_owner_decl.ty; |
| 235 | 236 | ||
| ... | @@ -247,7 +248,7 @@ pub fn generate( | ... | @@ -247,7 +248,7 @@ pub fn generate( |
| 247 | .liveness = liveness, | 248 | .liveness = liveness, |
| 248 | .target = &bin_file.options.target, | 249 | .target = &bin_file.options.target, |
| 249 | .bin_file = bin_file, | 250 | .bin_file = bin_file, |
| 250 | .mod_fn = module_fn, | 251 | .func_index = func_index, |
| 251 | .code = code, | 252 | .code = code, |
| 252 | .debug_output = debug_output, | 253 | .debug_output = debug_output, |
| 253 | .err_msg = null, | 254 | .err_msg = null, |
| ... | @@ -258,8 +259,8 @@ pub fn generate( | ... | @@ -258,8 +259,8 @@ pub fn generate( |
| 258 | .branch_stack = &branch_stack, | 259 | .branch_stack = &branch_stack, |
| 259 | .src_loc = src_loc, | 260 | .src_loc = src_loc, |
| 260 | .stack_align = undefined, | 261 | .stack_align = undefined, |
| 261 | .end_di_line = module_fn.rbrace_line, | 262 | .end_di_line = func.rbrace_line, |
| 262 | .end_di_column = module_fn.rbrace_column, | 263 | .end_di_column = func.rbrace_column, |
| 263 | }; | 264 | }; |
| 264 | defer function.stack.deinit(bin_file.allocator); | 265 | defer function.stack.deinit(bin_file.allocator); |
| 265 | defer function.blocks.deinit(bin_file.allocator); | 266 | defer function.blocks.deinit(bin_file.allocator); |
| ... | @@ -301,8 +302,8 @@ pub fn generate( | ... | @@ -301,8 +302,8 @@ pub fn generate( |
| 301 | .src_loc = src_loc, | 302 | .src_loc = src_loc, |
| 302 | .code = code, | 303 | .code = code, |
| 303 | .prev_di_pc = 0, | 304 | .prev_di_pc = 0, |
| 304 | .prev_di_line = module_fn.lbrace_line, | 305 | .prev_di_line = func.lbrace_line, |
| 305 | .prev_di_column = module_fn.lbrace_column, | 306 | .prev_di_column = func.lbrace_column, |
| 306 | }; | 307 | }; |
| 307 | defer emit.deinit(); | 308 | defer emit.deinit(); |
| 308 | 309 | ||
| ... | @@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1627 | } | 1628 | } |
| 1628 | 1629 | ||
| 1629 | fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { | 1630 | fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { |
| 1631 | const mod = self.bin_file.options.module.?; | ||
| 1630 | const arg = self.air.instructions.items(.data)[inst].arg; | 1632 | const arg = self.air.instructions.items(.data)[inst].arg; |
| 1631 | const ty = self.air.getRefType(arg.ty); | 1633 | const ty = self.air.getRefType(arg.ty); |
| 1632 | const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index); | 1634 | const owner_decl = mod.funcOwnerDeclIndex(self.func_index); |
| 1635 | const name = mod.getParamName(self.func_index, arg.src_index); | ||
| 1633 | 1636 | ||
| 1634 | switch (self.debug_output) { | 1637 | switch (self.debug_output) { |
| 1635 | .dwarf => |dw| switch (mcv) { | 1638 | .dwarf => |dw| switch (mcv) { |
| 1636 | .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{ | 1639 | .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{ |
| 1637 | .register = reg.dwarfLocOp(), | 1640 | .register = reg.dwarfLocOp(), |
| 1638 | }), | 1641 | }), |
| 1639 | .stack_offset => {}, | 1642 | .stack_offset => {}, |
| ... | @@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1742 | } | 1745 | } |
| 1743 | 1746 | ||
| 1744 | if (try self.air.value(callee, mod)) |func_value| { | 1747 | if (try self.air.value(callee, mod)) |func_value| { |
| 1745 | if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| { | 1748 | switch (mod.intern_pool.indexToKey(func_value.ip_index)) { |
| 1746 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); | 1749 | .func => |func| { |
| 1747 | const atom = elf_file.getAtom(atom_index); | 1750 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); |
| 1748 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | 1751 | const atom = elf_file.getAtom(atom_index); |
| 1749 | const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file))); | 1752 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); |
| 1750 | try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr }); | 1753 | const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file))); |
| 1751 | _ = try self.addInst(.{ | 1754 | try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr }); |
| 1752 | .tag = .jalr, | 1755 | _ = try self.addInst(.{ |
| 1753 | .data = .{ .i_type = .{ | 1756 | .tag = .jalr, |
| 1754 | .rd = .ra, | 1757 | .data = .{ .i_type = .{ |
| 1755 | .rs1 = .ra, | 1758 | .rd = .ra, |
| 1756 | .imm12 = 0, | 1759 | .rs1 = .ra, |
| 1757 | } }, | 1760 | .imm12 = 0, |
| 1758 | }); | 1761 | } }, |
| 1759 | } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) { | 1762 | }); |
| 1760 | return self.fail("TODO implement calling extern functions", .{}); | 1763 | }, |
| 1761 | } else { | 1764 | .extern_func => { |
| 1762 | return self.fail("TODO implement calling bitcasted functions", .{}); | 1765 | return self.fail("TODO implement calling extern functions", .{}); |
| 1766 | }, | ||
| 1767 | else => { | ||
| 1768 | return self.fail("TODO implement calling bitcasted functions", .{}); | ||
| 1769 | }, | ||
| 1763 | } | 1770 | } |
| 1764 | } else { | 1771 | } else { |
| 1765 | return self.fail("TODO implement calling runtime-known function pointer", .{}); | 1772 | return self.fail("TODO implement calling runtime-known function pointer", .{}); |
| ... | @@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { |
| 1876 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 1883 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 1877 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; | 1884 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 1878 | const mod = self.bin_file.options.module.?; | 1885 | const mod = self.bin_file.options.module.?; |
| 1879 | const function = mod.funcPtr(ty_fn.func); | 1886 | const func = mod.funcInfo(ty_fn.func); |
| 1880 | // TODO emit debug info for function change | 1887 | // TODO emit debug info for function change |
| 1881 | _ = function; | 1888 | _ = func; |
| 1882 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | 1889 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); |
| 1883 | } | 1890 | } |
| 1884 | 1891 | ||
| ... | @@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { | ... | @@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 2569 | } | 2576 | } |
| 2570 | 2577 | ||
| 2571 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { | 2578 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 2579 | const mod = self.bin_file.options.module.?; | ||
| 2572 | const mcv: MCValue = switch (try codegen.genTypedValue( | 2580 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 2573 | self.bin_file, | 2581 | self.bin_file, |
| 2574 | self.src_loc, | 2582 | self.src_loc, |
| 2575 | typed_value, | 2583 | typed_value, |
| 2576 | self.mod_fn.owner_decl, | 2584 | mod.funcOwnerDeclIndex(self.func_index), |
| 2577 | )) { | 2585 | )) { |
| 2578 | .mcv => |mcv| switch (mcv) { | 2586 | .mcv => |mcv| switch (mcv) { |
| 2579 | .none => .none, | 2587 | .none => .none, |
| ... | @@ -2605,6 +2613,7 @@ const CallMCValues = struct { | ... | @@ -2605,6 +2613,7 @@ const CallMCValues = struct { |
| 2605 | /// Caller must call `CallMCValues.deinit`. | 2613 | /// Caller must call `CallMCValues.deinit`. |
| 2606 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | 2614 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2607 | const mod = self.bin_file.options.module.?; | 2615 | const mod = self.bin_file.options.module.?; |
| 2616 | const ip = &mod.intern_pool; | ||
| 2608 | const fn_info = mod.typeToFunc(fn_ty).?; | 2617 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 2609 | const cc = fn_info.cc; | 2618 | const cc = fn_info.cc; |
| 2610 | var result: CallMCValues = .{ | 2619 | var result: CallMCValues = .{ |
| ... | @@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2636 | var next_stack_offset: u32 = 0; | 2645 | var next_stack_offset: u32 = 0; |
| 2637 | const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 }; | 2646 | const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 }; |
| 2638 | 2647 | ||
| 2639 | for (fn_info.param_types, 0..) |ty, i| { | 2648 | for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| { |
| 2640 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); | 2649 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); |
| 2641 | if (param_size <= 8) { | 2650 | if (param_size <= 8) { |
| 2642 | if (next_register < argument_registers.len) { | 2651 | if (next_register < argument_registers.len) { |
| 2643 | result.args[i] = .{ .register = argument_registers[next_register] }; | 2652 | result_arg.* = .{ .register = argument_registers[next_register] }; |
| 2644 | next_register += 1; | 2653 | next_register += 1; |
| 2645 | } else { | 2654 | } else { |
| 2646 | result.args[i] = .{ .stack_offset = next_stack_offset }; | 2655 | result_arg.* = .{ .stack_offset = next_stack_offset }; |
| 2647 | next_register += next_stack_offset; | 2656 | next_register += next_stack_offset; |
| 2648 | } | 2657 | } |
| 2649 | } else if (param_size <= 16) { | 2658 | } else if (param_size <= 16) { |
| ... | @@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2652 | } else if (next_register < argument_registers.len) { | 2661 | } else if (next_register < argument_registers.len) { |
| 2653 | return self.fail("TODO MCValues split register + stack", .{}); | 2662 | return self.fail("TODO MCValues split register + stack", .{}); |
| 2654 | } else { | 2663 | } else { |
| 2655 | result.args[i] = .{ .stack_offset = next_stack_offset }; | 2664 | result_arg.* = .{ .stack_offset = next_stack_offset }; |
| 2656 | next_register += next_stack_offset; | 2665 | next_register += next_stack_offset; |
| 2657 | } | 2666 | } |
| 2658 | } else { | 2667 | } else { |
| 2659 | result.args[i] = .{ .stack_offset = next_stack_offset }; | 2668 | result_arg.* = .{ .stack_offset = next_stack_offset }; |
| 2660 | next_register += next_stack_offset; | 2669 | next_register += next_stack_offset; |
| 2661 | } | 2670 | } |
| 2662 | } | 2671 | } |
src/arch/sparc64/CodeGen.zig+55-46| ... | @@ -11,6 +11,7 @@ const Allocator = mem.Allocator; | ... | @@ -11,6 +11,7 @@ const Allocator = mem.Allocator; |
| 11 | const builtin = @import("builtin"); | 11 | const builtin = @import("builtin"); |
| 12 | const link = @import("../../link.zig"); | 12 | const link = @import("../../link.zig"); |
| 13 | const Module = @import("../../Module.zig"); | 13 | const Module = @import("../../Module.zig"); |
| 14 | const InternPool = @import("../../InternPool.zig"); | ||
| 14 | const TypedValue = @import("../../TypedValue.zig"); | 15 | const TypedValue = @import("../../TypedValue.zig"); |
| 15 | const ErrorMsg = Module.ErrorMsg; | 16 | const ErrorMsg = Module.ErrorMsg; |
| 16 | const codegen = @import("../../codegen.zig"); | 17 | const codegen = @import("../../codegen.zig"); |
| ... | @@ -52,7 +53,7 @@ air: Air, | ... | @@ -52,7 +53,7 @@ air: Air, |
| 52 | liveness: Liveness, | 53 | liveness: Liveness, |
| 53 | bin_file: *link.File, | 54 | bin_file: *link.File, |
| 54 | target: *const std.Target, | 55 | target: *const std.Target, |
| 55 | mod_fn: *const Module.Fn, | 56 | func_index: InternPool.Index, |
| 56 | code: *std.ArrayList(u8), | 57 | code: *std.ArrayList(u8), |
| 57 | debug_output: DebugInfoOutput, | 58 | debug_output: DebugInfoOutput, |
| 58 | err_msg: ?*ErrorMsg, | 59 | err_msg: ?*ErrorMsg, |
| ... | @@ -260,7 +261,7 @@ const BigTomb = struct { | ... | @@ -260,7 +261,7 @@ const BigTomb = struct { |
| 260 | pub fn generate( | 261 | pub fn generate( |
| 261 | bin_file: *link.File, | 262 | bin_file: *link.File, |
| 262 | src_loc: Module.SrcLoc, | 263 | src_loc: Module.SrcLoc, |
| 263 | module_fn_index: Module.Fn.Index, | 264 | func_index: InternPool.Index, |
| 264 | air: Air, | 265 | air: Air, |
| 265 | liveness: Liveness, | 266 | liveness: Liveness, |
| 266 | code: *std.ArrayList(u8), | 267 | code: *std.ArrayList(u8), |
| ... | @@ -271,8 +272,8 @@ pub fn generate( | ... | @@ -271,8 +272,8 @@ pub fn generate( |
| 271 | } | 272 | } |
| 272 | 273 | ||
| 273 | const mod = bin_file.options.module.?; | 274 | const mod = bin_file.options.module.?; |
| 274 | const module_fn = mod.funcPtr(module_fn_index); | 275 | const func = mod.funcInfo(func_index); |
| 275 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 276 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 276 | assert(fn_owner_decl.has_tv); | 277 | assert(fn_owner_decl.has_tv); |
| 277 | const fn_type = fn_owner_decl.ty; | 278 | const fn_type = fn_owner_decl.ty; |
| 278 | 279 | ||
| ... | @@ -289,8 +290,8 @@ pub fn generate( | ... | @@ -289,8 +290,8 @@ pub fn generate( |
| 289 | .air = air, | 290 | .air = air, |
| 290 | .liveness = liveness, | 291 | .liveness = liveness, |
| 291 | .target = &bin_file.options.target, | 292 | .target = &bin_file.options.target, |
| 293 | .func_index = func_index, | ||
| 292 | .bin_file = bin_file, | 294 | .bin_file = bin_file, |
| 293 | .mod_fn = module_fn, | ||
| 294 | .code = code, | 295 | .code = code, |
| 295 | .debug_output = debug_output, | 296 | .debug_output = debug_output, |
| 296 | .err_msg = null, | 297 | .err_msg = null, |
| ... | @@ -301,8 +302,8 @@ pub fn generate( | ... | @@ -301,8 +302,8 @@ pub fn generate( |
| 301 | .branch_stack = &branch_stack, | 302 | .branch_stack = &branch_stack, |
| 302 | .src_loc = src_loc, | 303 | .src_loc = src_loc, |
| 303 | .stack_align = undefined, | 304 | .stack_align = undefined, |
| 304 | .end_di_line = module_fn.rbrace_line, | 305 | .end_di_line = func.rbrace_line, |
| 305 | .end_di_column = module_fn.rbrace_column, | 306 | .end_di_column = func.rbrace_column, |
| 306 | }; | 307 | }; |
| 307 | defer function.stack.deinit(bin_file.allocator); | 308 | defer function.stack.deinit(bin_file.allocator); |
| 308 | defer function.blocks.deinit(bin_file.allocator); | 309 | defer function.blocks.deinit(bin_file.allocator); |
| ... | @@ -344,8 +345,8 @@ pub fn generate( | ... | @@ -344,8 +345,8 @@ pub fn generate( |
| 344 | .src_loc = src_loc, | 345 | .src_loc = src_loc, |
| 345 | .code = code, | 346 | .code = code, |
| 346 | .prev_di_pc = 0, | 347 | .prev_di_pc = 0, |
| 347 | .prev_di_line = module_fn.lbrace_line, | 348 | .prev_di_line = func.lbrace_line, |
| 348 | .prev_di_column = module_fn.lbrace_column, | 349 | .prev_di_column = func.lbrace_column, |
| 349 | }; | 350 | }; |
| 350 | defer emit.deinit(); | 351 | defer emit.deinit(); |
| 351 | 352 | ||
| ... | @@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1345 | // on linking. | 1346 | // on linking. |
| 1346 | if (try self.air.value(callee, mod)) |func_value| { | 1347 | if (try self.air.value(callee, mod)) |func_value| { |
| 1347 | if (self.bin_file.tag == link.File.Elf.base_tag) { | 1348 | if (self.bin_file.tag == link.File.Elf.base_tag) { |
| 1348 | if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| { | 1349 | switch (mod.intern_pool.indexToKey(func_value.ip_index)) { |
| 1349 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { | 1350 | .func => |func| { |
| 1350 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); | 1351 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 1351 | const atom = elf_file.getAtom(atom_index); | 1352 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); |
| 1352 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | 1353 | const atom = elf_file.getAtom(atom_index); |
| 1353 | break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file))); | 1354 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); |
| 1354 | } else unreachable; | 1355 | break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file))); |
| 1356 | } else unreachable; | ||
| 1355 | 1357 | ||
| 1356 | try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr }); | 1358 | try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr }); |
| 1357 | 1359 | ||
| 1358 | _ = try self.addInst(.{ | 1360 | _ = try self.addInst(.{ |
| 1359 | .tag = .jmpl, | 1361 | .tag = .jmpl, |
| 1360 | .data = .{ | 1362 | .data = .{ |
| 1361 | .arithmetic_3op = .{ | 1363 | .arithmetic_3op = .{ |
| 1362 | .is_imm = false, | 1364 | .is_imm = false, |
| 1363 | .rd = .o7, | 1365 | .rd = .o7, |
| 1364 | .rs1 = .o7, | 1366 | .rs1 = .o7, |
| 1365 | .rs2_or_imm = .{ .rs2 = .g0 }, | 1367 | .rs2_or_imm = .{ .rs2 = .g0 }, |
| 1368 | }, | ||
| 1366 | }, | 1369 | }, |
| 1367 | }, | 1370 | }); |
| 1368 | }); | ||
| 1369 | 1371 | ||
| 1370 | // TODO Find a way to fill this delay slot | 1372 | // TODO Find a way to fill this delay slot |
| 1371 | _ = try self.addInst(.{ | 1373 | _ = try self.addInst(.{ |
| 1372 | .tag = .nop, | 1374 | .tag = .nop, |
| 1373 | .data = .{ .nop = {} }, | 1375 | .data = .{ .nop = {} }, |
| 1374 | }); | 1376 | }); |
| 1375 | } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) { | 1377 | }, |
| 1376 | return self.fail("TODO implement calling extern functions", .{}); | 1378 | .extern_func => { |
| 1377 | } else { | 1379 | return self.fail("TODO implement calling extern functions", .{}); |
| 1378 | return self.fail("TODO implement calling bitcasted functions", .{}); | 1380 | }, |
| 1381 | else => { | ||
| 1382 | return self.fail("TODO implement calling bitcasted functions", .{}); | ||
| 1383 | }, | ||
| 1379 | } | 1384 | } |
| 1380 | } else @panic("TODO SPARCv9 currently does not support non-ELF binaries"); | 1385 | } else @panic("TODO SPARCv9 currently does not support non-ELF binaries"); |
| 1381 | } else { | 1386 | } else { |
| ... | @@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 1660 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 1665 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 1661 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; | 1666 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 1662 | const mod = self.bin_file.options.module.?; | 1667 | const mod = self.bin_file.options.module.?; |
| 1663 | const function = mod.funcPtr(ty_fn.func); | 1668 | const func = mod.funcInfo(ty_fn.func); |
| 1664 | // TODO emit debug info for function change | 1669 | // TODO emit debug info for function change |
| 1665 | _ = function; | 1670 | _ = func; |
| 1666 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | 1671 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); |
| 1667 | } | 1672 | } |
| 1668 | 1673 | ||
| ... | @@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live | ... | @@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live |
| 3595 | } | 3600 | } |
| 3596 | 3601 | ||
| 3597 | fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { | 3602 | fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { |
| 3603 | const mod = self.bin_file.options.module.?; | ||
| 3598 | const arg = self.air.instructions.items(.data)[inst].arg; | 3604 | const arg = self.air.instructions.items(.data)[inst].arg; |
| 3599 | const ty = self.air.getRefType(arg.ty); | 3605 | const ty = self.air.getRefType(arg.ty); |
| 3600 | const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index); | 3606 | const owner_decl = mod.funcOwnerDeclIndex(self.func_index); |
| 3607 | const name = mod.getParamName(self.func_index, arg.src_index); | ||
| 3601 | 3608 | ||
| 3602 | switch (self.debug_output) { | 3609 | switch (self.debug_output) { |
| 3603 | .dwarf => |dw| switch (mcv) { | 3610 | .dwarf => |dw| switch (mcv) { |
| 3604 | .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{ | 3611 | .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{ |
| 3605 | .register = reg.dwarfLocOp(), | 3612 | .register = reg.dwarfLocOp(), |
| 3606 | }), | 3613 | }), |
| 3607 | else => {}, | 3614 | else => {}, |
| ... | @@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re | ... | @@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re |
| 4127 | } | 4134 | } |
| 4128 | 4135 | ||
| 4129 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { | 4136 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 4137 | const mod = self.bin_file.options.module.?; | ||
| 4130 | const mcv: MCValue = switch (try codegen.genTypedValue( | 4138 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 4131 | self.bin_file, | 4139 | self.bin_file, |
| 4132 | self.src_loc, | 4140 | self.src_loc, |
| 4133 | typed_value, | 4141 | typed_value, |
| 4134 | self.mod_fn.owner_decl, | 4142 | mod.funcOwnerDeclIndex(self.func_index), |
| 4135 | )) { | 4143 | )) { |
| 4136 | .mcv => |mcv| switch (mcv) { | 4144 | .mcv => |mcv| switch (mcv) { |
| 4137 | .none => .none, | 4145 | .none => .none, |
| ... | @@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 { | ... | @@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 { |
| 4452 | /// Caller must call `CallMCValues.deinit`. | 4460 | /// Caller must call `CallMCValues.deinit`. |
| 4453 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues { | 4461 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues { |
| 4454 | const mod = self.bin_file.options.module.?; | 4462 | const mod = self.bin_file.options.module.?; |
| 4463 | const ip = &mod.intern_pool; | ||
| 4455 | const fn_info = mod.typeToFunc(fn_ty).?; | 4464 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 4456 | const cc = fn_info.cc; | 4465 | const cc = fn_info.cc; |
| 4457 | var result: CallMCValues = .{ | 4466 | var result: CallMCValues = .{ |
| ... | @@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) | ... | @@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) |
| 4486 | .callee => abi.c_abi_int_param_regs_callee_view, | 4495 | .callee => abi.c_abi_int_param_regs_callee_view, |
| 4487 | }; | 4496 | }; |
| 4488 | 4497 | ||
| 4489 | for (fn_info.param_types, 0..) |ty, i| { | 4498 | for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| { |
| 4490 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); | 4499 | const param_size = @as(u32, @intCast(ty.toType().abiSize(mod))); |
| 4491 | if (param_size <= 8) { | 4500 | if (param_size <= 8) { |
| 4492 | if (next_register < argument_registers.len) { | 4501 | if (next_register < argument_registers.len) { |
| 4493 | result.args[i] = .{ .register = argument_registers[next_register] }; | 4502 | result_arg.* = .{ .register = argument_registers[next_register] }; |
| 4494 | next_register += 1; | 4503 | next_register += 1; |
| 4495 | } else { | 4504 | } else { |
| 4496 | result.args[i] = .{ .stack_offset = next_stack_offset }; | 4505 | result_arg.* = .{ .stack_offset = next_stack_offset }; |
| 4497 | next_register += next_stack_offset; | 4506 | next_register += next_stack_offset; |
| 4498 | } | 4507 | } |
| 4499 | } else if (param_size <= 16) { | 4508 | } else if (param_size <= 16) { |
| ... | @@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) | ... | @@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) |
| 4502 | } else if (next_register < argument_registers.len) { | 4511 | } else if (next_register < argument_registers.len) { |
| 4503 | return self.fail("TODO MCValues split register + stack", .{}); | 4512 | return self.fail("TODO MCValues split register + stack", .{}); |
| 4504 | } else { | 4513 | } else { |
| 4505 | result.args[i] = .{ .stack_offset = next_stack_offset }; | 4514 | result_arg.* = .{ .stack_offset = next_stack_offset }; |
| 4506 | next_register += next_stack_offset; | 4515 | next_register += next_stack_offset; |
| 4507 | } | 4516 | } |
| 4508 | } else { | 4517 | } else { |
| 4509 | result.args[i] = .{ .stack_offset = next_stack_offset }; | 4518 | result_arg.* = .{ .stack_offset = next_stack_offset }; |
| 4510 | next_register += next_stack_offset; | 4519 | next_register += next_stack_offset; |
| 4511 | } | 4520 | } |
| 4512 | } | 4521 | } |
src/arch/wasm/CodeGen.zig+16-12| ... | @@ -650,7 +650,7 @@ air: Air, | ... | @@ -650,7 +650,7 @@ air: Air, |
| 650 | liveness: Liveness, | 650 | liveness: Liveness, |
| 651 | gpa: mem.Allocator, | 651 | gpa: mem.Allocator, |
| 652 | debug_output: codegen.DebugInfoOutput, | 652 | debug_output: codegen.DebugInfoOutput, |
| 653 | mod_fn: *const Module.Fn, | 653 | func_index: InternPool.Index, |
| 654 | /// Contains a list of current branches. | 654 | /// Contains a list of current branches. |
| 655 | /// When we return from a branch, the branch will be popped from this list, | 655 | /// When we return from a branch, the branch will be popped from this list, |
| 656 | /// which means branches can only contain references from within its own branch, | 656 | /// which means branches can only contain references from within its own branch, |
| ... | @@ -1202,7 +1202,7 @@ fn genFunctype( | ... | @@ -1202,7 +1202,7 @@ fn genFunctype( |
| 1202 | pub fn generate( | 1202 | pub fn generate( |
| 1203 | bin_file: *link.File, | 1203 | bin_file: *link.File, |
| 1204 | src_loc: Module.SrcLoc, | 1204 | src_loc: Module.SrcLoc, |
| 1205 | func_index: Module.Fn.Index, | 1205 | func_index: InternPool.Index, |
| 1206 | air: Air, | 1206 | air: Air, |
| 1207 | liveness: Liveness, | 1207 | liveness: Liveness, |
| 1208 | code: *std.ArrayList(u8), | 1208 | code: *std.ArrayList(u8), |
| ... | @@ -1210,7 +1210,7 @@ pub fn generate( | ... | @@ -1210,7 +1210,7 @@ pub fn generate( |
| 1210 | ) codegen.CodeGenError!codegen.Result { | 1210 | ) codegen.CodeGenError!codegen.Result { |
| 1211 | _ = src_loc; | 1211 | _ = src_loc; |
| 1212 | const mod = bin_file.options.module.?; | 1212 | const mod = bin_file.options.module.?; |
| 1213 | const func = mod.funcPtr(func_index); | 1213 | const func = mod.funcInfo(func_index); |
| 1214 | var code_gen: CodeGen = .{ | 1214 | var code_gen: CodeGen = .{ |
| 1215 | .gpa = bin_file.allocator, | 1215 | .gpa = bin_file.allocator, |
| 1216 | .air = air, | 1216 | .air = air, |
| ... | @@ -1223,7 +1223,7 @@ pub fn generate( | ... | @@ -1223,7 +1223,7 @@ pub fn generate( |
| 1223 | .target = bin_file.options.target, | 1223 | .target = bin_file.options.target, |
| 1224 | .bin_file = bin_file.cast(link.File.Wasm).?, | 1224 | .bin_file = bin_file.cast(link.File.Wasm).?, |
| 1225 | .debug_output = debug_output, | 1225 | .debug_output = debug_output, |
| 1226 | .mod_fn = func, | 1226 | .func_index = func_index, |
| 1227 | }; | 1227 | }; |
| 1228 | defer code_gen.deinit(); | 1228 | defer code_gen.deinit(); |
| 1229 | 1229 | ||
| ... | @@ -1237,8 +1237,9 @@ pub fn generate( | ... | @@ -1237,8 +1237,9 @@ pub fn generate( |
| 1237 | 1237 | ||
| 1238 | fn genFunc(func: *CodeGen) InnerError!void { | 1238 | fn genFunc(func: *CodeGen) InnerError!void { |
| 1239 | const mod = func.bin_file.base.options.module.?; | 1239 | const mod = func.bin_file.base.options.module.?; |
| 1240 | const ip = &mod.intern_pool; | ||
| 1240 | const fn_info = mod.typeToFunc(func.decl.ty).?; | 1241 | const fn_info = mod.typeToFunc(func.decl.ty).?; |
| 1241 | var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod); | 1242 | var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod); |
| 1242 | defer func_type.deinit(func.gpa); | 1243 | defer func_type.deinit(func.gpa); |
| 1243 | _ = try func.bin_file.storeDeclType(func.decl_index, func_type); | 1244 | _ = try func.bin_file.storeDeclType(func.decl_index, func_type); |
| 1244 | 1245 | ||
| ... | @@ -1347,6 +1348,7 @@ const CallWValues = struct { | ... | @@ -1347,6 +1348,7 @@ const CallWValues = struct { |
| 1347 | 1348 | ||
| 1348 | fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues { | 1349 | fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues { |
| 1349 | const mod = func.bin_file.base.options.module.?; | 1350 | const mod = func.bin_file.base.options.module.?; |
| 1351 | const ip = &mod.intern_pool; | ||
| 1350 | const fn_info = mod.typeToFunc(fn_ty).?; | 1352 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 1351 | const cc = fn_info.cc; | 1353 | const cc = fn_info.cc; |
| 1352 | var result: CallWValues = .{ | 1354 | var result: CallWValues = .{ |
| ... | @@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV | ... | @@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1369 | 1371 | ||
| 1370 | switch (cc) { | 1372 | switch (cc) { |
| 1371 | .Unspecified => { | 1373 | .Unspecified => { |
| 1372 | for (fn_info.param_types) |ty| { | 1374 | for (fn_info.param_types.get(ip)) |ty| { |
| 1373 | if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) { | 1375 | if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) { |
| 1374 | continue; | 1376 | continue; |
| 1375 | } | 1377 | } |
| ... | @@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV | ... | @@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1379 | } | 1381 | } |
| 1380 | }, | 1382 | }, |
| 1381 | .C => { | 1383 | .C => { |
| 1382 | for (fn_info.param_types) |ty| { | 1384 | for (fn_info.param_types.get(ip)) |ty| { |
| 1383 | const ty_classes = abi.classifyType(ty.toType(), mod); | 1385 | const ty_classes = abi.classifyType(ty.toType(), mod); |
| 1384 | for (ty_classes) |class| { | 1386 | for (ty_classes) |class| { |
| 1385 | if (class == .none) continue; | 1387 | if (class == .none) continue; |
| ... | @@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2185 | const ty = func.typeOf(pl_op.operand); | 2187 | const ty = func.typeOf(pl_op.operand); |
| 2186 | 2188 | ||
| 2187 | const mod = func.bin_file.base.options.module.?; | 2189 | const mod = func.bin_file.base.options.module.?; |
| 2190 | const ip = &mod.intern_pool; | ||
| 2188 | const fn_ty = switch (ty.zigTypeTag(mod)) { | 2191 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| 2189 | .Fn => ty, | 2192 | .Fn => ty, |
| 2190 | .Pointer => ty.childType(mod), | 2193 | .Pointer => ty.childType(mod), |
| ... | @@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2203 | } else if (func_val.getExternFunc(mod)) |extern_func| { | 2206 | } else if (func_val.getExternFunc(mod)) |extern_func| { |
| 2204 | const ext_decl = mod.declPtr(extern_func.decl); | 2207 | const ext_decl = mod.declPtr(extern_func.decl); |
| 2205 | const ext_info = mod.typeToFunc(ext_decl.ty).?; | 2208 | const ext_info = mod.typeToFunc(ext_decl.ty).?; |
| 2206 | var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod); | 2209 | var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), ext_info.return_type.toType(), mod); |
| 2207 | defer func_type.deinit(func.gpa); | 2210 | defer func_type.deinit(func.gpa); |
| 2208 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl); | 2211 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl); |
| 2209 | const atom = func.bin_file.getAtomPtr(atom_index); | 2212 | const atom = func.bin_file.getAtomPtr(atom_index); |
| ... | @@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2253 | const operand = try func.resolveInst(pl_op.operand); | 2256 | const operand = try func.resolveInst(pl_op.operand); |
| 2254 | try func.emitWValue(operand); | 2257 | try func.emitWValue(operand); |
| 2255 | 2258 | ||
| 2256 | var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod); | 2259 | var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod); |
| 2257 | defer fn_type.deinit(func.gpa); | 2260 | defer fn_type.deinit(func.gpa); |
| 2258 | 2261 | ||
| 2259 | const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type); | 2262 | const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type); |
| ... | @@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2564 | switch (func.debug_output) { | 2567 | switch (func.debug_output) { |
| 2565 | .dwarf => |dwarf| { | 2568 | .dwarf => |dwarf| { |
| 2566 | const src_index = func.air.instructions.items(.data)[inst].arg.src_index; | 2569 | const src_index = func.air.instructions.items(.data)[inst].arg.src_index; |
| 2567 | const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, src_index); | 2570 | const name = mod.getParamName(func.func_index, src_index); |
| 2568 | try dwarf.genArgDbgInfo(name, arg_ty, func.mod_fn.owner_decl, .{ | 2571 | try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{ |
| 2569 | .wasm_local = arg.local.value, | 2572 | .wasm_local = arg.local.value, |
| 2570 | }); | 2573 | }); |
| 2571 | }, | 2574 | }, |
| ... | @@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6198 | fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { | 6201 | fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { |
| 6199 | if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{}); | 6202 | if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{}); |
| 6200 | 6203 | ||
| 6204 | const mod = func.bin_file.base.options.module.?; | ||
| 6201 | const pl_op = func.air.instructions.items(.data)[inst].pl_op; | 6205 | const pl_op = func.air.instructions.items(.data)[inst].pl_op; |
| 6202 | const ty = func.typeOf(pl_op.operand); | 6206 | const ty = func.typeOf(pl_op.operand); |
| 6203 | const operand = try func.resolveInst(pl_op.operand); | 6207 | const operand = try func.resolveInst(pl_op.operand); |
| ... | @@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { | ... | @@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { |
| 6214 | break :blk .nop; | 6218 | break :blk .nop; |
| 6215 | }, | 6219 | }, |
| 6216 | }; | 6220 | }; |
| 6217 | try func.debug_output.dwarf.genVarDbgInfo(name, ty, func.mod_fn.owner_decl, is_ptr, loc); | 6221 | try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc); |
| 6218 | 6222 | ||
| 6219 | func.finishAir(inst, .none, &.{}); | 6223 | func.finishAir(inst, .none, &.{}); |
| 6220 | } | 6224 | } |
src/arch/x86_64/CodeGen.zig+23-22| ... | @@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; | ... | @@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; |
| 110 | const RegisterOffset = struct { reg: Register, off: i32 = 0 }; | 110 | const RegisterOffset = struct { reg: Register, off: i32 = 0 }; |
| 111 | 111 | ||
| 112 | const Owner = union(enum) { | 112 | const Owner = union(enum) { |
| 113 | mod_fn: *const Module.Fn, | 113 | func_index: InternPool.Index, |
| 114 | lazy_sym: link.File.LazySymbol, | 114 | lazy_sym: link.File.LazySymbol, |
| 115 | 115 | ||
| 116 | fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index { | 116 | fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index { |
| 117 | return switch (owner) { | 117 | return switch (owner) { |
| 118 | .mod_fn => |mod_fn| mod_fn.owner_decl, | 118 | .func_index => |func_index| mod.funcOwnerDeclIndex(func_index), |
| 119 | .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod), | 119 | .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod), |
| 120 | }; | 120 | }; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 { | 123 | fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 { |
| 124 | switch (owner) { | 124 | switch (owner) { |
| 125 | .mod_fn => |mod_fn| { | 125 | .func_index => |func_index| { |
| 126 | const decl_index = mod_fn.owner_decl; | 126 | const mod = ctx.bin_file.options.module.?; |
| 127 | const decl_index = mod.funcOwnerDeclIndex(func_index); | ||
| 127 | if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { | 128 | if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { |
| 128 | const atom = try macho_file.getOrCreateAtomForDecl(decl_index); | 129 | const atom = try macho_file.getOrCreateAtomForDecl(decl_index); |
| 129 | return macho_file.getAtom(atom).getSymbolIndex().?; | 130 | return macho_file.getAtom(atom).getSymbolIndex().?; |
| ... | @@ -638,7 +639,7 @@ const Self = @This(); | ... | @@ -638,7 +639,7 @@ const Self = @This(); |
| 638 | pub fn generate( | 639 | pub fn generate( |
| 639 | bin_file: *link.File, | 640 | bin_file: *link.File, |
| 640 | src_loc: Module.SrcLoc, | 641 | src_loc: Module.SrcLoc, |
| 641 | module_fn_index: Module.Fn.Index, | 642 | func_index: InternPool.Index, |
| 642 | air: Air, | 643 | air: Air, |
| 643 | liveness: Liveness, | 644 | liveness: Liveness, |
| 644 | code: *std.ArrayList(u8), | 645 | code: *std.ArrayList(u8), |
| ... | @@ -649,8 +650,8 @@ pub fn generate( | ... | @@ -649,8 +650,8 @@ pub fn generate( |
| 649 | } | 650 | } |
| 650 | 651 | ||
| 651 | const mod = bin_file.options.module.?; | 652 | const mod = bin_file.options.module.?; |
| 652 | const module_fn = mod.funcPtr(module_fn_index); | 653 | const func = mod.funcInfo(func_index); |
| 653 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 654 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 654 | assert(fn_owner_decl.has_tv); | 655 | assert(fn_owner_decl.has_tv); |
| 655 | const fn_type = fn_owner_decl.ty; | 656 | const fn_type = fn_owner_decl.ty; |
| 656 | 657 | ||
| ... | @@ -662,15 +663,15 @@ pub fn generate( | ... | @@ -662,15 +663,15 @@ pub fn generate( |
| 662 | .target = &bin_file.options.target, | 663 | .target = &bin_file.options.target, |
| 663 | .bin_file = bin_file, | 664 | .bin_file = bin_file, |
| 664 | .debug_output = debug_output, | 665 | .debug_output = debug_output, |
| 665 | .owner = .{ .mod_fn = module_fn }, | 666 | .owner = .{ .func_index = func_index }, |
| 666 | .err_msg = null, | 667 | .err_msg = null, |
| 667 | .args = undefined, // populated after `resolveCallingConventionValues` | 668 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 668 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` | 669 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| 669 | .fn_type = fn_type, | 670 | .fn_type = fn_type, |
| 670 | .arg_index = 0, | 671 | .arg_index = 0, |
| 671 | .src_loc = src_loc, | 672 | .src_loc = src_loc, |
| 672 | .end_di_line = module_fn.rbrace_line, | 673 | .end_di_line = func.rbrace_line, |
| 673 | .end_di_column = module_fn.rbrace_column, | 674 | .end_di_column = func.rbrace_column, |
| 674 | }; | 675 | }; |
| 675 | defer { | 676 | defer { |
| 676 | function.frame_allocs.deinit(gpa); | 677 | function.frame_allocs.deinit(gpa); |
| ... | @@ -687,17 +688,16 @@ pub fn generate( | ... | @@ -687,17 +688,16 @@ pub fn generate( |
| 687 | if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa); | 688 | if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa); |
| 688 | } | 689 | } |
| 689 | 690 | ||
| 690 | wip_mir_log.debug("{}:", .{function.fmtDecl(module_fn.owner_decl)}); | 691 | wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)}); |
| 692 | |||
| 693 | const ip = &mod.intern_pool; | ||
| 691 | 694 | ||
| 692 | try function.frame_allocs.resize(gpa, FrameIndex.named_count); | 695 | try function.frame_allocs.resize(gpa, FrameIndex.named_count); |
| 693 | function.frame_allocs.set( | 696 | function.frame_allocs.set( |
| 694 | @intFromEnum(FrameIndex.stack_frame), | 697 | @intFromEnum(FrameIndex.stack_frame), |
| 695 | FrameAlloc.init(.{ | 698 | FrameAlloc.init(.{ |
| 696 | .size = 0, | 699 | .size = 0, |
| 697 | .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack| | 700 | .alignment = @intCast(func.analysis(ip).stack_alignment.toByteUnitsOptional() orelse 1), |
| 698 | @intCast(set_align_stack.alignment.toByteUnitsOptional().?) | ||
| 699 | else | ||
| 700 | 1, | ||
| 701 | }), | 701 | }), |
| 702 | ); | 702 | ); |
| 703 | function.frame_allocs.set( | 703 | function.frame_allocs.set( |
| ... | @@ -761,8 +761,8 @@ pub fn generate( | ... | @@ -761,8 +761,8 @@ pub fn generate( |
| 761 | .debug_output = debug_output, | 761 | .debug_output = debug_output, |
| 762 | .code = code, | 762 | .code = code, |
| 763 | .prev_di_pc = 0, | 763 | .prev_di_pc = 0, |
| 764 | .prev_di_line = module_fn.lbrace_line, | 764 | .prev_di_line = func.lbrace_line, |
| 765 | .prev_di_column = module_fn.lbrace_column, | 765 | .prev_di_column = func.lbrace_column, |
| 766 | }; | 766 | }; |
| 767 | defer emit.deinit(); | 767 | defer emit.deinit(); |
| 768 | emit.emitMir() catch |err| switch (err) { | 768 | emit.emitMir() catch |err| switch (err) { |
| ... | @@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 7942 | 7942 | ||
| 7943 | const ty = self.typeOfIndex(inst); | 7943 | const ty = self.typeOfIndex(inst); |
| 7944 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; | 7944 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; |
| 7945 | const name = self.owner.mod_fn.getParamName(mod, src_index); | 7945 | const name = mod.getParamName(self.owner.func_index, src_index); |
| 7946 | try self.genArgDbgInfo(ty, name, dst_mcv); | 7946 | try self.genArgDbgInfo(ty, name, dst_mcv); |
| 7947 | 7947 | ||
| 7948 | break :result dst_mcv; | 7948 | break :result dst_mcv; |
| ... | @@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8139 | if (try self.air.value(callee, mod)) |func_value| { | 8139 | if (try self.air.value(callee, mod)) |func_value| { |
| 8140 | const func_key = mod.intern_pool.indexToKey(func_value.ip_index); | 8140 | const func_key = mod.intern_pool.indexToKey(func_value.ip_index); |
| 8141 | if (switch (func_key) { | 8141 | if (switch (func_key) { |
| 8142 | .func => |func| mod.funcPtr(func.index).owner_decl, | 8142 | .func => |func| func.owner_decl, |
| 8143 | .ptr => |ptr| switch (ptr.addr) { | 8143 | .ptr => |ptr| switch (ptr.addr) { |
| 8144 | .decl => |decl| decl, | 8144 | .decl => |decl| decl, |
| 8145 | else => null, | 8145 | else => null, |
| ... | @@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { |
| 8582 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { | 8582 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 8583 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; | 8583 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 8584 | const mod = self.bin_file.options.module.?; | 8584 | const mod = self.bin_file.options.module.?; |
| 8585 | const function = mod.funcPtr(ty_fn.func); | 8585 | const func = mod.funcInfo(ty_fn.func); |
| 8586 | // TODO emit debug info for function change | 8586 | // TODO emit debug info for function change |
| 8587 | _ = function; | 8587 | _ = func; |
| 8588 | return self.finishAir(inst, .unreach, .{ .none, .none, .none }); | 8588 | return self.finishAir(inst, .unreach, .{ .none, .none, .none }); |
| 8589 | } | 8589 | } |
| 8590 | 8590 | ||
| ... | @@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues( | ... | @@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues( |
| 11719 | stack_frame_base: FrameIndex, | 11719 | stack_frame_base: FrameIndex, |
| 11720 | ) !CallMCValues { | 11720 | ) !CallMCValues { |
| 11721 | const mod = self.bin_file.options.module.?; | 11721 | const mod = self.bin_file.options.module.?; |
| 11722 | const ip = &mod.intern_pool; | ||
| 11722 | const cc = fn_info.cc; | 11723 | const cc = fn_info.cc; |
| 11723 | const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len); | 11724 | const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len); |
| 11724 | defer self.gpa.free(param_types); | 11725 | defer self.gpa.free(param_types); |
| 11725 | 11726 | ||
| 11726 | for (param_types[0..fn_info.param_types.len], fn_info.param_types) |*dest, src| { | 11727 | for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| { |
| 11727 | dest.* = src.toType(); | 11728 | dest.* = src.toType(); |
| 11728 | } | 11729 | } |
| 11729 | // TODO: promote var arg types | 11730 | // TODO: promote var arg types |
src/codegen.zig+1-1| ... | @@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) { | ... | @@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) { |
| 67 | pub fn generateFunction( | 67 | pub fn generateFunction( |
| 68 | bin_file: *link.File, | 68 | bin_file: *link.File, |
| 69 | src_loc: Module.SrcLoc, | 69 | src_loc: Module.SrcLoc, |
| 70 | func_index: Module.Fn.Index, | 70 | func_index: InternPool.Index, |
| 71 | air: Air, | 71 | air: Air, |
| 72 | liveness: Liveness, | 72 | liveness: Liveness, |
| 73 | code: *std.ArrayList(u8), | 73 | code: *std.ArrayList(u8), |
src/codegen/c.zig+15-8| ... | @@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { | ... | @@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { |
| 257 | return .{ .data = ident }; | 257 | return .{ .data = ident }; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | /// This data is available when outputting .c code for a `Module.Fn.Index`. | 260 | /// This data is available when outputting .c code for a `InternPool.Index` |
| 261 | /// that corresponds to `func`. | ||
| 261 | /// It is not available when generating .h file. | 262 | /// It is not available when generating .h file. |
| 262 | pub const Function = struct { | 263 | pub const Function = struct { |
| 263 | air: Air, | 264 | air: Air, |
| ... | @@ -268,7 +269,7 @@ pub const Function = struct { | ... | @@ -268,7 +269,7 @@ pub const Function = struct { |
| 268 | next_block_index: usize = 0, | 269 | next_block_index: usize = 0, |
| 269 | object: Object, | 270 | object: Object, |
| 270 | lazy_fns: LazyFnMap, | 271 | lazy_fns: LazyFnMap, |
| 271 | func_index: Module.Fn.Index, | 272 | func_index: InternPool.Index, |
| 272 | /// All the locals, to be emitted at the top of the function. | 273 | /// All the locals, to be emitted at the top of the function. |
| 273 | locals: std.ArrayListUnmanaged(Local) = .{}, | 274 | locals: std.ArrayListUnmanaged(Local) = .{}, |
| 274 | /// Which locals are available for reuse, based on Type. | 275 | /// Which locals are available for reuse, based on Type. |
| ... | @@ -1487,6 +1488,7 @@ pub const DeclGen = struct { | ... | @@ -1487,6 +1488,7 @@ pub const DeclGen = struct { |
| 1487 | ) !void { | 1488 | ) !void { |
| 1488 | const store = &dg.ctypes.set; | 1489 | const store = &dg.ctypes.set; |
| 1489 | const mod = dg.module; | 1490 | const mod = dg.module; |
| 1491 | const ip = &mod.intern_pool; | ||
| 1490 | 1492 | ||
| 1491 | const fn_decl = mod.declPtr(fn_decl_index); | 1493 | const fn_decl = mod.declPtr(fn_decl_index); |
| 1492 | const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind); | 1494 | const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind); |
| ... | @@ -1499,7 +1501,7 @@ pub const DeclGen = struct { | ... | @@ -1499,7 +1501,7 @@ pub const DeclGen = struct { |
| 1499 | else => unreachable, | 1501 | else => unreachable, |
| 1500 | } | 1502 | } |
| 1501 | } | 1503 | } |
| 1502 | if (fn_decl.val.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold "); | 1504 | if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold "); |
| 1503 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); | 1505 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); |
| 1504 | 1506 | ||
| 1505 | const trailing = try renderTypePrefix( | 1507 | const trailing = try renderTypePrefix( |
| ... | @@ -1744,7 +1746,7 @@ pub const DeclGen = struct { | ... | @@ -1744,7 +1746,7 @@ pub const DeclGen = struct { |
| 1744 | return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) { | 1746 | return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) { |
| 1745 | .variable => |variable| mod.decl_exports.contains(variable.decl), | 1747 | .variable => |variable| mod.decl_exports.contains(variable.decl), |
| 1746 | .extern_func => true, | 1748 | .extern_func => true, |
| 1747 | .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl), | 1749 | .func => |func| mod.decl_exports.contains(func.owner_decl), |
| 1748 | else => unreachable, | 1750 | else => unreachable, |
| 1749 | }; | 1751 | }; |
| 1750 | } | 1752 | } |
| ... | @@ -1800,7 +1802,12 @@ pub const DeclGen = struct { | ... | @@ -1800,7 +1802,12 @@ pub const DeclGen = struct { |
| 1800 | } | 1802 | } |
| 1801 | } | 1803 | } |
| 1802 | 1804 | ||
| 1803 | fn writeCValueMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { | 1805 | fn writeCValueMember( |
| 1806 | dg: *DeclGen, | ||
| 1807 | writer: anytype, | ||
| 1808 | c_value: CValue, | ||
| 1809 | member: CValue, | ||
| 1810 | ) error{ OutOfMemory, AnalysisFail }!void { | ||
| 1804 | try dg.writeCValue(writer, c_value); | 1811 | try dg.writeCValue(writer, c_value); |
| 1805 | try writer.writeByte('.'); | 1812 | try writer.writeByte('.'); |
| 1806 | try dg.writeCValue(writer, member); | 1813 | try dg.writeCValue(writer, member); |
| ... | @@ -4161,7 +4168,7 @@ fn airCall( | ... | @@ -4161,7 +4168,7 @@ fn airCall( |
| 4161 | const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known; | 4168 | const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known; |
| 4162 | break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) { | 4169 | break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) { |
| 4163 | .extern_func => |extern_func| extern_func.decl, | 4170 | .extern_func => |extern_func| extern_func.decl, |
| 4164 | .func => |func| mod.funcPtr(func.index).owner_decl, | 4171 | .func => |func| func.owner_decl, |
| 4165 | .ptr => |ptr| switch (ptr.addr) { | 4172 | .ptr => |ptr| switch (ptr.addr) { |
| 4166 | .decl => |decl| decl, | 4173 | .decl => |decl| decl, |
| 4167 | else => break :known, | 4174 | else => break :known, |
| ... | @@ -4238,9 +4245,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4238,9 +4245,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4238 | const ty_fn = f.air.instructions.items(.data)[inst].ty_fn; | 4245 | const ty_fn = f.air.instructions.items(.data)[inst].ty_fn; |
| 4239 | const mod = f.object.dg.module; | 4246 | const mod = f.object.dg.module; |
| 4240 | const writer = f.object.writer(); | 4247 | const writer = f.object.writer(); |
| 4241 | const function = mod.funcPtr(ty_fn.func); | 4248 | const owner_decl = mod.funcOwnerDeclPtr(ty_fn.func); |
| 4242 | try writer.print("/* dbg func:{s} */\n", .{ | 4249 | try writer.print("/* dbg func:{s} */\n", .{ |
| 4243 | mod.intern_pool.stringToSlice(mod.declPtr(function.owner_decl).name), | 4250 | mod.intern_pool.stringToSlice(owner_decl.name), |
| 4244 | }); | 4251 | }); |
| 4245 | return .none; | 4252 | return .none; |
| 4246 | } | 4253 | } |
src/codegen/c/type.zig+9-5| ... | @@ -1722,6 +1722,7 @@ pub const CType = extern union { | ... | @@ -1722,6 +1722,7 @@ pub const CType = extern union { |
| 1722 | 1722 | ||
| 1723 | .Fn => { | 1723 | .Fn => { |
| 1724 | const info = mod.typeToFunc(ty).?; | 1724 | const info = mod.typeToFunc(ty).?; |
| 1725 | const ip = &mod.intern_pool; | ||
| 1725 | if (!info.is_generic) { | 1726 | if (!info.is_generic) { |
| 1726 | if (lookup.isMutable()) { | 1727 | if (lookup.isMutable()) { |
| 1727 | const param_kind: Kind = switch (kind) { | 1728 | const param_kind: Kind = switch (kind) { |
| ... | @@ -1730,7 +1731,7 @@ pub const CType = extern union { | ... | @@ -1730,7 +1731,7 @@ pub const CType = extern union { |
| 1730 | .payload => unreachable, | 1731 | .payload => unreachable, |
| 1731 | }; | 1732 | }; |
| 1732 | _ = try lookup.typeToIndex(info.return_type.toType(), param_kind); | 1733 | _ = try lookup.typeToIndex(info.return_type.toType(), param_kind); |
| 1733 | for (info.param_types) |param_type| { | 1734 | for (info.param_types.get(ip)) |param_type| { |
| 1734 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; | 1735 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1735 | _ = try lookup.typeToIndex(param_type.toType(), param_kind); | 1736 | _ = try lookup.typeToIndex(param_type.toType(), param_kind); |
| 1736 | } | 1737 | } |
| ... | @@ -2014,6 +2015,7 @@ pub const CType = extern union { | ... | @@ -2014,6 +2015,7 @@ pub const CType = extern union { |
| 2014 | .function, | 2015 | .function, |
| 2015 | .varargs_function, | 2016 | .varargs_function, |
| 2016 | => { | 2017 | => { |
| 2018 | const ip = &mod.intern_pool; | ||
| 2017 | const info = mod.typeToFunc(ty).?; | 2019 | const info = mod.typeToFunc(ty).?; |
| 2018 | assert(!info.is_generic); | 2020 | assert(!info.is_generic); |
| 2019 | const param_kind: Kind = switch (kind) { | 2021 | const param_kind: Kind = switch (kind) { |
| ... | @@ -2023,14 +2025,14 @@ pub const CType = extern union { | ... | @@ -2023,14 +2025,14 @@ pub const CType = extern union { |
| 2023 | }; | 2025 | }; |
| 2024 | 2026 | ||
| 2025 | var c_params_len: usize = 0; | 2027 | var c_params_len: usize = 0; |
| 2026 | for (info.param_types) |param_type| { | 2028 | for (info.param_types.get(ip)) |param_type| { |
| 2027 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; | 2029 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2028 | c_params_len += 1; | 2030 | c_params_len += 1; |
| 2029 | } | 2031 | } |
| 2030 | 2032 | ||
| 2031 | const params_pl = try arena.alloc(Index, c_params_len); | 2033 | const params_pl = try arena.alloc(Index, c_params_len); |
| 2032 | var c_param_i: usize = 0; | 2034 | var c_param_i: usize = 0; |
| 2033 | for (info.param_types) |param_type| { | 2035 | for (info.param_types.get(ip)) |param_type| { |
| 2034 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; | 2036 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2035 | params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?; | 2037 | params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?; |
| 2036 | c_param_i += 1; | 2038 | c_param_i += 1; |
| ... | @@ -2147,6 +2149,7 @@ pub const CType = extern union { | ... | @@ -2147,6 +2149,7 @@ pub const CType = extern union { |
| 2147 | => { | 2149 | => { |
| 2148 | if (ty.zigTypeTag(mod) != .Fn) return false; | 2150 | if (ty.zigTypeTag(mod) != .Fn) return false; |
| 2149 | 2151 | ||
| 2152 | const ip = &mod.intern_pool; | ||
| 2150 | const info = mod.typeToFunc(ty).?; | 2153 | const info = mod.typeToFunc(ty).?; |
| 2151 | assert(!info.is_generic); | 2154 | assert(!info.is_generic); |
| 2152 | const data = cty.cast(Payload.Function).?.data; | 2155 | const data = cty.cast(Payload.Function).?.data; |
| ... | @@ -2160,7 +2163,7 @@ pub const CType = extern union { | ... | @@ -2160,7 +2163,7 @@ pub const CType = extern union { |
| 2160 | return false; | 2163 | return false; |
| 2161 | 2164 | ||
| 2162 | var c_param_i: usize = 0; | 2165 | var c_param_i: usize = 0; |
| 2163 | for (info.param_types) |param_type| { | 2166 | for (info.param_types.get(ip)) |param_type| { |
| 2164 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; | 2167 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2165 | 2168 | ||
| 2166 | if (c_param_i >= data.param_types.len) return false; | 2169 | if (c_param_i >= data.param_types.len) return false; |
| ... | @@ -2202,6 +2205,7 @@ pub const CType = extern union { | ... | @@ -2202,6 +2205,7 @@ pub const CType = extern union { |
| 2202 | autoHash(hasher, t); | 2205 | autoHash(hasher, t); |
| 2203 | 2206 | ||
| 2204 | const mod = self.lookup.getModule(); | 2207 | const mod = self.lookup.getModule(); |
| 2208 | const ip = &mod.intern_pool; | ||
| 2205 | switch (t) { | 2209 | switch (t) { |
| 2206 | .fwd_anon_struct, | 2210 | .fwd_anon_struct, |
| 2207 | .fwd_anon_union, | 2211 | .fwd_anon_union, |
| ... | @@ -2270,7 +2274,7 @@ pub const CType = extern union { | ... | @@ -2270,7 +2274,7 @@ pub const CType = extern union { |
| 2270 | }; | 2274 | }; |
| 2271 | 2275 | ||
| 2272 | self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind); | 2276 | self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind); |
| 2273 | for (info.param_types) |param_type| { | 2277 | for (info.param_types.get(ip)) |param_type| { |
| 2274 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; | 2278 | if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2275 | self.updateHasherRecurse(hasher, param_type.toType(), param_kind); | 2279 | self.updateHasherRecurse(hasher, param_type.toType(), param_kind); |
| 2276 | } | 2280 | } |
src/codegen/llvm.zig+75-68| ... | @@ -867,14 +867,15 @@ pub const Object = struct { | ... | @@ -867,14 +867,15 @@ pub const Object = struct { |
| 867 | pub fn updateFunc( | 867 | pub fn updateFunc( |
| 868 | o: *Object, | 868 | o: *Object, |
| 869 | mod: *Module, | 869 | mod: *Module, |
| 870 | func_index: Module.Fn.Index, | 870 | func_index: InternPool.Index, |
| 871 | air: Air, | 871 | air: Air, |
| 872 | liveness: Liveness, | 872 | liveness: Liveness, |
| 873 | ) !void { | 873 | ) !void { |
| 874 | const func = mod.funcPtr(func_index); | 874 | const func = mod.funcInfo(func_index); |
| 875 | const decl_index = func.owner_decl; | 875 | const decl_index = func.owner_decl; |
| 876 | const decl = mod.declPtr(decl_index); | 876 | const decl = mod.declPtr(decl_index); |
| 877 | const target = mod.getTarget(); | 877 | const target = mod.getTarget(); |
| 878 | const ip = &mod.intern_pool; | ||
| 878 | 879 | ||
| 879 | var dg: DeclGen = .{ | 880 | var dg: DeclGen = .{ |
| 880 | .object = o, | 881 | .object = o, |
| ... | @@ -885,24 +886,23 @@ pub const Object = struct { | ... | @@ -885,24 +886,23 @@ pub const Object = struct { |
| 885 | 886 | ||
| 886 | const llvm_func = try o.resolveLlvmFunction(decl_index); | 887 | const llvm_func = try o.resolveLlvmFunction(decl_index); |
| 887 | 888 | ||
| 888 | if (mod.align_stack_fns.get(func_index)) |align_info| { | 889 | if (func.analysis(ip).is_noinline) { |
| 889 | o.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?); | ||
| 890 | o.addFnAttr(llvm_func, "noinline"); | 890 | o.addFnAttr(llvm_func, "noinline"); |
| 891 | } else { | 891 | } else { |
| 892 | Object.removeFnAttr(llvm_func, "alignstack"); | 892 | Object.removeFnAttr(llvm_func, "noinline"); |
| 893 | if (!func.is_noinline) Object.removeFnAttr(llvm_func, "noinline"); | ||
| 894 | } | 893 | } |
| 895 | 894 | ||
| 896 | if (func.is_cold) { | 895 | if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| { |
| 897 | o.addFnAttr(llvm_func, "cold"); | 896 | o.addFnAttrInt(llvm_func, "alignstack", alignment); |
| 897 | o.addFnAttr(llvm_func, "noinline"); | ||
| 898 | } else { | 898 | } else { |
| 899 | Object.removeFnAttr(llvm_func, "cold"); | 899 | Object.removeFnAttr(llvm_func, "alignstack"); |
| 900 | } | 900 | } |
| 901 | 901 | ||
| 902 | if (func.is_noinline) { | 902 | if (func.analysis(ip).is_cold) { |
| 903 | o.addFnAttr(llvm_func, "noinline"); | 903 | o.addFnAttr(llvm_func, "cold"); |
| 904 | } else { | 904 | } else { |
| 905 | Object.removeFnAttr(llvm_func, "noinline"); | 905 | Object.removeFnAttr(llvm_func, "cold"); |
| 906 | } | 906 | } |
| 907 | 907 | ||
| 908 | // TODO: disable this if safety is off for the function scope | 908 | // TODO: disable this if safety is off for the function scope |
| ... | @@ -921,7 +921,7 @@ pub const Object = struct { | ... | @@ -921,7 +921,7 @@ pub const Object = struct { |
| 921 | o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); | 921 | o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); |
| 922 | } | 922 | } |
| 923 | 923 | ||
| 924 | if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| | 924 | if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| |
| 925 | llvm_func.setSection(section); | 925 | llvm_func.setSection(section); |
| 926 | 926 | ||
| 927 | // Remove all the basic blocks of a function in order to start over, generating | 927 | // Remove all the basic blocks of a function in order to start over, generating |
| ... | @@ -968,7 +968,7 @@ pub const Object = struct { | ... | @@ -968,7 +968,7 @@ pub const Object = struct { |
| 968 | .byval => { | 968 | .byval => { |
| 969 | assert(!it.byval_attr); | 969 | assert(!it.byval_attr); |
| 970 | const param_index = it.zig_index - 1; | 970 | const param_index = it.zig_index - 1; |
| 971 | const param_ty = fn_info.param_types[param_index].toType(); | 971 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 972 | const param = llvm_func.getParam(llvm_arg_i); | 972 | const param = llvm_func.getParam(llvm_arg_i); |
| 973 | try args.ensureUnusedCapacity(1); | 973 | try args.ensureUnusedCapacity(1); |
| 974 | 974 | ||
| ... | @@ -987,7 +987,7 @@ pub const Object = struct { | ... | @@ -987,7 +987,7 @@ pub const Object = struct { |
| 987 | llvm_arg_i += 1; | 987 | llvm_arg_i += 1; |
| 988 | }, | 988 | }, |
| 989 | .byref => { | 989 | .byref => { |
| 990 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 990 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 991 | const param_llvm_ty = try o.lowerType(param_ty); | 991 | const param_llvm_ty = try o.lowerType(param_ty); |
| 992 | const param = llvm_func.getParam(llvm_arg_i); | 992 | const param = llvm_func.getParam(llvm_arg_i); |
| 993 | const alignment = param_ty.abiAlignment(mod); | 993 | const alignment = param_ty.abiAlignment(mod); |
| ... | @@ -1006,7 +1006,7 @@ pub const Object = struct { | ... | @@ -1006,7 +1006,7 @@ pub const Object = struct { |
| 1006 | } | 1006 | } |
| 1007 | }, | 1007 | }, |
| 1008 | .byref_mut => { | 1008 | .byref_mut => { |
| 1009 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 1009 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1010 | const param_llvm_ty = try o.lowerType(param_ty); | 1010 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1011 | const param = llvm_func.getParam(llvm_arg_i); | 1011 | const param = llvm_func.getParam(llvm_arg_i); |
| 1012 | const alignment = param_ty.abiAlignment(mod); | 1012 | const alignment = param_ty.abiAlignment(mod); |
| ... | @@ -1026,7 +1026,7 @@ pub const Object = struct { | ... | @@ -1026,7 +1026,7 @@ pub const Object = struct { |
| 1026 | }, | 1026 | }, |
| 1027 | .abi_sized_int => { | 1027 | .abi_sized_int => { |
| 1028 | assert(!it.byval_attr); | 1028 | assert(!it.byval_attr); |
| 1029 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 1029 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1030 | const param = llvm_func.getParam(llvm_arg_i); | 1030 | const param = llvm_func.getParam(llvm_arg_i); |
| 1031 | llvm_arg_i += 1; | 1031 | llvm_arg_i += 1; |
| 1032 | 1032 | ||
| ... | @@ -1053,7 +1053,7 @@ pub const Object = struct { | ... | @@ -1053,7 +1053,7 @@ pub const Object = struct { |
| 1053 | }, | 1053 | }, |
| 1054 | .slice => { | 1054 | .slice => { |
| 1055 | assert(!it.byval_attr); | 1055 | assert(!it.byval_attr); |
| 1056 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 1056 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1057 | const ptr_info = param_ty.ptrInfo(mod); | 1057 | const ptr_info = param_ty.ptrInfo(mod); |
| 1058 | 1058 | ||
| 1059 | if (math.cast(u5, it.zig_index - 1)) |i| { | 1059 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| ... | @@ -1083,7 +1083,7 @@ pub const Object = struct { | ... | @@ -1083,7 +1083,7 @@ pub const Object = struct { |
| 1083 | .multiple_llvm_types => { | 1083 | .multiple_llvm_types => { |
| 1084 | assert(!it.byval_attr); | 1084 | assert(!it.byval_attr); |
| 1085 | const field_types = it.llvm_types_buffer[0..it.llvm_types_len]; | 1085 | const field_types = it.llvm_types_buffer[0..it.llvm_types_len]; |
| 1086 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 1086 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1087 | const param_llvm_ty = try o.lowerType(param_ty); | 1087 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1088 | const param_alignment = param_ty.abiAlignment(mod); | 1088 | const param_alignment = param_ty.abiAlignment(mod); |
| 1089 | const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target); | 1089 | const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target); |
| ... | @@ -1114,7 +1114,7 @@ pub const Object = struct { | ... | @@ -1114,7 +1114,7 @@ pub const Object = struct { |
| 1114 | args.appendAssumeCapacity(casted); | 1114 | args.appendAssumeCapacity(casted); |
| 1115 | }, | 1115 | }, |
| 1116 | .float_array => { | 1116 | .float_array => { |
| 1117 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 1117 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1118 | const param_llvm_ty = try o.lowerType(param_ty); | 1118 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1119 | const param = llvm_func.getParam(llvm_arg_i); | 1119 | const param = llvm_func.getParam(llvm_arg_i); |
| 1120 | llvm_arg_i += 1; | 1120 | llvm_arg_i += 1; |
| ... | @@ -1132,7 +1132,7 @@ pub const Object = struct { | ... | @@ -1132,7 +1132,7 @@ pub const Object = struct { |
| 1132 | } | 1132 | } |
| 1133 | }, | 1133 | }, |
| 1134 | .i32_array, .i64_array => { | 1134 | .i32_array, .i64_array => { |
| 1135 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 1135 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1136 | const param_llvm_ty = try o.lowerType(param_ty); | 1136 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1137 | const param = llvm_func.getParam(llvm_arg_i); | 1137 | const param = llvm_func.getParam(llvm_arg_i); |
| 1138 | llvm_arg_i += 1; | 1138 | llvm_arg_i += 1; |
| ... | @@ -1168,7 +1168,7 @@ pub const Object = struct { | ... | @@ -1168,7 +1168,7 @@ pub const Object = struct { |
| 1168 | const decl_di_ty = try o.lowerDebugType(decl.ty, .full); | 1168 | const decl_di_ty = try o.lowerDebugType(decl.ty, .full); |
| 1169 | const subprogram = dib.createFunction( | 1169 | const subprogram = dib.createFunction( |
| 1170 | di_file.?.toScope(), | 1170 | di_file.?.toScope(), |
| 1171 | mod.intern_pool.stringToSlice(decl.name), | 1171 | ip.stringToSlice(decl.name), |
| 1172 | llvm_func.getValueName(), | 1172 | llvm_func.getValueName(), |
| 1173 | di_file.?, | 1173 | di_file.?, |
| 1174 | line_number, | 1174 | line_number, |
| ... | @@ -1460,6 +1460,7 @@ pub const Object = struct { | ... | @@ -1460,6 +1460,7 @@ pub const Object = struct { |
| 1460 | const target = o.target; | 1460 | const target = o.target; |
| 1461 | const dib = o.di_builder.?; | 1461 | const dib = o.di_builder.?; |
| 1462 | const mod = o.module; | 1462 | const mod = o.module; |
| 1463 | const ip = &mod.intern_pool; | ||
| 1463 | switch (ty.zigTypeTag(mod)) { | 1464 | switch (ty.zigTypeTag(mod)) { |
| 1464 | .Void, .NoReturn => { | 1465 | .Void, .NoReturn => { |
| 1465 | const di_type = dib.createBasicType("void", 0, DW.ATE.signed); | 1466 | const di_type = dib.createBasicType("void", 0, DW.ATE.signed); |
| ... | @@ -1492,7 +1493,6 @@ pub const Object = struct { | ... | @@ -1492,7 +1493,6 @@ pub const Object = struct { |
| 1492 | return enum_di_ty; | 1493 | return enum_di_ty; |
| 1493 | } | 1494 | } |
| 1494 | 1495 | ||
| 1495 | const ip = &mod.intern_pool; | ||
| 1496 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 1496 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; |
| 1497 | 1497 | ||
| 1498 | const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len); | 1498 | const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len); |
| ... | @@ -1518,7 +1518,7 @@ pub const Object = struct { | ... | @@ -1518,7 +1518,7 @@ pub const Object = struct { |
| 1518 | if (@sizeOf(usize) == @sizeOf(u64)) { | 1518 | if (@sizeOf(usize) == @sizeOf(u64)) { |
| 1519 | enumerators[i] = dib.createEnumerator2( | 1519 | enumerators[i] = dib.createEnumerator2( |
| 1520 | field_name_z, | 1520 | field_name_z, |
| 1521 | @as(c_uint, @intCast(bigint.limbs.len)), | 1521 | @intCast(bigint.limbs.len), |
| 1522 | bigint.limbs.ptr, | 1522 | bigint.limbs.ptr, |
| 1523 | int_info.bits, | 1523 | int_info.bits, |
| 1524 | int_info.signedness == .unsigned, | 1524 | int_info.signedness == .unsigned, |
| ... | @@ -2320,8 +2320,8 @@ pub const Object = struct { | ... | @@ -2320,8 +2320,8 @@ pub const Object = struct { |
| 2320 | try param_di_types.append(try o.lowerDebugType(ptr_ty, .full)); | 2320 | try param_di_types.append(try o.lowerDebugType(ptr_ty, .full)); |
| 2321 | } | 2321 | } |
| 2322 | 2322 | ||
| 2323 | for (0..mod.typeToFunc(ty).?.param_types.len) |i| { | 2323 | for (0..fn_info.param_types.len) |i| { |
| 2324 | const param_ty = mod.typeToFunc(ty).?.param_types[i].toType(); | 2324 | const param_ty = fn_info.param_types.get(ip)[i].toType(); |
| 2325 | if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 2325 | if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2326 | 2326 | ||
| 2327 | if (isByRef(param_ty, mod)) { | 2327 | if (isByRef(param_ty, mod)) { |
| ... | @@ -2475,9 +2475,10 @@ pub const Object = struct { | ... | @@ -2475,9 +2475,10 @@ pub const Object = struct { |
| 2475 | const fn_type = try o.lowerType(zig_fn_type); | 2475 | const fn_type = try o.lowerType(zig_fn_type); |
| 2476 | 2476 | ||
| 2477 | const fqn = try decl.getFullyQualifiedName(mod); | 2477 | const fqn = try decl.getFullyQualifiedName(mod); |
| 2478 | const ip = &mod.intern_pool; | ||
| 2478 | 2479 | ||
| 2479 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); | 2480 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| 2480 | const llvm_fn = o.llvm_module.addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace); | 2481 | const llvm_fn = o.llvm_module.addFunctionInAddressSpace(ip.stringToSlice(fqn), fn_type, llvm_addrspace); |
| 2481 | gop.value_ptr.* = llvm_fn; | 2482 | gop.value_ptr.* = llvm_fn; |
| 2482 | 2483 | ||
| 2483 | const is_extern = decl.isExtern(mod); | 2484 | const is_extern = decl.isExtern(mod); |
| ... | @@ -2486,8 +2487,8 @@ pub const Object = struct { | ... | @@ -2486,8 +2487,8 @@ pub const Object = struct { |
| 2486 | llvm_fn.setUnnamedAddr(.True); | 2487 | llvm_fn.setUnnamedAddr(.True); |
| 2487 | } else { | 2488 | } else { |
| 2488 | if (target.isWasm()) { | 2489 | if (target.isWasm()) { |
| 2489 | o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name)); | 2490 | o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name)); |
| 2490 | if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { | 2491 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { |
| 2491 | if (!std.mem.eql(u8, lib_name, "c")) { | 2492 | if (!std.mem.eql(u8, lib_name, "c")) { |
| 2492 | o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); | 2493 | o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); |
| 2493 | } | 2494 | } |
| ... | @@ -2546,13 +2547,13 @@ pub const Object = struct { | ... | @@ -2546,13 +2547,13 @@ pub const Object = struct { |
| 2546 | while (it.next()) |lowering| switch (lowering) { | 2547 | while (it.next()) |lowering| switch (lowering) { |
| 2547 | .byval => { | 2548 | .byval => { |
| 2548 | const param_index = it.zig_index - 1; | 2549 | const param_index = it.zig_index - 1; |
| 2549 | const param_ty = fn_info.param_types[param_index].toType(); | 2550 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 2550 | if (!isByRef(param_ty, mod)) { | 2551 | if (!isByRef(param_ty, mod)) { |
| 2551 | o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); | 2552 | o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 2552 | } | 2553 | } |
| 2553 | }, | 2554 | }, |
| 2554 | .byref => { | 2555 | .byref => { |
| 2555 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 2556 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1]; |
| 2556 | const param_llvm_ty = try o.lowerType(param_ty.toType()); | 2557 | const param_llvm_ty = try o.lowerType(param_ty.toType()); |
| 2557 | const alignment = param_ty.toType().abiAlignment(mod); | 2558 | const alignment = param_ty.toType().abiAlignment(mod); |
| 2558 | o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | 2559 | o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| ... | @@ -3031,6 +3032,7 @@ pub const Object = struct { | ... | @@ -3031,6 +3032,7 @@ pub const Object = struct { |
| 3031 | 3032 | ||
| 3032 | fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type { | 3033 | fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type { |
| 3033 | const mod = o.module; | 3034 | const mod = o.module; |
| 3035 | const ip = &mod.intern_pool; | ||
| 3034 | const fn_info = mod.typeToFunc(fn_ty).?; | 3036 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 3035 | const llvm_ret_ty = try lowerFnRetTy(o, fn_info); | 3037 | const llvm_ret_ty = try lowerFnRetTy(o, fn_info); |
| 3036 | 3038 | ||
| ... | @@ -3052,19 +3054,19 @@ pub const Object = struct { | ... | @@ -3052,19 +3054,19 @@ pub const Object = struct { |
| 3052 | while (it.next()) |lowering| switch (lowering) { | 3054 | while (it.next()) |lowering| switch (lowering) { |
| 3053 | .no_bits => continue, | 3055 | .no_bits => continue, |
| 3054 | .byval => { | 3056 | .byval => { |
| 3055 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 3057 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 3056 | try llvm_params.append(try o.lowerType(param_ty)); | 3058 | try llvm_params.append(try o.lowerType(param_ty)); |
| 3057 | }, | 3059 | }, |
| 3058 | .byref, .byref_mut => { | 3060 | .byref, .byref_mut => { |
| 3059 | try llvm_params.append(o.context.pointerType(0)); | 3061 | try llvm_params.append(o.context.pointerType(0)); |
| 3060 | }, | 3062 | }, |
| 3061 | .abi_sized_int => { | 3063 | .abi_sized_int => { |
| 3062 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 3064 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 3063 | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); | 3065 | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); |
| 3064 | try llvm_params.append(o.context.intType(abi_size * 8)); | 3066 | try llvm_params.append(o.context.intType(abi_size * 8)); |
| 3065 | }, | 3067 | }, |
| 3066 | .slice => { | 3068 | .slice => { |
| 3067 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 3069 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 3068 | const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional) | 3070 | const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional) |
| 3069 | param_ty.optionalChild(mod).slicePtrFieldType(mod) | 3071 | param_ty.optionalChild(mod).slicePtrFieldType(mod) |
| 3070 | else | 3072 | else |
| ... | @@ -3083,7 +3085,7 @@ pub const Object = struct { | ... | @@ -3083,7 +3085,7 @@ pub const Object = struct { |
| 3083 | try llvm_params.append(o.context.intType(16)); | 3085 | try llvm_params.append(o.context.intType(16)); |
| 3084 | }, | 3086 | }, |
| 3085 | .float_array => |count| { | 3087 | .float_array => |count| { |
| 3086 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 3088 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 3087 | const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?); | 3089 | const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?); |
| 3088 | const field_count = @as(c_uint, @intCast(count)); | 3090 | const field_count = @as(c_uint, @intCast(count)); |
| 3089 | const arr_ty = float_ty.arrayType(field_count); | 3091 | const arr_ty = float_ty.arrayType(field_count); |
| ... | @@ -3137,8 +3139,7 @@ pub const Object = struct { | ... | @@ -3137,8 +3139,7 @@ pub const Object = struct { |
| 3137 | return llvm_type.getUndef(); | 3139 | return llvm_type.getUndef(); |
| 3138 | } | 3140 | } |
| 3139 | 3141 | ||
| 3140 | const val_key = mod.intern_pool.indexToKey(tv.val.toIntern()); | 3142 | switch (mod.intern_pool.indexToKey(tv.val.toIntern())) { |
| 3141 | switch (val_key) { | ||
| 3142 | .int_type, | 3143 | .int_type, |
| 3143 | .ptr_type, | 3144 | .ptr_type, |
| 3144 | .array_type, | 3145 | .array_type, |
| ... | @@ -3175,12 +3176,14 @@ pub const Object = struct { | ... | @@ -3175,12 +3176,14 @@ pub const Object = struct { |
| 3175 | .enum_literal, | 3176 | .enum_literal, |
| 3176 | .empty_enum_value, | 3177 | .empty_enum_value, |
| 3177 | => unreachable, // non-runtime values | 3178 | => unreachable, // non-runtime values |
| 3178 | .extern_func, .func => { | 3179 | .extern_func => |extern_func| { |
| 3179 | const fn_decl_index = switch (val_key) { | 3180 | const fn_decl_index = extern_func.decl; |
| 3180 | .extern_func => |extern_func| extern_func.decl, | 3181 | const fn_decl = mod.declPtr(fn_decl_index); |
| 3181 | .func => |func| mod.funcPtr(func.index).owner_decl, | 3182 | try mod.markDeclAlive(fn_decl); |
| 3182 | else => unreachable, | 3183 | return o.resolveLlvmFunction(fn_decl_index); |
| 3183 | }; | 3184 | }, |
| 3185 | .func => |func| { | ||
| 3186 | const fn_decl_index = func.owner_decl; | ||
| 3184 | const fn_decl = mod.declPtr(fn_decl_index); | 3187 | const fn_decl = mod.declPtr(fn_decl_index); |
| 3185 | try mod.markDeclAlive(fn_decl); | 3188 | try mod.markDeclAlive(fn_decl); |
| 3186 | return o.resolveLlvmFunction(fn_decl_index); | 3189 | return o.resolveLlvmFunction(fn_decl_index); |
| ... | @@ -4598,6 +4601,7 @@ pub const FuncGen = struct { | ... | @@ -4598,6 +4601,7 @@ pub const FuncGen = struct { |
| 4598 | const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len])); | 4601 | const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len])); |
| 4599 | const o = self.dg.object; | 4602 | const o = self.dg.object; |
| 4600 | const mod = o.module; | 4603 | const mod = o.module; |
| 4604 | const ip = &mod.intern_pool; | ||
| 4601 | const callee_ty = self.typeOf(pl_op.operand); | 4605 | const callee_ty = self.typeOf(pl_op.operand); |
| 4602 | const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) { | 4606 | const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) { |
| 4603 | .Fn => callee_ty, | 4607 | .Fn => callee_ty, |
| ... | @@ -4801,14 +4805,14 @@ pub const FuncGen = struct { | ... | @@ -4801,14 +4805,14 @@ pub const FuncGen = struct { |
| 4801 | while (it.next()) |lowering| switch (lowering) { | 4805 | while (it.next()) |lowering| switch (lowering) { |
| 4802 | .byval => { | 4806 | .byval => { |
| 4803 | const param_index = it.zig_index - 1; | 4807 | const param_index = it.zig_index - 1; |
| 4804 | const param_ty = fn_info.param_types[param_index].toType(); | 4808 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 4805 | if (!isByRef(param_ty, mod)) { | 4809 | if (!isByRef(param_ty, mod)) { |
| 4806 | o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1); | 4810 | o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 4807 | } | 4811 | } |
| 4808 | }, | 4812 | }, |
| 4809 | .byref => { | 4813 | .byref => { |
| 4810 | const param_index = it.zig_index - 1; | 4814 | const param_index = it.zig_index - 1; |
| 4811 | const param_ty = fn_info.param_types[param_index].toType(); | 4815 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 4812 | const param_llvm_ty = try o.lowerType(param_ty); | 4816 | const param_llvm_ty = try o.lowerType(param_ty); |
| 4813 | const alignment = param_ty.abiAlignment(mod); | 4817 | const alignment = param_ty.abiAlignment(mod); |
| 4814 | o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | 4818 | o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| ... | @@ -4828,7 +4832,7 @@ pub const FuncGen = struct { | ... | @@ -4828,7 +4832,7 @@ pub const FuncGen = struct { |
| 4828 | 4832 | ||
| 4829 | .slice => { | 4833 | .slice => { |
| 4830 | assert(!it.byval_attr); | 4834 | assert(!it.byval_attr); |
| 4831 | const param_ty = fn_info.param_types[it.zig_index - 1].toType(); | 4835 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 4832 | const ptr_info = param_ty.ptrInfo(mod); | 4836 | const ptr_info = param_ty.ptrInfo(mod); |
| 4833 | const llvm_arg_i = it.llvm_index - 2; | 4837 | const llvm_arg_i = it.llvm_index - 2; |
| 4834 | 4838 | ||
| ... | @@ -4930,7 +4934,7 @@ pub const FuncGen = struct { | ... | @@ -4930,7 +4934,7 @@ pub const FuncGen = struct { |
| 4930 | fg.context.pointerType(0).constNull(), | 4934 | fg.context.pointerType(0).constNull(), |
| 4931 | null_opt_addr_global, | 4935 | null_opt_addr_global, |
| 4932 | }; | 4936 | }; |
| 4933 | const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?; | 4937 | const panic_func = mod.funcInfo(mod.panic_func_index); |
| 4934 | const panic_decl = mod.declPtr(panic_func.owner_decl); | 4938 | const panic_decl = mod.declPtr(panic_func.owner_decl); |
| 4935 | const fn_info = mod.typeToFunc(panic_decl.ty).?; | 4939 | const fn_info = mod.typeToFunc(panic_decl.ty).?; |
| 4936 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl); | 4940 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl); |
| ... | @@ -6030,7 +6034,7 @@ pub const FuncGen = struct { | ... | @@ -6030,7 +6034,7 @@ pub const FuncGen = struct { |
| 6030 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; | 6034 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 6031 | 6035 | ||
| 6032 | const mod = o.module; | 6036 | const mod = o.module; |
| 6033 | const func = mod.funcPtr(ty_fn.func); | 6037 | const func = mod.funcInfo(ty_fn.func); |
| 6034 | const decl_index = func.owner_decl; | 6038 | const decl_index = func.owner_decl; |
| 6035 | const decl = mod.declPtr(decl_index); | 6039 | const decl = mod.declPtr(decl_index); |
| 6036 | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); | 6040 | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); |
| ... | @@ -6039,7 +6043,7 @@ pub const FuncGen = struct { | ... | @@ -6039,7 +6043,7 @@ pub const FuncGen = struct { |
| 6039 | const cur_debug_location = self.builder.getCurrentDebugLocation2(); | 6043 | const cur_debug_location = self.builder.getCurrentDebugLocation2(); |
| 6040 | 6044 | ||
| 6041 | try self.dbg_inlined.append(self.gpa, .{ | 6045 | try self.dbg_inlined.append(self.gpa, .{ |
| 6042 | .loc = @as(*llvm.DILocation, @ptrCast(cur_debug_location)), | 6046 | .loc = @ptrCast(cur_debug_location), |
| 6043 | .scope = self.di_scope.?, | 6047 | .scope = self.di_scope.?, |
| 6044 | .base_line = self.base_line, | 6048 | .base_line = self.base_line, |
| 6045 | }); | 6049 | }); |
| ... | @@ -6057,8 +6061,6 @@ pub const FuncGen = struct { | ... | @@ -6057,8 +6061,6 @@ pub const FuncGen = struct { |
| 6057 | .is_var_args = false, | 6061 | .is_var_args = false, |
| 6058 | .is_generic = false, | 6062 | .is_generic = false, |
| 6059 | .is_noinline = false, | 6063 | .is_noinline = false, |
| 6060 | .align_is_generic = false, | ||
| 6061 | .cc_is_generic = false, | ||
| 6062 | .section_is_generic = false, | 6064 | .section_is_generic = false, |
| 6063 | .addrspace_is_generic = false, | 6065 | .addrspace_is_generic = false, |
| 6064 | }); | 6066 | }); |
| ... | @@ -6090,8 +6092,7 @@ pub const FuncGen = struct { | ... | @@ -6090,8 +6092,7 @@ pub const FuncGen = struct { |
| 6090 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; | 6092 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 6091 | 6093 | ||
| 6092 | const mod = o.module; | 6094 | const mod = o.module; |
| 6093 | const func = mod.funcPtr(ty_fn.func); | 6095 | const decl = mod.funcOwnerDeclPtr(ty_fn.func); |
| 6094 | const decl = mod.declPtr(func.owner_decl); | ||
| 6095 | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); | 6096 | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); |
| 6096 | self.di_file = di_file; | 6097 | self.di_file = di_file; |
| 6097 | const old = self.dbg_inlined.pop(); | 6098 | const old = self.dbg_inlined.pop(); |
| ... | @@ -8137,12 +8138,13 @@ pub const FuncGen = struct { | ... | @@ -8137,12 +8138,13 @@ pub const FuncGen = struct { |
| 8137 | } | 8138 | } |
| 8138 | 8139 | ||
| 8139 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; | 8140 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; |
| 8140 | const func = self.dg.decl.getOwnedFunction(mod).?; | 8141 | const func_index = self.dg.decl.getOwnedFunctionIndex(); |
| 8142 | const func = mod.funcInfo(func_index); | ||
| 8141 | const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1; | 8143 | const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1; |
| 8142 | const lbrace_col = func.lbrace_column + 1; | 8144 | const lbrace_col = func.lbrace_column + 1; |
| 8143 | const di_local_var = dib.createParameterVariable( | 8145 | const di_local_var = dib.createParameterVariable( |
| 8144 | self.di_scope.?, | 8146 | self.di_scope.?, |
| 8145 | func.getParamName(mod, src_index).ptr, // TODO test 0 bit args | 8147 | mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args |
| 8146 | self.di_file.?, | 8148 | self.di_file.?, |
| 8147 | lbrace_line, | 8149 | lbrace_line, |
| 8148 | try o.lowerDebugType(inst_ty, .full), | 8150 | try o.lowerDebugType(inst_ty, .full), |
| ... | @@ -10653,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField { | ... | @@ -10653,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField { |
| 10653 | } | 10655 | } |
| 10654 | 10656 | ||
| 10655 | fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool { | 10657 | fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool { |
| 10656 | if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false; | 10658 | const return_type = fn_info.return_type.toType(); |
| 10659 | if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) return false; | ||
| 10657 | 10660 | ||
| 10658 | const target = mod.getTarget(); | 10661 | const target = mod.getTarget(); |
| 10659 | switch (fn_info.cc) { | 10662 | switch (fn_info.cc) { |
| 10660 | .Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod), | 10663 | .Unspecified, .Inline => return isByRef(return_type, mod), |
| 10661 | .C => switch (target.cpu.arch) { | 10664 | .C => switch (target.cpu.arch) { |
| 10662 | .mips, .mipsel => return false, | 10665 | .mips, .mipsel => return false, |
| 10663 | .x86_64 => switch (target.os.tag) { | 10666 | .x86_64 => switch (target.os.tag) { |
| 10664 | .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory, | 10667 | .windows => return x86_64_abi.classifyWindows(return_type, mod) == .memory, |
| 10665 | else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod), | 10668 | else => return firstParamSRetSystemV(return_type, mod), |
| 10666 | }, | 10669 | }, |
| 10667 | .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect, | 10670 | .wasm32 => return wasm_c_abi.classifyType(return_type, mod)[0] == .indirect, |
| 10668 | .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory, | 10671 | .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(return_type, mod) == .memory, |
| 10669 | .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) { | 10672 | .arm, .armeb => switch (arm_c_abi.classifyType(return_type, mod, .ret)) { |
| 10670 | .memory, .i64_array => return true, | 10673 | .memory, .i64_array => return true, |
| 10671 | .i32_array => |size| return size != 1, | 10674 | .i32_array => |size| return size != 1, |
| 10672 | .byval => return false, | 10675 | .byval => return false, |
| 10673 | }, | 10676 | }, |
| 10674 | .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory, | 10677 | .riscv32, .riscv64 => return riscv_c_abi.classifyType(return_type, mod) == .memory, |
| 10675 | else => return false, // TODO investigate C ABI for other architectures | 10678 | else => return false, // TODO investigate C ABI for other architectures |
| 10676 | }, | 10679 | }, |
| 10677 | .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod), | 10680 | .SysV => return firstParamSRetSystemV(return_type, mod), |
| 10678 | .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory, | 10681 | .Win64 => return x86_64_abi.classifyWindows(return_type, mod) == .memory, |
| 10679 | .Stdcall => return !isScalar(mod, fn_info.return_type.toType()), | 10682 | .Stdcall => return !isScalar(mod, return_type), |
| 10680 | else => return false, | 10683 | else => return false, |
| 10681 | } | 10684 | } |
| 10682 | } | 10685 | } |
| ... | @@ -10888,13 +10891,17 @@ const ParamTypeIterator = struct { | ... | @@ -10888,13 +10891,17 @@ const ParamTypeIterator = struct { |
| 10888 | 10891 | ||
| 10889 | pub fn next(it: *ParamTypeIterator) ?Lowering { | 10892 | pub fn next(it: *ParamTypeIterator) ?Lowering { |
| 10890 | if (it.zig_index >= it.fn_info.param_types.len) return null; | 10893 | if (it.zig_index >= it.fn_info.param_types.len) return null; |
| 10891 | const ty = it.fn_info.param_types[it.zig_index]; | 10894 | const mod = it.object.module; |
| 10895 | const ip = &mod.intern_pool; | ||
| 10896 | const ty = it.fn_info.param_types.get(ip)[it.zig_index]; | ||
| 10892 | it.byval_attr = false; | 10897 | it.byval_attr = false; |
| 10893 | return nextInner(it, ty.toType()); | 10898 | return nextInner(it, ty.toType()); |
| 10894 | } | 10899 | } |
| 10895 | 10900 | ||
| 10896 | /// `airCall` uses this instead of `next` so that it can take into account variadic functions. | 10901 | /// `airCall` uses this instead of `next` so that it can take into account variadic functions. |
| 10897 | pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering { | 10902 | pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering { |
| 10903 | const mod = it.object.module; | ||
| 10904 | const ip = &mod.intern_pool; | ||
| 10898 | if (it.zig_index >= it.fn_info.param_types.len) { | 10905 | if (it.zig_index >= it.fn_info.param_types.len) { |
| 10899 | if (it.zig_index >= args.len) { | 10906 | if (it.zig_index >= args.len) { |
| 10900 | return null; | 10907 | return null; |
| ... | @@ -10902,7 +10909,7 @@ const ParamTypeIterator = struct { | ... | @@ -10902,7 +10909,7 @@ const ParamTypeIterator = struct { |
| 10902 | return nextInner(it, fg.typeOf(args[it.zig_index])); | 10909 | return nextInner(it, fg.typeOf(args[it.zig_index])); |
| 10903 | } | 10910 | } |
| 10904 | } else { | 10911 | } else { |
| 10905 | return nextInner(it, it.fn_info.param_types[it.zig_index].toType()); | 10912 | return nextInner(it, it.fn_info.param_types.get(ip)[it.zig_index].toType()); |
| 10906 | } | 10913 | } |
| 10907 | } | 10914 | } |
| 10908 | 10915 |
src/codegen/spirv.zig+12-8| ... | @@ -238,7 +238,7 @@ pub const DeclGen = struct { | ... | @@ -238,7 +238,7 @@ pub const DeclGen = struct { |
| 238 | if (ty.zigTypeTag(mod) == .Fn) { | 238 | if (ty.zigTypeTag(mod) == .Fn) { |
| 239 | const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) { | 239 | const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) { |
| 240 | .extern_func => |extern_func| extern_func.decl, | 240 | .extern_func => |extern_func| extern_func.decl, |
| 241 | .func => |func| mod.funcPtr(func.index).owner_decl, | 241 | .func => |func| func.owner_decl, |
| 242 | else => unreachable, | 242 | else => unreachable, |
| 243 | }; | 243 | }; |
| 244 | const spv_decl_index = try self.resolveDecl(fn_decl_index); | 244 | const spv_decl_index = try self.resolveDecl(fn_decl_index); |
| ... | @@ -255,13 +255,14 @@ pub const DeclGen = struct { | ... | @@ -255,13 +255,14 @@ pub const DeclGen = struct { |
| 255 | /// Fetch or allocate a result id for decl index. This function also marks the decl as alive. | 255 | /// Fetch or allocate a result id for decl index. This function also marks the decl as alive. |
| 256 | /// Note: Function does not actually generate the decl. | 256 | /// Note: Function does not actually generate the decl. |
| 257 | 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 { |
| 258 | const decl = self.module.declPtr(decl_index); | 258 | const mod = self.module; |
| 259 | try self.module.markDeclAlive(decl); | 259 | const decl = mod.declPtr(decl_index); |
| 260 | try mod.markDeclAlive(decl); | ||
| 260 | 261 | ||
| 261 | const entry = try self.decl_link.getOrPut(decl_index); | 262 | const entry = try self.decl_link.getOrPut(decl_index); |
| 262 | if (!entry.found_existing) { | 263 | if (!entry.found_existing) { |
| 263 | // TODO: Extern fn? | 264 | // TODO: Extern fn? |
| 264 | const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none) | 265 | const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod)) |
| 265 | .func | 266 | .func |
| 266 | else | 267 | else |
| 267 | .global; | 268 | .global; |
| ... | @@ -1268,6 +1269,7 @@ pub const DeclGen = struct { | ... | @@ -1268,6 +1269,7 @@ pub const DeclGen = struct { |
| 1268 | }, | 1269 | }, |
| 1269 | .Fn => switch (repr) { | 1270 | .Fn => switch (repr) { |
| 1270 | .direct => { | 1271 | .direct => { |
| 1272 | const ip = &mod.intern_pool; | ||
| 1271 | const fn_info = mod.typeToFunc(ty).?; | 1273 | const fn_info = mod.typeToFunc(ty).?; |
| 1272 | // TODO: Put this somewhere in Sema.zig | 1274 | // TODO: Put this somewhere in Sema.zig |
| 1273 | if (fn_info.is_var_args) | 1275 | if (fn_info.is_var_args) |
| ... | @@ -1275,8 +1277,8 @@ pub const DeclGen = struct { | ... | @@ -1275,8 +1277,8 @@ pub const DeclGen = struct { |
| 1275 | 1277 | ||
| 1276 | const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len); | 1278 | const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len); |
| 1277 | defer self.gpa.free(param_ty_refs); | 1279 | defer self.gpa.free(param_ty_refs); |
| 1278 | for (param_ty_refs, 0..) |*param_type, i| { | 1280 | for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| { |
| 1279 | param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct); | 1281 | param_type.* = try self.resolveType(fn_param_type.toType(), .direct); |
| 1280 | } | 1282 | } |
| 1281 | const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct); | 1283 | const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct); |
| 1282 | 1284 | ||
| ... | @@ -1576,6 +1578,7 @@ pub const DeclGen = struct { | ... | @@ -1576,6 +1578,7 @@ pub const DeclGen = struct { |
| 1576 | 1578 | ||
| 1577 | fn genDecl(self: *DeclGen) !void { | 1579 | fn genDecl(self: *DeclGen) !void { |
| 1578 | const mod = self.module; | 1580 | const mod = self.module; |
| 1581 | const ip = &mod.intern_pool; | ||
| 1579 | const decl = mod.declPtr(self.decl_index); | 1582 | const decl = mod.declPtr(self.decl_index); |
| 1580 | const spv_decl_index = try self.resolveDecl(self.decl_index); | 1583 | const spv_decl_index = try self.resolveDecl(self.decl_index); |
| 1581 | 1584 | ||
| ... | @@ -1594,7 +1597,8 @@ pub const DeclGen = struct { | ... | @@ -1594,7 +1597,8 @@ pub const DeclGen = struct { |
| 1594 | const fn_info = mod.typeToFunc(decl.ty).?; | 1597 | const fn_info = mod.typeToFunc(decl.ty).?; |
| 1595 | 1598 | ||
| 1596 | try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); | 1599 | try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); |
| 1597 | for (fn_info.param_types) |param_type| { | 1600 | for (0..fn_info.param_types.len) |i| { |
| 1601 | const param_type = fn_info.param_types.get(ip)[i]; | ||
| 1598 | const param_type_id = try self.resolveTypeId(param_type.toType()); | 1602 | const param_type_id = try self.resolveTypeId(param_type.toType()); |
| 1599 | const arg_result_id = self.spv.allocId(); | 1603 | const arg_result_id = self.spv.allocId(); |
| 1600 | try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{ | 1604 | try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{ |
| ... | @@ -1621,7 +1625,7 @@ pub const DeclGen = struct { | ... | @@ -1621,7 +1625,7 @@ pub const DeclGen = struct { |
| 1621 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); | 1625 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 1622 | try self.spv.addFunction(spv_decl_index, self.func); | 1626 | try self.spv.addFunction(spv_decl_index, self.func); |
| 1623 | 1627 | ||
| 1624 | const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module)); | 1628 | const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module)); |
| 1625 | 1629 | ||
| 1626 | try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{ | 1630 | try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{ |
| 1627 | .target = decl_id, | 1631 | .target = decl_id, |
src/link.zig+2-1| ... | @@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig"); | ... | @@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig"); |
| 16 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | 16 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; |
| 17 | const Liveness = @import("Liveness.zig"); | 17 | const Liveness = @import("Liveness.zig"); |
| 18 | const Module = @import("Module.zig"); | 18 | const Module = @import("Module.zig"); |
| 19 | const InternPool = @import("InternPool.zig"); | ||
| 19 | const Package = @import("Package.zig"); | 20 | const Package = @import("Package.zig"); |
| 20 | const Type = @import("type.zig").Type; | 21 | const Type = @import("type.zig").Type; |
| 21 | const TypedValue = @import("TypedValue.zig"); | 22 | const TypedValue = @import("TypedValue.zig"); |
| ... | @@ -562,7 +563,7 @@ pub const File = struct { | ... | @@ -562,7 +563,7 @@ pub const File = struct { |
| 562 | } | 563 | } |
| 563 | 564 | ||
| 564 | /// May be called before or after updateDeclExports for any given Decl. | 565 | /// May be called before or after updateDeclExports for any given Decl. |
| 565 | pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) UpdateDeclError!void { | 566 | pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void { |
| 566 | if (build_options.only_c) { | 567 | if (build_options.only_c) { |
| 567 | assert(base.tag == .c); | 568 | assert(base.tag == .c); |
| 568 | return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness); | 569 | return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness); |
src/link/C.zig+2-2| ... | @@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { | ... | @@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { |
| 88 | } | 88 | } |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | pub fn updateFunc(self: *C, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 91 | pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 92 | const tracy = trace(@src()); | 92 | const tracy = trace(@src()); |
| 93 | defer tracy.end(); | 93 | defer tracy.end(); |
| 94 | 94 | ||
| 95 | const gpa = self.base.allocator; | 95 | const gpa = self.base.allocator; |
| 96 | 96 | ||
| 97 | const func = module.funcPtr(func_index); | 97 | const func = module.funcInfo(func_index); |
| 98 | const decl_index = func.owner_decl; | 98 | const decl_index = func.owner_decl; |
| 99 | const gop = try self.decl_table.getOrPut(gpa, decl_index); | 99 | const gop = try self.decl_table.getOrPut(gpa, decl_index); |
| 100 | if (!gop.found_existing) { | 100 | if (!gop.found_existing) { |
src/link/Coff.zig+3-3| ... | @@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void { | ... | @@ -1032,7 +1032,7 @@ 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 | } |
| 1034 | 1034 | ||
| 1035 | pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 1035 | pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.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 | } |
| ... | @@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A | ... | @@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A |
| 1044 | const tracy = trace(@src()); | 1044 | const tracy = trace(@src()); |
| 1045 | defer tracy.end(); | 1045 | defer tracy.end(); |
| 1046 | 1046 | ||
| 1047 | const func = mod.funcPtr(func_index); | 1047 | const func = mod.funcInfo(func_index); |
| 1048 | const decl_index = func.owner_decl; | 1048 | const decl_index = func.owner_decl; |
| 1049 | const decl = mod.declPtr(decl_index); | 1049 | const decl = mod.declPtr(decl_index); |
| 1050 | 1050 | ||
| ... | @@ -1424,7 +1424,7 @@ pub fn updateDeclExports( | ... | @@ -1424,7 +1424,7 @@ pub fn updateDeclExports( |
| 1424 | // detect the default subsystem. | 1424 | // detect the default subsystem. |
| 1425 | for (exports) |exp| { | 1425 | for (exports) |exp| { |
| 1426 | const exported_decl = mod.declPtr(exp.exported_decl); | 1426 | const exported_decl = mod.declPtr(exp.exported_decl); |
| 1427 | if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue; | 1427 | if (exported_decl.getOwnedFunction(mod) == null) continue; |
| 1428 | const winapi_cc = switch (self.base.options.target.cpu.arch) { | 1428 | const winapi_cc = switch (self.base.options.target.cpu.arch) { |
| 1429 | .x86 => std.builtin.CallingConvention.Stdcall, | 1429 | .x86 => std.builtin.CallingConvention.Stdcall, |
| 1430 | else => std.builtin.CallingConvention.C, | 1430 | else => std.builtin.CallingConvention.C, |
src/link/Dwarf.zig+23-34| ... | @@ -1043,6 +1043,7 @@ pub fn commitDeclState( | ... | @@ -1043,6 +1043,7 @@ pub fn commitDeclState( |
| 1043 | var dbg_line_buffer = &decl_state.dbg_line; | 1043 | var dbg_line_buffer = &decl_state.dbg_line; |
| 1044 | var dbg_info_buffer = &decl_state.dbg_info; | 1044 | var dbg_info_buffer = &decl_state.dbg_info; |
| 1045 | const decl = mod.declPtr(decl_index); | 1045 | const decl = mod.declPtr(decl_index); |
| 1046 | const ip = &mod.intern_pool; | ||
| 1046 | 1047 | ||
| 1047 | const target_endian = self.target.cpu.arch.endian(); | 1048 | const target_endian = self.target.cpu.arch.endian(); |
| 1048 | 1049 | ||
| ... | @@ -1241,20 +1242,9 @@ pub fn commitDeclState( | ... | @@ -1241,20 +1242,9 @@ pub fn commitDeclState( |
| 1241 | while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) { | 1242 | while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) { |
| 1242 | const symbol = &decl_state.abbrev_table.items[sym_index]; | 1243 | const symbol = &decl_state.abbrev_table.items[sym_index]; |
| 1243 | const ty = symbol.type; | 1244 | const ty = symbol.type; |
| 1244 | const deferred: bool = blk: { | 1245 | if (ip.isErrorSetType(ty.toIntern())) continue; |
| 1245 | if (ty.isAnyError(mod)) break :blk true; | ||
| 1246 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 1247 | .inferred_error_set_type => |ies_index| { | ||
| 1248 | const ies = mod.inferredErrorSetPtr(ies_index); | ||
| 1249 | if (!ies.is_resolved) break :blk true; | ||
| 1250 | }, | ||
| 1251 | else => {}, | ||
| 1252 | } | ||
| 1253 | break :blk false; | ||
| 1254 | }; | ||
| 1255 | if (deferred) continue; | ||
| 1256 | 1246 | ||
| 1257 | symbol.offset = @as(u32, @intCast(dbg_info_buffer.items.len)); | 1247 | symbol.offset = @intCast(dbg_info_buffer.items.len); |
| 1258 | try decl_state.addDbgInfoType(mod, di_atom_index, ty); | 1248 | try decl_state.addDbgInfoType(mod, di_atom_index, ty); |
| 1259 | } | 1249 | } |
| 1260 | } | 1250 | } |
| ... | @@ -1265,18 +1255,7 @@ pub fn commitDeclState( | ... | @@ -1265,18 +1255,7 @@ pub fn commitDeclState( |
| 1265 | if (reloc.target) |target| { | 1255 | if (reloc.target) |target| { |
| 1266 | const symbol = decl_state.abbrev_table.items[target]; | 1256 | const symbol = decl_state.abbrev_table.items[target]; |
| 1267 | const ty = symbol.type; | 1257 | const ty = symbol.type; |
| 1268 | const deferred: bool = blk: { | 1258 | if (ip.isErrorSetType(ty.toIntern())) { |
| 1269 | if (ty.isAnyError(mod)) break :blk true; | ||
| 1270 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 1271 | .inferred_error_set_type => |ies_index| { | ||
| 1272 | const ies = mod.inferredErrorSetPtr(ies_index); | ||
| 1273 | if (!ies.is_resolved) break :blk true; | ||
| 1274 | }, | ||
| 1275 | else => {}, | ||
| 1276 | } | ||
| 1277 | break :blk false; | ||
| 1278 | }; | ||
| 1279 | if (deferred) { | ||
| 1280 | log.debug("resolving %{d} deferred until flush", .{target}); | 1259 | log.debug("resolving %{d} deferred until flush", .{target}); |
| 1281 | try self.global_abbrev_relocs.append(gpa, .{ | 1260 | try self.global_abbrev_relocs.append(gpa, .{ |
| 1282 | .target = null, | 1261 | .target = null, |
| ... | @@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void { | ... | @@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void { |
| 2505 | defer arena_alloc.deinit(); | 2484 | defer arena_alloc.deinit(); |
| 2506 | const arena = arena_alloc.allocator(); | 2485 | const arena = arena_alloc.allocator(); |
| 2507 | 2486 | ||
| 2508 | // TODO: don't create a zig type for this, just make the dwarf info | ||
| 2509 | // without touching the zig type system. | ||
| 2510 | const names = try arena.dupe(InternPool.NullTerminatedString, module.global_error_set.keys()); | ||
| 2511 | std.mem.sort(InternPool.NullTerminatedString, names, {}, InternPool.NullTerminatedString.indexLessThan); | ||
| 2512 | |||
| 2513 | const error_ty = try module.intern(.{ .error_set_type = .{ .names = names } }); | ||
| 2514 | var dbg_info_buffer = std.ArrayList(u8).init(arena); | 2487 | var dbg_info_buffer = std.ArrayList(u8).init(arena); |
| 2515 | try addDbgInfoErrorSet(module, error_ty.toType(), self.target, &dbg_info_buffer); | 2488 | try addDbgInfoErrorSetNames( |
| 2489 | module, | ||
| 2490 | Type.anyerror, | ||
| 2491 | module.global_error_set.keys(), | ||
| 2492 | self.target, | ||
| 2493 | &dbg_info_buffer, | ||
| 2494 | ); | ||
| 2516 | 2495 | ||
| 2517 | const di_atom_index = try self.createAtom(.di_atom); | 2496 | const di_atom_index = try self.createAtom(.di_atom); |
| 2518 | log.debug("updateDeclDebugInfoAllocation in flushModule", .{}); | 2497 | log.debug("updateDeclDebugInfoAllocation in flushModule", .{}); |
| 2519 | try self.updateDeclDebugInfoAllocation(di_atom_index, @as(u32, @intCast(dbg_info_buffer.items.len))); | 2498 | try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len)); |
| 2520 | log.debug("writeDeclDebugInfo in flushModule", .{}); | 2499 | log.debug("writeDeclDebugInfo in flushModule", .{}); |
| 2521 | try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items); | 2500 | try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items); |
| 2522 | 2501 | ||
| ... | @@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet( | ... | @@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet( |
| 2633 | ty: Type, | 2612 | ty: Type, |
| 2634 | target: std.Target, | 2613 | target: std.Target, |
| 2635 | dbg_info_buffer: *std.ArrayList(u8), | 2614 | dbg_info_buffer: *std.ArrayList(u8), |
| 2615 | ) !void { | ||
| 2616 | return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod), target, dbg_info_buffer); | ||
| 2617 | } | ||
| 2618 | |||
| 2619 | fn addDbgInfoErrorSetNames( | ||
| 2620 | mod: *Module, | ||
| 2621 | /// Used for printing the type name only. | ||
| 2622 | ty: Type, | ||
| 2623 | error_names: []const InternPool.NullTerminatedString, | ||
| 2624 | target: std.Target, | ||
| 2625 | dbg_info_buffer: *std.ArrayList(u8), | ||
| 2636 | ) !void { | 2626 | ) !void { |
| 2637 | const target_endian = target.cpu.arch.endian(); | 2627 | const target_endian = target.cpu.arch.endian(); |
| 2638 | 2628 | ||
| ... | @@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet( | ... | @@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet( |
| 2655 | // DW.AT.const_value, DW.FORM.data8 | 2645 | // DW.AT.const_value, DW.FORM.data8 |
| 2656 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian); | 2646 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian); |
| 2657 | 2647 | ||
| 2658 | const error_names = ty.errorSetNames(mod); | ||
| 2659 | for (error_names) |error_name_ip| { | 2648 | for (error_names) |error_name_ip| { |
| 2660 | const int = try mod.getErrorValue(error_name_ip); | 2649 | const int = try mod.getErrorValue(error_name_ip); |
| 2661 | const error_name = mod.intern_pool.stringToSlice(error_name_ip); | 2650 | const error_name = mod.intern_pool.stringToSlice(error_name_ip); |
src/link/Elf.zig+2-2| ... | @@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s | ... | @@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s |
| 2575 | return local_sym; | 2575 | return local_sym; |
| 2576 | } | 2576 | } |
| 2577 | 2577 | ||
| 2578 | pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 2578 | pub fn updateFunc(self: *Elf, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 2579 | if (build_options.skip_non_native and builtin.object_format != .elf) { | 2579 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 2580 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 2580 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 2581 | } | 2581 | } |
| ... | @@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai | ... | @@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai |
| 2586 | const tracy = trace(@src()); | 2586 | const tracy = trace(@src()); |
| 2587 | defer tracy.end(); | 2587 | defer tracy.end(); |
| 2588 | 2588 | ||
| 2589 | const func = mod.funcPtr(func_index); | 2589 | const func = mod.funcInfo(func_index); |
| 2590 | const decl_index = func.owner_decl; | 2590 | const decl_index = func.owner_decl; |
| 2591 | const decl = mod.declPtr(decl_index); | 2591 | const decl = mod.declPtr(decl_index); |
| 2592 | 2592 |
src/link/MachO.zig+2-2| ... | @@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { | ... | @@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { |
| 1845 | self.markRelocsDirtyByTarget(target); | 1845 | self.markRelocsDirtyByTarget(target); |
| 1846 | } | 1846 | } |
| 1847 | 1847 | ||
| 1848 | pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 1848 | pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 1849 | if (build_options.skip_non_native and builtin.object_format != .macho) { | 1849 | if (build_options.skip_non_native and builtin.object_format != .macho) { |
| 1850 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 1850 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1851 | } | 1851 | } |
| ... | @@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: | ... | @@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: |
| 1855 | const tracy = trace(@src()); | 1855 | const tracy = trace(@src()); |
| 1856 | defer tracy.end(); | 1856 | defer tracy.end(); |
| 1857 | 1857 | ||
| 1858 | const func = mod.funcPtr(func_index); | 1858 | const func = mod.funcInfo(func_index); |
| 1859 | const decl_index = func.owner_decl; | 1859 | const decl_index = func.owner_decl; |
| 1860 | const decl = mod.declPtr(decl_index); | 1860 | const decl = mod.declPtr(decl_index); |
| 1861 | 1861 |
src/link/NvPtx.zig+2-1| ... | @@ -13,6 +13,7 @@ const assert = std.debug.assert; | ... | @@ -13,6 +13,7 @@ const assert = std.debug.assert; |
| 13 | const log = std.log.scoped(.link); | 13 | const log = std.log.scoped(.link); |
| 14 | 14 | ||
| 15 | const Module = @import("../Module.zig"); | 15 | const Module = @import("../Module.zig"); |
| 16 | const InternPool = @import("../InternPool.zig"); | ||
| 16 | const Compilation = @import("../Compilation.zig"); | 17 | const Compilation = @import("../Compilation.zig"); |
| 17 | const link = @import("../link.zig"); | 18 | const link = @import("../link.zig"); |
| 18 | const trace = @import("../tracy.zig").trace; | 19 | const trace = @import("../tracy.zig").trace; |
| ... | @@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void { | ... | @@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void { |
| 68 | self.base.allocator.free(self.ptx_file_name); | 69 | self.base.allocator.free(self.ptx_file_name); |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | pub fn updateFunc(self: *NvPtx, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 72 | pub fn updateFunc(self: *NvPtx, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 72 | if (!build_options.have_llvm) return; | 73 | if (!build_options.have_llvm) return; |
| 73 | try self.llvm_object.updateFunc(module, func_index, air, liveness); | 74 | try self.llvm_object.updateFunc(module, func_index, air, liveness); |
| 74 | } | 75 | } |
src/link/Plan9.zig+4-3| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | const Plan9 = @This(); | 4 | const Plan9 = @This(); |
| 5 | const link = @import("../link.zig"); | 5 | const link = @import("../link.zig"); |
| 6 | const Module = @import("../Module.zig"); | 6 | const Module = @import("../Module.zig"); |
| 7 | const InternPool = @import("../InternPool.zig"); | ||
| 7 | const Compilation = @import("../Compilation.zig"); | 8 | const Compilation = @import("../Compilation.zig"); |
| 8 | const aout = @import("Plan9/aout.zig"); | 9 | const aout = @import("Plan9/aout.zig"); |
| 9 | const codegen = @import("../codegen.zig"); | 10 | const codegen = @import("../codegen.zig"); |
| ... | @@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi | ... | @@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi |
| 344 | } | 345 | } |
| 345 | } | 346 | } |
| 346 | 347 | ||
| 347 | pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 348 | pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 348 | if (build_options.skip_non_native and builtin.object_format != .plan9) { | 349 | if (build_options.skip_non_native and builtin.object_format != .plan9) { |
| 349 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 350 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 350 | } | 351 | } |
| 351 | 352 | ||
| 352 | const func = mod.funcPtr(func_index); | 353 | const func = mod.funcInfo(func_index); |
| 353 | const decl_index = func.owner_decl; | 354 | const decl_index = func.owner_decl; |
| 354 | const decl = mod.declPtr(decl_index); | 355 | const decl = mod.declPtr(decl_index); |
| 355 | self.freeUnnamedConsts(decl_index); | 356 | self.freeUnnamedConsts(decl_index); |
| ... | @@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { | ... | @@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { |
| 908 | // in the deleteUnusedDecl function. | 909 | // in the deleteUnusedDecl function. |
| 909 | const mod = self.base.options.module.?; | 910 | const mod = self.base.options.module.?; |
| 910 | const decl = mod.declPtr(decl_index); | 911 | const decl = mod.declPtr(decl_index); |
| 911 | const is_fn = decl.val.getFunctionIndex(mod) != .none; | 912 | const is_fn = decl.val.isFuncBody(mod); |
| 912 | if (is_fn) { | 913 | if (is_fn) { |
| 913 | var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?; | 914 | var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?; |
| 914 | var submap = symidx_and_submap.functions; | 915 | var submap = symidx_and_submap.functions; |
src/link/SpirV.zig+4-3| ... | @@ -29,6 +29,7 @@ const assert = std.debug.assert; | ... | @@ -29,6 +29,7 @@ const assert = std.debug.assert; |
| 29 | const log = std.log.scoped(.link); | 29 | const log = std.log.scoped(.link); |
| 30 | 30 | ||
| 31 | const Module = @import("../Module.zig"); | 31 | const Module = @import("../Module.zig"); |
| 32 | const InternPool = @import("../InternPool.zig"); | ||
| 32 | const Compilation = @import("../Compilation.zig"); | 33 | const Compilation = @import("../Compilation.zig"); |
| 33 | const link = @import("../link.zig"); | 34 | const link = @import("../link.zig"); |
| 34 | const codegen = @import("../codegen/spirv.zig"); | 35 | const codegen = @import("../codegen/spirv.zig"); |
| ... | @@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void { | ... | @@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void { |
| 103 | self.decl_link.deinit(); | 104 | self.decl_link.deinit(); |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | pub fn updateFunc(self: *SpirV, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 107 | pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 107 | if (build_options.skip_non_native) { | 108 | if (build_options.skip_non_native) { |
| 108 | @panic("Attempted to compile for architecture that was disabled by build configuration"); | 109 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | const func = module.funcPtr(func_index); | 112 | const func = module.funcInfo(func_index); |
| 112 | 113 | ||
| 113 | var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link); | 114 | var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link); |
| 114 | defer decl_gen.deinit(); | 115 | defer decl_gen.deinit(); |
| ... | @@ -138,7 +139,7 @@ pub fn updateDeclExports( | ... | @@ -138,7 +139,7 @@ pub fn updateDeclExports( |
| 138 | exports: []const *Module.Export, | 139 | exports: []const *Module.Export, |
| 139 | ) !void { | 140 | ) !void { |
| 140 | const decl = mod.declPtr(decl_index); | 141 | const decl = mod.declPtr(decl_index); |
| 141 | if (decl.val.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) { | 142 | if (decl.val.isFuncBody(mod) and decl.ty.fnCallingConvention(mod) == .Kernel) { |
| 142 | // TODO: Unify with resolveDecl in spirv.zig. | 143 | // TODO: Unify with resolveDecl in spirv.zig. |
| 143 | const entry = try self.decl_link.getOrPut(decl_index); | 144 | const entry = try self.decl_link.getOrPut(decl_index); |
| 144 | if (!entry.found_existing) { | 145 | if (!entry.found_existing) { |
src/link/Wasm.zig+3-2| ... | @@ -12,6 +12,7 @@ const log = std.log.scoped(.link); | ... | @@ -12,6 +12,7 @@ const log = std.log.scoped(.link); |
| 12 | pub const Atom = @import("Wasm/Atom.zig"); | 12 | pub const Atom = @import("Wasm/Atom.zig"); |
| 13 | const Dwarf = @import("Dwarf.zig"); | 13 | const Dwarf = @import("Dwarf.zig"); |
| 14 | const Module = @import("../Module.zig"); | 14 | const Module = @import("../Module.zig"); |
| 15 | const InternPool = @import("../InternPool.zig"); | ||
| 15 | const Compilation = @import("../Compilation.zig"); | 16 | const Compilation = @import("../Compilation.zig"); |
| 16 | const CodeGen = @import("../arch/wasm/CodeGen.zig"); | 17 | const CodeGen = @import("../arch/wasm/CodeGen.zig"); |
| 17 | const codegen = @import("../codegen.zig"); | 18 | const codegen = @import("../codegen.zig"); |
| ... | @@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 { | ... | @@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 { |
| 1338 | return index; | 1339 | return index; |
| 1339 | } | 1340 | } |
| 1340 | 1341 | ||
| 1341 | pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void { | 1342 | pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 1342 | if (build_options.skip_non_native and builtin.object_format != .wasm) { | 1343 | if (build_options.skip_non_native and builtin.object_format != .wasm) { |
| 1343 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 1344 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1344 | } | 1345 | } |
| ... | @@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A | ... | @@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A |
| 1349 | const tracy = trace(@src()); | 1350 | const tracy = trace(@src()); |
| 1350 | defer tracy.end(); | 1351 | defer tracy.end(); |
| 1351 | 1352 | ||
| 1352 | const func = mod.funcPtr(func_index); | 1353 | const func = mod.funcInfo(func_index); |
| 1353 | const decl_index = func.owner_decl; | 1354 | const decl_index = func.owner_decl; |
| 1354 | const decl = mod.declPtr(decl_index); | 1355 | const decl = mod.declPtr(decl_index); |
| 1355 | const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); | 1356 | const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); |
src/print_air.zig+1-1| ... | @@ -665,7 +665,7 @@ const Writer = struct { | ... | @@ -665,7 +665,7 @@ const Writer = struct { |
| 665 | fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 665 | fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 666 | const ty_fn = w.air.instructions.items(.data)[inst].ty_fn; | 666 | const ty_fn = w.air.instructions.items(.data)[inst].ty_fn; |
| 667 | const func_index = ty_fn.func; | 667 | const func_index = ty_fn.func; |
| 668 | const owner_decl = w.module.declPtr(w.module.funcPtr(func_index).owner_decl); | 668 | const owner_decl = w.module.funcOwnerDeclPtr(func_index); |
| 669 | try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)}); | 669 | try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)}); |
| 670 | } | 670 | } |
| 671 | 671 |
src/type.zig+53-43| ... | @@ -250,21 +250,19 @@ pub const Type = struct { | ... | @@ -250,21 +250,19 @@ pub const Type = struct { |
| 250 | try print(error_union_type.payload_type.toType(), writer, mod); | 250 | try print(error_union_type.payload_type.toType(), writer, mod); |
| 251 | return; | 251 | return; |
| 252 | }, | 252 | }, |
| 253 | .inferred_error_set_type => |index| { | 253 | .inferred_error_set_type => |func_index| { |
| 254 | const ies = mod.inferredErrorSetPtr(index); | ||
| 255 | const func = ies.func; | ||
| 256 | |||
| 257 | try writer.writeAll("@typeInfo(@typeInfo(@TypeOf("); | 254 | try writer.writeAll("@typeInfo(@typeInfo(@TypeOf("); |
| 258 | const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl); | 255 | const owner_decl = mod.funcOwnerDeclPtr(func_index); |
| 259 | try owner_decl.renderFullyQualifiedName(mod, writer); | 256 | try owner_decl.renderFullyQualifiedName(mod, writer); |
| 260 | try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set"); | 257 | try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set"); |
| 261 | }, | 258 | }, |
| 262 | .error_set_type => |error_set_type| { | 259 | .error_set_type => |error_set_type| { |
| 260 | const ip = &mod.intern_pool; | ||
| 263 | const names = error_set_type.names; | 261 | const names = error_set_type.names; |
| 264 | try writer.writeAll("error{"); | 262 | try writer.writeAll("error{"); |
| 265 | for (names, 0..) |name, i| { | 263 | for (names.get(ip), 0..) |name, i| { |
| 266 | if (i != 0) try writer.writeByte(','); | 264 | if (i != 0) try writer.writeByte(','); |
| 267 | try writer.print("{}", .{name.fmt(&mod.intern_pool)}); | 265 | try writer.print("{}", .{name.fmt(ip)}); |
| 268 | } | 266 | } |
| 269 | try writer.writeAll("}"); | 267 | try writer.writeAll("}"); |
| 270 | }, | 268 | }, |
| ... | @@ -294,6 +292,7 @@ pub const Type = struct { | ... | @@ -294,6 +292,7 @@ pub const Type = struct { |
| 294 | .comptime_int, | 292 | .comptime_int, |
| 295 | .comptime_float, | 293 | .comptime_float, |
| 296 | .noreturn, | 294 | .noreturn, |
| 295 | .adhoc_inferred_error_set, | ||
| 297 | => return writer.writeAll(@tagName(s)), | 296 | => return writer.writeAll(@tagName(s)), |
| 298 | 297 | ||
| 299 | .null, | 298 | .null, |
| ... | @@ -367,7 +366,8 @@ pub const Type = struct { | ... | @@ -367,7 +366,8 @@ pub const Type = struct { |
| 367 | try writer.writeAll("noinline "); | 366 | try writer.writeAll("noinline "); |
| 368 | } | 367 | } |
| 369 | try writer.writeAll("fn("); | 368 | try writer.writeAll("fn("); |
| 370 | for (fn_info.param_types, 0..) |param_ty, i| { | 369 | const param_types = fn_info.param_types.get(&mod.intern_pool); |
| 370 | for (param_types, 0..) |param_ty, i| { | ||
| 371 | if (i != 0) try writer.writeAll(", "); | 371 | if (i != 0) try writer.writeAll(", "); |
| 372 | if (std.math.cast(u5, i)) |index| { | 372 | if (std.math.cast(u5, i)) |index| { |
| 373 | if (fn_info.paramIsComptime(index)) { | 373 | if (fn_info.paramIsComptime(index)) { |
| ... | @@ -384,7 +384,7 @@ pub const Type = struct { | ... | @@ -384,7 +384,7 @@ pub const Type = struct { |
| 384 | } | 384 | } |
| 385 | } | 385 | } |
| 386 | if (fn_info.is_var_args) { | 386 | if (fn_info.is_var_args) { |
| 387 | if (fn_info.param_types.len != 0) { | 387 | if (param_types.len != 0) { |
| 388 | try writer.writeAll(", "); | 388 | try writer.writeAll(", "); |
| 389 | } | 389 | } |
| 390 | try writer.writeAll("..."); | 390 | try writer.writeAll("..."); |
| ... | @@ -534,6 +534,7 @@ pub const Type = struct { | ... | @@ -534,6 +534,7 @@ pub const Type = struct { |
| 534 | .c_longdouble, | 534 | .c_longdouble, |
| 535 | .bool, | 535 | .bool, |
| 536 | .anyerror, | 536 | .anyerror, |
| 537 | .adhoc_inferred_error_set, | ||
| 537 | .anyopaque, | 538 | .anyopaque, |
| 538 | .atomic_order, | 539 | .atomic_order, |
| 539 | .atomic_rmw_op, | 540 | .atomic_rmw_op, |
| ... | @@ -697,6 +698,7 @@ pub const Type = struct { | ... | @@ -697,6 +698,7 @@ pub const Type = struct { |
| 697 | => true, | 698 | => true, |
| 698 | 699 | ||
| 699 | .anyerror, | 700 | .anyerror, |
| 701 | .adhoc_inferred_error_set, | ||
| 700 | .anyopaque, | 702 | .anyopaque, |
| 701 | .atomic_order, | 703 | .atomic_order, |
| 702 | .atomic_rmw_op, | 704 | .atomic_rmw_op, |
| ... | @@ -955,7 +957,9 @@ pub const Type = struct { | ... | @@ -955,7 +957,9 @@ pub const Type = struct { |
| 955 | }, | 957 | }, |
| 956 | 958 | ||
| 957 | // TODO revisit this when we have the concept of the error tag type | 959 | // TODO revisit this when we have the concept of the error tag type |
| 958 | .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 }, | 960 | .anyerror, |
| 961 | .adhoc_inferred_error_set, | ||
| 962 | => return AbiAlignmentAdvanced{ .scalar = 2 }, | ||
| 959 | 963 | ||
| 960 | .void, | 964 | .void, |
| 961 | .type, | 965 | .type, |
| ... | @@ -1419,7 +1423,9 @@ pub const Type = struct { | ... | @@ -1419,7 +1423,9 @@ pub const Type = struct { |
| 1419 | => return AbiSizeAdvanced{ .scalar = 0 }, | 1423 | => return AbiSizeAdvanced{ .scalar = 0 }, |
| 1420 | 1424 | ||
| 1421 | // TODO revisit this when we have the concept of the error tag type | 1425 | // TODO revisit this when we have the concept of the error tag type |
| 1422 | .anyerror => return AbiSizeAdvanced{ .scalar = 2 }, | 1426 | .anyerror, |
| 1427 | .adhoc_inferred_error_set, | ||
| 1428 | => return AbiSizeAdvanced{ .scalar = 2 }, | ||
| 1423 | 1429 | ||
| 1424 | .prefetch_options => unreachable, // missing call to resolveTypeFields | 1430 | .prefetch_options => unreachable, // missing call to resolveTypeFields |
| 1425 | .export_options => unreachable, // missing call to resolveTypeFields | 1431 | .export_options => unreachable, // missing call to resolveTypeFields |
| ... | @@ -1662,7 +1668,9 @@ pub const Type = struct { | ... | @@ -1662,7 +1668,9 @@ pub const Type = struct { |
| 1662 | .void => return 0, | 1668 | .void => return 0, |
| 1663 | 1669 | ||
| 1664 | // TODO revisit this when we have the concept of the error tag type | 1670 | // TODO revisit this when we have the concept of the error tag type |
| 1665 | .anyerror => return 16, | 1671 | .anyerror, |
| 1672 | .adhoc_inferred_error_set, | ||
| 1673 | => return 16, | ||
| 1666 | 1674 | ||
| 1667 | .anyopaque => unreachable, | 1675 | .anyopaque => unreachable, |
| 1668 | .type => unreachable, | 1676 | .type => unreachable, |
| ... | @@ -2050,21 +2058,19 @@ pub const Type = struct { | ... | @@ -2050,21 +2058,19 @@ pub const Type = struct { |
| 2050 | 2058 | ||
| 2051 | /// Asserts that the type is an error union. | 2059 | /// Asserts that the type is an error union. |
| 2052 | pub fn errorUnionSet(ty: Type, mod: *Module) Type { | 2060 | pub fn errorUnionSet(ty: Type, mod: *Module) Type { |
| 2053 | return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.error_set_type.toType(); | 2061 | return mod.intern_pool.errorUnionSet(ty.toIntern()).toType(); |
| 2054 | } | 2062 | } |
| 2055 | 2063 | ||
| 2056 | /// Returns false for unresolved inferred error sets. | 2064 | /// Returns false for unresolved inferred error sets. |
| 2057 | pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool { | 2065 | pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool { |
| 2066 | const ip = &mod.intern_pool; | ||
| 2058 | return switch (ty.toIntern()) { | 2067 | return switch (ty.toIntern()) { |
| 2059 | .anyerror_type => false, | 2068 | .anyerror_type => false, |
| 2060 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2069 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 2061 | .error_set_type => |error_set_type| error_set_type.names.len == 0, | 2070 | .error_set_type => |error_set_type| error_set_type.names.len == 0, |
| 2062 | .inferred_error_set_type => |index| { | 2071 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2063 | const inferred_error_set = mod.inferredErrorSetPtr(index); | 2072 | .none, .anyerror_type => false, |
| 2064 | // Can't know for sure. | 2073 | else => |t| ip.indexToKey(t).error_set_type.names.len == 0, |
| 2065 | if (!inferred_error_set.is_resolved) return false; | ||
| 2066 | if (inferred_error_set.is_anyerror) return false; | ||
| 2067 | return inferred_error_set.errors.count() == 0; | ||
| 2068 | }, | 2074 | }, |
| 2069 | else => unreachable, | 2075 | else => unreachable, |
| 2070 | }, | 2076 | }, |
| ... | @@ -2075,10 +2081,11 @@ pub const Type = struct { | ... | @@ -2075,10 +2081,11 @@ pub const Type = struct { |
| 2075 | /// Note that the result may be a false negative if the type did not get error set | 2081 | /// Note that the result may be a false negative if the type did not get error set |
| 2076 | /// resolution prior to this call. | 2082 | /// resolution prior to this call. |
| 2077 | pub fn isAnyError(ty: Type, mod: *Module) bool { | 2083 | pub fn isAnyError(ty: Type, mod: *Module) bool { |
| 2084 | const ip = &mod.intern_pool; | ||
| 2078 | return switch (ty.toIntern()) { | 2085 | return switch (ty.toIntern()) { |
| 2079 | .anyerror_type => true, | 2086 | .anyerror_type => true, |
| 2080 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2087 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { |
| 2081 | .inferred_error_set_type => |i| mod.inferredErrorSetPtr(i).is_anyerror, | 2088 | .inferred_error_set_type => |i| ip.funcIesResolved(i).* == .anyerror_type, |
| 2082 | else => false, | 2089 | else => false, |
| 2083 | }, | 2090 | }, |
| 2084 | }; | 2091 | }; |
| ... | @@ -2102,13 +2109,11 @@ pub const Type = struct { | ... | @@ -2102,13 +2109,11 @@ pub const Type = struct { |
| 2102 | return switch (ty) { | 2109 | return switch (ty) { |
| 2103 | .anyerror_type => true, | 2110 | .anyerror_type => true, |
| 2104 | else => switch (ip.indexToKey(ty)) { | 2111 | else => switch (ip.indexToKey(ty)) { |
| 2105 | .error_set_type => |error_set_type| { | 2112 | .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null, |
| 2106 | return error_set_type.nameIndex(ip, name) != null; | 2113 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2107 | }, | 2114 | .anyerror_type => true, |
| 2108 | .inferred_error_set_type => |index| { | 2115 | .none => false, |
| 2109 | const ies = ip.inferredErrorSetPtrConst(index); | 2116 | else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null, |
| 2110 | if (ies.is_anyerror) return true; | ||
| 2111 | return ies.errors.contains(name); | ||
| 2112 | }, | 2117 | }, |
| 2113 | else => unreachable, | 2118 | else => unreachable, |
| 2114 | }, | 2119 | }, |
| ... | @@ -2128,12 +2133,14 @@ pub const Type = struct { | ... | @@ -2128,12 +2133,14 @@ pub const Type = struct { |
| 2128 | const field_name_interned = ip.getString(name).unwrap() orelse return false; | 2133 | const field_name_interned = ip.getString(name).unwrap() orelse return false; |
| 2129 | return error_set_type.nameIndex(ip, field_name_interned) != null; | 2134 | return error_set_type.nameIndex(ip, field_name_interned) != null; |
| 2130 | }, | 2135 | }, |
| 2131 | .inferred_error_set_type => |index| { | 2136 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2132 | const ies = ip.inferredErrorSetPtr(index); | 2137 | .anyerror_type => true, |
| 2133 | if (ies.is_anyerror) return true; | 2138 | .none => false, |
| 2134 | // If the string is not interned, then the field certainly is not present. | 2139 | else => |t| { |
| 2135 | const field_name_interned = ip.getString(name).unwrap() orelse return false; | 2140 | // If the string is not interned, then the field certainly is not present. |
| 2136 | return ies.errors.contains(field_name_interned); | 2141 | const field_name_interned = ip.getString(name).unwrap() orelse return false; |
| 2142 | return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null; | ||
| 2143 | }, | ||
| 2137 | }, | 2144 | }, |
| 2138 | else => unreachable, | 2145 | else => unreachable, |
| 2139 | }, | 2146 | }, |
| ... | @@ -2231,7 +2238,7 @@ pub const Type = struct { | ... | @@ -2231,7 +2238,7 @@ pub const Type = struct { |
| 2231 | var ty = starting_ty; | 2238 | var ty = starting_ty; |
| 2232 | 2239 | ||
| 2233 | while (true) switch (ty.toIntern()) { | 2240 | while (true) switch (ty.toIntern()) { |
| 2234 | .anyerror_type => { | 2241 | .anyerror_type, .adhoc_inferred_error_set_type => { |
| 2235 | // TODO revisit this when error sets support custom int types | 2242 | // TODO revisit this when error sets support custom int types |
| 2236 | return .{ .signedness = .unsigned, .bits = 16 }; | 2243 | return .{ .signedness = .unsigned, .bits = 16 }; |
| 2237 | }, | 2244 | }, |
| ... | @@ -2365,7 +2372,7 @@ pub const Type = struct { | ... | @@ -2365,7 +2372,7 @@ pub const Type = struct { |
| 2365 | 2372 | ||
| 2366 | /// Asserts the type is a function or a function pointer. | 2373 | /// Asserts the type is a function or a function pointer. |
| 2367 | pub fn fnReturnType(ty: Type, mod: *Module) Type { | 2374 | pub fn fnReturnType(ty: Type, mod: *Module) Type { |
| 2368 | return mod.intern_pool.funcReturnType(ty.toIntern()).toType(); | 2375 | return mod.intern_pool.funcTypeReturnType(ty.toIntern()).toType(); |
| 2369 | } | 2376 | } |
| 2370 | 2377 | ||
| 2371 | /// Asserts the type is a function. | 2378 | /// Asserts the type is a function. |
| ... | @@ -2505,6 +2512,7 @@ pub const Type = struct { | ... | @@ -2505,6 +2512,7 @@ pub const Type = struct { |
| 2505 | .export_options, | 2512 | .export_options, |
| 2506 | .extern_options, | 2513 | .extern_options, |
| 2507 | .type_info, | 2514 | .type_info, |
| 2515 | .adhoc_inferred_error_set, | ||
| 2508 | => return null, | 2516 | => return null, |
| 2509 | 2517 | ||
| 2510 | .void => return Value.void, | 2518 | .void => return Value.void, |
| ... | @@ -2699,6 +2707,7 @@ pub const Type = struct { | ... | @@ -2699,6 +2707,7 @@ pub const Type = struct { |
| 2699 | .bool, | 2707 | .bool, |
| 2700 | .void, | 2708 | .void, |
| 2701 | .anyerror, | 2709 | .anyerror, |
| 2710 | .adhoc_inferred_error_set, | ||
| 2702 | .noreturn, | 2711 | .noreturn, |
| 2703 | .generic_poison, | 2712 | .generic_poison, |
| 2704 | .atomic_order, | 2713 | .atomic_order, |
| ... | @@ -2942,14 +2951,15 @@ pub const Type = struct { | ... | @@ -2942,14 +2951,15 @@ pub const Type = struct { |
| 2942 | } | 2951 | } |
| 2943 | 2952 | ||
| 2944 | // Asserts that `ty` is an error set and not `anyerror`. | 2953 | // Asserts that `ty` is an error set and not `anyerror`. |
| 2954 | // Asserts that `ty` is resolved if it is an inferred error set. | ||
| 2945 | pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString { | 2955 | pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString { |
| 2946 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2956 | const ip = &mod.intern_pool; |
| 2947 | .error_set_type => |x| x.names, | 2957 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2948 | .inferred_error_set_type => |index| { | 2958 | .error_set_type => |x| x.names.get(ip), |
| 2949 | const inferred_error_set = mod.inferredErrorSetPtr(index); | 2959 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2950 | assert(inferred_error_set.is_resolved); | 2960 | .none => unreachable, // unresolved inferred error set |
| 2951 | assert(!inferred_error_set.is_anyerror); | 2961 | .anyerror_type => unreachable, |
| 2952 | return inferred_error_set.errors.keys(); | 2962 | else => |t| ip.indexToKey(t).error_set_type.names.get(ip), |
| 2953 | }, | 2963 | }, |
| 2954 | else => unreachable, | 2964 | else => unreachable, |
| 2955 | }; | 2965 | }; |
src/value.zig+13-5| ... | @@ -262,6 +262,11 @@ pub const Value = struct { | ... | @@ -262,6 +262,11 @@ pub const Value = struct { |
| 262 | return ip.getOrPutTrailingString(gpa, len); | 262 | return ip.getOrPutTrailingString(gpa, len); |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | pub fn intern2(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index { | ||
| 266 | if (val.ip_index != .none) return val.ip_index; | ||
| 267 | return intern(val, ty, mod); | ||
| 268 | } | ||
| 269 | |||
| 265 | pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index { | 270 | pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index { |
| 266 | if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern(); | 271 | if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern(); |
| 267 | switch (val.tag()) { | 272 | switch (val.tag()) { |
| ... | @@ -473,12 +478,15 @@ pub const Value = struct { | ... | @@ -473,12 +478,15 @@ pub const Value = struct { |
| 473 | }; | 478 | }; |
| 474 | } | 479 | } |
| 475 | 480 | ||
| 476 | pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn { | 481 | pub fn isFuncBody(val: Value, mod: *Module) bool { |
| 477 | return mod.funcPtrUnwrap(val.getFunctionIndex(mod)); | 482 | return mod.intern_pool.isFuncBody(val.toIntern()); |
| 478 | } | 483 | } |
| 479 | 484 | ||
| 480 | pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex { | 485 | pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func { |
| 481 | return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none; | 486 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 487 | .func => |x| x, | ||
| 488 | else => null, | ||
| 489 | }; | ||
| 482 | } | 490 | } |
| 483 | 491 | ||
| 484 | pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc { | 492 | pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc { |
| ... | @@ -1462,7 +1470,7 @@ pub const Value = struct { | ... | @@ -1462,7 +1470,7 @@ pub const Value = struct { |
| 1462 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { | 1470 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 1463 | .variable => |variable| variable.decl, | 1471 | .variable => |variable| variable.decl, |
| 1464 | .extern_func => |extern_func| extern_func.decl, | 1472 | .extern_func => |extern_func| extern_func.decl, |
| 1465 | .func => |func| mod.funcPtr(func.index).owner_decl, | 1473 | .func => |func| func.owner_decl, |
| 1466 | .ptr => |ptr| switch (ptr.addr) { | 1474 | .ptr => |ptr| switch (ptr.addr) { |
| 1467 | .decl => |decl| decl, | 1475 | .decl => |decl| decl, |
| 1468 | .mut_decl => |mut_decl| mut_decl.decl, | 1476 | .mut_decl => |mut_decl| mut_decl.decl, |
test/behavior/generics.zig+13| ... | @@ -443,3 +443,16 @@ test "generic function passed as comptime argument" { | ... | @@ -443,3 +443,16 @@ test "generic function passed as comptime argument" { |
| 443 | }; | 443 | }; |
| 444 | try S.doMath(std.math.add, 5, 6); | 444 | try S.doMath(std.math.add, 5, 6); |
| 445 | } | 445 | } |
| 446 | |||
| 447 | test "return type of generic function is function pointer" { | ||
| 448 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 449 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 450 | |||
| 451 | const S = struct { | ||
| 452 | fn b(comptime T: type) ?*const fn () error{}!T { | ||
| 453 | return null; | ||
| 454 | } | ||
| 455 | }; | ||
| 456 | |||
| 457 | try expect(null == S.b(void)); | ||
| 458 | } |
test/cases/compile_errors/anytype_param_requires_comptime.zig+4-2| ... | @@ -16,5 +16,7 @@ pub export fn entry() void { | ... | @@ -16,5 +16,7 @@ pub export fn entry() void { |
| 16 | // backend=stage2 | 16 | // backend=stage2 |
| 17 | // target=native | 17 | // target=native |
| 18 | // | 18 | // |
| 19 | // :7:14: error: unable to resolve comptime value | 19 | // :7:14: error: runtime-known argument passed to comptime-only type parameter |
| 20 | // :7:14: note: argument to parameter with comptime-only type must be comptime-known | 20 | // :9:12: note: declared here |
| 21 | // :4:16: note: struct requires comptime because of this field | ||
| 22 | // :4:16: note: types are not available at runtime |
test/cases/compile_errors/export_function_with_comptime_parameter.zig+1-1| ... | @@ -6,4 +6,4 @@ export fn foo(comptime x: anytype, y: i32) i32 { | ... | @@ -6,4 +6,4 @@ export fn foo(comptime x: anytype, y: i32) i32 { |
| 6 | // backend=stage2 | 6 | // backend=stage2 |
| 7 | // target=native | 7 | // target=native |
| 8 | // | 8 | // |
| 9 | // :1:15: error: comptime parameters not allowed in function with calling convention 'C' | 9 | // :1:27: error: comptime parameters not allowed in function with calling convention 'C' |
test/cases/compile_errors/export_generic_function.zig+1-1| ... | @@ -7,4 +7,4 @@ export fn foo(num: anytype) i32 { | ... | @@ -7,4 +7,4 @@ export fn foo(num: anytype) i32 { |
| 7 | // backend=stage2 | 7 | // backend=stage2 |
| 8 | // target=native | 8 | // target=native |
| 9 | // | 9 | // |
| 10 | // :1:15: error: generic parameters not allowed in function with calling convention 'C' | 10 | // :1:20: error: generic parameters not allowed in function with calling convention 'C' |
test/cases/compile_errors/extern_function_with_comptime_parameter.zig+1-1| ... | @@ -19,5 +19,5 @@ comptime { | ... | @@ -19,5 +19,5 @@ comptime { |
| 19 | // target=native | 19 | // target=native |
| 20 | // | 20 | // |
| 21 | // :5:30: error: comptime parameters not allowed in function with calling convention 'C' | 21 | // :5:30: error: comptime parameters not allowed in function with calling convention 'C' |
| 22 | // :6:30: error: generic parameters not allowed in function with calling convention 'C' | 22 | // :6:41: error: generic parameters not allowed in function with calling convention 'C' |
| 23 | // :1:15: error: comptime parameters not allowed in function with calling convention 'C' | 23 | // :1:15: error: comptime parameters not allowed in function with calling convention 'C' |
test/cases/compile_errors/generic_function_instance_with_non-constant_expression.zig+2-2| ... | @@ -13,5 +13,5 @@ export fn entry() usize { | ... | @@ -13,5 +13,5 @@ export fn entry() usize { |
| 13 | // backend=stage2 | 13 | // backend=stage2 |
| 14 | // target=native | 14 | // target=native |
| 15 | // | 15 | // |
| 16 | // :5:16: error: unable to resolve comptime value | 16 | // :5:16: error: runtime-known argument passed to comptime parameter |
| 17 | // :5:16: note: parameter is comptime | 17 | // :1:17: note: declared comptime here |
test/standalone.zig-4| ... | @@ -213,10 +213,6 @@ pub const build_cases = [_]BuildCase{ | ... | @@ -213,10 +213,6 @@ pub const build_cases = [_]BuildCase{ |
| 213 | // .build_root = "test/standalone/sigpipe", | 213 | // .build_root = "test/standalone/sigpipe", |
| 214 | // .import = @import("standalone/sigpipe/build.zig"), | 214 | // .import = @import("standalone/sigpipe/build.zig"), |
| 215 | //}, | 215 | //}, |
| 216 | .{ | ||
| 217 | .build_root = "test/standalone/issue_13030", | ||
| 218 | .import = @import("standalone/issue_13030/build.zig"), | ||
| 219 | }, | ||
| 220 | // TODO restore this test | 216 | // TODO restore this test |
| 221 | //.{ | 217 | //.{ |
| 222 | // .build_root = "test/standalone/options", | 218 | // .build_root = "test/standalone/options", |
test/standalone/issue_13030/build.zig deleted-24| ... | @@ -1,24 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const CrossTarget = std.zig.CrossTarget; | ||
| 4 | |||
| 5 | pub fn build(b: *std.Build) void { | ||
| 6 | const test_step = b.step("test", "Test it"); | ||
| 7 | b.default_step = test_step; | ||
| 8 | |||
| 9 | add(b, test_step, .Debug); | ||
| 10 | add(b, test_step, .ReleaseFast); | ||
| 11 | add(b, test_step, .ReleaseSmall); | ||
| 12 | add(b, test_step, .ReleaseSafe); | ||
| 13 | } | ||
| 14 | |||
| 15 | fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { | ||
| 16 | const obj = b.addObject(.{ | ||
| 17 | .name = "main", | ||
| 18 | .root_source_file = .{ .path = "main.zig" }, | ||
| 19 | .optimize = optimize, | ||
| 20 | .target = .{}, | ||
| 21 | }); | ||
| 22 | |||
| 23 | test_step.dependOn(&obj.step); | ||
| 24 | } | ||
test/standalone/issue_13030/main.zig deleted-7| ... | @@ -1,7 +0,0 @@ | ||
| 1 | fn b(comptime T: type) ?*const fn () error{}!T { | ||
| 2 | return null; | ||
| 3 | } | ||
| 4 | |||
| 5 | export fn entry() void { | ||
| 6 | _ = b(void); | ||
| 7 | } | ||