| author | |
| committer | |
| log | 97aa5f7b8a059f91b78ce7cd70cba0f3aa2c5118 |
| tree | 4e2dc7d8083a24bb01cf8e94e684e3256b7f0a31 |
| parent | 377ecc6afb14a112a07c6d2c3570e2b77b12a116 |
| parent | 38331b1cabf86586bdf70c80ed98f74c60305160 |
| signature |
compiler: namespace type equivalence based on AST node + captures39 files changed, 4063 insertions(+), 2919 deletions(-)
lib/std/zig/AstGen.zig+226-109| ... | @@ -44,6 +44,9 @@ compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{}, | ... | @@ -44,6 +44,9 @@ compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{}, |
| 44 | /// The topmost block of the current function. | 44 | /// The topmost block of the current function. |
| 45 | fn_block: ?*GenZir = null, | 45 | fn_block: ?*GenZir = null, |
| 46 | fn_var_args: bool = false, | 46 | fn_var_args: bool = false, |
| 47 | /// Whether we are somewhere within a function. If `true`, any container decls may be | ||
| 48 | /// generic and thus must be tunneled through closure. | ||
| 49 | within_fn: bool = false, | ||
| 47 | /// The return type of the current function. This may be a trivial `Ref`, or | 50 | /// The return type of the current function. This may be a trivial `Ref`, or |
| 48 | /// otherwise it refers to a `ret_type` instruction. | 51 | /// otherwise it refers to a `ret_type` instruction. |
| 49 | fn_ret_ty: Zir.Inst.Ref = .none, | 52 | fn_ret_ty: Zir.Inst.Ref = .none, |
| ... | @@ -2205,7 +2208,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn | ... | @@ -2205,7 +2208,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2205 | }, | 2208 | }, |
| 2206 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 2209 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2207 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 2210 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2208 | .namespace, .enum_namespace => break, | 2211 | .namespace => break, |
| 2209 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 2212 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2210 | .top => unreachable, | 2213 | .top => unreachable, |
| 2211 | } | 2214 | } |
| ... | @@ -2279,7 +2282,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) | ... | @@ -2279,7 +2282,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2279 | try parent_gz.addDefer(defer_scope.index, defer_scope.len); | 2282 | try parent_gz.addDefer(defer_scope.index, defer_scope.len); |
| 2280 | }, | 2283 | }, |
| 2281 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 2284 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2282 | .namespace, .enum_namespace => break, | 2285 | .namespace => break, |
| 2283 | .top => unreachable, | 2286 | .top => unreachable, |
| 2284 | } | 2287 | } |
| 2285 | } | 2288 | } |
| ... | @@ -2412,7 +2415,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke | ... | @@ -2412,7 +2415,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke |
| 2412 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 2415 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2413 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 2416 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2414 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 2417 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2415 | .namespace, .enum_namespace => break, | 2418 | .namespace => break, |
| 2416 | .top => unreachable, | 2419 | .top => unreachable, |
| 2417 | } | 2420 | } |
| 2418 | } | 2421 | } |
| ... | @@ -2790,7 +2793,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2790,7 +2793,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2790 | .@"resume", | 2793 | .@"resume", |
| 2791 | .@"await", | 2794 | .@"await", |
| 2792 | .ret_err_value_code, | 2795 | .ret_err_value_code, |
| 2793 | .closure_get, | ||
| 2794 | .ret_ptr, | 2796 | .ret_ptr, |
| 2795 | .ret_type, | 2797 | .ret_type, |
| 2796 | .for_len, | 2798 | .for_len, |
| ... | @@ -2860,7 +2862,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2860,7 +2862,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2860 | .store_to_inferred_ptr, | 2862 | .store_to_inferred_ptr, |
| 2861 | .resolve_inferred_alloc, | 2863 | .resolve_inferred_alloc, |
| 2862 | .set_runtime_safety, | 2864 | .set_runtime_safety, |
| 2863 | .closure_capture, | ||
| 2864 | .memcpy, | 2865 | .memcpy, |
| 2865 | .memset, | 2866 | .memset, |
| 2866 | .validate_deref, | 2867 | .validate_deref, |
| ... | @@ -2928,7 +2929,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct { | ... | @@ -2928,7 +2929,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct { |
| 2928 | const have_err_payload = defer_scope.remapped_err_code != .none; | 2929 | const have_err_payload = defer_scope.remapped_err_code != .none; |
| 2929 | need_err_code = need_err_code or have_err_payload; | 2930 | need_err_code = need_err_code or have_err_payload; |
| 2930 | }, | 2931 | }, |
| 2931 | .namespace, .enum_namespace => unreachable, | 2932 | .namespace => unreachable, |
| 2932 | .top => unreachable, | 2933 | .top => unreachable, |
| 2933 | } | 2934 | } |
| 2934 | } | 2935 | } |
| ... | @@ -2998,7 +2999,7 @@ fn genDefers( | ... | @@ -2998,7 +2999,7 @@ fn genDefers( |
| 2998 | .normal_only => continue, | 2999 | .normal_only => continue, |
| 2999 | } | 3000 | } |
| 3000 | }, | 3001 | }, |
| 3001 | .namespace, .enum_namespace => unreachable, | 3002 | .namespace => unreachable, |
| 3002 | .top => unreachable, | 3003 | .top => unreachable, |
| 3003 | } | 3004 | } |
| 3004 | } | 3005 | } |
| ... | @@ -3042,7 +3043,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v | ... | @@ -3042,7 +3043,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v |
| 3042 | scope = s.parent; | 3043 | scope = s.parent; |
| 3043 | }, | 3044 | }, |
| 3044 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 3045 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 3045 | .namespace, .enum_namespace => unreachable, | 3046 | .namespace => unreachable, |
| 3046 | .top => unreachable, | 3047 | .top => unreachable, |
| 3047 | } | 3048 | } |
| 3048 | } | 3049 | } |
| ... | @@ -4052,6 +4053,11 @@ fn fnDecl( | ... | @@ -4052,6 +4053,11 @@ fn fnDecl( |
| 4052 | }; | 4053 | }; |
| 4053 | defer fn_gz.unstack(); | 4054 | defer fn_gz.unstack(); |
| 4054 | 4055 | ||
| 4056 | // Set this now, since parameter types, return type, etc may be generic. | ||
| 4057 | const prev_within_fn = astgen.within_fn; | ||
| 4058 | defer astgen.within_fn = prev_within_fn; | ||
| 4059 | astgen.within_fn = true; | ||
| 4060 | |||
| 4055 | const is_pub = fn_proto.visib_token != null; | 4061 | const is_pub = fn_proto.visib_token != null; |
| 4056 | const is_export = blk: { | 4062 | const is_export = blk: { |
| 4057 | const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false; | 4063 | const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| ... | @@ -4313,6 +4319,10 @@ fn fnDecl( | ... | @@ -4313,6 +4319,10 @@ fn fnDecl( |
| 4313 | 4319 | ||
| 4314 | const prev_fn_block = astgen.fn_block; | 4320 | const prev_fn_block = astgen.fn_block; |
| 4315 | const prev_fn_ret_ty = astgen.fn_ret_ty; | 4321 | const prev_fn_ret_ty = astgen.fn_ret_ty; |
| 4322 | defer { | ||
| 4323 | astgen.fn_block = prev_fn_block; | ||
| 4324 | astgen.fn_ret_ty = prev_fn_ret_ty; | ||
| 4325 | } | ||
| 4316 | astgen.fn_block = &fn_gz; | 4326 | astgen.fn_block = &fn_gz; |
| 4317 | astgen.fn_ret_ty = if (is_inferred_error or ret_ref.toIndex() != null) r: { | 4327 | astgen.fn_ret_ty = if (is_inferred_error or ret_ref.toIndex() != null) r: { |
| 4318 | // We're essentially guaranteed to need the return type at some point, | 4328 | // We're essentially guaranteed to need the return type at some point, |
| ... | @@ -4321,10 +4331,6 @@ fn fnDecl( | ... | @@ -4321,10 +4331,6 @@ fn fnDecl( |
| 4321 | // return type now so the rest of the function can use it. | 4331 | // return type now so the rest of the function can use it. |
| 4322 | break :r try fn_gz.addNode(.ret_type, decl_node); | 4332 | break :r try fn_gz.addNode(.ret_type, decl_node); |
| 4323 | } else ret_ref; | 4333 | } else ret_ref; |
| 4324 | defer { | ||
| 4325 | astgen.fn_block = prev_fn_block; | ||
| 4326 | astgen.fn_ret_ty = prev_fn_ret_ty; | ||
| 4327 | } | ||
| 4328 | 4334 | ||
| 4329 | const prev_var_args = astgen.fn_var_args; | 4335 | const prev_var_args = astgen.fn_var_args; |
| 4330 | astgen.fn_var_args = is_var_args; | 4336 | astgen.fn_var_args = is_var_args; |
| ... | @@ -4732,7 +4738,7 @@ fn testDecl( | ... | @@ -4732,7 +4738,7 @@ fn testDecl( |
| 4732 | }, | 4738 | }, |
| 4733 | .gen_zir => s = s.cast(GenZir).?.parent, | 4739 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 4734 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 4740 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 4735 | .namespace, .enum_namespace => { | 4741 | .namespace => { |
| 4736 | const ns = s.cast(Scope.Namespace).?; | 4742 | const ns = s.cast(Scope.Namespace).?; |
| 4737 | if (ns.decls.get(name_str_index)) |i| { | 4743 | if (ns.decls.get(name_str_index)) |i| { |
| 4738 | if (found_already) |f| { | 4744 | if (found_already) |f| { |
| ... | @@ -4770,11 +4776,14 @@ fn testDecl( | ... | @@ -4770,11 +4776,14 @@ fn testDecl( |
| 4770 | }; | 4776 | }; |
| 4771 | defer fn_block.unstack(); | 4777 | defer fn_block.unstack(); |
| 4772 | 4778 | ||
| 4779 | const prev_within_fn = astgen.within_fn; | ||
| 4773 | const prev_fn_block = astgen.fn_block; | 4780 | const prev_fn_block = astgen.fn_block; |
| 4774 | const prev_fn_ret_ty = astgen.fn_ret_ty; | 4781 | const prev_fn_ret_ty = astgen.fn_ret_ty; |
| 4782 | astgen.within_fn = true; | ||
| 4775 | astgen.fn_block = &fn_block; | 4783 | astgen.fn_block = &fn_block; |
| 4776 | astgen.fn_ret_ty = .anyerror_void_error_union_type; | 4784 | astgen.fn_ret_ty = .anyerror_void_error_union_type; |
| 4777 | defer { | 4785 | defer { |
| 4786 | astgen.within_fn = prev_within_fn; | ||
| 4778 | astgen.fn_block = prev_fn_block; | 4787 | astgen.fn_block = prev_fn_block; |
| 4779 | astgen.fn_ret_ty = prev_fn_ret_ty; | 4788 | astgen.fn_ret_ty = prev_fn_ret_ty; |
| 4780 | } | 4789 | } |
| ... | @@ -4849,10 +4858,10 @@ fn structDeclInner( | ... | @@ -4849,10 +4858,10 @@ fn structDeclInner( |
| 4849 | try gz.setStruct(decl_inst, .{ | 4858 | try gz.setStruct(decl_inst, .{ |
| 4850 | .src_node = node, | 4859 | .src_node = node, |
| 4851 | .layout = layout, | 4860 | .layout = layout, |
| 4861 | .captures_len = 0, | ||
| 4852 | .fields_len = 0, | 4862 | .fields_len = 0, |
| 4853 | .decls_len = 0, | 4863 | .decls_len = 0, |
| 4854 | .backing_int_ref = .none, | 4864 | .has_backing_int = false, |
| 4855 | .backing_int_body_len = 0, | ||
| 4856 | .known_non_opv = false, | 4865 | .known_non_opv = false, |
| 4857 | .known_comptime_only = false, | 4866 | .known_comptime_only = false, |
| 4858 | .is_tuple = false, | 4867 | .is_tuple = false, |
| ... | @@ -4873,6 +4882,7 @@ fn structDeclInner( | ... | @@ -4873,6 +4882,7 @@ fn structDeclInner( |
| 4873 | .node = node, | 4882 | .node = node, |
| 4874 | .inst = decl_inst, | 4883 | .inst = decl_inst, |
| 4875 | .declaring_gz = gz, | 4884 | .declaring_gz = gz, |
| 4885 | .maybe_generic = astgen.within_fn, | ||
| 4876 | }; | 4886 | }; |
| 4877 | defer namespace.deinit(gpa); | 4887 | defer namespace.deinit(gpa); |
| 4878 | 4888 | ||
| ... | @@ -5142,10 +5152,10 @@ fn structDeclInner( | ... | @@ -5142,10 +5152,10 @@ fn structDeclInner( |
| 5142 | try gz.setStruct(decl_inst, .{ | 5152 | try gz.setStruct(decl_inst, .{ |
| 5143 | .src_node = node, | 5153 | .src_node = node, |
| 5144 | .layout = layout, | 5154 | .layout = layout, |
| 5155 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5145 | .fields_len = field_count, | 5156 | .fields_len = field_count, |
| 5146 | .decls_len = decl_count, | 5157 | .decls_len = decl_count, |
| 5147 | .backing_int_ref = backing_int_ref, | 5158 | .has_backing_int = backing_int_ref != .none, |
| 5148 | .backing_int_body_len = @intCast(backing_int_body_len), | ||
| 5149 | .known_non_opv = known_non_opv, | 5159 | .known_non_opv = known_non_opv, |
| 5150 | .known_comptime_only = known_comptime_only, | 5160 | .known_comptime_only = known_comptime_only, |
| 5151 | .is_tuple = is_tuple, | 5161 | .is_tuple = is_tuple, |
| ... | @@ -5159,15 +5169,22 @@ fn structDeclInner( | ... | @@ -5159,15 +5169,22 @@ fn structDeclInner( |
| 5159 | const decls_slice = wip_members.declsSlice(); | 5169 | const decls_slice = wip_members.declsSlice(); |
| 5160 | const fields_slice = wip_members.fieldsSlice(); | 5170 | const fields_slice = wip_members.fieldsSlice(); |
| 5161 | const bodies_slice = astgen.scratch.items[bodies_start..]; | 5171 | const bodies_slice = astgen.scratch.items[bodies_start..]; |
| 5162 | try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + | 5172 | try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + 2 + |
| 5163 | decls_slice.len + fields_slice.len + bodies_slice.len); | 5173 | decls_slice.len + namespace.captures.count() + fields_slice.len + bodies_slice.len); |
| 5164 | astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]); | 5174 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); |
| 5175 | if (backing_int_ref != .none) { | ||
| 5176 | astgen.extra.appendAssumeCapacity(@intCast(backing_int_body_len)); | ||
| 5177 | if (backing_int_body_len == 0) { | ||
| 5178 | astgen.extra.appendAssumeCapacity(@intFromEnum(backing_int_ref)); | ||
| 5179 | } else { | ||
| 5180 | astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]); | ||
| 5181 | } | ||
| 5182 | } | ||
| 5165 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5183 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5166 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 5184 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5167 | astgen.extra.appendSliceAssumeCapacity(bodies_slice); | 5185 | astgen.extra.appendSliceAssumeCapacity(bodies_slice); |
| 5168 | 5186 | ||
| 5169 | block_scope.unstack(); | 5187 | block_scope.unstack(); |
| 5170 | try gz.addNamespaceCaptures(&namespace); | ||
| 5171 | return decl_inst.toRef(); | 5188 | return decl_inst.toRef(); |
| 5172 | } | 5189 | } |
| 5173 | 5190 | ||
| ... | @@ -5190,6 +5207,7 @@ fn unionDeclInner( | ... | @@ -5190,6 +5207,7 @@ fn unionDeclInner( |
| 5190 | .node = node, | 5207 | .node = node, |
| 5191 | .inst = decl_inst, | 5208 | .inst = decl_inst, |
| 5192 | .declaring_gz = gz, | 5209 | .declaring_gz = gz, |
| 5210 | .maybe_generic = astgen.within_fn, | ||
| 5193 | }; | 5211 | }; |
| 5194 | defer namespace.deinit(gpa); | 5212 | defer namespace.deinit(gpa); |
| 5195 | 5213 | ||
| ... | @@ -5368,6 +5386,7 @@ fn unionDeclInner( | ... | @@ -5368,6 +5386,7 @@ fn unionDeclInner( |
| 5368 | .src_node = node, | 5386 | .src_node = node, |
| 5369 | .layout = layout, | 5387 | .layout = layout, |
| 5370 | .tag_type = arg_inst, | 5388 | .tag_type = arg_inst, |
| 5389 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5371 | .body_len = body_len, | 5390 | .body_len = body_len, |
| 5372 | .fields_len = field_count, | 5391 | .fields_len = field_count, |
| 5373 | .decls_len = decl_count, | 5392 | .decls_len = decl_count, |
| ... | @@ -5379,13 +5398,13 @@ fn unionDeclInner( | ... | @@ -5379,13 +5398,13 @@ fn unionDeclInner( |
| 5379 | wip_members.finishBits(bits_per_field); | 5398 | wip_members.finishBits(bits_per_field); |
| 5380 | const decls_slice = wip_members.declsSlice(); | 5399 | const decls_slice = wip_members.declsSlice(); |
| 5381 | const fields_slice = wip_members.fieldsSlice(); | 5400 | const fields_slice = wip_members.fieldsSlice(); |
| 5382 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len); | 5401 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len + body_len + fields_slice.len); |
| 5402 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | ||
| 5383 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5403 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5384 | astgen.appendBodyWithFixups(body); | 5404 | astgen.appendBodyWithFixups(body); |
| 5385 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 5405 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5386 | 5406 | ||
| 5387 | block_scope.unstack(); | 5407 | block_scope.unstack(); |
| 5388 | try gz.addNamespaceCaptures(&namespace); | ||
| 5389 | return decl_inst.toRef(); | 5408 | return decl_inst.toRef(); |
| 5390 | } | 5409 | } |
| 5391 | 5410 | ||
| ... | @@ -5537,6 +5556,7 @@ fn containerDecl( | ... | @@ -5537,6 +5556,7 @@ fn containerDecl( |
| 5537 | .node = node, | 5556 | .node = node, |
| 5538 | .inst = decl_inst, | 5557 | .inst = decl_inst, |
| 5539 | .declaring_gz = gz, | 5558 | .declaring_gz = gz, |
| 5559 | .maybe_generic = astgen.within_fn, | ||
| 5540 | }; | 5560 | }; |
| 5541 | defer namespace.deinit(gpa); | 5561 | defer namespace.deinit(gpa); |
| 5542 | 5562 | ||
| ... | @@ -5555,7 +5575,7 @@ fn containerDecl( | ... | @@ -5555,7 +5575,7 @@ fn containerDecl( |
| 5555 | defer block_scope.unstack(); | 5575 | defer block_scope.unstack(); |
| 5556 | 5576 | ||
| 5557 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); | 5577 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 5558 | namespace.base.tag = .enum_namespace; | 5578 | namespace.base.tag = .namespace; |
| 5559 | 5579 | ||
| 5560 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) | 5580 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) |
| 5561 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg) | 5581 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg) |
| ... | @@ -5586,7 +5606,6 @@ fn containerDecl( | ... | @@ -5586,7 +5606,6 @@ fn containerDecl( |
| 5586 | if (member_node == counts.nonexhaustive_node) | 5606 | if (member_node == counts.nonexhaustive_node) |
| 5587 | continue; | 5607 | continue; |
| 5588 | fields_hasher.update(tree.getNodeSource(member_node)); | 5608 | fields_hasher.update(tree.getNodeSource(member_node)); |
| 5589 | namespace.base.tag = .namespace; | ||
| 5590 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { | 5609 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5591 | .decl => continue, | 5610 | .decl => continue, |
| 5592 | .field => |field| field, | 5611 | .field => |field| field, |
| ... | @@ -5630,7 +5649,6 @@ fn containerDecl( | ... | @@ -5630,7 +5649,6 @@ fn containerDecl( |
| 5630 | }, | 5649 | }, |
| 5631 | ); | 5650 | ); |
| 5632 | } | 5651 | } |
| 5633 | namespace.base.tag = .enum_namespace; | ||
| 5634 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); | 5652 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); |
| 5635 | wip_members.appendToField(@intFromEnum(tag_value_inst)); | 5653 | wip_members.appendToField(@intFromEnum(tag_value_inst)); |
| 5636 | } | 5654 | } |
| ... | @@ -5676,6 +5694,7 @@ fn containerDecl( | ... | @@ -5676,6 +5694,7 @@ fn containerDecl( |
| 5676 | .src_node = node, | 5694 | .src_node = node, |
| 5677 | .nonexhaustive = nonexhaustive, | 5695 | .nonexhaustive = nonexhaustive, |
| 5678 | .tag_type = arg_inst, | 5696 | .tag_type = arg_inst, |
| 5697 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5679 | .body_len = body_len, | 5698 | .body_len = body_len, |
| 5680 | .fields_len = @intCast(counts.total_fields), | 5699 | .fields_len = @intCast(counts.total_fields), |
| 5681 | .decls_len = @intCast(counts.decls), | 5700 | .decls_len = @intCast(counts.decls), |
| ... | @@ -5685,13 +5704,13 @@ fn containerDecl( | ... | @@ -5685,13 +5704,13 @@ fn containerDecl( |
| 5685 | wip_members.finishBits(bits_per_field); | 5704 | wip_members.finishBits(bits_per_field); |
| 5686 | const decls_slice = wip_members.declsSlice(); | 5705 | const decls_slice = wip_members.declsSlice(); |
| 5687 | const fields_slice = wip_members.fieldsSlice(); | 5706 | const fields_slice = wip_members.fieldsSlice(); |
| 5688 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len); | 5707 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len + body_len + fields_slice.len); |
| 5708 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | ||
| 5689 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5709 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5690 | astgen.appendBodyWithFixups(body); | 5710 | astgen.appendBodyWithFixups(body); |
| 5691 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 5711 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5692 | 5712 | ||
| 5693 | block_scope.unstack(); | 5713 | block_scope.unstack(); |
| 5694 | try gz.addNamespaceCaptures(&namespace); | ||
| 5695 | return rvalue(gz, ri, decl_inst.toRef(), node); | 5714 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5696 | }, | 5715 | }, |
| 5697 | .keyword_opaque => { | 5716 | .keyword_opaque => { |
| ... | @@ -5704,6 +5723,7 @@ fn containerDecl( | ... | @@ -5704,6 +5723,7 @@ fn containerDecl( |
| 5704 | .node = node, | 5723 | .node = node, |
| 5705 | .inst = decl_inst, | 5724 | .inst = decl_inst, |
| 5706 | .declaring_gz = gz, | 5725 | .declaring_gz = gz, |
| 5726 | .maybe_generic = astgen.within_fn, | ||
| 5707 | }; | 5727 | }; |
| 5708 | defer namespace.deinit(gpa); | 5728 | defer namespace.deinit(gpa); |
| 5709 | 5729 | ||
| ... | @@ -5733,16 +5753,17 @@ fn containerDecl( | ... | @@ -5733,16 +5753,17 @@ fn containerDecl( |
| 5733 | 5753 | ||
| 5734 | try gz.setOpaque(decl_inst, .{ | 5754 | try gz.setOpaque(decl_inst, .{ |
| 5735 | .src_node = node, | 5755 | .src_node = node, |
| 5756 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5736 | .decls_len = decl_count, | 5757 | .decls_len = decl_count, |
| 5737 | }); | 5758 | }); |
| 5738 | 5759 | ||
| 5739 | wip_members.finishBits(0); | 5760 | wip_members.finishBits(0); |
| 5740 | const decls_slice = wip_members.declsSlice(); | 5761 | const decls_slice = wip_members.declsSlice(); |
| 5741 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len); | 5762 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len); |
| 5763 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | ||
| 5742 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5764 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5743 | 5765 | ||
| 5744 | block_scope.unstack(); | 5766 | block_scope.unstack(); |
| 5745 | try gz.addNamespaceCaptures(&namespace); | ||
| 5746 | return rvalue(gz, ri, decl_inst.toRef(), node); | 5767 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5747 | }, | 5768 | }, |
| 5748 | else => unreachable, | 5769 | else => unreachable, |
| ... | @@ -8238,12 +8259,17 @@ fn localVarRef( | ... | @@ -8238,12 +8259,17 @@ fn localVarRef( |
| 8238 | ident_token: Ast.TokenIndex, | 8259 | ident_token: Ast.TokenIndex, |
| 8239 | ) InnerError!Zir.Inst.Ref { | 8260 | ) InnerError!Zir.Inst.Ref { |
| 8240 | const astgen = gz.astgen; | 8261 | const astgen = gz.astgen; |
| 8241 | const gpa = astgen.gpa; | ||
| 8242 | const name_str_index = try astgen.identAsString(ident_token); | 8262 | const name_str_index = try astgen.identAsString(ident_token); |
| 8243 | var s = scope; | 8263 | var s = scope; |
| 8244 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already | 8264 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already |
| 8265 | var found_needs_tunnel: bool = undefined; // defined when `found_already != null` | ||
| 8266 | var found_namespaces_out: u32 = undefined; // defined when `found_already != null` | ||
| 8267 | |||
| 8268 | // The number of namespaces above `gz` we currently are | ||
| 8245 | var num_namespaces_out: u32 = 0; | 8269 | var num_namespaces_out: u32 = 0; |
| 8246 | var capturing_namespace: ?*Scope.Namespace = null; | 8270 | // defined by `num_namespaces_out != 0` |
| 8271 | var capturing_namespace: *Scope.Namespace = undefined; | ||
| 8272 | |||
| 8247 | while (true) switch (s.tag) { | 8273 | while (true) switch (s.tag) { |
| 8248 | .local_val => { | 8274 | .local_val => { |
| 8249 | const local_val = s.cast(Scope.LocalVal).?; | 8275 | const local_val = s.cast(Scope.LocalVal).?; |
| ... | @@ -8257,15 +8283,13 @@ fn localVarRef( | ... | @@ -8257,15 +8283,13 @@ fn localVarRef( |
| 8257 | local_val.used = ident_token; | 8283 | local_val.used = ident_token; |
| 8258 | } | 8284 | } |
| 8259 | 8285 | ||
| 8260 | const value_inst = try tunnelThroughClosure( | 8286 | const value_inst = if (num_namespaces_out != 0) try tunnelThroughClosure( |
| 8261 | gz, | 8287 | gz, |
| 8262 | ident, | 8288 | ident, |
| 8263 | num_namespaces_out, | 8289 | num_namespaces_out, |
| 8264 | capturing_namespace, | 8290 | .{ .ref = local_val.inst }, |
| 8265 | local_val.inst, | 8291 | .{ .token = local_val.token_src }, |
| 8266 | local_val.token_src, | 8292 | ) else local_val.inst; |
| 8267 | gpa, | ||
| 8268 | ); | ||
| 8269 | 8293 | ||
| 8270 | return rvalueNoCoercePreRef(gz, ri, value_inst, ident); | 8294 | return rvalueNoCoercePreRef(gz, ri, value_inst, ident); |
| 8271 | } | 8295 | } |
| ... | @@ -8285,19 +8309,17 @@ fn localVarRef( | ... | @@ -8285,19 +8309,17 @@ fn localVarRef( |
| 8285 | const ident_name = try astgen.identifierTokenString(ident_token); | 8309 | const ident_name = try astgen.identifierTokenString(ident_token); |
| 8286 | return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{ | 8310 | return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{ |
| 8287 | try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}), | 8311 | try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}), |
| 8288 | try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}), | 8312 | try astgen.errNoteNode(capturing_namespace.node, "crosses namespace boundary here", .{}), |
| 8289 | }); | 8313 | }); |
| 8290 | } | 8314 | } |
| 8291 | 8315 | ||
| 8292 | const ptr_inst = try tunnelThroughClosure( | 8316 | const ptr_inst = if (num_namespaces_out != 0) try tunnelThroughClosure( |
| 8293 | gz, | 8317 | gz, |
| 8294 | ident, | 8318 | ident, |
| 8295 | num_namespaces_out, | 8319 | num_namespaces_out, |
| 8296 | capturing_namespace, | 8320 | .{ .ref = local_ptr.ptr }, |
| 8297 | local_ptr.ptr, | 8321 | .{ .token = local_ptr.token_src }, |
| 8298 | local_ptr.token_src, | 8322 | ) else local_ptr.ptr; |
| 8299 | gpa, | ||
| 8300 | ); | ||
| 8301 | 8323 | ||
| 8302 | switch (ri.rl) { | 8324 | switch (ri.rl) { |
| 8303 | .ref, .ref_coerced_ty => { | 8325 | .ref, .ref_coerced_ty => { |
| ... | @@ -8314,7 +8336,7 @@ fn localVarRef( | ... | @@ -8314,7 +8336,7 @@ fn localVarRef( |
| 8314 | }, | 8336 | }, |
| 8315 | .gen_zir => s = s.cast(GenZir).?.parent, | 8337 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 8316 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 8338 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 8317 | .namespace, .enum_namespace => { | 8339 | .namespace => { |
| 8318 | const ns = s.cast(Scope.Namespace).?; | 8340 | const ns = s.cast(Scope.Namespace).?; |
| 8319 | if (ns.decls.get(name_str_index)) |i| { | 8341 | if (ns.decls.get(name_str_index)) |i| { |
| 8320 | if (found_already) |f| { | 8342 | if (found_already) |f| { |
| ... | @@ -8325,8 +8347,10 @@ fn localVarRef( | ... | @@ -8325,8 +8347,10 @@ fn localVarRef( |
| 8325 | } | 8347 | } |
| 8326 | // We found a match but must continue looking for ambiguous references to decls. | 8348 | // We found a match but must continue looking for ambiguous references to decls. |
| 8327 | found_already = i; | 8349 | found_already = i; |
| 8350 | found_needs_tunnel = ns.maybe_generic; | ||
| 8351 | found_namespaces_out = num_namespaces_out; | ||
| 8328 | } | 8352 | } |
| 8329 | if (s.tag == .namespace) num_namespaces_out += 1; | 8353 | num_namespaces_out += 1; |
| 8330 | capturing_namespace = ns; | 8354 | capturing_namespace = ns; |
| 8331 | s = ns.parent; | 8355 | s = ns.parent; |
| 8332 | }, | 8356 | }, |
| ... | @@ -8339,6 +8363,29 @@ fn localVarRef( | ... | @@ -8339,6 +8363,29 @@ fn localVarRef( |
| 8339 | 8363 | ||
| 8340 | // Decl references happen by name rather than ZIR index so that when unrelated | 8364 | // Decl references happen by name rather than ZIR index so that when unrelated |
| 8341 | // decls are modified, ZIR code containing references to them can be unmodified. | 8365 | // decls are modified, ZIR code containing references to them can be unmodified. |
| 8366 | |||
| 8367 | if (found_namespaces_out > 0 and found_needs_tunnel) { | ||
| 8368 | switch (ri.rl) { | ||
| 8369 | .ref, .ref_coerced_ty => return tunnelThroughClosure( | ||
| 8370 | gz, | ||
| 8371 | ident, | ||
| 8372 | found_namespaces_out, | ||
| 8373 | .{ .decl_ref = name_str_index }, | ||
| 8374 | .{ .node = found_already.? }, | ||
| 8375 | ), | ||
| 8376 | else => { | ||
| 8377 | const result = try tunnelThroughClosure( | ||
| 8378 | gz, | ||
| 8379 | ident, | ||
| 8380 | found_namespaces_out, | ||
| 8381 | .{ .decl_val = name_str_index }, | ||
| 8382 | .{ .node = found_already.? }, | ||
| 8383 | ); | ||
| 8384 | return rvalueNoCoercePreRef(gz, ri, result, ident); | ||
| 8385 | }, | ||
| 8386 | } | ||
| 8387 | } | ||
| 8388 | |||
| 8342 | switch (ri.rl) { | 8389 | switch (ri.rl) { |
| 8343 | .ref, .ref_coerced_ty => return gz.addStrTok(.decl_ref, name_str_index, ident_token), | 8390 | .ref, .ref_coerced_ty => return gz.addStrTok(.decl_ref, name_str_index, ident_token), |
| 8344 | else => { | 8391 | else => { |
| ... | @@ -8348,41 +8395,90 @@ fn localVarRef( | ... | @@ -8348,41 +8395,90 @@ fn localVarRef( |
| 8348 | } | 8395 | } |
| 8349 | } | 8396 | } |
| 8350 | 8397 | ||
| 8351 | /// Adds a capture to a namespace, if needed. | 8398 | /// Access a ZIR instruction through closure. May tunnel through arbitrarily |
| 8352 | /// Returns the index of the closure_capture instruction. | 8399 | /// many namespaces, adding closure captures as required. |
| 8400 | /// Returns the index of the `closure_get` instruction added to `gz`. | ||
| 8353 | fn tunnelThroughClosure( | 8401 | fn tunnelThroughClosure( |
| 8354 | gz: *GenZir, | 8402 | gz: *GenZir, |
| 8403 | /// The node which references the value to be captured. | ||
| 8355 | inner_ref_node: Ast.Node.Index, | 8404 | inner_ref_node: Ast.Node.Index, |
| 8405 | /// The number of namespaces being tunnelled through. At least 1. | ||
| 8356 | num_tunnels: u32, | 8406 | num_tunnels: u32, |
| 8357 | ns: ?*Scope.Namespace, | 8407 | /// The value being captured. |
| 8358 | value: Zir.Inst.Ref, | 8408 | value: union(enum) { |
| 8359 | token: Ast.TokenIndex, | 8409 | ref: Zir.Inst.Ref, |
| 8360 | gpa: Allocator, | 8410 | decl_val: Zir.NullTerminatedString, |
| 8411 | decl_ref: Zir.NullTerminatedString, | ||
| 8412 | }, | ||
| 8413 | /// The location of the value's declaration. | ||
| 8414 | decl_src: union(enum) { | ||
| 8415 | token: Ast.TokenIndex, | ||
| 8416 | node: Ast.Node.Index, | ||
| 8417 | }, | ||
| 8361 | ) !Zir.Inst.Ref { | 8418 | ) !Zir.Inst.Ref { |
| 8362 | // For trivial values, we don't need a tunnel. | 8419 | switch (value) { |
| 8363 | // Just return the ref. | 8420 | .ref => |v| if (v.toIndex() == null) return v, // trivia value; do not need tunnel |
| 8364 | if (num_tunnels == 0 or value.toIndex() == null) { | 8421 | .decl_val, .decl_ref => {}, |
| 8365 | return value; | ||
| 8366 | } | 8422 | } |
| 8367 | 8423 | ||
| 8368 | // Otherwise we need a tunnel. Check if this namespace | 8424 | const astgen = gz.astgen; |
| 8369 | // already has one for this value. | 8425 | const gpa = astgen.gpa; |
| 8370 | const gop = try ns.?.captures.getOrPut(gpa, value.toIndex().?); | 8426 | |
| 8371 | if (!gop.found_existing) { | 8427 | // Otherwise we need a tunnel. First, figure out the path of namespaces we |
| 8372 | // Make a new capture for this value but don't add it to the declaring_gz yet | 8428 | // are tunneling through. This is usually only going to be one or two, so |
| 8373 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ | 8429 | // use an SFBA to optimize for the common case. |
| 8374 | .tag = .closure_capture, | 8430 | var sfba = std.heap.stackFallback(@sizeOf(usize) * 2, astgen.arena); |
| 8375 | .data = .{ .un_tok = .{ | 8431 | var intermediate_tunnels = try sfba.get().alloc(*Scope.Namespace, num_tunnels - 1); |
| 8376 | .operand = value, | 8432 | |
| 8377 | .src_tok = ns.?.declaring_gz.?.tokenIndexToRelative(token), | 8433 | const root_ns = ns: { |
| 8378 | } }, | 8434 | var i: usize = num_tunnels - 1; |
| 8435 | var scope: *Scope = gz.parent; | ||
| 8436 | while (i > 0) { | ||
| 8437 | if (scope.cast(Scope.Namespace)) |mid_ns| { | ||
| 8438 | i -= 1; | ||
| 8439 | intermediate_tunnels[i] = mid_ns; | ||
| 8440 | } | ||
| 8441 | scope = scope.parent().?; | ||
| 8442 | } | ||
| 8443 | while (true) { | ||
| 8444 | if (scope.cast(Scope.Namespace)) |ns| break :ns ns; | ||
| 8445 | scope = scope.parent().?; | ||
| 8446 | } | ||
| 8447 | }; | ||
| 8448 | |||
| 8449 | // Now that we know the scopes we're tunneling through, begin adding | ||
| 8450 | // captures as required, starting with the outermost namespace. | ||
| 8451 | const root_capture = Zir.Inst.Capture.wrap(switch (value) { | ||
| 8452 | .ref => |v| .{ .instruction = v.toIndex().? }, | ||
| 8453 | .decl_val => |str| .{ .decl_val = str }, | ||
| 8454 | .decl_ref => |str| .{ .decl_ref = str }, | ||
| 8455 | }); | ||
| 8456 | var cur_capture_index = std.math.cast( | ||
| 8457 | u16, | ||
| 8458 | (try root_ns.captures.getOrPut(gpa, root_capture)).index, | ||
| 8459 | ) orelse return astgen.failNodeNotes(root_ns.node, "this compiler implementation only supports up to 65536 captures per namespace", .{}, &.{ | ||
| 8460 | switch (decl_src) { | ||
| 8461 | .token => |t| try astgen.errNoteTok(t, "captured value here", .{}), | ||
| 8462 | .node => |n| try astgen.errNoteNode(n, "captured value here", .{}), | ||
| 8463 | }, | ||
| 8464 | try astgen.errNoteNode(inner_ref_node, "value used here", .{}), | ||
| 8465 | }); | ||
| 8466 | |||
| 8467 | for (intermediate_tunnels) |tunnel_ns| { | ||
| 8468 | cur_capture_index = std.math.cast( | ||
| 8469 | u16, | ||
| 8470 | (try tunnel_ns.captures.getOrPut(gpa, Zir.Inst.Capture.wrap(.{ .nested = cur_capture_index }))).index, | ||
| 8471 | ) orelse return astgen.failNodeNotes(tunnel_ns.node, "this compiler implementation only supports up to 65536 captures per namespace", .{}, &.{ | ||
| 8472 | switch (decl_src) { | ||
| 8473 | .token => |t| try astgen.errNoteTok(t, "captured value here", .{}), | ||
| 8474 | .node => |n| try astgen.errNoteNode(n, "captured value here", .{}), | ||
| 8475 | }, | ||
| 8476 | try astgen.errNoteNode(inner_ref_node, "value used here", .{}), | ||
| 8379 | }); | 8477 | }); |
| 8380 | gop.value_ptr.* = @enumFromInt(gz.astgen.instructions.len - 1); | ||
| 8381 | } | 8478 | } |
| 8382 | 8479 | ||
| 8383 | // Add an instruction to get the value from the closure into | 8480 | // Add an instruction to get the value from the closure. |
| 8384 | // our current context | 8481 | return gz.addExtendedNodeSmall(.closure_get, inner_ref_node, cur_capture_index); |
| 8385 | return try gz.addInstNode(.closure_get, gop.value_ptr.*, inner_ref_node); | ||
| 8386 | } | 8482 | } |
| 8387 | 8483 | ||
| 8388 | fn stringLiteral( | 8484 | fn stringLiteral( |
| ... | @@ -9095,7 +9191,7 @@ fn builtinCall( | ... | @@ -9095,7 +9191,7 @@ fn builtinCall( |
| 9095 | }, | 9191 | }, |
| 9096 | .gen_zir => s = s.cast(GenZir).?.parent, | 9192 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 9097 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 9193 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 9098 | .namespace, .enum_namespace => { | 9194 | .namespace => { |
| 9099 | const ns = s.cast(Scope.Namespace).?; | 9195 | const ns = s.cast(Scope.Namespace).?; |
| 9100 | if (ns.decls.get(decl_name)) |i| { | 9196 | if (ns.decls.get(decl_name)) |i| { |
| 9101 | if (found_already) |f| { | 9197 | if (found_already) |f| { |
| ... | @@ -11605,7 +11701,7 @@ const Scope = struct { | ... | @@ -11605,7 +11701,7 @@ const Scope = struct { |
| 11605 | } | 11701 | } |
| 11606 | if (T == Namespace) { | 11702 | if (T == Namespace) { |
| 11607 | switch (base.tag) { | 11703 | switch (base.tag) { |
| 11608 | .namespace, .enum_namespace => return @fieldParentPtr(T, "base", base), | 11704 | .namespace => return @fieldParentPtr(T, "base", base), |
| 11609 | else => return null, | 11705 | else => return null, |
| 11610 | } | 11706 | } |
| 11611 | } | 11707 | } |
| ... | @@ -11621,7 +11717,7 @@ const Scope = struct { | ... | @@ -11621,7 +11717,7 @@ const Scope = struct { |
| 11621 | .local_val => base.cast(LocalVal).?.parent, | 11717 | .local_val => base.cast(LocalVal).?.parent, |
| 11622 | .local_ptr => base.cast(LocalPtr).?.parent, | 11718 | .local_ptr => base.cast(LocalPtr).?.parent, |
| 11623 | .defer_normal, .defer_error => base.cast(Defer).?.parent, | 11719 | .defer_normal, .defer_error => base.cast(Defer).?.parent, |
| 11624 | .namespace, .enum_namespace => base.cast(Namespace).?.parent, | 11720 | .namespace => base.cast(Namespace).?.parent, |
| 11625 | .top => null, | 11721 | .top => null, |
| 11626 | }; | 11722 | }; |
| 11627 | } | 11723 | } |
| ... | @@ -11633,7 +11729,6 @@ const Scope = struct { | ... | @@ -11633,7 +11729,6 @@ const Scope = struct { |
| 11633 | defer_normal, | 11729 | defer_normal, |
| 11634 | defer_error, | 11730 | defer_error, |
| 11635 | namespace, | 11731 | namespace, |
| 11636 | enum_namespace, | ||
| 11637 | top, | 11732 | top, |
| 11638 | }; | 11733 | }; |
| 11639 | 11734 | ||
| ... | @@ -11720,14 +11815,14 @@ const Scope = struct { | ... | @@ -11720,14 +11815,14 @@ const Scope = struct { |
| 11720 | decls: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.Node.Index) = .{}, | 11815 | decls: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.Node.Index) = .{}, |
| 11721 | node: Ast.Node.Index, | 11816 | node: Ast.Node.Index, |
| 11722 | inst: Zir.Inst.Index, | 11817 | inst: Zir.Inst.Index, |
| 11818 | maybe_generic: bool, | ||
| 11723 | 11819 | ||
| 11724 | /// The astgen scope containing this namespace. | 11820 | /// The astgen scope containing this namespace. |
| 11725 | /// Only valid during astgen. | 11821 | /// Only valid during astgen. |
| 11726 | declaring_gz: ?*GenZir, | 11822 | declaring_gz: ?*GenZir, |
| 11727 | 11823 | ||
| 11728 | /// Map from the raw captured value to the instruction | 11824 | /// Set of captures used by this namespace. |
| 11729 | /// ref of the capture for decls in this namespace | 11825 | captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Capture, void) = .{}, |
| 11730 | captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, | ||
| 11731 | 11826 | ||
| 11732 | fn deinit(self: *Namespace, gpa: Allocator) void { | 11827 | fn deinit(self: *Namespace, gpa: Allocator) void { |
| 11733 | self.decls.deinit(gpa); | 11828 | self.decls.deinit(gpa); |
| ... | @@ -11787,12 +11882,6 @@ const GenZir = struct { | ... | @@ -11787,12 +11882,6 @@ const GenZir = struct { |
| 11787 | // Set if this GenZir is a defer or it is inside a defer. | 11882 | // Set if this GenZir is a defer or it is inside a defer. |
| 11788 | any_defer_node: Ast.Node.Index = 0, | 11883 | any_defer_node: Ast.Node.Index = 0, |
| 11789 | 11884 | ||
| 11790 | /// Namespace members are lazy. When executing a decl within a namespace, | ||
| 11791 | /// any references to external instructions need to be treated specially. | ||
| 11792 | /// This list tracks those references. See also .closure_capture and .closure_get. | ||
| 11793 | /// Keys are the raw instruction index, values are the closure_capture instruction. | ||
| 11794 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, | ||
| 11795 | |||
| 11796 | const unstacked_top = std.math.maxInt(usize); | 11885 | const unstacked_top = std.math.maxInt(usize); |
| 11797 | /// Call unstack before adding any new instructions to containing GenZir. | 11886 | /// Call unstack before adding any new instructions to containing GenZir. |
| 11798 | fn unstack(self: *GenZir) void { | 11887 | fn unstack(self: *GenZir) void { |
| ... | @@ -12534,6 +12623,30 @@ const GenZir = struct { | ... | @@ -12534,6 +12623,30 @@ const GenZir = struct { |
| 12534 | return new_index.toRef(); | 12623 | return new_index.toRef(); |
| 12535 | } | 12624 | } |
| 12536 | 12625 | ||
| 12626 | fn addExtendedNodeSmall( | ||
| 12627 | gz: *GenZir, | ||
| 12628 | opcode: Zir.Inst.Extended, | ||
| 12629 | src_node: Ast.Node.Index, | ||
| 12630 | small: u16, | ||
| 12631 | ) !Zir.Inst.Ref { | ||
| 12632 | const astgen = gz.astgen; | ||
| 12633 | const gpa = astgen.gpa; | ||
| 12634 | |||
| 12635 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | ||
| 12636 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | ||
| 12637 | const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); | ||
| 12638 | astgen.instructions.appendAssumeCapacity(.{ | ||
| 12639 | .tag = .extended, | ||
| 12640 | .data = .{ .extended = .{ | ||
| 12641 | .opcode = opcode, | ||
| 12642 | .small = small, | ||
| 12643 | .operand = @bitCast(gz.nodeIndexToRelative(src_node)), | ||
| 12644 | } }, | ||
| 12645 | }); | ||
| 12646 | gz.instructions.appendAssumeCapacity(new_index); | ||
| 12647 | return new_index.toRef(); | ||
| 12648 | } | ||
| 12649 | |||
| 12537 | fn addUnTok( | 12650 | fn addUnTok( |
| 12538 | gz: *GenZir, | 12651 | gz: *GenZir, |
| 12539 | tag: Zir.Inst.Tag, | 12652 | tag: Zir.Inst.Tag, |
| ... | @@ -12957,10 +13070,10 @@ const GenZir = struct { | ... | @@ -12957,10 +13070,10 @@ const GenZir = struct { |
| 12957 | 13070 | ||
| 12958 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13071 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 12959 | src_node: Ast.Node.Index, | 13072 | src_node: Ast.Node.Index, |
| 13073 | captures_len: u32, | ||
| 12960 | fields_len: u32, | 13074 | fields_len: u32, |
| 12961 | decls_len: u32, | 13075 | decls_len: u32, |
| 12962 | backing_int_ref: Zir.Inst.Ref, | 13076 | has_backing_int: bool, |
| 12963 | backing_int_body_len: u32, | ||
| 12964 | layout: std.builtin.Type.ContainerLayout, | 13077 | layout: std.builtin.Type.ContainerLayout, |
| 12965 | known_non_opv: bool, | 13078 | known_non_opv: bool, |
| 12966 | known_comptime_only: bool, | 13079 | known_comptime_only: bool, |
| ... | @@ -12978,7 +13091,7 @@ const GenZir = struct { | ... | @@ -12978,7 +13091,7 @@ const GenZir = struct { |
| 12978 | 13091 | ||
| 12979 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 13092 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 12980 | 13093 | ||
| 12981 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 4); | 13094 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 3); |
| 12982 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ | 13095 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ |
| 12983 | .fields_hash_0 = fields_hash_arr[0], | 13096 | .fields_hash_0 = fields_hash_arr[0], |
| 12984 | .fields_hash_1 = fields_hash_arr[1], | 13097 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -12987,26 +13100,24 @@ const GenZir = struct { | ... | @@ -12987,26 +13100,24 @@ const GenZir = struct { |
| 12987 | .src_node = gz.nodeIndexToRelative(args.src_node), | 13100 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 12988 | }); | 13101 | }); |
| 12989 | 13102 | ||
| 13103 | if (args.captures_len != 0) { | ||
| 13104 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13105 | } | ||
| 12990 | if (args.fields_len != 0) { | 13106 | if (args.fields_len != 0) { |
| 12991 | astgen.extra.appendAssumeCapacity(args.fields_len); | 13107 | astgen.extra.appendAssumeCapacity(args.fields_len); |
| 12992 | } | 13108 | } |
| 12993 | if (args.decls_len != 0) { | 13109 | if (args.decls_len != 0) { |
| 12994 | astgen.extra.appendAssumeCapacity(args.decls_len); | 13110 | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 12995 | } | 13111 | } |
| 12996 | if (args.backing_int_ref != .none) { | ||
| 12997 | astgen.extra.appendAssumeCapacity(args.backing_int_body_len); | ||
| 12998 | if (args.backing_int_body_len == 0) { | ||
| 12999 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_ref)); | ||
| 13000 | } | ||
| 13001 | } | ||
| 13002 | astgen.instructions.set(@intFromEnum(inst), .{ | 13112 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13003 | .tag = .extended, | 13113 | .tag = .extended, |
| 13004 | .data = .{ .extended = .{ | 13114 | .data = .{ .extended = .{ |
| 13005 | .opcode = .struct_decl, | 13115 | .opcode = .struct_decl, |
| 13006 | .small = @bitCast(Zir.Inst.StructDecl.Small{ | 13116 | .small = @bitCast(Zir.Inst.StructDecl.Small{ |
| 13117 | .has_captures_len = args.captures_len != 0, | ||
| 13007 | .has_fields_len = args.fields_len != 0, | 13118 | .has_fields_len = args.fields_len != 0, |
| 13008 | .has_decls_len = args.decls_len != 0, | 13119 | .has_decls_len = args.decls_len != 0, |
| 13009 | .has_backing_int = args.backing_int_ref != .none, | 13120 | .has_backing_int = args.has_backing_int, |
| 13010 | .known_non_opv = args.known_non_opv, | 13121 | .known_non_opv = args.known_non_opv, |
| 13011 | .known_comptime_only = args.known_comptime_only, | 13122 | .known_comptime_only = args.known_comptime_only, |
| 13012 | .is_tuple = args.is_tuple, | 13123 | .is_tuple = args.is_tuple, |
| ... | @@ -13024,6 +13135,7 @@ const GenZir = struct { | ... | @@ -13024,6 +13135,7 @@ const GenZir = struct { |
| 13024 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13135 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13025 | src_node: Ast.Node.Index, | 13136 | src_node: Ast.Node.Index, |
| 13026 | tag_type: Zir.Inst.Ref, | 13137 | tag_type: Zir.Inst.Ref, |
| 13138 | captures_len: u32, | ||
| 13027 | body_len: u32, | 13139 | body_len: u32, |
| 13028 | fields_len: u32, | 13140 | fields_len: u32, |
| 13029 | decls_len: u32, | 13141 | decls_len: u32, |
| ... | @@ -13039,7 +13151,7 @@ const GenZir = struct { | ... | @@ -13039,7 +13151,7 @@ const GenZir = struct { |
| 13039 | 13151 | ||
| 13040 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 13152 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13041 | 13153 | ||
| 13042 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 4); | 13154 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 5); |
| 13043 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ | 13155 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ |
| 13044 | .fields_hash_0 = fields_hash_arr[0], | 13156 | .fields_hash_0 = fields_hash_arr[0], |
| 13045 | .fields_hash_1 = fields_hash_arr[1], | 13157 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -13051,6 +13163,9 @@ const GenZir = struct { | ... | @@ -13051,6 +13163,9 @@ const GenZir = struct { |
| 13051 | if (args.tag_type != .none) { | 13163 | if (args.tag_type != .none) { |
| 13052 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | 13164 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 13053 | } | 13165 | } |
| 13166 | if (args.captures_len != 0) { | ||
| 13167 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13168 | } | ||
| 13054 | if (args.body_len != 0) { | 13169 | if (args.body_len != 0) { |
| 13055 | astgen.extra.appendAssumeCapacity(args.body_len); | 13170 | astgen.extra.appendAssumeCapacity(args.body_len); |
| 13056 | } | 13171 | } |
| ... | @@ -13066,6 +13181,7 @@ const GenZir = struct { | ... | @@ -13066,6 +13181,7 @@ const GenZir = struct { |
| 13066 | .opcode = .union_decl, | 13181 | .opcode = .union_decl, |
| 13067 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ | 13182 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ |
| 13068 | .has_tag_type = args.tag_type != .none, | 13183 | .has_tag_type = args.tag_type != .none, |
| 13184 | .has_captures_len = args.captures_len != 0, | ||
| 13069 | .has_body_len = args.body_len != 0, | 13185 | .has_body_len = args.body_len != 0, |
| 13070 | .has_fields_len = args.fields_len != 0, | 13186 | .has_fields_len = args.fields_len != 0, |
| 13071 | .has_decls_len = args.decls_len != 0, | 13187 | .has_decls_len = args.decls_len != 0, |
| ... | @@ -13082,6 +13198,7 @@ const GenZir = struct { | ... | @@ -13082,6 +13198,7 @@ const GenZir = struct { |
| 13082 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13198 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13083 | src_node: Ast.Node.Index, | 13199 | src_node: Ast.Node.Index, |
| 13084 | tag_type: Zir.Inst.Ref, | 13200 | tag_type: Zir.Inst.Ref, |
| 13201 | captures_len: u32, | ||
| 13085 | body_len: u32, | 13202 | body_len: u32, |
| 13086 | fields_len: u32, | 13203 | fields_len: u32, |
| 13087 | decls_len: u32, | 13204 | decls_len: u32, |
| ... | @@ -13095,7 +13212,7 @@ const GenZir = struct { | ... | @@ -13095,7 +13212,7 @@ const GenZir = struct { |
| 13095 | 13212 | ||
| 13096 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 13213 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13097 | 13214 | ||
| 13098 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 4); | 13215 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 5); |
| 13099 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ | 13216 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ |
| 13100 | .fields_hash_0 = fields_hash_arr[0], | 13217 | .fields_hash_0 = fields_hash_arr[0], |
| 13101 | .fields_hash_1 = fields_hash_arr[1], | 13218 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -13107,6 +13224,9 @@ const GenZir = struct { | ... | @@ -13107,6 +13224,9 @@ const GenZir = struct { |
| 13107 | if (args.tag_type != .none) { | 13224 | if (args.tag_type != .none) { |
| 13108 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | 13225 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 13109 | } | 13226 | } |
| 13227 | if (args.captures_len != 0) { | ||
| 13228 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13229 | } | ||
| 13110 | if (args.body_len != 0) { | 13230 | if (args.body_len != 0) { |
| 13111 | astgen.extra.appendAssumeCapacity(args.body_len); | 13231 | astgen.extra.appendAssumeCapacity(args.body_len); |
| 13112 | } | 13232 | } |
| ... | @@ -13122,6 +13242,7 @@ const GenZir = struct { | ... | @@ -13122,6 +13242,7 @@ const GenZir = struct { |
| 13122 | .opcode = .enum_decl, | 13242 | .opcode = .enum_decl, |
| 13123 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ | 13243 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ |
| 13124 | .has_tag_type = args.tag_type != .none, | 13244 | .has_tag_type = args.tag_type != .none, |
| 13245 | .has_captures_len = args.captures_len != 0, | ||
| 13125 | .has_body_len = args.body_len != 0, | 13246 | .has_body_len = args.body_len != 0, |
| 13126 | .has_fields_len = args.fields_len != 0, | 13247 | .has_fields_len = args.fields_len != 0, |
| 13127 | .has_decls_len = args.decls_len != 0, | 13248 | .has_decls_len = args.decls_len != 0, |
| ... | @@ -13135,6 +13256,7 @@ const GenZir = struct { | ... | @@ -13135,6 +13256,7 @@ const GenZir = struct { |
| 13135 | 13256 | ||
| 13136 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13257 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13137 | src_node: Ast.Node.Index, | 13258 | src_node: Ast.Node.Index, |
| 13259 | captures_len: u32, | ||
| 13138 | decls_len: u32, | 13260 | decls_len: u32, |
| 13139 | }) !void { | 13261 | }) !void { |
| 13140 | const astgen = gz.astgen; | 13262 | const astgen = gz.astgen; |
| ... | @@ -13142,11 +13264,14 @@ const GenZir = struct { | ... | @@ -13142,11 +13264,14 @@ const GenZir = struct { |
| 13142 | 13264 | ||
| 13143 | assert(args.src_node != 0); | 13265 | assert(args.src_node != 0); |
| 13144 | 13266 | ||
| 13145 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 1); | 13267 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 2); |
| 13146 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ | 13268 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| 13147 | .src_node = gz.nodeIndexToRelative(args.src_node), | 13269 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 13148 | }); | 13270 | }); |
| 13149 | 13271 | ||
| 13272 | if (args.captures_len != 0) { | ||
| 13273 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13274 | } | ||
| 13150 | if (args.decls_len != 0) { | 13275 | if (args.decls_len != 0) { |
| 13151 | astgen.extra.appendAssumeCapacity(args.decls_len); | 13276 | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13152 | } | 13277 | } |
| ... | @@ -13155,6 +13280,7 @@ const GenZir = struct { | ... | @@ -13155,6 +13280,7 @@ const GenZir = struct { |
| 13155 | .data = .{ .extended = .{ | 13280 | .data = .{ .extended = .{ |
| 13156 | .opcode = .opaque_decl, | 13281 | .opcode = .opaque_decl, |
| 13157 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ | 13282 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ |
| 13283 | .has_captures_len = args.captures_len != 0, | ||
| 13158 | .has_decls_len = args.decls_len != 0, | 13284 | .has_decls_len = args.decls_len != 0, |
| 13159 | .name_strategy = gz.anon_name_strategy, | 13285 | .name_strategy = gz.anon_name_strategy, |
| 13160 | }), | 13286 | }), |
| ... | @@ -13197,15 +13323,6 @@ const GenZir = struct { | ... | @@ -13197,15 +13323,6 @@ const GenZir = struct { |
| 13197 | } | 13323 | } |
| 13198 | } | 13324 | } |
| 13199 | 13325 | ||
| 13200 | fn addNamespaceCaptures(gz: *GenZir, namespace: *Scope.Namespace) !void { | ||
| 13201 | if (namespace.captures.count() > 0) { | ||
| 13202 | try gz.instructions.ensureUnusedCapacity(gz.astgen.gpa, namespace.captures.count()); | ||
| 13203 | for (namespace.captures.values()) |capture| { | ||
| 13204 | gz.instructions.appendAssumeCapacity(capture); | ||
| 13205 | } | ||
| 13206 | } | ||
| 13207 | } | ||
| 13208 | |||
| 13209 | fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: Zir.NullTerminatedString, inst: Zir.Inst.Ref) !void { | 13326 | fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: Zir.NullTerminatedString, inst: Zir.Inst.Ref) !void { |
| 13210 | if (gz.is_comptime) return; | 13327 | if (gz.is_comptime) return; |
| 13211 | 13328 | ||
| ... | @@ -13305,7 +13422,7 @@ fn detectLocalShadowing( | ... | @@ -13305,7 +13422,7 @@ fn detectLocalShadowing( |
| 13305 | } | 13422 | } |
| 13306 | s = local_ptr.parent; | 13423 | s = local_ptr.parent; |
| 13307 | }, | 13424 | }, |
| 13308 | .namespace, .enum_namespace => { | 13425 | .namespace => { |
| 13309 | outer_scope = true; | 13426 | outer_scope = true; |
| 13310 | const ns = s.cast(Scope.Namespace).?; | 13427 | const ns = s.cast(Scope.Namespace).?; |
| 13311 | const decl_node = ns.decls.get(ident_name) orelse { | 13428 | const decl_node = ns.decls.get(ident_name) orelse { |
| ... | @@ -13478,7 +13595,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. | ... | @@ -13478,7 +13595,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 13478 | } | 13595 | } |
| 13479 | s = local_ptr.parent; | 13596 | s = local_ptr.parent; |
| 13480 | }, | 13597 | }, |
| 13481 | .namespace, .enum_namespace => s = s.cast(Scope.Namespace).?.parent, | 13598 | .namespace => s = s.cast(Scope.Namespace).?.parent, |
| 13482 | .gen_zir => s = s.cast(GenZir).?.parent, | 13599 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 13483 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 13600 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 13484 | .top => break, | 13601 | .top => break, |
lib/std/zig/Zir.zig+123-48| ... | @@ -1004,17 +1004,6 @@ pub const Inst = struct { | ... | @@ -1004,17 +1004,6 @@ pub const Inst = struct { |
| 1004 | @"resume", | 1004 | @"resume", |
| 1005 | @"await", | 1005 | @"await", |
| 1006 | 1006 | ||
| 1007 | /// When a type or function refers to a comptime value from an outer | ||
| 1008 | /// scope, that forms a closure over comptime value. The outer scope | ||
| 1009 | /// will record a capture of that value, which encodes its current state | ||
| 1010 | /// and marks it to persist. Uses `un_tok` field. Operand is the | ||
| 1011 | /// instruction value to capture. | ||
| 1012 | closure_capture, | ||
| 1013 | /// The inner scope of a closure uses closure_get to retrieve the value | ||
| 1014 | /// stored by the outer scope. Uses `inst_node` field. Operand is the | ||
| 1015 | /// closure_capture instruction ref. | ||
| 1016 | closure_get, | ||
| 1017 | |||
| 1018 | /// A defer statement. | 1007 | /// A defer statement. |
| 1019 | /// Uses the `defer` union field. | 1008 | /// Uses the `defer` union field. |
| 1020 | @"defer", | 1009 | @"defer", |
| ... | @@ -1251,8 +1240,6 @@ pub const Inst = struct { | ... | @@ -1251,8 +1240,6 @@ pub const Inst = struct { |
| 1251 | .@"await", | 1240 | .@"await", |
| 1252 | .ret_err_value_code, | 1241 | .ret_err_value_code, |
| 1253 | .extended, | 1242 | .extended, |
| 1254 | .closure_get, | ||
| 1255 | .closure_capture, | ||
| 1256 | .ret_ptr, | 1243 | .ret_ptr, |
| 1257 | .ret_type, | 1244 | .ret_type, |
| 1258 | .@"try", | 1245 | .@"try", |
| ... | @@ -1542,8 +1529,6 @@ pub const Inst = struct { | ... | @@ -1542,8 +1529,6 @@ pub const Inst = struct { |
| 1542 | .@"resume", | 1529 | .@"resume", |
| 1543 | .@"await", | 1530 | .@"await", |
| 1544 | .ret_err_value_code, | 1531 | .ret_err_value_code, |
| 1545 | .closure_get, | ||
| 1546 | .closure_capture, | ||
| 1547 | .@"break", | 1532 | .@"break", |
| 1548 | .break_inline, | 1533 | .break_inline, |
| 1549 | .condbr, | 1534 | .condbr, |
| ... | @@ -1829,9 +1814,6 @@ pub const Inst = struct { | ... | @@ -1829,9 +1814,6 @@ pub const Inst = struct { |
| 1829 | .@"resume" = .un_node, | 1814 | .@"resume" = .un_node, |
| 1830 | .@"await" = .un_node, | 1815 | .@"await" = .un_node, |
| 1831 | 1816 | ||
| 1832 | .closure_capture = .un_tok, | ||
| 1833 | .closure_get = .inst_node, | ||
| 1834 | |||
| 1835 | .@"defer" = .@"defer", | 1817 | .@"defer" = .@"defer", |
| 1836 | .defer_err_code = .defer_err_code, | 1818 | .defer_err_code = .defer_err_code, |
| 1837 | 1819 | ||
| ... | @@ -2074,6 +2056,10 @@ pub const Inst = struct { | ... | @@ -2074,6 +2056,10 @@ pub const Inst = struct { |
| 2074 | /// `operand` is payload index to `RestoreErrRetIndex`. | 2056 | /// `operand` is payload index to `RestoreErrRetIndex`. |
| 2075 | /// `small` is undefined. | 2057 | /// `small` is undefined. |
| 2076 | restore_err_ret_index, | 2058 | restore_err_ret_index, |
| 2059 | /// Retrieves a value from the current type declaration scope's closure. | ||
| 2060 | /// `operand` is `src_node: i32`. | ||
| 2061 | /// `small` is closure index. | ||
| 2062 | closure_get, | ||
| 2077 | /// Used as a placeholder instruction which is just a dummy index for Sema to replace | 2063 | /// Used as a placeholder instruction which is just a dummy index for Sema to replace |
| 2078 | /// with a specific value. For instance, this is used for the capture of an `errdefer`. | 2064 | /// with a specific value. For instance, this is used for the capture of an `errdefer`. |
| 2079 | /// This should never appear in a body. | 2065 | /// This should never appear in a body. |
| ... | @@ -2949,7 +2935,7 @@ pub const Inst = struct { | ... | @@ -2949,7 +2935,7 @@ pub const Inst = struct { |
| 2949 | /// These are stored in trailing data in `extra` for each prong. | 2935 | /// These are stored in trailing data in `extra` for each prong. |
| 2950 | pub const ProngInfo = packed struct(u32) { | 2936 | pub const ProngInfo = packed struct(u32) { |
| 2951 | body_len: u28, | 2937 | body_len: u28, |
| 2952 | capture: Capture, | 2938 | capture: ProngInfo.Capture, |
| 2953 | is_inline: bool, | 2939 | is_inline: bool, |
| 2954 | has_tag_capture: bool, | 2940 | has_tag_capture: bool, |
| 2955 | 2941 | ||
| ... | @@ -3013,19 +2999,21 @@ pub const Inst = struct { | ... | @@ -3013,19 +2999,21 @@ pub const Inst = struct { |
| 3013 | }; | 2999 | }; |
| 3014 | 3000 | ||
| 3015 | /// Trailing: | 3001 | /// Trailing: |
| 3016 | /// 0. fields_len: u32, // if has_fields_len | 3002 | /// 0. captures_len: u32 // if has_captures_len |
| 3017 | /// 1. decls_len: u32, // if has_decls_len | 3003 | /// 1. fields_len: u32, // if has_fields_len |
| 3018 | /// 2. backing_int_body_len: u32, // if has_backing_int | 3004 | /// 2. decls_len: u32, // if has_decls_len |
| 3019 | /// 3. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 | 3005 | /// 3. capture: Capture // for every captures_len |
| 3020 | /// 4. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0 | 3006 | /// 4. backing_int_body_len: u32, // if has_backing_int |
| 3021 | /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction | 3007 | /// 5. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 |
| 3022 | /// 6. flags: u32 // for every 8 fields | 3008 | /// 6. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0 |
| 3009 | /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction | ||
| 3010 | /// 8. flags: u32 // for every 8 fields | ||
| 3023 | /// - sets of 4 bits: | 3011 | /// - sets of 4 bits: |
| 3024 | /// 0b000X: whether corresponding field has an align expression | 3012 | /// 0b000X: whether corresponding field has an align expression |
| 3025 | /// 0b00X0: whether corresponding field has a default expression | 3013 | /// 0b00X0: whether corresponding field has a default expression |
| 3026 | /// 0b0X00: whether corresponding field is comptime | 3014 | /// 0b0X00: whether corresponding field is comptime |
| 3027 | /// 0bX000: whether corresponding field has a type expression | 3015 | /// 0bX000: whether corresponding field has a type expression |
| 3028 | /// 7. fields: { // for every fields_len | 3016 | /// 9. fields: { // for every fields_len |
| 3029 | /// field_name: u32, // if !is_tuple | 3017 | /// field_name: u32, // if !is_tuple |
| 3030 | /// doc_comment: NullTerminatedString, // .empty if no doc comment | 3018 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 3031 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. | 3019 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. |
| ... | @@ -3033,7 +3021,7 @@ pub const Inst = struct { | ... | @@ -3033,7 +3021,7 @@ pub const Inst = struct { |
| 3033 | /// align_body_len: u32, // if corresponding bit is set | 3021 | /// align_body_len: u32, // if corresponding bit is set |
| 3034 | /// init_body_len: u32, // if corresponding bit is set | 3022 | /// init_body_len: u32, // if corresponding bit is set |
| 3035 | /// } | 3023 | /// } |
| 3036 | /// 8. bodies: { // for every fields_len | 3024 | /// 10. bodies: { // for every fields_len |
| 3037 | /// field_type_body_inst: Inst, // for each field_type_body_len | 3025 | /// field_type_body_inst: Inst, // for each field_type_body_len |
| 3038 | /// align_body_inst: Inst, // for each align_body_len | 3026 | /// align_body_inst: Inst, // for each align_body_len |
| 3039 | /// init_body_inst: Inst, // for each init_body_len | 3027 | /// init_body_inst: Inst, // for each init_body_len |
| ... | @@ -3052,6 +3040,7 @@ pub const Inst = struct { | ... | @@ -3052,6 +3040,7 @@ pub const Inst = struct { |
| 3052 | } | 3040 | } |
| 3053 | 3041 | ||
| 3054 | pub const Small = packed struct { | 3042 | pub const Small = packed struct { |
| 3043 | has_captures_len: bool, | ||
| 3055 | has_fields_len: bool, | 3044 | has_fields_len: bool, |
| 3056 | has_decls_len: bool, | 3045 | has_decls_len: bool, |
| 3057 | has_backing_int: bool, | 3046 | has_backing_int: bool, |
| ... | @@ -3063,8 +3052,57 @@ pub const Inst = struct { | ... | @@ -3063,8 +3052,57 @@ pub const Inst = struct { |
| 3063 | any_default_inits: bool, | 3052 | any_default_inits: bool, |
| 3064 | any_comptime_fields: bool, | 3053 | any_comptime_fields: bool, |
| 3065 | any_aligned_fields: bool, | 3054 | any_aligned_fields: bool, |
| 3066 | _: u3 = undefined, | 3055 | _: u2 = undefined, |
| 3056 | }; | ||
| 3057 | }; | ||
| 3058 | |||
| 3059 | /// Represents a single value being captured in a type declaration's closure. | ||
| 3060 | pub const Capture = packed struct(u32) { | ||
| 3061 | tag: enum(u2) { | ||
| 3062 | /// `data` is a `u16` index into the parent closure. | ||
| 3063 | nested, | ||
| 3064 | /// `data` is a `Zir.Inst.Index` to an instruction whose value is being captured. | ||
| 3065 | instruction, | ||
| 3066 | /// `data` is a `NullTerminatedString` to a decl name. | ||
| 3067 | decl_val, | ||
| 3068 | /// `data` is a `NullTerminatedString` to a decl name. | ||
| 3069 | decl_ref, | ||
| 3070 | }, | ||
| 3071 | data: u30, | ||
| 3072 | pub const Unwrapped = union(enum) { | ||
| 3073 | nested: u16, | ||
| 3074 | instruction: Zir.Inst.Index, | ||
| 3075 | decl_val: NullTerminatedString, | ||
| 3076 | decl_ref: NullTerminatedString, | ||
| 3067 | }; | 3077 | }; |
| 3078 | pub fn wrap(cap: Unwrapped) Capture { | ||
| 3079 | return switch (cap) { | ||
| 3080 | .nested => |idx| .{ | ||
| 3081 | .tag = .nested, | ||
| 3082 | .data = idx, | ||
| 3083 | }, | ||
| 3084 | .instruction => |inst| .{ | ||
| 3085 | .tag = .instruction, | ||
| 3086 | .data = @intCast(@intFromEnum(inst)), | ||
| 3087 | }, | ||
| 3088 | .decl_val => |str| .{ | ||
| 3089 | .tag = .decl_val, | ||
| 3090 | .data = @intCast(@intFromEnum(str)), | ||
| 3091 | }, | ||
| 3092 | .decl_ref => |str| .{ | ||
| 3093 | .tag = .decl_ref, | ||
| 3094 | .data = @intCast(@intFromEnum(str)), | ||
| 3095 | }, | ||
| 3096 | }; | ||
| 3097 | } | ||
| 3098 | pub fn unwrap(cap: Capture) Unwrapped { | ||
| 3099 | return switch (cap.tag) { | ||
| 3100 | .nested => .{ .nested = @intCast(cap.data) }, | ||
| 3101 | .instruction => .{ .instruction = @enumFromInt(cap.data) }, | ||
| 3102 | .decl_val => .{ .decl_val = @enumFromInt(cap.data) }, | ||
| 3103 | .decl_ref => .{ .decl_ref = @enumFromInt(cap.data) }, | ||
| 3104 | }; | ||
| 3105 | } | ||
| 3068 | }; | 3106 | }; |
| 3069 | 3107 | ||
| 3070 | pub const NameStrategy = enum(u2) { | 3108 | pub const NameStrategy = enum(u2) { |
| ... | @@ -3098,14 +3136,16 @@ pub const Inst = struct { | ... | @@ -3098,14 +3136,16 @@ pub const Inst = struct { |
| 3098 | 3136 | ||
| 3099 | /// Trailing: | 3137 | /// Trailing: |
| 3100 | /// 0. tag_type: Ref, // if has_tag_type | 3138 | /// 0. tag_type: Ref, // if has_tag_type |
| 3101 | /// 1. body_len: u32, // if has_body_len | 3139 | /// 1. captures_len: u32, // if has_captures_len |
| 3102 | /// 2. fields_len: u32, // if has_fields_len | 3140 | /// 2. body_len: u32, // if has_body_len |
| 3103 | /// 3. decls_len: u32, // if has_decls_len | 3141 | /// 3. fields_len: u32, // if has_fields_len |
| 3104 | /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction | 3142 | /// 4. decls_len: u32, // if has_decls_len |
| 3105 | /// 5. inst: Index // for every body_len | 3143 | /// 5. capture: Capture // for every captures_len |
| 3106 | /// 6. has_bits: u32 // for every 32 fields | 3144 | /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3145 | /// 7. inst: Index // for every body_len | ||
| 3146 | /// 8. has_bits: u32 // for every 32 fields | ||
| 3107 | /// - the bit is whether corresponding field has an value expression | 3147 | /// - the bit is whether corresponding field has an value expression |
| 3108 | /// 7. fields: { // for every fields_len | 3148 | /// 9. fields: { // for every fields_len |
| 3109 | /// field_name: u32, | 3149 | /// field_name: u32, |
| 3110 | /// doc_comment: u32, // .empty if no doc_comment | 3150 | /// doc_comment: u32, // .empty if no doc_comment |
| 3111 | /// value: Ref, // if corresponding bit is set | 3151 | /// value: Ref, // if corresponding bit is set |
| ... | @@ -3125,29 +3165,32 @@ pub const Inst = struct { | ... | @@ -3125,29 +3165,32 @@ pub const Inst = struct { |
| 3125 | 3165 | ||
| 3126 | pub const Small = packed struct { | 3166 | pub const Small = packed struct { |
| 3127 | has_tag_type: bool, | 3167 | has_tag_type: bool, |
| 3168 | has_captures_len: bool, | ||
| 3128 | has_body_len: bool, | 3169 | has_body_len: bool, |
| 3129 | has_fields_len: bool, | 3170 | has_fields_len: bool, |
| 3130 | has_decls_len: bool, | 3171 | has_decls_len: bool, |
| 3131 | name_strategy: NameStrategy, | 3172 | name_strategy: NameStrategy, |
| 3132 | nonexhaustive: bool, | 3173 | nonexhaustive: bool, |
| 3133 | _: u9 = undefined, | 3174 | _: u8 = undefined, |
| 3134 | }; | 3175 | }; |
| 3135 | }; | 3176 | }; |
| 3136 | 3177 | ||
| 3137 | /// Trailing: | 3178 | /// Trailing: |
| 3138 | /// 0. tag_type: Ref, // if has_tag_type | 3179 | /// 0. tag_type: Ref, // if has_tag_type |
| 3139 | /// 1. body_len: u32, // if has_body_len | 3180 | /// 1. captures_len: u32 // if has_captures_len |
| 3140 | /// 2. fields_len: u32, // if has_fields_len | 3181 | /// 2. body_len: u32, // if has_body_len |
| 3141 | /// 3. decls_len: u32, // if has_decls_len | 3182 | /// 3. fields_len: u32, // if has_fields_len |
| 3142 | /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction | 3183 | /// 4. decls_len: u37, // if has_decls_len |
| 3143 | /// 5. inst: Index // for every body_len | 3184 | /// 5. capture: Capture // for every captures_len |
| 3144 | /// 6. has_bits: u32 // for every 8 fields | 3185 | /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3186 | /// 7. inst: Index // for every body_len | ||
| 3187 | /// 8. has_bits: u32 // for every 8 fields | ||
| 3145 | /// - sets of 4 bits: | 3188 | /// - sets of 4 bits: |
| 3146 | /// 0b000X: whether corresponding field has a type expression | 3189 | /// 0b000X: whether corresponding field has a type expression |
| 3147 | /// 0b00X0: whether corresponding field has a align expression | 3190 | /// 0b00X0: whether corresponding field has a align expression |
| 3148 | /// 0b0X00: whether corresponding field has a tag value expression | 3191 | /// 0b0X00: whether corresponding field has a tag value expression |
| 3149 | /// 0bX000: unused | 3192 | /// 0bX000: unused |
| 3150 | /// 7. fields: { // for every fields_len | 3193 | /// 9. fields: { // for every fields_len |
| 3151 | /// field_name: NullTerminatedString, // null terminated string index | 3194 | /// field_name: NullTerminatedString, // null terminated string index |
| 3152 | /// doc_comment: NullTerminatedString, // .empty if no doc comment | 3195 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 3153 | /// field_type: Ref, // if corresponding bit is set | 3196 | /// field_type: Ref, // if corresponding bit is set |
| ... | @@ -3170,6 +3213,7 @@ pub const Inst = struct { | ... | @@ -3170,6 +3213,7 @@ pub const Inst = struct { |
| 3170 | 3213 | ||
| 3171 | pub const Small = packed struct { | 3214 | pub const Small = packed struct { |
| 3172 | has_tag_type: bool, | 3215 | has_tag_type: bool, |
| 3216 | has_captures_len: bool, | ||
| 3173 | has_body_len: bool, | 3217 | has_body_len: bool, |
| 3174 | has_fields_len: bool, | 3218 | has_fields_len: bool, |
| 3175 | has_decls_len: bool, | 3219 | has_decls_len: bool, |
| ... | @@ -3183,13 +3227,15 @@ pub const Inst = struct { | ... | @@ -3183,13 +3227,15 @@ pub const Inst = struct { |
| 3183 | /// true | false | union(T) { } | 3227 | /// true | false | union(T) { } |
| 3184 | auto_enum_tag: bool, | 3228 | auto_enum_tag: bool, |
| 3185 | any_aligned_fields: bool, | 3229 | any_aligned_fields: bool, |
| 3186 | _: u6 = undefined, | 3230 | _: u5 = undefined, |
| 3187 | }; | 3231 | }; |
| 3188 | }; | 3232 | }; |
| 3189 | 3233 | ||
| 3190 | /// Trailing: | 3234 | /// Trailing: |
| 3191 | /// 0. decls_len: u32, // if has_decls_len | 3235 | /// 0. captures_len: u32, // if has_captures_len |
| 3192 | /// 1. decl: Index, // for every decls_len; points to a `declaration` instruction | 3236 | /// 1. decls_len: u32, // if has_decls_len |
| 3237 | /// 2. capture: Capture, // for every captures_len | ||
| 3238 | /// 3. decl: Index, // for every decls_len; points to a `declaration` instruction | ||
| 3193 | pub const OpaqueDecl = struct { | 3239 | pub const OpaqueDecl = struct { |
| 3194 | src_node: i32, | 3240 | src_node: i32, |
| 3195 | 3241 | ||
| ... | @@ -3198,9 +3244,10 @@ pub const Inst = struct { | ... | @@ -3198,9 +3244,10 @@ pub const Inst = struct { |
| 3198 | } | 3244 | } |
| 3199 | 3245 | ||
| 3200 | pub const Small = packed struct { | 3246 | pub const Small = packed struct { |
| 3247 | has_captures_len: bool, | ||
| 3201 | has_decls_len: bool, | 3248 | has_decls_len: bool, |
| 3202 | name_strategy: NameStrategy, | 3249 | name_strategy: NameStrategy, |
| 3203 | _: u13 = undefined, | 3250 | _: u12 = undefined, |
| 3204 | }; | 3251 | }; |
| 3205 | }; | 3252 | }; |
| 3206 | 3253 | ||
| ... | @@ -3502,6 +3549,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3502,6 +3549,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3502 | .struct_decl => { | 3549 | .struct_decl => { |
| 3503 | const small: Inst.StructDecl.Small = @bitCast(extended.small); | 3550 | const small: Inst.StructDecl.Small = @bitCast(extended.small); |
| 3504 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len); | 3551 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len); |
| 3552 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3553 | const captures_len = zir.extra[extra_index]; | ||
| 3554 | extra_index += 1; | ||
| 3555 | break :captures_len captures_len; | ||
| 3556 | } else 0; | ||
| 3505 | extra_index += @intFromBool(small.has_fields_len); | 3557 | extra_index += @intFromBool(small.has_fields_len); |
| 3506 | const decls_len = if (small.has_decls_len) decls_len: { | 3558 | const decls_len = if (small.has_decls_len) decls_len: { |
| 3507 | const decls_len = zir.extra[extra_index]; | 3559 | const decls_len = zir.extra[extra_index]; |
| ... | @@ -3509,6 +3561,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3509,6 +3561,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3509 | break :decls_len decls_len; | 3561 | break :decls_len decls_len; |
| 3510 | } else 0; | 3562 | } else 0; |
| 3511 | 3563 | ||
| 3564 | extra_index += captures_len; | ||
| 3565 | |||
| 3512 | if (small.has_backing_int) { | 3566 | if (small.has_backing_int) { |
| 3513 | const backing_int_body_len = zir.extra[extra_index]; | 3567 | const backing_int_body_len = zir.extra[extra_index]; |
| 3514 | extra_index += 1; // backing_int_body_len | 3568 | extra_index += 1; // backing_int_body_len |
| ... | @@ -3529,6 +3583,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3529,6 +3583,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3529 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); | 3583 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); |
| 3530 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len); | 3584 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len); |
| 3531 | extra_index += @intFromBool(small.has_tag_type); | 3585 | extra_index += @intFromBool(small.has_tag_type); |
| 3586 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3587 | const captures_len = zir.extra[extra_index]; | ||
| 3588 | extra_index += 1; | ||
| 3589 | break :captures_len captures_len; | ||
| 3590 | } else 0; | ||
| 3532 | extra_index += @intFromBool(small.has_body_len); | 3591 | extra_index += @intFromBool(small.has_body_len); |
| 3533 | extra_index += @intFromBool(small.has_fields_len); | 3592 | extra_index += @intFromBool(small.has_fields_len); |
| 3534 | const decls_len = if (small.has_decls_len) decls_len: { | 3593 | const decls_len = if (small.has_decls_len) decls_len: { |
| ... | @@ -3537,6 +3596,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3537,6 +3596,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3537 | break :decls_len decls_len; | 3596 | break :decls_len decls_len; |
| 3538 | } else 0; | 3597 | } else 0; |
| 3539 | 3598 | ||
| 3599 | extra_index += captures_len; | ||
| 3600 | |||
| 3540 | return .{ | 3601 | return .{ |
| 3541 | .extra_index = extra_index, | 3602 | .extra_index = extra_index, |
| 3542 | .decls_remaining = decls_len, | 3603 | .decls_remaining = decls_len, |
| ... | @@ -3547,6 +3608,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3547,6 +3608,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3547 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); | 3608 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3548 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len); | 3609 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len); |
| 3549 | extra_index += @intFromBool(small.has_tag_type); | 3610 | extra_index += @intFromBool(small.has_tag_type); |
| 3611 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3612 | const captures_len = zir.extra[extra_index]; | ||
| 3613 | extra_index += 1; | ||
| 3614 | break :captures_len captures_len; | ||
| 3615 | } else 0; | ||
| 3550 | extra_index += @intFromBool(small.has_body_len); | 3616 | extra_index += @intFromBool(small.has_body_len); |
| 3551 | extra_index += @intFromBool(small.has_fields_len); | 3617 | extra_index += @intFromBool(small.has_fields_len); |
| 3552 | const decls_len = if (small.has_decls_len) decls_len: { | 3618 | const decls_len = if (small.has_decls_len) decls_len: { |
| ... | @@ -3555,6 +3621,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3555,6 +3621,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3555 | break :decls_len decls_len; | 3621 | break :decls_len decls_len; |
| 3556 | } else 0; | 3622 | } else 0; |
| 3557 | 3623 | ||
| 3624 | extra_index += captures_len; | ||
| 3625 | |||
| 3558 | return .{ | 3626 | return .{ |
| 3559 | .extra_index = extra_index, | 3627 | .extra_index = extra_index, |
| 3560 | .decls_remaining = decls_len, | 3628 | .decls_remaining = decls_len, |
| ... | @@ -3569,6 +3637,13 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3569,6 +3637,13 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3569 | extra_index += 1; | 3637 | extra_index += 1; |
| 3570 | break :decls_len decls_len; | 3638 | break :decls_len decls_len; |
| 3571 | } else 0; | 3639 | } else 0; |
| 3640 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3641 | const captures_len = zir.extra[extra_index]; | ||
| 3642 | extra_index += 1; | ||
| 3643 | break :captures_len captures_len; | ||
| 3644 | } else 0; | ||
| 3645 | |||
| 3646 | extra_index += captures_len; | ||
| 3572 | 3647 | ||
| 3573 | return .{ | 3648 | return .{ |
| 3574 | .extra_index = extra_index, | 3649 | .extra_index = extra_index, |
src/Autodoc.zig+72-24| ... | @@ -450,7 +450,7 @@ const Scope = struct { | ... | @@ -450,7 +450,7 @@ const Scope = struct { |
| 450 | Zir.NullTerminatedString, // index into the current file's string table (decl name) | 450 | Zir.NullTerminatedString, // index into the current file's string table (decl name) |
| 451 | *DeclStatus, | 451 | *DeclStatus, |
| 452 | ) = .{}, | 452 | ) = .{}, |
| 453 | 453 | captures: []const Zir.Inst.Capture = &.{}, | |
| 454 | enclosing_type: ?usize, // index into `types`, null = file top-level struct | 454 | enclosing_type: ?usize, // index into `types`, null = file top-level struct |
| 455 | 455 | ||
| 456 | pub const DeclStatus = union(enum) { | 456 | pub const DeclStatus = union(enum) { |
| ... | @@ -459,6 +459,24 @@ const Scope = struct { | ... | @@ -459,6 +459,24 @@ const Scope = struct { |
| 459 | NotRequested: u32, // instr_index | 459 | NotRequested: u32, // instr_index |
| 460 | }; | 460 | }; |
| 461 | 461 | ||
| 462 | fn getCapture(scope: Scope, idx: u16) struct { | ||
| 463 | union(enum) { inst: Zir.Inst.Index, decl: Zir.NullTerminatedString }, | ||
| 464 | *Scope, | ||
| 465 | } { | ||
| 466 | const parent = scope.parent.?; | ||
| 467 | return switch (scope.captures[idx].unwrap()) { | ||
| 468 | .nested => |parent_idx| parent.getCapture(parent_idx), | ||
| 469 | .instruction => |inst| .{ | ||
| 470 | .{ .inst = inst }, | ||
| 471 | parent, | ||
| 472 | }, | ||
| 473 | .decl_val, .decl_ref => |str| .{ | ||
| 474 | .{ .decl = str }, | ||
| 475 | parent, | ||
| 476 | }, | ||
| 477 | }; | ||
| 478 | } | ||
| 479 | |||
| 462 | /// Returns a pointer so that the caller has a chance to modify the value | 480 | /// Returns a pointer so that the caller has a chance to modify the value |
| 463 | /// in case they decide to start analyzing a previously not requested decl. | 481 | /// in case they decide to start analyzing a previously not requested decl. |
| 464 | /// Another reason is that in some places we use the pointer to uniquely | 482 | /// Another reason is that in some places we use the pointer to uniquely |
| ... | @@ -1151,29 +1169,6 @@ fn walkInstruction( | ... | @@ -1151,29 +1169,6 @@ fn walkInstruction( |
| 1151 | .expr = .{ .comptimeExpr = 0 }, | 1169 | .expr = .{ .comptimeExpr = 0 }, |
| 1152 | }; | 1170 | }; |
| 1153 | }, | 1171 | }, |
| 1154 | .closure_get => { | ||
| 1155 | const inst_node = data[@intFromEnum(inst)].inst_node; | ||
| 1156 | |||
| 1157 | const code = try self.getBlockSource(file, parent_src, inst_node.src_node); | ||
| 1158 | const idx = self.comptime_exprs.items.len; | ||
| 1159 | try self.exprs.append(self.arena, .{ .comptimeExpr = idx }); | ||
| 1160 | try self.comptime_exprs.append(self.arena, .{ .code = code }); | ||
| 1161 | |||
| 1162 | return DocData.WalkResult{ | ||
| 1163 | .expr = .{ .comptimeExpr = idx }, | ||
| 1164 | }; | ||
| 1165 | }, | ||
| 1166 | .closure_capture => { | ||
| 1167 | const un_tok = data[@intFromEnum(inst)].un_tok; | ||
| 1168 | return try self.walkRef( | ||
| 1169 | file, | ||
| 1170 | parent_scope, | ||
| 1171 | parent_src, | ||
| 1172 | un_tok.operand, | ||
| 1173 | need_type, | ||
| 1174 | call_ctx, | ||
| 1175 | ); | ||
| 1176 | }, | ||
| 1177 | .str => { | 1172 | .str => { |
| 1178 | const str = data[@intFromEnum(inst)].str.get(file.zir); | 1173 | const str = data[@intFromEnum(inst)].str.get(file.zir); |
| 1179 | 1174 | ||
| ... | @@ -3395,11 +3390,23 @@ fn walkInstruction( | ... | @@ -3395,11 +3390,23 @@ fn walkInstruction( |
| 3395 | .enclosing_type = type_slot_index, | 3390 | .enclosing_type = type_slot_index, |
| 3396 | }; | 3391 | }; |
| 3397 | 3392 | ||
| 3393 | const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); | ||
| 3398 | const extra = file.zir.extraData(Zir.Inst.OpaqueDecl, extended.operand); | 3394 | const extra = file.zir.extraData(Zir.Inst.OpaqueDecl, extended.operand); |
| 3399 | var extra_index: usize = extra.end; | 3395 | var extra_index: usize = extra.end; |
| 3400 | 3396 | ||
| 3401 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); | 3397 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); |
| 3402 | 3398 | ||
| 3399 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3400 | const captures_len = file.zir.extra[extra_index]; | ||
| 3401 | extra_index += 1; | ||
| 3402 | break :blk captures_len; | ||
| 3403 | } else 0; | ||
| 3404 | |||
| 3405 | if (small.has_decls_len) extra_index += 1; | ||
| 3406 | |||
| 3407 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3408 | extra_index += captures_len; | ||
| 3409 | |||
| 3403 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3410 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3404 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3411 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3405 | 3412 | ||
| ... | @@ -3503,6 +3510,12 @@ fn walkInstruction( | ... | @@ -3503,6 +3510,12 @@ fn walkInstruction( |
| 3503 | break :blk tag_ref; | 3510 | break :blk tag_ref; |
| 3504 | } else null; | 3511 | } else null; |
| 3505 | 3512 | ||
| 3513 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3514 | const captures_len = file.zir.extra[extra_index]; | ||
| 3515 | extra_index += 1; | ||
| 3516 | break :blk captures_len; | ||
| 3517 | } else 0; | ||
| 3518 | |||
| 3506 | const body_len = if (small.has_body_len) blk: { | 3519 | const body_len = if (small.has_body_len) blk: { |
| 3507 | const body_len = file.zir.extra[extra_index]; | 3520 | const body_len = file.zir.extra[extra_index]; |
| 3508 | extra_index += 1; | 3521 | extra_index += 1; |
| ... | @@ -3520,6 +3533,11 @@ fn walkInstruction( | ... | @@ -3520,6 +3533,11 @@ fn walkInstruction( |
| 3520 | else => .{ .enumLiteral = @tagName(small.layout) }, | 3533 | else => .{ .enumLiteral = @tagName(small.layout) }, |
| 3521 | }; | 3534 | }; |
| 3522 | 3535 | ||
| 3536 | if (small.has_decls_len) extra_index += 1; | ||
| 3537 | |||
| 3538 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3539 | extra_index += captures_len; | ||
| 3540 | |||
| 3523 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3541 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3524 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3542 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3525 | 3543 | ||
| ... | @@ -3631,6 +3649,12 @@ fn walkInstruction( | ... | @@ -3631,6 +3649,12 @@ fn walkInstruction( |
| 3631 | break :blk wr.expr; | 3649 | break :blk wr.expr; |
| 3632 | } else null; | 3650 | } else null; |
| 3633 | 3651 | ||
| 3652 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3653 | const captures_len = file.zir.extra[extra_index]; | ||
| 3654 | extra_index += 1; | ||
| 3655 | break :blk captures_len; | ||
| 3656 | } else 0; | ||
| 3657 | |||
| 3634 | const body_len = if (small.has_body_len) blk: { | 3658 | const body_len = if (small.has_body_len) blk: { |
| 3635 | const body_len = file.zir.extra[extra_index]; | 3659 | const body_len = file.zir.extra[extra_index]; |
| 3636 | extra_index += 1; | 3660 | extra_index += 1; |
| ... | @@ -3643,6 +3667,11 @@ fn walkInstruction( | ... | @@ -3643,6 +3667,11 @@ fn walkInstruction( |
| 3643 | break :blk fields_len; | 3667 | break :blk fields_len; |
| 3644 | } else 0; | 3668 | } else 0; |
| 3645 | 3669 | ||
| 3670 | if (small.has_decls_len) extra_index += 1; | ||
| 3671 | |||
| 3672 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3673 | extra_index += captures_len; | ||
| 3674 | |||
| 3646 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3675 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3647 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3676 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3648 | 3677 | ||
| ... | @@ -3759,6 +3788,12 @@ fn walkInstruction( | ... | @@ -3759,6 +3788,12 @@ fn walkInstruction( |
| 3759 | 3788 | ||
| 3760 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); | 3789 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); |
| 3761 | 3790 | ||
| 3791 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3792 | const captures_len = file.zir.extra[extra_index]; | ||
| 3793 | extra_index += 1; | ||
| 3794 | break :blk captures_len; | ||
| 3795 | } else 0; | ||
| 3796 | |||
| 3762 | const fields_len = if (small.has_fields_len) blk: { | 3797 | const fields_len = if (small.has_fields_len) blk: { |
| 3763 | const fields_len = file.zir.extra[extra_index]; | 3798 | const fields_len = file.zir.extra[extra_index]; |
| 3764 | extra_index += 1; | 3799 | extra_index += 1; |
| ... | @@ -3768,6 +3803,9 @@ fn walkInstruction( | ... | @@ -3768,6 +3803,9 @@ fn walkInstruction( |
| 3768 | // We don't care about decls yet | 3803 | // We don't care about decls yet |
| 3769 | if (small.has_decls_len) extra_index += 1; | 3804 | if (small.has_decls_len) extra_index += 1; |
| 3770 | 3805 | ||
| 3806 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3807 | extra_index += captures_len; | ||
| 3808 | |||
| 3771 | var backing_int: ?DocData.Expr = null; | 3809 | var backing_int: ?DocData.Expr = null; |
| 3772 | if (small.has_backing_int) { | 3810 | if (small.has_backing_int) { |
| 3773 | const backing_int_body_len = file.zir.extra[extra_index]; | 3811 | const backing_int_body_len = file.zir.extra[extra_index]; |
| ... | @@ -4018,6 +4056,16 @@ fn walkInstruction( | ... | @@ -4018,6 +4056,16 @@ fn walkInstruction( |
| 4018 | .expr = .{ .cmpxchgIndex = cmpxchg_index }, | 4056 | .expr = .{ .cmpxchgIndex = cmpxchg_index }, |
| 4019 | }; | 4057 | }; |
| 4020 | }, | 4058 | }, |
| 4059 | .closure_get => { | ||
| 4060 | const captured, const scope = parent_scope.getCapture(extended.small); | ||
| 4061 | switch (captured) { | ||
| 4062 | .inst => |cap_inst| return self.walkInstruction(file, scope, parent_src, cap_inst, need_type, call_ctx), | ||
| 4063 | .decl => |str| { | ||
| 4064 | const decl_status = parent_scope.resolveDeclName(str, file, inst.toOptional()); | ||
| 4065 | return .{ .expr = .{ .declRef = decl_status } }; | ||
| 4066 | }, | ||
| 4067 | } | ||
| 4068 | }, | ||
| 4021 | } | 4069 | } |
| 4022 | }, | 4070 | }, |
| 4023 | } | 4071 | } |
src/Builtin.zig+2| ... | @@ -264,6 +264,8 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { | ... | @@ -264,6 +264,8 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { |
| 264 | assert(!file.zir.hasCompileErrors()); // builtin.zig must not have astgen errors | 264 | assert(!file.zir.hasCompileErrors()); // builtin.zig must not have astgen errors |
| 265 | file.zir_loaded = true; | 265 | file.zir_loaded = true; |
| 266 | file.status = .success_zir; | 266 | file.status = .success_zir; |
| 267 | // Note that whilst we set `zir_loaded` here, we populated `path_digest` | ||
| 268 | // all the way back in `Package.Module.create`. | ||
| 267 | } | 269 | } |
| 268 | 270 | ||
| 269 | fn writeFile(file: *File, mod: *Module) !void { | 271 | fn writeFile(file: *File, mod: *Module) !void { |
src/Compilation.zig+4| ... | @@ -1326,6 +1326,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1326,6 +1326,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1326 | .global = options.config, | 1326 | .global = options.config, |
| 1327 | .parent = options.root_mod, | 1327 | .parent = options.root_mod, |
| 1328 | .builtin_mod = options.root_mod.getBuiltinDependency(), | 1328 | .builtin_mod = options.root_mod.getBuiltinDependency(), |
| 1329 | .builtin_modules = null, // `builtin_mod` is set | ||
| 1329 | }); | 1330 | }); |
| 1330 | try options.root_mod.deps.putNoClobber(arena, "compiler_rt", compiler_rt_mod); | 1331 | try options.root_mod.deps.putNoClobber(arena, "compiler_rt", compiler_rt_mod); |
| 1331 | } | 1332 | } |
| ... | @@ -1430,6 +1431,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1430,6 +1431,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1430 | .global = options.config, | 1431 | .global = options.config, |
| 1431 | .parent = options.root_mod, | 1432 | .parent = options.root_mod, |
| 1432 | .builtin_mod = options.root_mod.getBuiltinDependency(), | 1433 | .builtin_mod = options.root_mod.getBuiltinDependency(), |
| 1434 | .builtin_modules = null, // `builtin_mod` is set | ||
| 1433 | }); | 1435 | }); |
| 1434 | 1436 | ||
| 1435 | const zcu = try arena.create(Module); | 1437 | const zcu = try arena.create(Module); |
| ... | @@ -6107,6 +6109,7 @@ fn buildOutputFromZig( | ... | @@ -6107,6 +6109,7 @@ fn buildOutputFromZig( |
| 6107 | .cc_argv = &.{}, | 6109 | .cc_argv = &.{}, |
| 6108 | .parent = null, | 6110 | .parent = null, |
| 6109 | .builtin_mod = null, | 6111 | .builtin_mod = null, |
| 6112 | .builtin_modules = null, // there is only one module in this compilation | ||
| 6110 | }); | 6113 | }); |
| 6111 | const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; | 6114 | const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; |
| 6112 | const target = comp.getTarget(); | 6115 | const target = comp.getTarget(); |
| ... | @@ -6219,6 +6222,7 @@ pub fn build_crt_file( | ... | @@ -6219,6 +6222,7 @@ pub fn build_crt_file( |
| 6219 | .cc_argv = &.{}, | 6222 | .cc_argv = &.{}, |
| 6220 | .parent = null, | 6223 | .parent = null, |
| 6221 | .builtin_mod = null, | 6224 | .builtin_mod = null, |
| 6225 | .builtin_modules = null, // there is only one module in this compilation | ||
| 6222 | }); | 6226 | }); |
| 6223 | 6227 | ||
| 6224 | for (c_source_files) |*item| { | 6228 | for (c_source_files) |*item| { |
src/InternPool.zig+1781-1219| ... | @@ -1,7 +1,6 @@ | ... | @@ -1,7 +1,6 @@ |
| 1 | //! All interned objects have both a value and a type. | 1 | //! All interned objects have both a value and a type. |
| 2 | //! This data structure is self-contained, with the following exceptions: | 2 | //! This data structure is self-contained, with the following exceptions: |
| 3 | //! * Module.Namespace has a pointer to Module.File | 3 | //! * Module.Namespace has a pointer to Module.File |
| 4 | //! * Module.Decl has a pointer to Module.CaptureScope | ||
| 5 | 4 | ||
| 6 | /// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are | 5 | /// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are |
| 7 | /// constructed lazily. | 6 | /// constructed lazily. |
| ... | @@ -345,6 +344,7 @@ const KeyAdapter = struct { | ... | @@ -345,6 +344,7 @@ const KeyAdapter = struct { |
| 345 | 344 | ||
| 346 | pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool { | 345 | pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool { |
| 347 | _ = b_void; | 346 | _ = b_void; |
| 347 | if (ctx.intern_pool.items.items(.tag)[b_map_index] == .removed) return false; | ||
| 348 | return ctx.intern_pool.indexToKey(@as(Index, @enumFromInt(b_map_index))).eql(a, ctx.intern_pool); | 348 | return ctx.intern_pool.indexToKey(@as(Index, @enumFromInt(b_map_index))).eql(a, ctx.intern_pool); |
| 349 | } | 349 | } |
| 350 | 350 | ||
| ... | @@ -502,6 +502,51 @@ pub const OptionalNullTerminatedString = enum(u32) { | ... | @@ -502,6 +502,51 @@ pub const OptionalNullTerminatedString = enum(u32) { |
| 502 | } | 502 | } |
| 503 | }; | 503 | }; |
| 504 | 504 | ||
| 505 | /// A single value captured in the closure of a namespace type. This is not a plain | ||
| 506 | /// `Index` because we must differentiate between the following cases: | ||
| 507 | /// * runtime-known value (where we store the type) | ||
| 508 | /// * comptime-known value (where we store the value) | ||
| 509 | /// * decl val (so that we can analyze the value lazily) | ||
| 510 | /// * decl ref (so that we can analyze the reference lazily) | ||
| 511 | pub const CaptureValue = packed struct(u32) { | ||
| 512 | tag: enum { @"comptime", runtime, decl_val, decl_ref }, | ||
| 513 | idx: u30, | ||
| 514 | |||
| 515 | pub fn wrap(val: Unwrapped) CaptureValue { | ||
| 516 | return switch (val) { | ||
| 517 | .@"comptime" => |i| .{ .tag = .@"comptime", .idx = @intCast(@intFromEnum(i)) }, | ||
| 518 | .runtime => |i| .{ .tag = .runtime, .idx = @intCast(@intFromEnum(i)) }, | ||
| 519 | .decl_val => |i| .{ .tag = .decl_val, .idx = @intCast(@intFromEnum(i)) }, | ||
| 520 | .decl_ref => |i| .{ .tag = .decl_ref, .idx = @intCast(@intFromEnum(i)) }, | ||
| 521 | }; | ||
| 522 | } | ||
| 523 | pub fn unwrap(val: CaptureValue) Unwrapped { | ||
| 524 | return switch (val.tag) { | ||
| 525 | .@"comptime" => .{ .@"comptime" = @enumFromInt(val.idx) }, | ||
| 526 | .runtime => .{ .runtime = @enumFromInt(val.idx) }, | ||
| 527 | .decl_val => .{ .decl_val = @enumFromInt(val.idx) }, | ||
| 528 | .decl_ref => .{ .decl_ref = @enumFromInt(val.idx) }, | ||
| 529 | }; | ||
| 530 | } | ||
| 531 | |||
| 532 | pub const Unwrapped = union(enum) { | ||
| 533 | /// Index refers to the value. | ||
| 534 | @"comptime": Index, | ||
| 535 | /// Index refers to the type. | ||
| 536 | runtime: Index, | ||
| 537 | decl_val: DeclIndex, | ||
| 538 | decl_ref: DeclIndex, | ||
| 539 | }; | ||
| 540 | |||
| 541 | pub const Slice = struct { | ||
| 542 | start: u32, | ||
| 543 | len: u32, | ||
| 544 | pub fn get(slice: Slice, ip: *const InternPool) []CaptureValue { | ||
| 545 | return @ptrCast(ip.extra.items[slice.start..][0..slice.len]); | ||
| 546 | } | ||
| 547 | }; | ||
| 548 | }; | ||
| 549 | |||
| 505 | pub const Key = union(enum) { | 550 | pub const Key = union(enum) { |
| 506 | int_type: IntType, | 551 | int_type: IntType, |
| 507 | ptr_type: PtrType, | 552 | ptr_type: PtrType, |
| ... | @@ -516,14 +561,14 @@ pub const Key = union(enum) { | ... | @@ -516,14 +561,14 @@ pub const Key = union(enum) { |
| 516 | /// This represents a struct that has been explicitly declared in source code, | 561 | /// This represents a struct that has been explicitly declared in source code, |
| 517 | /// or was created with `@Type`. It is unique and based on a declaration. | 562 | /// or was created with `@Type`. It is unique and based on a declaration. |
| 518 | /// It may be a tuple, if declared like this: `struct {A, B, C}`. | 563 | /// It may be a tuple, if declared like this: `struct {A, B, C}`. |
| 519 | struct_type: StructType, | 564 | struct_type: NamespaceType, |
| 520 | /// This is an anonymous struct or tuple type which has no corresponding | 565 | /// This is an anonymous struct or tuple type which has no corresponding |
| 521 | /// declaration. It is used for types that have no `struct` keyword in the | 566 | /// declaration. It is used for types that have no `struct` keyword in the |
| 522 | /// source code, and were not created via `@Type`. | 567 | /// source code, and were not created via `@Type`. |
| 523 | anon_struct_type: AnonStructType, | 568 | anon_struct_type: AnonStructType, |
| 524 | union_type: Key.UnionType, | 569 | union_type: NamespaceType, |
| 525 | opaque_type: OpaqueType, | 570 | opaque_type: NamespaceType, |
| 526 | enum_type: EnumType, | 571 | enum_type: NamespaceType, |
| 527 | func_type: FuncType, | 572 | func_type: FuncType, |
| 528 | error_set_type: ErrorSetType, | 573 | error_set_type: ErrorSetType, |
| 529 | /// The payload is the function body, either a `func_decl` or `func_instance`. | 574 | /// The payload is the function body, either a `func_decl` or `func_instance`. |
| ... | @@ -645,348 +690,6 @@ pub const Key = union(enum) { | ... | @@ -645,348 +690,6 @@ pub const Key = union(enum) { |
| 645 | child: Index, | 690 | child: Index, |
| 646 | }; | 691 | }; |
| 647 | 692 | ||
| 648 | pub const OpaqueType = extern struct { | ||
| 649 | /// The Decl that corresponds to the opaque itself. | ||
| 650 | decl: DeclIndex, | ||
| 651 | /// Represents the declarations inside this opaque. | ||
| 652 | namespace: NamespaceIndex, | ||
| 653 | zir_index: TrackedInst.Index.Optional, | ||
| 654 | }; | ||
| 655 | |||
| 656 | /// Although packed structs and non-packed structs are encoded differently, | ||
| 657 | /// this struct is used for both categories since they share some common | ||
| 658 | /// functionality. | ||
| 659 | pub const StructType = struct { | ||
| 660 | extra_index: u32, | ||
| 661 | /// `none` when the struct is `@TypeOf(.{})`. | ||
| 662 | decl: OptionalDeclIndex, | ||
| 663 | /// `none` when the struct has no declarations. | ||
| 664 | namespace: OptionalNamespaceIndex, | ||
| 665 | /// Index of the struct_decl ZIR instruction. | ||
| 666 | zir_index: TrackedInst.Index.Optional, | ||
| 667 | layout: std.builtin.Type.ContainerLayout, | ||
| 668 | field_names: NullTerminatedString.Slice, | ||
| 669 | field_types: Index.Slice, | ||
| 670 | field_inits: Index.Slice, | ||
| 671 | field_aligns: Alignment.Slice, | ||
| 672 | runtime_order: RuntimeOrder.Slice, | ||
| 673 | comptime_bits: ComptimeBits, | ||
| 674 | offsets: Offsets, | ||
| 675 | names_map: OptionalMapIndex, | ||
| 676 | |||
| 677 | pub const ComptimeBits = struct { | ||
| 678 | start: u32, | ||
| 679 | /// This is the number of u32 elements, not the number of struct fields. | ||
| 680 | len: u32, | ||
| 681 | |||
| 682 | pub fn get(this: @This(), ip: *const InternPool) []u32 { | ||
| 683 | return ip.extra.items[this.start..][0..this.len]; | ||
| 684 | } | ||
| 685 | |||
| 686 | pub fn getBit(this: @This(), ip: *const InternPool, i: usize) bool { | ||
| 687 | if (this.len == 0) return false; | ||
| 688 | return @as(u1, @truncate(this.get(ip)[i / 32] >> @intCast(i % 32))) != 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | pub fn setBit(this: @This(), ip: *const InternPool, i: usize) void { | ||
| 692 | this.get(ip)[i / 32] |= @as(u32, 1) << @intCast(i % 32); | ||
| 693 | } | ||
| 694 | |||
| 695 | pub fn clearBit(this: @This(), ip: *const InternPool, i: usize) void { | ||
| 696 | this.get(ip)[i / 32] &= ~(@as(u32, 1) << @intCast(i % 32)); | ||
| 697 | } | ||
| 698 | }; | ||
| 699 | |||
| 700 | pub const Offsets = struct { | ||
| 701 | start: u32, | ||
| 702 | len: u32, | ||
| 703 | |||
| 704 | pub fn get(this: @This(), ip: *const InternPool) []u32 { | ||
| 705 | return @ptrCast(ip.extra.items[this.start..][0..this.len]); | ||
| 706 | } | ||
| 707 | }; | ||
| 708 | |||
| 709 | pub const RuntimeOrder = enum(u32) { | ||
| 710 | /// Placeholder until layout is resolved. | ||
| 711 | unresolved = std.math.maxInt(u32) - 0, | ||
| 712 | /// Field not present at runtime | ||
| 713 | omitted = std.math.maxInt(u32) - 1, | ||
| 714 | _, | ||
| 715 | |||
| 716 | pub const Slice = struct { | ||
| 717 | start: u32, | ||
| 718 | len: u32, | ||
| 719 | |||
| 720 | pub fn get(slice: RuntimeOrder.Slice, ip: *const InternPool) []RuntimeOrder { | ||
| 721 | return @ptrCast(ip.extra.items[slice.start..][0..slice.len]); | ||
| 722 | } | ||
| 723 | }; | ||
| 724 | |||
| 725 | pub fn toInt(i: @This()) ?u32 { | ||
| 726 | return switch (i) { | ||
| 727 | .omitted => null, | ||
| 728 | .unresolved => unreachable, | ||
| 729 | else => @intFromEnum(i), | ||
| 730 | }; | ||
| 731 | } | ||
| 732 | }; | ||
| 733 | |||
| 734 | /// Look up field index based on field name. | ||
| 735 | pub fn nameIndex(self: StructType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | ||
| 736 | const names_map = self.names_map.unwrap() orelse { | ||
| 737 | const i = name.toUnsigned(ip) orelse return null; | ||
| 738 | if (i >= self.field_types.len) return null; | ||
| 739 | return i; | ||
| 740 | }; | ||
| 741 | const map = &ip.maps.items[@intFromEnum(names_map)]; | ||
| 742 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) }; | ||
| 743 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | ||
| 744 | return @intCast(field_index); | ||
| 745 | } | ||
| 746 | |||
| 747 | /// Returns the already-existing field with the same name, if any. | ||
| 748 | pub fn addFieldName( | ||
| 749 | self: @This(), | ||
| 750 | ip: *InternPool, | ||
| 751 | name: NullTerminatedString, | ||
| 752 | ) ?u32 { | ||
| 753 | return ip.addFieldName(self.names_map.unwrap().?, self.field_names.start, name); | ||
| 754 | } | ||
| 755 | |||
| 756 | pub fn fieldAlign(s: @This(), ip: *const InternPool, i: usize) Alignment { | ||
| 757 | if (s.field_aligns.len == 0) return .none; | ||
| 758 | return s.field_aligns.get(ip)[i]; | ||
| 759 | } | ||
| 760 | |||
| 761 | pub fn fieldInit(s: @This(), ip: *const InternPool, i: usize) Index { | ||
| 762 | if (s.field_inits.len == 0) return .none; | ||
| 763 | assert(s.haveFieldInits(ip)); | ||
| 764 | return s.field_inits.get(ip)[i]; | ||
| 765 | } | ||
| 766 | |||
| 767 | /// Returns `none` in the case the struct is a tuple. | ||
| 768 | pub fn fieldName(s: @This(), ip: *const InternPool, i: usize) OptionalNullTerminatedString { | ||
| 769 | if (s.field_names.len == 0) return .none; | ||
| 770 | return s.field_names.get(ip)[i].toOptional(); | ||
| 771 | } | ||
| 772 | |||
| 773 | pub fn fieldIsComptime(s: @This(), ip: *const InternPool, i: usize) bool { | ||
| 774 | return s.comptime_bits.getBit(ip, i); | ||
| 775 | } | ||
| 776 | |||
| 777 | pub fn setFieldComptime(s: @This(), ip: *InternPool, i: usize) void { | ||
| 778 | s.comptime_bits.setBit(ip, i); | ||
| 779 | } | ||
| 780 | |||
| 781 | /// Reads the non-opv flag calculated during AstGen. Used to short-circuit more | ||
| 782 | /// complicated logic. | ||
| 783 | pub fn knownNonOpv(s: @This(), ip: *InternPool) bool { | ||
| 784 | return switch (s.layout) { | ||
| 785 | .Packed => false, | ||
| 786 | .Auto, .Extern => s.flagsPtr(ip).known_non_opv, | ||
| 787 | }; | ||
| 788 | } | ||
| 789 | |||
| 790 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 791 | /// Asserts the struct is not packed. | ||
| 792 | pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStruct.Flags { | ||
| 793 | assert(self.layout != .Packed); | ||
| 794 | const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?; | ||
| 795 | return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]); | ||
| 796 | } | ||
| 797 | |||
| 798 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 799 | /// Asserts that the struct is packed. | ||
| 800 | pub fn packedFlagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStructPacked.Flags { | ||
| 801 | assert(self.layout == .Packed); | ||
| 802 | const flags_field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?; | ||
| 803 | return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]); | ||
| 804 | } | ||
| 805 | |||
| 806 | pub fn assumeRuntimeBitsIfFieldTypesWip(s: @This(), ip: *InternPool) bool { | ||
| 807 | if (s.layout == .Packed) return false; | ||
| 808 | const flags_ptr = s.flagsPtr(ip); | ||
| 809 | if (flags_ptr.field_types_wip) { | ||
| 810 | flags_ptr.assumed_runtime_bits = true; | ||
| 811 | return true; | ||
| 812 | } | ||
| 813 | return false; | ||
| 814 | } | ||
| 815 | |||
| 816 | pub fn setTypesWip(s: @This(), ip: *InternPool) bool { | ||
| 817 | if (s.layout == .Packed) return false; | ||
| 818 | const flags_ptr = s.flagsPtr(ip); | ||
| 819 | if (flags_ptr.field_types_wip) return true; | ||
| 820 | flags_ptr.field_types_wip = true; | ||
| 821 | return false; | ||
| 822 | } | ||
| 823 | |||
| 824 | pub fn clearTypesWip(s: @This(), ip: *InternPool) void { | ||
| 825 | if (s.layout == .Packed) return; | ||
| 826 | s.flagsPtr(ip).field_types_wip = false; | ||
| 827 | } | ||
| 828 | |||
| 829 | pub fn setLayoutWip(s: @This(), ip: *InternPool) bool { | ||
| 830 | if (s.layout == .Packed) return false; | ||
| 831 | const flags_ptr = s.flagsPtr(ip); | ||
| 832 | if (flags_ptr.layout_wip) return true; | ||
| 833 | flags_ptr.layout_wip = true; | ||
| 834 | return false; | ||
| 835 | } | ||
| 836 | |||
| 837 | pub fn clearLayoutWip(s: @This(), ip: *InternPool) void { | ||
| 838 | if (s.layout == .Packed) return; | ||
| 839 | s.flagsPtr(ip).layout_wip = false; | ||
| 840 | } | ||
| 841 | |||
| 842 | pub fn setAlignmentWip(s: @This(), ip: *InternPool) bool { | ||
| 843 | if (s.layout == .Packed) return false; | ||
| 844 | const flags_ptr = s.flagsPtr(ip); | ||
| 845 | if (flags_ptr.alignment_wip) return true; | ||
| 846 | flags_ptr.alignment_wip = true; | ||
| 847 | return false; | ||
| 848 | } | ||
| 849 | |||
| 850 | pub fn clearAlignmentWip(s: @This(), ip: *InternPool) void { | ||
| 851 | if (s.layout == .Packed) return; | ||
| 852 | s.flagsPtr(ip).alignment_wip = false; | ||
| 853 | } | ||
| 854 | |||
| 855 | pub fn setInitsWip(s: @This(), ip: *InternPool) bool { | ||
| 856 | switch (s.layout) { | ||
| 857 | .Packed => { | ||
| 858 | const flag = &s.packedFlagsPtr(ip).field_inits_wip; | ||
| 859 | if (flag.*) return true; | ||
| 860 | flag.* = true; | ||
| 861 | return false; | ||
| 862 | }, | ||
| 863 | .Auto, .Extern => { | ||
| 864 | const flag = &s.flagsPtr(ip).field_inits_wip; | ||
| 865 | if (flag.*) return true; | ||
| 866 | flag.* = true; | ||
| 867 | return false; | ||
| 868 | }, | ||
| 869 | } | ||
| 870 | } | ||
| 871 | |||
| 872 | pub fn clearInitsWip(s: @This(), ip: *InternPool) void { | ||
| 873 | switch (s.layout) { | ||
| 874 | .Packed => s.packedFlagsPtr(ip).field_inits_wip = false, | ||
| 875 | .Auto, .Extern => s.flagsPtr(ip).field_inits_wip = false, | ||
| 876 | } | ||
| 877 | } | ||
| 878 | |||
| 879 | pub fn setFullyResolved(s: @This(), ip: *InternPool) bool { | ||
| 880 | if (s.layout == .Packed) return true; | ||
| 881 | const flags_ptr = s.flagsPtr(ip); | ||
| 882 | if (flags_ptr.fully_resolved) return true; | ||
| 883 | flags_ptr.fully_resolved = true; | ||
| 884 | return false; | ||
| 885 | } | ||
| 886 | |||
| 887 | pub fn clearFullyResolved(s: @This(), ip: *InternPool) void { | ||
| 888 | s.flagsPtr(ip).fully_resolved = false; | ||
| 889 | } | ||
| 890 | |||
| 891 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 892 | /// Asserts the struct is not packed. | ||
| 893 | pub fn size(self: @This(), ip: *InternPool) *u32 { | ||
| 894 | assert(self.layout != .Packed); | ||
| 895 | const size_field_index = std.meta.fieldIndex(Tag.TypeStruct, "size").?; | ||
| 896 | return @ptrCast(&ip.extra.items[self.extra_index + size_field_index]); | ||
| 897 | } | ||
| 898 | |||
| 899 | /// The backing integer type of the packed struct. Whether zig chooses | ||
| 900 | /// this type or the user specifies it, it is stored here. This will be | ||
| 901 | /// set to `none` until the layout is resolved. | ||
| 902 | /// Asserts the struct is packed. | ||
| 903 | pub fn backingIntType(s: @This(), ip: *const InternPool) *Index { | ||
| 904 | assert(s.layout == .Packed); | ||
| 905 | const field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_ty").?; | ||
| 906 | return @ptrCast(&ip.extra.items[s.extra_index + field_index]); | ||
| 907 | } | ||
| 908 | |||
| 909 | /// Asserts the struct is not packed. | ||
| 910 | pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { | ||
| 911 | assert(s.layout != .Packed); | ||
| 912 | const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; | ||
| 913 | ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); | ||
| 914 | } | ||
| 915 | |||
| 916 | pub fn haveFieldTypes(s: @This(), ip: *const InternPool) bool { | ||
| 917 | const types = s.field_types.get(ip); | ||
| 918 | return types.len == 0 or types[0] != .none; | ||
| 919 | } | ||
| 920 | |||
| 921 | pub fn haveFieldInits(s: @This(), ip: *const InternPool) bool { | ||
| 922 | return switch (s.layout) { | ||
| 923 | .Packed => s.packedFlagsPtr(ip).inits_resolved, | ||
| 924 | .Auto, .Extern => s.flagsPtr(ip).inits_resolved, | ||
| 925 | }; | ||
| 926 | } | ||
| 927 | |||
| 928 | pub fn setHaveFieldInits(s: @This(), ip: *InternPool) void { | ||
| 929 | switch (s.layout) { | ||
| 930 | .Packed => s.packedFlagsPtr(ip).inits_resolved = true, | ||
| 931 | .Auto, .Extern => s.flagsPtr(ip).inits_resolved = true, | ||
| 932 | } | ||
| 933 | } | ||
| 934 | |||
| 935 | pub fn haveLayout(s: @This(), ip: *InternPool) bool { | ||
| 936 | return switch (s.layout) { | ||
| 937 | .Packed => s.backingIntType(ip).* != .none, | ||
| 938 | .Auto, .Extern => s.flagsPtr(ip).layout_resolved, | ||
| 939 | }; | ||
| 940 | } | ||
| 941 | |||
| 942 | pub fn isTuple(s: @This(), ip: *InternPool) bool { | ||
| 943 | return s.layout != .Packed and s.flagsPtr(ip).is_tuple; | ||
| 944 | } | ||
| 945 | |||
| 946 | pub fn hasReorderedFields(s: @This()) bool { | ||
| 947 | return s.layout == .Auto; | ||
| 948 | } | ||
| 949 | |||
| 950 | pub const RuntimeOrderIterator = struct { | ||
| 951 | ip: *InternPool, | ||
| 952 | field_index: u32, | ||
| 953 | struct_type: InternPool.Key.StructType, | ||
| 954 | |||
| 955 | pub fn next(it: *@This()) ?u32 { | ||
| 956 | var i = it.field_index; | ||
| 957 | |||
| 958 | if (i >= it.struct_type.field_types.len) | ||
| 959 | return null; | ||
| 960 | |||
| 961 | if (it.struct_type.hasReorderedFields()) { | ||
| 962 | it.field_index += 1; | ||
| 963 | return it.struct_type.runtime_order.get(it.ip)[i].toInt(); | ||
| 964 | } | ||
| 965 | |||
| 966 | while (it.struct_type.fieldIsComptime(it.ip, i)) { | ||
| 967 | i += 1; | ||
| 968 | if (i >= it.struct_type.field_types.len) | ||
| 969 | return null; | ||
| 970 | } | ||
| 971 | |||
| 972 | it.field_index = i + 1; | ||
| 973 | return i; | ||
| 974 | } | ||
| 975 | }; | ||
| 976 | |||
| 977 | /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. | ||
| 978 | /// May or may not include zero-bit fields. | ||
| 979 | /// Asserts the struct is not packed. | ||
| 980 | pub fn iterateRuntimeOrder(s: @This(), ip: *InternPool) RuntimeOrderIterator { | ||
| 981 | assert(s.layout != .Packed); | ||
| 982 | return .{ | ||
| 983 | .ip = ip, | ||
| 984 | .field_index = 0, | ||
| 985 | .struct_type = s, | ||
| 986 | }; | ||
| 987 | } | ||
| 988 | }; | ||
| 989 | |||
| 990 | pub const AnonStructType = struct { | 693 | pub const AnonStructType = struct { |
| 991 | types: Index.Slice, | 694 | types: Index.Slice, |
| 992 | /// This may be empty, indicating this is a tuple. | 695 | /// This may be empty, indicating this is a tuple. |
| ... | @@ -1010,192 +713,41 @@ pub const Key = union(enum) { | ... | @@ -1010,192 +713,41 @@ pub const Key = union(enum) { |
| 1010 | } | 713 | } |
| 1011 | }; | 714 | }; |
| 1012 | 715 | ||
| 1013 | /// Serves two purposes: | 716 | /// This is the hashmap key. To fetch other data associated with the type, see: |
| 1014 | /// * Being the key in the InternPool hash map, which only requires the `decl` field. | 717 | /// * `loadStructType` |
| 1015 | /// * Provide the other fields that do not require chasing the enum type. | 718 | /// * `loadUnionType` |
| 1016 | pub const UnionType = struct { | 719 | /// * `loadEnumType` |
| 1017 | /// The Decl that corresponds to the union itself. | 720 | /// * `loadOpaqueType` |
| 1018 | decl: DeclIndex, | 721 | pub const NamespaceType = union(enum) { |
| 1019 | /// The index of the `Tag.TypeUnion` payload. Ignored by `get`, | 722 | /// This type corresponds to an actual source declaration, e.g. `struct { ... }`. |
| 1020 | /// populated by `indexToKey`. | 723 | /// It is hashed based on its ZIR instruction index and set of captures. |
| 1021 | extra_index: u32, | 724 | declared: struct { |
| 1022 | namespace: NamespaceIndex, | 725 | /// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction. |
| 1023 | flags: Tag.TypeUnion.Flags, | 726 | zir_index: TrackedInst.Index, |
| 1024 | /// The enum that provides the list of field names and values. | 727 | /// The captured values of this type. These values must be fully resolved per the language spec. |
| 1025 | enum_tag_ty: Index, | 728 | captures: union(enum) { |
| 1026 | zir_index: TrackedInst.Index.Optional, | 729 | owned: CaptureValue.Slice, |
| 1027 | 730 | external: []const CaptureValue, | |
| 1028 | /// The returned pointer expires with any addition to the `InternPool`. | 731 | }, |
| 1029 | pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags { | 732 | }, |
| 1030 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; | 733 | /// This type is an automatically-generated enum tag type for a union. |
| 1031 | return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]); | 734 | /// It is hashed based on the index of the union type it corresponds to. |
| 1032 | } | 735 | generated_tag: struct { |
| 1033 | 736 | /// The union for which this is a tag type. | |
| 1034 | /// The returned pointer expires with any addition to the `InternPool`. | 737 | union_type: Index, |
| 1035 | pub fn size(self: @This(), ip: *InternPool) *u32 { | 738 | }, |
| 1036 | const size_field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?; | 739 | /// This type originates from a reification via `@Type`. |
| 1037 | return &ip.extra.items[self.extra_index + size_field_index]; | 740 | /// It is hased based on its ZIR instruction index and fields, attributes, etc. |
| 1038 | } | 741 | /// To avoid making this key overly complex, the type-specific data is hased by Sema. |
| 1039 | 742 | reified: struct { | |
| 1040 | /// The returned pointer expires with any addition to the `InternPool`. | 743 | /// A `reify` instruction. |
| 1041 | pub fn padding(self: @This(), ip: *InternPool) *u32 { | 744 | zir_index: TrackedInst.Index, |
| 1042 | const padding_field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?; | 745 | /// A hash of this type's attributes, fields, etc, generated by Sema. |
| 1043 | return &ip.extra.items[self.extra_index + padding_field_index]; | 746 | type_hash: u64, |
| 1044 | } | 747 | }, |
| 1045 | 748 | /// This type is `@TypeOf(.{})`. | |
| 1046 | pub fn haveFieldTypes(self: @This(), ip: *const InternPool) bool { | 749 | /// TODO: can we change the language spec to not special-case this type? |
| 1047 | return self.flagsPtr(ip).status.haveFieldTypes(); | 750 | empty_struct: void, |
| 1048 | } | ||
| 1049 | |||
| 1050 | pub fn hasTag(self: @This(), ip: *const InternPool) bool { | ||
| 1051 | return self.flagsPtr(ip).runtime_tag.hasTag(); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | pub fn getLayout(self: @This(), ip: *const InternPool) std.builtin.Type.ContainerLayout { | ||
| 1055 | return self.flagsPtr(ip).layout; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | pub fn haveLayout(self: @This(), ip: *const InternPool) bool { | ||
| 1059 | return self.flagsPtr(ip).status.haveLayout(); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | /// Pointer to an enum type which is used for the tag of the union. | ||
| 1063 | /// This type is created even for untagged unions, even when the memory | ||
| 1064 | /// layout does not store the tag. | ||
| 1065 | /// Whether zig chooses this type or the user specifies it, it is stored here. | ||
| 1066 | /// This will be set to the null type until status is `have_field_types`. | ||
| 1067 | /// This accessor is provided so that the tag type can be mutated, and so that | ||
| 1068 | /// when it is mutated, the mutations are observed. | ||
| 1069 | /// The returned pointer is invalidated when something is added to the `InternPool`. | ||
| 1070 | pub fn tagTypePtr(self: @This(), ip: *const InternPool) *Index { | ||
| 1071 | const tag_ty_field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?; | ||
| 1072 | return @ptrCast(&ip.extra.items[self.extra_index + tag_ty_field_index]); | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | pub fn setFieldTypes(self: @This(), ip: *InternPool, types: []const Index) void { | ||
| 1076 | @memcpy((Index.Slice{ | ||
| 1077 | .start = @intCast(self.extra_index + @typeInfo(Tag.TypeUnion).Struct.fields.len), | ||
| 1078 | .len = @intCast(types.len), | ||
| 1079 | }).get(ip), types); | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | pub fn setFieldAligns(self: @This(), ip: *InternPool, aligns: []const Alignment) void { | ||
| 1083 | if (aligns.len == 0) return; | ||
| 1084 | assert(self.flagsPtr(ip).any_aligned_fields); | ||
| 1085 | @memcpy((Alignment.Slice{ | ||
| 1086 | .start = @intCast( | ||
| 1087 | self.extra_index + @typeInfo(Tag.TypeUnion).Struct.fields.len + aligns.len, | ||
| 1088 | ), | ||
| 1089 | .len = @intCast(aligns.len), | ||
| 1090 | }).get(ip), aligns); | ||
| 1091 | } | ||
| 1092 | }; | ||
| 1093 | |||
| 1094 | pub const EnumType = struct { | ||
| 1095 | /// The Decl that corresponds to the enum itself. | ||
| 1096 | decl: DeclIndex, | ||
| 1097 | /// Represents the declarations inside this enum. | ||
| 1098 | namespace: OptionalNamespaceIndex, | ||
| 1099 | /// An integer type which is used for the numerical value of the enum. | ||
| 1100 | /// This field is present regardless of whether the enum has an | ||
| 1101 | /// explicitly provided tag type or auto-numbered. | ||
| 1102 | tag_ty: Index, | ||
| 1103 | /// Set of field names in declaration order. | ||
| 1104 | names: NullTerminatedString.Slice, | ||
| 1105 | /// Maps integer tag value to field index. | ||
| 1106 | /// Entries are in declaration order, same as `fields`. | ||
| 1107 | /// If this is empty, it means the enum tags are auto-numbered. | ||
| 1108 | values: Index.Slice, | ||
| 1109 | tag_mode: TagMode, | ||
| 1110 | /// This is ignored by `get` but will always be provided by `indexToKey`. | ||
| 1111 | names_map: OptionalMapIndex = .none, | ||
| 1112 | /// This is ignored by `get` but will be provided by `indexToKey` when | ||
| 1113 | /// a value map exists. | ||
| 1114 | values_map: OptionalMapIndex = .none, | ||
| 1115 | zir_index: TrackedInst.Index.Optional, | ||
| 1116 | |||
| 1117 | pub const TagMode = enum { | ||
| 1118 | /// The integer tag type was auto-numbered by zig. | ||
| 1119 | auto, | ||
| 1120 | /// The integer tag type was provided by the enum declaration, and the enum | ||
| 1121 | /// is exhaustive. | ||
| 1122 | explicit, | ||
| 1123 | /// The integer tag type was provided by the enum declaration, and the enum | ||
| 1124 | /// is non-exhaustive. | ||
| 1125 | nonexhaustive, | ||
| 1126 | }; | ||
| 1127 | |||
| 1128 | /// Look up field index based on field name. | ||
| 1129 | pub fn nameIndex(self: EnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | ||
| 1130 | const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)]; | ||
| 1131 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) }; | ||
| 1132 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | ||
| 1133 | return @intCast(field_index); | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | /// Look up field index based on tag value. | ||
| 1137 | /// Asserts that `values_map` is not `none`. | ||
| 1138 | /// This function returns `null` when `tag_val` does not have the | ||
| 1139 | /// integer tag type of the enum. | ||
| 1140 | pub fn tagValueIndex(self: EnumType, ip: *const InternPool, tag_val: Index) ?u32 { | ||
| 1141 | assert(tag_val != .none); | ||
| 1142 | // TODO: we should probably decide a single interface for this function, but currently | ||
| 1143 | // it's being called with both tag values and underlying ints. Fix this! | ||
| 1144 | const int_tag_val = switch (ip.indexToKey(tag_val)) { | ||
| 1145 | .enum_tag => |enum_tag| enum_tag.int, | ||
| 1146 | .int => tag_val, | ||
| 1147 | else => unreachable, | ||
| 1148 | }; | ||
| 1149 | if (self.values_map.unwrap()) |values_map| { | ||
| 1150 | const map = &ip.maps.items[@intFromEnum(values_map)]; | ||
| 1151 | const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) }; | ||
| 1152 | const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null; | ||
| 1153 | return @intCast(field_index); | ||
| 1154 | } | ||
| 1155 | // Auto-numbered enum. Convert `int_tag_val` to field index. | ||
| 1156 | const field_index = switch (ip.indexToKey(int_tag_val).int.storage) { | ||
| 1157 | inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null, | ||
| 1158 | .big_int => |x| x.to(u32) catch return null, | ||
| 1159 | .lazy_align, .lazy_size => unreachable, | ||
| 1160 | }; | ||
| 1161 | return if (field_index < self.names.len) field_index else null; | ||
| 1162 | } | ||
| 1163 | }; | ||
| 1164 | |||
| 1165 | pub const IncompleteEnumType = struct { | ||
| 1166 | /// Same as corresponding `EnumType` field. | ||
| 1167 | decl: DeclIndex, | ||
| 1168 | /// Same as corresponding `EnumType` field. | ||
| 1169 | namespace: OptionalNamespaceIndex, | ||
| 1170 | /// The field names and field values are not known yet, but | ||
| 1171 | /// the number of fields must be known ahead of time. | ||
| 1172 | fields_len: u32, | ||
| 1173 | /// This information is needed so that the size does not change | ||
| 1174 | /// later when populating field values. | ||
| 1175 | has_values: bool, | ||
| 1176 | /// Same as corresponding `EnumType` field. | ||
| 1177 | tag_mode: EnumType.TagMode, | ||
| 1178 | /// This may be updated via `setTagType` later. | ||
| 1179 | tag_ty: Index = .none, | ||
| 1180 | zir_index: TrackedInst.Index.Optional, | ||
| 1181 | |||
| 1182 | pub fn toEnumType(self: @This()) EnumType { | ||
| 1183 | return .{ | ||
| 1184 | .decl = self.decl, | ||
| 1185 | .namespace = self.namespace, | ||
| 1186 | .tag_ty = self.tag_ty, | ||
| 1187 | .tag_mode = self.tag_mode, | ||
| 1188 | .names = .{ .start = 0, .len = 0 }, | ||
| 1189 | .values = .{ .start = 0, .len = 0 }, | ||
| 1190 | .zir_index = self.zir_index, | ||
| 1191 | }; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | /// Only the decl is used for hashing and equality, so we can construct | ||
| 1195 | /// this minimal key for use with `map`. | ||
| 1196 | pub fn toKey(self: @This()) Key { | ||
| 1197 | return .{ .enum_type = self.toEnumType() }; | ||
| 1198 | } | ||
| 1199 | }; | 751 | }; |
| 1200 | 752 | ||
| 1201 | pub const FuncType = struct { | 753 | pub const FuncType = struct { |
| ... | @@ -1546,12 +1098,37 @@ pub const Key = union(enum) { | ... | @@ -1546,12 +1098,37 @@ pub const Key = union(enum) { |
| 1546 | .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)), | 1098 | .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)), |
| 1547 | }, | 1099 | }, |
| 1548 | 1100 | ||
| 1549 | inline .opaque_type, | 1101 | .variable => |variable| Hash.hash(seed, asBytes(&variable.decl)), |
| 1102 | |||
| 1103 | .opaque_type, | ||
| 1550 | .enum_type, | 1104 | .enum_type, |
| 1551 | .variable, | ||
| 1552 | .union_type, | 1105 | .union_type, |
| 1553 | .struct_type, | 1106 | .struct_type, |
| 1554 | => |x| Hash.hash(seed, asBytes(&x.decl)), | 1107 | => |namespace_type| { |
| 1108 | var hasher = Hash.init(seed); | ||
| 1109 | std.hash.autoHash(&hasher, std.meta.activeTag(namespace_type)); | ||
| 1110 | switch (namespace_type) { | ||
| 1111 | .declared => |declared| { | ||
| 1112 | std.hash.autoHash(&hasher, declared.zir_index); | ||
| 1113 | const captures = switch (declared.captures) { | ||
| 1114 | .owned => |cvs| cvs.get(ip), | ||
| 1115 | .external => |cvs| cvs, | ||
| 1116 | }; | ||
| 1117 | for (captures) |cv| { | ||
| 1118 | std.hash.autoHash(&hasher, cv); | ||
| 1119 | } | ||
| 1120 | }, | ||
| 1121 | .generated_tag => |generated_tag| { | ||
| 1122 | std.hash.autoHash(&hasher, generated_tag.union_type); | ||
| 1123 | }, | ||
| 1124 | .reified => |reified| { | ||
| 1125 | std.hash.autoHash(&hasher, reified.zir_index); | ||
| 1126 | std.hash.autoHash(&hasher, reified.type_hash); | ||
| 1127 | }, | ||
| 1128 | .empty_struct => {}, | ||
| 1129 | } | ||
| 1130 | return hasher.final(); | ||
| 1131 | }, | ||
| 1555 | 1132 | ||
| 1556 | .int => |int| { | 1133 | .int => |int| { |
| 1557 | var hasher = Hash.init(seed); | 1134 | var hasher = Hash.init(seed); |
| ... | @@ -1956,21 +1533,31 @@ pub const Key = union(enum) { | ... | @@ -1956,21 +1533,31 @@ pub const Key = union(enum) { |
| 1956 | } | 1533 | } |
| 1957 | }, | 1534 | }, |
| 1958 | 1535 | ||
| 1959 | .opaque_type => |a_info| { | 1536 | inline .opaque_type, .enum_type, .union_type, .struct_type => |a_info, a_tag_ct| { |
| 1960 | const b_info = b.opaque_type; | 1537 | const b_info = @field(b, @tagName(a_tag_ct)); |
| 1961 | return a_info.decl == b_info.decl; | 1538 | if (std.meta.activeTag(a_info) != b_info) return false; |
| 1962 | }, | 1539 | switch (a_info) { |
| 1963 | .enum_type => |a_info| { | 1540 | .declared => |a_d| { |
| 1964 | const b_info = b.enum_type; | 1541 | const b_d = b_info.declared; |
| 1965 | return a_info.decl == b_info.decl; | 1542 | if (a_d.zir_index != b_d.zir_index) return false; |
| 1966 | }, | 1543 | const a_captures = switch (a_d.captures) { |
| 1967 | .union_type => |a_info| { | 1544 | .owned => |s| s.get(ip), |
| 1968 | const b_info = b.union_type; | 1545 | .external => |cvs| cvs, |
| 1969 | return a_info.decl == b_info.decl; | 1546 | }; |
| 1970 | }, | 1547 | const b_captures = switch (b_d.captures) { |
| 1971 | .struct_type => |a_info| { | 1548 | .owned => |s| s.get(ip), |
| 1972 | const b_info = b.struct_type; | 1549 | .external => |cvs| cvs, |
| 1973 | return a_info.decl == b_info.decl; | 1550 | }; |
| 1551 | return std.mem.eql(u32, @ptrCast(a_captures), @ptrCast(b_captures)); | ||
| 1552 | }, | ||
| 1553 | .generated_tag => |a_gt| return a_gt.union_type == b_info.generated_tag.union_type, | ||
| 1554 | .reified => |a_r| { | ||
| 1555 | const b_r = b_info.reified; | ||
| 1556 | return a_r.zir_index == b_r.zir_index and | ||
| 1557 | a_r.type_hash == b_r.type_hash; | ||
| 1558 | }, | ||
| 1559 | .empty_struct => return true, | ||
| 1560 | } | ||
| 1974 | }, | 1561 | }, |
| 1975 | .aggregate => |a_info| { | 1562 | .aggregate => |a_info| { |
| 1976 | const b_info = b.aggregate; | 1563 | const b_info = b.aggregate; |
| ... | @@ -2112,21 +1699,15 @@ pub const RequiresComptime = enum(u2) { no, yes, unknown, wip }; | ... | @@ -2112,21 +1699,15 @@ pub const RequiresComptime = enum(u2) { no, yes, unknown, wip }; |
| 2112 | // Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a | 1699 | // Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a |
| 2113 | // minimal hashmap key, this type is a convenience type that contains info | 1700 | // minimal hashmap key, this type is a convenience type that contains info |
| 2114 | // needed by semantic analysis. | 1701 | // needed by semantic analysis. |
| 2115 | pub const UnionType = struct { | 1702 | pub const LoadedUnionType = struct { |
| 1703 | /// The index of the `Tag.TypeUnion` payload. | ||
| 1704 | extra_index: u32, | ||
| 2116 | /// The Decl that corresponds to the union itself. | 1705 | /// The Decl that corresponds to the union itself. |
| 2117 | decl: DeclIndex, | 1706 | decl: DeclIndex, |
| 2118 | /// Represents the declarations inside this union. | 1707 | /// Represents the declarations inside this union. |
| 2119 | namespace: NamespaceIndex, | 1708 | namespace: OptionalNamespaceIndex, |
| 2120 | /// The enum tag type. | 1709 | /// The enum tag type. |
| 2121 | enum_tag_ty: Index, | 1710 | enum_tag_ty: Index, |
| 2122 | /// The integer tag type of the enum. | ||
| 2123 | int_tag_ty: Index, | ||
| 2124 | /// ABI size of the union, including padding | ||
| 2125 | size: u64, | ||
| 2126 | /// Trailing padding bytes | ||
| 2127 | padding: u32, | ||
| 2128 | /// List of field names in declaration order. | ||
| 2129 | field_names: NullTerminatedString.Slice, | ||
| 2130 | /// List of field types in declaration order. | 1711 | /// List of field types in declaration order. |
| 2131 | /// These are `none` until `status` is `have_field_types` or `have_layout`. | 1712 | /// These are `none` until `status` is `have_field_types` or `have_layout`. |
| 2132 | field_types: Index.Slice, | 1713 | field_types: Index.Slice, |
| ... | @@ -2134,12 +1715,9 @@ pub const UnionType = struct { | ... | @@ -2134,12 +1715,9 @@ pub const UnionType = struct { |
| 2134 | /// `none` means the ABI alignment of the type. | 1715 | /// `none` means the ABI alignment of the type. |
| 2135 | /// If this slice has length 0 it means all elements are `none`. | 1716 | /// If this slice has length 0 it means all elements are `none`. |
| 2136 | field_aligns: Alignment.Slice, | 1717 | field_aligns: Alignment.Slice, |
| 2137 | /// Index of the union_decl ZIR instruction. | 1718 | /// Index of the union_decl or reify ZIR instruction. |
| 2138 | zir_index: TrackedInst.Index.Optional, | 1719 | zir_index: TrackedInst.Index, |
| 2139 | /// Index into extra array of the `flags` field. | 1720 | captures: CaptureValue.Slice, |
| 2140 | flags_index: u32, | ||
| 2141 | /// Copied from `enum_tag_ty`. | ||
| 2142 | names_map: OptionalMapIndex, | ||
| 2143 | 1721 | ||
| 2144 | pub const RuntimeTag = enum(u2) { | 1722 | pub const RuntimeTag = enum(u2) { |
| 2145 | none, | 1723 | none, |
| ... | @@ -2154,118 +1732,823 @@ pub const UnionType = struct { | ... | @@ -2154,118 +1732,823 @@ pub const UnionType = struct { |
| 2154 | } | 1732 | } |
| 2155 | }; | 1733 | }; |
| 2156 | 1734 | ||
| 2157 | pub const Status = enum(u3) { | 1735 | pub const Status = enum(u3) { |
| 2158 | none, | 1736 | none, |
| 2159 | field_types_wip, | 1737 | field_types_wip, |
| 2160 | have_field_types, | 1738 | have_field_types, |
| 2161 | layout_wip, | 1739 | layout_wip, |
| 2162 | have_layout, | 1740 | have_layout, |
| 2163 | fully_resolved_wip, | 1741 | fully_resolved_wip, |
| 2164 | /// The types and all its fields have had their layout resolved. | 1742 | /// The types and all its fields have had their layout resolved. |
| 2165 | /// Even through pointer, which `have_layout` does not ensure. | 1743 | /// Even through pointer, which `have_layout` does not ensure. |
| 2166 | fully_resolved, | 1744 | fully_resolved, |
| 1745 | |||
| 1746 | pub fn haveFieldTypes(status: Status) bool { | ||
| 1747 | return switch (status) { | ||
| 1748 | .none, | ||
| 1749 | .field_types_wip, | ||
| 1750 | => false, | ||
| 1751 | .have_field_types, | ||
| 1752 | .layout_wip, | ||
| 1753 | .have_layout, | ||
| 1754 | .fully_resolved_wip, | ||
| 1755 | .fully_resolved, | ||
| 1756 | => true, | ||
| 1757 | }; | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | pub fn haveLayout(status: Status) bool { | ||
| 1761 | return switch (status) { | ||
| 1762 | .none, | ||
| 1763 | .field_types_wip, | ||
| 1764 | .have_field_types, | ||
| 1765 | .layout_wip, | ||
| 1766 | => false, | ||
| 1767 | .have_layout, | ||
| 1768 | .fully_resolved_wip, | ||
| 1769 | .fully_resolved, | ||
| 1770 | => true, | ||
| 1771 | }; | ||
| 1772 | } | ||
| 1773 | }; | ||
| 1774 | |||
| 1775 | pub fn loadTagType(self: LoadedUnionType, ip: *InternPool) LoadedEnumType { | ||
| 1776 | return ip.loadEnumType(self.enum_tag_ty); | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | /// Pointer to an enum type which is used for the tag of the union. | ||
| 1780 | /// This type is created even for untagged unions, even when the memory | ||
| 1781 | /// layout does not store the tag. | ||
| 1782 | /// Whether zig chooses this type or the user specifies it, it is stored here. | ||
| 1783 | /// This will be set to the null type until status is `have_field_types`. | ||
| 1784 | /// This accessor is provided so that the tag type can be mutated, and so that | ||
| 1785 | /// when it is mutated, the mutations are observed. | ||
| 1786 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 1787 | pub fn tagTypePtr(self: LoadedUnionType, ip: *const InternPool) *Index { | ||
| 1788 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?; | ||
| 1789 | return @ptrCast(&ip.extra.items[self.extra_index + field_index]); | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 1793 | pub fn flagsPtr(self: LoadedUnionType, ip: *const InternPool) *Tag.TypeUnion.Flags { | ||
| 1794 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; | ||
| 1795 | return @ptrCast(&ip.extra.items[self.extra_index + field_index]); | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 1799 | pub fn size(self: LoadedUnionType, ip: *const InternPool) *u32 { | ||
| 1800 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?; | ||
| 1801 | return &ip.extra.items[self.extra_index + field_index]; | ||
| 1802 | } | ||
| 1803 | |||
| 1804 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 1805 | pub fn padding(self: LoadedUnionType, ip: *const InternPool) *u32 { | ||
| 1806 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?; | ||
| 1807 | return &ip.extra.items[self.extra_index + field_index]; | ||
| 1808 | } | ||
| 1809 | |||
| 1810 | pub fn hasTag(self: LoadedUnionType, ip: *const InternPool) bool { | ||
| 1811 | return self.flagsPtr(ip).runtime_tag.hasTag(); | ||
| 1812 | } | ||
| 1813 | |||
| 1814 | pub fn haveFieldTypes(self: LoadedUnionType, ip: *const InternPool) bool { | ||
| 1815 | return self.flagsPtr(ip).status.haveFieldTypes(); | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | pub fn haveLayout(self: LoadedUnionType, ip: *const InternPool) bool { | ||
| 1819 | return self.flagsPtr(ip).status.haveLayout(); | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | pub fn getLayout(self: LoadedUnionType, ip: *const InternPool) std.builtin.Type.ContainerLayout { | ||
| 1823 | return self.flagsPtr(ip).layout; | ||
| 1824 | } | ||
| 1825 | |||
| 1826 | pub fn fieldAlign(self: LoadedUnionType, ip: *const InternPool, field_index: u32) Alignment { | ||
| 1827 | if (self.field_aligns.len == 0) return .none; | ||
| 1828 | return self.field_aligns.get(ip)[field_index]; | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | /// This does not mutate the field of LoadedUnionType. | ||
| 1832 | pub fn setZirIndex(self: LoadedUnionType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { | ||
| 1833 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; | ||
| 1834 | const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?; | ||
| 1835 | const ptr: *TrackedInst.Index.Optional = | ||
| 1836 | @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]); | ||
| 1837 | ptr.* = new_zir_index; | ||
| 1838 | } | ||
| 1839 | |||
| 1840 | pub fn setFieldTypes(self: LoadedUnionType, ip: *const InternPool, types: []const Index) void { | ||
| 1841 | @memcpy(self.field_types.get(ip), types); | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | pub fn setFieldAligns(self: LoadedUnionType, ip: *const InternPool, aligns: []const Alignment) void { | ||
| 1845 | if (aligns.len == 0) return; | ||
| 1846 | assert(self.flagsPtr(ip).any_aligned_fields); | ||
| 1847 | @memcpy(self.field_aligns.get(ip), aligns); | ||
| 1848 | } | ||
| 1849 | }; | ||
| 1850 | |||
| 1851 | pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { | ||
| 1852 | const data = ip.items.items(.data)[@intFromEnum(index)]; | ||
| 1853 | const type_union = ip.extraDataTrail(Tag.TypeUnion, data); | ||
| 1854 | const fields_len = type_union.data.fields_len; | ||
| 1855 | |||
| 1856 | var extra_index = type_union.end; | ||
| 1857 | const captures_len = if (type_union.data.flags.any_captures) c: { | ||
| 1858 | const len = ip.extra.items[extra_index]; | ||
| 1859 | extra_index += 1; | ||
| 1860 | break :c len; | ||
| 1861 | } else 0; | ||
| 1862 | |||
| 1863 | const captures: CaptureValue.Slice = .{ | ||
| 1864 | .start = extra_index, | ||
| 1865 | .len = captures_len, | ||
| 1866 | }; | ||
| 1867 | extra_index += captures_len; | ||
| 1868 | if (type_union.data.flags.is_reified) { | ||
| 1869 | extra_index += 2; // PackedU64 | ||
| 1870 | } | ||
| 1871 | |||
| 1872 | const field_types: Index.Slice = .{ | ||
| 1873 | .start = extra_index, | ||
| 1874 | .len = fields_len, | ||
| 1875 | }; | ||
| 1876 | extra_index += fields_len; | ||
| 1877 | |||
| 1878 | const field_aligns: Alignment.Slice = if (type_union.data.flags.any_aligned_fields) a: { | ||
| 1879 | const a: Alignment.Slice = .{ | ||
| 1880 | .start = extra_index, | ||
| 1881 | .len = fields_len, | ||
| 1882 | }; | ||
| 1883 | extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable; | ||
| 1884 | break :a a; | ||
| 1885 | } else .{ .start = 0, .len = 0 }; | ||
| 1886 | |||
| 1887 | return .{ | ||
| 1888 | .extra_index = data, | ||
| 1889 | .decl = type_union.data.decl, | ||
| 1890 | .namespace = type_union.data.namespace, | ||
| 1891 | .enum_tag_ty = type_union.data.tag_ty, | ||
| 1892 | .field_types = field_types, | ||
| 1893 | .field_aligns = field_aligns, | ||
| 1894 | .zir_index = type_union.data.zir_index, | ||
| 1895 | .captures = captures, | ||
| 1896 | }; | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | pub const LoadedStructType = struct { | ||
| 1900 | /// The index of the `Tag.TypeStruct` or `Tag.TypeStructPacked` payload. | ||
| 1901 | extra_index: u32, | ||
| 1902 | /// The struct's owner Decl. `none` when the struct is `@TypeOf(.{})`. | ||
| 1903 | decl: OptionalDeclIndex, | ||
| 1904 | /// `none` when the struct has no declarations. | ||
| 1905 | namespace: OptionalNamespaceIndex, | ||
| 1906 | /// Index of the `struct_decl` or `reify` ZIR instruction. | ||
| 1907 | /// Only `none` when the struct is `@TypeOf(.{})`. | ||
| 1908 | zir_index: TrackedInst.Index.Optional, | ||
| 1909 | layout: std.builtin.Type.ContainerLayout, | ||
| 1910 | field_names: NullTerminatedString.Slice, | ||
| 1911 | field_types: Index.Slice, | ||
| 1912 | field_inits: Index.Slice, | ||
| 1913 | field_aligns: Alignment.Slice, | ||
| 1914 | runtime_order: RuntimeOrder.Slice, | ||
| 1915 | comptime_bits: ComptimeBits, | ||
| 1916 | offsets: Offsets, | ||
| 1917 | names_map: OptionalMapIndex, | ||
| 1918 | captures: CaptureValue.Slice, | ||
| 1919 | |||
| 1920 | pub const ComptimeBits = struct { | ||
| 1921 | start: u32, | ||
| 1922 | /// This is the number of u32 elements, not the number of struct fields. | ||
| 1923 | len: u32, | ||
| 1924 | |||
| 1925 | pub fn get(this: ComptimeBits, ip: *const InternPool) []u32 { | ||
| 1926 | return ip.extra.items[this.start..][0..this.len]; | ||
| 1927 | } | ||
| 1928 | |||
| 1929 | pub fn getBit(this: ComptimeBits, ip: *const InternPool, i: usize) bool { | ||
| 1930 | if (this.len == 0) return false; | ||
| 1931 | return @as(u1, @truncate(this.get(ip)[i / 32] >> @intCast(i % 32))) != 0; | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | pub fn setBit(this: ComptimeBits, ip: *const InternPool, i: usize) void { | ||
| 1935 | this.get(ip)[i / 32] |= @as(u32, 1) << @intCast(i % 32); | ||
| 1936 | } | ||
| 1937 | |||
| 1938 | pub fn clearBit(this: ComptimeBits, ip: *const InternPool, i: usize) void { | ||
| 1939 | this.get(ip)[i / 32] &= ~(@as(u32, 1) << @intCast(i % 32)); | ||
| 1940 | } | ||
| 1941 | }; | ||
| 1942 | |||
| 1943 | pub const Offsets = struct { | ||
| 1944 | start: u32, | ||
| 1945 | len: u32, | ||
| 1946 | |||
| 1947 | pub fn get(this: Offsets, ip: *const InternPool) []u32 { | ||
| 1948 | return @ptrCast(ip.extra.items[this.start..][0..this.len]); | ||
| 1949 | } | ||
| 1950 | }; | ||
| 1951 | |||
| 1952 | pub const RuntimeOrder = enum(u32) { | ||
| 1953 | /// Placeholder until layout is resolved. | ||
| 1954 | unresolved = std.math.maxInt(u32) - 0, | ||
| 1955 | /// Field not present at runtime | ||
| 1956 | omitted = std.math.maxInt(u32) - 1, | ||
| 1957 | _, | ||
| 1958 | |||
| 1959 | pub const Slice = struct { | ||
| 1960 | start: u32, | ||
| 1961 | len: u32, | ||
| 1962 | |||
| 1963 | pub fn get(slice: RuntimeOrder.Slice, ip: *const InternPool) []RuntimeOrder { | ||
| 1964 | return @ptrCast(ip.extra.items[slice.start..][0..slice.len]); | ||
| 1965 | } | ||
| 1966 | }; | ||
| 1967 | |||
| 1968 | pub fn toInt(i: RuntimeOrder) ?u32 { | ||
| 1969 | return switch (i) { | ||
| 1970 | .omitted => null, | ||
| 1971 | .unresolved => unreachable, | ||
| 1972 | else => @intFromEnum(i), | ||
| 1973 | }; | ||
| 1974 | } | ||
| 1975 | }; | ||
| 1976 | |||
| 1977 | /// Look up field index based on field name. | ||
| 1978 | pub fn nameIndex(self: LoadedStructType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | ||
| 1979 | const names_map = self.names_map.unwrap() orelse { | ||
| 1980 | const i = name.toUnsigned(ip) orelse return null; | ||
| 1981 | if (i >= self.field_types.len) return null; | ||
| 1982 | return i; | ||
| 1983 | }; | ||
| 1984 | const map = &ip.maps.items[@intFromEnum(names_map)]; | ||
| 1985 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) }; | ||
| 1986 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | ||
| 1987 | return @intCast(field_index); | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | /// Returns the already-existing field with the same name, if any. | ||
| 1991 | pub fn addFieldName( | ||
| 1992 | self: @This(), | ||
| 1993 | ip: *InternPool, | ||
| 1994 | name: NullTerminatedString, | ||
| 1995 | ) ?u32 { | ||
| 1996 | return ip.addFieldName(self.names_map.unwrap().?, self.field_names.start, name); | ||
| 1997 | } | ||
| 1998 | |||
| 1999 | pub fn fieldAlign(s: @This(), ip: *const InternPool, i: usize) Alignment { | ||
| 2000 | if (s.field_aligns.len == 0) return .none; | ||
| 2001 | return s.field_aligns.get(ip)[i]; | ||
| 2002 | } | ||
| 2003 | |||
| 2004 | pub fn fieldInit(s: @This(), ip: *const InternPool, i: usize) Index { | ||
| 2005 | if (s.field_inits.len == 0) return .none; | ||
| 2006 | assert(s.haveFieldInits(ip)); | ||
| 2007 | return s.field_inits.get(ip)[i]; | ||
| 2008 | } | ||
| 2009 | |||
| 2010 | /// Returns `none` in the case the struct is a tuple. | ||
| 2011 | pub fn fieldName(s: @This(), ip: *const InternPool, i: usize) OptionalNullTerminatedString { | ||
| 2012 | if (s.field_names.len == 0) return .none; | ||
| 2013 | return s.field_names.get(ip)[i].toOptional(); | ||
| 2014 | } | ||
| 2015 | |||
| 2016 | pub fn fieldIsComptime(s: @This(), ip: *const InternPool, i: usize) bool { | ||
| 2017 | return s.comptime_bits.getBit(ip, i); | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | pub fn setFieldComptime(s: @This(), ip: *InternPool, i: usize) void { | ||
| 2021 | s.comptime_bits.setBit(ip, i); | ||
| 2022 | } | ||
| 2023 | |||
| 2024 | /// Reads the non-opv flag calculated during AstGen. Used to short-circuit more | ||
| 2025 | /// complicated logic. | ||
| 2026 | pub fn knownNonOpv(s: @This(), ip: *InternPool) bool { | ||
| 2027 | return switch (s.layout) { | ||
| 2028 | .Packed => false, | ||
| 2029 | .Auto, .Extern => s.flagsPtr(ip).known_non_opv, | ||
| 2030 | }; | ||
| 2031 | } | ||
| 2032 | |||
| 2033 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 2034 | /// Asserts the struct is not packed. | ||
| 2035 | pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStruct.Flags { | ||
| 2036 | assert(self.layout != .Packed); | ||
| 2037 | const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?; | ||
| 2038 | return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]); | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | /// The returned pointer expires with any addition to the `InternPool`. | ||
| 2042 | /// Asserts that the struct is packed. | ||
| 2043 | pub fn packedFlagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStructPacked.Flags { | ||
| 2044 | assert(self.layout == .Packed); | ||
| 2045 | const flags_field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?; | ||
| 2046 | return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]); | ||
| 2047 | } | ||
| 2048 | |||
| 2049 | pub fn assumeRuntimeBitsIfFieldTypesWip(s: @This(), ip: *InternPool) bool { | ||
| 2050 | if (s.layout == .Packed) return false; | ||
| 2051 | const flags_ptr = s.flagsPtr(ip); | ||
| 2052 | if (flags_ptr.field_types_wip) { | ||
| 2053 | flags_ptr.assumed_runtime_bits = true; | ||
| 2054 | return true; | ||
| 2055 | } | ||
| 2056 | return false; | ||
| 2057 | } | ||
| 2058 | |||
| 2059 | pub fn setTypesWip(s: @This(), ip: *InternPool) bool { | ||
| 2060 | if (s.layout == .Packed) return false; | ||
| 2061 | const flags_ptr = s.flagsPtr(ip); | ||
| 2062 | if (flags_ptr.field_types_wip) return true; | ||
| 2063 | flags_ptr.field_types_wip = true; | ||
| 2064 | return false; | ||
| 2065 | } | ||
| 2066 | |||
| 2067 | pub fn clearTypesWip(s: @This(), ip: *InternPool) void { | ||
| 2068 | if (s.layout == .Packed) return; | ||
| 2069 | s.flagsPtr(ip).field_types_wip = false; | ||
| 2070 | } | ||
| 2071 | |||
| 2072 | pub fn setLayoutWip(s: @This(), ip: *InternPool) bool { | ||
| 2073 | if (s.layout == .Packed) return false; | ||
| 2074 | const flags_ptr = s.flagsPtr(ip); | ||
| 2075 | if (flags_ptr.layout_wip) return true; | ||
| 2076 | flags_ptr.layout_wip = true; | ||
| 2077 | return false; | ||
| 2078 | } | ||
| 2079 | |||
| 2080 | pub fn clearLayoutWip(s: @This(), ip: *InternPool) void { | ||
| 2081 | if (s.layout == .Packed) return; | ||
| 2082 | s.flagsPtr(ip).layout_wip = false; | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | pub fn setAlignmentWip(s: @This(), ip: *InternPool) bool { | ||
| 2086 | if (s.layout == .Packed) return false; | ||
| 2087 | const flags_ptr = s.flagsPtr(ip); | ||
| 2088 | if (flags_ptr.alignment_wip) return true; | ||
| 2089 | flags_ptr.alignment_wip = true; | ||
| 2090 | return false; | ||
| 2091 | } | ||
| 2092 | |||
| 2093 | pub fn clearAlignmentWip(s: @This(), ip: *InternPool) void { | ||
| 2094 | if (s.layout == .Packed) return; | ||
| 2095 | s.flagsPtr(ip).alignment_wip = false; | ||
| 2096 | } | ||
| 2167 | 2097 | ||
| 2168 | pub fn haveFieldTypes(status: Status) bool { | 2098 | pub fn setInitsWip(s: @This(), ip: *InternPool) bool { |
| 2169 | return switch (status) { | 2099 | switch (s.layout) { |
| 2170 | .none, | 2100 | .Packed => { |
| 2171 | .field_types_wip, | 2101 | const flag = &s.packedFlagsPtr(ip).field_inits_wip; |
| 2172 | => false, | 2102 | if (flag.*) return true; |
| 2173 | .have_field_types, | 2103 | flag.* = true; |
| 2174 | .layout_wip, | 2104 | return false; |
| 2175 | .have_layout, | 2105 | }, |
| 2176 | .fully_resolved_wip, | 2106 | .Auto, .Extern => { |
| 2177 | .fully_resolved, | 2107 | const flag = &s.flagsPtr(ip).field_inits_wip; |
| 2178 | => true, | 2108 | if (flag.*) return true; |
| 2179 | }; | 2109 | flag.* = true; |
| 2110 | return false; | ||
| 2111 | }, | ||
| 2180 | } | 2112 | } |
| 2113 | } | ||
| 2181 | 2114 | ||
| 2182 | pub fn haveLayout(status: Status) bool { | 2115 | pub fn clearInitsWip(s: @This(), ip: *InternPool) void { |
| 2183 | return switch (status) { | 2116 | switch (s.layout) { |
| 2184 | .none, | 2117 | .Packed => s.packedFlagsPtr(ip).field_inits_wip = false, |
| 2185 | .field_types_wip, | 2118 | .Auto, .Extern => s.flagsPtr(ip).field_inits_wip = false, |
| 2186 | .have_field_types, | ||
| 2187 | .layout_wip, | ||
| 2188 | => false, | ||
| 2189 | .have_layout, | ||
| 2190 | .fully_resolved_wip, | ||
| 2191 | .fully_resolved, | ||
| 2192 | => true, | ||
| 2193 | }; | ||
| 2194 | } | 2119 | } |
| 2195 | }; | 2120 | } |
| 2121 | |||
| 2122 | pub fn setFullyResolved(s: @This(), ip: *InternPool) bool { | ||
| 2123 | if (s.layout == .Packed) return true; | ||
| 2124 | const flags_ptr = s.flagsPtr(ip); | ||
| 2125 | if (flags_ptr.fully_resolved) return true; | ||
| 2126 | flags_ptr.fully_resolved = true; | ||
| 2127 | return false; | ||
| 2128 | } | ||
| 2129 | |||
| 2130 | pub fn clearFullyResolved(s: @This(), ip: *InternPool) void { | ||
| 2131 | s.flagsPtr(ip).fully_resolved = false; | ||
| 2132 | } | ||
| 2196 | 2133 | ||
| 2197 | /// The returned pointer expires with any addition to the `InternPool`. | 2134 | /// The returned pointer expires with any addition to the `InternPool`. |
| 2198 | pub fn flagsPtr(self: UnionType, ip: *const InternPool) *Tag.TypeUnion.Flags { | 2135 | /// Asserts the struct is not packed. |
| 2199 | return @ptrCast(&ip.extra.items[self.flags_index]); | 2136 | pub fn size(self: @This(), ip: *InternPool) *u32 { |
| 2137 | assert(self.layout != .Packed); | ||
| 2138 | const size_field_index = std.meta.fieldIndex(Tag.TypeStruct, "size").?; | ||
| 2139 | return @ptrCast(&ip.extra.items[self.extra_index + size_field_index]); | ||
| 2200 | } | 2140 | } |
| 2201 | 2141 | ||
| 2202 | /// Look up field index based on field name. | 2142 | /// The backing integer type of the packed struct. Whether zig chooses |
| 2203 | pub fn nameIndex(self: UnionType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | 2143 | /// this type or the user specifies it, it is stored here. This will be |
| 2204 | const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)]; | 2144 | /// set to `none` until the layout is resolved. |
| 2205 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) }; | 2145 | /// Asserts the struct is packed. |
| 2206 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | 2146 | pub fn backingIntType(s: @This(), ip: *const InternPool) *Index { |
| 2207 | return @intCast(field_index); | 2147 | assert(s.layout == .Packed); |
| 2148 | const field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_ty").?; | ||
| 2149 | return @ptrCast(&ip.extra.items[s.extra_index + field_index]); | ||
| 2208 | } | 2150 | } |
| 2209 | 2151 | ||
| 2210 | pub fn hasTag(self: UnionType, ip: *const InternPool) bool { | 2152 | /// Asserts the struct is not packed. |
| 2211 | return self.flagsPtr(ip).runtime_tag.hasTag(); | 2153 | pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { |
| 2154 | assert(s.layout != .Packed); | ||
| 2155 | const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; | ||
| 2156 | ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); | ||
| 2212 | } | 2157 | } |
| 2213 | 2158 | ||
| 2214 | pub fn haveFieldTypes(self: UnionType, ip: *const InternPool) bool { | 2159 | pub fn haveFieldTypes(s: @This(), ip: *const InternPool) bool { |
| 2215 | return self.flagsPtr(ip).status.haveFieldTypes(); | 2160 | const types = s.field_types.get(ip); |
| 2161 | return types.len == 0 or types[0] != .none; | ||
| 2216 | } | 2162 | } |
| 2217 | 2163 | ||
| 2218 | pub fn haveLayout(self: UnionType, ip: *const InternPool) bool { | 2164 | pub fn haveFieldInits(s: @This(), ip: *const InternPool) bool { |
| 2219 | return self.flagsPtr(ip).status.haveLayout(); | 2165 | return switch (s.layout) { |
| 2166 | .Packed => s.packedFlagsPtr(ip).inits_resolved, | ||
| 2167 | .Auto, .Extern => s.flagsPtr(ip).inits_resolved, | ||
| 2168 | }; | ||
| 2220 | } | 2169 | } |
| 2221 | 2170 | ||
| 2222 | pub fn getLayout(self: UnionType, ip: *const InternPool) std.builtin.Type.ContainerLayout { | 2171 | pub fn setHaveFieldInits(s: @This(), ip: *InternPool) void { |
| 2223 | return self.flagsPtr(ip).layout; | 2172 | switch (s.layout) { |
| 2173 | .Packed => s.packedFlagsPtr(ip).inits_resolved = true, | ||
| 2174 | .Auto, .Extern => s.flagsPtr(ip).inits_resolved = true, | ||
| 2175 | } | ||
| 2224 | } | 2176 | } |
| 2225 | 2177 | ||
| 2226 | pub fn fieldAlign(self: UnionType, ip: *const InternPool, field_index: u32) Alignment { | 2178 | pub fn haveLayout(s: @This(), ip: *InternPool) bool { |
| 2227 | if (self.field_aligns.len == 0) return .none; | 2179 | return switch (s.layout) { |
| 2228 | return self.field_aligns.get(ip)[field_index]; | 2180 | .Packed => s.backingIntType(ip).* != .none, |
| 2181 | .Auto, .Extern => s.flagsPtr(ip).layout_resolved, | ||
| 2182 | }; | ||
| 2229 | } | 2183 | } |
| 2230 | 2184 | ||
| 2231 | /// This does not mutate the field of UnionType. | 2185 | pub fn isTuple(s: @This(), ip: *InternPool) bool { |
| 2232 | pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { | 2186 | return s.layout != .Packed and s.flagsPtr(ip).is_tuple; |
| 2233 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; | 2187 | } |
| 2234 | const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?; | 2188 | |
| 2235 | const ptr: *TrackedInst.Index.Optional = | 2189 | pub fn hasReorderedFields(s: @This()) bool { |
| 2236 | @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]); | 2190 | return s.layout == .Auto; |
| 2237 | ptr.* = new_zir_index; | 2191 | } |
| 2192 | |||
| 2193 | pub const RuntimeOrderIterator = struct { | ||
| 2194 | ip: *InternPool, | ||
| 2195 | field_index: u32, | ||
| 2196 | struct_type: InternPool.LoadedStructType, | ||
| 2197 | |||
| 2198 | pub fn next(it: *@This()) ?u32 { | ||
| 2199 | var i = it.field_index; | ||
| 2200 | |||
| 2201 | if (i >= it.struct_type.field_types.len) | ||
| 2202 | return null; | ||
| 2203 | |||
| 2204 | if (it.struct_type.hasReorderedFields()) { | ||
| 2205 | it.field_index += 1; | ||
| 2206 | return it.struct_type.runtime_order.get(it.ip)[i].toInt(); | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | while (it.struct_type.fieldIsComptime(it.ip, i)) { | ||
| 2210 | i += 1; | ||
| 2211 | if (i >= it.struct_type.field_types.len) | ||
| 2212 | return null; | ||
| 2213 | } | ||
| 2214 | |||
| 2215 | it.field_index = i + 1; | ||
| 2216 | return i; | ||
| 2217 | } | ||
| 2218 | }; | ||
| 2219 | |||
| 2220 | /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. | ||
| 2221 | /// May or may not include zero-bit fields. | ||
| 2222 | /// Asserts the struct is not packed. | ||
| 2223 | pub fn iterateRuntimeOrder(s: @This(), ip: *InternPool) RuntimeOrderIterator { | ||
| 2224 | assert(s.layout != .Packed); | ||
| 2225 | return .{ | ||
| 2226 | .ip = ip, | ||
| 2227 | .field_index = 0, | ||
| 2228 | .struct_type = s, | ||
| 2229 | }; | ||
| 2238 | } | 2230 | } |
| 2239 | }; | 2231 | }; |
| 2240 | 2232 | ||
| 2241 | /// Fetch all the interesting fields of a union type into a convenient data | 2233 | pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 2242 | /// structure. | 2234 | const item = ip.items.get(@intFromEnum(index)); |
| 2243 | /// This asserts that the union's enum tag type has been resolved. | 2235 | switch (item.tag) { |
| 2244 | pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType { | 2236 | .type_struct => { |
| 2245 | const type_union = ip.extraDataTrail(Tag.TypeUnion, key.extra_index); | 2237 | if (item.data == 0) return .{ |
| 2246 | const enum_ty = type_union.data.tag_ty; | 2238 | .extra_index = 0, |
| 2247 | const enum_info = ip.indexToKey(enum_ty).enum_type; | 2239 | .decl = .none, |
| 2248 | const fields_len: u32 = @intCast(enum_info.names.len); | 2240 | .namespace = .none, |
| 2241 | .zir_index = .none, | ||
| 2242 | .layout = .Auto, | ||
| 2243 | .field_names = .{ .start = 0, .len = 0 }, | ||
| 2244 | .field_types = .{ .start = 0, .len = 0 }, | ||
| 2245 | .field_inits = .{ .start = 0, .len = 0 }, | ||
| 2246 | .field_aligns = .{ .start = 0, .len = 0 }, | ||
| 2247 | .runtime_order = .{ .start = 0, .len = 0 }, | ||
| 2248 | .comptime_bits = .{ .start = 0, .len = 0 }, | ||
| 2249 | .offsets = .{ .start = 0, .len = 0 }, | ||
| 2250 | .names_map = .none, | ||
| 2251 | .captures = .{ .start = 0, .len = 0 }, | ||
| 2252 | }; | ||
| 2253 | const extra = ip.extraDataTrail(Tag.TypeStruct, item.data); | ||
| 2254 | const fields_len = extra.data.fields_len; | ||
| 2255 | var extra_index = extra.end; | ||
| 2256 | const captures_len = if (extra.data.flags.any_captures) c: { | ||
| 2257 | const len = ip.extra.items[extra_index]; | ||
| 2258 | extra_index += 1; | ||
| 2259 | break :c len; | ||
| 2260 | } else 0; | ||
| 2261 | const captures: CaptureValue.Slice = .{ | ||
| 2262 | .start = extra_index, | ||
| 2263 | .len = captures_len, | ||
| 2264 | }; | ||
| 2265 | extra_index += captures_len; | ||
| 2266 | if (extra.data.flags.is_reified) { | ||
| 2267 | extra_index += 2; // PackedU64 | ||
| 2268 | } | ||
| 2269 | const field_types: Index.Slice = .{ | ||
| 2270 | .start = extra_index, | ||
| 2271 | .len = fields_len, | ||
| 2272 | }; | ||
| 2273 | extra_index += fields_len; | ||
| 2274 | const names_map: OptionalMapIndex, const names: NullTerminatedString.Slice = if (!extra.data.flags.is_tuple) n: { | ||
| 2275 | const names_map: OptionalMapIndex = @enumFromInt(ip.extra.items[extra_index]); | ||
| 2276 | extra_index += 1; | ||
| 2277 | const names: NullTerminatedString.Slice = .{ .start = extra_index, .len = fields_len }; | ||
| 2278 | extra_index += fields_len; | ||
| 2279 | break :n .{ names_map, names }; | ||
| 2280 | } else .{ .none, .{ .start = 0, .len = 0 } }; | ||
| 2281 | const inits: Index.Slice = if (extra.data.flags.any_default_inits) i: { | ||
| 2282 | const inits: Index.Slice = .{ .start = extra_index, .len = fields_len }; | ||
| 2283 | extra_index += fields_len; | ||
| 2284 | break :i inits; | ||
| 2285 | } else .{ .start = 0, .len = 0 }; | ||
| 2286 | const namespace: OptionalNamespaceIndex = if (extra.data.flags.has_namespace) n: { | ||
| 2287 | const n: NamespaceIndex = @enumFromInt(ip.extra.items[extra_index]); | ||
| 2288 | extra_index += 1; | ||
| 2289 | break :n n.toOptional(); | ||
| 2290 | } else .none; | ||
| 2291 | const aligns: Alignment.Slice = if (extra.data.flags.any_aligned_fields) a: { | ||
| 2292 | const a: Alignment.Slice = .{ .start = extra_index, .len = fields_len }; | ||
| 2293 | extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable; | ||
| 2294 | break :a a; | ||
| 2295 | } else .{ .start = 0, .len = 0 }; | ||
| 2296 | const comptime_bits: LoadedStructType.ComptimeBits = if (extra.data.flags.any_comptime_fields) c: { | ||
| 2297 | const len = std.math.divCeil(u32, fields_len, 32) catch unreachable; | ||
| 2298 | const c: LoadedStructType.ComptimeBits = .{ .start = extra_index, .len = len }; | ||
| 2299 | extra_index += len; | ||
| 2300 | break :c c; | ||
| 2301 | } else .{ .start = 0, .len = 0 }; | ||
| 2302 | const runtime_order: LoadedStructType.RuntimeOrder.Slice = if (!extra.data.flags.is_extern) ro: { | ||
| 2303 | const ro: LoadedStructType.RuntimeOrder.Slice = .{ .start = extra_index, .len = fields_len }; | ||
| 2304 | extra_index += fields_len; | ||
| 2305 | break :ro ro; | ||
| 2306 | } else .{ .start = 0, .len = 0 }; | ||
| 2307 | const offsets: LoadedStructType.Offsets = o: { | ||
| 2308 | const o: LoadedStructType.Offsets = .{ .start = extra_index, .len = fields_len }; | ||
| 2309 | extra_index += fields_len; | ||
| 2310 | break :o o; | ||
| 2311 | }; | ||
| 2312 | return .{ | ||
| 2313 | .extra_index = item.data, | ||
| 2314 | .decl = extra.data.decl.toOptional(), | ||
| 2315 | .namespace = namespace, | ||
| 2316 | .zir_index = extra.data.zir_index.toOptional(), | ||
| 2317 | .layout = if (extra.data.flags.is_extern) .Extern else .Auto, | ||
| 2318 | .field_names = names, | ||
| 2319 | .field_types = field_types, | ||
| 2320 | .field_inits = inits, | ||
| 2321 | .field_aligns = aligns, | ||
| 2322 | .runtime_order = runtime_order, | ||
| 2323 | .comptime_bits = comptime_bits, | ||
| 2324 | .offsets = offsets, | ||
| 2325 | .names_map = names_map, | ||
| 2326 | .captures = captures, | ||
| 2327 | }; | ||
| 2328 | }, | ||
| 2329 | .type_struct_packed, .type_struct_packed_inits => { | ||
| 2330 | const extra = ip.extraDataTrail(Tag.TypeStructPacked, item.data); | ||
| 2331 | const has_inits = item.tag == .type_struct_packed_inits; | ||
| 2332 | const fields_len = extra.data.fields_len; | ||
| 2333 | var extra_index = extra.end; | ||
| 2334 | const captures_len = if (extra.data.flags.any_captures) c: { | ||
| 2335 | const len = ip.extra.items[extra_index]; | ||
| 2336 | extra_index += 1; | ||
| 2337 | break :c len; | ||
| 2338 | } else 0; | ||
| 2339 | const captures: CaptureValue.Slice = .{ | ||
| 2340 | .start = extra_index, | ||
| 2341 | .len = captures_len, | ||
| 2342 | }; | ||
| 2343 | extra_index += captures_len; | ||
| 2344 | if (extra.data.flags.is_reified) { | ||
| 2345 | extra_index += 2; // PackedU64 | ||
| 2346 | } | ||
| 2347 | const field_types: Index.Slice = .{ | ||
| 2348 | .start = extra_index, | ||
| 2349 | .len = fields_len, | ||
| 2350 | }; | ||
| 2351 | extra_index += fields_len; | ||
| 2352 | const field_names: NullTerminatedString.Slice = .{ | ||
| 2353 | .start = extra_index, | ||
| 2354 | .len = fields_len, | ||
| 2355 | }; | ||
| 2356 | extra_index += fields_len; | ||
| 2357 | const field_inits: Index.Slice = if (has_inits) inits: { | ||
| 2358 | const i: Index.Slice = .{ | ||
| 2359 | .start = extra_index, | ||
| 2360 | .len = fields_len, | ||
| 2361 | }; | ||
| 2362 | extra_index += fields_len; | ||
| 2363 | break :inits i; | ||
| 2364 | } else .{ .start = 0, .len = 0 }; | ||
| 2365 | return .{ | ||
| 2366 | .extra_index = item.data, | ||
| 2367 | .decl = extra.data.decl.toOptional(), | ||
| 2368 | .namespace = extra.data.namespace, | ||
| 2369 | .zir_index = extra.data.zir_index.toOptional(), | ||
| 2370 | .layout = .Packed, | ||
| 2371 | .field_names = field_names, | ||
| 2372 | .field_types = field_types, | ||
| 2373 | .field_inits = field_inits, | ||
| 2374 | .field_aligns = .{ .start = 0, .len = 0 }, | ||
| 2375 | .runtime_order = .{ .start = 0, .len = 0 }, | ||
| 2376 | .comptime_bits = .{ .start = 0, .len = 0 }, | ||
| 2377 | .offsets = .{ .start = 0, .len = 0 }, | ||
| 2378 | .names_map = extra.data.names_map.toOptional(), | ||
| 2379 | .captures = captures, | ||
| 2380 | }; | ||
| 2381 | }, | ||
| 2382 | else => unreachable, | ||
| 2383 | } | ||
| 2384 | } | ||
| 2385 | |||
| 2386 | const LoadedEnumType = struct { | ||
| 2387 | /// The Decl that corresponds to the enum itself. | ||
| 2388 | decl: DeclIndex, | ||
| 2389 | /// Represents the declarations inside this enum. | ||
| 2390 | namespace: OptionalNamespaceIndex, | ||
| 2391 | /// An integer type which is used for the numerical value of the enum. | ||
| 2392 | /// This field is present regardless of whether the enum has an | ||
| 2393 | /// explicitly provided tag type or auto-numbered. | ||
| 2394 | tag_ty: Index, | ||
| 2395 | /// Set of field names in declaration order. | ||
| 2396 | names: NullTerminatedString.Slice, | ||
| 2397 | /// Maps integer tag value to field index. | ||
| 2398 | /// Entries are in declaration order, same as `fields`. | ||
| 2399 | /// If this is empty, it means the enum tags are auto-numbered. | ||
| 2400 | values: Index.Slice, | ||
| 2401 | tag_mode: TagMode, | ||
| 2402 | names_map: MapIndex, | ||
| 2403 | /// This is guaranteed to not be `.none` if explicit values are provided. | ||
| 2404 | values_map: OptionalMapIndex, | ||
| 2405 | /// This is `none` only if this is a generated tag type. | ||
| 2406 | zir_index: TrackedInst.Index.Optional, | ||
| 2407 | captures: CaptureValue.Slice, | ||
| 2408 | |||
| 2409 | pub const TagMode = enum { | ||
| 2410 | /// The integer tag type was auto-numbered by zig. | ||
| 2411 | auto, | ||
| 2412 | /// The integer tag type was provided by the enum declaration, and the enum | ||
| 2413 | /// is exhaustive. | ||
| 2414 | explicit, | ||
| 2415 | /// The integer tag type was provided by the enum declaration, and the enum | ||
| 2416 | /// is non-exhaustive. | ||
| 2417 | nonexhaustive, | ||
| 2418 | }; | ||
| 2419 | |||
| 2420 | /// Look up field index based on field name. | ||
| 2421 | pub fn nameIndex(self: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | ||
| 2422 | const map = &ip.maps.items[@intFromEnum(self.names_map)]; | ||
| 2423 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) }; | ||
| 2424 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | ||
| 2425 | return @intCast(field_index); | ||
| 2426 | } | ||
| 2427 | |||
| 2428 | /// Look up field index based on tag value. | ||
| 2429 | /// Asserts that `values_map` is not `none`. | ||
| 2430 | /// This function returns `null` when `tag_val` does not have the | ||
| 2431 | /// integer tag type of the enum. | ||
| 2432 | pub fn tagValueIndex(self: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 { | ||
| 2433 | assert(tag_val != .none); | ||
| 2434 | // TODO: we should probably decide a single interface for this function, but currently | ||
| 2435 | // it's being called with both tag values and underlying ints. Fix this! | ||
| 2436 | const int_tag_val = switch (ip.indexToKey(tag_val)) { | ||
| 2437 | .enum_tag => |enum_tag| enum_tag.int, | ||
| 2438 | .int => tag_val, | ||
| 2439 | else => unreachable, | ||
| 2440 | }; | ||
| 2441 | if (self.values_map.unwrap()) |values_map| { | ||
| 2442 | const map = &ip.maps.items[@intFromEnum(values_map)]; | ||
| 2443 | const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) }; | ||
| 2444 | const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null; | ||
| 2445 | return @intCast(field_index); | ||
| 2446 | } | ||
| 2447 | // Auto-numbered enum. Convert `int_tag_val` to field index. | ||
| 2448 | const field_index = switch (ip.indexToKey(int_tag_val).int.storage) { | ||
| 2449 | inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null, | ||
| 2450 | .big_int => |x| x.to(u32) catch return null, | ||
| 2451 | .lazy_align, .lazy_size => unreachable, | ||
| 2452 | }; | ||
| 2453 | return if (field_index < self.names.len) field_index else null; | ||
| 2454 | } | ||
| 2455 | }; | ||
| 2249 | 2456 | ||
| 2457 | pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { | ||
| 2458 | const item = ip.items.get(@intFromEnum(index)); | ||
| 2459 | const tag_mode: LoadedEnumType.TagMode = switch (item.tag) { | ||
| 2460 | .type_enum_auto => { | ||
| 2461 | const extra = ip.extraDataTrail(EnumAuto, item.data); | ||
| 2462 | var extra_index: u32 = @intCast(extra.end); | ||
| 2463 | if (extra.data.zir_index == .none) { | ||
| 2464 | extra_index += 1; // owner_union | ||
| 2465 | } | ||
| 2466 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { | ||
| 2467 | extra_index += 2; // type_hash: PackedU64 | ||
| 2468 | break :c 0; | ||
| 2469 | } else extra.data.captures_len; | ||
| 2470 | return .{ | ||
| 2471 | .decl = extra.data.decl, | ||
| 2472 | .namespace = extra.data.namespace, | ||
| 2473 | .tag_ty = extra.data.int_tag_type, | ||
| 2474 | .names = .{ | ||
| 2475 | .start = extra_index + captures_len, | ||
| 2476 | .len = extra.data.fields_len, | ||
| 2477 | }, | ||
| 2478 | .values = .{ .start = 0, .len = 0 }, | ||
| 2479 | .tag_mode = .auto, | ||
| 2480 | .names_map = extra.data.names_map, | ||
| 2481 | .values_map = .none, | ||
| 2482 | .zir_index = extra.data.zir_index, | ||
| 2483 | .captures = .{ | ||
| 2484 | .start = extra_index, | ||
| 2485 | .len = captures_len, | ||
| 2486 | }, | ||
| 2487 | }; | ||
| 2488 | }, | ||
| 2489 | .type_enum_explicit => .explicit, | ||
| 2490 | .type_enum_nonexhaustive => .nonexhaustive, | ||
| 2491 | else => unreachable, | ||
| 2492 | }; | ||
| 2493 | const extra = ip.extraDataTrail(EnumExplicit, item.data); | ||
| 2494 | var extra_index: u32 = @intCast(extra.end); | ||
| 2495 | if (extra.data.zir_index == .none) { | ||
| 2496 | extra_index += 1; // owner_union | ||
| 2497 | } | ||
| 2498 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { | ||
| 2499 | extra_index += 2; // type_hash: PackedU64 | ||
| 2500 | break :c 0; | ||
| 2501 | } else extra.data.captures_len; | ||
| 2250 | return .{ | 2502 | return .{ |
| 2251 | .decl = type_union.data.decl, | 2503 | .decl = extra.data.decl, |
| 2252 | .namespace = type_union.data.namespace, | 2504 | .namespace = extra.data.namespace, |
| 2253 | .enum_tag_ty = enum_ty, | 2505 | .tag_ty = extra.data.int_tag_type, |
| 2254 | .int_tag_ty = enum_info.tag_ty, | 2506 | .names = .{ |
| 2255 | .size = type_union.data.size, | 2507 | .start = extra_index + captures_len, |
| 2256 | .padding = type_union.data.padding, | 2508 | .len = extra.data.fields_len, |
| 2257 | .field_names = enum_info.names, | ||
| 2258 | .names_map = enum_info.names_map, | ||
| 2259 | .field_types = .{ | ||
| 2260 | .start = type_union.end, | ||
| 2261 | .len = fields_len, | ||
| 2262 | }, | 2509 | }, |
| 2263 | .field_aligns = .{ | 2510 | .values = .{ |
| 2264 | .start = type_union.end + fields_len, | 2511 | .start = extra_index + captures_len + extra.data.fields_len, |
| 2265 | .len = if (type_union.data.flags.any_aligned_fields) fields_len else 0, | 2512 | .len = if (extra.data.values_map != .none) extra.data.fields_len else 0, |
| 2513 | }, | ||
| 2514 | .tag_mode = tag_mode, | ||
| 2515 | .names_map = extra.data.names_map, | ||
| 2516 | .values_map = extra.data.values_map, | ||
| 2517 | .zir_index = extra.data.zir_index, | ||
| 2518 | .captures = .{ | ||
| 2519 | .start = extra_index, | ||
| 2520 | .len = captures_len, | ||
| 2521 | }, | ||
| 2522 | }; | ||
| 2523 | } | ||
| 2524 | |||
| 2525 | /// Note that this type doubles as the payload for `Tag.type_opaque`. | ||
| 2526 | pub const LoadedOpaqueType = struct { | ||
| 2527 | /// The opaque's owner Decl. | ||
| 2528 | decl: DeclIndex, | ||
| 2529 | /// Contains the declarations inside this opaque. | ||
| 2530 | namespace: OptionalNamespaceIndex, | ||
| 2531 | /// Index of the `opaque_decl` or `reify` instruction. | ||
| 2532 | zir_index: TrackedInst.Index, | ||
| 2533 | captures: CaptureValue.Slice, | ||
| 2534 | }; | ||
| 2535 | |||
| 2536 | pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType { | ||
| 2537 | assert(ip.items.items(.tag)[@intFromEnum(index)] == .type_opaque); | ||
| 2538 | const extra_index = ip.items.items(.data)[@intFromEnum(index)]; | ||
| 2539 | const extra = ip.extraDataTrail(Tag.TypeOpaque, extra_index); | ||
| 2540 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) | ||
| 2541 | 0 | ||
| 2542 | else | ||
| 2543 | extra.data.captures_len; | ||
| 2544 | return .{ | ||
| 2545 | .decl = extra.data.decl, | ||
| 2546 | .namespace = extra.data.namespace, | ||
| 2547 | .zir_index = extra.data.zir_index, | ||
| 2548 | .captures = .{ | ||
| 2549 | .start = extra.end, | ||
| 2550 | .len = captures_len, | ||
| 2266 | }, | 2551 | }, |
| 2267 | .zir_index = type_union.data.zir_index, | ||
| 2268 | .flags_index = key.extra_index + std.meta.fieldIndex(Tag.TypeUnion, "flags").?, | ||
| 2269 | }; | 2552 | }; |
| 2270 | } | 2553 | } |
| 2271 | 2554 | ||
| ... | @@ -2457,6 +2740,7 @@ pub const Index = enum(u32) { | ... | @@ -2457,6 +2740,7 @@ pub const Index = enum(u32) { |
| 2457 | }, | 2740 | }, |
| 2458 | }; | 2741 | }; |
| 2459 | 2742 | ||
| 2743 | removed: void, | ||
| 2460 | type_int_signed: struct { data: u32 }, | 2744 | type_int_signed: struct { data: u32 }, |
| 2461 | type_int_unsigned: struct { data: u32 }, | 2745 | type_int_unsigned: struct { data: u32 }, |
| 2462 | type_array_big: struct { data: *Array }, | 2746 | type_array_big: struct { data: *Array }, |
| ... | @@ -2484,9 +2768,8 @@ pub const Index = enum(u32) { | ... | @@ -2484,9 +2768,8 @@ pub const Index = enum(u32) { |
| 2484 | type_enum_explicit: DataIsExtraIndexOfEnumExplicit, | 2768 | type_enum_explicit: DataIsExtraIndexOfEnumExplicit, |
| 2485 | type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit, | 2769 | type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit, |
| 2486 | simple_type: struct { data: SimpleType }, | 2770 | simple_type: struct { data: SimpleType }, |
| 2487 | type_opaque: struct { data: *Key.OpaqueType }, | 2771 | type_opaque: struct { data: *Tag.TypeOpaque }, |
| 2488 | type_struct: struct { data: *Tag.TypeStruct }, | 2772 | type_struct: struct { data: *Tag.TypeStruct }, |
| 2489 | type_struct_ns: struct { data: NamespaceIndex }, | ||
| 2490 | type_struct_anon: DataIsExtraIndexOfTypeStructAnon, | 2773 | type_struct_anon: DataIsExtraIndexOfTypeStructAnon, |
| 2491 | type_struct_packed: struct { data: *Tag.TypeStructPacked }, | 2774 | type_struct_packed: struct { data: *Tag.TypeStructPacked }, |
| 2492 | type_struct_packed_inits: struct { data: *Tag.TypeStructPacked }, | 2775 | type_struct_packed_inits: struct { data: *Tag.TypeStructPacked }, |
| ... | @@ -2865,6 +3148,12 @@ comptime { | ... | @@ -2865,6 +3148,12 @@ comptime { |
| 2865 | } | 3148 | } |
| 2866 | 3149 | ||
| 2867 | pub const Tag = enum(u8) { | 3150 | pub const Tag = enum(u8) { |
| 3151 | /// This special tag represents a value which was removed from this pool via | ||
| 3152 | /// `InternPool.remove`. The item remains allocated to preserve indices, but | ||
| 3153 | /// lookups will consider it not equal to any other item, and all queries | ||
| 3154 | /// assert not this tag. `data` is unused. | ||
| 3155 | removed, | ||
| 3156 | |||
| 2868 | /// An integer type. | 3157 | /// An integer type. |
| 2869 | /// data is number of bits | 3158 | /// data is number of bits |
| 2870 | type_int_signed, | 3159 | type_int_signed, |
| ... | @@ -2920,15 +3209,12 @@ pub const Tag = enum(u8) { | ... | @@ -2920,15 +3209,12 @@ pub const Tag = enum(u8) { |
| 2920 | /// data is SimpleType enum value. | 3209 | /// data is SimpleType enum value. |
| 2921 | simple_type, | 3210 | simple_type, |
| 2922 | /// An opaque type. | 3211 | /// An opaque type. |
| 2923 | /// data is index of Key.OpaqueType in extra. | 3212 | /// data is index of Tag.TypeOpaque in extra. |
| 2924 | type_opaque, | 3213 | type_opaque, |
| 2925 | /// A non-packed struct type. | 3214 | /// A non-packed struct type. |
| 2926 | /// data is 0 or extra index of `TypeStruct`. | 3215 | /// data is 0 or extra index of `TypeStruct`. |
| 2927 | /// data == 0 represents `@TypeOf(.{})`. | 3216 | /// data == 0 represents `@TypeOf(.{})`. |
| 2928 | type_struct, | 3217 | type_struct, |
| 2929 | /// A non-packed struct type that has only a namespace; no fields. | ||
| 2930 | /// data is NamespaceIndex. | ||
| 2931 | type_struct_ns, | ||
| 2932 | /// An AnonStructType which stores types, names, and values for fields. | 3218 | /// An AnonStructType which stores types, names, and values for fields. |
| 2933 | /// data is extra index of `TypeStructAnon`. | 3219 | /// data is extra index of `TypeStructAnon`. |
| 2934 | type_struct_anon, | 3220 | type_struct_anon, |
| ... | @@ -3126,7 +3412,6 @@ pub const Tag = enum(u8) { | ... | @@ -3126,7 +3412,6 @@ pub const Tag = enum(u8) { |
| 3126 | memoized_call, | 3412 | memoized_call, |
| 3127 | 3413 | ||
| 3128 | const ErrorUnionType = Key.ErrorUnionType; | 3414 | const ErrorUnionType = Key.ErrorUnionType; |
| 3129 | const OpaqueType = Key.OpaqueType; | ||
| 3130 | const TypeValue = Key.TypeValue; | 3415 | const TypeValue = Key.TypeValue; |
| 3131 | const Error = Key.Error; | 3416 | const Error = Key.Error; |
| 3132 | const EnumTag = Key.EnumTag; | 3417 | const EnumTag = Key.EnumTag; |
| ... | @@ -3136,6 +3421,7 @@ pub const Tag = enum(u8) { | ... | @@ -3136,6 +3421,7 @@ pub const Tag = enum(u8) { |
| 3136 | 3421 | ||
| 3137 | fn Payload(comptime tag: Tag) type { | 3422 | fn Payload(comptime tag: Tag) type { |
| 3138 | return switch (tag) { | 3423 | return switch (tag) { |
| 3424 | .removed => unreachable, | ||
| 3139 | .type_int_signed => unreachable, | 3425 | .type_int_signed => unreachable, |
| 3140 | .type_int_unsigned => unreachable, | 3426 | .type_int_unsigned => unreachable, |
| 3141 | .type_array_big => Array, | 3427 | .type_array_big => Array, |
| ... | @@ -3153,9 +3439,8 @@ pub const Tag = enum(u8) { | ... | @@ -3153,9 +3439,8 @@ pub const Tag = enum(u8) { |
| 3153 | .type_enum_explicit => EnumExplicit, | 3439 | .type_enum_explicit => EnumExplicit, |
| 3154 | .type_enum_nonexhaustive => EnumExplicit, | 3440 | .type_enum_nonexhaustive => EnumExplicit, |
| 3155 | .simple_type => unreachable, | 3441 | .simple_type => unreachable, |
| 3156 | .type_opaque => OpaqueType, | 3442 | .type_opaque => TypeOpaque, |
| 3157 | .type_struct => TypeStruct, | 3443 | .type_struct => TypeStruct, |
| 3158 | .type_struct_ns => unreachable, | ||
| 3159 | .type_struct_anon => TypeStructAnon, | 3444 | .type_struct_anon => TypeStructAnon, |
| 3160 | .type_struct_packed, .type_struct_packed_inits => TypeStructPacked, | 3445 | .type_struct_packed, .type_struct_packed_inits => TypeStructPacked, |
| 3161 | .type_tuple_anon => TypeStructAnon, | 3446 | .type_tuple_anon => TypeStructAnon, |
| ... | @@ -3311,43 +3596,54 @@ pub const Tag = enum(u8) { | ... | @@ -3311,43 +3596,54 @@ pub const Tag = enum(u8) { |
| 3311 | }; | 3596 | }; |
| 3312 | }; | 3597 | }; |
| 3313 | 3598 | ||
| 3314 | /// The number of fields is provided by the `tag_ty` field. | ||
| 3315 | /// Trailing: | 3599 | /// Trailing: |
| 3316 | /// 0. field type: Index for each field; declaration order | 3600 | /// 0. captures_len: u32 // if `any_captures` |
| 3317 | /// 1. field align: Alignment for each field; declaration order | 3601 | /// 1. capture: CaptureValue // for each `captures_len` |
| 3602 | /// 2. type_hash: PackedU64 // if `is_reified` | ||
| 3603 | /// 3. field type: Index for each field; declaration order | ||
| 3604 | /// 4. field align: Alignment for each field; declaration order | ||
| 3318 | pub const TypeUnion = struct { | 3605 | pub const TypeUnion = struct { |
| 3319 | flags: Flags, | 3606 | flags: Flags, |
| 3607 | /// This could be provided through the tag type, but it is more convenient | ||
| 3608 | /// to store it directly. This is also necessary for `dumpStatsFallible` to | ||
| 3609 | /// work on unresolved types. | ||
| 3610 | fields_len: u32, | ||
| 3320 | /// Only valid after .have_layout | 3611 | /// Only valid after .have_layout |
| 3321 | size: u32, | 3612 | size: u32, |
| 3322 | /// Only valid after .have_layout | 3613 | /// Only valid after .have_layout |
| 3323 | padding: u32, | 3614 | padding: u32, |
| 3324 | decl: DeclIndex, | 3615 | decl: DeclIndex, |
| 3325 | namespace: NamespaceIndex, | 3616 | namespace: OptionalNamespaceIndex, |
| 3326 | /// The enum that provides the list of field names and values. | 3617 | /// The enum that provides the list of field names and values. |
| 3327 | tag_ty: Index, | 3618 | tag_ty: Index, |
| 3328 | zir_index: TrackedInst.Index.Optional, | 3619 | zir_index: TrackedInst.Index, |
| 3329 | 3620 | ||
| 3330 | pub const Flags = packed struct(u32) { | 3621 | pub const Flags = packed struct(u32) { |
| 3331 | runtime_tag: UnionType.RuntimeTag, | 3622 | any_captures: bool, |
| 3623 | runtime_tag: LoadedUnionType.RuntimeTag, | ||
| 3332 | /// If false, the field alignment trailing data is omitted. | 3624 | /// If false, the field alignment trailing data is omitted. |
| 3333 | any_aligned_fields: bool, | 3625 | any_aligned_fields: bool, |
| 3334 | layout: std.builtin.Type.ContainerLayout, | 3626 | layout: std.builtin.Type.ContainerLayout, |
| 3335 | status: UnionType.Status, | 3627 | status: LoadedUnionType.Status, |
| 3336 | requires_comptime: RequiresComptime, | 3628 | requires_comptime: RequiresComptime, |
| 3337 | assumed_runtime_bits: bool, | 3629 | assumed_runtime_bits: bool, |
| 3338 | assumed_pointer_aligned: bool, | 3630 | assumed_pointer_aligned: bool, |
| 3339 | alignment: Alignment, | 3631 | alignment: Alignment, |
| 3340 | _: u14 = 0, | 3632 | is_reified: bool, |
| 3633 | _: u12 = 0, | ||
| 3341 | }; | 3634 | }; |
| 3342 | }; | 3635 | }; |
| 3343 | 3636 | ||
| 3344 | /// Trailing: | 3637 | /// Trailing: |
| 3345 | /// 0. type: Index for each fields_len | 3638 | /// 0. captures_len: u32 // if `any_captures` |
| 3346 | /// 1. name: NullTerminatedString for each fields_len | 3639 | /// 1. capture: CaptureValue // for each `captures_len` |
| 3347 | /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits | 3640 | /// 2. type_hash: PackedU64 // if `is_reified` |
| 3641 | /// 3. type: Index for each fields_len | ||
| 3642 | /// 4. name: NullTerminatedString for each fields_len | ||
| 3643 | /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits | ||
| 3348 | pub const TypeStructPacked = struct { | 3644 | pub const TypeStructPacked = struct { |
| 3349 | decl: DeclIndex, | 3645 | decl: DeclIndex, |
| 3350 | zir_index: TrackedInst.Index.Optional, | 3646 | zir_index: TrackedInst.Index, |
| 3351 | fields_len: u32, | 3647 | fields_len: u32, |
| 3352 | namespace: OptionalNamespaceIndex, | 3648 | namespace: OptionalNamespaceIndex, |
| 3353 | backing_int_ty: Index, | 3649 | backing_int_ty: Index, |
| ... | @@ -3355,10 +3651,12 @@ pub const Tag = enum(u8) { | ... | @@ -3355,10 +3651,12 @@ pub const Tag = enum(u8) { |
| 3355 | flags: Flags, | 3651 | flags: Flags, |
| 3356 | 3652 | ||
| 3357 | pub const Flags = packed struct(u32) { | 3653 | pub const Flags = packed struct(u32) { |
| 3654 | any_captures: bool, | ||
| 3358 | /// Dependency loop detection when resolving field inits. | 3655 | /// Dependency loop detection when resolving field inits. |
| 3359 | field_inits_wip: bool, | 3656 | field_inits_wip: bool, |
| 3360 | inits_resolved: bool, | 3657 | inits_resolved: bool, |
| 3361 | _: u30 = 0, | 3658 | is_reified: bool, |
| 3659 | _: u28 = 0, | ||
| 3362 | }; | 3660 | }; |
| 3363 | }; | 3661 | }; |
| 3364 | 3662 | ||
| ... | @@ -3377,29 +3675,33 @@ pub const Tag = enum(u8) { | ... | @@ -3377,29 +3675,33 @@ pub const Tag = enum(u8) { |
| 3377 | /// than coming up with some other scheme for the data. | 3675 | /// than coming up with some other scheme for the data. |
| 3378 | /// | 3676 | /// |
| 3379 | /// Trailing: | 3677 | /// Trailing: |
| 3380 | /// 0. type: Index for each field in declared order | 3678 | /// 0. captures_len: u32 // if `any_captures` |
| 3381 | /// 1. if not is_tuple: | 3679 | /// 1. capture: CaptureValue // for each `captures_len` |
| 3680 | /// 2. type_hash: PackedU64 // if `is_reified` | ||
| 3681 | /// 3. type: Index for each field in declared order | ||
| 3682 | /// 4. if not is_tuple: | ||
| 3382 | /// names_map: MapIndex, | 3683 | /// names_map: MapIndex, |
| 3383 | /// name: NullTerminatedString // for each field in declared order | 3684 | /// name: NullTerminatedString // for each field in declared order |
| 3384 | /// 2. if any_default_inits: | 3685 | /// 5. if any_default_inits: |
| 3385 | /// init: Index // for each field in declared order | 3686 | /// init: Index // for each field in declared order |
| 3386 | /// 3. if has_namespace: | 3687 | /// 6. if has_namespace: |
| 3387 | /// namespace: NamespaceIndex | 3688 | /// namespace: NamespaceIndex |
| 3388 | /// 4. if any_aligned_fields: | 3689 | /// 7. if any_aligned_fields: |
| 3389 | /// align: Alignment // for each field in declared order | 3690 | /// align: Alignment // for each field in declared order |
| 3390 | /// 5. if any_comptime_fields: | 3691 | /// 8. if any_comptime_fields: |
| 3391 | /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0 | 3692 | /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0 |
| 3392 | /// 6. if not is_extern: | 3693 | /// 9. if not is_extern: |
| 3393 | /// field_index: RuntimeOrder // for each field in runtime order | 3694 | /// field_index: RuntimeOrder // for each field in runtime order |
| 3394 | /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved | 3695 | /// 10. field_offset: u32 // for each field in declared order, undef until layout_resolved |
| 3395 | pub const TypeStruct = struct { | 3696 | pub const TypeStruct = struct { |
| 3396 | decl: DeclIndex, | 3697 | decl: DeclIndex, |
| 3397 | zir_index: TrackedInst.Index.Optional, | 3698 | zir_index: TrackedInst.Index, |
| 3398 | fields_len: u32, | 3699 | fields_len: u32, |
| 3399 | flags: Flags, | 3700 | flags: Flags, |
| 3400 | size: u32, | 3701 | size: u32, |
| 3401 | 3702 | ||
| 3402 | pub const Flags = packed struct(u32) { | 3703 | pub const Flags = packed struct(u32) { |
| 3704 | any_captures: bool, | ||
| 3403 | is_extern: bool, | 3705 | is_extern: bool, |
| 3404 | known_non_opv: bool, | 3706 | known_non_opv: bool, |
| 3405 | requires_comptime: RequiresComptime, | 3707 | requires_comptime: RequiresComptime, |
| ... | @@ -3428,10 +3730,23 @@ pub const Tag = enum(u8) { | ... | @@ -3428,10 +3730,23 @@ pub const Tag = enum(u8) { |
| 3428 | // The types and all its fields have had their layout resolved. Even through pointer, | 3730 | // The types and all its fields have had their layout resolved. Even through pointer, |
| 3429 | // which `layout_resolved` does not ensure. | 3731 | // which `layout_resolved` does not ensure. |
| 3430 | fully_resolved: bool, | 3732 | fully_resolved: bool, |
| 3431 | 3733 | is_reified: bool, | |
| 3432 | _: u8 = 0, | 3734 | _: u6 = 0, |
| 3433 | }; | 3735 | }; |
| 3434 | }; | 3736 | }; |
| 3737 | |||
| 3738 | /// Trailing: | ||
| 3739 | /// 0. capture: CaptureValue // for each `captures_len` | ||
| 3740 | pub const TypeOpaque = struct { | ||
| 3741 | /// The opaque's owner Decl. | ||
| 3742 | decl: DeclIndex, | ||
| 3743 | /// Contains the declarations inside this opaque. | ||
| 3744 | namespace: OptionalNamespaceIndex, | ||
| 3745 | /// The index of the `opaque_decl` instruction. | ||
| 3746 | zir_index: TrackedInst.Index, | ||
| 3747 | /// `std.math.maxInt(u32)` indicates this type is reified. | ||
| 3748 | captures_len: u32, | ||
| 3749 | }; | ||
| 3435 | }; | 3750 | }; |
| 3436 | 3751 | ||
| 3437 | /// State that is mutable during semantic analysis. This data is not used for | 3752 | /// State that is mutable during semantic analysis. This data is not used for |
| ... | @@ -3738,11 +4053,16 @@ pub const Array = struct { | ... | @@ -3738,11 +4053,16 @@ pub const Array = struct { |
| 3738 | }; | 4053 | }; |
| 3739 | 4054 | ||
| 3740 | /// Trailing: | 4055 | /// Trailing: |
| 3741 | /// 0. field name: NullTerminatedString for each fields_len; declaration order | 4056 | /// 0. owner_union: Index // if `zir_index == .none` |
| 3742 | /// 1. tag value: Index for each fields_len; declaration order | 4057 | /// 1. capture: CaptureValue // for each `captures_len` |
| 4058 | /// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | ||
| 4059 | /// 3. field name: NullTerminatedString for each fields_len; declaration order | ||
| 4060 | /// 4. tag value: Index for each fields_len; declaration order | ||
| 3743 | pub const EnumExplicit = struct { | 4061 | pub const EnumExplicit = struct { |
| 3744 | /// The Decl that corresponds to the enum itself. | 4062 | /// The Decl that corresponds to the enum itself. |
| 3745 | decl: DeclIndex, | 4063 | decl: DeclIndex, |
| 4064 | /// `std.math.maxInt(u32)` indicates this type is reified. | ||
| 4065 | captures_len: u32, | ||
| 3746 | /// This may be `none` if there are no declarations. | 4066 | /// This may be `none` if there are no declarations. |
| 3747 | namespace: OptionalNamespaceIndex, | 4067 | namespace: OptionalNamespaceIndex, |
| 3748 | /// An integer type which is used for the numerical value of the enum, which | 4068 | /// An integer type which is used for the numerical value of the enum, which |
| ... | @@ -3755,14 +4075,21 @@ pub const EnumExplicit = struct { | ... | @@ -3755,14 +4075,21 @@ pub const EnumExplicit = struct { |
| 3755 | /// If this is `none`, it means the trailing tag values are absent because | 4075 | /// If this is `none`, it means the trailing tag values are absent because |
| 3756 | /// they are auto-numbered. | 4076 | /// they are auto-numbered. |
| 3757 | values_map: OptionalMapIndex, | 4077 | values_map: OptionalMapIndex, |
| 4078 | /// `none` means this is a generated tag type. | ||
| 4079 | /// There will be a trailing union type for which this is a tag. | ||
| 3758 | zir_index: TrackedInst.Index.Optional, | 4080 | zir_index: TrackedInst.Index.Optional, |
| 3759 | }; | 4081 | }; |
| 3760 | 4082 | ||
| 3761 | /// Trailing: | 4083 | /// Trailing: |
| 3762 | /// 0. field name: NullTerminatedString for each fields_len; declaration order | 4084 | /// 0. owner_union: Index // if `zir_index == .none` |
| 4085 | /// 1. capture: CaptureValue // for each `captures_len` | ||
| 4086 | /// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | ||
| 4087 | /// 3. field name: NullTerminatedString for each fields_len; declaration order | ||
| 3763 | pub const EnumAuto = struct { | 4088 | pub const EnumAuto = struct { |
| 3764 | /// The Decl that corresponds to the enum itself. | 4089 | /// The Decl that corresponds to the enum itself. |
| 3765 | decl: DeclIndex, | 4090 | decl: DeclIndex, |
| 4091 | /// `std.math.maxInt(u32)` indicates this type is reified. | ||
| 4092 | captures_len: u32, | ||
| 3766 | /// This may be `none` if there are no declarations. | 4093 | /// This may be `none` if there are no declarations. |
| 3767 | namespace: OptionalNamespaceIndex, | 4094 | namespace: OptionalNamespaceIndex, |
| 3768 | /// An integer type which is used for the numerical value of the enum, which | 4095 | /// An integer type which is used for the numerical value of the enum, which |
| ... | @@ -3771,6 +4098,8 @@ pub const EnumAuto = struct { | ... | @@ -3771,6 +4098,8 @@ pub const EnumAuto = struct { |
| 3771 | fields_len: u32, | 4098 | fields_len: u32, |
| 3772 | /// Maps field names to declaration index. | 4099 | /// Maps field names to declaration index. |
| 3773 | names_map: MapIndex, | 4100 | names_map: MapIndex, |
| 4101 | /// `none` means this is a generated tag type. | ||
| 4102 | /// There will be a trailing union type for which this is a tag. | ||
| 3774 | zir_index: TrackedInst.Index.Optional, | 4103 | zir_index: TrackedInst.Index.Optional, |
| 3775 | }; | 4104 | }; |
| 3776 | 4105 | ||
| ... | @@ -4011,6 +4340,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -4011,6 +4340,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 4011 | const item = ip.items.get(@intFromEnum(index)); | 4340 | const item = ip.items.get(@intFromEnum(index)); |
| 4012 | const data = item.data; | 4341 | const data = item.data; |
| 4013 | return switch (item.tag) { | 4342 | return switch (item.tag) { |
| 4343 | .removed => unreachable, | ||
| 4014 | .type_int_signed => .{ | 4344 | .type_int_signed => .{ |
| 4015 | .int_type = .{ | 4345 | .int_type = .{ |
| 4016 | .signedness = .signed, | 4346 | .signedness = .signed, |
| ... | @@ -4072,68 +4402,124 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -4072,68 +4402,124 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 4072 | .inferred_error_set_type = @enumFromInt(data), | 4402 | .inferred_error_set_type = @enumFromInt(data), |
| 4073 | }, | 4403 | }, |
| 4074 | 4404 | ||
| 4075 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, | 4405 | .type_opaque => .{ .opaque_type = ns: { |
| 4076 | 4406 | const extra = ip.extraDataTrail(Tag.TypeOpaque, data); | |
| 4077 | .type_struct => .{ .struct_type = if (data == 0) .{ | 4407 | if (extra.data.captures_len == std.math.maxInt(u32)) { |
| 4078 | .extra_index = 0, | 4408 | break :ns .{ .reified = .{ |
| 4079 | .namespace = .none, | 4409 | .zir_index = extra.data.zir_index, |
| 4080 | .decl = .none, | 4410 | .type_hash = 0, |
| 4081 | .zir_index = undefined, | 4411 | } }; |
| 4082 | .layout = .Auto, | 4412 | } |
| 4083 | .field_names = .{ .start = 0, .len = 0 }, | 4413 | break :ns .{ .declared = .{ |
| 4084 | .field_types = .{ .start = 0, .len = 0 }, | 4414 | .zir_index = extra.data.zir_index, |
| 4085 | .field_inits = .{ .start = 0, .len = 0 }, | 4415 | .captures = .{ .owned = .{ |
| 4086 | .field_aligns = .{ .start = 0, .len = 0 }, | 4416 | .start = extra.end, |
| 4087 | .runtime_order = .{ .start = 0, .len = 0 }, | 4417 | .len = extra.data.captures_len, |
| 4088 | .comptime_bits = .{ .start = 0, .len = 0 }, | 4418 | } }, |
| 4089 | .offsets = .{ .start = 0, .len = 0 }, | 4419 | } }; |
| 4090 | .names_map = undefined, | 4420 | } }, |
| 4091 | } else extraStructType(ip, data) }, | 4421 | |
| 4092 | 4422 | .type_struct => .{ .struct_type = ns: { | |
| 4093 | .type_struct_ns => .{ .struct_type = .{ | 4423 | if (data == 0) break :ns .empty_struct; |
| 4094 | .extra_index = 0, | 4424 | const extra = ip.extraDataTrail(Tag.TypeStruct, data); |
| 4095 | .namespace = @as(NamespaceIndex, @enumFromInt(data)).toOptional(), | 4425 | if (extra.data.flags.is_reified) { |
| 4096 | .decl = .none, | 4426 | assert(!extra.data.flags.any_captures); |
| 4097 | .zir_index = undefined, | 4427 | break :ns .{ .reified = .{ |
| 4098 | .layout = .Auto, | 4428 | .zir_index = extra.data.zir_index, |
| 4099 | .field_names = .{ .start = 0, .len = 0 }, | 4429 | .type_hash = ip.extraData(PackedU64, extra.end).get(), |
| 4100 | .field_types = .{ .start = 0, .len = 0 }, | 4430 | } }; |
| 4101 | .field_inits = .{ .start = 0, .len = 0 }, | 4431 | } |
| 4102 | .field_aligns = .{ .start = 0, .len = 0 }, | 4432 | break :ns .{ .declared = .{ |
| 4103 | .runtime_order = .{ .start = 0, .len = 0 }, | 4433 | .zir_index = extra.data.zir_index, |
| 4104 | .comptime_bits = .{ .start = 0, .len = 0 }, | 4434 | .captures = .{ .owned = if (extra.data.flags.any_captures) .{ |
| 4105 | .offsets = .{ .start = 0, .len = 0 }, | 4435 | .start = extra.end + 1, |
| 4106 | .names_map = undefined, | 4436 | .len = ip.extra.items[extra.end], |
| 4437 | } else .{ .start = 0, .len = 0 } }, | ||
| 4438 | } }; | ||
| 4439 | } }, | ||
| 4440 | |||
| 4441 | .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = ns: { | ||
| 4442 | const extra = ip.extraDataTrail(Tag.TypeStructPacked, data); | ||
| 4443 | if (extra.data.flags.is_reified) { | ||
| 4444 | assert(!extra.data.flags.any_captures); | ||
| 4445 | break :ns .{ .reified = .{ | ||
| 4446 | .zir_index = extra.data.zir_index, | ||
| 4447 | .type_hash = ip.extraData(PackedU64, extra.end).get(), | ||
| 4448 | } }; | ||
| 4449 | } | ||
| 4450 | break :ns .{ .declared = .{ | ||
| 4451 | .zir_index = extra.data.zir_index, | ||
| 4452 | .captures = .{ .owned = if (extra.data.flags.any_captures) .{ | ||
| 4453 | .start = extra.end + 1, | ||
| 4454 | .len = ip.extra.items[extra.end], | ||
| 4455 | } else .{ .start = 0, .len = 0 } }, | ||
| 4456 | } }; | ||
| 4107 | } }, | 4457 | } }, |
| 4108 | 4458 | ||
| 4109 | .type_struct_anon => .{ .anon_struct_type = extraTypeStructAnon(ip, data) }, | 4459 | .type_struct_anon => .{ .anon_struct_type = extraTypeStructAnon(ip, data) }, |
| 4110 | .type_tuple_anon => .{ .anon_struct_type = extraTypeTupleAnon(ip, data) }, | 4460 | .type_tuple_anon => .{ .anon_struct_type = extraTypeTupleAnon(ip, data) }, |
| 4111 | .type_struct_packed => .{ .struct_type = extraPackedStructType(ip, data, false) }, | 4461 | .type_union => .{ .union_type = ns: { |
| 4112 | .type_struct_packed_inits => .{ .struct_type = extraPackedStructType(ip, data, true) }, | 4462 | const extra = ip.extraDataTrail(Tag.TypeUnion, data); |
| 4113 | .type_union => .{ .union_type = extraUnionType(ip, data) }, | 4463 | if (extra.data.flags.is_reified) { |
| 4464 | assert(!extra.data.flags.any_captures); | ||
| 4465 | break :ns .{ .reified = .{ | ||
| 4466 | .zir_index = extra.data.zir_index, | ||
| 4467 | .type_hash = ip.extraData(PackedU64, extra.end).get(), | ||
| 4468 | } }; | ||
| 4469 | } | ||
| 4470 | break :ns .{ .declared = .{ | ||
| 4471 | .zir_index = extra.data.zir_index, | ||
| 4472 | .captures = .{ .owned = if (extra.data.flags.any_captures) .{ | ||
| 4473 | .start = extra.end + 1, | ||
| 4474 | .len = ip.extra.items[extra.end], | ||
| 4475 | } else .{ .start = 0, .len = 0 } }, | ||
| 4476 | } }; | ||
| 4477 | } }, | ||
| 4114 | 4478 | ||
| 4115 | .type_enum_auto => { | 4479 | .type_enum_auto => .{ .enum_type = ns: { |
| 4116 | const enum_auto = ip.extraDataTrail(EnumAuto, data); | 4480 | const extra = ip.extraDataTrail(EnumAuto, data); |
| 4117 | return .{ .enum_type = .{ | 4481 | const zir_index = extra.data.zir_index.unwrap() orelse { |
| 4118 | .decl = enum_auto.data.decl, | 4482 | assert(extra.data.captures_len == 0); |
| 4119 | .namespace = enum_auto.data.namespace, | 4483 | break :ns .{ .generated_tag = .{ |
| 4120 | .tag_ty = enum_auto.data.int_tag_type, | 4484 | .union_type = @enumFromInt(ip.extra.items[extra.end]), |
| 4121 | .names = .{ | 4485 | } }; |
| 4122 | .start = @intCast(enum_auto.end), | 4486 | }; |
| 4123 | .len = enum_auto.data.fields_len, | 4487 | if (extra.data.captures_len == std.math.maxInt(u32)) { |
| 4124 | }, | 4488 | break :ns .{ .reified = .{ |
| 4125 | .values = .{ | 4489 | .zir_index = zir_index, |
| 4126 | .start = 0, | 4490 | .type_hash = ip.extraData(PackedU64, extra.end).get(), |
| 4127 | .len = 0, | 4491 | } }; |
| 4128 | }, | 4492 | } |
| 4129 | .tag_mode = .auto, | 4493 | break :ns .{ .declared = .{ |
| 4130 | .names_map = enum_auto.data.names_map.toOptional(), | 4494 | .zir_index = zir_index, |
| 4131 | .values_map = .none, | 4495 | .captures = .{ .owned = .{ |
| 4132 | .zir_index = enum_auto.data.zir_index, | 4496 | .start = extra.end, |
| 4497 | .len = extra.data.captures_len, | ||
| 4498 | } }, | ||
| 4133 | } }; | 4499 | } }; |
| 4134 | }, | 4500 | } }, |
| 4135 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), | 4501 | .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: { |
| 4136 | .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive), | 4502 | const extra = ip.extraDataTrail(EnumExplicit, data); |
| 4503 | const zir_index = extra.data.zir_index.unwrap() orelse { | ||
| 4504 | assert(extra.data.captures_len == 0); | ||
| 4505 | break :ns .{ .generated_tag = .{ | ||
| 4506 | .union_type = @enumFromInt(ip.extra.items[extra.end]), | ||
| 4507 | } }; | ||
| 4508 | }; | ||
| 4509 | if (extra.data.captures_len == std.math.maxInt(u32)) { | ||
| 4510 | break :ns .{ .reified = .{ | ||
| 4511 | .zir_index = zir_index, | ||
| 4512 | .type_hash = ip.extraData(PackedU64, extra.end).get(), | ||
| 4513 | } }; | ||
| 4514 | } | ||
| 4515 | break :ns .{ .declared = .{ | ||
| 4516 | .zir_index = zir_index, | ||
| 4517 | .captures = .{ .owned = .{ | ||
| 4518 | .start = extra.end, | ||
| 4519 | .len = extra.data.captures_len, | ||
| 4520 | } }, | ||
| 4521 | } }; | ||
| 4522 | } }, | ||
| 4137 | .type_function => .{ .func_type = ip.extraFuncType(data) }, | 4523 | .type_function => .{ .func_type = ip.extraFuncType(data) }, |
| 4138 | 4524 | ||
| 4139 | .undef => .{ .undef = @as(Index, @enumFromInt(data)) }, | 4525 | .undef => .{ .undef = @as(Index, @enumFromInt(data)) }, |
| ... | @@ -4366,7 +4752,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -4366,7 +4752,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 4366 | }, | 4752 | }, |
| 4367 | .type_array_small, | 4753 | .type_array_small, |
| 4368 | .type_vector, | 4754 | .type_vector, |
| 4369 | .type_struct_ns, | ||
| 4370 | .type_struct_packed, | 4755 | .type_struct_packed, |
| 4371 | => .{ .aggregate = .{ | 4756 | => .{ .aggregate = .{ |
| 4372 | .ty = ty, | 4757 | .ty = ty, |
| ... | @@ -4375,16 +4760,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -4375,16 +4760,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 4375 | 4760 | ||
| 4376 | // There is only one possible value precisely due to the | 4761 | // There is only one possible value precisely due to the |
| 4377 | // fact that this values slice is fully populated! | 4762 | // fact that this values slice is fully populated! |
| 4378 | .type_struct => { | 4763 | .type_struct, .type_struct_packed_inits => { |
| 4379 | const info = extraStructType(ip, ty_item.data); | 4764 | const info = loadStructType(ip, ty); |
| 4380 | return .{ .aggregate = .{ | ||
| 4381 | .ty = ty, | ||
| 4382 | .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) }, | ||
| 4383 | } }; | ||
| 4384 | }, | ||
| 4385 | |||
| 4386 | .type_struct_packed_inits => { | ||
| 4387 | const info = extraPackedStructType(ip, ty_item.data, true); | ||
| 4388 | return .{ .aggregate = .{ | 4765 | return .{ .aggregate = .{ |
| 4389 | .ty = ty, | 4766 | .ty = ty, |
| 4390 | .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) }, | 4767 | .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) }, |
| ... | @@ -4476,18 +4853,6 @@ fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType { | ... | @@ -4476,18 +4853,6 @@ fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType { |
| 4476 | }; | 4853 | }; |
| 4477 | } | 4854 | } |
| 4478 | 4855 | ||
| 4479 | fn extraUnionType(ip: *const InternPool, extra_index: u32) Key.UnionType { | ||
| 4480 | const type_union = ip.extraData(Tag.TypeUnion, extra_index); | ||
| 4481 | return .{ | ||
| 4482 | .decl = type_union.decl, | ||
| 4483 | .namespace = type_union.namespace, | ||
| 4484 | .flags = type_union.flags, | ||
| 4485 | .enum_tag_ty = type_union.tag_ty, | ||
| 4486 | .zir_index = type_union.zir_index, | ||
| 4487 | .extra_index = extra_index, | ||
| 4488 | }; | ||
| 4489 | } | ||
| 4490 | |||
| 4491 | fn extraTypeStructAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType { | 4856 | fn extraTypeStructAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType { |
| 4492 | const type_struct_anon = ip.extraDataTrail(TypeStructAnon, extra_index); | 4857 | const type_struct_anon = ip.extraDataTrail(TypeStructAnon, extra_index); |
| 4493 | const fields_len = type_struct_anon.data.fields_len; | 4858 | const fields_len = type_struct_anon.data.fields_len; |
| ... | @@ -4526,109 +4891,6 @@ fn extraTypeTupleAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructTyp | ... | @@ -4526,109 +4891,6 @@ fn extraTypeTupleAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructTyp |
| 4526 | }; | 4891 | }; |
| 4527 | } | 4892 | } |
| 4528 | 4893 | ||
| 4529 | fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType { | ||
| 4530 | const s = ip.extraDataTrail(Tag.TypeStruct, extra_index); | ||
| 4531 | const fields_len = s.data.fields_len; | ||
| 4532 | |||
| 4533 | var index = s.end; | ||
| 4534 | |||
| 4535 | const field_types = t: { | ||
| 4536 | const types: Index.Slice = .{ .start = index, .len = fields_len }; | ||
| 4537 | index += fields_len; | ||
| 4538 | break :t types; | ||
| 4539 | }; | ||
| 4540 | const names_map, const field_names: NullTerminatedString.Slice = t: { | ||
| 4541 | if (s.data.flags.is_tuple) break :t .{ .none, .{ .start = 0, .len = 0 } }; | ||
| 4542 | const names_map: MapIndex = @enumFromInt(ip.extra.items[index]); | ||
| 4543 | index += 1; | ||
| 4544 | const names: NullTerminatedString.Slice = .{ .start = index, .len = fields_len }; | ||
| 4545 | index += fields_len; | ||
| 4546 | break :t .{ names_map.toOptional(), names }; | ||
| 4547 | }; | ||
| 4548 | const field_inits: Index.Slice = t: { | ||
| 4549 | if (!s.data.flags.any_default_inits) break :t .{ .start = 0, .len = 0 }; | ||
| 4550 | const inits: Index.Slice = .{ .start = index, .len = fields_len }; | ||
| 4551 | index += fields_len; | ||
| 4552 | break :t inits; | ||
| 4553 | }; | ||
| 4554 | const namespace = t: { | ||
| 4555 | if (!s.data.flags.has_namespace) break :t .none; | ||
| 4556 | const namespace: NamespaceIndex = @enumFromInt(ip.extra.items[index]); | ||
| 4557 | index += 1; | ||
| 4558 | break :t namespace.toOptional(); | ||
| 4559 | }; | ||
| 4560 | const field_aligns: Alignment.Slice = t: { | ||
| 4561 | if (!s.data.flags.any_aligned_fields) break :t .{ .start = 0, .len = 0 }; | ||
| 4562 | const aligns: Alignment.Slice = .{ .start = index, .len = fields_len }; | ||
| 4563 | index += (fields_len + 3) / 4; | ||
| 4564 | break :t aligns; | ||
| 4565 | }; | ||
| 4566 | const comptime_bits: Key.StructType.ComptimeBits = t: { | ||
| 4567 | if (!s.data.flags.any_comptime_fields) break :t .{ .start = 0, .len = 0 }; | ||
| 4568 | const comptime_bits: Key.StructType.ComptimeBits = .{ .start = index, .len = fields_len }; | ||
| 4569 | index += (fields_len + 31) / 32; | ||
| 4570 | break :t comptime_bits; | ||
| 4571 | }; | ||
| 4572 | const runtime_order: Key.StructType.RuntimeOrder.Slice = t: { | ||
| 4573 | if (s.data.flags.is_extern) break :t .{ .start = 0, .len = 0 }; | ||
| 4574 | const ro: Key.StructType.RuntimeOrder.Slice = .{ .start = index, .len = fields_len }; | ||
| 4575 | index += fields_len; | ||
| 4576 | break :t ro; | ||
| 4577 | }; | ||
| 4578 | const offsets = t: { | ||
| 4579 | const offsets: Key.StructType.Offsets = .{ .start = index, .len = fields_len }; | ||
| 4580 | index += fields_len; | ||
| 4581 | break :t offsets; | ||
| 4582 | }; | ||
| 4583 | return .{ | ||
| 4584 | .extra_index = extra_index, | ||
| 4585 | .decl = s.data.decl.toOptional(), | ||
| 4586 | .zir_index = s.data.zir_index, | ||
| 4587 | .layout = if (s.data.flags.is_extern) .Extern else .Auto, | ||
| 4588 | .field_types = field_types, | ||
| 4589 | .names_map = names_map, | ||
| 4590 | .field_names = field_names, | ||
| 4591 | .field_inits = field_inits, | ||
| 4592 | .namespace = namespace, | ||
| 4593 | .field_aligns = field_aligns, | ||
| 4594 | .comptime_bits = comptime_bits, | ||
| 4595 | .runtime_order = runtime_order, | ||
| 4596 | .offsets = offsets, | ||
| 4597 | }; | ||
| 4598 | } | ||
| 4599 | |||
| 4600 | fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) Key.StructType { | ||
| 4601 | const type_struct_packed = ip.extraDataTrail(Tag.TypeStructPacked, extra_index); | ||
| 4602 | const fields_len = type_struct_packed.data.fields_len; | ||
| 4603 | return .{ | ||
| 4604 | .extra_index = extra_index, | ||
| 4605 | .decl = type_struct_packed.data.decl.toOptional(), | ||
| 4606 | .namespace = type_struct_packed.data.namespace, | ||
| 4607 | .zir_index = type_struct_packed.data.zir_index, | ||
| 4608 | .layout = .Packed, | ||
| 4609 | .field_types = .{ | ||
| 4610 | .start = type_struct_packed.end, | ||
| 4611 | .len = fields_len, | ||
| 4612 | }, | ||
| 4613 | .field_names = .{ | ||
| 4614 | .start = type_struct_packed.end + fields_len, | ||
| 4615 | .len = fields_len, | ||
| 4616 | }, | ||
| 4617 | .field_inits = if (inits) .{ | ||
| 4618 | .start = type_struct_packed.end + fields_len * 2, | ||
| 4619 | .len = fields_len, | ||
| 4620 | } else .{ | ||
| 4621 | .start = 0, | ||
| 4622 | .len = 0, | ||
| 4623 | }, | ||
| 4624 | .field_aligns = .{ .start = 0, .len = 0 }, | ||
| 4625 | .runtime_order = .{ .start = 0, .len = 0 }, | ||
| 4626 | .comptime_bits = .{ .start = 0, .len = 0 }, | ||
| 4627 | .offsets = .{ .start = 0, .len = 0 }, | ||
| 4628 | .names_map = type_struct_packed.data.names_map.toOptional(), | ||
| 4629 | }; | ||
| 4630 | } | ||
| 4631 | |||
| 4632 | fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType { | 4894 | fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType { |
| 4633 | const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index); | 4895 | const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index); |
| 4634 | var index: usize = type_function.end; | 4896 | var index: usize = type_function.end; |
| ... | @@ -4720,28 +4982,6 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func { | ... | @@ -4720,28 +4982,6 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func { |
| 4720 | return func; | 4982 | return func; |
| 4721 | } | 4983 | } |
| 4722 | 4984 | ||
| 4723 | fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key { | ||
| 4724 | const enum_explicit = ip.extraDataTrail(EnumExplicit, data); | ||
| 4725 | const fields_len = enum_explicit.data.fields_len; | ||
| 4726 | return .{ .enum_type = .{ | ||
| 4727 | .decl = enum_explicit.data.decl, | ||
| 4728 | .namespace = enum_explicit.data.namespace, | ||
| 4729 | .tag_ty = enum_explicit.data.int_tag_type, | ||
| 4730 | .names = .{ | ||
| 4731 | .start = @intCast(enum_explicit.end), | ||
| 4732 | .len = fields_len, | ||
| 4733 | }, | ||
| 4734 | .values = .{ | ||
| 4735 | .start = @intCast(enum_explicit.end + fields_len), | ||
| 4736 | .len = if (enum_explicit.data.values_map != .none) fields_len else 0, | ||
| 4737 | }, | ||
| 4738 | .tag_mode = tag_mode, | ||
| 4739 | .names_map = enum_explicit.data.names_map.toOptional(), | ||
| 4740 | .values_map = enum_explicit.data.values_map, | ||
| 4741 | .zir_index = enum_explicit.data.zir_index, | ||
| 4742 | } }; | ||
| 4743 | } | ||
| 4744 | |||
| 4745 | fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key { | 4985 | fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key { |
| 4746 | const int_info = ip.limbData(Int, limb_index); | 4986 | const int_info = ip.limbData(Int, limb_index); |
| 4747 | return .{ .int = .{ | 4987 | return .{ .int = .{ |
| ... | @@ -4901,15 +5141,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -4901,15 +5141,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 4901 | .struct_type => unreachable, // use getStructType() instead | 5141 | .struct_type => unreachable, // use getStructType() instead |
| 4902 | .anon_struct_type => unreachable, // use getAnonStructType() instead | 5142 | .anon_struct_type => unreachable, // use getAnonStructType() instead |
| 4903 | .union_type => unreachable, // use getUnionType() instead | 5143 | .union_type => unreachable, // use getUnionType() instead |
| 5144 | .opaque_type => unreachable, // use getOpaqueType() instead | ||
| 4904 | 5145 | ||
| 4905 | .opaque_type => |opaque_type| { | 5146 | .enum_type => unreachable, // use getEnumType() instead |
| 4906 | ip.items.appendAssumeCapacity(.{ | ||
| 4907 | .tag = .type_opaque, | ||
| 4908 | .data = try ip.addExtra(gpa, opaque_type), | ||
| 4909 | }); | ||
| 4910 | }, | ||
| 4911 | |||
| 4912 | .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead | ||
| 4913 | .func_type => unreachable, // use getFuncType() instead | 5147 | .func_type => unreachable, // use getFuncType() instead |
| 4914 | .extern_func => unreachable, // use getExternFunc() instead | 5148 | .extern_func => unreachable, // use getExternFunc() instead |
| 4915 | .func => unreachable, // use getFuncInstance() or getFuncDecl() instead | 5149 | .func => unreachable, // use getFuncInstance() or getFuncDecl() instead |
| ... | @@ -5027,14 +5261,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5027,14 +5261,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5027 | assert(ptr.addr == .field); | 5261 | assert(ptr.addr == .field); |
| 5028 | assert(base_index.index < anon_struct_type.types.len); | 5262 | assert(base_index.index < anon_struct_type.types.len); |
| 5029 | }, | 5263 | }, |
| 5030 | .struct_type => |struct_type| { | 5264 | .struct_type => { |
| 5031 | assert(ptr.addr == .field); | 5265 | assert(ptr.addr == .field); |
| 5032 | assert(base_index.index < struct_type.field_types.len); | 5266 | assert(base_index.index < ip.loadStructType(base_ptr_type.child).field_types.len); |
| 5033 | }, | 5267 | }, |
| 5034 | .union_type => |union_key| { | 5268 | .union_type => { |
| 5035 | const union_type = ip.loadUnionType(union_key); | 5269 | const union_type = ip.loadUnionType(base_ptr_type.child); |
| 5036 | assert(ptr.addr == .field); | 5270 | assert(ptr.addr == .field); |
| 5037 | assert(base_index.index < union_type.field_names.len); | 5271 | assert(base_index.index < union_type.field_types.len); |
| 5038 | }, | 5272 | }, |
| 5039 | .ptr_type => |slice_type| { | 5273 | .ptr_type => |slice_type| { |
| 5040 | assert(ptr.addr == .field); | 5274 | assert(ptr.addr == .field); |
| ... | @@ -5305,7 +5539,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5305,7 +5539,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5305 | assert(ip.isEnumType(enum_tag.ty)); | 5539 | assert(ip.isEnumType(enum_tag.ty)); |
| 5306 | switch (ip.indexToKey(enum_tag.ty)) { | 5540 | switch (ip.indexToKey(enum_tag.ty)) { |
| 5307 | .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))), | 5541 | .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))), |
| 5308 | .enum_type => |enum_type| assert(ip.typeOf(enum_tag.int) == enum_type.tag_ty), | 5542 | .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).tag_ty), |
| 5309 | else => unreachable, | 5543 | else => unreachable, |
| 5310 | } | 5544 | } |
| 5311 | ip.items.appendAssumeCapacity(.{ | 5545 | ip.items.appendAssumeCapacity(.{ |
| ... | @@ -5398,8 +5632,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5398,8 +5632,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5398 | assert(ip.typeOf(elem) == child); | 5632 | assert(ip.typeOf(elem) == child); |
| 5399 | } | 5633 | } |
| 5400 | }, | 5634 | }, |
| 5401 | .struct_type => |t| { | 5635 | .struct_type => { |
| 5402 | for (aggregate.storage.values(), t.field_types.get(ip)) |elem, field_ty| { | 5636 | for (aggregate.storage.values(), ip.loadStructType(aggregate.ty).field_types.get(ip)) |elem, field_ty| { |
| 5403 | assert(ip.typeOf(elem) == field_ty); | 5637 | assert(ip.typeOf(elem) == field_ty); |
| 5404 | } | 5638 | } |
| 5405 | }, | 5639 | }, |
| ... | @@ -5572,10 +5806,17 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5572,10 +5806,17 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5572 | } | 5806 | } |
| 5573 | 5807 | ||
| 5574 | pub const UnionTypeInit = struct { | 5808 | pub const UnionTypeInit = struct { |
| 5575 | flags: Tag.TypeUnion.Flags, | 5809 | flags: packed struct { |
| 5576 | decl: DeclIndex, | 5810 | runtime_tag: LoadedUnionType.RuntimeTag, |
| 5577 | namespace: NamespaceIndex, | 5811 | any_aligned_fields: bool, |
| 5578 | zir_index: TrackedInst.Index.Optional, | 5812 | layout: std.builtin.Type.ContainerLayout, |
| 5813 | status: LoadedUnionType.Status, | ||
| 5814 | requires_comptime: RequiresComptime, | ||
| 5815 | assumed_runtime_bits: bool, | ||
| 5816 | assumed_pointer_aligned: bool, | ||
| 5817 | alignment: Alignment, | ||
| 5818 | }, | ||
| 5819 | has_namespace: bool, | ||
| 5579 | fields_len: u32, | 5820 | fields_len: u32, |
| 5580 | enum_tag_ty: Index, | 5821 | enum_tag_ty: Index, |
| 5581 | /// May have length 0 which leaves the values unset until later. | 5822 | /// May have length 0 which leaves the values unset until later. |
| ... | @@ -5584,27 +5825,84 @@ pub const UnionTypeInit = struct { | ... | @@ -5584,27 +5825,84 @@ pub const UnionTypeInit = struct { |
| 5584 | /// The logic for `any_aligned_fields` is asserted to have been done before | 5825 | /// The logic for `any_aligned_fields` is asserted to have been done before |
| 5585 | /// calling this function. | 5826 | /// calling this function. |
| 5586 | field_aligns: []const Alignment, | 5827 | field_aligns: []const Alignment, |
| 5828 | key: union(enum) { | ||
| 5829 | declared: struct { | ||
| 5830 | zir_index: TrackedInst.Index, | ||
| 5831 | captures: []const CaptureValue, | ||
| 5832 | }, | ||
| 5833 | reified: struct { | ||
| 5834 | zir_index: TrackedInst.Index, | ||
| 5835 | type_hash: u64, | ||
| 5836 | }, | ||
| 5837 | }, | ||
| 5587 | }; | 5838 | }; |
| 5588 | 5839 | ||
| 5589 | pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocator.Error!Index { | 5840 | pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocator.Error!WipNamespaceType.Result { |
| 5590 | const prev_extra_len = ip.extra.items.len; | 5841 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 5842 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ .union_type = switch (ini.key) { | ||
| 5843 | .declared => |d| .{ .declared = .{ | ||
| 5844 | .zir_index = d.zir_index, | ||
| 5845 | .captures = .{ .external = d.captures }, | ||
| 5846 | } }, | ||
| 5847 | .reified => |r| .{ .reified = .{ | ||
| 5848 | .zir_index = r.zir_index, | ||
| 5849 | .type_hash = r.type_hash, | ||
| 5850 | } }, | ||
| 5851 | } }, adapter); | ||
| 5852 | if (gop.found_existing) return .{ .existing = @enumFromInt(gop.index) }; | ||
| 5853 | errdefer _ = ip.map.pop(); | ||
| 5854 | |||
| 5591 | const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; | 5855 | const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; |
| 5592 | const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); | 5856 | const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); |
| 5593 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeUnion).Struct.fields.len + | 5857 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeUnion).Struct.fields.len + |
| 5858 | // TODO: fmt bug | ||
| 5859 | // zig fmt: off | ||
| 5860 | switch (ini.key) { | ||
| 5861 | .declared => |d| @intFromBool(d.captures.len != 0) + d.captures.len, | ||
| 5862 | .reified => 2, // type_hash: PackedU64 | ||
| 5863 | } + | ||
| 5864 | // zig fmt: on | ||
| 5594 | ini.fields_len + // field types | 5865 | ini.fields_len + // field types |
| 5595 | align_elements_len); | 5866 | align_elements_len); |
| 5596 | try ip.items.ensureUnusedCapacity(gpa, 1); | 5867 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 5597 | 5868 | ||
| 5598 | const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{ | 5869 | const extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{ |
| 5599 | .flags = ini.flags, | 5870 | .flags = .{ |
| 5871 | .any_captures = ini.key == .declared and ini.key.declared.captures.len != 0, | ||
| 5872 | .runtime_tag = ini.flags.runtime_tag, | ||
| 5873 | .any_aligned_fields = ini.flags.any_aligned_fields, | ||
| 5874 | .layout = ini.flags.layout, | ||
| 5875 | .status = ini.flags.status, | ||
| 5876 | .requires_comptime = ini.flags.requires_comptime, | ||
| 5877 | .assumed_runtime_bits = ini.flags.assumed_runtime_bits, | ||
| 5878 | .assumed_pointer_aligned = ini.flags.assumed_pointer_aligned, | ||
| 5879 | .alignment = ini.flags.alignment, | ||
| 5880 | .is_reified = ini.key == .reified, | ||
| 5881 | }, | ||
| 5882 | .fields_len = ini.fields_len, | ||
| 5600 | .size = std.math.maxInt(u32), | 5883 | .size = std.math.maxInt(u32), |
| 5601 | .padding = std.math.maxInt(u32), | 5884 | .padding = std.math.maxInt(u32), |
| 5602 | .decl = ini.decl, | 5885 | .decl = undefined, // set by `finish` |
| 5603 | .namespace = ini.namespace, | 5886 | .namespace = .none, // set by `finish` |
| 5604 | .tag_ty = ini.enum_tag_ty, | 5887 | .tag_ty = ini.enum_tag_ty, |
| 5605 | .zir_index = ini.zir_index, | 5888 | .zir_index = switch (ini.key) { |
| 5889 | inline else => |x| x.zir_index, | ||
| 5890 | }, | ||
| 5891 | }); | ||
| 5892 | |||
| 5893 | ip.items.appendAssumeCapacity(.{ | ||
| 5894 | .tag = .type_union, | ||
| 5895 | .data = extra_index, | ||
| 5606 | }); | 5896 | }); |
| 5607 | 5897 | ||
| 5898 | switch (ini.key) { | ||
| 5899 | .declared => |d| if (d.captures.len != 0) { | ||
| 5900 | ip.extra.appendAssumeCapacity(@intCast(d.captures.len)); | ||
| 5901 | ip.extra.appendSliceAssumeCapacity(@ptrCast(d.captures)); | ||
| 5902 | }, | ||
| 5903 | .reified => |r| _ = ip.addExtraAssumeCapacity(PackedU64.init(r.type_hash)), | ||
| 5904 | } | ||
| 5905 | |||
| 5608 | // field types | 5906 | // field types |
| 5609 | if (ini.field_types.len > 0) { | 5907 | if (ini.field_types.len > 0) { |
| 5610 | assert(ini.field_types.len == ini.fields_len); | 5908 | assert(ini.field_types.len == ini.fields_len); |
| ... | @@ -5627,27 +5925,41 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat | ... | @@ -5627,27 +5925,41 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat |
| 5627 | assert(ini.field_aligns.len == 0); | 5925 | assert(ini.field_aligns.len == 0); |
| 5628 | } | 5926 | } |
| 5629 | 5927 | ||
| 5630 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 5928 | return .{ .wip = .{ |
| 5631 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ | 5929 | .index = @enumFromInt(ip.items.len - 1), |
| 5632 | .union_type = extraUnionType(ip, union_type_extra_index), | 5930 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "decl").?, |
| 5633 | }, adapter); | 5931 | .namespace_extra_index = if (ini.has_namespace) |
| 5634 | if (gop.found_existing) { | 5932 | extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").? |
| 5635 | ip.extra.items.len = prev_extra_len; | 5933 | else |
| 5636 | return @enumFromInt(gop.index); | 5934 | null, |
| 5935 | } }; | ||
| 5936 | } | ||
| 5937 | |||
| 5938 | pub const WipNamespaceType = struct { | ||
| 5939 | index: Index, | ||
| 5940 | decl_extra_index: u32, | ||
| 5941 | namespace_extra_index: ?u32, | ||
| 5942 | pub fn finish(wip: WipNamespaceType, ip: *InternPool, decl: DeclIndex, namespace: OptionalNamespaceIndex) Index { | ||
| 5943 | ip.extra.items[wip.decl_extra_index] = @intFromEnum(decl); | ||
| 5944 | if (wip.namespace_extra_index) |i| { | ||
| 5945 | ip.extra.items[i] = @intFromEnum(namespace.unwrap().?); | ||
| 5946 | } else { | ||
| 5947 | assert(namespace == .none); | ||
| 5948 | } | ||
| 5949 | return wip.index; | ||
| 5950 | } | ||
| 5951 | pub fn cancel(wip: WipNamespaceType, ip: *InternPool) void { | ||
| 5952 | ip.remove(wip.index); | ||
| 5637 | } | 5953 | } |
| 5638 | 5954 | ||
| 5639 | ip.items.appendAssumeCapacity(.{ | 5955 | pub const Result = union(enum) { |
| 5640 | .tag = .type_union, | 5956 | wip: WipNamespaceType, |
| 5641 | .data = union_type_extra_index, | 5957 | existing: Index, |
| 5642 | }); | 5958 | }; |
| 5643 | return @enumFromInt(ip.items.len - 1); | 5959 | }; |
| 5644 | } | ||
| 5645 | 5960 | ||
| 5646 | pub const StructTypeInit = struct { | 5961 | pub const StructTypeInit = struct { |
| 5647 | decl: DeclIndex, | ||
| 5648 | namespace: OptionalNamespaceIndex, | ||
| 5649 | layout: std.builtin.Type.ContainerLayout, | 5962 | layout: std.builtin.Type.ContainerLayout, |
| 5650 | zir_index: TrackedInst.Index.Optional, | ||
| 5651 | fields_len: u32, | 5963 | fields_len: u32, |
| 5652 | known_non_opv: bool, | 5964 | known_non_opv: bool, |
| 5653 | requires_comptime: RequiresComptime, | 5965 | requires_comptime: RequiresComptime, |
| ... | @@ -5656,69 +5968,101 @@ pub const StructTypeInit = struct { | ... | @@ -5656,69 +5968,101 @@ pub const StructTypeInit = struct { |
| 5656 | any_default_inits: bool, | 5968 | any_default_inits: bool, |
| 5657 | inits_resolved: bool, | 5969 | inits_resolved: bool, |
| 5658 | any_aligned_fields: bool, | 5970 | any_aligned_fields: bool, |
| 5971 | has_namespace: bool, | ||
| 5972 | key: union(enum) { | ||
| 5973 | declared: struct { | ||
| 5974 | zir_index: TrackedInst.Index, | ||
| 5975 | captures: []const CaptureValue, | ||
| 5976 | }, | ||
| 5977 | reified: struct { | ||
| 5978 | zir_index: TrackedInst.Index, | ||
| 5979 | type_hash: u64, | ||
| 5980 | }, | ||
| 5981 | }, | ||
| 5659 | }; | 5982 | }; |
| 5660 | 5983 | ||
| 5661 | pub fn getStructType( | 5984 | pub fn getStructType( |
| 5662 | ip: *InternPool, | 5985 | ip: *InternPool, |
| 5663 | gpa: Allocator, | 5986 | gpa: Allocator, |
| 5664 | ini: StructTypeInit, | 5987 | ini: StructTypeInit, |
| 5665 | ) Allocator.Error!Index { | 5988 | ) Allocator.Error!WipNamespaceType.Result { |
| 5666 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 5989 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 5667 | const key: Key = .{ | 5990 | const key: Key = .{ .struct_type = switch (ini.key) { |
| 5668 | .struct_type = .{ | 5991 | .declared => |d| .{ .declared = .{ |
| 5669 | // Only the decl matters for hashing and equality purposes. | 5992 | .zir_index = d.zir_index, |
| 5670 | .decl = ini.decl.toOptional(), | 5993 | .captures = .{ .external = d.captures }, |
| 5671 | 5994 | } }, | |
| 5672 | .extra_index = undefined, | 5995 | .reified => |r| .{ .reified = .{ |
| 5673 | .namespace = undefined, | 5996 | .zir_index = r.zir_index, |
| 5674 | .zir_index = undefined, | 5997 | .type_hash = r.type_hash, |
| 5675 | .layout = undefined, | 5998 | } }, |
| 5676 | .field_names = undefined, | 5999 | } }; |
| 5677 | .field_types = undefined, | ||
| 5678 | .field_inits = undefined, | ||
| 5679 | .field_aligns = undefined, | ||
| 5680 | .runtime_order = undefined, | ||
| 5681 | .comptime_bits = undefined, | ||
| 5682 | .offsets = undefined, | ||
| 5683 | .names_map = undefined, | ||
| 5684 | }, | ||
| 5685 | }; | ||
| 5686 | const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); | 6000 | const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); |
| 5687 | if (gop.found_existing) return @enumFromInt(gop.index); | 6001 | if (gop.found_existing) return .{ .existing = @enumFromInt(gop.index) }; |
| 5688 | errdefer _ = ip.map.pop(); | 6002 | errdefer _ = ip.map.pop(); |
| 5689 | 6003 | ||
| 5690 | const names_map = try ip.addMap(gpa, ini.fields_len); | 6004 | const names_map = try ip.addMap(gpa, ini.fields_len); |
| 5691 | errdefer _ = ip.maps.pop(); | 6005 | errdefer _ = ip.maps.pop(); |
| 5692 | 6006 | ||
| 6007 | const zir_index = switch (ini.key) { | ||
| 6008 | inline else => |x| x.zir_index, | ||
| 6009 | }; | ||
| 6010 | |||
| 5693 | const is_extern = switch (ini.layout) { | 6011 | const is_extern = switch (ini.layout) { |
| 5694 | .Auto => false, | 6012 | .Auto => false, |
| 5695 | .Extern => true, | 6013 | .Extern => true, |
| 5696 | .Packed => { | 6014 | .Packed => { |
| 5697 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStructPacked).Struct.fields.len + | 6015 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStructPacked).Struct.fields.len + |
| 6016 | // TODO: fmt bug | ||
| 6017 | // zig fmt: off | ||
| 6018 | switch (ini.key) { | ||
| 6019 | .declared => |d| @intFromBool(d.captures.len != 0) + d.captures.len, | ||
| 6020 | .reified => 2, // type_hash: PackedU64 | ||
| 6021 | } + | ||
| 6022 | // zig fmt: on | ||
| 5698 | ini.fields_len + // types | 6023 | ini.fields_len + // types |
| 5699 | ini.fields_len + // names | 6024 | ini.fields_len + // names |
| 5700 | ini.fields_len); // inits | 6025 | ini.fields_len); // inits |
| 6026 | const extra_index = ip.addExtraAssumeCapacity(Tag.TypeStructPacked{ | ||
| 6027 | .decl = undefined, // set by `finish` | ||
| 6028 | .zir_index = zir_index, | ||
| 6029 | .fields_len = ini.fields_len, | ||
| 6030 | .namespace = .none, | ||
| 6031 | .backing_int_ty = .none, | ||
| 6032 | .names_map = names_map, | ||
| 6033 | .flags = .{ | ||
| 6034 | .any_captures = ini.key == .declared and ini.key.declared.captures.len != 0, | ||
| 6035 | .field_inits_wip = false, | ||
| 6036 | .inits_resolved = ini.inits_resolved, | ||
| 6037 | .is_reified = ini.key == .reified, | ||
| 6038 | }, | ||
| 6039 | }); | ||
| 5701 | try ip.items.append(gpa, .{ | 6040 | try ip.items.append(gpa, .{ |
| 5702 | .tag = if (ini.any_default_inits) .type_struct_packed_inits else .type_struct_packed, | 6041 | .tag = if (ini.any_default_inits) .type_struct_packed_inits else .type_struct_packed, |
| 5703 | .data = ip.addExtraAssumeCapacity(Tag.TypeStructPacked{ | 6042 | .data = extra_index, |
| 5704 | .decl = ini.decl, | ||
| 5705 | .zir_index = ini.zir_index, | ||
| 5706 | .fields_len = ini.fields_len, | ||
| 5707 | .namespace = ini.namespace, | ||
| 5708 | .backing_int_ty = .none, | ||
| 5709 | .names_map = names_map, | ||
| 5710 | .flags = .{ | ||
| 5711 | .field_inits_wip = false, | ||
| 5712 | .inits_resolved = ini.inits_resolved, | ||
| 5713 | }, | ||
| 5714 | }), | ||
| 5715 | }); | 6043 | }); |
| 6044 | switch (ini.key) { | ||
| 6045 | .declared => |d| if (d.captures.len != 0) { | ||
| 6046 | ip.extra.appendAssumeCapacity(@intCast(d.captures.len)); | ||
| 6047 | ip.extra.appendSliceAssumeCapacity(@ptrCast(d.captures)); | ||
| 6048 | }, | ||
| 6049 | .reified => |r| { | ||
| 6050 | _ = ip.addExtraAssumeCapacity(PackedU64.init(r.type_hash)); | ||
| 6051 | }, | ||
| 6052 | } | ||
| 5716 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); | 6053 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); |
| 5717 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(OptionalNullTerminatedString.none), ini.fields_len); | 6054 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(OptionalNullTerminatedString.none), ini.fields_len); |
| 5718 | if (ini.any_default_inits) { | 6055 | if (ini.any_default_inits) { |
| 5719 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); | 6056 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); |
| 5720 | } | 6057 | } |
| 5721 | return @enumFromInt(ip.items.len - 1); | 6058 | return .{ .wip = .{ |
| 6059 | .index = @enumFromInt(ip.items.len - 1), | ||
| 6060 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "decl").?, | ||
| 6061 | .namespace_extra_index = if (ini.has_namespace) | ||
| 6062 | extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").? | ||
| 6063 | else | ||
| 6064 | null, | ||
| 6065 | } }; | ||
| 5722 | }, | 6066 | }, |
| 5723 | }; | 6067 | }; |
| 5724 | 6068 | ||
| ... | @@ -5727,38 +6071,57 @@ pub fn getStructType( | ... | @@ -5727,38 +6071,57 @@ pub fn getStructType( |
| 5727 | const comptime_elements_len = if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0; | 6071 | const comptime_elements_len = if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0; |
| 5728 | 6072 | ||
| 5729 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStruct).Struct.fields.len + | 6073 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStruct).Struct.fields.len + |
| 6074 | // TODO: fmt bug | ||
| 6075 | // zig fmt: off | ||
| 6076 | switch (ini.key) { | ||
| 6077 | .declared => |d| @intFromBool(d.captures.len != 0) + d.captures.len, | ||
| 6078 | .reified => 2, // type_hash: PackedU64 | ||
| 6079 | } + | ||
| 6080 | // zig fmt: on | ||
| 5730 | (ini.fields_len * 5) + // types, names, inits, runtime order, offsets | 6081 | (ini.fields_len * 5) + // types, names, inits, runtime order, offsets |
| 5731 | align_elements_len + comptime_elements_len + | 6082 | align_elements_len + comptime_elements_len + |
| 5732 | 2); // names_map + namespace | 6083 | 2); // names_map + namespace |
| 6084 | const extra_index = ip.addExtraAssumeCapacity(Tag.TypeStruct{ | ||
| 6085 | .decl = undefined, // set by `finish` | ||
| 6086 | .zir_index = zir_index, | ||
| 6087 | .fields_len = ini.fields_len, | ||
| 6088 | .size = std.math.maxInt(u32), | ||
| 6089 | .flags = .{ | ||
| 6090 | .any_captures = ini.key == .declared and ini.key.declared.captures.len != 0, | ||
| 6091 | .is_extern = is_extern, | ||
| 6092 | .known_non_opv = ini.known_non_opv, | ||
| 6093 | .requires_comptime = ini.requires_comptime, | ||
| 6094 | .is_tuple = ini.is_tuple, | ||
| 6095 | .assumed_runtime_bits = false, | ||
| 6096 | .assumed_pointer_aligned = false, | ||
| 6097 | .has_namespace = ini.has_namespace, | ||
| 6098 | .any_comptime_fields = ini.any_comptime_fields, | ||
| 6099 | .any_default_inits = ini.any_default_inits, | ||
| 6100 | .any_aligned_fields = ini.any_aligned_fields, | ||
| 6101 | .alignment = .none, | ||
| 6102 | .alignment_wip = false, | ||
| 6103 | .field_types_wip = false, | ||
| 6104 | .layout_wip = false, | ||
| 6105 | .layout_resolved = false, | ||
| 6106 | .field_inits_wip = false, | ||
| 6107 | .inits_resolved = ini.inits_resolved, | ||
| 6108 | .fully_resolved = false, | ||
| 6109 | .is_reified = ini.key == .reified, | ||
| 6110 | }, | ||
| 6111 | }); | ||
| 5733 | try ip.items.append(gpa, .{ | 6112 | try ip.items.append(gpa, .{ |
| 5734 | .tag = .type_struct, | 6113 | .tag = .type_struct, |
| 5735 | .data = ip.addExtraAssumeCapacity(Tag.TypeStruct{ | 6114 | .data = extra_index, |
| 5736 | .decl = ini.decl, | ||
| 5737 | .zir_index = ini.zir_index, | ||
| 5738 | .fields_len = ini.fields_len, | ||
| 5739 | .size = std.math.maxInt(u32), | ||
| 5740 | .flags = .{ | ||
| 5741 | .is_extern = is_extern, | ||
| 5742 | .known_non_opv = ini.known_non_opv, | ||
| 5743 | .requires_comptime = ini.requires_comptime, | ||
| 5744 | .is_tuple = ini.is_tuple, | ||
| 5745 | .assumed_runtime_bits = false, | ||
| 5746 | .assumed_pointer_aligned = false, | ||
| 5747 | .has_namespace = ini.namespace != .none, | ||
| 5748 | .any_comptime_fields = ini.any_comptime_fields, | ||
| 5749 | .any_default_inits = ini.any_default_inits, | ||
| 5750 | .any_aligned_fields = ini.any_aligned_fields, | ||
| 5751 | .alignment = .none, | ||
| 5752 | .alignment_wip = false, | ||
| 5753 | .field_types_wip = false, | ||
| 5754 | .layout_wip = false, | ||
| 5755 | .layout_resolved = false, | ||
| 5756 | .field_inits_wip = false, | ||
| 5757 | .inits_resolved = ini.inits_resolved, | ||
| 5758 | .fully_resolved = false, | ||
| 5759 | }, | ||
| 5760 | }), | ||
| 5761 | }); | 6115 | }); |
| 6116 | switch (ini.key) { | ||
| 6117 | .declared => |d| if (d.captures.len != 0) { | ||
| 6118 | ip.extra.appendAssumeCapacity(@intCast(d.captures.len)); | ||
| 6119 | ip.extra.appendSliceAssumeCapacity(@ptrCast(d.captures)); | ||
| 6120 | }, | ||
| 6121 | .reified => |r| { | ||
| 6122 | _ = ip.addExtraAssumeCapacity(PackedU64.init(r.type_hash)); | ||
| 6123 | }, | ||
| 6124 | } | ||
| 5762 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); | 6125 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); |
| 5763 | if (!ini.is_tuple) { | 6126 | if (!ini.is_tuple) { |
| 5764 | ip.extra.appendAssumeCapacity(@intFromEnum(names_map)); | 6127 | ip.extra.appendAssumeCapacity(@intFromEnum(names_map)); |
| ... | @@ -5767,9 +6130,10 @@ pub fn getStructType( | ... | @@ -5767,9 +6130,10 @@ pub fn getStructType( |
| 5767 | if (ini.any_default_inits) { | 6130 | if (ini.any_default_inits) { |
| 5768 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); | 6131 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len); |
| 5769 | } | 6132 | } |
| 5770 | if (ini.namespace.unwrap()) |namespace| { | 6133 | const namespace_extra_index: ?u32 = if (ini.has_namespace) i: { |
| 5771 | ip.extra.appendAssumeCapacity(@intFromEnum(namespace)); | 6134 | ip.extra.appendAssumeCapacity(undefined); // set by `finish` |
| 5772 | } | 6135 | break :i @intCast(ip.extra.items.len - 1); |
| 6136 | } else null; | ||
| 5773 | if (ini.any_aligned_fields) { | 6137 | if (ini.any_aligned_fields) { |
| 5774 | ip.extra.appendNTimesAssumeCapacity(align_element, align_elements_len); | 6138 | ip.extra.appendNTimesAssumeCapacity(align_element, align_elements_len); |
| 5775 | } | 6139 | } |
| ... | @@ -5777,10 +6141,14 @@ pub fn getStructType( | ... | @@ -5777,10 +6141,14 @@ pub fn getStructType( |
| 5777 | ip.extra.appendNTimesAssumeCapacity(0, comptime_elements_len); | 6141 | ip.extra.appendNTimesAssumeCapacity(0, comptime_elements_len); |
| 5778 | } | 6142 | } |
| 5779 | if (ini.layout == .Auto) { | 6143 | if (ini.layout == .Auto) { |
| 5780 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Key.StructType.RuntimeOrder.unresolved), ini.fields_len); | 6144 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(LoadedStructType.RuntimeOrder.unresolved), ini.fields_len); |
| 5781 | } | 6145 | } |
| 5782 | ip.extra.appendNTimesAssumeCapacity(std.math.maxInt(u32), ini.fields_len); | 6146 | ip.extra.appendNTimesAssumeCapacity(std.math.maxInt(u32), ini.fields_len); |
| 5783 | return @enumFromInt(ip.items.len - 1); | 6147 | return .{ .wip = .{ |
| 6148 | .index = @enumFromInt(ip.items.len - 1), | ||
| 6149 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "decl").?, | ||
| 6150 | .namespace_extra_index = namespace_extra_index, | ||
| 6151 | } }; | ||
| 5784 | } | 6152 | } |
| 5785 | 6153 | ||
| 5786 | pub const AnonStructTypeInit = struct { | 6154 | pub const AnonStructTypeInit = struct { |
| ... | @@ -6395,7 +6763,6 @@ fn finishFuncInstance( | ... | @@ -6395,7 +6763,6 @@ fn finishFuncInstance( |
| 6395 | .@"addrspace" = fn_owner_decl.@"addrspace", | 6763 | .@"addrspace" = fn_owner_decl.@"addrspace", |
| 6396 | .analysis = .complete, | 6764 | .analysis = .complete, |
| 6397 | .zir_decl_index = fn_owner_decl.zir_decl_index, | 6765 | .zir_decl_index = fn_owner_decl.zir_decl_index, |
| 6398 | .src_scope = fn_owner_decl.src_scope, | ||
| 6399 | .is_pub = fn_owner_decl.is_pub, | 6766 | .is_pub = fn_owner_decl.is_pub, |
| 6400 | .is_exported = fn_owner_decl.is_exported, | 6767 | .is_exported = fn_owner_decl.is_exported, |
| 6401 | .alive = true, | 6768 | .alive = true, |
| ... | @@ -6417,257 +6784,386 @@ fn finishFuncInstance( | ... | @@ -6417,257 +6784,386 @@ fn finishFuncInstance( |
| 6417 | return func_index; | 6784 | return func_index; |
| 6418 | } | 6785 | } |
| 6419 | 6786 | ||
| 6420 | /// Provides API for completing an enum type after calling `getIncompleteEnum`. | 6787 | pub const EnumTypeInit = struct { |
| 6421 | pub const IncompleteEnumType = struct { | 6788 | has_namespace: bool, |
| 6789 | has_values: bool, | ||
| 6790 | tag_mode: LoadedEnumType.TagMode, | ||
| 6791 | fields_len: u32, | ||
| 6792 | key: union(enum) { | ||
| 6793 | declared: struct { | ||
| 6794 | zir_index: TrackedInst.Index, | ||
| 6795 | captures: []const CaptureValue, | ||
| 6796 | }, | ||
| 6797 | reified: struct { | ||
| 6798 | zir_index: TrackedInst.Index, | ||
| 6799 | type_hash: u64, | ||
| 6800 | }, | ||
| 6801 | }, | ||
| 6802 | }; | ||
| 6803 | |||
| 6804 | pub const WipEnumType = struct { | ||
| 6422 | index: Index, | 6805 | index: Index, |
| 6423 | tag_ty_index: u32, | 6806 | tag_ty_index: u32, |
| 6807 | decl_index: u32, | ||
| 6808 | namespace_index: ?u32, | ||
| 6424 | names_map: MapIndex, | 6809 | names_map: MapIndex, |
| 6425 | names_start: u32, | 6810 | names_start: u32, |
| 6426 | values_map: OptionalMapIndex, | 6811 | values_map: OptionalMapIndex, |
| 6427 | values_start: u32, | 6812 | values_start: u32, |
| 6428 | 6813 | ||
| 6429 | pub fn setTagType(self: @This(), ip: *InternPool, tag_ty: Index) void { | 6814 | pub fn prepare( |
| 6430 | assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty)); | 6815 | wip: WipEnumType, |
| 6431 | ip.extra.items[self.tag_ty_index] = @intFromEnum(tag_ty); | 6816 | ip: *InternPool, |
| 6817 | decl: DeclIndex, | ||
| 6818 | namespace: OptionalNamespaceIndex, | ||
| 6819 | ) void { | ||
| 6820 | ip.extra.items[wip.decl_index] = @intFromEnum(decl); | ||
| 6821 | if (wip.namespace_index) |i| { | ||
| 6822 | ip.extra.items[i] = @intFromEnum(namespace.unwrap().?); | ||
| 6823 | } else { | ||
| 6824 | assert(namespace == .none); | ||
| 6825 | } | ||
| 6432 | } | 6826 | } |
| 6433 | 6827 | ||
| 6434 | /// Returns the already-existing field with the same name, if any. | 6828 | pub fn setTagTy(wip: WipEnumType, ip: *InternPool, tag_ty: Index) void { |
| 6435 | pub fn addFieldName( | 6829 | assert(ip.isIntegerType(tag_ty)); |
| 6436 | self: @This(), | 6830 | ip.extra.items[wip.tag_ty_index] = @intFromEnum(tag_ty); |
| 6437 | ip: *InternPool, | ||
| 6438 | name: NullTerminatedString, | ||
| 6439 | ) ?u32 { | ||
| 6440 | return ip.addFieldName(self.names_map, self.names_start, name); | ||
| 6441 | } | 6831 | } |
| 6442 | 6832 | ||
| 6443 | /// Returns the already-existing field with the same value, if any. | 6833 | pub const FieldConflict = struct { |
| 6444 | /// Make sure the type of the value has the integer tag type of the enum. | 6834 | kind: enum { name, value }, |
| 6445 | pub fn addFieldValue( | 6835 | prev_field_idx: u32, |
| 6446 | self: @This(), | 6836 | }; |
| 6447 | ip: *InternPool, | 6837 | |
| 6448 | value: Index, | 6838 | /// Returns the already-existing field with the same name or value, if any. |
| 6449 | ) ?u32 { | 6839 | /// If the enum is automatially numbered, `value` must be `.none`. |
| 6450 | assert(ip.typeOf(value) == @as(Index, @enumFromInt(ip.extra.items[self.tag_ty_index]))); | 6840 | /// Otherwise, the type of `value` must be the integer tag type of the enum. |
| 6451 | const map = &ip.maps.items[@intFromEnum(self.values_map.unwrap().?)]; | 6841 | pub fn nextField(wip: WipEnumType, ip: *InternPool, name: NullTerminatedString, value: Index) ?FieldConflict { |
| 6842 | if (ip.addFieldName(wip.names_map, wip.names_start, name)) |conflict| { | ||
| 6843 | return .{ .kind = .name, .prev_field_idx = conflict }; | ||
| 6844 | } | ||
| 6845 | if (value == .none) { | ||
| 6846 | assert(wip.values_map == .none); | ||
| 6847 | return null; | ||
| 6848 | } | ||
| 6849 | assert(ip.typeOf(value) == @as(Index, @enumFromInt(ip.extra.items[wip.tag_ty_index]))); | ||
| 6850 | const map = &ip.maps.items[@intFromEnum(wip.values_map.unwrap().?)]; | ||
| 6452 | const field_index = map.count(); | 6851 | const field_index = map.count(); |
| 6453 | const indexes = ip.extra.items[self.values_start..][0..field_index]; | 6852 | const indexes = ip.extra.items[wip.values_start..][0..field_index]; |
| 6454 | const adapter: Index.Adapter = .{ .indexes = @ptrCast(indexes) }; | 6853 | const adapter: Index.Adapter = .{ .indexes = @ptrCast(indexes) }; |
| 6455 | const gop = map.getOrPutAssumeCapacityAdapted(value, adapter); | 6854 | const gop = map.getOrPutAssumeCapacityAdapted(value, adapter); |
| 6456 | if (gop.found_existing) return @intCast(gop.index); | 6855 | if (gop.found_existing) { |
| 6457 | ip.extra.items[self.values_start + field_index] = @intFromEnum(value); | 6856 | return .{ .kind = .value, .prev_field_idx = @intCast(gop.index) }; |
| 6857 | } | ||
| 6858 | ip.extra.items[wip.values_start + field_index] = @intFromEnum(value); | ||
| 6458 | return null; | 6859 | return null; |
| 6459 | } | 6860 | } |
| 6460 | }; | ||
| 6461 | 6861 | ||
| 6462 | /// This is used to create an enum type in the `InternPool`, with the ability | 6862 | pub fn cancel(wip: WipEnumType, ip: *InternPool) void { |
| 6463 | /// to update the tag type, field names, and field values later. | 6863 | ip.remove(wip.index); |
| 6464 | pub fn getIncompleteEnum( | ||
| 6465 | ip: *InternPool, | ||
| 6466 | gpa: Allocator, | ||
| 6467 | enum_type: Key.IncompleteEnumType, | ||
| 6468 | ) Allocator.Error!IncompleteEnumType { | ||
| 6469 | switch (enum_type.tag_mode) { | ||
| 6470 | .auto => return getIncompleteEnumAuto(ip, gpa, enum_type), | ||
| 6471 | .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit), | ||
| 6472 | .nonexhaustive => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_nonexhaustive), | ||
| 6473 | } | 6864 | } |
| 6474 | } | ||
| 6475 | |||
| 6476 | fn getIncompleteEnumAuto( | ||
| 6477 | ip: *InternPool, | ||
| 6478 | gpa: Allocator, | ||
| 6479 | enum_type: Key.IncompleteEnumType, | ||
| 6480 | ) Allocator.Error!IncompleteEnumType { | ||
| 6481 | const int_tag_type = if (enum_type.tag_ty != .none) | ||
| 6482 | enum_type.tag_ty | ||
| 6483 | else | ||
| 6484 | try ip.get(gpa, .{ .int_type = .{ | ||
| 6485 | .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len), | ||
| 6486 | .signedness = .unsigned, | ||
| 6487 | } }); | ||
| 6488 | |||
| 6489 | // We must keep the map in sync with `items`. The hash and equality functions | ||
| 6490 | // for enum types only look at the decl field, which is present even in | ||
| 6491 | // an `IncompleteEnumType`. | ||
| 6492 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 6493 | const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter); | ||
| 6494 | assert(!gop.found_existing); | ||
| 6495 | |||
| 6496 | const names_map = try ip.addMap(gpa, enum_type.fields_len); | ||
| 6497 | |||
| 6498 | const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len; | ||
| 6499 | try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len); | ||
| 6500 | try ip.items.ensureUnusedCapacity(gpa, 1); | ||
| 6501 | |||
| 6502 | const extra_index = ip.addExtraAssumeCapacity(EnumAuto{ | ||
| 6503 | .decl = enum_type.decl, | ||
| 6504 | .namespace = enum_type.namespace, | ||
| 6505 | .int_tag_type = int_tag_type, | ||
| 6506 | .names_map = names_map, | ||
| 6507 | .fields_len = enum_type.fields_len, | ||
| 6508 | .zir_index = enum_type.zir_index, | ||
| 6509 | }); | ||
| 6510 | 6865 | ||
| 6511 | ip.items.appendAssumeCapacity(.{ | 6866 | pub const Result = union(enum) { |
| 6512 | .tag = .type_enum_auto, | 6867 | wip: WipEnumType, |
| 6513 | .data = extra_index, | 6868 | existing: Index, |
| 6514 | }); | ||
| 6515 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), enum_type.fields_len); | ||
| 6516 | return .{ | ||
| 6517 | .index = @enumFromInt(ip.items.len - 1), | ||
| 6518 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?, | ||
| 6519 | .names_map = names_map, | ||
| 6520 | .names_start = extra_index + extra_fields_len, | ||
| 6521 | .values_map = .none, | ||
| 6522 | .values_start = undefined, | ||
| 6523 | }; | 6869 | }; |
| 6524 | } | 6870 | }; |
| 6525 | 6871 | ||
| 6526 | fn getIncompleteEnumExplicit( | 6872 | pub fn getEnumType( |
| 6527 | ip: *InternPool, | 6873 | ip: *InternPool, |
| 6528 | gpa: Allocator, | 6874 | gpa: Allocator, |
| 6529 | enum_type: Key.IncompleteEnumType, | 6875 | ini: EnumTypeInit, |
| 6530 | tag: Tag, | 6876 | ) Allocator.Error!WipEnumType.Result { |
| 6531 | ) Allocator.Error!IncompleteEnumType { | ||
| 6532 | // We must keep the map in sync with `items`. The hash and equality functions | ||
| 6533 | // for enum types only look at the decl field, which is present even in | ||
| 6534 | // an `IncompleteEnumType`. | ||
| 6535 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 6877 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 6536 | const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter); | 6878 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ .enum_type = switch (ini.key) { |
| 6537 | assert(!gop.found_existing); | 6879 | .declared => |d| .{ .declared = .{ |
| 6538 | 6880 | .zir_index = d.zir_index, | |
| 6539 | const names_map = try ip.addMap(gpa, enum_type.fields_len); | 6881 | .captures = .{ .external = d.captures }, |
| 6540 | const values_map: OptionalMapIndex = if (!enum_type.has_values) .none else m: { | 6882 | } }, |
| 6541 | const values_map = try ip.addMap(gpa, enum_type.fields_len); | 6883 | .reified => |r| .{ .reified = .{ |
| 6542 | break :m values_map.toOptional(); | 6884 | .zir_index = r.zir_index, |
| 6543 | }; | 6885 | .type_hash = r.type_hash, |
| 6544 | 6886 | } }, | |
| 6545 | const reserved_len = enum_type.fields_len + | 6887 | } }, adapter); |
| 6546 | if (enum_type.has_values) enum_type.fields_len else 0; | 6888 | if (gop.found_existing) return .{ .existing = @enumFromInt(gop.index) }; |
| 6889 | assert(gop.index == ip.items.len); | ||
| 6890 | errdefer _ = ip.map.pop(); | ||
| 6547 | 6891 | ||
| 6548 | const extra_fields_len: u32 = @typeInfo(EnumExplicit).Struct.fields.len; | ||
| 6549 | try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + reserved_len); | ||
| 6550 | try ip.items.ensureUnusedCapacity(gpa, 1); | 6892 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 6551 | 6893 | ||
| 6552 | const extra_index = ip.addExtraAssumeCapacity(EnumExplicit{ | 6894 | const names_map = try ip.addMap(gpa, ini.fields_len); |
| 6553 | .decl = enum_type.decl, | 6895 | errdefer _ = ip.maps.pop(); |
| 6554 | .namespace = enum_type.namespace, | ||
| 6555 | .int_tag_type = enum_type.tag_ty, | ||
| 6556 | .fields_len = enum_type.fields_len, | ||
| 6557 | .names_map = names_map, | ||
| 6558 | .values_map = values_map, | ||
| 6559 | .zir_index = enum_type.zir_index, | ||
| 6560 | }); | ||
| 6561 | 6896 | ||
| 6562 | ip.items.appendAssumeCapacity(.{ | 6897 | switch (ini.tag_mode) { |
| 6563 | .tag = tag, | 6898 | .auto => { |
| 6564 | .data = extra_index, | 6899 | assert(!ini.has_values); |
| 6565 | }); | 6900 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len + |
| 6566 | // This is both fields and values (if present). | 6901 | // TODO: fmt bug |
| 6567 | ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), reserved_len); | 6902 | // zig fmt: off |
| 6568 | return .{ | 6903 | switch (ini.key) { |
| 6569 | .index = @enumFromInt(ip.items.len - 1), | 6904 | .declared => |d| d.captures.len, |
| 6570 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?, | 6905 | .reified => 2, // type_hash: PackedU64 |
| 6571 | .names_map = names_map, | 6906 | } + |
| 6572 | .names_start = extra_index + extra_fields_len, | 6907 | // zig fmt: on |
| 6573 | .values_map = values_map, | 6908 | ini.fields_len); // field types |
| 6574 | .values_start = extra_index + extra_fields_len + enum_type.fields_len, | 6909 | |
| 6575 | }; | 6910 | const extra_index = ip.addExtraAssumeCapacity(EnumAuto{ |
| 6911 | .decl = undefined, // set by `prepare` | ||
| 6912 | .captures_len = switch (ini.key) { | ||
| 6913 | .declared => |d| @intCast(d.captures.len), | ||
| 6914 | .reified => std.math.maxInt(u32), | ||
| 6915 | }, | ||
| 6916 | .namespace = .none, | ||
| 6917 | .int_tag_type = .none, // set by `prepare` | ||
| 6918 | .fields_len = ini.fields_len, | ||
| 6919 | .names_map = names_map, | ||
| 6920 | .zir_index = switch (ini.key) { | ||
| 6921 | inline else => |x| x.zir_index, | ||
| 6922 | }.toOptional(), | ||
| 6923 | }); | ||
| 6924 | ip.items.appendAssumeCapacity(.{ | ||
| 6925 | .tag = .type_enum_auto, | ||
| 6926 | .data = extra_index, | ||
| 6927 | }); | ||
| 6928 | switch (ini.key) { | ||
| 6929 | .declared => |d| ip.extra.appendSliceAssumeCapacity(@ptrCast(d.captures)), | ||
| 6930 | .reified => |r| _ = ip.addExtraAssumeCapacity(PackedU64.init(r.type_hash)), | ||
| 6931 | } | ||
| 6932 | const names_start = ip.extra.items.len; | ||
| 6933 | ip.extra.appendNTimesAssumeCapacity(undefined, ini.fields_len); | ||
| 6934 | return .{ .wip = .{ | ||
| 6935 | .index = @enumFromInt(gop.index), | ||
| 6936 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?, | ||
| 6937 | .decl_index = extra_index + std.meta.fieldIndex(EnumAuto, "decl").?, | ||
| 6938 | .namespace_index = if (ini.has_namespace) extra_index + std.meta.fieldIndex(EnumAuto, "namespace").? else null, | ||
| 6939 | .names_map = names_map, | ||
| 6940 | .names_start = @intCast(names_start), | ||
| 6941 | .values_map = .none, | ||
| 6942 | .values_start = undefined, | ||
| 6943 | } }; | ||
| 6944 | }, | ||
| 6945 | .explicit, .nonexhaustive => { | ||
| 6946 | const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: { | ||
| 6947 | const values_map = try ip.addMap(gpa, ini.fields_len); | ||
| 6948 | break :m values_map.toOptional(); | ||
| 6949 | }; | ||
| 6950 | errdefer if (ini.has_values) { | ||
| 6951 | _ = ip.map.pop(); | ||
| 6952 | }; | ||
| 6953 | |||
| 6954 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len + | ||
| 6955 | // TODO: fmt bug | ||
| 6956 | // zig fmt: off | ||
| 6957 | switch (ini.key) { | ||
| 6958 | .declared => |d| d.captures.len, | ||
| 6959 | .reified => 2, // type_hash: PackedU64 | ||
| 6960 | } + | ||
| 6961 | // zig fmt: on | ||
| 6962 | ini.fields_len + // field types | ||
| 6963 | ini.fields_len * @intFromBool(ini.has_values)); // field values | ||
| 6964 | |||
| 6965 | const extra_index = ip.addExtraAssumeCapacity(EnumExplicit{ | ||
| 6966 | .decl = undefined, // set by `prepare` | ||
| 6967 | .captures_len = switch (ini.key) { | ||
| 6968 | .declared => |d| @intCast(d.captures.len), | ||
| 6969 | .reified => std.math.maxInt(u32), | ||
| 6970 | }, | ||
| 6971 | .namespace = .none, | ||
| 6972 | .int_tag_type = .none, // set by `prepare` | ||
| 6973 | .fields_len = ini.fields_len, | ||
| 6974 | .names_map = names_map, | ||
| 6975 | .values_map = values_map, | ||
| 6976 | .zir_index = switch (ini.key) { | ||
| 6977 | inline else => |x| x.zir_index, | ||
| 6978 | }.toOptional(), | ||
| 6979 | }); | ||
| 6980 | ip.items.appendAssumeCapacity(.{ | ||
| 6981 | .tag = switch (ini.tag_mode) { | ||
| 6982 | .auto => unreachable, | ||
| 6983 | .explicit => .type_enum_explicit, | ||
| 6984 | .nonexhaustive => .type_enum_nonexhaustive, | ||
| 6985 | }, | ||
| 6986 | .data = extra_index, | ||
| 6987 | }); | ||
| 6988 | switch (ini.key) { | ||
| 6989 | .declared => |d| ip.extra.appendSliceAssumeCapacity(@ptrCast(d.captures)), | ||
| 6990 | .reified => |r| _ = ip.addExtraAssumeCapacity(PackedU64.init(r.type_hash)), | ||
| 6991 | } | ||
| 6992 | const names_start = ip.extra.items.len; | ||
| 6993 | ip.extra.appendNTimesAssumeCapacity(undefined, ini.fields_len); | ||
| 6994 | const values_start = ip.extra.items.len; | ||
| 6995 | if (ini.has_values) { | ||
| 6996 | ip.extra.appendNTimesAssumeCapacity(undefined, ini.fields_len); | ||
| 6997 | } | ||
| 6998 | return .{ .wip = .{ | ||
| 6999 | .index = @enumFromInt(gop.index), | ||
| 7000 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?, | ||
| 7001 | .decl_index = extra_index + std.meta.fieldIndex(EnumAuto, "decl").?, | ||
| 7002 | .namespace_index = if (ini.has_namespace) extra_index + std.meta.fieldIndex(EnumAuto, "namespace").? else null, | ||
| 7003 | .names_map = names_map, | ||
| 7004 | .names_start = @intCast(names_start), | ||
| 7005 | .values_map = values_map, | ||
| 7006 | .values_start = @intCast(values_start), | ||
| 7007 | } }; | ||
| 7008 | }, | ||
| 7009 | } | ||
| 6576 | } | 7010 | } |
| 6577 | 7011 | ||
| 6578 | pub const GetEnumInit = struct { | 7012 | const GeneratedTagEnumTypeInit = struct { |
| 6579 | decl: DeclIndex, | 7013 | decl: DeclIndex, |
| 6580 | namespace: OptionalNamespaceIndex, | 7014 | owner_union_ty: Index, |
| 6581 | tag_ty: Index, | 7015 | tag_ty: Index, |
| 6582 | names: []const NullTerminatedString, | 7016 | names: []const NullTerminatedString, |
| 6583 | values: []const Index, | 7017 | values: []const Index, |
| 6584 | tag_mode: Key.EnumType.TagMode, | 7018 | tag_mode: LoadedEnumType.TagMode, |
| 6585 | zir_index: TrackedInst.Index.Optional, | ||
| 6586 | }; | 7019 | }; |
| 6587 | 7020 | ||
| 6588 | pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index { | 7021 | /// Creates an enum type which was automatically-generated as the tag type of a |
| 6589 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 7022 | /// `union` with no explicit tag type. Since this is only called once per union |
| 6590 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ | 7023 | /// type, it asserts that no matching type yet exists. |
| 6591 | .enum_type = .{ | 7024 | pub fn getGeneratedTagEnumType(ip: *InternPool, gpa: Allocator, ini: GeneratedTagEnumTypeInit) Allocator.Error!Index { |
| 6592 | // Only the decl is used for hashing and equality. | 7025 | assert(ip.isUnion(ini.owner_union_ty)); |
| 6593 | .decl = ini.decl, | 7026 | assert(ip.isIntegerType(ini.tag_ty)); |
| 6594 | 7027 | for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty); | |
| 6595 | .namespace = undefined, | 7028 | |
| 6596 | .tag_ty = undefined, | 7029 | try ip.map.ensureUnusedCapacity(gpa, 1); |
| 6597 | .names = undefined, | ||
| 6598 | .values = undefined, | ||
| 6599 | .tag_mode = undefined, | ||
| 6600 | .names_map = undefined, | ||
| 6601 | .values_map = undefined, | ||
| 6602 | .zir_index = undefined, | ||
| 6603 | }, | ||
| 6604 | }, adapter); | ||
| 6605 | if (gop.found_existing) return @enumFromInt(gop.index); | ||
| 6606 | errdefer _ = ip.map.pop(); | ||
| 6607 | try ip.items.ensureUnusedCapacity(gpa, 1); | 7030 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 6608 | 7031 | ||
| 6609 | assert(ini.tag_ty == .noreturn_type or ip.isIntegerType(ini.tag_ty)); | 7032 | const names_map = try ip.addMap(gpa, ini.names.len); |
| 6610 | for (ini.values) |value| assert(ip.typeOf(value) == ini.tag_ty); | 7033 | errdefer _ = ip.maps.pop(); |
| 7034 | ip.addStringsToMap(names_map, ini.names); | ||
| 7035 | |||
| 7036 | const fields_len: u32 = @intCast(ini.names.len); | ||
| 6611 | 7037 | ||
| 6612 | switch (ini.tag_mode) { | 7038 | switch (ini.tag_mode) { |
| 6613 | .auto => { | 7039 | .auto => { |
| 6614 | const names_map = try ip.addMap(gpa, ini.names.len); | ||
| 6615 | addStringsToMap(ip, names_map, ini.names); | ||
| 6616 | |||
| 6617 | const fields_len: u32 = @intCast(ini.names.len); | ||
| 6618 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len + | 7040 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len + |
| 6619 | fields_len); | 7041 | 1 + // owner_union |
| 7042 | fields_len); // field names | ||
| 6620 | ip.items.appendAssumeCapacity(.{ | 7043 | ip.items.appendAssumeCapacity(.{ |
| 6621 | .tag = .type_enum_auto, | 7044 | .tag = .type_enum_auto, |
| 6622 | .data = ip.addExtraAssumeCapacity(EnumAuto{ | 7045 | .data = ip.addExtraAssumeCapacity(EnumAuto{ |
| 6623 | .decl = ini.decl, | 7046 | .decl = ini.decl, |
| 6624 | .namespace = ini.namespace, | 7047 | .captures_len = 0, |
| 7048 | .namespace = .none, | ||
| 6625 | .int_tag_type = ini.tag_ty, | 7049 | .int_tag_type = ini.tag_ty, |
| 7050 | .fields_len = fields_len, | ||
| 6626 | .names_map = names_map, | 7051 | .names_map = names_map, |
| 7052 | .zir_index = .none, | ||
| 7053 | }), | ||
| 7054 | }); | ||
| 7055 | ip.extra.appendAssumeCapacity(@intFromEnum(ini.owner_union_ty)); | ||
| 7056 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); | ||
| 7057 | }, | ||
| 7058 | .explicit, .nonexhaustive => { | ||
| 7059 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len + | ||
| 7060 | 1 + // owner_union | ||
| 7061 | fields_len + // field names | ||
| 7062 | ini.values.len); // field values | ||
| 7063 | |||
| 7064 | const values_map: OptionalMapIndex = if (ini.values.len != 0) m: { | ||
| 7065 | const map = try ip.addMap(gpa, ini.values.len); | ||
| 7066 | addIndexesToMap(ip, map, ini.values); | ||
| 7067 | break :m map.toOptional(); | ||
| 7068 | } else .none; | ||
| 7069 | // We don't clean up the values map on error! | ||
| 7070 | errdefer @compileError("error path leaks values_map"); | ||
| 7071 | |||
| 7072 | ip.items.appendAssumeCapacity(.{ | ||
| 7073 | .tag = switch (ini.tag_mode) { | ||
| 7074 | .explicit => .type_enum_explicit, | ||
| 7075 | .nonexhaustive => .type_enum_nonexhaustive, | ||
| 7076 | .auto => unreachable, | ||
| 7077 | }, | ||
| 7078 | .data = ip.addExtraAssumeCapacity(EnumExplicit{ | ||
| 7079 | .decl = ini.decl, | ||
| 7080 | .captures_len = 0, | ||
| 7081 | .namespace = .none, | ||
| 7082 | .int_tag_type = ini.tag_ty, | ||
| 6627 | .fields_len = fields_len, | 7083 | .fields_len = fields_len, |
| 6628 | .zir_index = ini.zir_index, | 7084 | .names_map = names_map, |
| 7085 | .values_map = values_map, | ||
| 7086 | .zir_index = .none, | ||
| 6629 | }), | 7087 | }), |
| 6630 | }); | 7088 | }); |
| 7089 | ip.extra.appendAssumeCapacity(@intFromEnum(ini.owner_union_ty)); | ||
| 6631 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); | 7090 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); |
| 6632 | return @enumFromInt(ip.items.len - 1); | 7091 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values)); |
| 6633 | }, | 7092 | }, |
| 6634 | .explicit => return finishGetEnum(ip, gpa, ini, .type_enum_explicit), | ||
| 6635 | .nonexhaustive => return finishGetEnum(ip, gpa, ini, .type_enum_nonexhaustive), | ||
| 6636 | } | 7093 | } |
| 7094 | // Same as above | ||
| 7095 | errdefer @compileError("error path leaks values_map and extra data"); | ||
| 7096 | |||
| 7097 | // Capacity for this was ensured earlier | ||
| 7098 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 7099 | const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{ .enum_type = .{ | ||
| 7100 | .generated_tag = .{ .union_type = ini.owner_union_ty }, | ||
| 7101 | } }, adapter); | ||
| 7102 | assert(!gop.found_existing); | ||
| 7103 | assert(gop.index == ip.items.len - 1); | ||
| 7104 | return @enumFromInt(gop.index); | ||
| 6637 | } | 7105 | } |
| 6638 | 7106 | ||
| 6639 | pub fn finishGetEnum( | 7107 | pub const OpaqueTypeIni = struct { |
| 6640 | ip: *InternPool, | 7108 | has_namespace: bool, |
| 6641 | gpa: Allocator, | 7109 | key: union(enum) { |
| 6642 | ini: GetEnumInit, | 7110 | declared: struct { |
| 6643 | tag: Tag, | 7111 | zir_index: TrackedInst.Index, |
| 6644 | ) Allocator.Error!Index { | 7112 | captures: []const CaptureValue, |
| 6645 | const names_map = try ip.addMap(gpa, ini.names.len); | 7113 | }, |
| 6646 | addStringsToMap(ip, names_map, ini.names); | 7114 | reified: struct { |
| 7115 | zir_index: TrackedInst.Index, | ||
| 7116 | // No type hash since reifid opaques have no data other than the `@Type` location | ||
| 7117 | }, | ||
| 7118 | }, | ||
| 7119 | }; | ||
| 6647 | 7120 | ||
| 6648 | const values_map: OptionalMapIndex = if (ini.values.len == 0) .none else m: { | 7121 | pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, ini: OpaqueTypeIni) Allocator.Error!WipNamespaceType.Result { |
| 6649 | const values_map = try ip.addMap(gpa, ini.values.len); | 7122 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 6650 | addIndexesToMap(ip, values_map, ini.values); | 7123 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ .opaque_type = switch (ini.key) { |
| 6651 | break :m values_map.toOptional(); | 7124 | .declared => |d| .{ .declared = .{ |
| 6652 | }; | 7125 | .zir_index = d.zir_index, |
| 6653 | const fields_len: u32 = @intCast(ini.names.len); | 7126 | .captures = .{ .external = d.captures }, |
| 6654 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len + | 7127 | } }, |
| 6655 | fields_len); | 7128 | .reified => |r| .{ .reified = .{ |
| 7129 | .zir_index = r.zir_index, | ||
| 7130 | .type_hash = 0, | ||
| 7131 | } }, | ||
| 7132 | } }, adapter); | ||
| 7133 | if (gop.found_existing) return .{ .existing = @enumFromInt(gop.index) }; | ||
| 7134 | errdefer _ = ip.map.pop(); | ||
| 7135 | try ip.items.ensureUnusedCapacity(gpa, 1); | ||
| 7136 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeOpaque).Struct.fields.len + switch (ini.key) { | ||
| 7137 | .declared => |d| d.captures.len, | ||
| 7138 | .reified => 0, | ||
| 7139 | }); | ||
| 7140 | const extra_index = ip.addExtraAssumeCapacity(Tag.TypeOpaque{ | ||
| 7141 | .decl = undefined, // set by `finish` | ||
| 7142 | .namespace = .none, | ||
| 7143 | .zir_index = switch (ini.key) { | ||
| 7144 | inline else => |x| x.zir_index, | ||
| 7145 | }, | ||
| 7146 | .captures_len = switch (ini.key) { | ||
| 7147 | .declared => |d| @intCast(d.captures.len), | ||
| 7148 | .reified => std.math.maxInt(u32), | ||
| 7149 | }, | ||
| 7150 | }); | ||
| 6656 | ip.items.appendAssumeCapacity(.{ | 7151 | ip.items.appendAssumeCapacity(.{ |
| 6657 | .tag = tag, | 7152 | .tag = .type_opaque, |
| 6658 | .data = ip.addExtraAssumeCapacity(EnumExplicit{ | 7153 | .data = extra_index, |
| 6659 | .decl = ini.decl, | ||
| 6660 | .namespace = ini.namespace, | ||
| 6661 | .int_tag_type = ini.tag_ty, | ||
| 6662 | .fields_len = fields_len, | ||
| 6663 | .names_map = names_map, | ||
| 6664 | .values_map = values_map, | ||
| 6665 | .zir_index = ini.zir_index, | ||
| 6666 | }), | ||
| 6667 | }); | 7154 | }); |
| 6668 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); | 7155 | switch (ini.key) { |
| 6669 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values)); | 7156 | .declared => |d| ip.extra.appendSliceAssumeCapacity(@ptrCast(d.captures)), |
| 6670 | return @enumFromInt(ip.items.len - 1); | 7157 | .reified => {}, |
| 7158 | } | ||
| 7159 | return .{ .wip = .{ | ||
| 7160 | .index = @enumFromInt(gop.index), | ||
| 7161 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "decl").?, | ||
| 7162 | .namespace_extra_index = if (ini.has_namespace) | ||
| 7163 | extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").? | ||
| 7164 | else | ||
| 7165 | null, | ||
| 7166 | } }; | ||
| 6671 | } | 7167 | } |
| 6672 | 7168 | ||
| 6673 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { | 7169 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { |
| ... | @@ -6716,8 +7212,34 @@ fn addMap(ip: *InternPool, gpa: Allocator, cap: usize) Allocator.Error!MapIndex | ... | @@ -6716,8 +7212,34 @@ fn addMap(ip: *InternPool, gpa: Allocator, cap: usize) Allocator.Error!MapIndex |
| 6716 | 7212 | ||
| 6717 | /// This operation only happens under compile error conditions. | 7213 | /// This operation only happens under compile error conditions. |
| 6718 | /// Leak the index until the next garbage collection. | 7214 | /// Leak the index until the next garbage collection. |
| 6719 | /// TODO: this is a bit problematic to implement, can we get away without it? | 7215 | /// Invalidates all references to this index. |
| 6720 | pub const remove = @compileError("InternPool.remove is not currently a supported operation; put a TODO there instead"); | 7216 | pub fn remove(ip: *InternPool, index: Index) void { |
| 7217 | if (@intFromEnum(index) < static_keys.len) { | ||
| 7218 | // The item being removed replaced a special index via `InternPool.resolveBuiltinType`. | ||
| 7219 | // Restore the original item at this index. | ||
| 7220 | switch (static_keys[@intFromEnum(index)]) { | ||
| 7221 | .simple_type => |s| { | ||
| 7222 | ip.items.set(@intFromEnum(index), .{ | ||
| 7223 | .tag = .simple_type, | ||
| 7224 | .data = @intFromEnum(s), | ||
| 7225 | }); | ||
| 7226 | }, | ||
| 7227 | else => unreachable, | ||
| 7228 | } | ||
| 7229 | return; | ||
| 7230 | } | ||
| 7231 | |||
| 7232 | if (@intFromEnum(index) == ip.items.len - 1) { | ||
| 7233 | // Happy case - we can just drop the item without affecting any other indices. | ||
| 7234 | ip.items.len -= 1; | ||
| 7235 | _ = ip.map.pop(); | ||
| 7236 | } else { | ||
| 7237 | // We must preserve the item so that indices following it remain valid. | ||
| 7238 | // Thus, we will rewrite the tag to `removed`, leaking the item until | ||
| 7239 | // next GC but causing `KeyAdapter` to ignore it. | ||
| 7240 | ip.items.set(@intFromEnum(index), .{ .tag = .removed, .data = undefined }); | ||
| 7241 | } | ||
| 7242 | } | ||
| 6721 | 7243 | ||
| 6722 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { | 7244 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { |
| 6723 | const limbs_len = @as(u32, @intCast(limbs.len)); | 7245 | const limbs_len = @as(u32, @intCast(limbs.len)); |
| ... | @@ -7077,9 +7599,9 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al | ... | @@ -7077,9 +7599,9 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al |
| 7077 | .func => unreachable, | 7599 | .func => unreachable, |
| 7078 | 7600 | ||
| 7079 | .int => |int| switch (ip.indexToKey(new_ty)) { | 7601 | .int => |int| switch (ip.indexToKey(new_ty)) { |
| 7080 | .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{ | 7602 | .enum_type => return ip.get(gpa, .{ .enum_tag = .{ |
| 7081 | .ty = new_ty, | 7603 | .ty = new_ty, |
| 7082 | .int = try ip.getCoerced(gpa, val, enum_type.tag_ty), | 7604 | .int = try ip.getCoerced(gpa, val, ip.loadEnumType(new_ty).tag_ty), |
| 7083 | } }), | 7605 | } }), |
| 7084 | .ptr_type => return ip.get(gpa, .{ .ptr = .{ | 7606 | .ptr_type => return ip.get(gpa, .{ .ptr = .{ |
| 7085 | .ty = new_ty, | 7607 | .ty = new_ty, |
| ... | @@ -7108,7 +7630,8 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al | ... | @@ -7108,7 +7630,8 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al |
| 7108 | .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty)) | 7630 | .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty)) |
| 7109 | return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty), | 7631 | return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty), |
| 7110 | .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) { | 7632 | .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) { |
| 7111 | .enum_type => |enum_type| { | 7633 | .enum_type => { |
| 7634 | const enum_type = ip.loadEnumType(new_ty); | ||
| 7112 | const index = enum_type.nameIndex(ip, enum_literal).?; | 7635 | const index = enum_type.nameIndex(ip, enum_literal).?; |
| 7113 | return ip.get(gpa, .{ .enum_tag = .{ | 7636 | return ip.get(gpa, .{ .enum_tag = .{ |
| 7114 | .ty = new_ty, | 7637 | .ty = new_ty, |
| ... | @@ -7249,7 +7772,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al | ... | @@ -7249,7 +7772,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al |
| 7249 | const new_elem_ty = switch (ip.indexToKey(new_ty)) { | 7772 | const new_elem_ty = switch (ip.indexToKey(new_ty)) { |
| 7250 | inline .array_type, .vector_type => |seq_type| seq_type.child, | 7773 | inline .array_type, .vector_type => |seq_type| seq_type.child, |
| 7251 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[i], | 7774 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[i], |
| 7252 | .struct_type => |struct_type| struct_type.field_types.get(ip)[i], | 7775 | .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i], |
| 7253 | else => unreachable, | 7776 | else => unreachable, |
| 7254 | }; | 7777 | }; |
| 7255 | elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty); | 7778 | elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty); |
| ... | @@ -7513,6 +8036,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -7513,6 +8036,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 7513 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 8036 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 7514 | gop.value_ptr.count += 1; | 8037 | gop.value_ptr.count += 1; |
| 7515 | gop.value_ptr.bytes += 1 + 4 + @as(usize, switch (tag) { | 8038 | gop.value_ptr.bytes += 1 + 4 + @as(usize, switch (tag) { |
| 8039 | // Note that in this case, we have technically leaked some extra data | ||
| 8040 | // bytes which we do not account for here. | ||
| 8041 | .removed => 0, | ||
| 8042 | |||
| 7516 | .type_int_signed => 0, | 8043 | .type_int_signed => 0, |
| 7517 | .type_int_unsigned => 0, | 8044 | .type_int_unsigned => 0, |
| 7518 | .type_array_small => @sizeOf(Vector), | 8045 | .type_array_small => @sizeOf(Vector), |
| ... | @@ -7529,12 +8056,31 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -7529,12 +8056,31 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 7529 | break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len); | 8056 | break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len); |
| 7530 | }, | 8057 | }, |
| 7531 | .type_inferred_error_set => 0, | 8058 | .type_inferred_error_set => 0, |
| 7532 | .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit), | 8059 | .type_enum_explicit, .type_enum_nonexhaustive => b: { |
| 7533 | .type_enum_auto => @sizeOf(EnumAuto), | 8060 | const info = ip.extraData(EnumExplicit, data); |
| 7534 | .type_opaque => @sizeOf(Key.OpaqueType), | 8061 | var ints = @typeInfo(EnumExplicit).Struct.fields.len + info.captures_len + info.fields_len; |
| 8062 | if (info.values_map != .none) ints += info.fields_len; | ||
| 8063 | break :b @sizeOf(u32) * ints; | ||
| 8064 | }, | ||
| 8065 | .type_enum_auto => b: { | ||
| 8066 | const info = ip.extraData(EnumAuto, data); | ||
| 8067 | const ints = @typeInfo(EnumAuto).Struct.fields.len + info.captures_len + info.fields_len; | ||
| 8068 | break :b @sizeOf(u32) * ints; | ||
| 8069 | }, | ||
| 8070 | .type_opaque => b: { | ||
| 8071 | const info = ip.extraData(Tag.TypeOpaque, data); | ||
| 8072 | const ints = @typeInfo(Tag.TypeOpaque).Struct.fields.len + info.captures_len; | ||
| 8073 | break :b @sizeOf(u32) * ints; | ||
| 8074 | }, | ||
| 7535 | .type_struct => b: { | 8075 | .type_struct => b: { |
| 7536 | const info = ip.extraData(Tag.TypeStruct, data); | 8076 | if (data == 0) break :b 0; |
| 8077 | const extra = ip.extraDataTrail(Tag.TypeStruct, data); | ||
| 8078 | const info = extra.data; | ||
| 7537 | var ints: usize = @typeInfo(Tag.TypeStruct).Struct.fields.len; | 8079 | var ints: usize = @typeInfo(Tag.TypeStruct).Struct.fields.len; |
| 8080 | if (info.flags.any_captures) { | ||
| 8081 | const captures_len = ip.extra.items[extra.end]; | ||
| 8082 | ints += 1 + captures_len; | ||
| 8083 | } | ||
| 7538 | ints += info.fields_len; // types | 8084 | ints += info.fields_len; // types |
| 7539 | if (!info.flags.is_tuple) { | 8085 | if (!info.flags.is_tuple) { |
| 7540 | ints += 1; // names_map | 8086 | ints += 1; // names_map |
| ... | @@ -7552,20 +8098,29 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -7552,20 +8098,29 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 7552 | ints += info.fields_len; // offsets | 8098 | ints += info.fields_len; // offsets |
| 7553 | break :b @sizeOf(u32) * ints; | 8099 | break :b @sizeOf(u32) * ints; |
| 7554 | }, | 8100 | }, |
| 7555 | .type_struct_ns => @sizeOf(Module.Namespace), | ||
| 7556 | .type_struct_anon => b: { | 8101 | .type_struct_anon => b: { |
| 7557 | const info = ip.extraData(TypeStructAnon, data); | 8102 | const info = ip.extraData(TypeStructAnon, data); |
| 7558 | break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len); | 8103 | break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len); |
| 7559 | }, | 8104 | }, |
| 7560 | .type_struct_packed => b: { | 8105 | .type_struct_packed => b: { |
| 7561 | const info = ip.extraData(Tag.TypeStructPacked, data); | 8106 | const extra = ip.extraDataTrail(Tag.TypeStructPacked, data); |
| 8107 | const captures_len = if (extra.data.flags.any_captures) | ||
| 8108 | ip.extra.items[extra.end] | ||
| 8109 | else | ||
| 8110 | 0; | ||
| 7562 | break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len + | 8111 | break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len + |
| 7563 | info.fields_len + info.fields_len); | 8112 | @intFromBool(extra.data.flags.any_captures) + captures_len + |
| 8113 | extra.data.fields_len * 2); | ||
| 7564 | }, | 8114 | }, |
| 7565 | .type_struct_packed_inits => b: { | 8115 | .type_struct_packed_inits => b: { |
| 7566 | const info = ip.extraData(Tag.TypeStructPacked, data); | 8116 | const extra = ip.extraDataTrail(Tag.TypeStructPacked, data); |
| 8117 | const captures_len = if (extra.data.flags.any_captures) | ||
| 8118 | ip.extra.items[extra.end] | ||
| 8119 | else | ||
| 8120 | 0; | ||
| 7567 | break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len + | 8121 | break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len + |
| 7568 | info.fields_len + info.fields_len + info.fields_len); | 8122 | @intFromBool(extra.data.flags.any_captures) + captures_len + |
| 8123 | extra.data.fields_len * 3); | ||
| 7569 | }, | 8124 | }, |
| 7570 | .type_tuple_anon => b: { | 8125 | .type_tuple_anon => b: { |
| 7571 | const info = ip.extraData(TypeStructAnon, data); | 8126 | const info = ip.extraData(TypeStructAnon, data); |
| ... | @@ -7573,16 +8128,20 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -7573,16 +8128,20 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 7573 | }, | 8128 | }, |
| 7574 | 8129 | ||
| 7575 | .type_union => b: { | 8130 | .type_union => b: { |
| 7576 | const info = ip.extraData(Tag.TypeUnion, data); | 8131 | const extra = ip.extraDataTrail(Tag.TypeUnion, data); |
| 7577 | const enum_info = ip.indexToKey(info.tag_ty).enum_type; | 8132 | const captures_len = if (extra.data.flags.any_captures) |
| 7578 | const fields_len: u32 = @intCast(enum_info.names.len); | 8133 | ip.extra.items[extra.end] |
| 8134 | else | ||
| 8135 | 0; | ||
| 7579 | const per_field = @sizeOf(u32); // field type | 8136 | const per_field = @sizeOf(u32); // field type |
| 7580 | // 1 byte per field for alignment, rounded up to the nearest 4 bytes | 8137 | // 1 byte per field for alignment, rounded up to the nearest 4 bytes |
| 7581 | const alignments = if (info.flags.any_aligned_fields) | 8138 | const alignments = if (extra.data.flags.any_aligned_fields) |
| 7582 | ((fields_len + 3) / 4) * 4 | 8139 | ((extra.data.fields_len + 3) / 4) * 4 |
| 7583 | else | 8140 | else |
| 7584 | 0; | 8141 | 0; |
| 7585 | break :b @sizeOf(Tag.TypeUnion) + (fields_len * per_field) + alignments; | 8142 | break :b @sizeOf(Tag.TypeUnion) + |
| 8143 | 4 * (@intFromBool(extra.data.flags.any_captures) + captures_len) + | ||
| 8144 | (extra.data.fields_len * per_field) + alignments; | ||
| 7586 | }, | 8145 | }, |
| 7587 | 8146 | ||
| 7588 | .type_function => b: { | 8147 | .type_function => b: { |
| ... | @@ -7698,6 +8257,8 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -7698,6 +8257,8 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 7698 | for (tags, datas, 0..) |tag, data, i| { | 8257 | for (tags, datas, 0..) |tag, data, i| { |
| 7699 | try w.print("${d} = {s}(", .{ i, @tagName(tag) }); | 8258 | try w.print("${d} = {s}(", .{ i, @tagName(tag) }); |
| 7700 | switch (tag) { | 8259 | switch (tag) { |
| 8260 | .removed => {}, | ||
| 8261 | |||
| 7701 | .simple_type => try w.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(data)))}), | 8262 | .simple_type => try w.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(data)))}), |
| 7702 | .simple_value => try w.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(data)))}), | 8263 | .simple_value => try w.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(data)))}), |
| 7703 | 8264 | ||
| ... | @@ -7718,7 +8279,6 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -7718,7 +8279,6 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 7718 | .type_enum_auto, | 8279 | .type_enum_auto, |
| 7719 | .type_opaque, | 8280 | .type_opaque, |
| 7720 | .type_struct, | 8281 | .type_struct, |
| 7721 | .type_struct_ns, | ||
| 7722 | .type_struct_anon, | 8282 | .type_struct_anon, |
| 7723 | .type_struct_packed, | 8283 | .type_struct_packed, |
| 7724 | .type_struct_packed_inits, | 8284 | .type_struct_packed_inits, |
| ... | @@ -8105,6 +8665,8 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -8105,6 +8665,8 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 8105 | // This optimization on tags is needed so that indexToKey can call | 8665 | // This optimization on tags is needed so that indexToKey can call |
| 8106 | // typeOf without being recursive. | 8666 | // typeOf without being recursive. |
| 8107 | _ => switch (ip.items.items(.tag)[@intFromEnum(index)]) { | 8667 | _ => switch (ip.items.items(.tag)[@intFromEnum(index)]) { |
| 8668 | .removed => unreachable, | ||
| 8669 | |||
| 8108 | .type_int_signed, | 8670 | .type_int_signed, |
| 8109 | .type_int_unsigned, | 8671 | .type_int_unsigned, |
| 8110 | .type_array_big, | 8672 | .type_array_big, |
| ... | @@ -8124,7 +8686,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -8124,7 +8686,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 8124 | .simple_type, | 8686 | .simple_type, |
| 8125 | .type_opaque, | 8687 | .type_opaque, |
| 8126 | .type_struct, | 8688 | .type_struct, |
| 8127 | .type_struct_ns, | ||
| 8128 | .type_struct_anon, | 8689 | .type_struct_anon, |
| 8129 | .type_struct_packed, | 8690 | .type_struct_packed, |
| 8130 | .type_struct_packed_inits, | 8691 | .type_struct_packed_inits, |
| ... | @@ -8218,7 +8779,7 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E { | ... | @@ -8218,7 +8779,7 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E { |
| 8218 | 8779 | ||
| 8219 | pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 { | 8780 | pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 { |
| 8220 | return switch (ip.indexToKey(ty)) { | 8781 | return switch (ip.indexToKey(ty)) { |
| 8221 | .struct_type => |struct_type| struct_type.field_types.len, | 8782 | .struct_type => ip.loadStructType(ty).field_types.len, |
| 8222 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, | 8783 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, |
| 8223 | .array_type => |array_type| array_type.len, | 8784 | .array_type => |array_type| array_type.len, |
| 8224 | .vector_type => |vector_type| vector_type.len, | 8785 | .vector_type => |vector_type| vector_type.len, |
| ... | @@ -8228,7 +8789,7 @@ pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 { | ... | @@ -8228,7 +8789,7 @@ pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 { |
| 8228 | 8789 | ||
| 8229 | pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 { | 8790 | pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 { |
| 8230 | return switch (ip.indexToKey(ty)) { | 8791 | return switch (ip.indexToKey(ty)) { |
| 8231 | .struct_type => |struct_type| struct_type.field_types.len, | 8792 | .struct_type => ip.loadStructType(ty).field_types.len, |
| 8232 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, | 8793 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, |
| 8233 | .array_type => |array_type| array_type.len + @intFromBool(array_type.sentinel != .none), | 8794 | .array_type => |array_type| array_type.len + @intFromBool(array_type.sentinel != .none), |
| 8234 | .vector_type => |vector_type| vector_type.len, | 8795 | .vector_type => |vector_type| vector_type.len, |
| ... | @@ -8423,6 +8984,8 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -8423,6 +8984,8 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 8423 | .var_args_param_type => unreachable, // special tag | 8984 | .var_args_param_type => unreachable, // special tag |
| 8424 | 8985 | ||
| 8425 | _ => switch (ip.items.items(.tag)[@intFromEnum(index)]) { | 8986 | _ => switch (ip.items.items(.tag)[@intFromEnum(index)]) { |
| 8987 | .removed => unreachable, | ||
| 8988 | |||
| 8426 | .type_int_signed, | 8989 | .type_int_signed, |
| 8427 | .type_int_unsigned, | 8990 | .type_int_unsigned, |
| 8428 | => .Int, | 8991 | => .Int, |
| ... | @@ -8458,7 +9021,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -8458,7 +9021,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 8458 | .type_opaque => .Opaque, | 9021 | .type_opaque => .Opaque, |
| 8459 | 9022 | ||
| 8460 | .type_struct, | 9023 | .type_struct, |
| 8461 | .type_struct_ns, | ||
| 8462 | .type_struct_anon, | 9024 | .type_struct_anon, |
| 8463 | .type_struct_packed, | 9025 | .type_struct_packed, |
| 8464 | .type_struct_packed_inits, | 9026 | .type_struct_packed_inits, |
src/Liveness.zig+2-2| ... | @@ -131,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type { | ... | @@ -131,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type { |
| 131 | }; | 131 | }; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | pub fn analyze(gpa: Allocator, air: Air, intern_pool: *const InternPool) Allocator.Error!Liveness { | 134 | pub fn analyze(gpa: Allocator, air: Air, intern_pool: *InternPool) Allocator.Error!Liveness { |
| 135 | const tracy = trace(@src()); | 135 | const tracy = trace(@src()); |
| 136 | defer tracy.end(); | 136 | defer tracy.end(); |
| 137 | 137 | ||
| ... | @@ -836,7 +836,7 @@ pub const BigTomb = struct { | ... | @@ -836,7 +836,7 @@ pub const BigTomb = struct { |
| 836 | const Analysis = struct { | 836 | const Analysis = struct { |
| 837 | gpa: Allocator, | 837 | gpa: Allocator, |
| 838 | air: Air, | 838 | air: Air, |
| 839 | intern_pool: *const InternPool, | 839 | intern_pool: *InternPool, |
| 840 | tomb_bits: []usize, | 840 | tomb_bits: []usize, |
| 841 | special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32), | 841 | special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32), |
| 842 | extra: std.ArrayListUnmanaged(u32), | 842 | extra: std.ArrayListUnmanaged(u32), |
src/Module.zig+101-138| ... | @@ -101,17 +101,6 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{}, | ... | @@ -101,17 +101,6 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{}, |
| 101 | /// is not yet implemented. | 101 | /// is not yet implemented. |
| 102 | intern_pool: InternPool = .{}, | 102 | intern_pool: InternPool = .{}, |
| 103 | 103 | ||
| 104 | /// The index type for this array is `CaptureScope.Index` and the elements here are | ||
| 105 | /// the indexes of the parent capture scopes. | ||
| 106 | /// Memory is owned by gpa; garbage collected. | ||
| 107 | capture_scope_parents: std.ArrayListUnmanaged(CaptureScope.Index) = .{}, | ||
| 108 | /// Value is index of type | ||
| 109 | /// Memory is owned by gpa; garbage collected. | ||
| 110 | runtime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternPool.Index) = .{}, | ||
| 111 | /// Value is index of value | ||
| 112 | /// Memory is owned by gpa; garbage collected. | ||
| 113 | comptime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternPool.Index) = .{}, | ||
| 114 | |||
| 115 | /// To be eliminated in a future commit by moving more data into InternPool. | 104 | /// To be eliminated in a future commit by moving more data into InternPool. |
| 116 | /// Current uses that must be eliminated: | 105 | /// Current uses that must be eliminated: |
| 117 | /// * comptime pointer mutation | 106 | /// * comptime pointer mutation |
| ... | @@ -305,28 +294,6 @@ pub const Export = struct { | ... | @@ -305,28 +294,6 @@ pub const Export = struct { |
| 305 | } | 294 | } |
| 306 | }; | 295 | }; |
| 307 | 296 | ||
| 308 | pub const CaptureScope = struct { | ||
| 309 | pub const Key = extern struct { | ||
| 310 | zir_index: Zir.Inst.Index, | ||
| 311 | index: Index, | ||
| 312 | }; | ||
| 313 | |||
| 314 | /// Index into `capture_scope_parents` which uniquely identifies a capture scope. | ||
| 315 | pub const Index = enum(u32) { | ||
| 316 | none = std.math.maxInt(u32), | ||
| 317 | _, | ||
| 318 | |||
| 319 | pub fn parent(i: Index, mod: *Module) Index { | ||
| 320 | return mod.capture_scope_parents.items[@intFromEnum(i)]; | ||
| 321 | } | ||
| 322 | }; | ||
| 323 | }; | ||
| 324 | |||
| 325 | pub fn createCaptureScope(mod: *Module, parent: CaptureScope.Index) error{OutOfMemory}!CaptureScope.Index { | ||
| 326 | try mod.capture_scope_parents.append(mod.gpa, parent); | ||
| 327 | return @enumFromInt(mod.capture_scope_parents.items.len - 1); | ||
| 328 | } | ||
| 329 | |||
| 330 | const ValueArena = struct { | 297 | const ValueArena = struct { |
| 331 | state: std.heap.ArenaAllocator.State, | 298 | state: std.heap.ArenaAllocator.State, |
| 332 | state_acquired: ?*std.heap.ArenaAllocator.State = null, | 299 | state_acquired: ?*std.heap.ArenaAllocator.State = null, |
| ... | @@ -386,9 +353,6 @@ pub const Decl = struct { | ... | @@ -386,9 +353,6 @@ pub const Decl = struct { |
| 386 | /// there is no parent. | 353 | /// there is no parent. |
| 387 | src_namespace: Namespace.Index, | 354 | src_namespace: Namespace.Index, |
| 388 | 355 | ||
| 389 | /// The scope which lexically contains this decl. | ||
| 390 | src_scope: CaptureScope.Index, | ||
| 391 | |||
| 392 | /// The AST node index of this declaration. | 356 | /// The AST node index of this declaration. |
| 393 | /// Must be recomputed when the corresponding source file is modified. | 357 | /// Must be recomputed when the corresponding source file is modified. |
| 394 | src_node: Ast.Node.Index, | 358 | src_node: Ast.Node.Index, |
| ... | @@ -563,7 +527,7 @@ pub const Decl = struct { | ... | @@ -563,7 +527,7 @@ pub const Decl = struct { |
| 563 | 527 | ||
| 564 | /// If the Decl owns its value and it is a union, return it, | 528 | /// If the Decl owns its value and it is a union, return it, |
| 565 | /// otherwise null. | 529 | /// otherwise null. |
| 566 | pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.UnionType { | 530 | pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.LoadedUnionType { |
| 567 | if (!decl.owns_tv) return null; | 531 | if (!decl.owns_tv) return null; |
| 568 | if (decl.val.ip_index == .none) return null; | 532 | if (decl.val.ip_index == .none) return null; |
| 569 | return zcu.typeToUnion(decl.val.toType()); | 533 | return zcu.typeToUnion(decl.val.toType()); |
| ... | @@ -599,14 +563,15 @@ pub const Decl = struct { | ... | @@ -599,14 +563,15 @@ pub const Decl = struct { |
| 599 | /// enum, or opaque. | 563 | /// enum, or opaque. |
| 600 | pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex { | 564 | pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex { |
| 601 | if (!decl.has_tv) return .none; | 565 | if (!decl.has_tv) return .none; |
| 566 | const ip = &zcu.intern_pool; | ||
| 602 | return switch (decl.val.ip_index) { | 567 | return switch (decl.val.ip_index) { |
| 603 | .empty_struct_type => .none, | 568 | .empty_struct_type => .none, |
| 604 | .none => .none, | 569 | .none => .none, |
| 605 | else => switch (zcu.intern_pool.indexToKey(decl.val.toIntern())) { | 570 | else => switch (ip.indexToKey(decl.val.toIntern())) { |
| 606 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), | 571 | .opaque_type => ip.loadOpaqueType(decl.val.toIntern()).namespace, |
| 607 | .struct_type => |struct_type| struct_type.namespace, | 572 | .struct_type => ip.loadStructType(decl.val.toIntern()).namespace, |
| 608 | .union_type => |union_type| union_type.namespace.toOptional(), | 573 | .union_type => ip.loadUnionType(decl.val.toIntern()).namespace, |
| 609 | .enum_type => |enum_type| enum_type.namespace, | 574 | .enum_type => ip.loadEnumType(decl.val.toIntern()).namespace, |
| 610 | else => .none, | 575 | else => .none, |
| 611 | }, | 576 | }, |
| 612 | }; | 577 | }; |
| ... | @@ -792,7 +757,6 @@ pub const Namespace = struct { | ... | @@ -792,7 +757,6 @@ pub const Namespace = struct { |
| 792 | /// These are only declarations named directly by the AST; anonymous | 757 | /// These are only declarations named directly by the AST; anonymous |
| 793 | /// declarations are not stored here. | 758 | /// declarations are not stored here. |
| 794 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, | 759 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, |
| 795 | |||
| 796 | /// Key is usingnamespace Decl itself. To find the namespace being included, | 760 | /// Key is usingnamespace Decl itself. To find the namespace being included, |
| 797 | /// the Decl Value has to be resolved as a Type which has a Namespace. | 761 | /// the Decl Value has to be resolved as a Type which has a Namespace. |
| 798 | /// Value is whether the usingnamespace decl is marked `pub`. | 762 | /// Value is whether the usingnamespace decl is marked `pub`. |
| ... | @@ -2140,10 +2104,6 @@ pub fn deinit(zcu: *Zcu) void { | ... | @@ -2140,10 +2104,6 @@ pub fn deinit(zcu: *Zcu) void { |
| 2140 | 2104 | ||
| 2141 | zcu.intern_pool.deinit(gpa); | 2105 | zcu.intern_pool.deinit(gpa); |
| 2142 | zcu.tmp_hack_arena.deinit(); | 2106 | zcu.tmp_hack_arena.deinit(); |
| 2143 | |||
| 2144 | zcu.capture_scope_parents.deinit(gpa); | ||
| 2145 | zcu.runtime_capture_scopes.deinit(gpa); | ||
| 2146 | zcu.comptime_capture_scopes.deinit(gpa); | ||
| 2147 | } | 2107 | } |
| 2148 | 2108 | ||
| 2149 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | 2109 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| ... | @@ -3342,6 +3302,70 @@ pub fn semaPkg(mod: *Module, pkg: *Package.Module) !void { | ... | @@ -3342,6 +3302,70 @@ pub fn semaPkg(mod: *Module, pkg: *Package.Module) !void { |
| 3342 | return mod.semaFile(file); | 3302 | return mod.semaFile(file); |
| 3343 | } | 3303 | } |
| 3344 | 3304 | ||
| 3305 | fn getFileRootStruct(zcu: *Zcu, decl_index: Decl.Index, namespace_index: Namespace.Index, file: *File) Allocator.Error!InternPool.Index { | ||
| 3306 | const gpa = zcu.gpa; | ||
| 3307 | const ip = &zcu.intern_pool; | ||
| 3308 | const extended = file.zir.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; | ||
| 3309 | assert(extended.opcode == .struct_decl); | ||
| 3310 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | ||
| 3311 | assert(!small.has_captures_len); | ||
| 3312 | assert(!small.has_backing_int); | ||
| 3313 | assert(small.layout == .Auto); | ||
| 3314 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; | ||
| 3315 | const fields_len = if (small.has_fields_len) blk: { | ||
| 3316 | const fields_len = file.zir.extra[extra_index]; | ||
| 3317 | extra_index += 1; | ||
| 3318 | break :blk fields_len; | ||
| 3319 | } else 0; | ||
| 3320 | const decls_len = if (small.has_decls_len) blk: { | ||
| 3321 | const decls_len = file.zir.extra[extra_index]; | ||
| 3322 | extra_index += 1; | ||
| 3323 | break :blk decls_len; | ||
| 3324 | } else 0; | ||
| 3325 | const decls = file.zir.bodySlice(extra_index, decls_len); | ||
| 3326 | extra_index += decls_len; | ||
| 3327 | |||
| 3328 | const tracked_inst = try ip.trackZir(gpa, file, .main_struct_inst); | ||
| 3329 | const wip_ty = switch (try ip.getStructType(gpa, .{ | ||
| 3330 | .layout = .Auto, | ||
| 3331 | .fields_len = fields_len, | ||
| 3332 | .known_non_opv = small.known_non_opv, | ||
| 3333 | .requires_comptime = if (small.known_comptime_only) .yes else .unknown, | ||
| 3334 | .is_tuple = small.is_tuple, | ||
| 3335 | .any_comptime_fields = small.any_comptime_fields, | ||
| 3336 | .any_default_inits = small.any_default_inits, | ||
| 3337 | .inits_resolved = false, | ||
| 3338 | .any_aligned_fields = small.any_aligned_fields, | ||
| 3339 | .has_namespace = true, | ||
| 3340 | .key = .{ .declared = .{ | ||
| 3341 | .zir_index = tracked_inst, | ||
| 3342 | .captures = &.{}, | ||
| 3343 | } }, | ||
| 3344 | })) { | ||
| 3345 | .existing => unreachable, // we wouldn't be analysing the file root if this type existed | ||
| 3346 | .wip => |wip| wip, | ||
| 3347 | }; | ||
| 3348 | errdefer wip_ty.cancel(ip); | ||
| 3349 | |||
| 3350 | if (zcu.comp.debug_incremental) { | ||
| 3351 | try ip.addDependency( | ||
| 3352 | gpa, | ||
| 3353 | InternPool.Depender.wrap(.{ .decl = decl_index }), | ||
| 3354 | .{ .src_hash = tracked_inst }, | ||
| 3355 | ); | ||
| 3356 | } | ||
| 3357 | |||
| 3358 | const decl = zcu.declPtr(decl_index); | ||
| 3359 | decl.val = Value.fromInterned(wip_ty.index); | ||
| 3360 | decl.has_tv = true; | ||
| 3361 | decl.owns_tv = true; | ||
| 3362 | decl.analysis = .complete; | ||
| 3363 | |||
| 3364 | try zcu.scanNamespace(namespace_index, decls, decl); | ||
| 3365 | |||
| 3366 | return wip_ty.finish(ip, decl_index, namespace_index.toOptional()); | ||
| 3367 | } | ||
| 3368 | |||
| 3345 | /// Regardless of the file status, will create a `Decl` so that we | 3369 | /// Regardless of the file status, will create a `Decl` so that we |
| 3346 | /// can track dependencies and re-analyze when the file becomes outdated. | 3370 | /// can track dependencies and re-analyze when the file becomes outdated. |
| 3347 | pub fn semaFile(mod: *Module, file: *File) SemaError!void { | 3371 | pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| ... | @@ -3363,15 +3387,14 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3363,15 +3387,14 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3363 | .decl_index = undefined, | 3387 | .decl_index = undefined, |
| 3364 | .file_scope = file, | 3388 | .file_scope = file, |
| 3365 | }); | 3389 | }); |
| 3366 | const new_namespace = mod.namespacePtr(new_namespace_index); | ||
| 3367 | errdefer mod.destroyNamespace(new_namespace_index); | 3390 | errdefer mod.destroyNamespace(new_namespace_index); |
| 3368 | 3391 | ||
| 3369 | const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0, .none); | 3392 | const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0); |
| 3370 | const new_decl = mod.declPtr(new_decl_index); | 3393 | const new_decl = mod.declPtr(new_decl_index); |
| 3371 | errdefer @panic("TODO error handling"); | 3394 | errdefer @panic("TODO error handling"); |
| 3372 | 3395 | ||
| 3373 | file.root_decl = new_decl_index.toOptional(); | 3396 | file.root_decl = new_decl_index.toOptional(); |
| 3374 | new_namespace.decl_index = new_decl_index; | 3397 | mod.namespacePtr(new_namespace_index).decl_index = new_decl_index; |
| 3375 | 3398 | ||
| 3376 | new_decl.name = try file.fullyQualifiedName(mod); | 3399 | new_decl.name = try file.fullyQualifiedName(mod); |
| 3377 | new_decl.name_fully_qualified = true; | 3400 | new_decl.name_fully_qualified = true; |
| ... | @@ -3390,54 +3413,10 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3390,54 +3413,10 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3390 | } | 3413 | } |
| 3391 | assert(file.zir_loaded); | 3414 | assert(file.zir_loaded); |
| 3392 | 3415 | ||
| 3393 | var sema_arena = std.heap.ArenaAllocator.init(gpa); | 3416 | const struct_ty = try mod.getFileRootStruct(new_decl_index, new_namespace_index, file); |
| 3394 | defer sema_arena.deinit(); | 3417 | errdefer mod.intern_pool.remove(struct_ty); |
| 3395 | const sema_arena_allocator = sema_arena.allocator(); | ||
| 3396 | |||
| 3397 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); | ||
| 3398 | defer comptime_mutable_decls.deinit(); | ||
| 3399 | |||
| 3400 | var comptime_err_ret_trace = std.ArrayList(SrcLoc).init(gpa); | ||
| 3401 | defer comptime_err_ret_trace.deinit(); | ||
| 3402 | 3418 | ||
| 3403 | var sema: Sema = .{ | 3419 | switch (mod.comp.cache_use) { |
| 3404 | .mod = mod, | ||
| 3405 | .gpa = gpa, | ||
| 3406 | .arena = sema_arena_allocator, | ||
| 3407 | .code = file.zir, | ||
| 3408 | .owner_decl = new_decl, | ||
| 3409 | .owner_decl_index = new_decl_index, | ||
| 3410 | .func_index = .none, | ||
| 3411 | .func_is_naked = false, | ||
| 3412 | .fn_ret_ty = Type.void, | ||
| 3413 | .fn_ret_ty_ies = null, | ||
| 3414 | .owner_func_index = .none, | ||
| 3415 | .comptime_mutable_decls = &comptime_mutable_decls, | ||
| 3416 | .comptime_err_ret_trace = &comptime_err_ret_trace, | ||
| 3417 | }; | ||
| 3418 | defer sema.deinit(); | ||
| 3419 | |||
| 3420 | const struct_ty = sema.getStructType( | ||
| 3421 | new_decl_index, | ||
| 3422 | new_namespace_index, | ||
| 3423 | try mod.intern_pool.trackZir(gpa, file, .main_struct_inst), | ||
| 3424 | ) catch |err| switch (err) { | ||
| 3425 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3426 | }; | ||
| 3427 | // TODO: figure out InternPool removals for incremental compilation | ||
| 3428 | //errdefer ip.remove(struct_ty); | ||
| 3429 | for (comptime_mutable_decls.items) |decl_index| { | ||
| 3430 | const decl = mod.declPtr(decl_index); | ||
| 3431 | _ = try decl.internValue(mod); | ||
| 3432 | } | ||
| 3433 | |||
| 3434 | new_decl.val = Value.fromInterned(struct_ty); | ||
| 3435 | new_decl.has_tv = true; | ||
| 3436 | new_decl.owns_tv = true; | ||
| 3437 | new_decl.analysis = .complete; | ||
| 3438 | |||
| 3439 | const comp = mod.comp; | ||
| 3440 | switch (comp.cache_use) { | ||
| 3441 | .whole => |whole| if (whole.cache_manifest) |man| { | 3420 | .whole => |whole| if (whole.cache_manifest) |man| { |
| 3442 | const source = file.getSource(gpa) catch |err| { | 3421 | const source = file.getSource(gpa) catch |err| { |
| 3443 | try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)}); | 3422 | try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)}); |
| ... | @@ -3573,7 +3552,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { | ... | @@ -3573,7 +3552,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3573 | .sema = &sema, | 3552 | .sema = &sema, |
| 3574 | .src_decl = decl_index, | 3553 | .src_decl = decl_index, |
| 3575 | .namespace = decl.src_namespace, | 3554 | .namespace = decl.src_namespace, |
| 3576 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 3577 | .instructions = .{}, | 3555 | .instructions = .{}, |
| 3578 | .inlining = null, | 3556 | .inlining = null, |
| 3579 | .is_comptime = true, | 3557 | .is_comptime = true, |
| ... | @@ -4205,7 +4183,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void | ... | @@ -4205,7 +4183,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void |
| 4205 | ); | 4183 | ); |
| 4206 | const comp = zcu.comp; | 4184 | const comp = zcu.comp; |
| 4207 | if (!gop.found_existing) { | 4185 | if (!gop.found_existing) { |
| 4208 | const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope); | 4186 | const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node); |
| 4209 | const new_decl = zcu.declPtr(new_decl_index); | 4187 | const new_decl = zcu.declPtr(new_decl_index); |
| 4210 | new_decl.kind = kind; | 4188 | new_decl.kind = kind; |
| 4211 | new_decl.name = decl_name; | 4189 | new_decl.name = decl_name; |
| ... | @@ -4438,7 +4416,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -4438,7 +4416,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 4438 | .sema = &sema, | 4416 | .sema = &sema, |
| 4439 | .src_decl = decl_index, | 4417 | .src_decl = decl_index, |
| 4440 | .namespace = decl.src_namespace, | 4418 | .namespace = decl.src_namespace, |
| 4441 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 4442 | .instructions = .{}, | 4419 | .instructions = .{}, |
| 4443 | .inlining = null, | 4420 | .inlining = null, |
| 4444 | .is_comptime = false, | 4421 | .is_comptime = false, |
| ... | @@ -4639,7 +4616,6 @@ pub fn allocateNewDecl( | ... | @@ -4639,7 +4616,6 @@ pub fn allocateNewDecl( |
| 4639 | mod: *Module, | 4616 | mod: *Module, |
| 4640 | namespace: Namespace.Index, | 4617 | namespace: Namespace.Index, |
| 4641 | src_node: Ast.Node.Index, | 4618 | src_node: Ast.Node.Index, |
| 4642 | src_scope: CaptureScope.Index, | ||
| 4643 | ) !Decl.Index { | 4619 | ) !Decl.Index { |
| 4644 | const ip = &mod.intern_pool; | 4620 | const ip = &mod.intern_pool; |
| 4645 | const gpa = mod.gpa; | 4621 | const gpa = mod.gpa; |
| ... | @@ -4657,7 +4633,6 @@ pub fn allocateNewDecl( | ... | @@ -4657,7 +4633,6 @@ pub fn allocateNewDecl( |
| 4657 | .@"addrspace" = .generic, | 4633 | .@"addrspace" = .generic, |
| 4658 | .analysis = .unreferenced, | 4634 | .analysis = .unreferenced, |
| 4659 | .zir_decl_index = .none, | 4635 | .zir_decl_index = .none, |
| 4660 | .src_scope = src_scope, | ||
| 4661 | .is_pub = false, | 4636 | .is_pub = false, |
| 4662 | .is_exported = false, | 4637 | .is_exported = false, |
| 4663 | .alive = false, | 4638 | .alive = false, |
| ... | @@ -4697,17 +4672,16 @@ pub fn errorSetBits(mod: *Module) u16 { | ... | @@ -4697,17 +4672,16 @@ pub fn errorSetBits(mod: *Module) u16 { |
| 4697 | 4672 | ||
| 4698 | pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index { | 4673 | pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index { |
| 4699 | const src_decl = mod.declPtr(block.src_decl); | 4674 | const src_decl = mod.declPtr(block.src_decl); |
| 4700 | return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value); | 4675 | return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, typed_value); |
| 4701 | } | 4676 | } |
| 4702 | 4677 | ||
| 4703 | pub fn createAnonymousDeclFromDecl( | 4678 | pub fn createAnonymousDeclFromDecl( |
| 4704 | mod: *Module, | 4679 | mod: *Module, |
| 4705 | src_decl: *Decl, | 4680 | src_decl: *Decl, |
| 4706 | namespace: Namespace.Index, | 4681 | namespace: Namespace.Index, |
| 4707 | src_scope: CaptureScope.Index, | ||
| 4708 | tv: TypedValue, | 4682 | tv: TypedValue, |
| 4709 | ) !Decl.Index { | 4683 | ) !Decl.Index { |
| 4710 | const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope); | 4684 | const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node); |
| 4711 | errdefer mod.destroyDecl(new_decl_index); | 4685 | errdefer mod.destroyDecl(new_decl_index); |
| 4712 | const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ | 4686 | const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ |
| 4713 | src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), | 4687 | src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), |
| ... | @@ -5276,7 +5250,7 @@ pub fn populateTestFunctions( | ... | @@ -5276,7 +5250,7 @@ pub fn populateTestFunctions( |
| 5276 | .len = test_decl_name.len, | 5250 | .len = test_decl_name.len, |
| 5277 | .child = .u8_type, | 5251 | .child = .u8_type, |
| 5278 | }); | 5252 | }); |
| 5279 | const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .none, .{ | 5253 | const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ |
| 5280 | .ty = test_name_decl_ty, | 5254 | .ty = test_name_decl_ty, |
| 5281 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ | 5255 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 5282 | .ty = test_name_decl_ty.toIntern(), | 5256 | .ty = test_name_decl_ty.toIntern(), |
| ... | @@ -5322,7 +5296,7 @@ pub fn populateTestFunctions( | ... | @@ -5322,7 +5296,7 @@ pub fn populateTestFunctions( |
| 5322 | .child = test_fn_ty.toIntern(), | 5296 | .child = test_fn_ty.toIntern(), |
| 5323 | .sentinel = .none, | 5297 | .sentinel = .none, |
| 5324 | }); | 5298 | }); |
| 5325 | const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .none, .{ | 5299 | const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ |
| 5326 | .ty = array_decl_ty, | 5300 | .ty = array_decl_ty, |
| 5327 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ | 5301 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 5328 | .ty = array_decl_ty.toIntern(), | 5302 | .ty = array_decl_ty.toIntern(), |
| ... | @@ -5686,7 +5660,7 @@ pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Er | ... | @@ -5686,7 +5660,7 @@ pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Er |
| 5686 | pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value { | 5660 | pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value { |
| 5687 | const ip = &mod.intern_pool; | 5661 | const ip = &mod.intern_pool; |
| 5688 | const gpa = mod.gpa; | 5662 | const gpa = mod.gpa; |
| 5689 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 5663 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 5690 | 5664 | ||
| 5691 | if (enum_type.values.len == 0) { | 5665 | if (enum_type.values.len == 0) { |
| 5692 | // Auto-numbered fields. | 5666 | // Auto-numbered fields. |
| ... | @@ -5976,14 +5950,6 @@ pub fn atomicPtrAlignment( | ... | @@ -5976,14 +5950,6 @@ pub fn atomicPtrAlignment( |
| 5976 | return .none; | 5950 | return .none; |
| 5977 | } | 5951 | } |
| 5978 | 5952 | ||
| 5979 | pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc { | ||
| 5980 | return mod.declPtr(opaque_type.decl).srcLoc(mod); | ||
| 5981 | } | ||
| 5982 | |||
| 5983 | pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) !InternPool.NullTerminatedString { | ||
| 5984 | return mod.declPtr(opaque_type.decl).fullyQualifiedName(mod); | ||
| 5985 | } | ||
| 5986 | |||
| 5987 | pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { | 5953 | pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { |
| 5988 | return mod.declPtr(decl_index).getFileScope(mod); | 5954 | return mod.declPtr(decl_index).getFileScope(mod); |
| 5989 | } | 5955 | } |
| ... | @@ -5992,28 +5958,26 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { | ... | @@ -5992,28 +5958,26 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { |
| 5992 | /// * `@TypeOf(.{})` | 5958 | /// * `@TypeOf(.{})` |
| 5993 | /// * A struct which has no fields (`struct {}`). | 5959 | /// * A struct which has no fields (`struct {}`). |
| 5994 | /// * Not a struct. | 5960 | /// * Not a struct. |
| 5995 | pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType { | 5961 | pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType { |
| 5996 | if (ty.ip_index == .none) return null; | 5962 | if (ty.ip_index == .none) return null; |
| 5997 | return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 5963 | const ip = &mod.intern_pool; |
| 5998 | .struct_type => |t| t, | 5964 | return switch (ip.indexToKey(ty.ip_index)) { |
| 5965 | .struct_type => ip.loadStructType(ty.ip_index), | ||
| 5999 | else => null, | 5966 | else => null, |
| 6000 | }; | 5967 | }; |
| 6001 | } | 5968 | } |
| 6002 | 5969 | ||
| 6003 | pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType { | 5970 | pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType { |
| 6004 | if (ty.ip_index == .none) return null; | 5971 | const s = mod.typeToStruct(ty) orelse return null; |
| 6005 | return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | 5972 | if (s.layout != .Packed) return null; |
| 6006 | .struct_type => |t| if (t.layout == .Packed) t else null, | 5973 | return s; |
| 6007 | else => null, | ||
| 6008 | }; | ||
| 6009 | } | 5974 | } |
| 6010 | 5975 | ||
| 6011 | /// This asserts that the union's enum tag type has been resolved. | 5976 | pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.LoadedUnionType { |
| 6012 | pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.UnionType { | ||
| 6013 | if (ty.ip_index == .none) return null; | 5977 | if (ty.ip_index == .none) return null; |
| 6014 | const ip = &mod.intern_pool; | 5978 | const ip = &mod.intern_pool; |
| 6015 | return switch (ip.indexToKey(ty.ip_index)) { | 5979 | return switch (ip.indexToKey(ty.ip_index)) { |
| 6016 | .union_type => |k| ip.loadUnionType(k), | 5980 | .union_type => ip.loadUnionType(ty.ip_index), |
| 6017 | else => null, | 5981 | else => null, |
| 6018 | }; | 5982 | }; |
| 6019 | } | 5983 | } |
| ... | @@ -6115,7 +6079,7 @@ pub const UnionLayout = struct { | ... | @@ -6115,7 +6079,7 @@ pub const UnionLayout = struct { |
| 6115 | padding: u32, | 6079 | padding: u32, |
| 6116 | }; | 6080 | }; |
| 6117 | 6081 | ||
| 6118 | pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout { | 6082 | pub fn getUnionLayout(mod: *Module, u: InternPool.LoadedUnionType) UnionLayout { |
| 6119 | const ip = &mod.intern_pool; | 6083 | const ip = &mod.intern_pool; |
| 6120 | assert(u.haveLayout(ip)); | 6084 | assert(u.haveLayout(ip)); |
| 6121 | var most_aligned_field: u32 = undefined; | 6085 | var most_aligned_field: u32 = undefined; |
| ... | @@ -6161,7 +6125,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout { | ... | @@ -6161,7 +6125,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout { |
| 6161 | const tag_size = Type.fromInterned(u.enum_tag_ty).abiSize(mod); | 6125 | const tag_size = Type.fromInterned(u.enum_tag_ty).abiSize(mod); |
| 6162 | const tag_align = Type.fromInterned(u.enum_tag_ty).abiAlignment(mod).max(.@"1"); | 6126 | const tag_align = Type.fromInterned(u.enum_tag_ty).abiAlignment(mod).max(.@"1"); |
| 6163 | return .{ | 6127 | return .{ |
| 6164 | .abi_size = u.size, | 6128 | .abi_size = u.size(ip).*, |
| 6165 | .abi_align = tag_align.max(payload_align), | 6129 | .abi_align = tag_align.max(payload_align), |
| 6166 | .most_aligned_field = most_aligned_field, | 6130 | .most_aligned_field = most_aligned_field, |
| 6167 | .most_aligned_field_size = most_aligned_field_size, | 6131 | .most_aligned_field_size = most_aligned_field_size, |
| ... | @@ -6170,16 +6134,16 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout { | ... | @@ -6170,16 +6134,16 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout { |
| 6170 | .payload_align = payload_align, | 6134 | .payload_align = payload_align, |
| 6171 | .tag_align = tag_align, | 6135 | .tag_align = tag_align, |
| 6172 | .tag_size = tag_size, | 6136 | .tag_size = tag_size, |
| 6173 | .padding = u.padding, | 6137 | .padding = u.padding(ip).*, |
| 6174 | }; | 6138 | }; |
| 6175 | } | 6139 | } |
| 6176 | 6140 | ||
| 6177 | pub fn unionAbiSize(mod: *Module, u: InternPool.UnionType) u64 { | 6141 | pub fn unionAbiSize(mod: *Module, u: InternPool.LoadedUnionType) u64 { |
| 6178 | return mod.getUnionLayout(u).abi_size; | 6142 | return mod.getUnionLayout(u).abi_size; |
| 6179 | } | 6143 | } |
| 6180 | 6144 | ||
| 6181 | /// Returns 0 if the union is represented with 0 bits at runtime. | 6145 | /// Returns 0 if the union is represented with 0 bits at runtime. |
| 6182 | pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment { | 6146 | pub fn unionAbiAlignment(mod: *Module, u: InternPool.LoadedUnionType) Alignment { |
| 6183 | const ip = &mod.intern_pool; | 6147 | const ip = &mod.intern_pool; |
| 6184 | const have_tag = u.flagsPtr(ip).runtime_tag.hasTag(); | 6148 | const have_tag = u.flagsPtr(ip).runtime_tag.hasTag(); |
| 6185 | var max_align: Alignment = .none; | 6149 | var max_align: Alignment = .none; |
| ... | @@ -6196,7 +6160,7 @@ pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment { | ... | @@ -6196,7 +6160,7 @@ pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment { |
| 6196 | /// Returns the field alignment, assuming the union is not packed. | 6160 | /// Returns the field alignment, assuming the union is not packed. |
| 6197 | /// Keep implementation in sync with `Sema.unionFieldAlignment`. | 6161 | /// Keep implementation in sync with `Sema.unionFieldAlignment`. |
| 6198 | /// Prefer to call that function instead of this one during Sema. | 6162 | /// Prefer to call that function instead of this one during Sema. |
| 6199 | pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_index: u32) Alignment { | 6163 | pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.LoadedUnionType, field_index: u32) Alignment { |
| 6200 | const ip = &mod.intern_pool; | 6164 | const ip = &mod.intern_pool; |
| 6201 | const field_align = u.fieldAlign(ip, field_index); | 6165 | const field_align = u.fieldAlign(ip, field_index); |
| 6202 | if (field_align != .none) return field_align; | 6166 | if (field_align != .none) return field_align; |
| ... | @@ -6205,12 +6169,11 @@ pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_in | ... | @@ -6205,12 +6169,11 @@ pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_in |
| 6205 | } | 6169 | } |
| 6206 | 6170 | ||
| 6207 | /// Returns the index of the active field, given the current tag value | 6171 | /// Returns the index of the active field, given the current tag value |
| 6208 | pub fn unionTagFieldIndex(mod: *Module, u: InternPool.UnionType, enum_tag: Value) ?u32 { | 6172 | pub fn unionTagFieldIndex(mod: *Module, u: InternPool.LoadedUnionType, enum_tag: Value) ?u32 { |
| 6209 | const ip = &mod.intern_pool; | 6173 | const ip = &mod.intern_pool; |
| 6210 | if (enum_tag.toIntern() == .none) return null; | 6174 | if (enum_tag.toIntern() == .none) return null; |
| 6211 | assert(ip.typeOf(enum_tag.toIntern()) == u.enum_tag_ty); | 6175 | assert(ip.typeOf(enum_tag.toIntern()) == u.enum_tag_ty); |
| 6212 | const enum_type = ip.indexToKey(u.enum_tag_ty).enum_type; | 6176 | return u.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern()); |
| 6213 | return enum_type.tagValueIndex(ip, enum_tag.toIntern()); | ||
| 6214 | } | 6177 | } |
| 6215 | 6178 | ||
| 6216 | /// Returns the field alignment of a non-packed struct in byte units. | 6179 | /// Returns the field alignment of a non-packed struct in byte units. |
| ... | @@ -6257,7 +6220,7 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment { | ... | @@ -6257,7 +6220,7 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment { |
| 6257 | /// projects. | 6220 | /// projects. |
| 6258 | pub fn structPackedFieldBitOffset( | 6221 | pub fn structPackedFieldBitOffset( |
| 6259 | mod: *Module, | 6222 | mod: *Module, |
| 6260 | struct_type: InternPool.Key.StructType, | 6223 | struct_type: InternPool.LoadedStructType, |
| 6261 | field_index: u32, | 6224 | field_index: u32, |
| 6262 | ) u16 { | 6225 | ) u16 { |
| 6263 | const ip = &mod.intern_pool; | 6226 | const ip = &mod.intern_pool; |
src/Package/Module.zig+37-3| ... | @@ -63,6 +63,11 @@ pub const CreateOptions = struct { | ... | @@ -63,6 +63,11 @@ pub const CreateOptions = struct { |
| 63 | 63 | ||
| 64 | builtin_mod: ?*Package.Module, | 64 | builtin_mod: ?*Package.Module, |
| 65 | 65 | ||
| 66 | /// Allocated into the given `arena`. Should be shared across all module creations in a Compilation. | ||
| 67 | /// Ignored if `builtin_mod` is passed or if `!have_zcu`. | ||
| 68 | /// Otherwise, may be `null` only if this Compilation consists of a single module. | ||
| 69 | builtin_modules: ?*std.StringHashMapUnmanaged(*Module), | ||
| 70 | |||
| 66 | pub const Paths = struct { | 71 | pub const Paths = struct { |
| 67 | root: Package.Path, | 72 | root: Package.Path, |
| 68 | /// Relative to `root`. May contain path separators. | 73 | /// Relative to `root`. May contain path separators. |
| ... | @@ -364,11 +369,37 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { | ... | @@ -364,11 +369,37 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 364 | .wasi_exec_model = options.global.wasi_exec_model, | 369 | .wasi_exec_model = options.global.wasi_exec_model, |
| 365 | }, arena); | 370 | }, arena); |
| 366 | 371 | ||
| 372 | const new = if (options.builtin_modules) |builtins| new: { | ||
| 373 | const gop = try builtins.getOrPut(arena, generated_builtin_source); | ||
| 374 | if (gop.found_existing) break :b gop.value_ptr.*; | ||
| 375 | errdefer builtins.removeByPtr(gop.key_ptr); | ||
| 376 | const new = try arena.create(Module); | ||
| 377 | gop.value_ptr.* = new; | ||
| 378 | break :new new; | ||
| 379 | } else try arena.create(Module); | ||
| 380 | errdefer if (options.builtin_modules) |builtins| assert(builtins.remove(generated_builtin_source)); | ||
| 381 | |||
| 367 | const new_file = try arena.create(File); | 382 | const new_file = try arena.create(File); |
| 368 | 383 | ||
| 369 | const digest = Cache.HashHelper.oneShot(generated_builtin_source); | 384 | const bin_digest, const hex_digest = digest: { |
| 370 | const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest); | 385 | var hasher: Cache.Hasher = Cache.hasher_init; |
| 371 | const new = try arena.create(Module); | 386 | hasher.update(generated_builtin_source); |
| 387 | |||
| 388 | var bin_digest: Cache.BinDigest = undefined; | ||
| 389 | hasher.final(&bin_digest); | ||
| 390 | |||
| 391 | var hex_digest: Cache.HexDigest = undefined; | ||
| 392 | _ = std.fmt.bufPrint( | ||
| 393 | &hex_digest, | ||
| 394 | "{s}", | ||
| 395 | .{std.fmt.fmtSliceHexLower(&bin_digest)}, | ||
| 396 | ) catch unreachable; | ||
| 397 | |||
| 398 | break :digest .{ bin_digest, hex_digest }; | ||
| 399 | }; | ||
| 400 | |||
| 401 | const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ hex_digest); | ||
| 402 | |||
| 372 | new.* = .{ | 403 | new.* = .{ |
| 373 | .root = .{ | 404 | .root = .{ |
| 374 | .root_dir = options.global_cache_directory, | 405 | .root_dir = options.global_cache_directory, |
| ... | @@ -415,6 +446,9 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { | ... | @@ -415,6 +446,9 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 415 | .status = .never_loaded, | 446 | .status = .never_loaded, |
| 416 | .mod = new, | 447 | .mod = new, |
| 417 | .root_decl = .none, | 448 | .root_decl = .none, |
| 449 | // We might as well use this digest for the File `path digest`, since there's a | ||
| 450 | // one-to-one correspondence here between distinct paths and distinct contents. | ||
| 451 | .path_digest = bin_digest, | ||
| 418 | }; | 452 | }; |
| 419 | break :b new; | 453 | break :b new; |
| 420 | }; | 454 | }; |
src/Sema.zig+993-922| ... | @@ -155,7 +155,6 @@ const Namespace = Module.Namespace; | ... | @@ -155,7 +155,6 @@ const Namespace = Module.Namespace; |
| 155 | const CompileError = Module.CompileError; | 155 | const CompileError = Module.CompileError; |
| 156 | const SemaError = Module.SemaError; | 156 | const SemaError = Module.SemaError; |
| 157 | const Decl = Module.Decl; | 157 | const Decl = Module.Decl; |
| 158 | const CaptureScope = Module.CaptureScope; | ||
| 159 | const LazySrcLoc = std.zig.LazySrcLoc; | 158 | const LazySrcLoc = std.zig.LazySrcLoc; |
| 160 | const RangeSet = @import("RangeSet.zig"); | 159 | const RangeSet = @import("RangeSet.zig"); |
| 161 | const target_util = @import("target.zig"); | 160 | const target_util = @import("target.zig"); |
| ... | @@ -331,8 +330,6 @@ pub const Block = struct { | ... | @@ -331,8 +330,6 @@ pub const Block = struct { |
| 331 | /// used to add a `func_instance` into the `InternPool`. | 330 | /// used to add a `func_instance` into the `InternPool`. |
| 332 | params: std.MultiArrayList(Param) = .{}, | 331 | params: std.MultiArrayList(Param) = .{}, |
| 333 | 332 | ||
| 334 | wip_capture_scope: CaptureScope.Index, | ||
| 335 | |||
| 336 | label: ?*Label = null, | 333 | label: ?*Label = null, |
| 337 | inlining: ?*Inlining, | 334 | inlining: ?*Inlining, |
| 338 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. | 335 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. |
| ... | @@ -475,7 +472,6 @@ pub const Block = struct { | ... | @@ -475,7 +472,6 @@ pub const Block = struct { |
| 475 | .src_decl = parent.src_decl, | 472 | .src_decl = parent.src_decl, |
| 476 | .namespace = parent.namespace, | 473 | .namespace = parent.namespace, |
| 477 | .instructions = .{}, | 474 | .instructions = .{}, |
| 478 | .wip_capture_scope = parent.wip_capture_scope, | ||
| 479 | .label = null, | 475 | .label = null, |
| 480 | .inlining = parent.inlining, | 476 | .inlining = parent.inlining, |
| 481 | .is_comptime = parent.is_comptime, | 477 | .is_comptime = parent.is_comptime, |
| ... | @@ -974,12 +970,6 @@ fn analyzeBodyInner( | ... | @@ -974,12 +970,6 @@ fn analyzeBodyInner( |
| 974 | 970 | ||
| 975 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); | 971 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); |
| 976 | 972 | ||
| 977 | // Most of the time, we don't need to construct a new capture scope for a | ||
| 978 | // block. However, successive iterations of comptime loops can capture | ||
| 979 | // different values for the same Zir.Inst.Index, so in those cases, we will | ||
| 980 | // have to create nested capture scopes; see the `.repeat` case below. | ||
| 981 | const parent_capture_scope = block.wip_capture_scope; | ||
| 982 | |||
| 983 | const mod = sema.mod; | 973 | const mod = sema.mod; |
| 984 | const map = &sema.inst_map; | 974 | const map = &sema.inst_map; |
| 985 | const tags = sema.code.instructions.items(.tag); | 975 | const tags = sema.code.instructions.items(.tag); |
| ... | @@ -1028,7 +1018,6 @@ fn analyzeBodyInner( | ... | @@ -1028,7 +1018,6 @@ fn analyzeBodyInner( |
| 1028 | .c_import => try sema.zirCImport(block, inst), | 1018 | .c_import => try sema.zirCImport(block, inst), |
| 1029 | .call => try sema.zirCall(block, inst, .direct), | 1019 | .call => try sema.zirCall(block, inst, .direct), |
| 1030 | .field_call => try sema.zirCall(block, inst, .field), | 1020 | .field_call => try sema.zirCall(block, inst, .field), |
| 1031 | .closure_get => try sema.zirClosureGet(block, inst), | ||
| 1032 | .cmp_lt => try sema.zirCmp(block, inst, .lt), | 1021 | .cmp_lt => try sema.zirCmp(block, inst, .lt), |
| 1033 | .cmp_lte => try sema.zirCmp(block, inst, .lte), | 1022 | .cmp_lte => try sema.zirCmp(block, inst, .lte), |
| 1034 | .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)), | 1023 | .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)), |
| ... | @@ -1275,6 +1264,7 @@ fn analyzeBodyInner( | ... | @@ -1275,6 +1264,7 @@ fn analyzeBodyInner( |
| 1275 | .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), | 1264 | .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), |
| 1276 | .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), | 1265 | .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), |
| 1277 | .in_comptime => try sema.zirInComptime( block), | 1266 | .in_comptime => try sema.zirInComptime( block), |
| 1267 | .closure_get => try sema.zirClosureGet( block, extended), | ||
| 1278 | // zig fmt: on | 1268 | // zig fmt: on |
| 1279 | 1269 | ||
| 1280 | .fence => { | 1270 | .fence => { |
| ... | @@ -1453,11 +1443,6 @@ fn analyzeBodyInner( | ... | @@ -1453,11 +1443,6 @@ fn analyzeBodyInner( |
| 1453 | i += 1; | 1443 | i += 1; |
| 1454 | continue; | 1444 | continue; |
| 1455 | }, | 1445 | }, |
| 1456 | .closure_capture => { | ||
| 1457 | try sema.zirClosureCapture(block, inst); | ||
| 1458 | i += 1; | ||
| 1459 | continue; | ||
| 1460 | }, | ||
| 1461 | .memcpy => { | 1446 | .memcpy => { |
| 1462 | try sema.zirMemcpy(block, inst); | 1447 | try sema.zirMemcpy(block, inst); |
| 1463 | i += 1; | 1448 | i += 1; |
| ... | @@ -1534,11 +1519,6 @@ fn analyzeBodyInner( | ... | @@ -1534,11 +1519,6 @@ fn analyzeBodyInner( |
| 1534 | // Send comptime control flow back to the beginning of this block. | 1519 | // Send comptime control flow back to the beginning of this block. |
| 1535 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); | 1520 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); |
| 1536 | try sema.emitBackwardBranch(block, src); | 1521 | try sema.emitBackwardBranch(block, src); |
| 1537 | |||
| 1538 | // We need to construct new capture scopes for the next loop iteration so it | ||
| 1539 | // can capture values without clobbering the earlier iteration's captures. | ||
| 1540 | block.wip_capture_scope = try mod.createCaptureScope(parent_capture_scope); | ||
| 1541 | |||
| 1542 | i = 0; | 1522 | i = 0; |
| 1543 | continue; | 1523 | continue; |
| 1544 | } else { | 1524 | } else { |
| ... | @@ -1552,11 +1532,6 @@ fn analyzeBodyInner( | ... | @@ -1552,11 +1532,6 @@ fn analyzeBodyInner( |
| 1552 | // Send comptime control flow back to the beginning of this block. | 1532 | // Send comptime control flow back to the beginning of this block. |
| 1553 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); | 1533 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); |
| 1554 | try sema.emitBackwardBranch(block, src); | 1534 | try sema.emitBackwardBranch(block, src); |
| 1555 | |||
| 1556 | // We need to construct new capture scopes for the next loop iteration so it | ||
| 1557 | // can capture values without clobbering the earlier iteration's captures. | ||
| 1558 | block.wip_capture_scope = try mod.createCaptureScope(parent_capture_scope); | ||
| 1559 | |||
| 1560 | i = 0; | 1535 | i = 0; |
| 1561 | continue; | 1536 | continue; |
| 1562 | }, | 1537 | }, |
| ... | @@ -1855,10 +1830,6 @@ fn analyzeBodyInner( | ... | @@ -1855,10 +1830,6 @@ fn analyzeBodyInner( |
| 1855 | map.putAssumeCapacity(inst, air_inst); | 1830 | map.putAssumeCapacity(inst, air_inst); |
| 1856 | i += 1; | 1831 | i += 1; |
| 1857 | } | 1832 | } |
| 1858 | |||
| 1859 | // We may have overwritten the capture scope due to a `repeat` instruction where | ||
| 1860 | // the body had a capture; restore it now. | ||
| 1861 | block.wip_capture_scope = parent_capture_scope; | ||
| 1862 | } | 1833 | } |
| 1863 | 1834 | ||
| 1864 | pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { | 1835 | pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { |
| ... | @@ -2698,21 +2669,61 @@ fn analyzeAsInt( | ... | @@ -2698,21 +2669,61 @@ fn analyzeAsInt( |
| 2698 | return (try val.getUnsignedIntAdvanced(mod, sema)).?; | 2669 | return (try val.getUnsignedIntAdvanced(mod, sema)).?; |
| 2699 | } | 2670 | } |
| 2700 | 2671 | ||
| 2701 | pub fn getStructType( | 2672 | /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, |
| 2673 | /// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`. | ||
| 2674 | fn getCaptures(sema: *Sema, block: *Block, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { | ||
| 2675 | const zcu = sema.mod; | ||
| 2676 | const ip = &zcu.intern_pool; | ||
| 2677 | const parent_captures: InternPool.CaptureValue.Slice = zcu.namespacePtr(block.namespace).getType(zcu).getCaptures(zcu); | ||
| 2678 | |||
| 2679 | const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len); | ||
| 2680 | |||
| 2681 | for (sema.code.extra[extra_index..][0..captures_len], captures) |raw, *capture| { | ||
| 2682 | const zir_capture: Zir.Inst.Capture = @bitCast(raw); | ||
| 2683 | capture.* = switch (zir_capture.unwrap()) { | ||
| 2684 | .nested => |parent_idx| parent_captures.get(ip)[parent_idx], | ||
| 2685 | .instruction => |inst| InternPool.CaptureValue.wrap(capture: { | ||
| 2686 | const air_ref = try sema.resolveInst(inst.toRef()); | ||
| 2687 | if (try sema.resolveValueResolveLazy(air_ref)) |val| { | ||
| 2688 | break :capture .{ .@"comptime" = val.toIntern() }; | ||
| 2689 | } | ||
| 2690 | break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() }; | ||
| 2691 | }), | ||
| 2692 | .decl_val => |str| capture: { | ||
| 2693 | const decl_name = try ip.getOrPutString(sema.gpa, sema.code.nullTerminatedString(str)); | ||
| 2694 | const decl = try sema.lookupIdentifier(block, .unneeded, decl_name); // TODO: could we need this src loc? | ||
| 2695 | break :capture InternPool.CaptureValue.wrap(.{ .decl_val = decl }); | ||
| 2696 | }, | ||
| 2697 | .decl_ref => |str| capture: { | ||
| 2698 | const decl_name = try ip.getOrPutString(sema.gpa, sema.code.nullTerminatedString(str)); | ||
| 2699 | const decl = try sema.lookupIdentifier(block, .unneeded, decl_name); // TODO: could we need this src loc? | ||
| 2700 | break :capture InternPool.CaptureValue.wrap(.{ .decl_ref = decl }); | ||
| 2701 | }, | ||
| 2702 | }; | ||
| 2703 | } | ||
| 2704 | |||
| 2705 | return captures; | ||
| 2706 | } | ||
| 2707 | |||
| 2708 | fn zirStructDecl( | ||
| 2702 | sema: *Sema, | 2709 | sema: *Sema, |
| 2703 | decl: InternPool.DeclIndex, | 2710 | block: *Block, |
| 2704 | namespace: InternPool.NamespaceIndex, | 2711 | extended: Zir.Inst.Extended.InstData, |
| 2705 | tracked_inst: InternPool.TrackedInst.Index, | 2712 | inst: Zir.Inst.Index, |
| 2706 | ) !InternPool.Index { | 2713 | ) CompileError!Air.Inst.Ref { |
| 2707 | const mod = sema.mod; | 2714 | const mod = sema.mod; |
| 2708 | const gpa = sema.gpa; | 2715 | const gpa = sema.gpa; |
| 2709 | const ip = &mod.intern_pool; | 2716 | const ip = &mod.intern_pool; |
| 2710 | const zir_index = tracked_inst.resolve(ip); | ||
| 2711 | const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended; | ||
| 2712 | assert(extended.opcode == .struct_decl); | ||
| 2713 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 2717 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 2718 | const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand); | ||
| 2719 | const src = extra.data.src(); | ||
| 2720 | var extra_index = extra.end; | ||
| 2714 | 2721 | ||
| 2715 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; | 2722 | const captures_len = if (small.has_captures_len) blk: { |
| 2723 | const captures_len = sema.code.extra[extra_index]; | ||
| 2724 | extra_index += 1; | ||
| 2725 | break :blk captures_len; | ||
| 2726 | } else 0; | ||
| 2716 | const fields_len = if (small.has_fields_len) blk: { | 2727 | const fields_len = if (small.has_fields_len) blk: { |
| 2717 | const fields_len = sema.code.extra[extra_index]; | 2728 | const fields_len = sema.code.extra[extra_index]; |
| 2718 | extra_index += 1; | 2729 | extra_index += 1; |
| ... | @@ -2724,6 +2735,9 @@ pub fn getStructType( | ... | @@ -2724,6 +2735,9 @@ pub fn getStructType( |
| 2724 | break :blk decls_len; | 2735 | break :blk decls_len; |
| 2725 | } else 0; | 2736 | } else 0; |
| 2726 | 2737 | ||
| 2738 | const captures = try sema.getCaptures(block, extra_index, captures_len); | ||
| 2739 | extra_index += captures_len; | ||
| 2740 | |||
| 2727 | if (small.has_backing_int) { | 2741 | if (small.has_backing_int) { |
| 2728 | const backing_int_body_len = sema.code.extra[extra_index]; | 2742 | const backing_int_body_len = sema.code.extra[extra_index]; |
| 2729 | extra_index += 1; // backing_int_body_len | 2743 | extra_index += 1; // backing_int_body_len |
| ... | @@ -2734,49 +2748,38 @@ pub fn getStructType( | ... | @@ -2734,49 +2748,38 @@ pub fn getStructType( |
| 2734 | } | 2748 | } |
| 2735 | } | 2749 | } |
| 2736 | 2750 | ||
| 2737 | const decls = sema.code.bodySlice(extra_index, decls_len); | 2751 | const wip_ty = switch (try ip.getStructType(gpa, .{ |
| 2738 | try mod.scanNamespace(namespace, decls, mod.declPtr(decl)); | ||
| 2739 | extra_index += decls_len; | ||
| 2740 | |||
| 2741 | const ty = try ip.getStructType(gpa, .{ | ||
| 2742 | .decl = decl, | ||
| 2743 | .namespace = namespace.toOptional(), | ||
| 2744 | .zir_index = tracked_inst.toOptional(), | ||
| 2745 | .layout = small.layout, | 2752 | .layout = small.layout, |
| 2746 | .known_non_opv = small.known_non_opv, | ||
| 2747 | .is_tuple = small.is_tuple, | ||
| 2748 | .fields_len = fields_len, | 2753 | .fields_len = fields_len, |
| 2754 | .known_non_opv = small.known_non_opv, | ||
| 2749 | .requires_comptime = if (small.known_comptime_only) .yes else .unknown, | 2755 | .requires_comptime = if (small.known_comptime_only) .yes else .unknown, |
| 2750 | .any_default_inits = small.any_default_inits, | 2756 | .is_tuple = small.is_tuple, |
| 2751 | .any_comptime_fields = small.any_comptime_fields, | 2757 | .any_comptime_fields = small.any_comptime_fields, |
| 2758 | .any_default_inits = small.any_default_inits, | ||
| 2752 | .inits_resolved = false, | 2759 | .inits_resolved = false, |
| 2753 | .any_aligned_fields = small.any_aligned_fields, | 2760 | .any_aligned_fields = small.any_aligned_fields, |
| 2754 | }); | 2761 | .has_namespace = true or decls_len > 0, // TODO: see below |
| 2755 | 2762 | .key = .{ .declared = .{ | |
| 2756 | return ty; | 2763 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), |
| 2757 | } | 2764 | .captures = captures, |
| 2758 | 2765 | } }, | |
| 2759 | fn zirStructDecl( | 2766 | })) { |
| 2760 | sema: *Sema, | 2767 | .existing => |ty| return Air.internedToRef(ty), |
| 2761 | block: *Block, | 2768 | .wip => |wip| wip: { |
| 2762 | extended: Zir.Inst.Extended.InstData, | 2769 | if (sema.builtin_type_target_index == .none) break :wip wip; |
| 2763 | inst: Zir.Inst.Index, | 2770 | var new = wip; |
| 2764 | ) CompileError!Air.Inst.Ref { | 2771 | new.index = sema.builtin_type_target_index; |
| 2765 | const mod = sema.mod; | 2772 | ip.resolveBuiltinType(new.index, wip.index); |
| 2766 | const ip = &mod.intern_pool; | 2773 | break :wip new; |
| 2767 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 2774 | }, |
| 2768 | const src = sema.code.extraData(Zir.Inst.StructDecl, extended.operand).data.src(); | 2775 | }; |
| 2769 | 2776 | errdefer wip_ty.cancel(ip); | |
| 2770 | // Because these three things each reference each other, `undefined` | ||
| 2771 | // placeholders are used before being set after the struct type gains an | ||
| 2772 | // InternPool index. | ||
| 2773 | 2777 | ||
| 2774 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 2778 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 2775 | .ty = Type.noreturn, | 2779 | .ty = Type.type, |
| 2776 | .val = Value.@"unreachable", | 2780 | .val = Value.fromInterned(wip_ty.index), |
| 2777 | }, small.name_strategy, "struct", inst); | 2781 | }, small.name_strategy, "struct", inst); |
| 2778 | const new_decl = mod.declPtr(new_decl_index); | 2782 | mod.declPtr(new_decl_index).owns_tv = true; |
| 2779 | new_decl.owns_tv = true; | ||
| 2780 | errdefer mod.abortAnonDecl(new_decl_index); | 2783 | errdefer mod.abortAnonDecl(new_decl_index); |
| 2781 | 2784 | ||
| 2782 | if (sema.mod.comp.debug_incremental) { | 2785 | if (sema.mod.comp.debug_incremental) { |
| ... | @@ -2787,31 +2790,21 @@ fn zirStructDecl( | ... | @@ -2787,31 +2790,21 @@ fn zirStructDecl( |
| 2787 | ); | 2790 | ); |
| 2788 | } | 2791 | } |
| 2789 | 2792 | ||
| 2790 | const new_namespace_index = try mod.createNamespace(.{ | 2793 | // TODO: if AstGen tells us `@This` was not used in the fields, we can elide the namespace. |
| 2794 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (true or decls_len > 0) (try mod.createNamespace(.{ | ||
| 2791 | .parent = block.namespace.toOptional(), | 2795 | .parent = block.namespace.toOptional(), |
| 2792 | .decl_index = new_decl_index, | 2796 | .decl_index = new_decl_index, |
| 2793 | .file_scope = block.getFileScope(mod), | 2797 | .file_scope = block.getFileScope(mod), |
| 2794 | }); | 2798 | })).toOptional() else .none; |
| 2795 | errdefer mod.destroyNamespace(new_namespace_index); | 2799 | errdefer if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns); |
| 2796 | |||
| 2797 | const struct_ty = ty: { | ||
| 2798 | const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst); | ||
| 2799 | const ty = try sema.getStructType(new_decl_index, new_namespace_index, tracked_inst); | ||
| 2800 | if (sema.builtin_type_target_index != .none) { | ||
| 2801 | ip.resolveBuiltinType(sema.builtin_type_target_index, ty); | ||
| 2802 | break :ty sema.builtin_type_target_index; | ||
| 2803 | } | ||
| 2804 | break :ty ty; | ||
| 2805 | }; | ||
| 2806 | // TODO: figure out InternPool removals for incremental compilation | ||
| 2807 | //errdefer ip.remove(struct_ty); | ||
| 2808 | 2800 | ||
| 2809 | new_decl.ty = Type.type; | 2801 | if (new_namespace_index.unwrap()) |ns| { |
| 2810 | new_decl.val = Value.fromInterned(struct_ty); | 2802 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| 2803 | try mod.scanNamespace(ns, decls, mod.declPtr(new_decl_index)); | ||
| 2804 | } | ||
| 2811 | 2805 | ||
| 2812 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | ||
| 2813 | try mod.finalizeAnonDecl(new_decl_index); | 2806 | try mod.finalizeAnonDecl(new_decl_index); |
| 2814 | return decl_val; | 2807 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index)); |
| 2815 | } | 2808 | } |
| 2816 | 2809 | ||
| 2817 | fn createAnonymousDeclTypeNamed( | 2810 | fn createAnonymousDeclTypeNamed( |
| ... | @@ -2827,10 +2820,9 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2827,10 +2820,9 @@ fn createAnonymousDeclTypeNamed( |
| 2827 | const ip = &mod.intern_pool; | 2820 | const ip = &mod.intern_pool; |
| 2828 | const gpa = sema.gpa; | 2821 | const gpa = sema.gpa; |
| 2829 | const namespace = block.namespace; | 2822 | const namespace = block.namespace; |
| 2830 | const src_scope = block.wip_capture_scope; | ||
| 2831 | const src_decl = mod.declPtr(block.src_decl); | 2823 | const src_decl = mod.declPtr(block.src_decl); |
| 2832 | const src_node = src_decl.relativeToNodeIndex(src.node_offset.x); | 2824 | const src_node = src_decl.relativeToNodeIndex(src.node_offset.x); |
| 2833 | const new_decl_index = try mod.allocateNewDecl(namespace, src_node, src_scope); | 2825 | const new_decl_index = try mod.allocateNewDecl(namespace, src_node); |
| 2834 | errdefer mod.destroyDecl(new_decl_index); | 2826 | errdefer mod.destroyDecl(new_decl_index); |
| 2835 | 2827 | ||
| 2836 | switch (name_strategy) { | 2828 | switch (name_strategy) { |
| ... | @@ -2922,6 +2914,7 @@ fn zirEnumDecl( | ... | @@ -2922,6 +2914,7 @@ fn zirEnumDecl( |
| 2922 | 2914 | ||
| 2923 | const mod = sema.mod; | 2915 | const mod = sema.mod; |
| 2924 | const gpa = sema.gpa; | 2916 | const gpa = sema.gpa; |
| 2917 | const ip = &mod.intern_pool; | ||
| 2925 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); | 2918 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); |
| 2926 | const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); | 2919 | const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); |
| 2927 | var extra_index: usize = extra.end; | 2920 | var extra_index: usize = extra.end; |
| ... | @@ -2935,6 +2928,12 @@ fn zirEnumDecl( | ... | @@ -2935,6 +2928,12 @@ fn zirEnumDecl( |
| 2935 | break :blk tag_type_ref; | 2928 | break :blk tag_type_ref; |
| 2936 | } else .none; | 2929 | } else .none; |
| 2937 | 2930 | ||
| 2931 | const captures_len = if (small.has_captures_len) blk: { | ||
| 2932 | const captures_len = sema.code.extra[extra_index]; | ||
| 2933 | extra_index += 1; | ||
| 2934 | break :blk captures_len; | ||
| 2935 | } else 0; | ||
| 2936 | |||
| 2938 | const body_len = if (small.has_body_len) blk: { | 2937 | const body_len = if (small.has_body_len) blk: { |
| 2939 | const body_len = sema.code.extra[extra_index]; | 2938 | const body_len = sema.code.extra[extra_index]; |
| 2940 | extra_index += 1; | 2939 | extra_index += 1; |
| ... | @@ -2953,14 +2952,57 @@ fn zirEnumDecl( | ... | @@ -2953,14 +2952,57 @@ fn zirEnumDecl( |
| 2953 | break :blk decls_len; | 2952 | break :blk decls_len; |
| 2954 | } else 0; | 2953 | } else 0; |
| 2955 | 2954 | ||
| 2956 | // Because these three things each reference each other, `undefined` | 2955 | const captures = try sema.getCaptures(block, extra_index, captures_len); |
| 2957 | // placeholders are used before being set after the enum type gains an | 2956 | extra_index += captures_len; |
| 2958 | // InternPool index. | 2957 | |
| 2958 | const decls = sema.code.bodySlice(extra_index, decls_len); | ||
| 2959 | extra_index += decls_len; | ||
| 2960 | |||
| 2961 | const body = sema.code.bodySlice(extra_index, body_len); | ||
| 2962 | extra_index += body.len; | ||
| 2963 | |||
| 2964 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; | ||
| 2965 | const body_end = extra_index; | ||
| 2966 | extra_index += bit_bags_count; | ||
| 2967 | |||
| 2968 | const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| { | ||
| 2969 | if (bag != 0) break true; | ||
| 2970 | } else false; | ||
| 2971 | |||
| 2972 | const wip_ty = switch (try ip.getEnumType(gpa, .{ | ||
| 2973 | .has_namespace = true or decls_len > 0, // TODO: see below | ||
| 2974 | .has_values = any_values, | ||
| 2975 | .tag_mode = if (small.nonexhaustive) | ||
| 2976 | .nonexhaustive | ||
| 2977 | else if (tag_type_ref == .none) | ||
| 2978 | .auto | ||
| 2979 | else | ||
| 2980 | .explicit, | ||
| 2981 | .fields_len = fields_len, | ||
| 2982 | .key = .{ .declared = .{ | ||
| 2983 | .zir_index = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst), | ||
| 2984 | .captures = captures, | ||
| 2985 | } }, | ||
| 2986 | })) { | ||
| 2987 | .wip => |wip| wip: { | ||
| 2988 | if (sema.builtin_type_target_index == .none) break :wip wip; | ||
| 2989 | var new = wip; | ||
| 2990 | new.index = sema.builtin_type_target_index; | ||
| 2991 | ip.resolveBuiltinType(new.index, wip.index); | ||
| 2992 | break :wip new; | ||
| 2993 | }, | ||
| 2994 | .existing => |ty| return Air.internedToRef(ty), | ||
| 2995 | }; | ||
| 2959 | 2996 | ||
| 2997 | // Once this is `true`, we will not delete the decl or type even upon failure, since we | ||
| 2998 | // have finished constructing the type and are in the process of analyzing it. | ||
| 2960 | var done = false; | 2999 | var done = false; |
| 3000 | |||
| 3001 | errdefer if (!done) wip_ty.cancel(ip); | ||
| 3002 | |||
| 2961 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 3003 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 2962 | .ty = Type.noreturn, | 3004 | .ty = Type.type, |
| 2963 | .val = Value.@"unreachable", | 3005 | .val = Value.fromInterned(wip_ty.index), |
| 2964 | }, small.name_strategy, "enum", inst); | 3006 | }, small.name_strategy, "enum", inst); |
| 2965 | const new_decl = mod.declPtr(new_decl_index); | 3007 | const new_decl = mod.declPtr(new_decl_index); |
| 2966 | new_decl.owns_tv = true; | 3008 | new_decl.owns_tv = true; |
| ... | @@ -2974,56 +3016,21 @@ fn zirEnumDecl( | ... | @@ -2974,56 +3016,21 @@ fn zirEnumDecl( |
| 2974 | ); | 3016 | ); |
| 2975 | } | 3017 | } |
| 2976 | 3018 | ||
| 2977 | const new_namespace_index = try mod.createNamespace(.{ | 3019 | // TODO: if AstGen tells us `@This` was not used in the fields, we can elide the namespace. |
| 3020 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (true or decls_len > 0) (try mod.createNamespace(.{ | ||
| 2978 | .parent = block.namespace.toOptional(), | 3021 | .parent = block.namespace.toOptional(), |
| 2979 | .decl_index = new_decl_index, | 3022 | .decl_index = new_decl_index, |
| 2980 | .file_scope = block.getFileScope(mod), | 3023 | .file_scope = block.getFileScope(mod), |
| 2981 | }); | 3024 | })).toOptional() else .none; |
| 2982 | errdefer if (!done) mod.destroyNamespace(new_namespace_index); | 3025 | errdefer if (!done) if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns); |
| 2983 | |||
| 2984 | const decls = sema.code.bodySlice(extra_index, decls_len); | ||
| 2985 | try mod.scanNamespace(new_namespace_index, decls, new_decl); | ||
| 2986 | extra_index += decls_len; | ||
| 2987 | 3026 | ||
| 2988 | const body = sema.code.bodySlice(extra_index, body_len); | 3027 | if (new_namespace_index.unwrap()) |ns| { |
| 2989 | extra_index += body.len; | 3028 | try mod.scanNamespace(ns, decls, new_decl); |
| 2990 | 3029 | } | |
| 2991 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; | ||
| 2992 | const body_end = extra_index; | ||
| 2993 | extra_index += bit_bags_count; | ||
| 2994 | |||
| 2995 | const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| { | ||
| 2996 | if (bag != 0) break true; | ||
| 2997 | } else false; | ||
| 2998 | |||
| 2999 | const incomplete_enum = incomplete_enum: { | ||
| 3000 | var incomplete_enum = try mod.intern_pool.getIncompleteEnum(gpa, .{ | ||
| 3001 | .decl = new_decl_index, | ||
| 3002 | .namespace = new_namespace_index.toOptional(), | ||
| 3003 | .fields_len = fields_len, | ||
| 3004 | .has_values = any_values, | ||
| 3005 | .tag_mode = if (small.nonexhaustive) | ||
| 3006 | .nonexhaustive | ||
| 3007 | else if (tag_type_ref == .none) | ||
| 3008 | .auto | ||
| 3009 | else | ||
| 3010 | .explicit, | ||
| 3011 | .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(), | ||
| 3012 | }); | ||
| 3013 | if (sema.builtin_type_target_index != .none) { | ||
| 3014 | mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, incomplete_enum.index); | ||
| 3015 | incomplete_enum.index = sema.builtin_type_target_index; | ||
| 3016 | } | ||
| 3017 | break :incomplete_enum incomplete_enum; | ||
| 3018 | }; | ||
| 3019 | // TODO: figure out InternPool removals for incremental compilation | ||
| 3020 | //errdefer if (!done) mod.intern_pool.remove(incomplete_enum.index); | ||
| 3021 | |||
| 3022 | new_decl.ty = Type.type; | ||
| 3023 | new_decl.val = Value.fromInterned(incomplete_enum.index); | ||
| 3024 | 3030 | ||
| 3025 | const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index); | 3031 | // We've finished the initial construction of this type, and are about to perform analysis. |
| 3026 | try mod.finalizeAnonDecl(new_decl_index); | 3032 | // Set the decl and namespace appropriately, and don't destroy anything on failure. |
| 3033 | wip_ty.prepare(ip, new_decl_index, new_namespace_index); | ||
| 3027 | done = true; | 3034 | done = true; |
| 3028 | 3035 | ||
| 3029 | const int_tag_ty = ty: { | 3036 | const int_tag_ty = ty: { |
| ... | @@ -3053,8 +3060,7 @@ fn zirEnumDecl( | ... | @@ -3053,8 +3060,7 @@ fn zirEnumDecl( |
| 3053 | .parent = null, | 3060 | .parent = null, |
| 3054 | .sema = sema, | 3061 | .sema = sema, |
| 3055 | .src_decl = new_decl_index, | 3062 | .src_decl = new_decl_index, |
| 3056 | .namespace = new_namespace_index, | 3063 | .namespace = new_namespace_index.unwrap() orelse block.namespace, |
| 3057 | .wip_capture_scope = try mod.createCaptureScope(new_decl.src_scope), | ||
| 3058 | .instructions = .{}, | 3064 | .instructions = .{}, |
| 3059 | .inlining = null, | 3065 | .inlining = null, |
| 3060 | .is_comptime = true, | 3066 | .is_comptime = true, |
| ... | @@ -3070,7 +3076,6 @@ fn zirEnumDecl( | ... | @@ -3070,7 +3076,6 @@ fn zirEnumDecl( |
| 3070 | if (ty.zigTypeTag(mod) != .Int and ty.zigTypeTag(mod) != .ComptimeInt) { | 3076 | if (ty.zigTypeTag(mod) != .Int and ty.zigTypeTag(mod) != .ComptimeInt) { |
| 3071 | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); | 3077 | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); |
| 3072 | } | 3078 | } |
| 3073 | incomplete_enum.setTagType(&mod.intern_pool, ty.toIntern()); | ||
| 3074 | break :ty ty; | 3079 | break :ty ty; |
| 3075 | } else if (fields_len == 0) { | 3080 | } else if (fields_len == 0) { |
| 3076 | break :ty try mod.intType(.unsigned, 0); | 3081 | break :ty try mod.intType(.unsigned, 0); |
| ... | @@ -3080,6 +3085,8 @@ fn zirEnumDecl( | ... | @@ -3080,6 +3085,8 @@ fn zirEnumDecl( |
| 3080 | } | 3085 | } |
| 3081 | }; | 3086 | }; |
| 3082 | 3087 | ||
| 3088 | wip_ty.setTagTy(ip, int_tag_ty.toIntern()); | ||
| 3089 | |||
| 3083 | if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { | 3090 | if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { |
| 3084 | if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(mod)) { | 3091 | if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(mod)) { |
| 3085 | return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); | 3092 | return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); |
| ... | @@ -3103,7 +3110,6 @@ fn zirEnumDecl( | ... | @@ -3103,7 +3110,6 @@ fn zirEnumDecl( |
| 3103 | extra_index += 2; // field name, doc comment | 3110 | extra_index += 2; // field name, doc comment |
| 3104 | 3111 | ||
| 3105 | const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir); | 3112 | const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir); |
| 3106 | assert(incomplete_enum.addFieldName(&mod.intern_pool, field_name) == null); | ||
| 3107 | 3113 | ||
| 3108 | const tag_overflow = if (has_tag_value) overflow: { | 3114 | const tag_overflow = if (has_tag_value) overflow: { |
| 3109 | const tag_val_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | 3115 | const tag_val_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| ... | @@ -3124,12 +3130,13 @@ fn zirEnumDecl( | ... | @@ -3124,12 +3130,13 @@ fn zirEnumDecl( |
| 3124 | }; | 3130 | }; |
| 3125 | if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true; | 3131 | if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true; |
| 3126 | last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty); | 3132 | last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty); |
| 3127 | if (incomplete_enum.addFieldValue(&mod.intern_pool, last_tag_val.?.toIntern())) |other_index| { | 3133 | if (wip_ty.nextField(&mod.intern_pool, field_name, last_tag_val.?.toIntern())) |conflict| { |
| 3134 | assert(conflict.kind == .value); // AstGen validated names are unique | ||
| 3128 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ | 3135 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ |
| 3129 | .index = field_i, | 3136 | .index = field_i, |
| 3130 | .range = .value, | 3137 | .range = .value, |
| 3131 | }).lazy; | 3138 | }).lazy; |
| 3132 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; | 3139 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; |
| 3133 | const msg = msg: { | 3140 | const msg = msg: { |
| 3134 | const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); | 3141 | const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); |
| 3135 | errdefer msg.destroy(gpa); | 3142 | errdefer msg.destroy(gpa); |
| ... | @@ -3146,9 +3153,10 @@ fn zirEnumDecl( | ... | @@ -3146,9 +3153,10 @@ fn zirEnumDecl( |
| 3146 | else | 3153 | else |
| 3147 | try mod.intValue(int_tag_ty, 0); | 3154 | try mod.intValue(int_tag_ty, 0); |
| 3148 | if (overflow != null) break :overflow true; | 3155 | if (overflow != null) break :overflow true; |
| 3149 | if (incomplete_enum.addFieldValue(&mod.intern_pool, last_tag_val.?.toIntern())) |other_index| { | 3156 | if (wip_ty.nextField(&mod.intern_pool, field_name, last_tag_val.?.toIntern())) |conflict| { |
| 3157 | assert(conflict.kind == .value); // AstGen validated names are unique | ||
| 3150 | const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; | 3158 | const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; |
| 3151 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; | 3159 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; |
| 3152 | const msg = msg: { | 3160 | const msg = msg: { |
| 3153 | const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); | 3161 | const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); |
| 3154 | errdefer msg.destroy(gpa); | 3162 | errdefer msg.destroy(gpa); |
| ... | @@ -3159,6 +3167,7 @@ fn zirEnumDecl( | ... | @@ -3159,6 +3167,7 @@ fn zirEnumDecl( |
| 3159 | } | 3167 | } |
| 3160 | break :overflow false; | 3168 | break :overflow false; |
| 3161 | } else overflow: { | 3169 | } else overflow: { |
| 3170 | assert(wip_ty.nextField(&mod.intern_pool, field_name, .none) == null); | ||
| 3162 | last_tag_val = try mod.intValue(Type.comptime_int, field_i); | 3171 | last_tag_val = try mod.intValue(Type.comptime_int, field_i); |
| 3163 | if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true; | 3172 | if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true; |
| 3164 | last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty); | 3173 | last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty); |
| ... | @@ -3176,7 +3185,9 @@ fn zirEnumDecl( | ... | @@ -3176,7 +3185,9 @@ fn zirEnumDecl( |
| 3176 | return sema.failWithOwnedErrorMsg(block, msg); | 3185 | return sema.failWithOwnedErrorMsg(block, msg); |
| 3177 | } | 3186 | } |
| 3178 | } | 3187 | } |
| 3179 | return decl_val; | 3188 | |
| 3189 | try mod.finalizeAnonDecl(new_decl_index); | ||
| 3190 | return Air.internedToRef(wip_ty.index); | ||
| 3180 | } | 3191 | } |
| 3181 | 3192 | ||
| 3182 | fn zirUnionDecl( | 3193 | fn zirUnionDecl( |
| ... | @@ -3190,6 +3201,7 @@ fn zirUnionDecl( | ... | @@ -3190,6 +3201,7 @@ fn zirUnionDecl( |
| 3190 | 3201 | ||
| 3191 | const mod = sema.mod; | 3202 | const mod = sema.mod; |
| 3192 | const gpa = sema.gpa; | 3203 | const gpa = sema.gpa; |
| 3204 | const ip = &mod.intern_pool; | ||
| 3193 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | 3205 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3194 | const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); | 3206 | const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); |
| 3195 | var extra_index: usize = extra.end; | 3207 | var extra_index: usize = extra.end; |
| ... | @@ -3197,6 +3209,11 @@ fn zirUnionDecl( | ... | @@ -3197,6 +3209,11 @@ fn zirUnionDecl( |
| 3197 | const src = extra.data.src(); | 3209 | const src = extra.data.src(); |
| 3198 | 3210 | ||
| 3199 | extra_index += @intFromBool(small.has_tag_type); | 3211 | extra_index += @intFromBool(small.has_tag_type); |
| 3212 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3213 | const captures_len = sema.code.extra[extra_index]; | ||
| 3214 | extra_index += 1; | ||
| 3215 | break :blk captures_len; | ||
| 3216 | } else 0; | ||
| 3200 | extra_index += @intFromBool(small.has_body_len); | 3217 | extra_index += @intFromBool(small.has_body_len); |
| 3201 | const fields_len = if (small.has_fields_len) blk: { | 3218 | const fields_len = if (small.has_fields_len) blk: { |
| 3202 | const fields_len = sema.code.extra[extra_index]; | 3219 | const fields_len = sema.code.extra[extra_index]; |
| ... | @@ -3210,16 +3227,53 @@ fn zirUnionDecl( | ... | @@ -3210,16 +3227,53 @@ fn zirUnionDecl( |
| 3210 | break :blk decls_len; | 3227 | break :blk decls_len; |
| 3211 | } else 0; | 3228 | } else 0; |
| 3212 | 3229 | ||
| 3213 | // Because these three things each reference each other, `undefined` | 3230 | const captures = try sema.getCaptures(block, extra_index, captures_len); |
| 3214 | // placeholders are used before being set after the union type gains an | 3231 | extra_index += captures_len; |
| 3215 | // InternPool index. | 3232 | |
| 3233 | const wip_ty = switch (try ip.getUnionType(gpa, .{ | ||
| 3234 | .flags = .{ | ||
| 3235 | .layout = small.layout, | ||
| 3236 | .status = .none, | ||
| 3237 | .runtime_tag = if (small.has_tag_type or small.auto_enum_tag) | ||
| 3238 | .tagged | ||
| 3239 | else if (small.layout != .Auto) | ||
| 3240 | .none | ||
| 3241 | else switch (block.wantSafety()) { | ||
| 3242 | true => .safety, | ||
| 3243 | false => .none, | ||
| 3244 | }, | ||
| 3245 | .any_aligned_fields = small.any_aligned_fields, | ||
| 3246 | .requires_comptime = .unknown, | ||
| 3247 | .assumed_runtime_bits = false, | ||
| 3248 | .assumed_pointer_aligned = false, | ||
| 3249 | .alignment = .none, | ||
| 3250 | }, | ||
| 3251 | .has_namespace = true or decls_len != 0, // TODO: see below | ||
| 3252 | .fields_len = fields_len, | ||
| 3253 | .enum_tag_ty = .none, // set later | ||
| 3254 | .field_types = &.{}, // set later | ||
| 3255 | .field_aligns = &.{}, // set later | ||
| 3256 | .key = .{ .declared = .{ | ||
| 3257 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), | ||
| 3258 | .captures = captures, | ||
| 3259 | } }, | ||
| 3260 | })) { | ||
| 3261 | .wip => |wip| wip: { | ||
| 3262 | if (sema.builtin_type_target_index == .none) break :wip wip; | ||
| 3263 | var new = wip; | ||
| 3264 | new.index = sema.builtin_type_target_index; | ||
| 3265 | ip.resolveBuiltinType(new.index, wip.index); | ||
| 3266 | break :wip new; | ||
| 3267 | }, | ||
| 3268 | .existing => |ty| return Air.internedToRef(ty), | ||
| 3269 | }; | ||
| 3270 | errdefer wip_ty.cancel(ip); | ||
| 3216 | 3271 | ||
| 3217 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 3272 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 3218 | .ty = Type.noreturn, | 3273 | .ty = Type.type, |
| 3219 | .val = Value.@"unreachable", | 3274 | .val = Value.fromInterned(wip_ty.index), |
| 3220 | }, small.name_strategy, "union", inst); | 3275 | }, small.name_strategy, "union", inst); |
| 3221 | const new_decl = mod.declPtr(new_decl_index); | 3276 | mod.declPtr(new_decl_index).owns_tv = true; |
| 3222 | new_decl.owns_tv = true; | ||
| 3223 | errdefer mod.abortAnonDecl(new_decl_index); | 3277 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3224 | 3278 | ||
| 3225 | if (sema.mod.comp.debug_incremental) { | 3279 | if (sema.mod.comp.debug_incremental) { |
| ... | @@ -3230,58 +3284,22 @@ fn zirUnionDecl( | ... | @@ -3230,58 +3284,22 @@ fn zirUnionDecl( |
| 3230 | ); | 3284 | ); |
| 3231 | } | 3285 | } |
| 3232 | 3286 | ||
| 3233 | const new_namespace_index = try mod.createNamespace(.{ | 3287 | // TODO: if AstGen tells us `@This` was not used in the fields, we can elide the namespace. |
| 3288 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (true or decls_len > 0) (try mod.createNamespace(.{ | ||
| 3234 | .parent = block.namespace.toOptional(), | 3289 | .parent = block.namespace.toOptional(), |
| 3235 | .decl_index = new_decl_index, | 3290 | .decl_index = new_decl_index, |
| 3236 | .file_scope = block.getFileScope(mod), | 3291 | .file_scope = block.getFileScope(mod), |
| 3237 | }); | 3292 | })).toOptional() else .none; |
| 3238 | errdefer mod.destroyNamespace(new_namespace_index); | 3293 | errdefer if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns); |
| 3239 | 3294 | ||
| 3240 | const union_ty = ty: { | 3295 | if (new_namespace_index.unwrap()) |ns| { |
| 3241 | const ty = try mod.intern_pool.getUnionType(gpa, .{ | 3296 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| 3242 | .flags = .{ | 3297 | try mod.scanNamespace(ns, decls, mod.declPtr(new_decl_index)); |
| 3243 | .layout = small.layout, | 3298 | } |
| 3244 | .status = .none, | ||
| 3245 | .runtime_tag = if (small.has_tag_type or small.auto_enum_tag) | ||
| 3246 | .tagged | ||
| 3247 | else if (small.layout != .Auto) | ||
| 3248 | .none | ||
| 3249 | else switch (block.wantSafety()) { | ||
| 3250 | true => .safety, | ||
| 3251 | false => .none, | ||
| 3252 | }, | ||
| 3253 | .any_aligned_fields = small.any_aligned_fields, | ||
| 3254 | .requires_comptime = .unknown, | ||
| 3255 | .assumed_runtime_bits = false, | ||
| 3256 | .assumed_pointer_aligned = false, | ||
| 3257 | .alignment = .none, | ||
| 3258 | }, | ||
| 3259 | .decl = new_decl_index, | ||
| 3260 | .namespace = new_namespace_index, | ||
| 3261 | .zir_index = (try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst)).toOptional(), | ||
| 3262 | .fields_len = fields_len, | ||
| 3263 | .enum_tag_ty = .none, | ||
| 3264 | .field_types = &.{}, | ||
| 3265 | .field_aligns = &.{}, | ||
| 3266 | }); | ||
| 3267 | if (sema.builtin_type_target_index != .none) { | ||
| 3268 | mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, ty); | ||
| 3269 | break :ty sema.builtin_type_target_index; | ||
| 3270 | } | ||
| 3271 | break :ty ty; | ||
| 3272 | }; | ||
| 3273 | // TODO: figure out InternPool removals for incremental compilation | ||
| 3274 | //errdefer mod.intern_pool.remove(union_ty); | ||
| 3275 | |||
| 3276 | new_decl.ty = Type.type; | ||
| 3277 | new_decl.val = Value.fromInterned(union_ty); | ||
| 3278 | |||
| 3279 | const decls = sema.code.bodySlice(extra_index, decls_len); | ||
| 3280 | try mod.scanNamespace(new_namespace_index, decls, new_decl); | ||
| 3281 | 3299 | ||
| 3282 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | ||
| 3283 | try mod.finalizeAnonDecl(new_decl_index); | 3300 | try mod.finalizeAnonDecl(new_decl_index); |
| 3284 | return decl_val; | 3301 | |
| 3302 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index)); | ||
| 3285 | } | 3303 | } |
| 3286 | 3304 | ||
| 3287 | fn zirOpaqueDecl( | 3305 | fn zirOpaqueDecl( |
| ... | @@ -3294,62 +3312,72 @@ fn zirOpaqueDecl( | ... | @@ -3294,62 +3312,72 @@ fn zirOpaqueDecl( |
| 3294 | defer tracy.end(); | 3312 | defer tracy.end(); |
| 3295 | 3313 | ||
| 3296 | const mod = sema.mod; | 3314 | const mod = sema.mod; |
| 3315 | const gpa = sema.gpa; | ||
| 3316 | const ip = &mod.intern_pool; | ||
| 3317 | |||
| 3297 | const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); | 3318 | const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); |
| 3298 | const extra = sema.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); | 3319 | const extra = sema.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); |
| 3299 | var extra_index: usize = extra.end; | 3320 | var extra_index: usize = extra.end; |
| 3300 | 3321 | ||
| 3301 | const src = extra.data.src(); | 3322 | const src = extra.data.src(); |
| 3302 | 3323 | ||
| 3324 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3325 | const captures_len = sema.code.extra[extra_index]; | ||
| 3326 | extra_index += 1; | ||
| 3327 | break :blk captures_len; | ||
| 3328 | } else 0; | ||
| 3329 | |||
| 3303 | const decls_len = if (small.has_decls_len) blk: { | 3330 | const decls_len = if (small.has_decls_len) blk: { |
| 3304 | const decls_len = sema.code.extra[extra_index]; | 3331 | const decls_len = sema.code.extra[extra_index]; |
| 3305 | extra_index += 1; | 3332 | extra_index += 1; |
| 3306 | break :blk decls_len; | 3333 | break :blk decls_len; |
| 3307 | } else 0; | 3334 | } else 0; |
| 3308 | 3335 | ||
| 3309 | // Because these three things each reference each other, `undefined` | 3336 | const captures = try sema.getCaptures(block, extra_index, captures_len); |
| 3310 | // placeholders are used in two places before being set after the opaque | 3337 | extra_index += captures_len; |
| 3311 | // type gains an InternPool index. | 3338 | |
| 3339 | const wip_ty = switch (try ip.getOpaqueType(gpa, .{ | ||
| 3340 | .has_namespace = decls_len != 0, | ||
| 3341 | .key = .{ .declared = .{ | ||
| 3342 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), | ||
| 3343 | .captures = captures, | ||
| 3344 | } }, | ||
| 3345 | })) { | ||
| 3346 | .wip => |wip| wip, | ||
| 3347 | .existing => |ty| return Air.internedToRef(ty), | ||
| 3348 | }; | ||
| 3349 | errdefer wip_ty.cancel(ip); | ||
| 3312 | 3350 | ||
| 3313 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 3351 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 3314 | .ty = Type.noreturn, | 3352 | .ty = Type.type, |
| 3315 | .val = Value.@"unreachable", | 3353 | .val = Value.fromInterned(wip_ty.index), |
| 3316 | }, small.name_strategy, "opaque", inst); | 3354 | }, small.name_strategy, "opaque", inst); |
| 3317 | const new_decl = mod.declPtr(new_decl_index); | 3355 | mod.declPtr(new_decl_index).owns_tv = true; |
| 3318 | new_decl.owns_tv = true; | ||
| 3319 | errdefer mod.abortAnonDecl(new_decl_index); | 3356 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3320 | 3357 | ||
| 3321 | if (sema.mod.comp.debug_incremental) { | 3358 | if (sema.mod.comp.debug_incremental) { |
| 3322 | try mod.intern_pool.addDependency( | 3359 | try ip.addDependency( |
| 3323 | sema.gpa, | 3360 | gpa, |
| 3324 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | 3361 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), |
| 3325 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | 3362 | .{ .src_hash = try ip.trackZir(gpa, block.getFileScope(mod), inst) }, |
| 3326 | ); | 3363 | ); |
| 3327 | } | 3364 | } |
| 3328 | 3365 | ||
| 3329 | const new_namespace_index = try mod.createNamespace(.{ | 3366 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (decls_len > 0) (try mod.createNamespace(.{ |
| 3330 | .parent = block.namespace.toOptional(), | 3367 | .parent = block.namespace.toOptional(), |
| 3331 | .decl_index = new_decl_index, | 3368 | .decl_index = new_decl_index, |
| 3332 | .file_scope = block.getFileScope(mod), | 3369 | .file_scope = block.getFileScope(mod), |
| 3333 | }); | 3370 | })).toOptional() else .none; |
| 3334 | errdefer mod.destroyNamespace(new_namespace_index); | 3371 | errdefer if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns); |
| 3335 | 3372 | ||
| 3336 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ | 3373 | if (new_namespace_index.unwrap()) |ns| { |
| 3337 | .decl = new_decl_index, | 3374 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| 3338 | .namespace = new_namespace_index, | 3375 | try mod.scanNamespace(ns, decls, mod.declPtr(new_decl_index)); |
| 3339 | .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(), | 3376 | } |
| 3340 | } }); | ||
| 3341 | // TODO: figure out InternPool removals for incremental compilation | ||
| 3342 | //errdefer mod.intern_pool.remove(opaque_ty); | ||
| 3343 | |||
| 3344 | new_decl.ty = Type.type; | ||
| 3345 | new_decl.val = Value.fromInterned(opaque_ty); | ||
| 3346 | |||
| 3347 | const decls = sema.code.bodySlice(extra_index, decls_len); | ||
| 3348 | try mod.scanNamespace(new_namespace_index, decls, new_decl); | ||
| 3349 | 3377 | ||
| 3350 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | ||
| 3351 | try mod.finalizeAnonDecl(new_decl_index); | 3378 | try mod.finalizeAnonDecl(new_decl_index); |
| 3352 | return decl_val; | 3379 | |
| 3380 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index)); | ||
| 3353 | } | 3381 | } |
| 3354 | 3382 | ||
| 3355 | fn zirErrorSetDecl( | 3383 | fn zirErrorSetDecl( |
| ... | @@ -5333,7 +5361,7 @@ fn failWithBadMemberAccess( | ... | @@ -5333,7 +5361,7 @@ fn failWithBadMemberAccess( |
| 5333 | fn failWithBadStructFieldAccess( | 5361 | fn failWithBadStructFieldAccess( |
| 5334 | sema: *Sema, | 5362 | sema: *Sema, |
| 5335 | block: *Block, | 5363 | block: *Block, |
| 5336 | struct_type: InternPool.Key.StructType, | 5364 | struct_type: InternPool.LoadedStructType, |
| 5337 | field_src: LazySrcLoc, | 5365 | field_src: LazySrcLoc, |
| 5338 | field_name: InternPool.NullTerminatedString, | 5366 | field_name: InternPool.NullTerminatedString, |
| 5339 | ) CompileError { | 5367 | ) CompileError { |
| ... | @@ -5359,7 +5387,7 @@ fn failWithBadStructFieldAccess( | ... | @@ -5359,7 +5387,7 @@ fn failWithBadStructFieldAccess( |
| 5359 | fn failWithBadUnionFieldAccess( | 5387 | fn failWithBadUnionFieldAccess( |
| 5360 | sema: *Sema, | 5388 | sema: *Sema, |
| 5361 | block: *Block, | 5389 | block: *Block, |
| 5362 | union_obj: InternPool.UnionType, | 5390 | union_obj: InternPool.LoadedUnionType, |
| 5363 | field_src: LazySrcLoc, | 5391 | field_src: LazySrcLoc, |
| 5364 | field_name: InternPool.NullTerminatedString, | 5392 | field_name: InternPool.NullTerminatedString, |
| 5365 | ) CompileError { | 5393 | ) CompileError { |
| ... | @@ -5780,7 +5808,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -5780,7 +5808,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5780 | .sema = sema, | 5808 | .sema = sema, |
| 5781 | .src_decl = parent_block.src_decl, | 5809 | .src_decl = parent_block.src_decl, |
| 5782 | .namespace = parent_block.namespace, | 5810 | .namespace = parent_block.namespace, |
| 5783 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 5784 | .instructions = .{}, | 5811 | .instructions = .{}, |
| 5785 | .inlining = parent_block.inlining, | 5812 | .inlining = parent_block.inlining, |
| 5786 | .is_comptime = true, | 5813 | .is_comptime = true, |
| ... | @@ -5831,6 +5858,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -5831,6 +5858,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5831 | .global = comp.config, | 5858 | .global = comp.config, |
| 5832 | .parent = parent_mod, | 5859 | .parent = parent_mod, |
| 5833 | .builtin_mod = parent_mod.getBuiltinDependency(), | 5860 | .builtin_mod = parent_mod.getBuiltinDependency(), |
| 5861 | .builtin_modules = null, // `builtin_mod` is set | ||
| 5834 | }) catch |err| switch (err) { | 5862 | }) catch |err| switch (err) { |
| 5835 | // None of these are possible because we are creating a package with | 5863 | // None of these are possible because we are creating a package with |
| 5836 | // the exact same configuration as the parent package, which already | 5864 | // the exact same configuration as the parent package, which already |
| ... | @@ -5900,7 +5928,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt | ... | @@ -5900,7 +5928,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt |
| 5900 | .sema = sema, | 5928 | .sema = sema, |
| 5901 | .src_decl = parent_block.src_decl, | 5929 | .src_decl = parent_block.src_decl, |
| 5902 | .namespace = parent_block.namespace, | 5930 | .namespace = parent_block.namespace, |
| 5903 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 5904 | .instructions = .{}, | 5931 | .instructions = .{}, |
| 5905 | .label = &label, | 5932 | .label = &label, |
| 5906 | .inlining = parent_block.inlining, | 5933 | .inlining = parent_block.inlining, |
| ... | @@ -7515,7 +7542,6 @@ fn analyzeCall( | ... | @@ -7515,7 +7542,6 @@ fn analyzeCall( |
| 7515 | .sema = sema, | 7542 | .sema = sema, |
| 7516 | .src_decl = module_fn.owner_decl, | 7543 | .src_decl = module_fn.owner_decl, |
| 7517 | .namespace = fn_owner_decl.src_namespace, | 7544 | .namespace = fn_owner_decl.src_namespace, |
| 7518 | .wip_capture_scope = try mod.createCaptureScope(fn_owner_decl.src_scope), | ||
| 7519 | .instructions = .{}, | 7545 | .instructions = .{}, |
| 7520 | .label = null, | 7546 | .label = null, |
| 7521 | .inlining = &inlining, | 7547 | .inlining = &inlining, |
| ... | @@ -8036,7 +8062,6 @@ fn instantiateGenericCall( | ... | @@ -8036,7 +8062,6 @@ fn instantiateGenericCall( |
| 8036 | .sema = &child_sema, | 8062 | .sema = &child_sema, |
| 8037 | .src_decl = generic_owner_func.owner_decl, | 8063 | .src_decl = generic_owner_func.owner_decl, |
| 8038 | .namespace = namespace_index, | 8064 | .namespace = namespace_index, |
| 8039 | .wip_capture_scope = try mod.createCaptureScope(fn_owner_decl.src_scope), | ||
| 8040 | .instructions = .{}, | 8065 | .instructions = .{}, |
| 8041 | .inlining = null, | 8066 | .inlining = null, |
| 8042 | .is_comptime = true, | 8067 | .is_comptime = true, |
| ... | @@ -11409,7 +11434,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11409,7 +11434,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11409 | .sema = sema, | 11434 | .sema = sema, |
| 11410 | .src_decl = block.src_decl, | 11435 | .src_decl = block.src_decl, |
| 11411 | .namespace = block.namespace, | 11436 | .namespace = block.namespace, |
| 11412 | .wip_capture_scope = block.wip_capture_scope, | ||
| 11413 | .instructions = .{}, | 11437 | .instructions = .{}, |
| 11414 | .label = &label, | 11438 | .label = &label, |
| 11415 | .inlining = block.inlining, | 11439 | .inlining = block.inlining, |
| ... | @@ -12117,7 +12141,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -12117,7 +12141,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 12117 | .sema = sema, | 12141 | .sema = sema, |
| 12118 | .src_decl = block.src_decl, | 12142 | .src_decl = block.src_decl, |
| 12119 | .namespace = block.namespace, | 12143 | .namespace = block.namespace, |
| 12120 | .wip_capture_scope = block.wip_capture_scope, | ||
| 12121 | .instructions = .{}, | 12144 | .instructions = .{}, |
| 12122 | .label = &label, | 12145 | .label = &label, |
| 12123 | .inlining = block.inlining, | 12146 | .inlining = block.inlining, |
| ... | @@ -12281,7 +12304,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12281,7 +12304,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12281 | extra_index += info.body_len; | 12304 | extra_index += info.body_len; |
| 12282 | 12305 | ||
| 12283 | case_block.instructions.shrinkRetainingCapacity(0); | 12306 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12284 | case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope); | ||
| 12285 | 12307 | ||
| 12286 | const item = case_vals.items[scalar_i]; | 12308 | const item = case_vals.items[scalar_i]; |
| 12287 | // `item` is already guaranteed to be constant known. | 12309 | // `item` is already guaranteed to be constant known. |
| ... | @@ -12339,7 +12361,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12339,7 +12361,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12339 | case_val_idx += items_len; | 12361 | case_val_idx += items_len; |
| 12340 | 12362 | ||
| 12341 | case_block.instructions.shrinkRetainingCapacity(0); | 12363 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12342 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12343 | 12364 | ||
| 12344 | // Generate all possible cases as scalar prongs. | 12365 | // Generate all possible cases as scalar prongs. |
| 12345 | if (info.is_inline) { | 12366 | if (info.is_inline) { |
| ... | @@ -12371,7 +12392,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12371,7 +12392,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12371 | const item_ref = Air.internedToRef(item.toIntern()); | 12392 | const item_ref = Air.internedToRef(item.toIntern()); |
| 12372 | 12393 | ||
| 12373 | case_block.instructions.shrinkRetainingCapacity(0); | 12394 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12374 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12375 | 12395 | ||
| 12376 | if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { | 12396 | if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { |
| 12377 | error.NeededSourceLocation => { | 12397 | error.NeededSourceLocation => { |
| ... | @@ -12411,7 +12431,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12411,7 +12431,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12411 | cases_len += 1; | 12431 | cases_len += 1; |
| 12412 | 12432 | ||
| 12413 | case_block.instructions.shrinkRetainingCapacity(0); | 12433 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12414 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12415 | 12434 | ||
| 12416 | const analyze_body = if (union_originally) blk: { | 12435 | const analyze_body = if (union_originally) blk: { |
| 12417 | const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; | 12436 | const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; |
| ... | @@ -12557,7 +12576,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12557,7 +12576,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12557 | defer gpa.free(cond_body); | 12576 | defer gpa.free(cond_body); |
| 12558 | 12577 | ||
| 12559 | case_block.instructions.shrinkRetainingCapacity(0); | 12578 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12560 | case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope); | ||
| 12561 | 12579 | ||
| 12562 | const body = sema.code.bodySlice(extra_index, info.body_len); | 12580 | const body = sema.code.bodySlice(extra_index, info.body_len); |
| 12563 | extra_index += info.body_len; | 12581 | extra_index += info.body_len; |
| ... | @@ -12618,7 +12636,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12618,7 +12636,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12618 | const item_ref = Air.internedToRef(item_val.toIntern()); | 12636 | const item_ref = Air.internedToRef(item_val.toIntern()); |
| 12619 | 12637 | ||
| 12620 | case_block.instructions.shrinkRetainingCapacity(0); | 12638 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12621 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12622 | 12639 | ||
| 12623 | const analyze_body = if (union_originally) blk: { | 12640 | const analyze_body = if (union_originally) blk: { |
| 12624 | const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; | 12641 | const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; |
| ... | @@ -12669,7 +12686,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12669,7 +12686,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12669 | const item_ref = Air.internedToRef(item_val); | 12686 | const item_ref = Air.internedToRef(item_val); |
| 12670 | 12687 | ||
| 12671 | case_block.instructions.shrinkRetainingCapacity(0); | 12688 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12672 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12673 | 12689 | ||
| 12674 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12690 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12675 | emit_bb = true; | 12691 | emit_bb = true; |
| ... | @@ -12700,7 +12716,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12700,7 +12716,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12700 | const item_ref = Air.internedToRef(cur); | 12716 | const item_ref = Air.internedToRef(cur); |
| 12701 | 12717 | ||
| 12702 | case_block.instructions.shrinkRetainingCapacity(0); | 12718 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12703 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12704 | 12719 | ||
| 12705 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12720 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12706 | emit_bb = true; | 12721 | emit_bb = true; |
| ... | @@ -12728,7 +12743,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12728,7 +12743,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12728 | cases_len += 1; | 12743 | cases_len += 1; |
| 12729 | 12744 | ||
| 12730 | case_block.instructions.shrinkRetainingCapacity(0); | 12745 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12731 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12732 | 12746 | ||
| 12733 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12747 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12734 | emit_bb = true; | 12748 | emit_bb = true; |
| ... | @@ -12754,7 +12768,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12754,7 +12768,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12754 | cases_len += 1; | 12768 | cases_len += 1; |
| 12755 | 12769 | ||
| 12756 | case_block.instructions.shrinkRetainingCapacity(0); | 12770 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12757 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12758 | 12771 | ||
| 12759 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12772 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12760 | emit_bb = true; | 12773 | emit_bb = true; |
| ... | @@ -12783,7 +12796,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12783,7 +12796,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12783 | }; | 12796 | }; |
| 12784 | 12797 | ||
| 12785 | case_block.instructions.shrinkRetainingCapacity(0); | 12798 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12786 | case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope); | ||
| 12787 | 12799 | ||
| 12788 | if (mod.backendSupportsFeature(.is_named_enum_value) and | 12800 | if (mod.backendSupportsFeature(.is_named_enum_value) and |
| 12789 | special.body.len != 0 and block.wantSafety() and | 12801 | special.body.len != 0 and block.wantSafety() and |
| ... | @@ -13327,7 +13339,7 @@ fn validateSwitchItemEnum( | ... | @@ -13327,7 +13339,7 @@ fn validateSwitchItemEnum( |
| 13327 | const ip = &sema.mod.intern_pool; | 13339 | const ip = &sema.mod.intern_pool; |
| 13328 | const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); | 13340 | const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); |
| 13329 | const int = ip.indexToKey(item.val).enum_tag.int; | 13341 | const int = ip.indexToKey(item.val).enum_tag.int; |
| 13330 | const field_index = ip.indexToKey(ip.typeOf(item.val)).enum_type.tagValueIndex(ip, int) orelse { | 13342 | const field_index = ip.loadEnumType(ip.typeOf(item.val)).tagValueIndex(ip, int) orelse { |
| 13331 | const maybe_prev_src = try range_set.add(int, int, switch_prong_src); | 13343 | const maybe_prev_src = try range_set.add(int, int, switch_prong_src); |
| 13332 | try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 13344 | try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| 13333 | return item.ref; | 13345 | return item.ref; |
| ... | @@ -13607,15 +13619,15 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13607,15 +13619,15 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13607 | break :hf field_index < ty.structFieldCount(mod); | 13619 | break :hf field_index < ty.structFieldCount(mod); |
| 13608 | } | 13620 | } |
| 13609 | }, | 13621 | }, |
| 13610 | .struct_type => |struct_type| { | 13622 | .struct_type => { |
| 13611 | break :hf struct_type.nameIndex(ip, field_name) != null; | 13623 | break :hf ip.loadStructType(ty.toIntern()).nameIndex(ip, field_name) != null; |
| 13612 | }, | 13624 | }, |
| 13613 | .union_type => |union_type| { | 13625 | .union_type => { |
| 13614 | const union_obj = ip.loadUnionType(union_type); | 13626 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 13615 | break :hf union_obj.nameIndex(ip, field_name) != null; | 13627 | break :hf union_type.loadTagType(ip).nameIndex(ip, field_name) != null; |
| 13616 | }, | 13628 | }, |
| 13617 | .enum_type => |enum_type| { | 13629 | .enum_type => { |
| 13618 | break :hf enum_type.nameIndex(ip, field_name) != null; | 13630 | break :hf ip.loadEnumType(ty.toIntern()).nameIndex(ip, field_name) != null; |
| 13619 | }, | 13631 | }, |
| 13620 | .array_type => break :hf ip.stringEqlSlice(field_name, "len"), | 13632 | .array_type => break :hf ip.stringEqlSlice(field_name, "len"), |
| 13621 | else => {}, | 13633 | else => {}, |
| ... | @@ -17264,49 +17276,19 @@ fn zirThis( | ... | @@ -17264,49 +17276,19 @@ fn zirThis( |
| 17264 | return sema.analyzeDeclVal(block, src, this_decl_index); | 17276 | return sema.analyzeDeclVal(block, src, this_decl_index); |
| 17265 | } | 17277 | } |
| 17266 | 17278 | ||
| 17267 | fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 17279 | fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 17268 | const mod = sema.mod; | 17280 | const mod = sema.mod; |
| 17269 | const gpa = sema.gpa; | 17281 | const ip = &mod.intern_pool; |
| 17270 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; | 17282 | const captures = mod.namespacePtr(block.namespace).getType(mod).getCaptures(mod); |
| 17271 | // Closures are not necessarily constant values. For example, the | ||
| 17272 | // code might do something like this: | ||
| 17273 | // fn foo(x: anytype) void { const S = struct {field: @TypeOf(x)}; } | ||
| 17274 | // ...in which case the closure_capture instruction has access to a runtime | ||
| 17275 | // value only. In such case only the type is saved into the scope. | ||
| 17276 | const operand = try sema.resolveInst(inst_data.operand); | ||
| 17277 | const ty = sema.typeOf(operand); | ||
| 17278 | const key: CaptureScope.Key = .{ | ||
| 17279 | .zir_index = inst, | ||
| 17280 | .index = block.wip_capture_scope, | ||
| 17281 | }; | ||
| 17282 | if (try sema.resolveValue(operand)) |val| { | ||
| 17283 | try mod.comptime_capture_scopes.put(gpa, key, try val.intern(ty, mod)); | ||
| 17284 | } else { | ||
| 17285 | try mod.runtime_capture_scopes.put(gpa, key, ty.toIntern()); | ||
| 17286 | } | ||
| 17287 | } | ||
| 17288 | 17283 | ||
| 17289 | fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 17284 | const src_node: i32 = @bitCast(extended.operand); |
| 17290 | const mod = sema.mod; | 17285 | const src = LazySrcLoc.nodeOffset(src_node); |
| 17291 | //const ip = &mod.intern_pool; | 17286 | |
| 17292 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].inst_node; | 17287 | const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) { |
| 17293 | var scope: CaptureScope.Index = mod.declPtr(block.src_decl).src_scope; | 17288 | .@"comptime" => |index| return Air.internedToRef(index), |
| 17294 | assert(scope != .none); | 17289 | .runtime => |index| index, |
| 17295 | // Note: The target closure must be in this scope list. | 17290 | .decl_val => |decl_index| return sema.analyzeDeclVal(block, src, decl_index), |
| 17296 | // If it's not here, the zir is invalid, or the list is broken. | 17291 | .decl_ref => |decl_index| return sema.analyzeDeclRef(decl_index), |
| 17297 | const capture_ty = while (true) { | ||
| 17298 | // Note: We don't need to add a dependency here, because | ||
| 17299 | // decls always depend on their lexical parents. | ||
| 17300 | const key: CaptureScope.Key = .{ | ||
| 17301 | .zir_index = inst_data.inst, | ||
| 17302 | .index = scope, | ||
| 17303 | }; | ||
| 17304 | if (mod.comptime_capture_scopes.get(key)) |val| | ||
| 17305 | return Air.internedToRef(val); | ||
| 17306 | if (mod.runtime_capture_scopes.get(key)) |ty| | ||
| 17307 | break ty; | ||
| 17308 | scope = scope.parent(mod); | ||
| 17309 | assert(scope != .none); | ||
| 17310 | }; | 17292 | }; |
| 17311 | 17293 | ||
| 17312 | // The comptime case is handled already above. Runtime case below. | 17294 | // The comptime case is handled already above. Runtime case below. |
| ... | @@ -17322,15 +17304,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -17322,15 +17304,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 17322 | }); | 17304 | }); |
| 17323 | break :name null; | 17305 | break :name null; |
| 17324 | }; | 17306 | }; |
| 17325 | const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node); | 17307 | const node = sema.owner_decl.relativeToNodeIndex(src_node); |
| 17326 | const token = tree.nodes.items(.main_token)[node]; | 17308 | const token = tree.nodes.items(.main_token)[node]; |
| 17327 | break :name tree.tokenSlice(token); | 17309 | break :name tree.tokenSlice(token); |
| 17328 | }; | 17310 | }; |
| 17329 | 17311 | ||
| 17330 | const msg = if (name) |some| | 17312 | const msg = if (name) |some| |
| 17331 | try sema.errMsg(block, inst_data.src(), "'{s}' not accessible outside function scope", .{some}) | 17313 | try sema.errMsg(block, src, "'{s}' not accessible outside function scope", .{some}) |
| 17332 | else | 17314 | else |
| 17333 | try sema.errMsg(block, inst_data.src(), "variable not accessible outside function scope", .{}); | 17315 | try sema.errMsg(block, src, "variable not accessible outside function scope", .{}); |
| 17334 | errdefer msg.destroy(sema.gpa); | 17316 | errdefer msg.destroy(sema.gpa); |
| 17335 | 17317 | ||
| 17336 | // TODO add "declared here" note | 17318 | // TODO add "declared here" note |
| ... | @@ -17350,15 +17332,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -17350,15 +17332,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 17350 | }); | 17332 | }); |
| 17351 | break :name null; | 17333 | break :name null; |
| 17352 | }; | 17334 | }; |
| 17353 | const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node); | 17335 | const node = sema.owner_decl.relativeToNodeIndex(src_node); |
| 17354 | const token = tree.nodes.items(.main_token)[node]; | 17336 | const token = tree.nodes.items(.main_token)[node]; |
| 17355 | break :name tree.tokenSlice(token); | 17337 | break :name tree.tokenSlice(token); |
| 17356 | }; | 17338 | }; |
| 17357 | 17339 | ||
| 17358 | const msg = if (name) |some| | 17340 | const msg = if (name) |some| |
| 17359 | try sema.errMsg(block, inst_data.src(), "'{s}' not accessible from inner function", .{some}) | 17341 | try sema.errMsg(block, src, "'{s}' not accessible from inner function", .{some}) |
| 17360 | else | 17342 | else |
| 17361 | try sema.errMsg(block, inst_data.src(), "variable not accessible from inner function", .{}); | 17343 | try sema.errMsg(block, src, "variable not accessible from inner function", .{}); |
| 17362 | errdefer msg.destroy(sema.gpa); | 17344 | errdefer msg.destroy(sema.gpa); |
| 17363 | 17345 | ||
| 17364 | try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{}); | 17346 | try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{}); |
| ... | @@ -17954,7 +17936,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17954,7 +17936,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17954 | } }))); | 17936 | } }))); |
| 17955 | }, | 17937 | }, |
| 17956 | .Enum => { | 17938 | .Enum => { |
| 17957 | const is_exhaustive = Value.makeBool(ip.indexToKey(ty.toIntern()).enum_type.tag_mode != .nonexhaustive); | 17939 | const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive); |
| 17958 | 17940 | ||
| 17959 | const enum_field_ty = t: { | 17941 | const enum_field_ty = t: { |
| 17960 | const enum_field_ty_decl_index = (try sema.namespaceLookup( | 17942 | const enum_field_ty_decl_index = (try sema.namespaceLookup( |
| ... | @@ -17968,9 +17950,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17968,9 +17950,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17968 | break :t enum_field_ty_decl.val.toType(); | 17950 | break :t enum_field_ty_decl.val.toType(); |
| 17969 | }; | 17951 | }; |
| 17970 | 17952 | ||
| 17971 | const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.indexToKey(ty.toIntern()).enum_type.names.len); | 17953 | const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len); |
| 17972 | for (enum_field_vals, 0..) |*field_val, i| { | 17954 | for (enum_field_vals, 0..) |*field_val, i| { |
| 17973 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 17955 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 17974 | const value_val = if (enum_type.values.len > 0) | 17956 | const value_val = if (enum_type.values.len > 0) |
| 17975 | try mod.intern_pool.getCoercedInts( | 17957 | try mod.intern_pool.getCoercedInts( |
| 17976 | mod.gpa, | 17958 | mod.gpa, |
| ... | @@ -18045,7 +18027,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18045,7 +18027,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18045 | } }); | 18027 | } }); |
| 18046 | }; | 18028 | }; |
| 18047 | 18029 | ||
| 18048 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.indexToKey(ty.toIntern()).enum_type.namespace); | 18030 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace); |
| 18049 | 18031 | ||
| 18050 | const type_enum_ty = t: { | 18032 | const type_enum_ty = t: { |
| 18051 | const type_enum_ty_decl_index = (try sema.namespaceLookup( | 18033 | const type_enum_ty_decl_index = (try sema.namespaceLookup( |
| ... | @@ -18061,7 +18043,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18061,7 +18043,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18061 | 18043 | ||
| 18062 | const field_values = .{ | 18044 | const field_values = .{ |
| 18063 | // tag_type: type, | 18045 | // tag_type: type, |
| 18064 | ip.indexToKey(ty.toIntern()).enum_type.tag_ty, | 18046 | ip.loadEnumType(ty.toIntern()).tag_ty, |
| 18065 | // fields: []const EnumField, | 18047 | // fields: []const EnumField, |
| 18066 | fields_val, | 18048 | fields_val, |
| 18067 | // decls: []const Declaration, | 18049 | // decls: []const Declaration, |
| ... | @@ -18105,14 +18087,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18105,14 +18087,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18105 | 18087 | ||
| 18106 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout | 18088 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout |
| 18107 | const union_obj = mod.typeToUnion(ty).?; | 18089 | const union_obj = mod.typeToUnion(ty).?; |
| 18090 | const tag_type = union_obj.loadTagType(ip); | ||
| 18108 | const layout = union_obj.getLayout(ip); | 18091 | const layout = union_obj.getLayout(ip); |
| 18109 | 18092 | ||
| 18110 | const union_field_vals = try gpa.alloc(InternPool.Index, union_obj.field_names.len); | 18093 | const union_field_vals = try gpa.alloc(InternPool.Index, tag_type.names.len); |
| 18111 | defer gpa.free(union_field_vals); | 18094 | defer gpa.free(union_field_vals); |
| 18112 | 18095 | ||
| 18113 | for (union_field_vals, 0..) |*field_val, i| { | 18096 | for (union_field_vals, 0..) |*field_val, i| { |
| 18114 | // TODO: write something like getCoercedInts to avoid needing to dupe | 18097 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 18115 | const name = try sema.arena.dupeZ(u8, ip.stringToSlice(union_obj.field_names.get(ip)[i])); | 18098 | const name = try sema.arena.dupeZ(u8, ip.stringToSlice(tag_type.names.get(ip)[i])); |
| 18116 | const name_val = v: { | 18099 | const name_val = v: { |
| 18117 | const new_decl_ty = try mod.arrayType(.{ | 18100 | const new_decl_ty = try mod.arrayType(.{ |
| 18118 | .len = name.len, | 18101 | .len = name.len, |
| ... | @@ -18314,7 +18297,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18314,7 +18297,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18314 | } | 18297 | } |
| 18315 | break :fv; | 18298 | break :fv; |
| 18316 | }, | 18299 | }, |
| 18317 | .struct_type => |s| s, | 18300 | .struct_type => ip.loadStructType(ty.toIntern()), |
| 18318 | else => unreachable, | 18301 | else => unreachable, |
| 18319 | }; | 18302 | }; |
| 18320 | struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); | 18303 | struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); |
| ... | @@ -18631,7 +18614,6 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -18631,7 +18614,6 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 18631 | .sema = sema, | 18614 | .sema = sema, |
| 18632 | .src_decl = block.src_decl, | 18615 | .src_decl = block.src_decl, |
| 18633 | .namespace = block.namespace, | 18616 | .namespace = block.namespace, |
| 18634 | .wip_capture_scope = block.wip_capture_scope, | ||
| 18635 | .instructions = .{}, | 18617 | .instructions = .{}, |
| 18636 | .inlining = block.inlining, | 18618 | .inlining = block.inlining, |
| 18637 | .is_comptime = false, | 18619 | .is_comptime = false, |
| ... | @@ -18710,7 +18692,6 @@ fn zirTypeofPeer( | ... | @@ -18710,7 +18692,6 @@ fn zirTypeofPeer( |
| 18710 | .sema = sema, | 18692 | .sema = sema, |
| 18711 | .src_decl = block.src_decl, | 18693 | .src_decl = block.src_decl, |
| 18712 | .namespace = block.namespace, | 18694 | .namespace = block.namespace, |
| 18713 | .wip_capture_scope = block.wip_capture_scope, | ||
| 18714 | .instructions = .{}, | 18695 | .instructions = .{}, |
| 18715 | .inlining = block.inlining, | 18696 | .inlining = block.inlining, |
| 18716 | .is_comptime = false, | 18697 | .is_comptime = false, |
| ... | @@ -19186,7 +19167,6 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label | ... | @@ -19186,7 +19167,6 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label |
| 19186 | .sema = sema, | 19167 | .sema = sema, |
| 19187 | .src_decl = block.src_decl, | 19168 | .src_decl = block.src_decl, |
| 19188 | .namespace = block.namespace, | 19169 | .namespace = block.namespace, |
| 19189 | .wip_capture_scope = block.wip_capture_scope, | ||
| 19190 | .instructions = .{}, | 19170 | .instructions = .{}, |
| 19191 | .label = &labeled_block.label, | 19171 | .label = &labeled_block.label, |
| 19192 | .inlining = block.inlining, | 19172 | .inlining = block.inlining, |
| ... | @@ -20082,7 +20062,8 @@ fn finishStructInit( | ... | @@ -20082,7 +20062,8 @@ fn finishStructInit( |
| 20082 | } | 20062 | } |
| 20083 | } | 20063 | } |
| 20084 | }, | 20064 | }, |
| 20085 | .struct_type => |struct_type| { | 20065 | .struct_type => { |
| 20066 | const struct_type = ip.loadStructType(struct_ty.toIntern()); | ||
| 20086 | for (0..struct_type.field_types.len) |i| { | 20067 | for (0..struct_type.field_types.len) |i| { |
| 20087 | if (field_inits[i] != .none) { | 20068 | if (field_inits[i] != .none) { |
| 20088 | // Coerce the init value to the field type. | 20069 | // Coerce the init value to the field type. |
| ... | @@ -20683,7 +20664,8 @@ fn fieldType( | ... | @@ -20683,7 +20664,8 @@ fn fieldType( |
| 20683 | try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src); | 20664 | try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src); |
| 20684 | return Air.internedToRef(anon_struct.types.get(ip)[field_index]); | 20665 | return Air.internedToRef(anon_struct.types.get(ip)[field_index]); |
| 20685 | }, | 20666 | }, |
| 20686 | .struct_type => |struct_type| { | 20667 | .struct_type => { |
| 20668 | const struct_type = ip.loadStructType(cur_ty.toIntern()); | ||
| 20687 | const field_index = struct_type.nameIndex(ip, field_name) orelse | 20669 | const field_index = struct_type.nameIndex(ip, field_name) orelse |
| 20688 | return sema.failWithBadStructFieldAccess(block, struct_type, field_src, field_name); | 20670 | return sema.failWithBadStructFieldAccess(block, struct_type, field_src, field_name); |
| 20689 | const field_ty = struct_type.field_types.get(ip)[field_index]; | 20671 | const field_ty = struct_type.field_types.get(ip)[field_index]; |
| ... | @@ -20693,7 +20675,7 @@ fn fieldType( | ... | @@ -20693,7 +20675,7 @@ fn fieldType( |
| 20693 | }, | 20675 | }, |
| 20694 | .Union => { | 20676 | .Union => { |
| 20695 | const union_obj = mod.typeToUnion(cur_ty).?; | 20677 | const union_obj = mod.typeToUnion(cur_ty).?; |
| 20696 | const field_index = union_obj.nameIndex(ip, field_name) orelse | 20678 | const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse |
| 20697 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); | 20679 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 20698 | const field_ty = union_obj.field_types.get(ip)[field_index]; | 20680 | const field_ty = union_obj.field_types.get(ip)[field_index]; |
| 20699 | return Air.internedToRef(field_ty); | 20681 | return Air.internedToRef(field_ty); |
| ... | @@ -21022,7 +21004,7 @@ fn zirReify( | ... | @@ -21022,7 +21004,7 @@ fn zirReify( |
| 21022 | .AnyFrame => return sema.failWithUseOfAsync(block, src), | 21004 | .AnyFrame => return sema.failWithUseOfAsync(block, src), |
| 21023 | .EnumLiteral => return .enum_literal_type, | 21005 | .EnumLiteral => return .enum_literal_type, |
| 21024 | .Int => { | 21006 | .Int => { |
| 21025 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21007 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21026 | const signedness_val = try Value.fromInterned(union_val.val).fieldValue( | 21008 | const signedness_val = try Value.fromInterned(union_val.val).fieldValue( |
| 21027 | mod, | 21009 | mod, |
| 21028 | struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness")).?, | 21010 | struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness")).?, |
| ... | @@ -21038,7 +21020,7 @@ fn zirReify( | ... | @@ -21038,7 +21020,7 @@ fn zirReify( |
| 21038 | return Air.internedToRef(ty.toIntern()); | 21020 | return Air.internedToRef(ty.toIntern()); |
| 21039 | }, | 21021 | }, |
| 21040 | .Vector => { | 21022 | .Vector => { |
| 21041 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21023 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21042 | const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21024 | const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21043 | ip, | 21025 | ip, |
| 21044 | try ip.getOrPutString(gpa, "len"), | 21026 | try ip.getOrPutString(gpa, "len"), |
| ... | @@ -21060,7 +21042,7 @@ fn zirReify( | ... | @@ -21060,7 +21042,7 @@ fn zirReify( |
| 21060 | return Air.internedToRef(ty.toIntern()); | 21042 | return Air.internedToRef(ty.toIntern()); |
| 21061 | }, | 21043 | }, |
| 21062 | .Float => { | 21044 | .Float => { |
| 21063 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21045 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21064 | const bits_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21046 | const bits_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21065 | ip, | 21047 | ip, |
| 21066 | try ip.getOrPutString(gpa, "bits"), | 21048 | try ip.getOrPutString(gpa, "bits"), |
| ... | @@ -21078,7 +21060,7 @@ fn zirReify( | ... | @@ -21078,7 +21060,7 @@ fn zirReify( |
| 21078 | return Air.internedToRef(ty.toIntern()); | 21060 | return Air.internedToRef(ty.toIntern()); |
| 21079 | }, | 21061 | }, |
| 21080 | .Pointer => { | 21062 | .Pointer => { |
| 21081 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21063 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21082 | const size_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21064 | const size_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21083 | ip, | 21065 | ip, |
| 21084 | try ip.getOrPutString(gpa, "size"), | 21066 | try ip.getOrPutString(gpa, "size"), |
| ... | @@ -21190,7 +21172,7 @@ fn zirReify( | ... | @@ -21190,7 +21172,7 @@ fn zirReify( |
| 21190 | return Air.internedToRef(ty.toIntern()); | 21172 | return Air.internedToRef(ty.toIntern()); |
| 21191 | }, | 21173 | }, |
| 21192 | .Array => { | 21174 | .Array => { |
| 21193 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21175 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21194 | const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21176 | const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21195 | ip, | 21177 | ip, |
| 21196 | try ip.getOrPutString(gpa, "len"), | 21178 | try ip.getOrPutString(gpa, "len"), |
| ... | @@ -21219,7 +21201,7 @@ fn zirReify( | ... | @@ -21219,7 +21201,7 @@ fn zirReify( |
| 21219 | return Air.internedToRef(ty.toIntern()); | 21201 | return Air.internedToRef(ty.toIntern()); |
| 21220 | }, | 21202 | }, |
| 21221 | .Optional => { | 21203 | .Optional => { |
| 21222 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21204 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21223 | const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21205 | const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21224 | ip, | 21206 | ip, |
| 21225 | try ip.getOrPutString(gpa, "child"), | 21207 | try ip.getOrPutString(gpa, "child"), |
| ... | @@ -21231,7 +21213,7 @@ fn zirReify( | ... | @@ -21231,7 +21213,7 @@ fn zirReify( |
| 21231 | return Air.internedToRef(ty.toIntern()); | 21213 | return Air.internedToRef(ty.toIntern()); |
| 21232 | }, | 21214 | }, |
| 21233 | .ErrorUnion => { | 21215 | .ErrorUnion => { |
| 21234 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21216 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21235 | const error_set_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21217 | const error_set_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21236 | ip, | 21218 | ip, |
| 21237 | try ip.getOrPutString(gpa, "error_set"), | 21219 | try ip.getOrPutString(gpa, "error_set"), |
| ... | @@ -21260,7 +21242,7 @@ fn zirReify( | ... | @@ -21260,7 +21242,7 @@ fn zirReify( |
| 21260 | try names.ensureUnusedCapacity(sema.arena, len); | 21242 | try names.ensureUnusedCapacity(sema.arena, len); |
| 21261 | for (0..len) |i| { | 21243 | for (0..len) |i| { |
| 21262 | const elem_val = try payload_val.elemValue(mod, i); | 21244 | const elem_val = try payload_val.elemValue(mod, i); |
| 21263 | const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type; | 21245 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); |
| 21264 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | 21246 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( |
| 21265 | ip, | 21247 | ip, |
| 21266 | try ip.getOrPutString(gpa, "name"), | 21248 | try ip.getOrPutString(gpa, "name"), |
| ... | @@ -21280,7 +21262,7 @@ fn zirReify( | ... | @@ -21280,7 +21262,7 @@ fn zirReify( |
| 21280 | return Air.internedToRef(ty.toIntern()); | 21262 | return Air.internedToRef(ty.toIntern()); |
| 21281 | }, | 21263 | }, |
| 21282 | .Struct => { | 21264 | .Struct => { |
| 21283 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21265 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21284 | const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21266 | const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21285 | ip, | 21267 | ip, |
| 21286 | try ip.getOrPutString(gpa, "layout"), | 21268 | try ip.getOrPutString(gpa, "layout"), |
| ... | @@ -21316,7 +21298,7 @@ fn zirReify( | ... | @@ -21316,7 +21298,7 @@ fn zirReify( |
| 21316 | return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool()); | 21298 | return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool()); |
| 21317 | }, | 21299 | }, |
| 21318 | .Enum => { | 21300 | .Enum => { |
| 21319 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21301 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21320 | const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21302 | const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21321 | ip, | 21303 | ip, |
| 21322 | try ip.getOrPutString(gpa, "tag_type"), | 21304 | try ip.getOrPutString(gpa, "tag_type"), |
| ... | @@ -21334,105 +21316,14 @@ fn zirReify( | ... | @@ -21334,105 +21316,14 @@ fn zirReify( |
| 21334 | try ip.getOrPutString(gpa, "is_exhaustive"), | 21316 | try ip.getOrPutString(gpa, "is_exhaustive"), |
| 21335 | ).?); | 21317 | ).?); |
| 21336 | 21318 | ||
| 21337 | // Decls | ||
| 21338 | if (decls_val.sliceLen(mod) > 0) { | 21319 | if (decls_val.sliceLen(mod) > 0) { |
| 21339 | return sema.fail(block, src, "reified enums must have no decls", .{}); | 21320 | return sema.fail(block, src, "reified enums must have no decls", .{}); |
| 21340 | } | 21321 | } |
| 21341 | 21322 | ||
| 21342 | const int_tag_ty = tag_type_val.toType(); | 21323 | return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_val, name_strategy); |
| 21343 | if (int_tag_ty.zigTypeTag(mod) != .Int) { | ||
| 21344 | return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); | ||
| 21345 | } | ||
| 21346 | |||
| 21347 | // Because these things each reference each other, `undefined` | ||
| 21348 | // placeholders are used before being set after the enum type gains | ||
| 21349 | // an InternPool index. | ||
| 21350 | |||
| 21351 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | ||
| 21352 | .ty = Type.noreturn, | ||
| 21353 | .val = Value.@"unreachable", | ||
| 21354 | }, name_strategy, "enum", inst); | ||
| 21355 | const new_decl = mod.declPtr(new_decl_index); | ||
| 21356 | new_decl.owns_tv = true; | ||
| 21357 | errdefer { | ||
| 21358 | new_decl.has_tv = false; // namespace and val were destroyed by later errdefers | ||
| 21359 | mod.abortAnonDecl(new_decl_index); | ||
| 21360 | } | ||
| 21361 | |||
| 21362 | // Define our empty enum decl | ||
| 21363 | const fields_len: u32 = @intCast(try sema.usizeCast(block, src, fields_val.sliceLen(mod))); | ||
| 21364 | const incomplete_enum = try ip.getIncompleteEnum(gpa, .{ | ||
| 21365 | .decl = new_decl_index, | ||
| 21366 | .namespace = .none, | ||
| 21367 | .fields_len = fields_len, | ||
| 21368 | .has_values = true, | ||
| 21369 | .tag_mode = if (!is_exhaustive_val.toBool()) | ||
| 21370 | .nonexhaustive | ||
| 21371 | else | ||
| 21372 | .explicit, | ||
| 21373 | .tag_ty = int_tag_ty.toIntern(), | ||
| 21374 | .zir_index = .none, | ||
| 21375 | }); | ||
| 21376 | // TODO: figure out InternPool removals for incremental compilation | ||
| 21377 | //errdefer ip.remove(incomplete_enum.index); | ||
| 21378 | |||
| 21379 | new_decl.ty = Type.type; | ||
| 21380 | new_decl.val = Value.fromInterned(incomplete_enum.index); | ||
| 21381 | |||
| 21382 | for (0..fields_len) |field_i| { | ||
| 21383 | const elem_val = try fields_val.elemValue(mod, field_i); | ||
| 21384 | const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type; | ||
| 21385 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21386 | ip, | ||
| 21387 | try ip.getOrPutString(gpa, "name"), | ||
| 21388 | ).?); | ||
| 21389 | const value_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21390 | ip, | ||
| 21391 | try ip.getOrPutString(gpa, "value"), | ||
| 21392 | ).?); | ||
| 21393 | |||
| 21394 | const field_name = try name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21395 | |||
| 21396 | if (!try sema.intFitsInType(value_val, int_tag_ty, null)) { | ||
| 21397 | // TODO: better source location | ||
| 21398 | return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{ | ||
| 21399 | field_name.fmt(ip), | ||
| 21400 | value_val.fmtValue(Type.comptime_int, mod), | ||
| 21401 | int_tag_ty.fmt(mod), | ||
| 21402 | }); | ||
| 21403 | } | ||
| 21404 | |||
| 21405 | if (incomplete_enum.addFieldName(ip, field_name)) |other_index| { | ||
| 21406 | const msg = msg: { | ||
| 21407 | const msg = try sema.errMsg(block, src, "duplicate enum field '{}'", .{ | ||
| 21408 | field_name.fmt(ip), | ||
| 21409 | }); | ||
| 21410 | errdefer msg.destroy(gpa); | ||
| 21411 | _ = other_index; // TODO: this note is incorrect | ||
| 21412 | try sema.errNote(block, src, msg, "other field here", .{}); | ||
| 21413 | break :msg msg; | ||
| 21414 | }; | ||
| 21415 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21416 | } | ||
| 21417 | |||
| 21418 | if (incomplete_enum.addFieldValue(ip, (try mod.getCoerced(value_val, int_tag_ty)).toIntern())) |other| { | ||
| 21419 | const msg = msg: { | ||
| 21420 | const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{value_val.fmtValue(Type.comptime_int, mod)}); | ||
| 21421 | errdefer msg.destroy(gpa); | ||
| 21422 | _ = other; // TODO: this note is incorrect | ||
| 21423 | try sema.errNote(block, src, msg, "other enum tag value here", .{}); | ||
| 21424 | break :msg msg; | ||
| 21425 | }; | ||
| 21426 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21427 | } | ||
| 21428 | } | ||
| 21429 | |||
| 21430 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | ||
| 21431 | try mod.finalizeAnonDecl(new_decl_index); | ||
| 21432 | return decl_val; | ||
| 21433 | }, | 21324 | }, |
| 21434 | .Opaque => { | 21325 | .Opaque => { |
| 21435 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21326 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21436 | const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21327 | const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21437 | ip, | 21328 | ip, |
| 21438 | try ip.getOrPutString(gpa, "decls"), | 21329 | try ip.getOrPutString(gpa, "decls"), |
| ... | @@ -21443,45 +21334,30 @@ fn zirReify( | ... | @@ -21443,45 +21334,30 @@ fn zirReify( |
| 21443 | return sema.fail(block, src, "reified opaque must have no decls", .{}); | 21334 | return sema.fail(block, src, "reified opaque must have no decls", .{}); |
| 21444 | } | 21335 | } |
| 21445 | 21336 | ||
| 21446 | // Because these three things each reference each other, | 21337 | const wip_ty = switch (try ip.getOpaqueType(gpa, .{ |
| 21447 | // `undefined` placeholders are used in two places before being set | 21338 | .has_namespace = false, |
| 21448 | // after the opaque type gains an InternPool index. | 21339 | .key = .{ .reified = .{ |
| 21340 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), | ||
| 21341 | } }, | ||
| 21342 | })) { | ||
| 21343 | .existing => |ty| return Air.internedToRef(ty), | ||
| 21344 | .wip => |wip| wip, | ||
| 21345 | }; | ||
| 21346 | errdefer wip_ty.cancel(ip); | ||
| 21449 | 21347 | ||
| 21450 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 21348 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 21451 | .ty = Type.noreturn, | 21349 | .ty = Type.type, |
| 21452 | .val = Value.@"unreachable", | 21350 | .val = Value.fromInterned(wip_ty.index), |
| 21453 | }, name_strategy, "opaque", inst); | 21351 | }, name_strategy, "opaque", inst); |
| 21454 | const new_decl = mod.declPtr(new_decl_index); | 21352 | mod.declPtr(new_decl_index).owns_tv = true; |
| 21455 | new_decl.owns_tv = true; | 21353 | errdefer mod.abortAnonDecl(new_decl_index); |
| 21456 | errdefer { | ||
| 21457 | new_decl.has_tv = false; // namespace and val were destroyed by later errdefers | ||
| 21458 | mod.abortAnonDecl(new_decl_index); | ||
| 21459 | } | ||
| 21460 | |||
| 21461 | const new_namespace_index = try mod.createNamespace(.{ | ||
| 21462 | .parent = block.namespace.toOptional(), | ||
| 21463 | .decl_index = new_decl_index, | ||
| 21464 | .file_scope = block.getFileScope(mod), | ||
| 21465 | }); | ||
| 21466 | errdefer mod.destroyNamespace(new_namespace_index); | ||
| 21467 | |||
| 21468 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ | ||
| 21469 | .decl = new_decl_index, | ||
| 21470 | .namespace = new_namespace_index, | ||
| 21471 | .zir_index = .none, | ||
| 21472 | } }); | ||
| 21473 | // TODO: figure out InternPool removals for incremental compilation | ||
| 21474 | //errdefer ip.remove(opaque_ty); | ||
| 21475 | |||
| 21476 | new_decl.ty = Type.type; | ||
| 21477 | new_decl.val = Value.fromInterned(opaque_ty); | ||
| 21478 | 21354 | ||
| 21479 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | ||
| 21480 | try mod.finalizeAnonDecl(new_decl_index); | 21355 | try mod.finalizeAnonDecl(new_decl_index); |
| 21481 | return decl_val; | 21356 | |
| 21357 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none)); | ||
| 21482 | }, | 21358 | }, |
| 21483 | .Union => { | 21359 | .Union => { |
| 21484 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21360 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21485 | const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21361 | const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21486 | ip, | 21362 | ip, |
| 21487 | try ip.getOrPutString(gpa, "layout"), | 21363 | try ip.getOrPutString(gpa, "layout"), |
| ... | @@ -21499,216 +21375,15 @@ fn zirReify( | ... | @@ -21499,216 +21375,15 @@ fn zirReify( |
| 21499 | try ip.getOrPutString(gpa, "decls"), | 21375 | try ip.getOrPutString(gpa, "decls"), |
| 21500 | ).?); | 21376 | ).?); |
| 21501 | 21377 | ||
| 21502 | // Decls | ||
| 21503 | if (decls_val.sliceLen(mod) > 0) { | 21378 | if (decls_val.sliceLen(mod) > 0) { |
| 21504 | return sema.fail(block, src, "reified unions must have no decls", .{}); | 21379 | return sema.fail(block, src, "reified unions must have no decls", .{}); |
| 21505 | } | 21380 | } |
| 21506 | const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); | 21381 | const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); |
| 21507 | const fields_len: u32 = @intCast(try sema.usizeCast(block, src, fields_val.sliceLen(mod))); | ||
| 21508 | |||
| 21509 | // Tag type | ||
| 21510 | var explicit_tags_seen: []bool = &.{}; | ||
| 21511 | var enum_field_names: []InternPool.NullTerminatedString = &.{}; | ||
| 21512 | var enum_tag_ty: InternPool.Index = .none; | ||
| 21513 | if (tag_type_val.optionalValue(mod)) |payload_val| { | ||
| 21514 | enum_tag_ty = payload_val.toType().toIntern(); | ||
| 21515 | |||
| 21516 | const enum_type = switch (ip.indexToKey(enum_tag_ty)) { | ||
| 21517 | .enum_type => |x| x, | ||
| 21518 | else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}), | ||
| 21519 | }; | ||
| 21520 | |||
| 21521 | explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len); | ||
| 21522 | @memset(explicit_tags_seen, false); | ||
| 21523 | } else { | ||
| 21524 | enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len); | ||
| 21525 | } | ||
| 21526 | |||
| 21527 | // Fields | ||
| 21528 | var any_aligned_fields: bool = false; | ||
| 21529 | var union_fields: std.MultiArrayList(struct { | ||
| 21530 | type: InternPool.Index, | ||
| 21531 | alignment: InternPool.Alignment, | ||
| 21532 | }) = .{}; | ||
| 21533 | var field_name_table: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; | ||
| 21534 | try field_name_table.ensureTotalCapacity(sema.arena, fields_len); | ||
| 21535 | |||
| 21536 | for (0..fields_len) |i| { | ||
| 21537 | const elem_val = try fields_val.elemValue(mod, i); | ||
| 21538 | const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type; | ||
| 21539 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21540 | ip, | ||
| 21541 | try ip.getOrPutString(gpa, "name"), | ||
| 21542 | ).?); | ||
| 21543 | const type_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21544 | ip, | ||
| 21545 | try ip.getOrPutString(gpa, "type"), | ||
| 21546 | ).?); | ||
| 21547 | const alignment_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21548 | ip, | ||
| 21549 | try ip.getOrPutString(gpa, "alignment"), | ||
| 21550 | ).?); | ||
| 21551 | |||
| 21552 | const field_name = try name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21553 | |||
| 21554 | if (enum_field_names.len != 0) { | ||
| 21555 | enum_field_names[i] = field_name; | ||
| 21556 | } | ||
| 21557 | |||
| 21558 | if (enum_tag_ty != .none) { | ||
| 21559 | const tag_info = ip.indexToKey(enum_tag_ty).enum_type; | ||
| 21560 | const enum_index = tag_info.nameIndex(ip, field_name) orelse { | ||
| 21561 | return sema.fail(block, src, "no field named '{}' in enum '{}'", .{ | ||
| 21562 | field_name.fmt(ip), Type.fromInterned(enum_tag_ty).fmt(mod), | ||
| 21563 | }); | ||
| 21564 | }; | ||
| 21565 | assert(explicit_tags_seen.len == tag_info.names.len); | ||
| 21566 | // No check for duplicate because the check already happened in order | ||
| 21567 | // to create the enum type in the first place. | ||
| 21568 | assert(!explicit_tags_seen[enum_index]); | ||
| 21569 | explicit_tags_seen[enum_index] = true; | ||
| 21570 | } | ||
| 21571 | |||
| 21572 | const gop = field_name_table.getOrPutAssumeCapacity(field_name); | ||
| 21573 | if (gop.found_existing) { | ||
| 21574 | // TODO: better source location | ||
| 21575 | return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)}); | ||
| 21576 | } | ||
| 21577 | |||
| 21578 | const field_ty = type_val.toType(); | ||
| 21579 | const alignment_val_int = (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?; | ||
| 21580 | if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) { | ||
| 21581 | // TODO: better source location | ||
| 21582 | return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{ | ||
| 21583 | alignment_val_int, | ||
| 21584 | }); | ||
| 21585 | } | ||
| 21586 | const field_align = Alignment.fromByteUnits(alignment_val_int); | ||
| 21587 | any_aligned_fields = any_aligned_fields or field_align != .none; | ||
| 21588 | |||
| 21589 | try union_fields.append(sema.arena, .{ | ||
| 21590 | .type = field_ty.toIntern(), | ||
| 21591 | .alignment = field_align, | ||
| 21592 | }); | ||
| 21593 | 21382 | ||
| 21594 | if (field_ty.zigTypeTag(mod) == .Opaque) { | 21383 | return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_val, name_strategy); |
| 21595 | const msg = msg: { | ||
| 21596 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); | ||
| 21597 | errdefer msg.destroy(gpa); | ||
| 21598 | |||
| 21599 | try sema.addDeclaredHereNote(msg, field_ty); | ||
| 21600 | break :msg msg; | ||
| 21601 | }; | ||
| 21602 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21603 | } | ||
| 21604 | if (layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) { | ||
| 21605 | const msg = msg: { | ||
| 21606 | const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); | ||
| 21607 | errdefer msg.destroy(gpa); | ||
| 21608 | |||
| 21609 | const src_decl = mod.declPtr(block.src_decl); | ||
| 21610 | try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), field_ty, .union_field); | ||
| 21611 | |||
| 21612 | try sema.addDeclaredHereNote(msg, field_ty); | ||
| 21613 | break :msg msg; | ||
| 21614 | }; | ||
| 21615 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21616 | } else if (layout == .Packed and !try sema.validatePackedType(field_ty)) { | ||
| 21617 | const msg = msg: { | ||
| 21618 | const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); | ||
| 21619 | errdefer msg.destroy(gpa); | ||
| 21620 | |||
| 21621 | const src_decl = mod.declPtr(block.src_decl); | ||
| 21622 | try sema.explainWhyTypeIsNotPacked(msg, src_decl.toSrcLoc(src, mod), field_ty); | ||
| 21623 | |||
| 21624 | try sema.addDeclaredHereNote(msg, field_ty); | ||
| 21625 | break :msg msg; | ||
| 21626 | }; | ||
| 21627 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21628 | } | ||
| 21629 | } | ||
| 21630 | |||
| 21631 | if (enum_tag_ty != .none) { | ||
| 21632 | const tag_info = ip.indexToKey(enum_tag_ty).enum_type; | ||
| 21633 | if (tag_info.names.len > fields_len) { | ||
| 21634 | const msg = msg: { | ||
| 21635 | const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{}); | ||
| 21636 | errdefer msg.destroy(gpa); | ||
| 21637 | |||
| 21638 | assert(explicit_tags_seen.len == tag_info.names.len); | ||
| 21639 | for (tag_info.names.get(ip), 0..) |field_name, field_index| { | ||
| 21640 | if (explicit_tags_seen[field_index]) continue; | ||
| 21641 | try sema.addFieldErrNote(Type.fromInterned(enum_tag_ty), field_index, msg, "field '{}' missing, declared here", .{ | ||
| 21642 | field_name.fmt(ip), | ||
| 21643 | }); | ||
| 21644 | } | ||
| 21645 | try sema.addDeclaredHereNote(msg, Type.fromInterned(enum_tag_ty)); | ||
| 21646 | break :msg msg; | ||
| 21647 | }; | ||
| 21648 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21649 | } | ||
| 21650 | } else { | ||
| 21651 | enum_tag_ty = try sema.generateUnionTagTypeSimple(block, enum_field_names, .none); | ||
| 21652 | } | ||
| 21653 | |||
| 21654 | // Because these three things each reference each other, `undefined` | ||
| 21655 | // placeholders are used before being set after the union type gains an | ||
| 21656 | // InternPool index. | ||
| 21657 | |||
| 21658 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | ||
| 21659 | .ty = Type.noreturn, | ||
| 21660 | .val = Value.@"unreachable", | ||
| 21661 | }, name_strategy, "union", inst); | ||
| 21662 | const new_decl = mod.declPtr(new_decl_index); | ||
| 21663 | new_decl.owns_tv = true; | ||
| 21664 | errdefer { | ||
| 21665 | new_decl.has_tv = false; // namespace and val were destroyed by later errdefers | ||
| 21666 | mod.abortAnonDecl(new_decl_index); | ||
| 21667 | } | ||
| 21668 | |||
| 21669 | const new_namespace_index = try mod.createNamespace(.{ | ||
| 21670 | .parent = block.namespace.toOptional(), | ||
| 21671 | .decl_index = new_decl_index, | ||
| 21672 | .file_scope = block.getFileScope(mod), | ||
| 21673 | }); | ||
| 21674 | errdefer mod.destroyNamespace(new_namespace_index); | ||
| 21675 | |||
| 21676 | const union_ty = try ip.getUnionType(gpa, .{ | ||
| 21677 | .decl = new_decl_index, | ||
| 21678 | .namespace = new_namespace_index, | ||
| 21679 | .enum_tag_ty = enum_tag_ty, | ||
| 21680 | .fields_len = fields_len, | ||
| 21681 | .zir_index = .none, | ||
| 21682 | .flags = .{ | ||
| 21683 | .layout = layout, | ||
| 21684 | .status = .have_field_types, | ||
| 21685 | .runtime_tag = if (!tag_type_val.isNull(mod)) | ||
| 21686 | .tagged | ||
| 21687 | else if (layout != .Auto) | ||
| 21688 | .none | ||
| 21689 | else switch (block.wantSafety()) { | ||
| 21690 | true => .safety, | ||
| 21691 | false => .none, | ||
| 21692 | }, | ||
| 21693 | .any_aligned_fields = any_aligned_fields, | ||
| 21694 | .requires_comptime = .unknown, | ||
| 21695 | .assumed_runtime_bits = false, | ||
| 21696 | .assumed_pointer_aligned = false, | ||
| 21697 | .alignment = .none, | ||
| 21698 | }, | ||
| 21699 | .field_types = union_fields.items(.type), | ||
| 21700 | .field_aligns = if (any_aligned_fields) union_fields.items(.alignment) else &.{}, | ||
| 21701 | }); | ||
| 21702 | |||
| 21703 | new_decl.ty = Type.type; | ||
| 21704 | new_decl.val = Value.fromInterned(union_ty); | ||
| 21705 | |||
| 21706 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | ||
| 21707 | try mod.finalizeAnonDecl(new_decl_index); | ||
| 21708 | return decl_val; | ||
| 21709 | }, | 21384 | }, |
| 21710 | .Fn => { | 21385 | .Fn => { |
| 21711 | const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type; | 21386 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| 21712 | const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( | 21387 | const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( |
| 21713 | ip, | 21388 | ip, |
| 21714 | try ip.getOrPutString(gpa, "calling_convention"), | 21389 | try ip.getOrPutString(gpa, "calling_convention"), |
| ... | @@ -21759,7 +21434,7 @@ fn zirReify( | ... | @@ -21759,7 +21434,7 @@ fn zirReify( |
| 21759 | var noalias_bits: u32 = 0; | 21434 | var noalias_bits: u32 = 0; |
| 21760 | for (param_types, 0..) |*param_type, i| { | 21435 | for (param_types, 0..) |*param_type, i| { |
| 21761 | const elem_val = try params_val.elemValue(mod, i); | 21436 | const elem_val = try params_val.elemValue(mod, i); |
| 21762 | const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type; | 21437 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); |
| 21763 | const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | 21438 | const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( |
| 21764 | ip, | 21439 | ip, |
| 21765 | try ip.getOrPutString(gpa, "is_generic"), | 21440 | try ip.getOrPutString(gpa, "is_generic"), |
| ... | @@ -21804,126 +21479,492 @@ fn zirReify( | ... | @@ -21804,126 +21479,492 @@ fn zirReify( |
| 21804 | } | 21479 | } |
| 21805 | } | 21480 | } |
| 21806 | 21481 | ||
| 21807 | fn reifyStruct( | 21482 | fn reifyEnum( |
| 21808 | sema: *Sema, | 21483 | sema: *Sema, |
| 21809 | block: *Block, | 21484 | block: *Block, |
| 21810 | inst: Zir.Inst.Index, | 21485 | inst: Zir.Inst.Index, |
| 21811 | src: LazySrcLoc, | 21486 | src: LazySrcLoc, |
| 21812 | layout: std.builtin.Type.ContainerLayout, | 21487 | tag_ty: Type, |
| 21813 | backing_int_val: Value, | 21488 | is_exhaustive: bool, |
| 21814 | fields_val: Value, | 21489 | fields_val: Value, |
| 21815 | name_strategy: Zir.Inst.NameStrategy, | 21490 | name_strategy: Zir.Inst.NameStrategy, |
| 21816 | is_tuple: bool, | ||
| 21817 | ) CompileError!Air.Inst.Ref { | 21491 | ) CompileError!Air.Inst.Ref { |
| 21818 | const mod = sema.mod; | 21492 | const mod = sema.mod; |
| 21819 | const gpa = sema.gpa; | 21493 | const gpa = sema.gpa; |
| 21820 | const ip = &mod.intern_pool; | 21494 | const ip = &mod.intern_pool; |
| 21821 | 21495 | ||
| 21822 | if (is_tuple) switch (layout) { | 21496 | // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`. |
| 21823 | .Extern => return sema.fail(block, src, "extern tuples are not supported", .{}), | 21497 | |
| 21824 | .Packed => return sema.fail(block, src, "packed tuples are not supported", .{}), | 21498 | const fields_len: u32 = @intCast(fields_val.sliceLen(mod)); |
| 21825 | .Auto => {}, | 21499 | |
| 21500 | // The validation work here is non-trivial, and it's possible the type already exists. | ||
| 21501 | // So in this first pass, let's just construct a hash to optimize for this case. If the | ||
| 21502 | // inputs turn out to be invalid, we can cancel the WIP type later. | ||
| 21503 | |||
| 21504 | // For deduplication purposes, we must create a hash including all details of this type. | ||
| 21505 | // TODO: use a longer hash! | ||
| 21506 | var hasher = std.hash.Wyhash.init(0); | ||
| 21507 | std.hash.autoHash(&hasher, tag_ty.toIntern()); | ||
| 21508 | std.hash.autoHash(&hasher, is_exhaustive); | ||
| 21509 | std.hash.autoHash(&hasher, fields_len); | ||
| 21510 | |||
| 21511 | for (0..fields_len) |field_idx| { | ||
| 21512 | const field_info = try fields_val.elemValue(mod, field_idx); | ||
| 21513 | |||
| 21514 | const field_name_val = try field_info.fieldValue(mod, 0); | ||
| 21515 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); | ||
| 21516 | |||
| 21517 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21518 | |||
| 21519 | std.hash.autoHash(&hasher, .{ | ||
| 21520 | field_name, | ||
| 21521 | field_value_val.toIntern(), | ||
| 21522 | }); | ||
| 21523 | } | ||
| 21524 | |||
| 21525 | const wip_ty = switch (try ip.getEnumType(gpa, .{ | ||
| 21526 | .has_namespace = false, | ||
| 21527 | .has_values = true, | ||
| 21528 | .tag_mode = if (is_exhaustive) .explicit else .nonexhaustive, | ||
| 21529 | .fields_len = fields_len, | ||
| 21530 | .key = .{ .reified = .{ | ||
| 21531 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), | ||
| 21532 | .type_hash = hasher.final(), | ||
| 21533 | } }, | ||
| 21534 | })) { | ||
| 21535 | .wip => |wip| wip, | ||
| 21536 | .existing => |ty| return Air.internedToRef(ty), | ||
| 21826 | }; | 21537 | }; |
| 21538 | errdefer wip_ty.cancel(ip); | ||
| 21539 | |||
| 21540 | if (tag_ty.zigTypeTag(mod) != .Int) { | ||
| 21541 | return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); | ||
| 21542 | } | ||
| 21543 | |||
| 21544 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | ||
| 21545 | .ty = Type.type, | ||
| 21546 | .val = Value.fromInterned(wip_ty.index), | ||
| 21547 | }, name_strategy, "enum", inst); | ||
| 21548 | mod.declPtr(new_decl_index).owns_tv = true; | ||
| 21549 | errdefer mod.abortAnonDecl(new_decl_index); | ||
| 21550 | |||
| 21551 | wip_ty.prepare(ip, new_decl_index, .none); | ||
| 21552 | wip_ty.setTagTy(ip, tag_ty.toIntern()); | ||
| 21553 | |||
| 21554 | for (0..fields_len) |field_idx| { | ||
| 21555 | const field_info = try fields_val.elemValue(mod, field_idx); | ||
| 21556 | |||
| 21557 | const field_name_val = try field_info.fieldValue(mod, 0); | ||
| 21558 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); | ||
| 21559 | |||
| 21560 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21561 | |||
| 21562 | if (!try sema.intFitsInType(field_value_val, tag_ty, null)) { | ||
| 21563 | // TODO: better source location | ||
| 21564 | return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{ | ||
| 21565 | field_name.fmt(ip), | ||
| 21566 | field_value_val.fmtValue(Type.comptime_int, mod), | ||
| 21567 | tag_ty.fmt(mod), | ||
| 21568 | }); | ||
| 21569 | } | ||
| 21570 | |||
| 21571 | const coerced_field_val = try mod.getCoerced(field_value_val, tag_ty); | ||
| 21572 | if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| { | ||
| 21573 | return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) { | ||
| 21574 | .name => msg: { | ||
| 21575 | const msg = try sema.errMsg(block, src, "duplicate enum field '{}'", .{field_name.fmt(ip)}); | ||
| 21576 | errdefer msg.destroy(gpa); | ||
| 21577 | _ = conflict.prev_field_idx; // TODO: this note is incorrect | ||
| 21578 | try sema.errNote(block, src, msg, "other field here", .{}); | ||
| 21579 | break :msg msg; | ||
| 21580 | }, | ||
| 21581 | .value => msg: { | ||
| 21582 | const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{field_value_val.fmtValue(Type.comptime_int, mod)}); | ||
| 21583 | errdefer msg.destroy(gpa); | ||
| 21584 | _ = conflict.prev_field_idx; // TODO: this note is incorrect | ||
| 21585 | try sema.errNote(block, src, msg, "other enum tag value here", .{}); | ||
| 21586 | break :msg msg; | ||
| 21587 | }, | ||
| 21588 | }); | ||
| 21589 | } | ||
| 21590 | } | ||
| 21591 | |||
| 21592 | if (!is_exhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(mod)) { | ||
| 21593 | return sema.fail(block, src, "non-exhaustive enum specified every value", .{}); | ||
| 21594 | } | ||
| 21827 | 21595 | ||
| 21828 | const fields_len: u32 = @intCast(try sema.usizeCast(block, src, fields_val.sliceLen(mod))); | 21596 | try mod.finalizeAnonDecl(new_decl_index); |
| 21597 | return Air.internedToRef(wip_ty.index); | ||
| 21598 | } | ||
| 21829 | 21599 | ||
| 21830 | // Because these three things each reference each other, `undefined` | 21600 | fn reifyUnion( |
| 21831 | // placeholders are used before being set after the struct type gains an | 21601 | sema: *Sema, |
| 21832 | // InternPool index. | 21602 | block: *Block, |
| 21603 | inst: Zir.Inst.Index, | ||
| 21604 | src: LazySrcLoc, | ||
| 21605 | layout: std.builtin.Type.ContainerLayout, | ||
| 21606 | opt_tag_type_val: Value, | ||
| 21607 | fields_val: Value, | ||
| 21608 | name_strategy: Zir.Inst.NameStrategy, | ||
| 21609 | ) CompileError!Air.Inst.Ref { | ||
| 21610 | const mod = sema.mod; | ||
| 21611 | const gpa = sema.gpa; | ||
| 21612 | const ip = &mod.intern_pool; | ||
| 21613 | |||
| 21614 | // This logic must stay in sync with the structure of `std.builtin.Type.Union` - search for `fieldValue`. | ||
| 21615 | |||
| 21616 | const fields_len: u32 = @intCast(fields_val.sliceLen(mod)); | ||
| 21617 | |||
| 21618 | // The validation work here is non-trivial, and it's possible the type already exists. | ||
| 21619 | // So in this first pass, let's just construct a hash to optimize for this case. If the | ||
| 21620 | // inputs turn out to be invalid, we can cancel the WIP type later. | ||
| 21621 | |||
| 21622 | // For deduplication purposes, we must create a hash including all details of this type. | ||
| 21623 | // TODO: use a longer hash! | ||
| 21624 | var hasher = std.hash.Wyhash.init(0); | ||
| 21625 | std.hash.autoHash(&hasher, layout); | ||
| 21626 | std.hash.autoHash(&hasher, opt_tag_type_val.toIntern()); | ||
| 21627 | std.hash.autoHash(&hasher, fields_len); | ||
| 21628 | |||
| 21629 | var any_aligns = false; | ||
| 21630 | |||
| 21631 | for (0..fields_len) |field_idx| { | ||
| 21632 | const field_info = try fields_val.elemValue(mod, field_idx); | ||
| 21633 | |||
| 21634 | const field_name_val = try field_info.fieldValue(mod, 0); | ||
| 21635 | const field_type_val = try field_info.fieldValue(mod, 1); | ||
| 21636 | const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 2)); | ||
| 21637 | |||
| 21638 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21639 | |||
| 21640 | std.hash.autoHash(&hasher, .{ | ||
| 21641 | field_name, | ||
| 21642 | field_type_val.toIntern(), | ||
| 21643 | field_align_val.toIntern(), | ||
| 21644 | }); | ||
| 21645 | |||
| 21646 | if (field_align_val.toUnsignedInt(mod) != 0) { | ||
| 21647 | any_aligns = true; | ||
| 21648 | } | ||
| 21649 | } | ||
| 21650 | |||
| 21651 | const wip_ty = switch (try ip.getUnionType(gpa, .{ | ||
| 21652 | .flags = .{ | ||
| 21653 | .layout = layout, | ||
| 21654 | .status = .none, | ||
| 21655 | .runtime_tag = if (opt_tag_type_val.optionalValue(mod) != null) | ||
| 21656 | .tagged | ||
| 21657 | else if (layout != .Auto) | ||
| 21658 | .none | ||
| 21659 | else switch (block.wantSafety()) { | ||
| 21660 | true => .safety, | ||
| 21661 | false => .none, | ||
| 21662 | }, | ||
| 21663 | .any_aligned_fields = any_aligns, | ||
| 21664 | .requires_comptime = .unknown, | ||
| 21665 | .assumed_runtime_bits = false, | ||
| 21666 | .assumed_pointer_aligned = false, | ||
| 21667 | .alignment = .none, | ||
| 21668 | }, | ||
| 21669 | .has_namespace = false, | ||
| 21670 | .fields_len = fields_len, | ||
| 21671 | .enum_tag_ty = .none, // set later because not yet validated | ||
| 21672 | .field_types = &.{}, // set later | ||
| 21673 | .field_aligns = &.{}, // set later | ||
| 21674 | .key = .{ .reified = .{ | ||
| 21675 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), | ||
| 21676 | .type_hash = hasher.final(), | ||
| 21677 | } }, | ||
| 21678 | })) { | ||
| 21679 | .wip => |wip| wip, | ||
| 21680 | .existing => |ty| return Air.internedToRef(ty), | ||
| 21681 | }; | ||
| 21682 | errdefer wip_ty.cancel(ip); | ||
| 21833 | 21683 | ||
| 21834 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | 21684 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 21835 | .ty = Type.noreturn, | 21685 | .ty = Type.type, |
| 21836 | .val = Value.@"unreachable", | 21686 | .val = Value.fromInterned(wip_ty.index), |
| 21837 | }, name_strategy, "struct", inst); | 21687 | }, name_strategy, "union", inst); |
| 21838 | const new_decl = mod.declPtr(new_decl_index); | 21688 | mod.declPtr(new_decl_index).owns_tv = true; |
| 21839 | new_decl.owns_tv = true; | 21689 | errdefer mod.abortAnonDecl(new_decl_index); |
| 21840 | errdefer { | 21690 | |
| 21841 | new_decl.has_tv = false; // namespace and val were destroyed by later errdefers | 21691 | const field_types = try sema.arena.alloc(InternPool.Index, fields_len); |
| 21842 | mod.abortAnonDecl(new_decl_index); | 21692 | const field_aligns = if (any_aligns) try sema.arena.alloc(InternPool.Alignment, fields_len) else undefined; |
| 21693 | |||
| 21694 | const enum_tag_ty, const has_explicit_tag = if (opt_tag_type_val.optionalValue(mod)) |tag_type_val| tag_ty: { | ||
| 21695 | switch (ip.indexToKey(tag_type_val.toIntern())) { | ||
| 21696 | .enum_type => {}, | ||
| 21697 | else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}), | ||
| 21698 | } | ||
| 21699 | const enum_tag_ty = tag_type_val.toType(); | ||
| 21700 | |||
| 21701 | // We simply track which fields of the tag type have been seen. | ||
| 21702 | const tag_ty_fields_len = enum_tag_ty.enumFieldCount(mod); | ||
| 21703 | var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len); | ||
| 21704 | |||
| 21705 | for (field_types, 0..) |*field_ty, field_idx| { | ||
| 21706 | const field_info = try fields_val.elemValue(mod, field_idx); | ||
| 21707 | |||
| 21708 | const field_name_val = try field_info.fieldValue(mod, 0); | ||
| 21709 | const field_type_val = try field_info.fieldValue(mod, 1); | ||
| 21710 | |||
| 21711 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21712 | |||
| 21713 | const enum_index = enum_tag_ty.enumFieldIndex(field_name, mod) orelse { | ||
| 21714 | // TODO: better source location | ||
| 21715 | return sema.fail(block, src, "no field named '{}' in enum '{}'", .{ | ||
| 21716 | field_name.fmt(ip), enum_tag_ty.fmt(mod), | ||
| 21717 | }); | ||
| 21718 | }; | ||
| 21719 | if (seen_tags.isSet(enum_index)) { | ||
| 21720 | // TODO: better source location | ||
| 21721 | return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)}); | ||
| 21722 | } | ||
| 21723 | seen_tags.set(enum_index); | ||
| 21724 | |||
| 21725 | field_ty.* = field_type_val.toIntern(); | ||
| 21726 | if (any_aligns) { | ||
| 21727 | const byte_align = try (try field_info.fieldValue(mod, 2)).toUnsignedIntAdvanced(sema); | ||
| 21728 | if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) { | ||
| 21729 | // TODO: better source location | ||
| 21730 | return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align}); | ||
| 21731 | } | ||
| 21732 | field_aligns[field_idx] = Alignment.fromByteUnits(byte_align); | ||
| 21733 | } | ||
| 21734 | } | ||
| 21735 | |||
| 21736 | if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: { | ||
| 21737 | const msg = try sema.errMsg(block, src, "enum fields missing in union", .{}); | ||
| 21738 | errdefer msg.destroy(gpa); | ||
| 21739 | var it = seen_tags.iterator(.{ .kind = .unset }); | ||
| 21740 | while (it.next()) |enum_index| { | ||
| 21741 | const field_name = enum_tag_ty.enumFieldName(enum_index, mod); | ||
| 21742 | try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{}' missing, declared here", .{ | ||
| 21743 | field_name.fmt(ip), | ||
| 21744 | }); | ||
| 21745 | } | ||
| 21746 | try sema.addDeclaredHereNote(msg, enum_tag_ty); | ||
| 21747 | break :msg msg; | ||
| 21748 | }); | ||
| 21749 | |||
| 21750 | break :tag_ty .{ enum_tag_ty.toIntern(), true }; | ||
| 21751 | } else tag_ty: { | ||
| 21752 | // We must track field names and set up the tag type ourselves. | ||
| 21753 | var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; | ||
| 21754 | try field_names.ensureTotalCapacity(sema.arena, fields_len); | ||
| 21755 | |||
| 21756 | for (field_types, 0..) |*field_ty, field_idx| { | ||
| 21757 | const field_info = try fields_val.elemValue(mod, field_idx); | ||
| 21758 | |||
| 21759 | const field_name_val = try field_info.fieldValue(mod, 0); | ||
| 21760 | const field_type_val = try field_info.fieldValue(mod, 1); | ||
| 21761 | |||
| 21762 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21763 | const gop = field_names.getOrPutAssumeCapacity(field_name); | ||
| 21764 | if (gop.found_existing) { | ||
| 21765 | // TODO: better source location | ||
| 21766 | return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)}); | ||
| 21767 | } | ||
| 21768 | |||
| 21769 | field_ty.* = field_type_val.toIntern(); | ||
| 21770 | if (any_aligns) { | ||
| 21771 | const byte_align = try (try field_info.fieldValue(mod, 2)).toUnsignedIntAdvanced(sema); | ||
| 21772 | if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) { | ||
| 21773 | // TODO: better source location | ||
| 21774 | return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align}); | ||
| 21775 | } | ||
| 21776 | field_aligns[field_idx] = Alignment.fromByteUnits(byte_align); | ||
| 21777 | } | ||
| 21778 | } | ||
| 21779 | |||
| 21780 | const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), mod.declPtr(new_decl_index)); | ||
| 21781 | break :tag_ty .{ enum_tag_ty, false }; | ||
| 21782 | }; | ||
| 21783 | errdefer if (!has_explicit_tag) ip.remove(enum_tag_ty); // remove generated tag type on error | ||
| 21784 | |||
| 21785 | for (field_types) |field_ty_ip| { | ||
| 21786 | const field_ty = Type.fromInterned(field_ty_ip); | ||
| 21787 | if (field_ty.zigTypeTag(mod) == .Opaque) { | ||
| 21788 | return sema.failWithOwnedErrorMsg(block, msg: { | ||
| 21789 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); | ||
| 21790 | errdefer msg.destroy(gpa); | ||
| 21791 | |||
| 21792 | try sema.addDeclaredHereNote(msg, field_ty); | ||
| 21793 | break :msg msg; | ||
| 21794 | }); | ||
| 21795 | } | ||
| 21796 | if (layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) { | ||
| 21797 | return sema.failWithOwnedErrorMsg(block, msg: { | ||
| 21798 | const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); | ||
| 21799 | errdefer msg.destroy(gpa); | ||
| 21800 | |||
| 21801 | const src_decl = mod.declPtr(block.src_decl); | ||
| 21802 | try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), field_ty, .union_field); | ||
| 21803 | |||
| 21804 | try sema.addDeclaredHereNote(msg, field_ty); | ||
| 21805 | break :msg msg; | ||
| 21806 | }); | ||
| 21807 | } else if (layout == .Packed and !try sema.validatePackedType(field_ty)) { | ||
| 21808 | return sema.failWithOwnedErrorMsg(block, msg: { | ||
| 21809 | const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); | ||
| 21810 | errdefer msg.destroy(gpa); | ||
| 21811 | |||
| 21812 | const src_decl = mod.declPtr(block.src_decl); | ||
| 21813 | try sema.explainWhyTypeIsNotPacked(msg, src_decl.toSrcLoc(src, mod), field_ty); | ||
| 21814 | |||
| 21815 | try sema.addDeclaredHereNote(msg, field_ty); | ||
| 21816 | break :msg msg; | ||
| 21817 | }); | ||
| 21818 | } | ||
| 21843 | } | 21819 | } |
| 21844 | 21820 | ||
| 21845 | const ty = try ip.getStructType(gpa, .{ | 21821 | const loaded_union = ip.loadUnionType(wip_ty.index); |
| 21846 | .decl = new_decl_index, | 21822 | loaded_union.setFieldTypes(ip, field_types); |
| 21847 | .namespace = .none, | 21823 | if (any_aligns) { |
| 21848 | .zir_index = .none, | 21824 | loaded_union.setFieldAligns(ip, field_aligns); |
| 21825 | } | ||
| 21826 | loaded_union.tagTypePtr(ip).* = enum_tag_ty; | ||
| 21827 | loaded_union.flagsPtr(ip).status = .have_field_types; | ||
| 21828 | |||
| 21829 | try mod.finalizeAnonDecl(new_decl_index); | ||
| 21830 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none)); | ||
| 21831 | } | ||
| 21832 | |||
| 21833 | fn reifyStruct( | ||
| 21834 | sema: *Sema, | ||
| 21835 | block: *Block, | ||
| 21836 | inst: Zir.Inst.Index, | ||
| 21837 | src: LazySrcLoc, | ||
| 21838 | layout: std.builtin.Type.ContainerLayout, | ||
| 21839 | opt_backing_int_val: Value, | ||
| 21840 | fields_val: Value, | ||
| 21841 | name_strategy: Zir.Inst.NameStrategy, | ||
| 21842 | is_tuple: bool, | ||
| 21843 | ) CompileError!Air.Inst.Ref { | ||
| 21844 | const mod = sema.mod; | ||
| 21845 | const gpa = sema.gpa; | ||
| 21846 | const ip = &mod.intern_pool; | ||
| 21847 | |||
| 21848 | // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`. | ||
| 21849 | |||
| 21850 | const fields_len: u32 = @intCast(fields_val.sliceLen(mod)); | ||
| 21851 | |||
| 21852 | // The validation work here is non-trivial, and it's possible the type already exists. | ||
| 21853 | // So in this first pass, let's just construct a hash to optimize for this case. If the | ||
| 21854 | // inputs turn out to be invalid, we can cancel the WIP type later. | ||
| 21855 | |||
| 21856 | // For deduplication purposes, we must create a hash including all details of this type. | ||
| 21857 | // TODO: use a longer hash! | ||
| 21858 | var hasher = std.hash.Wyhash.init(0); | ||
| 21859 | std.hash.autoHash(&hasher, layout); | ||
| 21860 | std.hash.autoHash(&hasher, opt_backing_int_val.toIntern()); | ||
| 21861 | std.hash.autoHash(&hasher, is_tuple); | ||
| 21862 | std.hash.autoHash(&hasher, fields_len); | ||
| 21863 | |||
| 21864 | var any_comptime_fields = false; | ||
| 21865 | var any_default_inits = false; | ||
| 21866 | var any_aligned_fields = false; | ||
| 21867 | |||
| 21868 | for (0..fields_len) |field_idx| { | ||
| 21869 | const field_info = try fields_val.elemValue(mod, field_idx); | ||
| 21870 | |||
| 21871 | const field_name_val = try field_info.fieldValue(mod, 0); | ||
| 21872 | const field_type_val = try field_info.fieldValue(mod, 1); | ||
| 21873 | const field_default_value_val = try field_info.fieldValue(mod, 2); | ||
| 21874 | const field_is_comptime_val = try field_info.fieldValue(mod, 3); | ||
| 21875 | const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 4)); | ||
| 21876 | |||
| 21877 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21878 | const field_is_comptime = field_is_comptime_val.toBool(); | ||
| 21879 | const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(mod)) |ptr_val| d: { | ||
| 21880 | const ptr_ty = try mod.singleConstPtrType(field_type_val.toType()); | ||
| 21881 | // We need to do this deref here, so we won't check for this error case later on. | ||
| 21882 | const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime( | ||
| 21883 | block, | ||
| 21884 | src, | ||
| 21885 | .{ .needed_comptime_reason = "struct field default value must be comptime-known" }, | ||
| 21886 | ); | ||
| 21887 | // Resolve the value so that lazy values do not create distinct types. | ||
| 21888 | break :d (try sema.resolveLazyValue(val)).toIntern(); | ||
| 21889 | } else .none; | ||
| 21890 | |||
| 21891 | std.hash.autoHash(&hasher, .{ | ||
| 21892 | field_name, | ||
| 21893 | field_type_val.toIntern(), | ||
| 21894 | field_default_value, | ||
| 21895 | field_is_comptime, | ||
| 21896 | field_alignment_val.toIntern(), | ||
| 21897 | }); | ||
| 21898 | |||
| 21899 | if (field_is_comptime) any_comptime_fields = true; | ||
| 21900 | if (field_default_value != .none) any_default_inits = true; | ||
| 21901 | switch (try field_alignment_val.orderAgainstZeroAdvanced(mod, sema)) { | ||
| 21902 | .eq => {}, | ||
| 21903 | .gt => any_aligned_fields = true, | ||
| 21904 | .lt => unreachable, | ||
| 21905 | } | ||
| 21906 | } | ||
| 21907 | |||
| 21908 | const wip_ty = switch (try ip.getStructType(gpa, .{ | ||
| 21849 | .layout = layout, | 21909 | .layout = layout, |
| 21850 | .known_non_opv = false, | ||
| 21851 | .fields_len = fields_len, | 21910 | .fields_len = fields_len, |
| 21911 | .known_non_opv = false, | ||
| 21852 | .requires_comptime = .unknown, | 21912 | .requires_comptime = .unknown, |
| 21853 | .is_tuple = is_tuple, | 21913 | .is_tuple = is_tuple, |
| 21854 | // So that we don't have to scan ahead, we allocate space in the struct | 21914 | .any_comptime_fields = any_comptime_fields, |
| 21855 | // type for alignments, comptime fields, and default inits. This might | 21915 | .any_default_inits = any_default_inits, |
| 21856 | // result in wasted space, however, this is a permitted encoding of | 21916 | .any_aligned_fields = any_aligned_fields, |
| 21857 | // struct types. | ||
| 21858 | .any_comptime_fields = true, | ||
| 21859 | .any_default_inits = true, | ||
| 21860 | .inits_resolved = true, | 21917 | .inits_resolved = true, |
| 21861 | .any_aligned_fields = true, | 21918 | .has_namespace = false, |
| 21862 | }); | 21919 | .key = .{ .reified = .{ |
| 21863 | // TODO: figure out InternPool removals for incremental compilation | 21920 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), |
| 21864 | //errdefer ip.remove(ty); | 21921 | .type_hash = hasher.final(), |
| 21865 | const struct_type = ip.indexToKey(ty).struct_type; | 21922 | } }, |
| 21923 | })) { | ||
| 21924 | .wip => |wip| wip, | ||
| 21925 | .existing => |ty| return Air.internedToRef(ty), | ||
| 21926 | }; | ||
| 21927 | errdefer wip_ty.cancel(ip); | ||
| 21866 | 21928 | ||
| 21867 | new_decl.ty = Type.type; | 21929 | if (is_tuple) switch (layout) { |
| 21868 | new_decl.val = Value.fromInterned(ty); | 21930 | .Extern => return sema.fail(block, src, "extern tuples are not supported", .{}), |
| 21869 | 21931 | .Packed => return sema.fail(block, src, "packed tuples are not supported", .{}), | |
| 21870 | // Fields | 21932 | .Auto => {}, |
| 21871 | for (0..fields_len) |i| { | 21933 | }; |
| 21872 | const elem_val = try fields_val.elemValue(mod, i); | ||
| 21873 | const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type; | ||
| 21874 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21875 | ip, | ||
| 21876 | try ip.getOrPutString(gpa, "name"), | ||
| 21877 | ).?); | ||
| 21878 | const type_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21879 | ip, | ||
| 21880 | try ip.getOrPutString(gpa, "type"), | ||
| 21881 | ).?); | ||
| 21882 | const default_value_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21883 | ip, | ||
| 21884 | try ip.getOrPutString(gpa, "default_value"), | ||
| 21885 | ).?); | ||
| 21886 | const is_comptime_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21887 | ip, | ||
| 21888 | try ip.getOrPutString(gpa, "is_comptime"), | ||
| 21889 | ).?); | ||
| 21890 | const alignment_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | ||
| 21891 | ip, | ||
| 21892 | try ip.getOrPutString(gpa, "alignment"), | ||
| 21893 | ).?); | ||
| 21894 | |||
| 21895 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { | ||
| 21896 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); | ||
| 21897 | } | ||
| 21898 | const abi_align = (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?; | ||
| 21899 | |||
| 21900 | if (layout == .Packed) { | ||
| 21901 | if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); | ||
| 21902 | if (is_comptime_val.toBool()) return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}); | ||
| 21903 | } else { | ||
| 21904 | if (abi_align > 0 and !math.isPowerOfTwo(abi_align)) return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{abi_align}); | ||
| 21905 | struct_type.field_aligns.get(ip)[i] = Alignment.fromByteUnits(abi_align); | ||
| 21906 | } | ||
| 21907 | if (layout == .Extern and is_comptime_val.toBool()) { | ||
| 21908 | return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}); | ||
| 21909 | } | ||
| 21910 | 21934 | ||
| 21911 | const field_name = try name_val.toIpString(Type.slice_const_u8, mod); | 21935 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 21936 | .ty = Type.type, | ||
| 21937 | .val = Value.fromInterned(wip_ty.index), | ||
| 21938 | }, name_strategy, "struct", inst); | ||
| 21939 | mod.declPtr(new_decl_index).owns_tv = true; | ||
| 21940 | errdefer mod.abortAnonDecl(new_decl_index); | ||
| 21912 | 21941 | ||
| 21942 | const struct_type = ip.loadStructType(wip_ty.index); | ||
| 21943 | |||
| 21944 | for (0..fields_len) |field_idx| { | ||
| 21945 | const field_info = try fields_val.elemValue(mod, field_idx); | ||
| 21946 | |||
| 21947 | const field_name_val = try field_info.fieldValue(mod, 0); | ||
| 21948 | const field_type_val = try field_info.fieldValue(mod, 1); | ||
| 21949 | const field_default_value_val = try field_info.fieldValue(mod, 2); | ||
| 21950 | const field_is_comptime_val = try field_info.fieldValue(mod, 3); | ||
| 21951 | const field_alignment_val = try field_info.fieldValue(mod, 4); | ||
| 21952 | |||
| 21953 | const field_ty = field_type_val.toType(); | ||
| 21954 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | ||
| 21913 | if (is_tuple) { | 21955 | if (is_tuple) { |
| 21914 | const field_index = field_name.toUnsigned(ip) orelse return sema.fail( | 21956 | const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail( |
| 21915 | block, | 21957 | block, |
| 21916 | src, | 21958 | src, |
| 21917 | "tuple cannot have non-numeric field '{}'", | 21959 | "tuple cannot have non-numeric field '{}'", |
| 21918 | .{field_name.fmt(ip)}, | 21960 | .{field_name.fmt(ip)}, |
| 21919 | ); | 21961 | ); |
| 21920 | 21962 | if (field_name_index != field_idx) { | |
| 21921 | if (field_index >= fields_len) { | ||
| 21922 | return sema.fail( | 21963 | return sema.fail( |
| 21923 | block, | 21964 | block, |
| 21924 | src, | 21965 | src, |
| 21925 | "tuple field {} exceeds tuple field count", | 21966 | "tuple field name '{}' does not match field index {}", |
| 21926 | .{field_index}, | 21967 | .{ field_name_index, field_idx }, |
| 21927 | ); | 21968 | ); |
| 21928 | } | 21969 | } |
| 21929 | } else if (struct_type.addFieldName(ip, field_name)) |prev_index| { | 21970 | } else if (struct_type.addFieldName(ip, field_name)) |prev_index| { |
| ... | @@ -21931,45 +21972,72 @@ fn reifyStruct( | ... | @@ -21931,45 +21972,72 @@ fn reifyStruct( |
| 21931 | return sema.fail(block, src, "duplicate struct field name {}", .{field_name.fmt(ip)}); | 21972 | return sema.fail(block, src, "duplicate struct field name {}", .{field_name.fmt(ip)}); |
| 21932 | } | 21973 | } |
| 21933 | 21974 | ||
| 21934 | const field_ty = type_val.toType(); | 21975 | if (any_aligned_fields) { |
| 21935 | const default_val = if (default_value_val.optionalValue(mod)) |opt_val| | 21976 | if (!try sema.intFitsInType(field_alignment_val, Type.u32, null)) { |
| 21936 | (try sema.pointerDeref(block, src, opt_val, try mod.singleConstPtrType(field_ty)) orelse | 21977 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| 21937 | return sema.failWithNeededComptime(block, src, .{ | 21978 | } |
| 21938 | .needed_comptime_reason = "struct field default value must be comptime-known", | 21979 | |
| 21939 | })).toIntern() | 21980 | const byte_align = try field_alignment_val.toUnsignedIntAdvanced(sema); |
| 21940 | else | 21981 | if (byte_align == 0) { |
| 21941 | .none; | 21982 | if (layout != .Packed) { |
| 21942 | if (is_comptime_val.toBool() and default_val == .none) { | 21983 | struct_type.field_aligns.get(ip)[field_idx] = .none; |
| 21984 | } | ||
| 21985 | } else { | ||
| 21986 | if (layout == .Packed) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); | ||
| 21987 | if (!math.isPowerOfTwo(byte_align)) return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align}); | ||
| 21988 | struct_type.field_aligns.get(ip)[field_idx] = Alignment.fromNonzeroByteUnits(byte_align); | ||
| 21989 | } | ||
| 21990 | } | ||
| 21991 | |||
| 21992 | const field_is_comptime = field_is_comptime_val.toBool(); | ||
| 21993 | if (field_is_comptime) { | ||
| 21994 | assert(any_comptime_fields); | ||
| 21995 | switch (layout) { | ||
| 21996 | .Extern => return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}), | ||
| 21997 | .Packed => return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}), | ||
| 21998 | .Auto => struct_type.setFieldComptime(ip, field_idx), | ||
| 21999 | } | ||
| 22000 | } | ||
| 22001 | |||
| 22002 | const field_default: InternPool.Index = d: { | ||
| 22003 | if (!any_default_inits) break :d .none; | ||
| 22004 | const ptr_val = field_default_value_val.optionalValue(mod) orelse break :d .none; | ||
| 22005 | const ptr_ty = try mod.singleConstPtrType(field_ty); | ||
| 22006 | // Asserted comptime-dereferencable above. | ||
| 22007 | const val = (try sema.pointerDeref(block, src, ptr_val, ptr_ty)).?; | ||
| 22008 | // We already resolved this for deduplication, so we may as well do it now. | ||
| 22009 | break :d (try sema.resolveLazyValue(val)).toIntern(); | ||
| 22010 | }; | ||
| 22011 | |||
| 22012 | if (field_is_comptime and field_default == .none) { | ||
| 21943 | return sema.fail(block, src, "comptime field without default initialization value", .{}); | 22013 | return sema.fail(block, src, "comptime field without default initialization value", .{}); |
| 21944 | } | 22014 | } |
| 21945 | 22015 | ||
| 21946 | struct_type.field_types.get(ip)[i] = field_ty.toIntern(); | 22016 | struct_type.field_types.get(ip)[field_idx] = field_type_val.toIntern(); |
| 21947 | struct_type.field_inits.get(ip)[i] = default_val; | 22017 | if (field_default != .none) { |
| 21948 | if (is_comptime_val.toBool()) | 22018 | struct_type.field_inits.get(ip)[field_idx] = field_default; |
| 21949 | struct_type.setFieldComptime(ip, i); | 22019 | } |
| 21950 | 22020 | ||
| 21951 | if (field_ty.zigTypeTag(mod) == .Opaque) { | 22021 | if (field_ty.zigTypeTag(mod) == .Opaque) { |
| 21952 | const msg = msg: { | 22022 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 21953 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | 22023 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 21954 | errdefer msg.destroy(gpa); | 22024 | errdefer msg.destroy(gpa); |
| 21955 | 22025 | ||
| 21956 | try sema.addDeclaredHereNote(msg, field_ty); | 22026 | try sema.addDeclaredHereNote(msg, field_ty); |
| 21957 | break :msg msg; | 22027 | break :msg msg; |
| 21958 | }; | 22028 | }); |
| 21959 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21960 | } | 22029 | } |
| 21961 | if (field_ty.zigTypeTag(mod) == .NoReturn) { | 22030 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| 21962 | const msg = msg: { | 22031 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 21963 | const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); | 22032 | const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); |
| 21964 | errdefer msg.destroy(gpa); | 22033 | errdefer msg.destroy(gpa); |
| 21965 | 22034 | ||
| 21966 | try sema.addDeclaredHereNote(msg, field_ty); | 22035 | try sema.addDeclaredHereNote(msg, field_ty); |
| 21967 | break :msg msg; | 22036 | break :msg msg; |
| 21968 | }; | 22037 | }); |
| 21969 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21970 | } | 22038 | } |
| 21971 | if (layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) { | 22039 | if (layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) { |
| 21972 | const msg = msg: { | 22040 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 21973 | const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | 22041 | const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 21974 | errdefer msg.destroy(gpa); | 22042 | errdefer msg.destroy(gpa); |
| 21975 | 22043 | ||
| ... | @@ -21978,10 +22046,9 @@ fn reifyStruct( | ... | @@ -21978,10 +22046,9 @@ fn reifyStruct( |
| 21978 | 22046 | ||
| 21979 | try sema.addDeclaredHereNote(msg, field_ty); | 22047 | try sema.addDeclaredHereNote(msg, field_ty); |
| 21980 | break :msg msg; | 22048 | break :msg msg; |
| 21981 | }; | 22049 | }); |
| 21982 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21983 | } else if (layout == .Packed and !try sema.validatePackedType(field_ty)) { | 22050 | } else if (layout == .Packed and !try sema.validatePackedType(field_ty)) { |
| 21984 | const msg = msg: { | 22051 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 21985 | const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | 22052 | const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 21986 | errdefer msg.destroy(gpa); | 22053 | errdefer msg.destroy(gpa); |
| 21987 | 22054 | ||
| ... | @@ -21990,32 +22057,27 @@ fn reifyStruct( | ... | @@ -21990,32 +22057,27 @@ fn reifyStruct( |
| 21990 | 22057 | ||
| 21991 | try sema.addDeclaredHereNote(msg, field_ty); | 22058 | try sema.addDeclaredHereNote(msg, field_ty); |
| 21992 | break :msg msg; | 22059 | break :msg msg; |
| 21993 | }; | 22060 | }); |
| 21994 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 21995 | } | 22061 | } |
| 21996 | } | 22062 | } |
| 21997 | 22063 | ||
| 21998 | if (layout == .Packed) { | 22064 | if (layout == .Packed) { |
| 21999 | for (0..struct_type.field_types.len) |index| { | 22065 | var fields_bit_sum: u64 = 0; |
| 22000 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]); | 22066 | for (0..struct_type.field_types.len) |field_idx| { |
| 22067 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_idx]); | ||
| 22001 | sema.resolveTypeLayout(field_ty) catch |err| switch (err) { | 22068 | sema.resolveTypeLayout(field_ty) catch |err| switch (err) { |
| 22002 | error.AnalysisFail => { | 22069 | error.AnalysisFail => { |
| 22003 | const msg = sema.err orelse return err; | 22070 | const msg = sema.err orelse return err; |
| 22004 | try sema.addFieldErrNote(Type.fromInterned(ty), index, msg, "while checking this field", .{}); | 22071 | try sema.errNote(block, src, msg, "while checking a field of this struct", .{}); |
| 22005 | return err; | 22072 | return err; |
| 22006 | }, | 22073 | }, |
| 22007 | else => return err, | 22074 | else => return err, |
| 22008 | }; | 22075 | }; |
| 22009 | } | ||
| 22010 | |||
| 22011 | var fields_bit_sum: u64 = 0; | ||
| 22012 | for (0..struct_type.field_types.len) |i| { | ||
| 22013 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | ||
| 22014 | fields_bit_sum += field_ty.bitSize(mod); | 22076 | fields_bit_sum += field_ty.bitSize(mod); |
| 22015 | } | 22077 | } |
| 22016 | 22078 | ||
| 22017 | if (backing_int_val.optionalValue(mod)) |backing_int_ty_val| { | 22079 | if (opt_backing_int_val.optionalValue(mod)) |backing_int_val| { |
| 22018 | const backing_int_ty = backing_int_ty_val.toType(); | 22080 | const backing_int_ty = backing_int_val.toType(); |
| 22019 | try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum); | 22081 | try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum); |
| 22020 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); | 22082 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); |
| 22021 | } else { | 22083 | } else { |
| ... | @@ -22024,9 +22086,8 @@ fn reifyStruct( | ... | @@ -22024,9 +22086,8 @@ fn reifyStruct( |
| 22024 | } | 22086 | } |
| 22025 | } | 22087 | } |
| 22026 | 22088 | ||
| 22027 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | ||
| 22028 | try mod.finalizeAnonDecl(new_decl_index); | 22089 | try mod.finalizeAnonDecl(new_decl_index); |
| 22029 | return decl_val; | 22090 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none)); |
| 22030 | } | 22091 | } |
| 22031 | 22092 | ||
| 22032 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { | 22093 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { |
| ... | @@ -23241,7 +23302,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 | ... | @@ -23241,7 +23302,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 23241 | switch (ty.containerLayout(mod)) { | 23302 | switch (ty.containerLayout(mod)) { |
| 23242 | .Packed => { | 23303 | .Packed => { |
| 23243 | var bit_sum: u64 = 0; | 23304 | var bit_sum: u64 = 0; |
| 23244 | const struct_type = ip.indexToKey(ty.toIntern()).struct_type; | 23305 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 23245 | for (0..struct_type.field_types.len) |i| { | 23306 | for (0..struct_type.field_types.len) |i| { |
| 23246 | if (i == field_index) { | 23307 | if (i == field_index) { |
| 23247 | return bit_sum; | 23308 | return bit_sum; |
| ... | @@ -25919,7 +25980,7 @@ fn zirBuiltinExtern( | ... | @@ -25919,7 +25980,7 @@ fn zirBuiltinExtern( |
| 25919 | 25980 | ||
| 25920 | // TODO check duplicate extern | 25981 | // TODO check duplicate extern |
| 25921 | 25982 | ||
| 25922 | const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, .none); | 25983 | const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node); |
| 25923 | errdefer mod.destroyDecl(new_decl_index); | 25984 | errdefer mod.destroyDecl(new_decl_index); |
| 25924 | const new_decl = mod.declPtr(new_decl_index); | 25985 | const new_decl = mod.declPtr(new_decl_index); |
| 25925 | new_decl.name = options.name; | 25986 | new_decl.name = options.name; |
| ... | @@ -26515,7 +26576,6 @@ fn addSafetyCheck( | ... | @@ -26515,7 +26576,6 @@ fn addSafetyCheck( |
| 26515 | .sema = sema, | 26576 | .sema = sema, |
| 26516 | .src_decl = parent_block.src_decl, | 26577 | .src_decl = parent_block.src_decl, |
| 26517 | .namespace = parent_block.namespace, | 26578 | .namespace = parent_block.namespace, |
| 26518 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 26519 | .instructions = .{}, | 26579 | .instructions = .{}, |
| 26520 | .inlining = parent_block.inlining, | 26580 | .inlining = parent_block.inlining, |
| 26521 | .is_comptime = false, | 26581 | .is_comptime = false, |
| ... | @@ -26624,7 +26684,6 @@ fn panicUnwrapError( | ... | @@ -26624,7 +26684,6 @@ fn panicUnwrapError( |
| 26624 | .sema = sema, | 26684 | .sema = sema, |
| 26625 | .src_decl = parent_block.src_decl, | 26685 | .src_decl = parent_block.src_decl, |
| 26626 | .namespace = parent_block.namespace, | 26686 | .namespace = parent_block.namespace, |
| 26627 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 26628 | .instructions = .{}, | 26687 | .instructions = .{}, |
| 26629 | .inlining = parent_block.inlining, | 26688 | .inlining = parent_block.inlining, |
| 26630 | .is_comptime = false, | 26689 | .is_comptime = false, |
| ... | @@ -26741,7 +26800,6 @@ fn safetyCheckFormatted( | ... | @@ -26741,7 +26800,6 @@ fn safetyCheckFormatted( |
| 26741 | .sema = sema, | 26800 | .sema = sema, |
| 26742 | .src_decl = parent_block.src_decl, | 26801 | .src_decl = parent_block.src_decl, |
| 26743 | .namespace = parent_block.namespace, | 26802 | .namespace = parent_block.namespace, |
| 26744 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 26745 | .instructions = .{}, | 26803 | .instructions = .{}, |
| 26746 | .inlining = parent_block.inlining, | 26804 | .inlining = parent_block.inlining, |
| 26747 | .is_comptime = false, | 26805 | .is_comptime = false, |
| ... | @@ -27268,8 +27326,7 @@ fn fieldCallBind( | ... | @@ -27268,8 +27326,7 @@ fn fieldCallBind( |
| 27268 | .Union => { | 27326 | .Union => { |
| 27269 | try sema.resolveTypeFields(concrete_ty); | 27327 | try sema.resolveTypeFields(concrete_ty); |
| 27270 | const union_obj = mod.typeToUnion(concrete_ty).?; | 27328 | const union_obj = mod.typeToUnion(concrete_ty).?; |
| 27271 | _ = union_obj.nameIndex(ip, field_name) orelse break :find_field; | 27329 | _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field; |
| 27272 | |||
| 27273 | const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false); | 27330 | const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false); |
| 27274 | return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) }; | 27331 | return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) }; |
| 27275 | }, | 27332 | }, |
| ... | @@ -27643,7 +27700,8 @@ fn structFieldVal( | ... | @@ -27643,7 +27700,8 @@ fn structFieldVal( |
| 27643 | try sema.resolveTypeFields(struct_ty); | 27700 | try sema.resolveTypeFields(struct_ty); |
| 27644 | 27701 | ||
| 27645 | switch (ip.indexToKey(struct_ty.toIntern())) { | 27702 | switch (ip.indexToKey(struct_ty.toIntern())) { |
| 27646 | .struct_type => |struct_type| { | 27703 | .struct_type => { |
| 27704 | const struct_type = ip.loadStructType(struct_ty.toIntern()); | ||
| 27647 | if (struct_type.isTuple(ip)) | 27705 | if (struct_type.isTuple(ip)) |
| 27648 | return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); | 27706 | return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); |
| 27649 | 27707 | ||
| ... | @@ -27849,7 +27907,7 @@ fn unionFieldPtr( | ... | @@ -27849,7 +27907,7 @@ fn unionFieldPtr( |
| 27849 | 27907 | ||
| 27850 | try sema.requireRuntimeBlock(block, src, null); | 27908 | try sema.requireRuntimeBlock(block, src, null); |
| 27851 | if (!initializing and union_obj.getLayout(ip) == .Auto and block.wantSafety() and | 27909 | if (!initializing and union_obj.getLayout(ip) == .Auto and block.wantSafety() and |
| 27852 | union_ty.unionTagTypeSafety(mod) != null and union_obj.field_names.len > 1) | 27910 | union_ty.unionTagTypeSafety(mod) != null and union_obj.field_types.len > 1) |
| 27853 | { | 27911 | { |
| 27854 | const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); | 27912 | const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); |
| 27855 | const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); | 27913 | const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); |
| ... | @@ -27927,7 +27985,7 @@ fn unionFieldVal( | ... | @@ -27927,7 +27985,7 @@ fn unionFieldVal( |
| 27927 | 27985 | ||
| 27928 | try sema.requireRuntimeBlock(block, src, null); | 27986 | try sema.requireRuntimeBlock(block, src, null); |
| 27929 | if (union_obj.getLayout(ip) == .Auto and block.wantSafety() and | 27987 | if (union_obj.getLayout(ip) == .Auto and block.wantSafety() and |
| 27930 | union_ty.unionTagTypeSafety(mod) != null and union_obj.field_names.len > 1) | 27988 | union_ty.unionTagTypeSafety(mod) != null and union_obj.field_types.len > 1) |
| 27931 | { | 27989 | { |
| 27932 | const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); | 27990 | const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); |
| 27933 | const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); | 27991 | const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); |
| ... | @@ -31686,7 +31744,7 @@ fn coerceEnumToUnion( | ... | @@ -31686,7 +31744,7 @@ fn coerceEnumToUnion( |
| 31686 | const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{}); | 31744 | const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{}); |
| 31687 | errdefer msg.destroy(sema.gpa); | 31745 | errdefer msg.destroy(sema.gpa); |
| 31688 | 31746 | ||
| 31689 | const field_name = union_obj.field_names.get(ip)[field_index]; | 31747 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; |
| 31690 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{ | 31748 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{ |
| 31691 | field_name.fmt(ip), | 31749 | field_name.fmt(ip), |
| 31692 | }); | 31750 | }); |
| ... | @@ -31697,7 +31755,7 @@ fn coerceEnumToUnion( | ... | @@ -31697,7 +31755,7 @@ fn coerceEnumToUnion( |
| 31697 | } | 31755 | } |
| 31698 | const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse { | 31756 | const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse { |
| 31699 | const msg = msg: { | 31757 | const msg = msg: { |
| 31700 | const field_name = union_obj.field_names.get(ip)[field_index]; | 31758 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; |
| 31701 | const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{ | 31759 | const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{ |
| 31702 | inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod), | 31760 | inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod), |
| 31703 | field_ty.fmt(sema.mod), field_name.fmt(ip), | 31761 | field_ty.fmt(sema.mod), field_name.fmt(ip), |
| ... | @@ -31769,8 +31827,8 @@ fn coerceEnumToUnion( | ... | @@ -31769,8 +31827,8 @@ fn coerceEnumToUnion( |
| 31769 | ); | 31827 | ); |
| 31770 | errdefer msg.destroy(sema.gpa); | 31828 | errdefer msg.destroy(sema.gpa); |
| 31771 | 31829 | ||
| 31772 | for (0..union_obj.field_names.len) |field_index| { | 31830 | for (0..union_obj.field_types.len) |field_index| { |
| 31773 | const field_name = union_obj.field_names.get(ip)[field_index]; | 31831 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; |
| 31774 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 31832 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 31775 | if (!(try sema.typeHasRuntimeBits(field_ty))) continue; | 31833 | if (!(try sema.typeHasRuntimeBits(field_ty))) continue; |
| 31776 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{ | 31834 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{ |
| ... | @@ -31803,8 +31861,8 @@ fn coerceAnonStructToUnion( | ... | @@ -31803,8 +31861,8 @@ fn coerceAnonStructToUnion( |
| 31803 | .{ .name = anon_struct_type.names.get(ip)[0] } | 31861 | .{ .name = anon_struct_type.names.get(ip)[0] } |
| 31804 | else | 31862 | else |
| 31805 | .{ .count = anon_struct_type.names.len }, | 31863 | .{ .count = anon_struct_type.names.len }, |
| 31806 | .struct_type => |struct_type| name: { | 31864 | .struct_type => name: { |
| 31807 | const field_names = struct_type.field_names.get(ip); | 31865 | const field_names = ip.loadStructType(inst_ty.toIntern()).field_names.get(ip); |
| 31808 | break :name if (field_names.len == 1) | 31866 | break :name if (field_names.len == 1) |
| 31809 | .{ .name = field_names[0] } | 31867 | .{ .name = field_names[0] } |
| 31810 | else | 31868 | else |
| ... | @@ -32113,7 +32171,7 @@ fn coerceTupleToStruct( | ... | @@ -32113,7 +32171,7 @@ fn coerceTupleToStruct( |
| 32113 | var runtime_src: ?LazySrcLoc = null; | 32171 | var runtime_src: ?LazySrcLoc = null; |
| 32114 | const field_count = switch (ip.indexToKey(inst_ty.toIntern())) { | 32172 | const field_count = switch (ip.indexToKey(inst_ty.toIntern())) { |
| 32115 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, | 32173 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, |
| 32116 | .struct_type => |s| s.field_types.len, | 32174 | .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len, |
| 32117 | else => unreachable, | 32175 | else => unreachable, |
| 32118 | }; | 32176 | }; |
| 32119 | for (0..field_count) |field_index_usize| { | 32177 | for (0..field_count) |field_index_usize| { |
| ... | @@ -32125,7 +32183,7 @@ fn coerceTupleToStruct( | ... | @@ -32125,7 +32183,7 @@ fn coerceTupleToStruct( |
| 32125 | anon_struct_type.names.get(ip)[field_i] | 32183 | anon_struct_type.names.get(ip)[field_i] |
| 32126 | else | 32184 | else |
| 32127 | try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}), | 32185 | try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}), |
| 32128 | .struct_type => |s| s.field_names.get(ip)[field_i], | 32186 | .struct_type => ip.loadStructType(inst_ty.toIntern()).field_names.get(ip)[field_i], |
| 32129 | else => unreachable, | 32187 | else => unreachable, |
| 32130 | }; | 32188 | }; |
| 32131 | const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); | 32189 | const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); |
| ... | @@ -32213,7 +32271,7 @@ fn coerceTupleToTuple( | ... | @@ -32213,7 +32271,7 @@ fn coerceTupleToTuple( |
| 32213 | const ip = &mod.intern_pool; | 32271 | const ip = &mod.intern_pool; |
| 32214 | const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) { | 32272 | const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) { |
| 32215 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, | 32273 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, |
| 32216 | .struct_type => |struct_type| struct_type.field_types.len, | 32274 | .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.len, |
| 32217 | else => unreachable, | 32275 | else => unreachable, |
| 32218 | }; | 32276 | }; |
| 32219 | const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count); | 32277 | const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count); |
| ... | @@ -32223,7 +32281,7 @@ fn coerceTupleToTuple( | ... | @@ -32223,7 +32281,7 @@ fn coerceTupleToTuple( |
| 32223 | const inst_ty = sema.typeOf(inst); | 32281 | const inst_ty = sema.typeOf(inst); |
| 32224 | const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) { | 32282 | const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) { |
| 32225 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, | 32283 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, |
| 32226 | .struct_type => |struct_type| struct_type.field_types.len, | 32284 | .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len, |
| 32227 | else => unreachable, | 32285 | else => unreachable, |
| 32228 | }; | 32286 | }; |
| 32229 | if (src_field_count > dest_field_count) return error.NotCoercible; | 32287 | if (src_field_count > dest_field_count) return error.NotCoercible; |
| ... | @@ -32238,10 +32296,14 @@ fn coerceTupleToTuple( | ... | @@ -32238,10 +32296,14 @@ fn coerceTupleToTuple( |
| 32238 | anon_struct_type.names.get(ip)[field_i] | 32296 | anon_struct_type.names.get(ip)[field_i] |
| 32239 | else | 32297 | else |
| 32240 | try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}), | 32298 | try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}), |
| 32241 | .struct_type => |struct_type| if (struct_type.field_names.len > 0) | 32299 | .struct_type => s: { |
| 32242 | struct_type.field_names.get(ip)[field_i] | 32300 | const struct_type = ip.loadStructType(inst_ty.toIntern()); |
| 32243 | else | 32301 | if (struct_type.field_names.len > 0) { |
| 32244 | try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}), | 32302 | break :s struct_type.field_names.get(ip)[field_i]; |
| 32303 | } else { | ||
| 32304 | break :s try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}); | ||
| 32305 | } | ||
| 32306 | }, | ||
| 32245 | else => unreachable, | 32307 | else => unreachable, |
| 32246 | }; | 32308 | }; |
| 32247 | 32309 | ||
| ... | @@ -32250,12 +32312,12 @@ fn coerceTupleToTuple( | ... | @@ -32250,12 +32312,12 @@ fn coerceTupleToTuple( |
| 32250 | 32312 | ||
| 32251 | const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) { | 32313 | const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) { |
| 32252 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[field_index_usize], | 32314 | .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[field_index_usize], |
| 32253 | .struct_type => |struct_type| struct_type.field_types.get(ip)[field_index_usize], | 32315 | .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.get(ip)[field_index_usize], |
| 32254 | else => unreachable, | 32316 | else => unreachable, |
| 32255 | }; | 32317 | }; |
| 32256 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { | 32318 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { |
| 32257 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize], | 32319 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize], |
| 32258 | .struct_type => |struct_type| struct_type.fieldInit(ip, field_index_usize), | 32320 | .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, field_index_usize), |
| 32259 | else => unreachable, | 32321 | else => unreachable, |
| 32260 | }; | 32322 | }; |
| 32261 | 32323 | ||
| ... | @@ -32294,7 +32356,7 @@ fn coerceTupleToTuple( | ... | @@ -32294,7 +32356,7 @@ fn coerceTupleToTuple( |
| 32294 | 32356 | ||
| 32295 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { | 32357 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { |
| 32296 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i], | 32358 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i], |
| 32297 | .struct_type => |struct_type| struct_type.fieldInit(ip, i), | 32359 | .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, i), |
| 32298 | else => unreachable, | 32360 | else => unreachable, |
| 32299 | }; | 32361 | }; |
| 32300 | 32362 | ||
| ... | @@ -35534,7 +35596,7 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35534,7 +35596,7 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { |
| 35534 | pub fn resolveStructAlignment( | 35596 | pub fn resolveStructAlignment( |
| 35535 | sema: *Sema, | 35597 | sema: *Sema, |
| 35536 | ty: InternPool.Index, | 35598 | ty: InternPool.Index, |
| 35537 | struct_type: InternPool.Key.StructType, | 35599 | struct_type: InternPool.LoadedStructType, |
| 35538 | ) CompileError!Alignment { | 35600 | ) CompileError!Alignment { |
| 35539 | const mod = sema.mod; | 35601 | const mod = sema.mod; |
| 35540 | const ip = &mod.intern_pool; | 35602 | const ip = &mod.intern_pool; |
| ... | @@ -35674,7 +35736,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35674,7 +35736,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 35674 | } | 35736 | } |
| 35675 | } | 35737 | } |
| 35676 | 35738 | ||
| 35677 | const RuntimeOrder = InternPool.Key.StructType.RuntimeOrder; | 35739 | const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder; |
| 35678 | 35740 | ||
| 35679 | const AlignSortContext = struct { | 35741 | const AlignSortContext = struct { |
| 35680 | aligns: []const Alignment, | 35742 | aligns: []const Alignment, |
| ... | @@ -35726,7 +35788,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35726,7 +35788,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 35726 | _ = try sema.typeRequiresComptime(ty); | 35788 | _ = try sema.typeRequiresComptime(ty); |
| 35727 | } | 35789 | } |
| 35728 | 35790 | ||
| 35729 | fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) CompileError!void { | 35791 | fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) CompileError!void { |
| 35730 | const gpa = mod.gpa; | 35792 | const gpa = mod.gpa; |
| 35731 | const ip = &mod.intern_pool; | 35793 | const ip = &mod.intern_pool; |
| 35732 | 35794 | ||
| ... | @@ -35766,7 +35828,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp | ... | @@ -35766,7 +35828,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35766 | .sema = &sema, | 35828 | .sema = &sema, |
| 35767 | .src_decl = decl_index, | 35829 | .src_decl = decl_index, |
| 35768 | .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, | 35830 | .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, |
| 35769 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 35770 | .instructions = .{}, | 35831 | .instructions = .{}, |
| 35771 | .inlining = null, | 35832 | .inlining = null, |
| 35772 | .is_comptime = true, | 35833 | .is_comptime = true, |
| ... | @@ -35789,9 +35850,16 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp | ... | @@ -35789,9 +35850,16 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35789 | 35850 | ||
| 35790 | if (small.has_backing_int) { | 35851 | if (small.has_backing_int) { |
| 35791 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; | 35852 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 35853 | const captures_len = if (small.has_captures_len) blk: { | ||
| 35854 | const captures_len = zir.extra[extra_index]; | ||
| 35855 | extra_index += 1; | ||
| 35856 | break :blk captures_len; | ||
| 35857 | } else 0; | ||
| 35792 | extra_index += @intFromBool(small.has_fields_len); | 35858 | extra_index += @intFromBool(small.has_fields_len); |
| 35793 | extra_index += @intFromBool(small.has_decls_len); | 35859 | extra_index += @intFromBool(small.has_decls_len); |
| 35794 | 35860 | ||
| 35861 | extra_index += captures_len; | ||
| 35862 | |||
| 35795 | const backing_int_body_len = zir.extra[extra_index]; | 35863 | const backing_int_body_len = zir.extra[extra_index]; |
| 35796 | extra_index += 1; | 35864 | extra_index += 1; |
| 35797 | 35865 | ||
| ... | @@ -35879,7 +35947,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void | ... | @@ -35879,7 +35947,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void |
| 35879 | pub fn resolveUnionAlignment( | 35947 | pub fn resolveUnionAlignment( |
| 35880 | sema: *Sema, | 35948 | sema: *Sema, |
| 35881 | ty: Type, | 35949 | ty: Type, |
| 35882 | union_type: InternPool.Key.UnionType, | 35950 | union_type: InternPool.LoadedUnionType, |
| 35883 | ) CompileError!Alignment { | 35951 | ) CompileError!Alignment { |
| 35884 | const mod = sema.mod; | 35952 | const mod = sema.mod; |
| 35885 | const ip = &mod.intern_pool; | 35953 | const ip = &mod.intern_pool; |
| ... | @@ -35899,13 +35967,12 @@ pub fn resolveUnionAlignment( | ... | @@ -35899,13 +35967,12 @@ pub fn resolveUnionAlignment( |
| 35899 | 35967 | ||
| 35900 | try sema.resolveTypeFieldsUnion(ty, union_type); | 35968 | try sema.resolveTypeFieldsUnion(ty, union_type); |
| 35901 | 35969 | ||
| 35902 | const union_obj = ip.loadUnionType(union_type); | ||
| 35903 | var max_align: Alignment = .@"1"; | 35970 | var max_align: Alignment = .@"1"; |
| 35904 | for (0..union_obj.field_names.len) |field_index| { | 35971 | for (0..union_type.field_types.len) |field_index| { |
| 35905 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 35972 | const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); |
| 35906 | if (!(try sema.typeHasRuntimeBits(field_ty))) continue; | 35973 | if (!(try sema.typeHasRuntimeBits(field_ty))) continue; |
| 35907 | 35974 | ||
| 35908 | const explicit_align = union_obj.fieldAlign(ip, @intCast(field_index)); | 35975 | const explicit_align = union_type.fieldAlign(ip, @intCast(field_index)); |
| 35909 | const field_align = if (explicit_align != .none) | 35976 | const field_align = if (explicit_align != .none) |
| 35910 | explicit_align | 35977 | explicit_align |
| 35911 | else | 35978 | else |
| ... | @@ -35923,16 +35990,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35923,16 +35990,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 35923 | const mod = sema.mod; | 35990 | const mod = sema.mod; |
| 35924 | const ip = &mod.intern_pool; | 35991 | const ip = &mod.intern_pool; |
| 35925 | 35992 | ||
| 35926 | const union_type = ip.indexToKey(ty.ip_index).union_type; | 35993 | try sema.resolveTypeFieldsUnion(ty, ip.loadUnionType(ty.ip_index)); |
| 35927 | try sema.resolveTypeFieldsUnion(ty, union_type); | ||
| 35928 | 35994 | ||
| 35929 | const union_obj = ip.loadUnionType(union_type); | 35995 | // Load again, since the tag type might have changed due to resolution. |
| 35930 | switch (union_obj.flagsPtr(ip).status) { | 35996 | const union_type = ip.loadUnionType(ty.ip_index); |
| 35997 | |||
| 35998 | switch (union_type.flagsPtr(ip).status) { | ||
| 35931 | .none, .have_field_types => {}, | 35999 | .none, .have_field_types => {}, |
| 35932 | .field_types_wip, .layout_wip => { | 36000 | .field_types_wip, .layout_wip => { |
| 35933 | const msg = try Module.ErrorMsg.create( | 36001 | const msg = try Module.ErrorMsg.create( |
| 35934 | sema.gpa, | 36002 | sema.gpa, |
| 35935 | mod.declPtr(union_obj.decl).srcLoc(mod), | 36003 | mod.declPtr(union_type.decl).srcLoc(mod), |
| 35936 | "union '{}' depends on itself", | 36004 | "union '{}' depends on itself", |
| 35937 | .{ty.fmt(mod)}, | 36005 | .{ty.fmt(mod)}, |
| 35938 | ); | 36006 | ); |
| ... | @@ -35941,17 +36009,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35941,17 +36009,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 35941 | .have_layout, .fully_resolved_wip, .fully_resolved => return, | 36009 | .have_layout, .fully_resolved_wip, .fully_resolved => return, |
| 35942 | } | 36010 | } |
| 35943 | 36011 | ||
| 35944 | const prev_status = union_obj.flagsPtr(ip).status; | 36012 | const prev_status = union_type.flagsPtr(ip).status; |
| 35945 | errdefer if (union_obj.flagsPtr(ip).status == .layout_wip) { | 36013 | errdefer if (union_type.flagsPtr(ip).status == .layout_wip) { |
| 35946 | union_obj.flagsPtr(ip).status = prev_status; | 36014 | union_type.flagsPtr(ip).status = prev_status; |
| 35947 | }; | 36015 | }; |
| 35948 | 36016 | ||
| 35949 | union_obj.flagsPtr(ip).status = .layout_wip; | 36017 | union_type.flagsPtr(ip).status = .layout_wip; |
| 35950 | 36018 | ||
| 35951 | var max_size: u64 = 0; | 36019 | var max_size: u64 = 0; |
| 35952 | var max_align: Alignment = .@"1"; | 36020 | var max_align: Alignment = .@"1"; |
| 35953 | for (0..union_obj.field_names.len) |field_index| { | 36021 | for (0..union_type.field_types.len) |field_index| { |
| 35954 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 36022 | const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); |
| 35955 | if (!(try sema.typeHasRuntimeBits(field_ty))) continue; | 36023 | if (!(try sema.typeHasRuntimeBits(field_ty))) continue; |
| 35956 | 36024 | ||
| 35957 | max_size = @max(max_size, sema.typeAbiSize(field_ty) catch |err| switch (err) { | 36025 | max_size = @max(max_size, sema.typeAbiSize(field_ty) catch |err| switch (err) { |
| ... | @@ -35963,7 +36031,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35963,7 +36031,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 35963 | else => return err, | 36031 | else => return err, |
| 35964 | }); | 36032 | }); |
| 35965 | 36033 | ||
| 35966 | const explicit_align = union_obj.fieldAlign(ip, @intCast(field_index)); | 36034 | const explicit_align = union_type.fieldAlign(ip, @intCast(field_index)); |
| 35967 | const field_align = if (explicit_align != .none) | 36035 | const field_align = if (explicit_align != .none) |
| 35968 | explicit_align | 36036 | explicit_align |
| 35969 | else | 36037 | else |
| ... | @@ -35972,10 +36040,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35972,10 +36040,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 35972 | max_align = max_align.max(field_align); | 36040 | max_align = max_align.max(field_align); |
| 35973 | } | 36041 | } |
| 35974 | 36042 | ||
| 35975 | const flags = union_obj.flagsPtr(ip); | 36043 | const flags = union_type.flagsPtr(ip); |
| 35976 | const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(Type.fromInterned(union_obj.enum_tag_ty)); | 36044 | const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(Type.fromInterned(union_type.enum_tag_ty)); |
| 35977 | const size, const alignment, const padding = if (has_runtime_tag) layout: { | 36045 | const size, const alignment, const padding = if (has_runtime_tag) layout: { |
| 35978 | const enum_tag_type = Type.fromInterned(union_obj.enum_tag_ty); | 36046 | const enum_tag_type = Type.fromInterned(union_type.enum_tag_ty); |
| 35979 | const tag_align = try sema.typeAbiAlignment(enum_tag_type); | 36047 | const tag_align = try sema.typeAbiAlignment(enum_tag_type); |
| 35980 | const tag_size = try sema.typeAbiSize(enum_tag_type); | 36048 | const tag_size = try sema.typeAbiSize(enum_tag_type); |
| 35981 | 36049 | ||
| ... | @@ -36009,22 +36077,22 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -36009,22 +36077,22 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 36009 | flags.alignment = alignment; | 36077 | flags.alignment = alignment; |
| 36010 | flags.status = .have_layout; | 36078 | flags.status = .have_layout; |
| 36011 | 36079 | ||
| 36012 | if (union_obj.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) { | 36080 | if (union_type.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) { |
| 36013 | const msg = try Module.ErrorMsg.create( | 36081 | const msg = try Module.ErrorMsg.create( |
| 36014 | sema.gpa, | 36082 | sema.gpa, |
| 36015 | mod.declPtr(union_obj.decl).srcLoc(mod), | 36083 | mod.declPtr(union_type.decl).srcLoc(mod), |
| 36016 | "union layout depends on it having runtime bits", | 36084 | "union layout depends on it having runtime bits", |
| 36017 | .{}, | 36085 | .{}, |
| 36018 | ); | 36086 | ); |
| 36019 | return sema.failWithOwnedErrorMsg(null, msg); | 36087 | return sema.failWithOwnedErrorMsg(null, msg); |
| 36020 | } | 36088 | } |
| 36021 | 36089 | ||
| 36022 | if (union_obj.flagsPtr(ip).assumed_pointer_aligned and | 36090 | if (union_type.flagsPtr(ip).assumed_pointer_aligned and |
| 36023 | alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8)))) | 36091 | alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8)))) |
| 36024 | { | 36092 | { |
| 36025 | const msg = try Module.ErrorMsg.create( | 36093 | const msg = try Module.ErrorMsg.create( |
| 36026 | sema.gpa, | 36094 | sema.gpa, |
| 36027 | mod.declPtr(union_obj.decl).srcLoc(mod), | 36095 | mod.declPtr(union_type.decl).srcLoc(mod), |
| 36028 | "union layout depends on being pointer aligned", | 36096 | "union layout depends on being pointer aligned", |
| 36029 | .{}, | 36097 | .{}, |
| 36030 | ); | 36098 | ); |
| ... | @@ -36212,12 +36280,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -36212,12 +36280,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void { |
| 36212 | 36280 | ||
| 36213 | else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) { | 36281 | else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) { |
| 36214 | .type_struct, | 36282 | .type_struct, |
| 36215 | .type_struct_ns, | ||
| 36216 | .type_struct_packed, | 36283 | .type_struct_packed, |
| 36217 | .type_struct_packed_inits, | 36284 | .type_struct_packed_inits, |
| 36218 | => try sema.resolveTypeFieldsStruct(ty_ip, ip.indexToKey(ty_ip).struct_type), | 36285 | => try sema.resolveTypeFieldsStruct(ty_ip, ip.loadStructType(ty_ip)), |
| 36219 | 36286 | ||
| 36220 | .type_union => try sema.resolveTypeFieldsUnion(Type.fromInterned(ty_ip), ip.indexToKey(ty_ip).union_type), | 36287 | .type_union => try sema.resolveTypeFieldsUnion(Type.fromInterned(ty_ip), ip.loadUnionType(ty_ip)), |
| 36221 | .simple_type => try sema.resolveSimpleType(ip.indexToKey(ty_ip).simple_type), | 36288 | .simple_type => try sema.resolveSimpleType(ip.indexToKey(ty_ip).simple_type), |
| 36222 | else => {}, | 36289 | else => {}, |
| 36223 | }, | 36290 | }, |
| ... | @@ -36249,7 +36316,7 @@ fn resolveSimpleType(sema: *Sema, simple_type: InternPool.SimpleType) CompileErr | ... | @@ -36249,7 +36316,7 @@ fn resolveSimpleType(sema: *Sema, simple_type: InternPool.SimpleType) CompileErr |
| 36249 | pub fn resolveTypeFieldsStruct( | 36316 | pub fn resolveTypeFieldsStruct( |
| 36250 | sema: *Sema, | 36317 | sema: *Sema, |
| 36251 | ty: InternPool.Index, | 36318 | ty: InternPool.Index, |
| 36252 | struct_type: InternPool.Key.StructType, | 36319 | struct_type: InternPool.LoadedStructType, |
| 36253 | ) CompileError!void { | 36320 | ) CompileError!void { |
| 36254 | const mod = sema.mod; | 36321 | const mod = sema.mod; |
| 36255 | const ip = &mod.intern_pool; | 36322 | const ip = &mod.intern_pool; |
| ... | @@ -36309,7 +36376,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -36309,7 +36376,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void { |
| 36309 | struct_type.setHaveFieldInits(ip); | 36376 | struct_type.setHaveFieldInits(ip); |
| 36310 | } | 36377 | } |
| 36311 | 36378 | ||
| 36312 | pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key.UnionType) CompileError!void { | 36379 | pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) CompileError!void { |
| 36313 | const mod = sema.mod; | 36380 | const mod = sema.mod; |
| 36314 | const ip = &mod.intern_pool; | 36381 | const ip = &mod.intern_pool; |
| 36315 | const owner_decl = mod.declPtr(union_type.decl); | 36382 | const owner_decl = mod.declPtr(union_type.decl); |
| ... | @@ -36500,6 +36567,12 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | ... | @@ -36500,6 +36567,12 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 36500 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 36567 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 36501 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; | 36568 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 36502 | 36569 | ||
| 36570 | const captures_len = if (small.has_captures_len) blk: { | ||
| 36571 | const captures_len = zir.extra[extra_index]; | ||
| 36572 | extra_index += 1; | ||
| 36573 | break :blk captures_len; | ||
| 36574 | } else 0; | ||
| 36575 | |||
| 36503 | const fields_len = if (small.has_fields_len) blk: { | 36576 | const fields_len = if (small.has_fields_len) blk: { |
| 36504 | const fields_len = zir.extra[extra_index]; | 36577 | const fields_len = zir.extra[extra_index]; |
| 36505 | extra_index += 1; | 36578 | extra_index += 1; |
| ... | @@ -36512,6 +36585,8 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | ... | @@ -36512,6 +36585,8 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 36512 | break :decls_len decls_len; | 36585 | break :decls_len decls_len; |
| 36513 | } else 0; | 36586 | } else 0; |
| 36514 | 36587 | ||
| 36588 | extra_index += captures_len; | ||
| 36589 | |||
| 36515 | // The backing integer cannot be handled until `resolveStructLayout()`. | 36590 | // The backing integer cannot be handled until `resolveStructLayout()`. |
| 36516 | if (small.has_backing_int) { | 36591 | if (small.has_backing_int) { |
| 36517 | const backing_int_body_len = zir.extra[extra_index]; | 36592 | const backing_int_body_len = zir.extra[extra_index]; |
| ... | @@ -36532,7 +36607,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | ... | @@ -36532,7 +36607,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 36532 | fn semaStructFields( | 36607 | fn semaStructFields( |
| 36533 | mod: *Module, | 36608 | mod: *Module, |
| 36534 | arena: Allocator, | 36609 | arena: Allocator, |
| 36535 | struct_type: InternPool.Key.StructType, | 36610 | struct_type: InternPool.LoadedStructType, |
| 36536 | ) CompileError!void { | 36611 | ) CompileError!void { |
| 36537 | const gpa = mod.gpa; | 36612 | const gpa = mod.gpa; |
| 36538 | const ip = &mod.intern_pool; | 36613 | const ip = &mod.intern_pool; |
| ... | @@ -36584,7 +36659,6 @@ fn semaStructFields( | ... | @@ -36584,7 +36659,6 @@ fn semaStructFields( |
| 36584 | .sema = &sema, | 36659 | .sema = &sema, |
| 36585 | .src_decl = decl_index, | 36660 | .src_decl = decl_index, |
| 36586 | .namespace = namespace_index, | 36661 | .namespace = namespace_index, |
| 36587 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 36588 | .instructions = .{}, | 36662 | .instructions = .{}, |
| 36589 | .inlining = null, | 36663 | .inlining = null, |
| 36590 | .is_comptime = true, | 36664 | .is_comptime = true, |
| ... | @@ -36800,7 +36874,7 @@ fn semaStructFields( | ... | @@ -36800,7 +36874,7 @@ fn semaStructFields( |
| 36800 | fn semaStructFieldInits( | 36874 | fn semaStructFieldInits( |
| 36801 | mod: *Module, | 36875 | mod: *Module, |
| 36802 | arena: Allocator, | 36876 | arena: Allocator, |
| 36803 | struct_type: InternPool.Key.StructType, | 36877 | struct_type: InternPool.LoadedStructType, |
| 36804 | ) CompileError!void { | 36878 | ) CompileError!void { |
| 36805 | const gpa = mod.gpa; | 36879 | const gpa = mod.gpa; |
| 36806 | const ip = &mod.intern_pool; | 36880 | const ip = &mod.intern_pool; |
| ... | @@ -36842,7 +36916,6 @@ fn semaStructFieldInits( | ... | @@ -36842,7 +36916,6 @@ fn semaStructFieldInits( |
| 36842 | .sema = &sema, | 36916 | .sema = &sema, |
| 36843 | .src_decl = decl_index, | 36917 | .src_decl = decl_index, |
| 36844 | .namespace = namespace_index, | 36918 | .namespace = namespace_index, |
| 36845 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 36846 | .instructions = .{}, | 36919 | .instructions = .{}, |
| 36847 | .inlining = null, | 36920 | .inlining = null, |
| 36848 | .is_comptime = true, | 36921 | .is_comptime = true, |
| ... | @@ -36952,15 +37025,15 @@ fn semaStructFieldInits( | ... | @@ -36952,15 +37025,15 @@ fn semaStructFieldInits( |
| 36952 | } | 37025 | } |
| 36953 | } | 37026 | } |
| 36954 | 37027 | ||
| 36955 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.UnionType) CompileError!void { | 37028 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void { |
| 36956 | const tracy = trace(@src()); | 37029 | const tracy = trace(@src()); |
| 36957 | defer tracy.end(); | 37030 | defer tracy.end(); |
| 36958 | 37031 | ||
| 36959 | const gpa = mod.gpa; | 37032 | const gpa = mod.gpa; |
| 36960 | const ip = &mod.intern_pool; | 37033 | const ip = &mod.intern_pool; |
| 36961 | const decl_index = union_type.decl; | 37034 | const decl_index = union_type.decl; |
| 36962 | const zir = mod.namespacePtr(union_type.namespace).file_scope.zir; | 37035 | const zir = mod.namespacePtr(union_type.namespace.unwrap().?).file_scope.zir; |
| 36963 | const zir_index = union_type.zir_index.unwrap().?.resolve(ip); | 37036 | const zir_index = union_type.zir_index.resolve(ip); |
| 36964 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | 37037 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 36965 | assert(extended.opcode == .union_decl); | 37038 | assert(extended.opcode == .union_decl); |
| 36966 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | 37039 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); |
| ... | @@ -36974,6 +37047,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -36974,6 +37047,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36974 | break :blk ty_ref; | 37047 | break :blk ty_ref; |
| 36975 | } else .none; | 37048 | } else .none; |
| 36976 | 37049 | ||
| 37050 | const captures_len = if (small.has_captures_len) blk: { | ||
| 37051 | const captures_len = zir.extra[extra_index]; | ||
| 37052 | extra_index += 1; | ||
| 37053 | break :blk captures_len; | ||
| 37054 | } else 0; | ||
| 37055 | |||
| 36977 | const body_len = if (small.has_body_len) blk: { | 37056 | const body_len = if (small.has_body_len) blk: { |
| 36978 | const body_len = zir.extra[extra_index]; | 37057 | const body_len = zir.extra[extra_index]; |
| 36979 | extra_index += 1; | 37058 | extra_index += 1; |
| ... | @@ -36992,8 +37071,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -36992,8 +37071,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36992 | break :decls_len decls_len; | 37071 | break :decls_len decls_len; |
| 36993 | } else 0; | 37072 | } else 0; |
| 36994 | 37073 | ||
| 36995 | // Skip over decls. | 37074 | // Skip over captures and decls. |
| 36996 | extra_index += decls_len; | 37075 | extra_index += captures_len + decls_len; |
| 36997 | 37076 | ||
| 36998 | const body = zir.bodySlice(extra_index, body_len); | 37077 | const body = zir.bodySlice(extra_index, body_len); |
| 36999 | extra_index += body.len; | 37078 | extra_index += body.len; |
| ... | @@ -37027,8 +37106,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -37027,8 +37106,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 37027 | .parent = null, | 37106 | .parent = null, |
| 37028 | .sema = &sema, | 37107 | .sema = &sema, |
| 37029 | .src_decl = decl_index, | 37108 | .src_decl = decl_index, |
| 37030 | .namespace = union_type.namespace, | 37109 | .namespace = union_type.namespace.unwrap().?, |
| 37031 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 37032 | .instructions = .{}, | 37110 | .instructions = .{}, |
| 37033 | .inlining = null, | 37111 | .inlining = null, |
| 37034 | .is_comptime = true, | 37112 | .is_comptime = true, |
| ... | @@ -37079,7 +37157,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -37079,7 +37157,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 37079 | // The provided type is the enum tag type. | 37157 | // The provided type is the enum tag type. |
| 37080 | union_type.tagTypePtr(ip).* = provided_ty.toIntern(); | 37158 | union_type.tagTypePtr(ip).* = provided_ty.toIntern(); |
| 37081 | const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) { | 37159 | const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) { |
| 37082 | .enum_type => |x| x, | 37160 | .enum_type => ip.loadEnumType(provided_ty.toIntern()), |
| 37083 | else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(mod)}), | 37161 | else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(mod)}), |
| 37084 | }; | 37162 | }; |
| 37085 | // The fields of the union must match the enum exactly. | 37163 | // The fields of the union must match the enum exactly. |
| ... | @@ -37216,7 +37294,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -37216,7 +37294,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 37216 | } | 37294 | } |
| 37217 | 37295 | ||
| 37218 | if (explicit_tags_seen.len > 0) { | 37296 | if (explicit_tags_seen.len > 0) { |
| 37219 | const tag_info = ip.indexToKey(union_type.tagTypePtr(ip).*).enum_type; | 37297 | const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*); |
| 37220 | const enum_index = tag_info.nameIndex(ip, field_name) orelse { | 37298 | const enum_index = tag_info.nameIndex(ip, field_name) orelse { |
| 37221 | const ty_src = mod.fieldSrcLoc(union_type.decl, .{ | 37299 | const ty_src = mod.fieldSrcLoc(union_type.decl, .{ |
| 37222 | .index = field_i, | 37300 | .index = field_i, |
| ... | @@ -37327,7 +37405,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -37327,7 +37405,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 37327 | union_type.setFieldAligns(ip, field_aligns.items); | 37405 | union_type.setFieldAligns(ip, field_aligns.items); |
| 37328 | 37406 | ||
| 37329 | if (explicit_tags_seen.len > 0) { | 37407 | if (explicit_tags_seen.len > 0) { |
| 37330 | const tag_info = ip.indexToKey(union_type.tagTypePtr(ip).*).enum_type; | 37408 | const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*); |
| 37331 | if (tag_info.names.len > fields_len) { | 37409 | if (tag_info.names.len > fields_len) { |
| 37332 | const msg = msg: { | 37410 | const msg = msg: { |
| 37333 | const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{}); | 37411 | const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{}); |
| ... | @@ -37348,7 +37426,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -37348,7 +37426,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 37348 | const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), mod.declPtr(union_type.decl)); | 37426 | const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), mod.declPtr(union_type.decl)); |
| 37349 | union_type.tagTypePtr(ip).* = enum_ty; | 37427 | union_type.tagTypePtr(ip).* = enum_ty; |
| 37350 | } else { | 37428 | } else { |
| 37351 | const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_type.decl.toOptional()); | 37429 | const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, mod.declPtr(union_type.decl)); |
| 37352 | union_type.tagTypePtr(ip).* = enum_ty; | 37430 | union_type.tagTypePtr(ip).* = enum_ty; |
| 37353 | } | 37431 | } |
| 37354 | } | 37432 | } |
| ... | @@ -37365,16 +37443,16 @@ fn generateUnionTagTypeNumbered( | ... | @@ -37365,16 +37443,16 @@ fn generateUnionTagTypeNumbered( |
| 37365 | block: *Block, | 37443 | block: *Block, |
| 37366 | enum_field_names: []const InternPool.NullTerminatedString, | 37444 | enum_field_names: []const InternPool.NullTerminatedString, |
| 37367 | enum_field_vals: []const InternPool.Index, | 37445 | enum_field_vals: []const InternPool.Index, |
| 37368 | decl: *Module.Decl, | 37446 | union_owner_decl: *Module.Decl, |
| 37369 | ) !InternPool.Index { | 37447 | ) !InternPool.Index { |
| 37370 | const mod = sema.mod; | 37448 | const mod = sema.mod; |
| 37371 | const gpa = sema.gpa; | 37449 | const gpa = sema.gpa; |
| 37372 | const ip = &mod.intern_pool; | 37450 | const ip = &mod.intern_pool; |
| 37373 | 37451 | ||
| 37374 | const src_decl = mod.declPtr(block.src_decl); | 37452 | const src_decl = mod.declPtr(block.src_decl); |
| 37375 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope); | 37453 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); |
| 37376 | errdefer mod.destroyDecl(new_decl_index); | 37454 | errdefer mod.destroyDecl(new_decl_index); |
| 37377 | const fqn = try decl.fullyQualifiedName(mod); | 37455 | const fqn = try union_owner_decl.fullyQualifiedName(mod); |
| 37378 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); | 37456 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); |
| 37379 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ | 37457 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ |
| 37380 | .ty = Type.noreturn, | 37458 | .ty = Type.noreturn, |
| ... | @@ -37386,9 +37464,9 @@ fn generateUnionTagTypeNumbered( | ... | @@ -37386,9 +37464,9 @@ fn generateUnionTagTypeNumbered( |
| 37386 | new_decl.owns_tv = true; | 37464 | new_decl.owns_tv = true; |
| 37387 | new_decl.name_fully_qualified = true; | 37465 | new_decl.name_fully_qualified = true; |
| 37388 | 37466 | ||
| 37389 | const enum_ty = try ip.getEnum(gpa, .{ | 37467 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, .{ |
| 37390 | .decl = new_decl_index, | 37468 | .decl = new_decl_index, |
| 37391 | .namespace = .none, | 37469 | .owner_union_ty = union_owner_decl.val.toIntern(), |
| 37392 | .tag_ty = if (enum_field_vals.len == 0) | 37470 | .tag_ty = if (enum_field_vals.len == 0) |
| 37393 | (try mod.intType(.unsigned, 0)).toIntern() | 37471 | (try mod.intType(.unsigned, 0)).toIntern() |
| 37394 | else | 37472 | else |
| ... | @@ -37396,7 +37474,6 @@ fn generateUnionTagTypeNumbered( | ... | @@ -37396,7 +37474,6 @@ fn generateUnionTagTypeNumbered( |
| 37396 | .names = enum_field_names, | 37474 | .names = enum_field_names, |
| 37397 | .values = enum_field_vals, | 37475 | .values = enum_field_vals, |
| 37398 | .tag_mode = .explicit, | 37476 | .tag_mode = .explicit, |
| 37399 | .zir_index = .none, | ||
| 37400 | }); | 37477 | }); |
| 37401 | 37478 | ||
| 37402 | new_decl.ty = Type.type; | 37479 | new_decl.ty = Type.type; |
| ... | @@ -37410,22 +37487,16 @@ fn generateUnionTagTypeSimple( | ... | @@ -37410,22 +37487,16 @@ fn generateUnionTagTypeSimple( |
| 37410 | sema: *Sema, | 37487 | sema: *Sema, |
| 37411 | block: *Block, | 37488 | block: *Block, |
| 37412 | enum_field_names: []const InternPool.NullTerminatedString, | 37489 | enum_field_names: []const InternPool.NullTerminatedString, |
| 37413 | maybe_decl_index: InternPool.OptionalDeclIndex, | 37490 | union_owner_decl: *Module.Decl, |
| 37414 | ) !InternPool.Index { | 37491 | ) !InternPool.Index { |
| 37415 | const mod = sema.mod; | 37492 | const mod = sema.mod; |
| 37416 | const ip = &mod.intern_pool; | 37493 | const ip = &mod.intern_pool; |
| 37417 | const gpa = sema.gpa; | 37494 | const gpa = sema.gpa; |
| 37418 | 37495 | ||
| 37419 | const new_decl_index = new_decl_index: { | 37496 | const new_decl_index = new_decl_index: { |
| 37420 | const decl_index = maybe_decl_index.unwrap() orelse { | 37497 | const fqn = try union_owner_decl.fullyQualifiedName(mod); |
| 37421 | break :new_decl_index try mod.createAnonymousDecl(block, .{ | ||
| 37422 | .ty = Type.noreturn, | ||
| 37423 | .val = Value.@"unreachable", | ||
| 37424 | }); | ||
| 37425 | }; | ||
| 37426 | const fqn = try mod.declPtr(decl_index).fullyQualifiedName(mod); | ||
| 37427 | const src_decl = mod.declPtr(block.src_decl); | 37498 | const src_decl = mod.declPtr(block.src_decl); |
| 37428 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope); | 37499 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); |
| 37429 | errdefer mod.destroyDecl(new_decl_index); | 37500 | errdefer mod.destroyDecl(new_decl_index); |
| 37430 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); | 37501 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); |
| 37431 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ | 37502 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ |
| ... | @@ -37437,9 +37508,9 @@ fn generateUnionTagTypeSimple( | ... | @@ -37437,9 +37508,9 @@ fn generateUnionTagTypeSimple( |
| 37437 | }; | 37508 | }; |
| 37438 | errdefer mod.abortAnonDecl(new_decl_index); | 37509 | errdefer mod.abortAnonDecl(new_decl_index); |
| 37439 | 37510 | ||
| 37440 | const enum_ty = try ip.getEnum(gpa, .{ | 37511 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, .{ |
| 37441 | .decl = new_decl_index, | 37512 | .decl = new_decl_index, |
| 37442 | .namespace = .none, | 37513 | .owner_union_ty = union_owner_decl.val.toIntern(), |
| 37443 | .tag_ty = if (enum_field_names.len == 0) | 37514 | .tag_ty = if (enum_field_names.len == 0) |
| 37444 | (try mod.intType(.unsigned, 0)).toIntern() | 37515 | (try mod.intType(.unsigned, 0)).toIntern() |
| 37445 | else | 37516 | else |
| ... | @@ -37447,7 +37518,6 @@ fn generateUnionTagTypeSimple( | ... | @@ -37447,7 +37518,6 @@ fn generateUnionTagTypeSimple( |
| 37447 | .names = enum_field_names, | 37518 | .names = enum_field_names, |
| 37448 | .values = &.{}, | 37519 | .values = &.{}, |
| 37449 | .tag_mode = .auto, | 37520 | .tag_mode = .auto, |
| 37450 | .zir_index = .none, | ||
| 37451 | }); | 37521 | }); |
| 37452 | 37522 | ||
| 37453 | const new_decl = mod.declPtr(new_decl_index); | 37523 | const new_decl = mod.declPtr(new_decl_index); |
| ... | @@ -37460,7 +37530,6 @@ fn generateUnionTagTypeSimple( | ... | @@ -37460,7 +37530,6 @@ fn generateUnionTagTypeSimple( |
| 37460 | } | 37530 | } |
| 37461 | 37531 | ||
| 37462 | fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { | 37532 | fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 37463 | const mod = sema.mod; | ||
| 37464 | const gpa = sema.gpa; | 37533 | const gpa = sema.gpa; |
| 37465 | const src = LazySrcLoc.nodeOffset(0); | 37534 | const src = LazySrcLoc.nodeOffset(0); |
| 37466 | 37535 | ||
| ... | @@ -37469,7 +37538,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { | ... | @@ -37469,7 +37538,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 37469 | .sema = sema, | 37538 | .sema = sema, |
| 37470 | .src_decl = sema.owner_decl_index, | 37539 | .src_decl = sema.owner_decl_index, |
| 37471 | .namespace = sema.owner_decl.src_namespace, | 37540 | .namespace = sema.owner_decl.src_namespace, |
| 37472 | .wip_capture_scope = try mod.createCaptureScope(sema.owner_decl.src_scope), | ||
| 37473 | .instructions = .{}, | 37541 | .instructions = .{}, |
| 37474 | .inlining = null, | 37542 | .inlining = null, |
| 37475 | .is_comptime = true, | 37543 | .is_comptime = true, |
| ... | @@ -37510,7 +37578,6 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int | ... | @@ -37510,7 +37578,6 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int |
| 37510 | } | 37578 | } |
| 37511 | 37579 | ||
| 37512 | fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { | 37580 | fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 37513 | const mod = sema.mod; | ||
| 37514 | const ty_inst = try sema.getBuiltin(name); | 37581 | const ty_inst = try sema.getBuiltin(name); |
| 37515 | 37582 | ||
| 37516 | var block: Block = .{ | 37583 | var block: Block = .{ |
| ... | @@ -37518,7 +37585,6 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { | ... | @@ -37518,7 +37585,6 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 37518 | .sema = sema, | 37585 | .sema = sema, |
| 37519 | .src_decl = sema.owner_decl_index, | 37586 | .src_decl = sema.owner_decl_index, |
| 37520 | .namespace = sema.owner_decl.src_namespace, | 37587 | .namespace = sema.owner_decl.src_namespace, |
| 37521 | .wip_capture_scope = try mod.createCaptureScope(sema.owner_decl.src_scope), | ||
| 37522 | .instructions = .{}, | 37588 | .instructions = .{}, |
| 37523 | .inlining = null, | 37589 | .inlining = null, |
| 37524 | .is_comptime = true, | 37590 | .is_comptime = true, |
| ... | @@ -37636,6 +37702,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -37636,6 +37702,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37636 | => unreachable, | 37702 | => unreachable, |
| 37637 | 37703 | ||
| 37638 | _ => switch (ip.items.items(.tag)[@intFromEnum(ty.toIntern())]) { | 37704 | _ => switch (ip.items.items(.tag)[@intFromEnum(ty.toIntern())]) { |
| 37705 | .removed => unreachable, | ||
| 37706 | |||
| 37639 | .type_int_signed, // i0 handled above | 37707 | .type_int_signed, // i0 handled above |
| 37640 | .type_int_unsigned, // u0 handled above | 37708 | .type_int_unsigned, // u0 handled above |
| 37641 | .type_pointer, | 37709 | .type_pointer, |
| ... | @@ -37713,7 +37781,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -37713,7 +37781,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37713 | .type_enum_explicit, | 37781 | .type_enum_explicit, |
| 37714 | .type_enum_nonexhaustive, | 37782 | .type_enum_nonexhaustive, |
| 37715 | .type_struct, | 37783 | .type_struct, |
| 37716 | .type_struct_ns, | ||
| 37717 | .type_struct_anon, | 37784 | .type_struct_anon, |
| 37718 | .type_struct_packed, | 37785 | .type_struct_packed, |
| 37719 | .type_struct_packed_inits, | 37786 | .type_struct_packed_inits, |
| ... | @@ -37736,8 +37803,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -37736,8 +37803,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37736 | return null; | 37803 | return null; |
| 37737 | }, | 37804 | }, |
| 37738 | 37805 | ||
| 37739 | .struct_type => |struct_type| { | 37806 | .struct_type => { |
| 37740 | try sema.resolveTypeFields(ty); | 37807 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 37808 | try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type); | ||
| 37741 | 37809 | ||
| 37742 | if (struct_type.field_types.len == 0) { | 37810 | if (struct_type.field_types.len == 0) { |
| 37743 | // In this case the struct has no fields at all and | 37811 | // In this case the struct has no fields at all and |
| ... | @@ -37795,10 +37863,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -37795,10 +37863,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37795 | } }))); | 37863 | } }))); |
| 37796 | }, | 37864 | }, |
| 37797 | 37865 | ||
| 37798 | .union_type => |union_type| { | 37866 | .union_type => { |
| 37799 | try sema.resolveTypeFields(ty); | 37867 | const union_obj = ip.loadUnionType(ty.toIntern()); |
| 37800 | const union_obj = ip.loadUnionType(union_type); | 37868 | try sema.resolveTypeFieldsUnion(ty, union_obj); |
| 37801 | const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.enum_tag_ty))) orelse | 37869 | const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypePtr(ip).*))) orelse |
| 37802 | return null; | 37870 | return null; |
| 37803 | if (union_obj.field_types.len == 0) { | 37871 | if (union_obj.field_types.len == 0) { |
| 37804 | const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); | 37872 | const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); |
| ... | @@ -37825,39 +37893,42 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -37825,39 +37893,42 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37825 | return Value.fromInterned(only); | 37893 | return Value.fromInterned(only); |
| 37826 | }, | 37894 | }, |
| 37827 | 37895 | ||
| 37828 | .enum_type => |enum_type| switch (enum_type.tag_mode) { | 37896 | .enum_type => { |
| 37829 | .nonexhaustive => { | 37897 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 37830 | if (enum_type.tag_ty == .comptime_int_type) return null; | 37898 | switch (enum_type.tag_mode) { |
| 37899 | .nonexhaustive => { | ||
| 37900 | if (enum_type.tag_ty == .comptime_int_type) return null; | ||
| 37831 | 37901 | ||
| 37832 | if (try sema.typeHasOnePossibleValue(Type.fromInterned(enum_type.tag_ty))) |int_opv| { | 37902 | if (try sema.typeHasOnePossibleValue(Type.fromInterned(enum_type.tag_ty))) |int_opv| { |
| 37833 | const only = try mod.intern(.{ .enum_tag = .{ | 37903 | const only = try mod.intern(.{ .enum_tag = .{ |
| 37834 | .ty = ty.toIntern(), | 37904 | .ty = ty.toIntern(), |
| 37835 | .int = int_opv.toIntern(), | 37905 | .int = int_opv.toIntern(), |
| 37836 | } }); | 37906 | } }); |
| 37837 | return Value.fromInterned(only); | 37907 | return Value.fromInterned(only); |
| 37838 | } | 37908 | } |
| 37839 | 37909 | ||
| 37840 | return null; | 37910 | return null; |
| 37841 | }, | 37911 | }, |
| 37842 | .auto, .explicit => { | 37912 | .auto, .explicit => { |
| 37843 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null; | 37913 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null; |
| 37844 | 37914 | ||
| 37845 | return Value.fromInterned(switch (enum_type.names.len) { | 37915 | return Value.fromInterned(switch (enum_type.names.len) { |
| 37846 | 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }), | 37916 | 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }), |
| 37847 | 1 => try mod.intern(.{ .enum_tag = .{ | 37917 | 1 => try mod.intern(.{ .enum_tag = .{ |
| 37848 | .ty = ty.toIntern(), | 37918 | .ty = ty.toIntern(), |
| 37849 | .int = if (enum_type.values.len == 0) | 37919 | .int = if (enum_type.values.len == 0) |
| 37850 | (try mod.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern() | 37920 | (try mod.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern() |
| 37851 | else | 37921 | else |
| 37852 | try mod.intern_pool.getCoercedInts( | 37922 | try mod.intern_pool.getCoercedInts( |
| 37853 | mod.gpa, | 37923 | mod.gpa, |
| 37854 | mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int, | 37924 | mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int, |
| 37855 | enum_type.tag_ty, | 37925 | enum_type.tag_ty, |
| 37856 | ), | 37926 | ), |
| 37857 | } }), | 37927 | } }), |
| 37858 | else => return null, | 37928 | else => return null, |
| 37859 | }); | 37929 | }); |
| 37860 | }, | 37930 | }, |
| 37931 | } | ||
| 37861 | }, | 37932 | }, |
| 37862 | 37933 | ||
| 37863 | else => unreachable, | 37934 | else => unreachable, |
| ... | @@ -38189,7 +38260,7 @@ fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!Alignment { | ... | @@ -38189,7 +38260,7 @@ fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!Alignment { |
| 38189 | 38260 | ||
| 38190 | /// Not valid to call for packed unions. | 38261 | /// Not valid to call for packed unions. |
| 38191 | /// Keep implementation in sync with `Module.unionFieldNormalAlignment`. | 38262 | /// Keep implementation in sync with `Module.unionFieldNormalAlignment`. |
| 38192 | fn unionFieldAlignment(sema: *Sema, u: InternPool.UnionType, field_index: u32) !Alignment { | 38263 | fn unionFieldAlignment(sema: *Sema, u: InternPool.LoadedUnionType, field_index: u32) !Alignment { |
| 38193 | const mod = sema.mod; | 38264 | const mod = sema.mod; |
| 38194 | const ip = &mod.intern_pool; | 38265 | const ip = &mod.intern_pool; |
| 38195 | const field_align = u.fieldAlign(ip, field_index); | 38266 | const field_align = u.fieldAlign(ip, field_index); |
| ... | @@ -38237,7 +38308,7 @@ fn unionFieldIndex( | ... | @@ -38237,7 +38308,7 @@ fn unionFieldIndex( |
| 38237 | const ip = &mod.intern_pool; | 38308 | const ip = &mod.intern_pool; |
| 38238 | try sema.resolveTypeFields(union_ty); | 38309 | try sema.resolveTypeFields(union_ty); |
| 38239 | const union_obj = mod.typeToUnion(union_ty).?; | 38310 | const union_obj = mod.typeToUnion(union_ty).?; |
| 38240 | const field_index = union_obj.nameIndex(ip, field_name) orelse | 38311 | const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse |
| 38241 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); | 38312 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 38242 | return @intCast(field_index); | 38313 | return @intCast(field_index); |
| 38243 | } | 38314 | } |
| ... | @@ -38274,7 +38345,7 @@ fn anonStructFieldIndex( | ... | @@ -38274,7 +38345,7 @@ fn anonStructFieldIndex( |
| 38274 | .anon_struct_type => |anon_struct_type| for (anon_struct_type.names.get(ip), 0..) |name, i| { | 38345 | .anon_struct_type => |anon_struct_type| for (anon_struct_type.names.get(ip), 0..) |name, i| { |
| 38275 | if (name == field_name) return @intCast(i); | 38346 | if (name == field_name) return @intCast(i); |
| 38276 | }, | 38347 | }, |
| 38277 | .struct_type => |struct_type| if (struct_type.nameIndex(ip, field_name)) |i| return i, | 38348 | .struct_type => if (ip.loadStructType(struct_ty.toIntern()).nameIndex(ip, field_name)) |i| return i, |
| 38278 | else => unreachable, | 38349 | else => unreachable, |
| 38279 | } | 38350 | } |
| 38280 | return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{ | 38351 | return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{ |
| ... | @@ -38710,7 +38781,7 @@ fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool { | ... | @@ -38710,7 +38781,7 @@ fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool { |
| 38710 | /// Asserts the type is an enum. | 38781 | /// Asserts the type is an enum. |
| 38711 | fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { | 38782 | fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { |
| 38712 | const mod = sema.mod; | 38783 | const mod = sema.mod; |
| 38713 | const enum_type = mod.intern_pool.indexToKey(ty.toIntern()).enum_type; | 38784 | const enum_type = mod.intern_pool.loadEnumType(ty.toIntern()); |
| 38714 | assert(enum_type.tag_mode != .nonexhaustive); | 38785 | assert(enum_type.tag_mode != .nonexhaustive); |
| 38715 | // The `tagValueIndex` function call below relies on the type being the integer tag type. | 38786 | // The `tagValueIndex` function call below relies on the type being the integer tag type. |
| 38716 | // `getCoerced` assumes the value will fit the new type. | 38787 | // `getCoerced` assumes the value will fit the new type. |
src/TypedValue.zig+4-8| ... | @@ -89,7 +89,7 @@ pub fn print( | ... | @@ -89,7 +89,7 @@ pub fn print( |
| 89 | 89 | ||
| 90 | if (payload.tag) |tag| { | 90 | if (payload.tag) |tag| { |
| 91 | try print(.{ | 91 | try print(.{ |
| 92 | .ty = Type.fromInterned(ip.indexToKey(ty.toIntern()).union_type.enum_tag_ty), | 92 | .ty = Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty), |
| 93 | .val = tag, | 93 | .val = tag, |
| 94 | }, writer, level - 1, mod); | 94 | }, writer, level - 1, mod); |
| 95 | try writer.writeAll(" = "); | 95 | try writer.writeAll(" = "); |
| ... | @@ -247,7 +247,7 @@ pub fn print( | ... | @@ -247,7 +247,7 @@ pub fn print( |
| 247 | if (level == 0) { | 247 | if (level == 0) { |
| 248 | return writer.writeAll("(enum)"); | 248 | return writer.writeAll("(enum)"); |
| 249 | } | 249 | } |
| 250 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 250 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 251 | if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { | 251 | if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { |
| 252 | try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); | 252 | try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); |
| 253 | return; | 253 | return; |
| ... | @@ -398,7 +398,7 @@ pub fn print( | ... | @@ -398,7 +398,7 @@ pub fn print( |
| 398 | } | 398 | } |
| 399 | }, | 399 | }, |
| 400 | .Union => { | 400 | .Union => { |
| 401 | const field_name = mod.typeToUnion(container_ty).?.field_names.get(ip)[@intCast(field.index)]; | 401 | const field_name = mod.typeToUnion(container_ty).?.loadTagType(ip).names.get(ip)[@intCast(field.index)]; |
| 402 | try writer.print(".{i}", .{field_name.fmt(ip)}); | 402 | try writer.print(".{i}", .{field_name.fmt(ip)}); |
| 403 | }, | 403 | }, |
| 404 | .Pointer => { | 404 | .Pointer => { |
| ... | @@ -482,11 +482,7 @@ fn printAggregate( | ... | @@ -482,11 +482,7 @@ fn printAggregate( |
| 482 | for (0..max_len) |i| { | 482 | for (0..max_len) |i| { |
| 483 | if (i != 0) try writer.writeAll(", "); | 483 | if (i != 0) try writer.writeAll(", "); |
| 484 | 484 | ||
| 485 | const field_name = switch (ip.indexToKey(ty.toIntern())) { | 485 | const field_name = ty.structFieldName(@intCast(i), mod); |
| 486 | .struct_type => |x| x.fieldName(ip, i), | ||
| 487 | .anon_struct_type => |x| if (x.isTuple()) .none else x.names.get(ip)[i].toOptional(), | ||
| 488 | else => unreachable, | ||
| 489 | }; | ||
| 490 | 486 | ||
| 491 | if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(ip)}); | 487 | if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(ip)}); |
| 492 | try print(.{ | 488 | try print(.{ |
src/Value.zig+16-10| ... | @@ -424,22 +424,28 @@ pub fn toType(self: Value) Type { | ... | @@ -424,22 +424,28 @@ pub fn toType(self: Value) Type { |
| 424 | 424 | ||
| 425 | pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value { | 425 | pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value { |
| 426 | const ip = &mod.intern_pool; | 426 | const ip = &mod.intern_pool; |
| 427 | return switch (ip.indexToKey(ip.typeOf(val.toIntern()))) { | 427 | const enum_ty = ip.typeOf(val.toIntern()); |
| 428 | return switch (ip.indexToKey(enum_ty)) { | ||
| 428 | // Assume it is already an integer and return it directly. | 429 | // Assume it is already an integer and return it directly. |
| 429 | .simple_type, .int_type => val, | 430 | .simple_type, .int_type => val, |
| 430 | .enum_literal => |enum_literal| { | 431 | .enum_literal => |enum_literal| { |
| 431 | const field_index = ty.enumFieldIndex(enum_literal, mod).?; | 432 | const field_index = ty.enumFieldIndex(enum_literal, mod).?; |
| 432 | return switch (ip.indexToKey(ty.toIntern())) { | 433 | switch (ip.indexToKey(ty.toIntern())) { |
| 433 | // Assume it is already an integer and return it directly. | 434 | // Assume it is already an integer and return it directly. |
| 434 | .simple_type, .int_type => val, | 435 | .simple_type, .int_type => return val, |
| 435 | .enum_type => |enum_type| if (enum_type.values.len != 0) | 436 | .enum_type => { |
| 436 | Value.fromInterned(enum_type.values.get(ip)[field_index]) | 437 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 437 | else // Field index and integer values are the same. | 438 | if (enum_type.values.len != 0) { |
| 438 | mod.intValue(Type.fromInterned(enum_type.tag_ty), field_index), | 439 | return Value.fromInterned(enum_type.values.get(ip)[field_index]); |
| 440 | } else { | ||
| 441 | // Field index and integer values are the same. | ||
| 442 | return mod.intValue(Type.fromInterned(enum_type.tag_ty), field_index); | ||
| 443 | } | ||
| 444 | }, | ||
| 439 | else => unreachable, | 445 | else => unreachable, |
| 440 | }; | 446 | } |
| 441 | }, | 447 | }, |
| 442 | .enum_type => |enum_type| try mod.getCoerced(val, Type.fromInterned(enum_type.tag_ty)), | 448 | .enum_type => try mod.getCoerced(val, Type.fromInterned(ip.loadEnumType(enum_ty).tag_ty)), |
| 443 | else => unreachable, | 449 | else => unreachable, |
| 444 | }; | 450 | }; |
| 445 | } | 451 | } |
| ... | @@ -832,7 +838,7 @@ pub fn writeToPackedMemory( | ... | @@ -832,7 +838,7 @@ pub fn writeToPackedMemory( |
| 832 | } | 838 | } |
| 833 | }, | 839 | }, |
| 834 | .Struct => { | 840 | .Struct => { |
| 835 | const struct_type = ip.indexToKey(ty.toIntern()).struct_type; | 841 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 836 | // Sema is supposed to have emitted a compile error already in the case of Auto, | 842 | // Sema is supposed to have emitted a compile error already in the case of Auto, |
| 837 | // and Extern is handled in non-packed writeToMemory. | 843 | // and Extern is handled in non-packed writeToMemory. |
| 838 | assert(struct_type.layout == .Packed); | 844 | assert(struct_type.layout == .Packed); |
src/arch/wasm/CodeGen.zig+3-2| ... | @@ -3354,7 +3354,8 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { | ... | @@ -3354,7 +3354,8 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3354 | val.writeToMemory(ty, mod, &buf) catch unreachable; | 3354 | val.writeToMemory(ty, mod, &buf) catch unreachable; |
| 3355 | return func.storeSimdImmd(buf); | 3355 | return func.storeSimdImmd(buf); |
| 3356 | }, | 3356 | }, |
| 3357 | .struct_type => |struct_type| { | 3357 | .struct_type => { |
| 3358 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 3358 | // non-packed structs are not handled in this function because they | 3359 | // non-packed structs are not handled in this function because they |
| 3359 | // are by-ref types. | 3360 | // are by-ref types. |
| 3360 | assert(struct_type.layout == .Packed); | 3361 | assert(struct_type.layout == .Packed); |
| ... | @@ -5411,7 +5412,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5411,7 +5412,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5411 | const layout = union_ty.unionGetLayout(mod); | 5412 | const layout = union_ty.unionGetLayout(mod); |
| 5412 | const union_obj = mod.typeToUnion(union_ty).?; | 5413 | const union_obj = mod.typeToUnion(union_ty).?; |
| 5413 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); | 5414 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); |
| 5414 | const field_name = union_obj.field_names.get(ip)[extra.field_index]; | 5415 | const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 5415 | 5416 | ||
| 5416 | const tag_int = blk: { | 5417 | const tag_int = blk: { |
| 5417 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); | 5418 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); |
src/arch/wasm/abi.zig+1-1| ... | @@ -76,7 +76,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { | ... | @@ -76,7 +76,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { |
| 76 | } | 76 | } |
| 77 | const layout = ty.unionGetLayout(mod); | 77 | const layout = ty.unionGetLayout(mod); |
| 78 | assert(layout.tag_size == 0); | 78 | assert(layout.tag_size == 0); |
| 79 | if (union_obj.field_names.len > 1) return memory; | 79 | if (union_obj.field_types.len > 1) return memory; |
| 80 | const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]); | 80 | const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]); |
| 81 | return classifyType(first_field_ty, mod); | 81 | return classifyType(first_field_ty, mod); |
| 82 | }, | 82 | }, |
src/arch/x86_64/CodeGen.zig+1-1| ... | @@ -18183,7 +18183,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -18183,7 +18183,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 18183 | const dst_mcv = try self.allocRegOrMem(inst, false); | 18183 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 18184 | 18184 | ||
| 18185 | const union_obj = mod.typeToUnion(union_ty).?; | 18185 | const union_obj = mod.typeToUnion(union_ty).?; |
| 18186 | const field_name = union_obj.field_names.get(ip)[extra.field_index]; | 18186 | const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 18187 | const tag_ty = Type.fromInterned(union_obj.enum_tag_ty); | 18187 | const tag_ty = Type.fromInterned(union_obj.enum_tag_ty); |
| 18188 | const field_index = tag_ty.enumFieldIndex(field_name, mod).?; | 18188 | const field_index = tag_ty.enumFieldIndex(field_name, mod).?; |
| 18189 | const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); | 18189 | const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); |
src/codegen.zig+73-70| ... | @@ -510,88 +510,91 @@ pub fn generateSymbol( | ... | @@ -510,88 +510,91 @@ pub fn generateSymbol( |
| 510 | } | 510 | } |
| 511 | } | 511 | } |
| 512 | }, | 512 | }, |
| 513 | .struct_type => |struct_type| switch (struct_type.layout) { | 513 | .struct_type => { |
| 514 | .Packed => { | 514 | const struct_type = ip.loadStructType(typed_value.ty.toIntern()); |
| 515 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse | 515 | switch (struct_type.layout) { |
| 516 | return error.Overflow; | 516 | .Packed => { |
| 517 | const current_pos = code.items.len; | 517 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse |
| 518 | try code.resize(current_pos + abi_size); | 518 | return error.Overflow; |
| 519 | var bits: u16 = 0; | 519 | const current_pos = code.items.len; |
| 520 | 520 | try code.resize(current_pos + abi_size); | |
| 521 | for (struct_type.field_types.get(ip), 0..) |field_ty, index| { | 521 | var bits: u16 = 0; |
| 522 | const field_val = switch (aggregate.storage) { | 522 | |
| 523 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | 523 | for (struct_type.field_types.get(ip), 0..) |field_ty, index| { |
| 524 | .ty = field_ty, | 524 | const field_val = switch (aggregate.storage) { |
| 525 | .storage = .{ .u64 = bytes[index] }, | 525 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ |
| 526 | } }), | 526 | .ty = field_ty, |
| 527 | .elems => |elems| elems[index], | 527 | .storage = .{ .u64 = bytes[index] }, |
| 528 | .repeated_elem => |elem| elem, | 528 | } }), |
| 529 | }; | 529 | .elems => |elems| elems[index], |
| 530 | .repeated_elem => |elem| elem, | ||
| 531 | }; | ||
| 532 | |||
| 533 | // pointer may point to a decl which must be marked used | ||
| 534 | // but can also result in a relocation. Therefore we handle those separately. | ||
| 535 | if (Type.fromInterned(field_ty).zigTypeTag(mod) == .Pointer) { | ||
| 536 | const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(mod)) orelse | ||
| 537 | return error.Overflow; | ||
| 538 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); | ||
| 539 | defer tmp_list.deinit(); | ||
| 540 | switch (try generateSymbol(bin_file, src_loc, .{ | ||
| 541 | .ty = Type.fromInterned(field_ty), | ||
| 542 | .val = Value.fromInterned(field_val), | ||
| 543 | }, &tmp_list, debug_output, reloc_info)) { | ||
| 544 | .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items), | ||
| 545 | .fail => |em| return Result{ .fail = em }, | ||
| 546 | } | ||
| 547 | } else { | ||
| 548 | Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable; | ||
| 549 | } | ||
| 550 | bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod))); | ||
| 551 | } | ||
| 552 | }, | ||
| 553 | .Auto, .Extern => { | ||
| 554 | const struct_begin = code.items.len; | ||
| 555 | const field_types = struct_type.field_types.get(ip); | ||
| 556 | const offsets = struct_type.offsets.get(ip); | ||
| 557 | |||
| 558 | var it = struct_type.iterateRuntimeOrder(ip); | ||
| 559 | while (it.next()) |field_index| { | ||
| 560 | const field_ty = field_types[field_index]; | ||
| 561 | if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; | ||
| 562 | |||
| 563 | const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) { | ||
| 564 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | ||
| 565 | .ty = field_ty, | ||
| 566 | .storage = .{ .u64 = bytes[field_index] }, | ||
| 567 | } }), | ||
| 568 | .elems => |elems| elems[field_index], | ||
| 569 | .repeated_elem => |elem| elem, | ||
| 570 | }; | ||
| 571 | |||
| 572 | const padding = math.cast( | ||
| 573 | usize, | ||
| 574 | offsets[field_index] - (code.items.len - struct_begin), | ||
| 575 | ) orelse return error.Overflow; | ||
| 576 | if (padding > 0) try code.appendNTimes(0, padding); | ||
| 530 | 577 | ||
| 531 | // pointer may point to a decl which must be marked used | ||
| 532 | // but can also result in a relocation. Therefore we handle those separately. | ||
| 533 | if (Type.fromInterned(field_ty).zigTypeTag(mod) == .Pointer) { | ||
| 534 | const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(mod)) orelse | ||
| 535 | return error.Overflow; | ||
| 536 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); | ||
| 537 | defer tmp_list.deinit(); | ||
| 538 | switch (try generateSymbol(bin_file, src_loc, .{ | 578 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 539 | .ty = Type.fromInterned(field_ty), | 579 | .ty = Type.fromInterned(field_ty), |
| 540 | .val = Value.fromInterned(field_val), | 580 | .val = Value.fromInterned(field_val), |
| 541 | }, &tmp_list, debug_output, reloc_info)) { | 581 | }, code, debug_output, reloc_info)) { |
| 542 | .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items), | 582 | .ok => {}, |
| 543 | .fail => |em| return Result{ .fail = em }, | 583 | .fail => |em| return Result{ .fail = em }, |
| 544 | } | 584 | } |
| 545 | } else { | ||
| 546 | Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable; | ||
| 547 | } | 585 | } |
| 548 | bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod))); | 586 | |
| 549 | } | 587 | const size = struct_type.size(ip).*; |
| 550 | }, | 588 | const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?; |
| 551 | .Auto, .Extern => { | ||
| 552 | const struct_begin = code.items.len; | ||
| 553 | const field_types = struct_type.field_types.get(ip); | ||
| 554 | const offsets = struct_type.offsets.get(ip); | ||
| 555 | |||
| 556 | var it = struct_type.iterateRuntimeOrder(ip); | ||
| 557 | while (it.next()) |field_index| { | ||
| 558 | const field_ty = field_types[field_index]; | ||
| 559 | if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; | ||
| 560 | |||
| 561 | const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) { | ||
| 562 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | ||
| 563 | .ty = field_ty, | ||
| 564 | .storage = .{ .u64 = bytes[field_index] }, | ||
| 565 | } }), | ||
| 566 | .elems => |elems| elems[field_index], | ||
| 567 | .repeated_elem => |elem| elem, | ||
| 568 | }; | ||
| 569 | 589 | ||
| 570 | const padding = math.cast( | 590 | const padding = math.cast( |
| 571 | usize, | 591 | usize, |
| 572 | offsets[field_index] - (code.items.len - struct_begin), | 592 | std.mem.alignForward(u64, size, @max(alignment, 1)) - |
| 593 | (code.items.len - struct_begin), | ||
| 573 | ) orelse return error.Overflow; | 594 | ) orelse return error.Overflow; |
| 574 | if (padding > 0) try code.appendNTimes(0, padding); | 595 | if (padding > 0) try code.appendNTimes(0, padding); |
| 575 | 596 | }, | |
| 576 | switch (try generateSymbol(bin_file, src_loc, .{ | 597 | } |
| 577 | .ty = Type.fromInterned(field_ty), | ||
| 578 | .val = Value.fromInterned(field_val), | ||
| 579 | }, code, debug_output, reloc_info)) { | ||
| 580 | .ok => {}, | ||
| 581 | .fail => |em| return Result{ .fail = em }, | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | const size = struct_type.size(ip).*; | ||
| 586 | const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?; | ||
| 587 | |||
| 588 | const padding = math.cast( | ||
| 589 | usize, | ||
| 590 | std.mem.alignForward(u64, size, @max(alignment, 1)) - | ||
| 591 | (code.items.len - struct_begin), | ||
| 592 | ) orelse return error.Overflow; | ||
| 593 | if (padding > 0) try code.appendNTimes(0, padding); | ||
| 594 | }, | ||
| 595 | }, | 598 | }, |
| 596 | else => unreachable, | 599 | else => unreachable, |
| 597 | }, | 600 | }, |
src/codegen/c.zig+113-110| ... | @@ -1376,70 +1376,24 @@ pub const DeclGen = struct { | ... | @@ -1376,70 +1376,24 @@ pub const DeclGen = struct { |
| 1376 | } | 1376 | } |
| 1377 | try writer.writeByte('}'); | 1377 | try writer.writeByte('}'); |
| 1378 | }, | 1378 | }, |
| 1379 | .struct_type => |struct_type| switch (struct_type.layout) { | 1379 | .struct_type => { |
| 1380 | .Auto, .Extern => { | 1380 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 1381 | if (!location.isInitializer()) { | 1381 | switch (struct_type.layout) { |
| 1382 | try writer.writeByte('('); | 1382 | .Auto, .Extern => { |
| 1383 | try dg.renderType(writer, ty); | 1383 | if (!location.isInitializer()) { |
| 1384 | try writer.writeByte(')'); | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | try writer.writeByte('{'); | ||
| 1388 | var empty = true; | ||
| 1389 | for (0..struct_type.field_types.len) |field_index| { | ||
| 1390 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | ||
| 1391 | if (struct_type.fieldIsComptime(ip, field_index)) continue; | ||
| 1392 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1393 | |||
| 1394 | if (!empty) try writer.writeByte(','); | ||
| 1395 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { | ||
| 1396 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | ||
| 1397 | .ty = field_ty.toIntern(), | ||
| 1398 | .storage = .{ .u64 = bytes[field_index] }, | ||
| 1399 | } }), | ||
| 1400 | .elems => |elems| elems[field_index], | ||
| 1401 | .repeated_elem => |elem| elem, | ||
| 1402 | }; | ||
| 1403 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type); | ||
| 1404 | |||
| 1405 | empty = false; | ||
| 1406 | } | ||
| 1407 | try writer.writeByte('}'); | ||
| 1408 | }, | ||
| 1409 | .Packed => { | ||
| 1410 | const int_info = ty.intInfo(mod); | ||
| 1411 | |||
| 1412 | const bits = Type.smallestUnsignedBits(int_info.bits - 1); | ||
| 1413 | const bit_offset_ty = try mod.intType(.unsigned, bits); | ||
| 1414 | |||
| 1415 | var bit_offset: u64 = 0; | ||
| 1416 | var eff_num_fields: usize = 0; | ||
| 1417 | |||
| 1418 | for (0..struct_type.field_types.len) |field_index| { | ||
| 1419 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | ||
| 1420 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1421 | eff_num_fields += 1; | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | if (eff_num_fields == 0) { | ||
| 1425 | try writer.writeByte('('); | ||
| 1426 | try dg.renderValue(writer, ty, Value.undef, initializer_type); | ||
| 1427 | try writer.writeByte(')'); | ||
| 1428 | } else if (ty.bitSize(mod) > 64) { | ||
| 1429 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) | ||
| 1430 | var num_or = eff_num_fields - 1; | ||
| 1431 | while (num_or > 0) : (num_or -= 1) { | ||
| 1432 | try writer.writeAll("zig_or_"); | ||
| 1433 | try dg.renderTypeForBuiltinFnName(writer, ty); | ||
| 1434 | try writer.writeByte('('); | 1384 | try writer.writeByte('('); |
| 1385 | try dg.renderType(writer, ty); | ||
| 1386 | try writer.writeByte(')'); | ||
| 1435 | } | 1387 | } |
| 1436 | 1388 | ||
| 1437 | var eff_index: usize = 0; | 1389 | try writer.writeByte('{'); |
| 1438 | var needs_closing_paren = false; | 1390 | var empty = true; |
| 1439 | for (0..struct_type.field_types.len) |field_index| { | 1391 | for (0..struct_type.field_types.len) |field_index| { |
| 1440 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1392 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 1393 | if (struct_type.fieldIsComptime(ip, field_index)) continue; | ||
| 1441 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1394 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1442 | 1395 | ||
| 1396 | if (!empty) try writer.writeByte(','); | ||
| 1443 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { | 1397 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { |
| 1444 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | 1398 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ |
| 1445 | .ty = field_ty.toIntern(), | 1399 | .ty = field_ty.toIntern(), |
| ... | @@ -1448,64 +1402,113 @@ pub const DeclGen = struct { | ... | @@ -1448,64 +1402,113 @@ pub const DeclGen = struct { |
| 1448 | .elems => |elems| elems[field_index], | 1402 | .elems => |elems| elems[field_index], |
| 1449 | .repeated_elem => |elem| elem, | 1403 | .repeated_elem => |elem| elem, |
| 1450 | }; | 1404 | }; |
| 1451 | const cast_context = IntCastContext{ .value = .{ .value = Value.fromInterned(field_val) } }; | 1405 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type); |
| 1452 | if (bit_offset != 0) { | ||
| 1453 | try writer.writeAll("zig_shl_"); | ||
| 1454 | try dg.renderTypeForBuiltinFnName(writer, ty); | ||
| 1455 | try writer.writeByte('('); | ||
| 1456 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | ||
| 1457 | try writer.writeAll(", "); | ||
| 1458 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | ||
| 1459 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 1460 | try writer.writeByte(')'); | ||
| 1461 | } else { | ||
| 1462 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | ||
| 1463 | } | ||
| 1464 | |||
| 1465 | if (needs_closing_paren) try writer.writeByte(')'); | ||
| 1466 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); | ||
| 1467 | 1406 | ||
| 1468 | bit_offset += field_ty.bitSize(mod); | 1407 | empty = false; |
| 1469 | needs_closing_paren = true; | ||
| 1470 | eff_index += 1; | ||
| 1471 | } | 1408 | } |
| 1472 | } else { | 1409 | try writer.writeByte('}'); |
| 1473 | try writer.writeByte('('); | 1410 | }, |
| 1474 | // a << a_off | b << b_off | c << c_off | 1411 | .Packed => { |
| 1475 | var empty = true; | 1412 | const int_info = ty.intInfo(mod); |
| 1413 | |||
| 1414 | const bits = Type.smallestUnsignedBits(int_info.bits - 1); | ||
| 1415 | const bit_offset_ty = try mod.intType(.unsigned, bits); | ||
| 1416 | |||
| 1417 | var bit_offset: u64 = 0; | ||
| 1418 | var eff_num_fields: usize = 0; | ||
| 1419 | |||
| 1476 | for (0..struct_type.field_types.len) |field_index| { | 1420 | for (0..struct_type.field_types.len) |field_index| { |
| 1477 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1421 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 1478 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1422 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1423 | eff_num_fields += 1; | ||
| 1424 | } | ||
| 1479 | 1425 | ||
| 1480 | if (!empty) try writer.writeAll(" | "); | 1426 | if (eff_num_fields == 0) { |
| 1481 | try writer.writeByte('('); | 1427 | try writer.writeByte('('); |
| 1482 | try dg.renderType(writer, ty); | 1428 | try dg.renderValue(writer, ty, Value.undef, initializer_type); |
| 1483 | try writer.writeByte(')'); | 1429 | try writer.writeByte(')'); |
| 1430 | } else if (ty.bitSize(mod) > 64) { | ||
| 1431 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) | ||
| 1432 | var num_or = eff_num_fields - 1; | ||
| 1433 | while (num_or > 0) : (num_or -= 1) { | ||
| 1434 | try writer.writeAll("zig_or_"); | ||
| 1435 | try dg.renderTypeForBuiltinFnName(writer, ty); | ||
| 1436 | try writer.writeByte('('); | ||
| 1437 | } | ||
| 1484 | 1438 | ||
| 1485 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { | 1439 | var eff_index: usize = 0; |
| 1486 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | 1440 | var needs_closing_paren = false; |
| 1487 | .ty = field_ty.toIntern(), | 1441 | for (0..struct_type.field_types.len) |field_index| { |
| 1488 | .storage = .{ .u64 = bytes[field_index] }, | 1442 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 1489 | } }), | 1443 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1490 | .elems => |elems| elems[field_index], | 1444 | |
| 1491 | .repeated_elem => |elem| elem, | 1445 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { |
| 1492 | }; | 1446 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ |
| 1493 | 1447 | .ty = field_ty.toIntern(), | |
| 1494 | if (bit_offset != 0) { | 1448 | .storage = .{ .u64 = bytes[field_index] }, |
| 1495 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); | 1449 | } }), |
| 1496 | try writer.writeAll(" << "); | 1450 | .elems => |elems| elems[field_index], |
| 1497 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | 1451 | .repeated_elem => |elem| elem, |
| 1498 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | 1452 | }; |
| 1499 | } else { | 1453 | const cast_context = IntCastContext{ .value = .{ .value = Value.fromInterned(field_val) } }; |
| 1500 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); | 1454 | if (bit_offset != 0) { |
| 1455 | try writer.writeAll("zig_shl_"); | ||
| 1456 | try dg.renderTypeForBuiltinFnName(writer, ty); | ||
| 1457 | try writer.writeByte('('); | ||
| 1458 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | ||
| 1459 | try writer.writeAll(", "); | ||
| 1460 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | ||
| 1461 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 1462 | try writer.writeByte(')'); | ||
| 1463 | } else { | ||
| 1464 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | if (needs_closing_paren) try writer.writeByte(')'); | ||
| 1468 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); | ||
| 1469 | |||
| 1470 | bit_offset += field_ty.bitSize(mod); | ||
| 1471 | needs_closing_paren = true; | ||
| 1472 | eff_index += 1; | ||
| 1501 | } | 1473 | } |
| 1474 | } else { | ||
| 1475 | try writer.writeByte('('); | ||
| 1476 | // a << a_off | b << b_off | c << c_off | ||
| 1477 | var empty = true; | ||
| 1478 | for (0..struct_type.field_types.len) |field_index| { | ||
| 1479 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | ||
| 1480 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1502 | 1481 | ||
| 1503 | bit_offset += field_ty.bitSize(mod); | 1482 | if (!empty) try writer.writeAll(" | "); |
| 1504 | empty = false; | 1483 | try writer.writeByte('('); |
| 1484 | try dg.renderType(writer, ty); | ||
| 1485 | try writer.writeByte(')'); | ||
| 1486 | |||
| 1487 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { | ||
| 1488 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | ||
| 1489 | .ty = field_ty.toIntern(), | ||
| 1490 | .storage = .{ .u64 = bytes[field_index] }, | ||
| 1491 | } }), | ||
| 1492 | .elems => |elems| elems[field_index], | ||
| 1493 | .repeated_elem => |elem| elem, | ||
| 1494 | }; | ||
| 1495 | |||
| 1496 | if (bit_offset != 0) { | ||
| 1497 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); | ||
| 1498 | try writer.writeAll(" << "); | ||
| 1499 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | ||
| 1500 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 1501 | } else { | ||
| 1502 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); | ||
| 1503 | } | ||
| 1504 | |||
| 1505 | bit_offset += field_ty.bitSize(mod); | ||
| 1506 | empty = false; | ||
| 1507 | } | ||
| 1508 | try writer.writeByte(')'); | ||
| 1505 | } | 1509 | } |
| 1506 | try writer.writeByte(')'); | 1510 | }, |
| 1507 | } | 1511 | } |
| 1508 | }, | ||
| 1509 | }, | 1512 | }, |
| 1510 | else => unreachable, | 1513 | else => unreachable, |
| 1511 | }, | 1514 | }, |
| ... | @@ -1547,7 +1550,7 @@ pub const DeclGen = struct { | ... | @@ -1547,7 +1550,7 @@ pub const DeclGen = struct { |
| 1547 | 1550 | ||
| 1548 | const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; | 1551 | const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; |
| 1549 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 1552 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 1550 | const field_name = union_obj.field_names.get(ip)[field_index]; | 1553 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; |
| 1551 | if (union_obj.getLayout(ip) == .Packed) { | 1554 | if (union_obj.getLayout(ip) == .Packed) { |
| 1552 | if (field_ty.hasRuntimeBits(mod)) { | 1555 | if (field_ty.hasRuntimeBits(mod)) { |
| 1553 | if (field_ty.isPtrAtRuntime(mod)) { | 1556 | if (field_ty.isPtrAtRuntime(mod)) { |
| ... | @@ -5502,7 +5505,7 @@ fn fieldLocation( | ... | @@ -5502,7 +5505,7 @@ fn fieldLocation( |
| 5502 | .{ .field = .{ .identifier = "payload" } } | 5505 | .{ .field = .{ .identifier = "payload" } } |
| 5503 | else | 5506 | else |
| 5504 | .begin; | 5507 | .begin; |
| 5505 | const field_name = union_obj.field_names.get(ip)[field_index]; | 5508 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; |
| 5506 | return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_| | 5509 | return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_| |
| 5507 | .{ .payload_identifier = ip.stringToSlice(field_name) } | 5510 | .{ .payload_identifier = ip.stringToSlice(field_name) } |
| 5508 | else | 5511 | else |
| ... | @@ -5735,8 +5738,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5735,8 +5738,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5735 | else | 5738 | else |
| 5736 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, | 5739 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, |
| 5737 | 5740 | ||
| 5738 | .union_type => |union_type| field_name: { | 5741 | .union_type => field_name: { |
| 5739 | const union_obj = ip.loadUnionType(union_type); | 5742 | const union_obj = ip.loadUnionType(struct_ty.toIntern()); |
| 5740 | if (union_obj.flagsPtr(ip).layout == .Packed) { | 5743 | if (union_obj.flagsPtr(ip).layout == .Packed) { |
| 5741 | const operand_lval = if (struct_byval == .constant) blk: { | 5744 | const operand_lval = if (struct_byval == .constant) blk: { |
| 5742 | const operand_local = try f.allocLocal(inst, struct_ty); | 5745 | const operand_local = try f.allocLocal(inst, struct_ty); |
| ... | @@ -5762,8 +5765,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5762,8 +5765,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5762 | 5765 | ||
| 5763 | return local; | 5766 | return local; |
| 5764 | } else { | 5767 | } else { |
| 5765 | const name = union_obj.field_names.get(ip)[extra.field_index]; | 5768 | const name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 5766 | break :field_name if (union_type.hasTag(ip)) .{ | 5769 | break :field_name if (union_obj.hasTag(ip)) .{ |
| 5767 | .payload_identifier = ip.stringToSlice(name), | 5770 | .payload_identifier = ip.stringToSlice(name), |
| 5768 | } else .{ | 5771 | } else .{ |
| 5769 | .identifier = ip.stringToSlice(name), | 5772 | .identifier = ip.stringToSlice(name), |
| ... | @@ -7171,7 +7174,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7171,7 +7174,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7171 | 7174 | ||
| 7172 | const union_ty = f.typeOfIndex(inst); | 7175 | const union_ty = f.typeOfIndex(inst); |
| 7173 | const union_obj = mod.typeToUnion(union_ty).?; | 7176 | const union_obj = mod.typeToUnion(union_ty).?; |
| 7174 | const field_name = union_obj.field_names.get(ip)[extra.field_index]; | 7177 | const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 7175 | const payload_ty = f.typeOf(extra.init); | 7178 | const payload_ty = f.typeOf(extra.init); |
| 7176 | const payload = try f.resolveInst(extra.init); | 7179 | const payload = try f.resolveInst(extra.init); |
| 7177 | try reap(f, inst, &.{extra.init}); | 7180 | try reap(f, inst, &.{extra.init}); |
src/codegen/c/type.zig+8-8| ... | @@ -1507,7 +1507,7 @@ pub const CType = extern union { | ... | @@ -1507,7 +1507,7 @@ pub const CType = extern union { |
| 1507 | if (lookup.isMutable()) { | 1507 | if (lookup.isMutable()) { |
| 1508 | for (0..switch (zig_ty_tag) { | 1508 | for (0..switch (zig_ty_tag) { |
| 1509 | .Struct => ty.structFieldCount(mod), | 1509 | .Struct => ty.structFieldCount(mod), |
| 1510 | .Union => mod.typeToUnion(ty).?.field_names.len, | 1510 | .Union => mod.typeToUnion(ty).?.field_types.len, |
| 1511 | else => unreachable, | 1511 | else => unreachable, |
| 1512 | }) |field_i| { | 1512 | }) |field_i| { |
| 1513 | const field_ty = ty.structFieldType(field_i, mod); | 1513 | const field_ty = ty.structFieldType(field_i, mod); |
| ... | @@ -1589,7 +1589,7 @@ pub const CType = extern union { | ... | @@ -1589,7 +1589,7 @@ pub const CType = extern union { |
| 1589 | var is_packed = false; | 1589 | var is_packed = false; |
| 1590 | for (0..switch (zig_ty_tag) { | 1590 | for (0..switch (zig_ty_tag) { |
| 1591 | .Struct => ty.structFieldCount(mod), | 1591 | .Struct => ty.structFieldCount(mod), |
| 1592 | .Union => mod.typeToUnion(ty).?.field_names.len, | 1592 | .Union => mod.typeToUnion(ty).?.field_types.len, |
| 1593 | else => unreachable, | 1593 | else => unreachable, |
| 1594 | }) |field_i| { | 1594 | }) |field_i| { |
| 1595 | const field_ty = ty.structFieldType(field_i, mod); | 1595 | const field_ty = ty.structFieldType(field_i, mod); |
| ... | @@ -1940,7 +1940,7 @@ pub const CType = extern union { | ... | @@ -1940,7 +1940,7 @@ pub const CType = extern union { |
| 1940 | const zig_ty_tag = ty.zigTypeTag(mod); | 1940 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 1941 | const fields_len = switch (zig_ty_tag) { | 1941 | const fields_len = switch (zig_ty_tag) { |
| 1942 | .Struct => ty.structFieldCount(mod), | 1942 | .Struct => ty.structFieldCount(mod), |
| 1943 | .Union => mod.typeToUnion(ty).?.field_names.len, | 1943 | .Union => mod.typeToUnion(ty).?.field_types.len, |
| 1944 | else => unreachable, | 1944 | else => unreachable, |
| 1945 | }; | 1945 | }; |
| 1946 | 1946 | ||
| ... | @@ -1967,7 +1967,7 @@ pub const CType = extern union { | ... | @@ -1967,7 +1967,7 @@ pub const CType = extern union { |
| 1967 | else | 1967 | else |
| 1968 | arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) { | 1968 | arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) { |
| 1969 | .Struct => ty.legacyStructFieldName(field_i, mod), | 1969 | .Struct => ty.legacyStructFieldName(field_i, mod), |
| 1970 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], | 1970 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], |
| 1971 | else => unreachable, | 1971 | else => unreachable, |
| 1972 | })), | 1972 | })), |
| 1973 | .type = store.set.typeToIndex(field_ty, mod, switch (kind) { | 1973 | .type = store.set.typeToIndex(field_ty, mod, switch (kind) { |
| ... | @@ -2097,7 +2097,7 @@ pub const CType = extern union { | ... | @@ -2097,7 +2097,7 @@ pub const CType = extern union { |
| 2097 | var c_field_i: usize = 0; | 2097 | var c_field_i: usize = 0; |
| 2098 | for (0..switch (zig_ty_tag) { | 2098 | for (0..switch (zig_ty_tag) { |
| 2099 | .Struct => ty.structFieldCount(mod), | 2099 | .Struct => ty.structFieldCount(mod), |
| 2100 | .Union => mod.typeToUnion(ty).?.field_names.len, | 2100 | .Union => mod.typeToUnion(ty).?.field_types.len, |
| 2101 | else => unreachable, | 2101 | else => unreachable, |
| 2102 | }) |field_i_usize| { | 2102 | }) |field_i_usize| { |
| 2103 | const field_i: u32 = @intCast(field_i_usize); | 2103 | const field_i: u32 = @intCast(field_i_usize); |
| ... | @@ -2120,7 +2120,7 @@ pub const CType = extern union { | ... | @@ -2120,7 +2120,7 @@ pub const CType = extern union { |
| 2120 | else | 2120 | else |
| 2121 | ip.stringToSlice(switch (zig_ty_tag) { | 2121 | ip.stringToSlice(switch (zig_ty_tag) { |
| 2122 | .Struct => ty.legacyStructFieldName(field_i, mod), | 2122 | .Struct => ty.legacyStructFieldName(field_i, mod), |
| 2123 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], | 2123 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], |
| 2124 | else => unreachable, | 2124 | else => unreachable, |
| 2125 | }), | 2125 | }), |
| 2126 | mem.span(c_field.name), | 2126 | mem.span(c_field.name), |
| ... | @@ -2226,7 +2226,7 @@ pub const CType = extern union { | ... | @@ -2226,7 +2226,7 @@ pub const CType = extern union { |
| 2226 | const zig_ty_tag = ty.zigTypeTag(mod); | 2226 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2227 | for (0..switch (ty.zigTypeTag(mod)) { | 2227 | for (0..switch (ty.zigTypeTag(mod)) { |
| 2228 | .Struct => ty.structFieldCount(mod), | 2228 | .Struct => ty.structFieldCount(mod), |
| 2229 | .Union => mod.typeToUnion(ty).?.field_names.len, | 2229 | .Union => mod.typeToUnion(ty).?.field_types.len, |
| 2230 | else => unreachable, | 2230 | else => unreachable, |
| 2231 | }) |field_i_usize| { | 2231 | }) |field_i_usize| { |
| 2232 | const field_i: u32 = @intCast(field_i_usize); | 2232 | const field_i: u32 = @intCast(field_i_usize); |
| ... | @@ -2245,7 +2245,7 @@ pub const CType = extern union { | ... | @@ -2245,7 +2245,7 @@ pub const CType = extern union { |
| 2245 | else | 2245 | else |
| 2246 | mod.intern_pool.stringToSlice(switch (zig_ty_tag) { | 2246 | mod.intern_pool.stringToSlice(switch (zig_ty_tag) { |
| 2247 | .Struct => ty.legacyStructFieldName(field_i, mod), | 2247 | .Struct => ty.legacyStructFieldName(field_i, mod), |
| 2248 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], | 2248 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], |
| 2249 | else => unreachable, | 2249 | else => unreachable, |
| 2250 | })); | 2250 | })); |
| 2251 | autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align"); | 2251 | autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align"); |
src/codegen/llvm.zig+33-28| ... | @@ -1997,7 +1997,7 @@ pub const Object = struct { | ... | @@ -1997,7 +1997,7 @@ pub const Object = struct { |
| 1997 | return debug_enum_type; | 1997 | return debug_enum_type; |
| 1998 | } | 1998 | } |
| 1999 | 1999 | ||
| 2000 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 2000 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 2001 | 2001 | ||
| 2002 | const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len); | 2002 | const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len); |
| 2003 | defer gpa.free(enumerators); | 2003 | defer gpa.free(enumerators); |
| ... | @@ -2507,8 +2507,8 @@ pub const Object = struct { | ... | @@ -2507,8 +2507,8 @@ pub const Object = struct { |
| 2507 | try o.debug_type_map.put(gpa, ty, debug_struct_type); | 2507 | try o.debug_type_map.put(gpa, ty, debug_struct_type); |
| 2508 | return debug_struct_type; | 2508 | return debug_struct_type; |
| 2509 | }, | 2509 | }, |
| 2510 | .struct_type => |struct_type| { | 2510 | .struct_type => { |
| 2511 | if (!struct_type.haveFieldTypes(ip)) { | 2511 | if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) { |
| 2512 | // This can happen if a struct type makes it all the way to | 2512 | // This can happen if a struct type makes it all the way to |
| 2513 | // flush() without ever being instantiated or referenced (even | 2513 | // flush() without ever being instantiated or referenced (even |
| 2514 | // via pointer). The only reason we are hearing about it now is | 2514 | // via pointer). The only reason we are hearing about it now is |
| ... | @@ -2597,15 +2597,14 @@ pub const Object = struct { | ... | @@ -2597,15 +2597,14 @@ pub const Object = struct { |
| 2597 | const name = try o.allocTypeName(ty); | 2597 | const name = try o.allocTypeName(ty); |
| 2598 | defer gpa.free(name); | 2598 | defer gpa.free(name); |
| 2599 | 2599 | ||
| 2600 | const union_type = ip.indexToKey(ty.toIntern()).union_type; | 2600 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 2601 | if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) { | 2601 | if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2602 | const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); | 2602 | const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); |
| 2603 | try o.debug_type_map.put(gpa, ty, debug_union_type); | 2603 | try o.debug_type_map.put(gpa, ty, debug_union_type); |
| 2604 | return debug_union_type; | 2604 | return debug_union_type; |
| 2605 | } | 2605 | } |
| 2606 | 2606 | ||
| 2607 | const union_obj = ip.loadUnionType(union_type); | 2607 | const layout = mod.getUnionLayout(union_type); |
| 2608 | const layout = mod.getUnionLayout(union_obj); | ||
| 2609 | 2608 | ||
| 2610 | const debug_fwd_ref = try o.builder.debugForwardReference(); | 2609 | const debug_fwd_ref = try o.builder.debugForwardReference(); |
| 2611 | 2610 | ||
| ... | @@ -2622,7 +2621,7 @@ pub const Object = struct { | ... | @@ -2622,7 +2621,7 @@ pub const Object = struct { |
| 2622 | ty.abiSize(mod) * 8, | 2621 | ty.abiSize(mod) * 8, |
| 2623 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2622 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2624 | try o.builder.debugTuple( | 2623 | try o.builder.debugTuple( |
| 2625 | &.{try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty))}, | 2624 | &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))}, |
| 2626 | ), | 2625 | ), |
| 2627 | ); | 2626 | ); |
| 2628 | 2627 | ||
| ... | @@ -2636,21 +2635,23 @@ pub const Object = struct { | ... | @@ -2636,21 +2635,23 @@ pub const Object = struct { |
| 2636 | var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; | 2635 | var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; |
| 2637 | defer fields.deinit(gpa); | 2636 | defer fields.deinit(gpa); |
| 2638 | 2637 | ||
| 2639 | try fields.ensureUnusedCapacity(gpa, union_obj.field_names.len); | 2638 | try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len); |
| 2640 | 2639 | ||
| 2641 | const debug_union_fwd_ref = if (layout.tag_size == 0) | 2640 | const debug_union_fwd_ref = if (layout.tag_size == 0) |
| 2642 | debug_fwd_ref | 2641 | debug_fwd_ref |
| 2643 | else | 2642 | else |
| 2644 | try o.builder.debugForwardReference(); | 2643 | try o.builder.debugForwardReference(); |
| 2645 | 2644 | ||
| 2646 | for (0..union_obj.field_names.len) |field_index| { | 2645 | const tag_type = union_type.loadTagType(ip); |
| 2647 | const field_ty = union_obj.field_types.get(ip)[field_index]; | 2646 | |
| 2647 | for (0..tag_type.names.len) |field_index| { | ||
| 2648 | const field_ty = union_type.field_types.get(ip)[field_index]; | ||
| 2648 | if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue; | 2649 | if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2649 | 2650 | ||
| 2650 | const field_size = Type.fromInterned(field_ty).abiSize(mod); | 2651 | const field_size = Type.fromInterned(field_ty).abiSize(mod); |
| 2651 | const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index)); | 2652 | const field_align = mod.unionFieldNormalAlignment(union_type, @intCast(field_index)); |
| 2652 | 2653 | ||
| 2653 | const field_name = union_obj.field_names.get(ip)[field_index]; | 2654 | const field_name = tag_type.names.get(ip)[field_index]; |
| 2654 | fields.appendAssumeCapacity(try o.builder.debugMemberType( | 2655 | fields.appendAssumeCapacity(try o.builder.debugMemberType( |
| 2655 | try o.builder.metadataString(ip.stringToSlice(field_name)), | 2656 | try o.builder.metadataString(ip.stringToSlice(field_name)), |
| 2656 | .none, // File | 2657 | .none, // File |
| ... | @@ -2706,7 +2707,7 @@ pub const Object = struct { | ... | @@ -2706,7 +2707,7 @@ pub const Object = struct { |
| 2706 | .none, // File | 2707 | .none, // File |
| 2707 | debug_fwd_ref, | 2708 | debug_fwd_ref, |
| 2708 | 0, // Line | 2709 | 0, // Line |
| 2709 | try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty)), | 2710 | try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)), |
| 2710 | layout.tag_size * 8, | 2711 | layout.tag_size * 8, |
| 2711 | layout.tag_align.toByteUnits(0) * 8, | 2712 | layout.tag_align.toByteUnits(0) * 8, |
| 2712 | tag_offset * 8, | 2713 | tag_offset * 8, |
| ... | @@ -3321,9 +3322,11 @@ pub const Object = struct { | ... | @@ -3321,9 +3322,11 @@ pub const Object = struct { |
| 3321 | return o.builder.structType(.normal, fields[0..fields_len]); | 3322 | return o.builder.structType(.normal, fields[0..fields_len]); |
| 3322 | }, | 3323 | }, |
| 3323 | .simple_type => unreachable, | 3324 | .simple_type => unreachable, |
| 3324 | .struct_type => |struct_type| { | 3325 | .struct_type => { |
| 3325 | if (o.type_map.get(t.toIntern())) |value| return value; | 3326 | if (o.type_map.get(t.toIntern())) |value| return value; |
| 3326 | 3327 | ||
| 3328 | const struct_type = ip.loadStructType(t.toIntern()); | ||
| 3329 | |||
| 3327 | if (struct_type.layout == .Packed) { | 3330 | if (struct_type.layout == .Packed) { |
| 3328 | const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*)); | 3331 | const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*)); |
| 3329 | try o.type_map.put(o.gpa, t.toIntern(), int_ty); | 3332 | try o.type_map.put(o.gpa, t.toIntern(), int_ty); |
| ... | @@ -3468,10 +3471,10 @@ pub const Object = struct { | ... | @@ -3468,10 +3471,10 @@ pub const Object = struct { |
| 3468 | } | 3471 | } |
| 3469 | return o.builder.structType(.normal, llvm_field_types.items); | 3472 | return o.builder.structType(.normal, llvm_field_types.items); |
| 3470 | }, | 3473 | }, |
| 3471 | .union_type => |union_type| { | 3474 | .union_type => { |
| 3472 | if (o.type_map.get(t.toIntern())) |value| return value; | 3475 | if (o.type_map.get(t.toIntern())) |value| return value; |
| 3473 | 3476 | ||
| 3474 | const union_obj = ip.loadUnionType(union_type); | 3477 | const union_obj = ip.loadUnionType(t.toIntern()); |
| 3475 | const layout = mod.getUnionLayout(union_obj); | 3478 | const layout = mod.getUnionLayout(union_obj); |
| 3476 | 3479 | ||
| 3477 | if (union_obj.flagsPtr(ip).layout == .Packed) { | 3480 | if (union_obj.flagsPtr(ip).layout == .Packed) { |
| ... | @@ -3545,17 +3548,16 @@ pub const Object = struct { | ... | @@ -3545,17 +3548,16 @@ pub const Object = struct { |
| 3545 | ); | 3548 | ); |
| 3546 | return ty; | 3549 | return ty; |
| 3547 | }, | 3550 | }, |
| 3548 | .opaque_type => |opaque_type| { | 3551 | .opaque_type => { |
| 3549 | const gop = try o.type_map.getOrPut(o.gpa, t.toIntern()); | 3552 | const gop = try o.type_map.getOrPut(o.gpa, t.toIntern()); |
| 3550 | if (!gop.found_existing) { | 3553 | if (!gop.found_existing) { |
| 3551 | const name = try o.builder.string(ip.stringToSlice( | 3554 | const decl = mod.declPtr(ip.loadOpaqueType(t.toIntern()).decl); |
| 3552 | try mod.opaqueFullyQualifiedName(opaque_type), | 3555 | const name = try o.builder.string(ip.stringToSlice(try decl.fullyQualifiedName(mod))); |
| 3553 | )); | ||
| 3554 | gop.value_ptr.* = try o.builder.opaqueType(name); | 3556 | gop.value_ptr.* = try o.builder.opaqueType(name); |
| 3555 | } | 3557 | } |
| 3556 | return gop.value_ptr.*; | 3558 | return gop.value_ptr.*; |
| 3557 | }, | 3559 | }, |
| 3558 | .enum_type => |enum_type| try o.lowerType(Type.fromInterned(enum_type.tag_ty)), | 3560 | .enum_type => try o.lowerType(Type.fromInterned(ip.loadEnumType(t.toIntern()).tag_ty)), |
| 3559 | .func_type => |func_type| try o.lowerTypeFn(func_type), | 3561 | .func_type => |func_type| try o.lowerTypeFn(func_type), |
| 3560 | .error_set_type, .inferred_error_set_type => try o.errorIntType(), | 3562 | .error_set_type, .inferred_error_set_type => try o.errorIntType(), |
| 3561 | // values, not types | 3563 | // values, not types |
| ... | @@ -4032,7 +4034,8 @@ pub const Object = struct { | ... | @@ -4032,7 +4034,8 @@ pub const Object = struct { |
| 4032 | else | 4034 | else |
| 4033 | struct_ty, vals); | 4035 | struct_ty, vals); |
| 4034 | }, | 4036 | }, |
| 4035 | .struct_type => |struct_type| { | 4037 | .struct_type => { |
| 4038 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 4036 | assert(struct_type.haveLayout(ip)); | 4039 | assert(struct_type.haveLayout(ip)); |
| 4037 | const struct_ty = try o.lowerType(ty); | 4040 | const struct_ty = try o.lowerType(ty); |
| 4038 | if (struct_type.layout == .Packed) { | 4041 | if (struct_type.layout == .Packed) { |
| ... | @@ -4596,7 +4599,7 @@ pub const Object = struct { | ... | @@ -4596,7 +4599,7 @@ pub const Object = struct { |
| 4596 | fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { | 4599 | fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { |
| 4597 | const zcu = o.module; | 4600 | const zcu = o.module; |
| 4598 | const ip = &zcu.intern_pool; | 4601 | const ip = &zcu.intern_pool; |
| 4599 | const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type; | 4602 | const enum_type = ip.loadEnumType(enum_ty.toIntern()); |
| 4600 | 4603 | ||
| 4601 | // TODO: detect when the type changes and re-emit this function. | 4604 | // TODO: detect when the type changes and re-emit this function. |
| 4602 | const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); | 4605 | const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); |
| ... | @@ -9620,7 +9623,7 @@ pub const FuncGen = struct { | ... | @@ -9620,7 +9623,7 @@ pub const FuncGen = struct { |
| 9620 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { | 9623 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { |
| 9621 | const o = self.dg.object; | 9624 | const o = self.dg.object; |
| 9622 | const zcu = o.module; | 9625 | const zcu = o.module; |
| 9623 | const enum_type = zcu.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; | 9626 | const enum_type = zcu.intern_pool.loadEnumType(enum_ty.toIntern()); |
| 9624 | 9627 | ||
| 9625 | // TODO: detect when the type changes and re-emit this function. | 9628 | // TODO: detect when the type changes and re-emit this function. |
| 9626 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); | 9629 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); |
| ... | @@ -10092,7 +10095,7 @@ pub const FuncGen = struct { | ... | @@ -10092,7 +10095,7 @@ pub const FuncGen = struct { |
| 10092 | 10095 | ||
| 10093 | const tag_int = blk: { | 10096 | const tag_int = blk: { |
| 10094 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); | 10097 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); |
| 10095 | const union_field_name = union_obj.field_names.get(ip)[extra.field_index]; | 10098 | const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 10096 | const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?; | 10099 | const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?; |
| 10097 | const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index); | 10100 | const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index); |
| 10098 | const tag_int_val = try tag_val.intFromEnum(tag_ty, mod); | 10101 | const tag_int_val = try tag_val.intFromEnum(tag_ty, mod); |
| ... | @@ -11154,7 +11157,8 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E | ... | @@ -11154,7 +11157,8 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E |
| 11154 | if (first_non_integer == null or classes[first_non_integer.?] == .none) { | 11157 | if (first_non_integer == null or classes[first_non_integer.?] == .none) { |
| 11155 | assert(first_non_integer orelse classes.len == types_index); | 11158 | assert(first_non_integer orelse classes.len == types_index); |
| 11156 | switch (ip.indexToKey(return_type.toIntern())) { | 11159 | switch (ip.indexToKey(return_type.toIntern())) { |
| 11157 | .struct_type => |struct_type| { | 11160 | .struct_type => { |
| 11161 | const struct_type = ip.loadStructType(return_type.toIntern()); | ||
| 11158 | assert(struct_type.haveLayout(ip)); | 11162 | assert(struct_type.haveLayout(ip)); |
| 11159 | const size: u64 = struct_type.size(ip).*; | 11163 | const size: u64 = struct_type.size(ip).*; |
| 11160 | assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); | 11164 | assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); |
| ... | @@ -11446,7 +11450,8 @@ const ParamTypeIterator = struct { | ... | @@ -11446,7 +11450,8 @@ const ParamTypeIterator = struct { |
| 11446 | return .byref; | 11450 | return .byref; |
| 11447 | } | 11451 | } |
| 11448 | switch (ip.indexToKey(ty.toIntern())) { | 11452 | switch (ip.indexToKey(ty.toIntern())) { |
| 11449 | .struct_type => |struct_type| { | 11453 | .struct_type => { |
| 11454 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 11450 | assert(struct_type.haveLayout(ip)); | 11455 | assert(struct_type.haveLayout(ip)); |
| 11451 | const size: u64 = struct_type.size(ip).*; | 11456 | const size: u64 = struct_type.size(ip).*; |
| 11452 | assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); | 11457 | assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); |
| ... | @@ -11562,7 +11567,7 @@ fn isByRef(ty: Type, mod: *Module) bool { | ... | @@ -11562,7 +11567,7 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 11562 | } | 11567 | } |
| 11563 | return false; | 11568 | return false; |
| 11564 | }, | 11569 | }, |
| 11565 | .struct_type => |s| s, | 11570 | .struct_type => ip.loadStructType(ty.toIntern()), |
| 11566 | else => unreachable, | 11571 | else => unreachable, |
| 11567 | }; | 11572 | }; |
| 11568 | 11573 |
src/codegen/spirv.zig+9-11| ... | @@ -1528,7 +1528,7 @@ const DeclGen = struct { | ... | @@ -1528,7 +1528,7 @@ const DeclGen = struct { |
| 1528 | try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); | 1528 | try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); |
| 1529 | return ty_ref; | 1529 | return ty_ref; |
| 1530 | }, | 1530 | }, |
| 1531 | .struct_type => |struct_type| struct_type, | 1531 | .struct_type => ip.loadStructType(ty.toIntern()), |
| 1532 | else => unreachable, | 1532 | else => unreachable, |
| 1533 | }; | 1533 | }; |
| 1534 | 1534 | ||
| ... | @@ -3633,7 +3633,8 @@ const DeclGen = struct { | ... | @@ -3633,7 +3633,8 @@ const DeclGen = struct { |
| 3633 | index += 1; | 3633 | index += 1; |
| 3634 | } | 3634 | } |
| 3635 | }, | 3635 | }, |
| 3636 | .struct_type => |struct_type| { | 3636 | .struct_type => { |
| 3637 | const struct_type = ip.loadStructType(result_ty.toIntern()); | ||
| 3637 | var it = struct_type.iterateRuntimeOrder(ip); | 3638 | var it = struct_type.iterateRuntimeOrder(ip); |
| 3638 | for (elements, 0..) |element, i| { | 3639 | for (elements, 0..) |element, i| { |
| 3639 | const field_index = it.next().?; | 3640 | const field_index = it.next().?; |
| ... | @@ -3901,36 +3902,33 @@ const DeclGen = struct { | ... | @@ -3901,36 +3902,33 @@ const DeclGen = struct { |
| 3901 | const mod = self.module; | 3902 | const mod = self.module; |
| 3902 | const ip = &mod.intern_pool; | 3903 | const ip = &mod.intern_pool; |
| 3903 | const union_ty = mod.typeToUnion(ty).?; | 3904 | const union_ty = mod.typeToUnion(ty).?; |
| 3905 | const tag_ty = Type.fromInterned(union_ty.enum_tag_ty); | ||
| 3904 | 3906 | ||
| 3905 | if (union_ty.getLayout(ip) == .Packed) { | 3907 | if (union_ty.getLayout(ip) == .Packed) { |
| 3906 | unreachable; // TODO | 3908 | unreachable; // TODO |
| 3907 | } | 3909 | } |
| 3908 | 3910 | ||
| 3909 | const maybe_tag_ty = ty.unionTagTypeSafety(mod); | ||
| 3910 | const layout = self.unionLayout(ty); | 3911 | const layout = self.unionLayout(ty); |
| 3911 | 3912 | ||
| 3912 | const tag_int = if (layout.tag_size != 0) blk: { | 3913 | const tag_int = if (layout.tag_size != 0) blk: { |
| 3913 | const tag_ty = maybe_tag_ty.?; | 3914 | const tag_val = try mod.enumValueFieldIndex(tag_ty, active_field); |
| 3914 | const union_field_name = union_ty.field_names.get(ip)[active_field]; | ||
| 3915 | const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?; | ||
| 3916 | const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index); | ||
| 3917 | const tag_int_val = try tag_val.intFromEnum(tag_ty, mod); | 3915 | const tag_int_val = try tag_val.intFromEnum(tag_ty, mod); |
| 3918 | break :blk tag_int_val.toUnsignedInt(mod); | 3916 | break :blk tag_int_val.toUnsignedInt(mod); |
| 3919 | } else 0; | 3917 | } else 0; |
| 3920 | 3918 | ||
| 3921 | if (!layout.has_payload) { | 3919 | if (!layout.has_payload) { |
| 3922 | const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct); | 3920 | const tag_ty_ref = try self.resolveType(tag_ty, .direct); |
| 3923 | return try self.constInt(tag_ty_ref, tag_int); | 3921 | return try self.constInt(tag_ty_ref, tag_int); |
| 3924 | } | 3922 | } |
| 3925 | 3923 | ||
| 3926 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); | 3924 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); |
| 3927 | 3925 | ||
| 3928 | if (layout.tag_size != 0) { | 3926 | if (layout.tag_size != 0) { |
| 3929 | const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct); | 3927 | const tag_ty_ref = try self.resolveType(tag_ty, .direct); |
| 3930 | const tag_ptr_ty_ref = try self.ptrType(maybe_tag_ty.?, .Function); | 3928 | const tag_ptr_ty_ref = try self.ptrType(tag_ty, .Function); |
| 3931 | const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); | 3929 | const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); |
| 3932 | const tag_id = try self.constInt(tag_ty_ref, tag_int); | 3930 | const tag_id = try self.constInt(tag_ty_ref, tag_int); |
| 3933 | try self.store(maybe_tag_ty.?, ptr_id, tag_id, .{}); | 3931 | try self.store(tag_ty, ptr_id, tag_id, .{}); |
| 3934 | } | 3932 | } |
| 3935 | 3933 | ||
| 3936 | const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); | 3934 | const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); |
src/glibc.zig+1| ... | @@ -1118,6 +1118,7 @@ fn buildSharedLib( | ... | @@ -1118,6 +1118,7 @@ fn buildSharedLib( |
| 1118 | .cc_argv = &.{}, | 1118 | .cc_argv = &.{}, |
| 1119 | .parent = null, | 1119 | .parent = null, |
| 1120 | .builtin_mod = null, | 1120 | .builtin_mod = null, |
| 1121 | .builtin_modules = null, // there is only one module in this compilation | ||
| 1121 | }); | 1122 | }); |
| 1122 | 1123 | ||
| 1123 | const c_source_files = [1]Compilation.CSourceFile{ | 1124 | const c_source_files = [1]Compilation.CSourceFile{ |
src/libcxx.zig+2| ... | @@ -181,6 +181,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { | ... | @@ -181,6 +181,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| 181 | .cc_argv = &.{}, | 181 | .cc_argv = &.{}, |
| 182 | .parent = null, | 182 | .parent = null, |
| 183 | .builtin_mod = null, | 183 | .builtin_mod = null, |
| 184 | .builtin_modules = null, // there is only one module in this compilation | ||
| 184 | }); | 185 | }); |
| 185 | 186 | ||
| 186 | var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxx_files.len); | 187 | var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxx_files.len); |
| ... | @@ -395,6 +396,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { | ... | @@ -395,6 +396,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| 395 | .cc_argv = &.{}, | 396 | .cc_argv = &.{}, |
| 396 | .parent = null, | 397 | .parent = null, |
| 397 | .builtin_mod = null, | 398 | .builtin_mod = null, |
| 399 | .builtin_modules = null, // there is only one module in this compilation | ||
| 398 | }); | 400 | }); |
| 399 | 401 | ||
| 400 | var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxxabi_files.len); | 402 | var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxxabi_files.len); |
src/libtsan.zig+1| ... | @@ -92,6 +92,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) BuildError!v | ... | @@ -92,6 +92,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) BuildError!v |
| 92 | .cc_argv = &common_flags, | 92 | .cc_argv = &common_flags, |
| 93 | .parent = null, | 93 | .parent = null, |
| 94 | .builtin_mod = null, | 94 | .builtin_mod = null, |
| 95 | .builtin_modules = null, // there is only one module in this compilation | ||
| 95 | }) catch |err| { | 96 | }) catch |err| { |
| 96 | comp.setMiscFailure( | 97 | comp.setMiscFailure( |
| 97 | .libtsan, | 98 | .libtsan, |
src/libunwind.zig+1| ... | @@ -58,6 +58,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { | ... | @@ -58,6 +58,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| 58 | .cc_argv = &.{}, | 58 | .cc_argv = &.{}, |
| 59 | .parent = null, | 59 | .parent = null, |
| 60 | .builtin_mod = null, | 60 | .builtin_mod = null, |
| 61 | .builtin_modules = null, // there is only one module in this compilation | ||
| 61 | }); | 62 | }); |
| 62 | 63 | ||
| 63 | const root_name = "unwind"; | 64 | const root_name = "unwind"; |
src/link/Dwarf.zig+4-3| ... | @@ -311,7 +311,8 @@ pub const DeclState = struct { | ... | @@ -311,7 +311,8 @@ pub const DeclState = struct { |
| 311 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); | 311 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| 312 | } | 312 | } |
| 313 | }, | 313 | }, |
| 314 | .struct_type => |struct_type| { | 314 | .struct_type => { |
| 315 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 315 | // DW.AT.name, DW.FORM.string | 316 | // DW.AT.name, DW.FORM.string |
| 316 | try ty.print(dbg_info_buffer.writer(), mod); | 317 | try ty.print(dbg_info_buffer.writer(), mod); |
| 317 | try dbg_info_buffer.append(0); | 318 | try dbg_info_buffer.append(0); |
| ... | @@ -374,7 +375,7 @@ pub const DeclState = struct { | ... | @@ -374,7 +375,7 @@ pub const DeclState = struct { |
| 374 | try ty.print(dbg_info_buffer.writer(), mod); | 375 | try ty.print(dbg_info_buffer.writer(), mod); |
| 375 | try dbg_info_buffer.append(0); | 376 | try dbg_info_buffer.append(0); |
| 376 | 377 | ||
| 377 | const enum_type = ip.indexToKey(ty.ip_index).enum_type; | 378 | const enum_type = ip.loadEnumType(ty.ip_index); |
| 378 | for (enum_type.names.get(ip), 0..) |field_name_index, field_i| { | 379 | for (enum_type.names.get(ip), 0..) |field_name_index, field_i| { |
| 379 | const field_name = ip.stringToSlice(field_name_index); | 380 | const field_name = ip.stringToSlice(field_name_index); |
| 380 | // DW.AT.enumerator | 381 | // DW.AT.enumerator |
| ... | @@ -442,7 +443,7 @@ pub const DeclState = struct { | ... | @@ -442,7 +443,7 @@ pub const DeclState = struct { |
| 442 | try dbg_info_buffer.append(0); | 443 | try dbg_info_buffer.append(0); |
| 443 | } | 444 | } |
| 444 | 445 | ||
| 445 | for (union_obj.field_types.get(ip), union_obj.field_names.get(ip)) |field_ty, field_name| { | 446 | for (union_obj.field_types.get(ip), union_obj.loadTagType(ip).names.get(ip)) |field_ty, field_name| { |
| 446 | if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; | 447 | if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; |
| 447 | // DW.AT.member | 448 | // DW.AT.member |
| 448 | try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member)); | 449 | try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member)); |
src/main.zig+15-3| ... | @@ -2708,7 +2708,9 @@ fn buildOutputType( | ... | @@ -2708,7 +2708,9 @@ fn buildOutputType( |
| 2708 | create_module.opts.emit_bin = emit_bin != .no; | 2708 | create_module.opts.emit_bin = emit_bin != .no; |
| 2709 | create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0; | 2709 | create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0; |
| 2710 | 2710 | ||
| 2711 | const main_mod = try createModule(gpa, arena, &create_module, 0, null, zig_lib_directory); | 2711 | var builtin_modules: std.StringHashMapUnmanaged(*Package.Module) = .{}; |
| 2712 | // `builtin_modules` allocated into `arena`, so no deinit | ||
| 2713 | const main_mod = try createModule(gpa, arena, &create_module, 0, null, zig_lib_directory, &builtin_modules); | ||
| 2712 | for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| { | 2714 | for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| { |
| 2713 | if (cli_mod.resolved == null) | 2715 | if (cli_mod.resolved == null) |
| 2714 | fatal("module '{s}' declared but not used", .{key}); | 2716 | fatal("module '{s}' declared but not used", .{key}); |
| ... | @@ -2753,6 +2755,7 @@ fn buildOutputType( | ... | @@ -2753,6 +2755,7 @@ fn buildOutputType( |
| 2753 | .global = create_module.resolved_options, | 2755 | .global = create_module.resolved_options, |
| 2754 | .parent = main_mod, | 2756 | .parent = main_mod, |
| 2755 | .builtin_mod = main_mod.getBuiltinDependency(), | 2757 | .builtin_mod = main_mod.getBuiltinDependency(), |
| 2758 | .builtin_modules = null, // `builtin_mod` is specified | ||
| 2756 | }); | 2759 | }); |
| 2757 | test_mod.deps = try main_mod.deps.clone(arena); | 2760 | test_mod.deps = try main_mod.deps.clone(arena); |
| 2758 | break :test_mod test_mod; | 2761 | break :test_mod test_mod; |
| ... | @@ -2771,6 +2774,7 @@ fn buildOutputType( | ... | @@ -2771,6 +2774,7 @@ fn buildOutputType( |
| 2771 | .global = create_module.resolved_options, | 2774 | .global = create_module.resolved_options, |
| 2772 | .parent = main_mod, | 2775 | .parent = main_mod, |
| 2773 | .builtin_mod = main_mod.getBuiltinDependency(), | 2776 | .builtin_mod = main_mod.getBuiltinDependency(), |
| 2777 | .builtin_modules = null, // `builtin_mod` is specified | ||
| 2774 | }); | 2778 | }); |
| 2775 | 2779 | ||
| 2776 | break :root_mod test_mod; | 2780 | break :root_mod test_mod; |
| ... | @@ -3479,6 +3483,7 @@ fn createModule( | ... | @@ -3479,6 +3483,7 @@ fn createModule( |
| 3479 | index: usize, | 3483 | index: usize, |
| 3480 | parent: ?*Package.Module, | 3484 | parent: ?*Package.Module, |
| 3481 | zig_lib_directory: Cache.Directory, | 3485 | zig_lib_directory: Cache.Directory, |
| 3486 | builtin_modules: *std.StringHashMapUnmanaged(*Package.Module), | ||
| 3482 | ) Allocator.Error!*Package.Module { | 3487 | ) Allocator.Error!*Package.Module { |
| 3483 | const cli_mod = &create_module.modules.values()[index]; | 3488 | const cli_mod = &create_module.modules.values()[index]; |
| 3484 | if (cli_mod.resolved) |m| return m; | 3489 | if (cli_mod.resolved) |m| return m; |
| ... | @@ -3931,6 +3936,7 @@ fn createModule( | ... | @@ -3931,6 +3936,7 @@ fn createModule( |
| 3931 | .global = create_module.resolved_options, | 3936 | .global = create_module.resolved_options, |
| 3932 | .parent = parent, | 3937 | .parent = parent, |
| 3933 | .builtin_mod = null, | 3938 | .builtin_mod = null, |
| 3939 | .builtin_modules = builtin_modules, | ||
| 3934 | }) catch |err| switch (err) { | 3940 | }) catch |err| switch (err) { |
| 3935 | error.ValgrindUnsupportedOnTarget => fatal("unable to create module '{s}': valgrind does not support the selected target CPU architecture", .{name}), | 3941 | error.ValgrindUnsupportedOnTarget => fatal("unable to create module '{s}': valgrind does not support the selected target CPU architecture", .{name}), |
| 3936 | error.TargetRequiresSingleThreaded => fatal("unable to create module '{s}': the selected target does not support multithreading", .{name}), | 3942 | error.TargetRequiresSingleThreaded => fatal("unable to create module '{s}': the selected target does not support multithreading", .{name}), |
| ... | @@ -3953,7 +3959,7 @@ fn createModule( | ... | @@ -3953,7 +3959,7 @@ fn createModule( |
| 3953 | for (cli_mod.deps) |dep| { | 3959 | for (cli_mod.deps) |dep| { |
| 3954 | const dep_index = create_module.modules.getIndex(dep.value) orelse | 3960 | const dep_index = create_module.modules.getIndex(dep.value) orelse |
| 3955 | fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key }); | 3961 | fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key }); |
| 3956 | const dep_mod = try createModule(gpa, arena, create_module, dep_index, mod, zig_lib_directory); | 3962 | const dep_mod = try createModule(gpa, arena, create_module, dep_index, mod, zig_lib_directory, builtin_modules); |
| 3957 | try mod.deps.put(arena, dep.key, dep_mod); | 3963 | try mod.deps.put(arena, dep.key, dep_mod); |
| 3958 | } | 3964 | } |
| 3959 | 3965 | ||
| ... | @@ -5249,6 +5255,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -5249,6 +5255,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5249 | .global = config, | 5255 | .global = config, |
| 5250 | .parent = null, | 5256 | .parent = null, |
| 5251 | .builtin_mod = null, | 5257 | .builtin_mod = null, |
| 5258 | .builtin_modules = null, // all modules will inherit this one's builtin | ||
| 5252 | }); | 5259 | }); |
| 5253 | 5260 | ||
| 5254 | const builtin_mod = root_mod.getBuiltinDependency(); | 5261 | const builtin_mod = root_mod.getBuiltinDependency(); |
| ... | @@ -5265,6 +5272,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -5265,6 +5272,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5265 | .global = config, | 5272 | .global = config, |
| 5266 | .parent = root_mod, | 5273 | .parent = root_mod, |
| 5267 | .builtin_mod = builtin_mod, | 5274 | .builtin_mod = builtin_mod, |
| 5275 | .builtin_modules = null, // `builtin_mod` is specified | ||
| 5268 | }); | 5276 | }); |
| 5269 | 5277 | ||
| 5270 | var cleanup_build_dir: ?fs.Dir = null; | 5278 | var cleanup_build_dir: ?fs.Dir = null; |
| ... | @@ -5399,6 +5407,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -5399,6 +5407,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5399 | .global = config, | 5407 | .global = config, |
| 5400 | .parent = root_mod, | 5408 | .parent = root_mod, |
| 5401 | .builtin_mod = builtin_mod, | 5409 | .builtin_mod = builtin_mod, |
| 5410 | .builtin_modules = null, // `builtin_mod` is specified | ||
| 5402 | }); | 5411 | }); |
| 5403 | const hash_cloned = try arena.dupe(u8, &hash); | 5412 | const hash_cloned = try arena.dupe(u8, &hash); |
| 5404 | deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m); | 5413 | deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m); |
| ... | @@ -5648,6 +5657,7 @@ fn jitCmd( | ... | @@ -5648,6 +5657,7 @@ fn jitCmd( |
| 5648 | .global = config, | 5657 | .global = config, |
| 5649 | .parent = null, | 5658 | .parent = null, |
| 5650 | .builtin_mod = null, | 5659 | .builtin_mod = null, |
| 5660 | .builtin_modules = null, // all modules will inherit this one's builtin | ||
| 5651 | }); | 5661 | }); |
| 5652 | 5662 | ||
| 5653 | if (options.depend_on_aro) { | 5663 | if (options.depend_on_aro) { |
| ... | @@ -5670,6 +5680,7 @@ fn jitCmd( | ... | @@ -5670,6 +5680,7 @@ fn jitCmd( |
| 5670 | .global = config, | 5680 | .global = config, |
| 5671 | .parent = null, | 5681 | .parent = null, |
| 5672 | .builtin_mod = root_mod.getBuiltinDependency(), | 5682 | .builtin_mod = root_mod.getBuiltinDependency(), |
| 5683 | .builtin_modules = null, // `builtin_mod` is specified | ||
| 5673 | }); | 5684 | }); |
| 5674 | try root_mod.deps.put(arena, "aro", aro_mod); | 5685 | try root_mod.deps.put(arena, "aro", aro_mod); |
| 5675 | } | 5686 | } |
| ... | @@ -7216,10 +7227,11 @@ fn createDependenciesModule( | ... | @@ -7216,10 +7227,11 @@ fn createDependenciesModule( |
| 7216 | }, | 7227 | }, |
| 7217 | .fully_qualified_name = "root.@dependencies", | 7228 | .fully_qualified_name = "root.@dependencies", |
| 7218 | .parent = main_mod, | 7229 | .parent = main_mod, |
| 7219 | .builtin_mod = builtin_mod, | ||
| 7220 | .cc_argv = &.{}, | 7230 | .cc_argv = &.{}, |
| 7221 | .inherited = .{}, | 7231 | .inherited = .{}, |
| 7222 | .global = global_options, | 7232 | .global = global_options, |
| 7233 | .builtin_mod = builtin_mod, | ||
| 7234 | .builtin_modules = null, // `builtin_mod` is specified | ||
| 7223 | }); | 7235 | }); |
| 7224 | try main_mod.deps.put(arena, "@dependencies", deps_mod); | 7236 | try main_mod.deps.put(arena, "@dependencies", deps_mod); |
| 7225 | return deps_mod; | 7237 | return deps_mod; |
src/musl.zig+1| ... | @@ -250,6 +250,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr | ... | @@ -250,6 +250,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr |
| 250 | .cc_argv = cc_argv, | 250 | .cc_argv = cc_argv, |
| 251 | .parent = null, | 251 | .parent = null, |
| 252 | .builtin_mod = null, | 252 | .builtin_mod = null, |
| 253 | .builtin_modules = null, // there is only one module in this compilation | ||
| 253 | }); | 254 | }); |
| 254 | 255 | ||
| 255 | const sub_compilation = try Compilation.create(comp.gpa, arena, .{ | 256 | const sub_compilation = try Compilation.create(comp.gpa, arena, .{ |
src/print_zir.zig+102-5| ... | @@ -282,7 +282,6 @@ const Writer = struct { | ... | @@ -282,7 +282,6 @@ const Writer = struct { |
| 282 | 282 | ||
| 283 | .ref, | 283 | .ref, |
| 284 | .ret_implicit, | 284 | .ret_implicit, |
| 285 | .closure_capture, | ||
| 286 | .validate_ref_ty, | 285 | .validate_ref_ty, |
| 287 | => try self.writeUnTok(stream, inst), | 286 | => try self.writeUnTok(stream, inst), |
| 288 | 287 | ||
| ... | @@ -510,8 +509,6 @@ const Writer = struct { | ... | @@ -510,8 +509,6 @@ const Writer = struct { |
| 510 | 509 | ||
| 511 | .dbg_stmt => try self.writeDbgStmt(stream, inst), | 510 | .dbg_stmt => try self.writeDbgStmt(stream, inst), |
| 512 | 511 | ||
| 513 | .closure_get => try self.writeInstNode(stream, inst), | ||
| 514 | |||
| 515 | .@"defer" => try self.writeDefer(stream, inst), | 512 | .@"defer" => try self.writeDefer(stream, inst), |
| 516 | .defer_err_code => try self.writeDeferErrCode(stream, inst), | 513 | .defer_err_code => try self.writeDeferErrCode(stream, inst), |
| 517 | 514 | ||
| ... | @@ -611,6 +608,7 @@ const Writer = struct { | ... | @@ -611,6 +608,7 @@ const Writer = struct { |
| 611 | .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended), | 608 | .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended), |
| 612 | 609 | ||
| 613 | .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended), | 610 | .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended), |
| 611 | .closure_get => try self.writeClosureGet(stream, extended), | ||
| 614 | } | 612 | } |
| 615 | } | 613 | } |
| 616 | 614 | ||
| ... | @@ -1401,6 +1399,12 @@ const Writer = struct { | ... | @@ -1401,6 +1399,12 @@ const Writer = struct { |
| 1401 | 1399 | ||
| 1402 | var extra_index: usize = extra.end; | 1400 | var extra_index: usize = extra.end; |
| 1403 | 1401 | ||
| 1402 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1403 | const captures_len = self.code.extra[extra_index]; | ||
| 1404 | extra_index += 1; | ||
| 1405 | break :blk captures_len; | ||
| 1406 | } else 0; | ||
| 1407 | |||
| 1404 | const fields_len = if (small.has_fields_len) blk: { | 1408 | const fields_len = if (small.has_fields_len) blk: { |
| 1405 | const fields_len = self.code.extra[extra_index]; | 1409 | const fields_len = self.code.extra[extra_index]; |
| 1406 | extra_index += 1; | 1410 | extra_index += 1; |
| ... | @@ -1419,12 +1423,26 @@ const Writer = struct { | ... | @@ -1419,12 +1423,26 @@ const Writer = struct { |
| 1419 | 1423 | ||
| 1420 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | 1424 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); |
| 1421 | 1425 | ||
| 1422 | if (small.layout == .Packed and small.has_backing_int) { | 1426 | if (captures_len == 0) { |
| 1427 | try stream.writeAll("{}, "); | ||
| 1428 | } else { | ||
| 1429 | try stream.writeAll("{ "); | ||
| 1430 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1431 | extra_index += 1; | ||
| 1432 | for (1..captures_len) |_| { | ||
| 1433 | try stream.writeAll(", "); | ||
| 1434 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1435 | extra_index += 1; | ||
| 1436 | } | ||
| 1437 | try stream.writeAll(" }, "); | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | if (small.has_backing_int) { | ||
| 1423 | const backing_int_body_len = self.code.extra[extra_index]; | 1441 | const backing_int_body_len = self.code.extra[extra_index]; |
| 1424 | extra_index += 1; | 1442 | extra_index += 1; |
| 1425 | try stream.writeAll("Packed("); | 1443 | try stream.writeAll("Packed("); |
| 1426 | if (backing_int_body_len == 0) { | 1444 | if (backing_int_body_len == 0) { |
| 1427 | const backing_int_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | 1445 | const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); |
| 1428 | extra_index += 1; | 1446 | extra_index += 1; |
| 1429 | try self.writeInstRef(stream, backing_int_ref); | 1447 | try self.writeInstRef(stream, backing_int_ref); |
| 1430 | } else { | 1448 | } else { |
| ... | @@ -1601,6 +1619,12 @@ const Writer = struct { | ... | @@ -1601,6 +1619,12 @@ const Writer = struct { |
| 1601 | break :blk tag_type_ref; | 1619 | break :blk tag_type_ref; |
| 1602 | } else .none; | 1620 | } else .none; |
| 1603 | 1621 | ||
| 1622 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1623 | const captures_len = self.code.extra[extra_index]; | ||
| 1624 | extra_index += 1; | ||
| 1625 | break :blk captures_len; | ||
| 1626 | } else 0; | ||
| 1627 | |||
| 1604 | const body_len = if (small.has_body_len) blk: { | 1628 | const body_len = if (small.has_body_len) blk: { |
| 1605 | const body_len = self.code.extra[extra_index]; | 1629 | const body_len = self.code.extra[extra_index]; |
| 1606 | extra_index += 1; | 1630 | extra_index += 1; |
| ... | @@ -1624,6 +1648,20 @@ const Writer = struct { | ... | @@ -1624,6 +1648,20 @@ const Writer = struct { |
| 1624 | }); | 1648 | }); |
| 1625 | try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag); | 1649 | try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag); |
| 1626 | 1650 | ||
| 1651 | if (captures_len == 0) { | ||
| 1652 | try stream.writeAll("{}, "); | ||
| 1653 | } else { | ||
| 1654 | try stream.writeAll("{ "); | ||
| 1655 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1656 | extra_index += 1; | ||
| 1657 | for (1..captures_len) |_| { | ||
| 1658 | try stream.writeAll(", "); | ||
| 1659 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1660 | extra_index += 1; | ||
| 1661 | } | ||
| 1662 | try stream.writeAll(" }, "); | ||
| 1663 | } | ||
| 1664 | |||
| 1627 | if (decls_len == 0) { | 1665 | if (decls_len == 0) { |
| 1628 | try stream.writeAll("{}"); | 1666 | try stream.writeAll("{}"); |
| 1629 | } else { | 1667 | } else { |
| ... | @@ -1748,6 +1786,12 @@ const Writer = struct { | ... | @@ -1748,6 +1786,12 @@ const Writer = struct { |
| 1748 | break :blk tag_type_ref; | 1786 | break :blk tag_type_ref; |
| 1749 | } else .none; | 1787 | } else .none; |
| 1750 | 1788 | ||
| 1789 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1790 | const captures_len = self.code.extra[extra_index]; | ||
| 1791 | extra_index += 1; | ||
| 1792 | break :blk captures_len; | ||
| 1793 | } else 0; | ||
| 1794 | |||
| 1751 | const body_len = if (small.has_body_len) blk: { | 1795 | const body_len = if (small.has_body_len) blk: { |
| 1752 | const body_len = self.code.extra[extra_index]; | 1796 | const body_len = self.code.extra[extra_index]; |
| 1753 | extra_index += 1; | 1797 | extra_index += 1; |
| ... | @@ -1769,6 +1813,20 @@ const Writer = struct { | ... | @@ -1769,6 +1813,20 @@ const Writer = struct { |
| 1769 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | 1813 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); |
| 1770 | try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive); | 1814 | try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive); |
| 1771 | 1815 | ||
| 1816 | if (captures_len == 0) { | ||
| 1817 | try stream.writeAll("{}, "); | ||
| 1818 | } else { | ||
| 1819 | try stream.writeAll("{ "); | ||
| 1820 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1821 | extra_index += 1; | ||
| 1822 | for (1..captures_len) |_| { | ||
| 1823 | try stream.writeAll(", "); | ||
| 1824 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1825 | extra_index += 1; | ||
| 1826 | } | ||
| 1827 | try stream.writeAll(" }, "); | ||
| 1828 | } | ||
| 1829 | |||
| 1772 | if (decls_len == 0) { | 1830 | if (decls_len == 0) { |
| 1773 | try stream.writeAll("{}, "); | 1831 | try stream.writeAll("{}, "); |
| 1774 | } else { | 1832 | } else { |
| ... | @@ -1854,6 +1912,12 @@ const Writer = struct { | ... | @@ -1854,6 +1912,12 @@ const Writer = struct { |
| 1854 | const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); | 1912 | const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); |
| 1855 | var extra_index: usize = extra.end; | 1913 | var extra_index: usize = extra.end; |
| 1856 | 1914 | ||
| 1915 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1916 | const captures_len = self.code.extra[extra_index]; | ||
| 1917 | extra_index += 1; | ||
| 1918 | break :blk captures_len; | ||
| 1919 | } else 0; | ||
| 1920 | |||
| 1857 | const decls_len = if (small.has_decls_len) blk: { | 1921 | const decls_len = if (small.has_decls_len) blk: { |
| 1858 | const decls_len = self.code.extra[extra_index]; | 1922 | const decls_len = self.code.extra[extra_index]; |
| 1859 | extra_index += 1; | 1923 | extra_index += 1; |
| ... | @@ -1862,6 +1926,20 @@ const Writer = struct { | ... | @@ -1862,6 +1926,20 @@ const Writer = struct { |
| 1862 | 1926 | ||
| 1863 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | 1927 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); |
| 1864 | 1928 | ||
| 1929 | if (captures_len == 0) { | ||
| 1930 | try stream.writeAll("{}, "); | ||
| 1931 | } else { | ||
| 1932 | try stream.writeAll("{ "); | ||
| 1933 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1934 | extra_index += 1; | ||
| 1935 | for (1..captures_len) |_| { | ||
| 1936 | try stream.writeAll(", "); | ||
| 1937 | try self.writeCapture(stream, @bitCast(self.code.extra[extra_index])); | ||
| 1938 | extra_index += 1; | ||
| 1939 | } | ||
| 1940 | try stream.writeAll(" }, "); | ||
| 1941 | } | ||
| 1942 | |||
| 1865 | if (decls_len == 0) { | 1943 | if (decls_len == 0) { |
| 1866 | try stream.writeAll("{})"); | 1944 | try stream.writeAll("{})"); |
| 1867 | } else { | 1945 | } else { |
| ... | @@ -2706,6 +2784,12 @@ const Writer = struct { | ... | @@ -2706,6 +2784,12 @@ const Writer = struct { |
| 2706 | try self.writeSrc(stream, inst_data.src()); | 2784 | try self.writeSrc(stream, inst_data.src()); |
| 2707 | } | 2785 | } |
| 2708 | 2786 | ||
| 2787 | fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | ||
| 2788 | const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand)); | ||
| 2789 | try stream.print("{d})) ", .{extended.small}); | ||
| 2790 | try self.writeSrc(stream, src); | ||
| 2791 | } | ||
| 2792 | |||
| 2709 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { | 2793 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { |
| 2710 | if (ref == .none) { | 2794 | if (ref == .none) { |
| 2711 | return stream.writeAll(".none"); | 2795 | return stream.writeAll(".none"); |
| ... | @@ -2722,6 +2806,19 @@ const Writer = struct { | ... | @@ -2722,6 +2806,19 @@ const Writer = struct { |
| 2722 | return stream.print("%{d}", .{@intFromEnum(inst)}); | 2806 | return stream.print("%{d}", .{@intFromEnum(inst)}); |
| 2723 | } | 2807 | } |
| 2724 | 2808 | ||
| 2809 | fn writeCapture(self: *Writer, stream: anytype, capture: Zir.Inst.Capture) !void { | ||
| 2810 | switch (capture.unwrap()) { | ||
| 2811 | .nested => |i| return stream.print("[{d}]", .{i}), | ||
| 2812 | .instruction => |inst| return self.writeInstIndex(stream, inst), | ||
| 2813 | .decl_val => |str| try stream.print("decl_val \"{}\"", .{ | ||
| 2814 | std.zig.fmtEscapes(self.code.nullTerminatedString(str)), | ||
| 2815 | }), | ||
| 2816 | .decl_ref => |str| try stream.print("decl_ref \"{}\"", .{ | ||
| 2817 | std.zig.fmtEscapes(self.code.nullTerminatedString(str)), | ||
| 2818 | }), | ||
| 2819 | } | ||
| 2820 | } | ||
| 2821 | |||
| 2725 | fn writeOptionalInstRef( | 2822 | fn writeOptionalInstRef( |
| 2726 | self: *Writer, | 2823 | self: *Writer, |
| 2727 | stream: anytype, | 2824 | stream: anytype, |
src/type.zig+204-178| ... | @@ -320,11 +320,12 @@ pub const Type = struct { | ... | @@ -320,11 +320,12 @@ pub const Type = struct { |
| 320 | 320 | ||
| 321 | .generic_poison => unreachable, | 321 | .generic_poison => unreachable, |
| 322 | }, | 322 | }, |
| 323 | .struct_type => |struct_type| { | 323 | .struct_type => { |
| 324 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 324 | if (struct_type.decl.unwrap()) |decl_index| { | 325 | if (struct_type.decl.unwrap()) |decl_index| { |
| 325 | const decl = mod.declPtr(decl_index); | 326 | const decl = mod.declPtr(decl_index); |
| 326 | try decl.renderFullyQualifiedName(mod, writer); | 327 | try decl.renderFullyQualifiedName(mod, writer); |
| 327 | } else if (struct_type.namespace.unwrap()) |namespace_index| { | 328 | } else if (ip.loadStructType(ty.toIntern()).namespace.unwrap()) |namespace_index| { |
| 328 | const namespace = mod.namespacePtr(namespace_index); | 329 | const namespace = mod.namespacePtr(namespace_index); |
| 329 | try namespace.renderFullyQualifiedName(mod, .empty, writer); | 330 | try namespace.renderFullyQualifiedName(mod, .empty, writer); |
| 330 | } else { | 331 | } else { |
| ... | @@ -354,16 +355,16 @@ pub const Type = struct { | ... | @@ -354,16 +355,16 @@ pub const Type = struct { |
| 354 | try writer.writeAll("}"); | 355 | try writer.writeAll("}"); |
| 355 | }, | 356 | }, |
| 356 | 357 | ||
| 357 | .union_type => |union_type| { | 358 | .union_type => { |
| 358 | const decl = mod.declPtr(union_type.decl); | 359 | const decl = mod.declPtr(ip.loadUnionType(ty.toIntern()).decl); |
| 359 | try decl.renderFullyQualifiedName(mod, writer); | 360 | try decl.renderFullyQualifiedName(mod, writer); |
| 360 | }, | 361 | }, |
| 361 | .opaque_type => |opaque_type| { | 362 | .opaque_type => { |
| 362 | const decl = mod.declPtr(opaque_type.decl); | 363 | const decl = mod.declPtr(ip.loadOpaqueType(ty.toIntern()).decl); |
| 363 | try decl.renderFullyQualifiedName(mod, writer); | 364 | try decl.renderFullyQualifiedName(mod, writer); |
| 364 | }, | 365 | }, |
| 365 | .enum_type => |enum_type| { | 366 | .enum_type => { |
| 366 | const decl = mod.declPtr(enum_type.decl); | 367 | const decl = mod.declPtr(ip.loadEnumType(ty.toIntern()).decl); |
| 367 | try decl.renderFullyQualifiedName(mod, writer); | 368 | try decl.renderFullyQualifiedName(mod, writer); |
| 368 | }, | 369 | }, |
| 369 | .func_type => |fn_info| { | 370 | .func_type => |fn_info| { |
| ... | @@ -573,7 +574,8 @@ pub const Type = struct { | ... | @@ -573,7 +574,8 @@ pub const Type = struct { |
| 573 | 574 | ||
| 574 | .generic_poison => unreachable, | 575 | .generic_poison => unreachable, |
| 575 | }, | 576 | }, |
| 576 | .struct_type => |struct_type| { | 577 | .struct_type => { |
| 578 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 577 | if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) { | 579 | if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) { |
| 578 | // In this case, we guess that hasRuntimeBits() for this type is true, | 580 | // In this case, we guess that hasRuntimeBits() for this type is true, |
| 579 | // and then later if our guess was incorrect, we emit a compile error. | 581 | // and then later if our guess was incorrect, we emit a compile error. |
| ... | @@ -601,7 +603,8 @@ pub const Type = struct { | ... | @@ -601,7 +603,8 @@ pub const Type = struct { |
| 601 | return false; | 603 | return false; |
| 602 | }, | 604 | }, |
| 603 | 605 | ||
| 604 | .union_type => |union_type| { | 606 | .union_type => { |
| 607 | const union_type = ip.loadUnionType(ty.toIntern()); | ||
| 605 | switch (union_type.flagsPtr(ip).runtime_tag) { | 608 | switch (union_type.flagsPtr(ip).runtime_tag) { |
| 606 | .none => { | 609 | .none => { |
| 607 | if (union_type.flagsPtr(ip).status == .field_types_wip) { | 610 | if (union_type.flagsPtr(ip).status == .field_types_wip) { |
| ... | @@ -628,9 +631,8 @@ pub const Type = struct { | ... | @@ -628,9 +631,8 @@ pub const Type = struct { |
| 628 | .lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes()) | 631 | .lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes()) |
| 629 | return error.NeedLazy, | 632 | return error.NeedLazy, |
| 630 | } | 633 | } |
| 631 | const union_obj = ip.loadUnionType(union_type); | 634 | for (0..union_type.field_types.len) |field_index| { |
| 632 | for (0..union_obj.field_types.len) |field_index| { | 635 | const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); |
| 633 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | ||
| 634 | if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | 636 | if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) |
| 635 | return true; | 637 | return true; |
| 636 | } else { | 638 | } else { |
| ... | @@ -639,7 +641,7 @@ pub const Type = struct { | ... | @@ -639,7 +641,7 @@ pub const Type = struct { |
| 639 | }, | 641 | }, |
| 640 | 642 | ||
| 641 | .opaque_type => true, | 643 | .opaque_type => true, |
| 642 | .enum_type => |enum_type| Type.fromInterned(enum_type.tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), | 644 | .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), |
| 643 | 645 | ||
| 644 | // values, not types | 646 | // values, not types |
| 645 | .undef, | 647 | .undef, |
| ... | @@ -736,15 +738,19 @@ pub const Type = struct { | ... | @@ -736,15 +738,19 @@ pub const Type = struct { |
| 736 | .generic_poison, | 738 | .generic_poison, |
| 737 | => false, | 739 | => false, |
| 738 | }, | 740 | }, |
| 739 | .struct_type => |struct_type| { | 741 | .struct_type => { |
| 742 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 740 | // Struct with no fields have a well-defined layout of no bits. | 743 | // Struct with no fields have a well-defined layout of no bits. |
| 741 | return struct_type.layout != .Auto or struct_type.field_types.len == 0; | 744 | return struct_type.layout != .Auto or struct_type.field_types.len == 0; |
| 742 | }, | 745 | }, |
| 743 | .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) { | 746 | .union_type => { |
| 744 | .none, .safety => union_type.flagsPtr(ip).layout != .Auto, | 747 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 745 | .tagged => false, | 748 | return switch (union_type.flagsPtr(ip).runtime_tag) { |
| 749 | .none, .safety => union_type.flagsPtr(ip).layout != .Auto, | ||
| 750 | .tagged => false, | ||
| 751 | }; | ||
| 746 | }, | 752 | }, |
| 747 | .enum_type => |enum_type| switch (enum_type.tag_mode) { | 753 | .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) { |
| 748 | .auto => false, | 754 | .auto => false, |
| 749 | .explicit, .nonexhaustive => true, | 755 | .explicit, .nonexhaustive => true, |
| 750 | }, | 756 | }, |
| ... | @@ -1019,7 +1025,8 @@ pub const Type = struct { | ... | @@ -1019,7 +1025,8 @@ pub const Type = struct { |
| 1019 | .noreturn => unreachable, | 1025 | .noreturn => unreachable, |
| 1020 | .generic_poison => unreachable, | 1026 | .generic_poison => unreachable, |
| 1021 | }, | 1027 | }, |
| 1022 | .struct_type => |struct_type| { | 1028 | .struct_type => { |
| 1029 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 1023 | if (struct_type.layout == .Packed) { | 1030 | if (struct_type.layout == .Packed) { |
| 1024 | switch (strat) { | 1031 | switch (strat) { |
| 1025 | .sema => |sema| try sema.resolveTypeLayout(ty), | 1032 | .sema => |sema| try sema.resolveTypeLayout(ty), |
| ... | @@ -1066,7 +1073,8 @@ pub const Type = struct { | ... | @@ -1066,7 +1073,8 @@ pub const Type = struct { |
| 1066 | } | 1073 | } |
| 1067 | return .{ .scalar = big_align }; | 1074 | return .{ .scalar = big_align }; |
| 1068 | }, | 1075 | }, |
| 1069 | .union_type => |union_type| { | 1076 | .union_type => { |
| 1077 | const union_type = ip.loadUnionType(ty.toIntern()); | ||
| 1070 | const flags = union_type.flagsPtr(ip).*; | 1078 | const flags = union_type.flagsPtr(ip).*; |
| 1071 | if (flags.alignment != .none) return .{ .scalar = flags.alignment }; | 1079 | if (flags.alignment != .none) return .{ .scalar = flags.alignment }; |
| 1072 | 1080 | ||
| ... | @@ -1082,8 +1090,8 @@ pub const Type = struct { | ... | @@ -1082,8 +1090,8 @@ pub const Type = struct { |
| 1082 | return .{ .scalar = union_type.flagsPtr(ip).alignment }; | 1090 | return .{ .scalar = union_type.flagsPtr(ip).alignment }; |
| 1083 | }, | 1091 | }, |
| 1084 | .opaque_type => return .{ .scalar = .@"1" }, | 1092 | .opaque_type => return .{ .scalar = .@"1" }, |
| 1085 | .enum_type => |enum_type| return .{ | 1093 | .enum_type => return .{ |
| 1086 | .scalar = Type.fromInterned(enum_type.tag_ty).abiAlignment(mod), | 1094 | .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(mod), |
| 1087 | }, | 1095 | }, |
| 1088 | 1096 | ||
| 1089 | // values, not types | 1097 | // values, not types |
| ... | @@ -1394,7 +1402,8 @@ pub const Type = struct { | ... | @@ -1394,7 +1402,8 @@ pub const Type = struct { |
| 1394 | .noreturn => unreachable, | 1402 | .noreturn => unreachable, |
| 1395 | .generic_poison => unreachable, | 1403 | .generic_poison => unreachable, |
| 1396 | }, | 1404 | }, |
| 1397 | .struct_type => |struct_type| { | 1405 | .struct_type => { |
| 1406 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 1398 | switch (strat) { | 1407 | switch (strat) { |
| 1399 | .sema => |sema| try sema.resolveTypeLayout(ty), | 1408 | .sema => |sema| try sema.resolveTypeLayout(ty), |
| 1400 | .lazy => switch (struct_type.layout) { | 1409 | .lazy => switch (struct_type.layout) { |
| ... | @@ -1439,7 +1448,8 @@ pub const Type = struct { | ... | @@ -1439,7 +1448,8 @@ pub const Type = struct { |
| 1439 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; | 1448 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; |
| 1440 | }, | 1449 | }, |
| 1441 | 1450 | ||
| 1442 | .union_type => |union_type| { | 1451 | .union_type => { |
| 1452 | const union_type = ip.loadUnionType(ty.toIntern()); | ||
| 1443 | switch (strat) { | 1453 | switch (strat) { |
| 1444 | .sema => |sema| try sema.resolveTypeLayout(ty), | 1454 | .sema => |sema| try sema.resolveTypeLayout(ty), |
| 1445 | .lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{ | 1455 | .lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{ |
| ... | @@ -1455,7 +1465,7 @@ pub const Type = struct { | ... | @@ -1455,7 +1465,7 @@ pub const Type = struct { |
| 1455 | return .{ .scalar = union_type.size(ip).* }; | 1465 | return .{ .scalar = union_type.size(ip).* }; |
| 1456 | }, | 1466 | }, |
| 1457 | .opaque_type => unreachable, // no size available | 1467 | .opaque_type => unreachable, // no size available |
| 1458 | .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = Type.fromInterned(enum_type.tag_ty).abiSize(mod) }, | 1468 | .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(mod) }, |
| 1459 | 1469 | ||
| 1460 | // values, not types | 1470 | // values, not types |
| 1461 | .undef, | 1471 | .undef, |
| ... | @@ -1644,7 +1654,8 @@ pub const Type = struct { | ... | @@ -1644,7 +1654,8 @@ pub const Type = struct { |
| 1644 | .extern_options => unreachable, | 1654 | .extern_options => unreachable, |
| 1645 | .type_info => unreachable, | 1655 | .type_info => unreachable, |
| 1646 | }, | 1656 | }, |
| 1647 | .struct_type => |struct_type| { | 1657 | .struct_type => { |
| 1658 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 1648 | const is_packed = struct_type.layout == .Packed; | 1659 | const is_packed = struct_type.layout == .Packed; |
| 1649 | if (opt_sema) |sema| { | 1660 | if (opt_sema) |sema| { |
| 1650 | try sema.resolveTypeFields(ty); | 1661 | try sema.resolveTypeFields(ty); |
| ... | @@ -1661,7 +1672,8 @@ pub const Type = struct { | ... | @@ -1661,7 +1672,8 @@ pub const Type = struct { |
| 1661 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | 1672 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; |
| 1662 | }, | 1673 | }, |
| 1663 | 1674 | ||
| 1664 | .union_type => |union_type| { | 1675 | .union_type => { |
| 1676 | const union_type = ip.loadUnionType(ty.toIntern()); | ||
| 1665 | const is_packed = ty.containerLayout(mod) == .Packed; | 1677 | const is_packed = ty.containerLayout(mod) == .Packed; |
| 1666 | if (opt_sema) |sema| { | 1678 | if (opt_sema) |sema| { |
| 1667 | try sema.resolveTypeFields(ty); | 1679 | try sema.resolveTypeFields(ty); |
| ... | @@ -1670,19 +1682,18 @@ pub const Type = struct { | ... | @@ -1670,19 +1682,18 @@ pub const Type = struct { |
| 1670 | if (!is_packed) { | 1682 | if (!is_packed) { |
| 1671 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | 1683 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; |
| 1672 | } | 1684 | } |
| 1673 | const union_obj = ip.loadUnionType(union_type); | 1685 | assert(union_type.flagsPtr(ip).status.haveFieldTypes()); |
| 1674 | assert(union_obj.flagsPtr(ip).status.haveFieldTypes()); | ||
| 1675 | 1686 | ||
| 1676 | var size: u64 = 0; | 1687 | var size: u64 = 0; |
| 1677 | for (0..union_obj.field_types.len) |field_index| { | 1688 | for (0..union_type.field_types.len) |field_index| { |
| 1678 | const field_ty = union_obj.field_types.get(ip)[field_index]; | 1689 | const field_ty = union_type.field_types.get(ip)[field_index]; |
| 1679 | size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, opt_sema)); | 1690 | size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, opt_sema)); |
| 1680 | } | 1691 | } |
| 1681 | 1692 | ||
| 1682 | return size; | 1693 | return size; |
| 1683 | }, | 1694 | }, |
| 1684 | .opaque_type => unreachable, | 1695 | .opaque_type => unreachable, |
| 1685 | .enum_type => |enum_type| return bitSizeAdvanced(Type.fromInterned(enum_type.tag_ty), mod, opt_sema), | 1696 | .enum_type => return bitSizeAdvanced(Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), mod, opt_sema), |
| 1686 | 1697 | ||
| 1687 | // values, not types | 1698 | // values, not types |
| 1688 | .undef, | 1699 | .undef, |
| ... | @@ -1713,8 +1724,8 @@ pub const Type = struct { | ... | @@ -1713,8 +1724,8 @@ pub const Type = struct { |
| 1713 | pub fn layoutIsResolved(ty: Type, mod: *Module) bool { | 1724 | pub fn layoutIsResolved(ty: Type, mod: *Module) bool { |
| 1714 | const ip = &mod.intern_pool; | 1725 | const ip = &mod.intern_pool; |
| 1715 | return switch (ip.indexToKey(ty.toIntern())) { | 1726 | return switch (ip.indexToKey(ty.toIntern())) { |
| 1716 | .struct_type => |struct_type| struct_type.haveLayout(ip), | 1727 | .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip), |
| 1717 | .union_type => |union_type| union_type.haveLayout(ip), | 1728 | .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip), |
| 1718 | .array_type => |array_type| { | 1729 | .array_type => |array_type| { |
| 1719 | if ((array_type.len + @intFromBool(array_type.sentinel != .none)) == 0) return true; | 1730 | if ((array_type.len + @intFromBool(array_type.sentinel != .none)) == 0) return true; |
| 1720 | return Type.fromInterned(array_type.child).layoutIsResolved(mod); | 1731 | return Type.fromInterned(array_type.child).layoutIsResolved(mod); |
| ... | @@ -1914,16 +1925,18 @@ pub const Type = struct { | ... | @@ -1914,16 +1925,18 @@ pub const Type = struct { |
| 1914 | /// Otherwise, returns `null`. | 1925 | /// Otherwise, returns `null`. |
| 1915 | pub fn unionTagType(ty: Type, mod: *Module) ?Type { | 1926 | pub fn unionTagType(ty: Type, mod: *Module) ?Type { |
| 1916 | const ip = &mod.intern_pool; | 1927 | const ip = &mod.intern_pool; |
| 1917 | return switch (ip.indexToKey(ty.toIntern())) { | 1928 | switch (ip.indexToKey(ty.toIntern())) { |
| 1918 | .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) { | 1929 | .union_type => {}, |
| 1919 | .tagged => { | 1930 | else => return null, |
| 1920 | assert(union_type.flagsPtr(ip).status.haveFieldTypes()); | 1931 | } |
| 1921 | return Type.fromInterned(union_type.enum_tag_ty); | 1932 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 1922 | }, | 1933 | switch (union_type.flagsPtr(ip).runtime_tag) { |
| 1923 | else => null, | 1934 | .tagged => { |
| 1935 | assert(union_type.flagsPtr(ip).status.haveFieldTypes()); | ||
| 1936 | return Type.fromInterned(union_type.enum_tag_ty); | ||
| 1924 | }, | 1937 | }, |
| 1925 | else => null, | 1938 | else => return null, |
| 1926 | }; | 1939 | } |
| 1927 | } | 1940 | } |
| 1928 | 1941 | ||
| 1929 | /// Same as `unionTagType` but includes safety tag. | 1942 | /// Same as `unionTagType` but includes safety tag. |
| ... | @@ -1931,7 +1944,8 @@ pub const Type = struct { | ... | @@ -1931,7 +1944,8 @@ pub const Type = struct { |
| 1931 | pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type { | 1944 | pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type { |
| 1932 | const ip = &mod.intern_pool; | 1945 | const ip = &mod.intern_pool; |
| 1933 | return switch (ip.indexToKey(ty.toIntern())) { | 1946 | return switch (ip.indexToKey(ty.toIntern())) { |
| 1934 | .union_type => |union_type| { | 1947 | .union_type => { |
| 1948 | const union_type = ip.loadUnionType(ty.toIntern()); | ||
| 1935 | if (!union_type.hasTag(ip)) return null; | 1949 | if (!union_type.hasTag(ip)) return null; |
| 1936 | assert(union_type.haveFieldTypes(ip)); | 1950 | assert(union_type.haveFieldTypes(ip)); |
| 1937 | return Type.fromInterned(union_type.enum_tag_ty); | 1951 | return Type.fromInterned(union_type.enum_tag_ty); |
| ... | @@ -1981,17 +1995,16 @@ pub const Type = struct { | ... | @@ -1981,17 +1995,16 @@ pub const Type = struct { |
| 1981 | 1995 | ||
| 1982 | pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout { | 1996 | pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout { |
| 1983 | const ip = &mod.intern_pool; | 1997 | const ip = &mod.intern_pool; |
| 1984 | const union_type = ip.indexToKey(ty.toIntern()).union_type; | 1998 | const union_obj = ip.loadUnionType(ty.toIntern()); |
| 1985 | const union_obj = ip.loadUnionType(union_type); | ||
| 1986 | return mod.getUnionLayout(union_obj); | 1999 | return mod.getUnionLayout(union_obj); |
| 1987 | } | 2000 | } |
| 1988 | 2001 | ||
| 1989 | pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout { | 2002 | pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout { |
| 1990 | const ip = &mod.intern_pool; | 2003 | const ip = &mod.intern_pool; |
| 1991 | return switch (ip.indexToKey(ty.toIntern())) { | 2004 | return switch (ip.indexToKey(ty.toIntern())) { |
| 1992 | .struct_type => |struct_type| struct_type.layout, | 2005 | .struct_type => ip.loadStructType(ty.toIntern()).layout, |
| 1993 | .anon_struct_type => .Auto, | 2006 | .anon_struct_type => .Auto, |
| 1994 | .union_type => |union_type| union_type.flagsPtr(ip).layout, | 2007 | .union_type => ip.loadUnionType(ty.toIntern()).flagsPtr(ip).layout, |
| 1995 | else => unreachable, | 2008 | else => unreachable, |
| 1996 | }; | 2009 | }; |
| 1997 | } | 2010 | } |
| ... | @@ -2095,22 +2108,15 @@ pub const Type = struct { | ... | @@ -2095,22 +2108,15 @@ pub const Type = struct { |
| 2095 | 2108 | ||
| 2096 | /// Asserts the type is an array or vector or struct. | 2109 | /// Asserts the type is an array or vector or struct. |
| 2097 | pub fn arrayLen(ty: Type, mod: *const Module) u64 { | 2110 | pub fn arrayLen(ty: Type, mod: *const Module) u64 { |
| 2098 | return arrayLenIp(ty, &mod.intern_pool); | 2111 | return ty.arrayLenIp(&mod.intern_pool); |
| 2099 | } | 2112 | } |
| 2100 | 2113 | ||
| 2101 | pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 { | 2114 | pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 { |
| 2102 | return switch (ip.indexToKey(ty.toIntern())) { | 2115 | return ip.aggregateTypeLen(ty.toIntern()); |
| 2103 | .vector_type => |vector_type| vector_type.len, | ||
| 2104 | .array_type => |array_type| array_type.len, | ||
| 2105 | .struct_type => |struct_type| struct_type.field_types.len, | ||
| 2106 | .anon_struct_type => |tuple| tuple.types.len, | ||
| 2107 | |||
| 2108 | else => unreachable, | ||
| 2109 | }; | ||
| 2110 | } | 2116 | } |
| 2111 | 2117 | ||
| 2112 | pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 { | 2118 | pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 { |
| 2113 | return ty.arrayLen(mod) + @intFromBool(ty.sentinel(mod) != null); | 2119 | return mod.intern_pool.aggregateTypeLenIncludingSentinel(ty.toIntern()); |
| 2114 | } | 2120 | } |
| 2115 | 2121 | ||
| 2116 | pub fn vectorLen(ty: Type, mod: *const Module) u32 { | 2122 | pub fn vectorLen(ty: Type, mod: *const Module) u32 { |
| ... | @@ -2199,8 +2205,8 @@ pub const Type = struct { | ... | @@ -2199,8 +2205,8 @@ pub const Type = struct { |
| 2199 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) }, | 2205 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) }, |
| 2200 | else => switch (ip.indexToKey(ty.toIntern())) { | 2206 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 2201 | .int_type => |int_type| return int_type, | 2207 | .int_type => |int_type| return int_type, |
| 2202 | .struct_type => |t| ty = Type.fromInterned(t.backingIntType(ip).*), | 2208 | .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntType(ip).*), |
| 2203 | .enum_type => |enum_type| ty = Type.fromInterned(enum_type.tag_ty), | 2209 | .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), |
| 2204 | .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child), | 2210 | .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child), |
| 2205 | 2211 | ||
| 2206 | .error_set_type, .inferred_error_set_type => { | 2212 | .error_set_type, .inferred_error_set_type => { |
| ... | @@ -2463,7 +2469,8 @@ pub const Type = struct { | ... | @@ -2463,7 +2469,8 @@ pub const Type = struct { |
| 2463 | 2469 | ||
| 2464 | .generic_poison => unreachable, | 2470 | .generic_poison => unreachable, |
| 2465 | }, | 2471 | }, |
| 2466 | .struct_type => |struct_type| { | 2472 | .struct_type => { |
| 2473 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 2467 | assert(struct_type.haveFieldTypes(ip)); | 2474 | assert(struct_type.haveFieldTypes(ip)); |
| 2468 | if (struct_type.knownNonOpv(ip)) | 2475 | if (struct_type.knownNonOpv(ip)) |
| 2469 | return null; | 2476 | return null; |
| ... | @@ -2505,11 +2512,11 @@ pub const Type = struct { | ... | @@ -2505,11 +2512,11 @@ pub const Type = struct { |
| 2505 | } }))); | 2512 | } }))); |
| 2506 | }, | 2513 | }, |
| 2507 | 2514 | ||
| 2508 | .union_type => |union_type| { | 2515 | .union_type => { |
| 2509 | const union_obj = ip.loadUnionType(union_type); | 2516 | const union_obj = ip.loadUnionType(ty.toIntern()); |
| 2510 | const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse | 2517 | const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse |
| 2511 | return null; | 2518 | return null; |
| 2512 | if (union_obj.field_names.len == 0) { | 2519 | if (union_obj.field_types.len == 0) { |
| 2513 | const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); | 2520 | const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); |
| 2514 | return Value.fromInterned(only); | 2521 | return Value.fromInterned(only); |
| 2515 | } | 2522 | } |
| ... | @@ -2524,45 +2531,48 @@ pub const Type = struct { | ... | @@ -2524,45 +2531,48 @@ pub const Type = struct { |
| 2524 | return Value.fromInterned(only); | 2531 | return Value.fromInterned(only); |
| 2525 | }, | 2532 | }, |
| 2526 | .opaque_type => return null, | 2533 | .opaque_type => return null, |
| 2527 | .enum_type => |enum_type| switch (enum_type.tag_mode) { | 2534 | .enum_type => { |
| 2528 | .nonexhaustive => { | 2535 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 2529 | if (enum_type.tag_ty == .comptime_int_type) return null; | 2536 | switch (enum_type.tag_mode) { |
| 2530 | 2537 | .nonexhaustive => { | |
| 2531 | if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| { | 2538 | if (enum_type.tag_ty == .comptime_int_type) return null; |
| 2532 | const only = try mod.intern(.{ .enum_tag = .{ | 2539 | |
| 2533 | .ty = ty.toIntern(), | 2540 | if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| { |
| 2534 | .int = int_opv.toIntern(), | 2541 | const only = try mod.intern(.{ .enum_tag = .{ |
| 2535 | } }); | 2542 | .ty = ty.toIntern(), |
| 2536 | return Value.fromInterned(only); | 2543 | .int = int_opv.toIntern(), |
| 2537 | } | 2544 | } }); |
| 2545 | return Value.fromInterned(only); | ||
| 2546 | } | ||
| 2538 | 2547 | ||
| 2539 | return null; | 2548 | return null; |
| 2540 | }, | 2549 | }, |
| 2541 | .auto, .explicit => { | 2550 | .auto, .explicit => { |
| 2542 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null; | 2551 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null; |
| 2543 | 2552 | ||
| 2544 | switch (enum_type.names.len) { | 2553 | switch (enum_type.names.len) { |
| 2545 | 0 => { | 2554 | 0 => { |
| 2546 | const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); | 2555 | const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); |
| 2547 | return Value.fromInterned(only); | ||
| 2548 | }, | ||
| 2549 | 1 => { | ||
| 2550 | if (enum_type.values.len == 0) { | ||
| 2551 | const only = try mod.intern(.{ .enum_tag = .{ | ||
| 2552 | .ty = ty.toIntern(), | ||
| 2553 | .int = try mod.intern(.{ .int = .{ | ||
| 2554 | .ty = enum_type.tag_ty, | ||
| 2555 | .storage = .{ .u64 = 0 }, | ||
| 2556 | } }), | ||
| 2557 | } }); | ||
| 2558 | return Value.fromInterned(only); | 2556 | return Value.fromInterned(only); |
| 2559 | } else { | 2557 | }, |
| 2560 | return Value.fromInterned(enum_type.values.get(ip)[0]); | 2558 | 1 => { |
| 2561 | } | 2559 | if (enum_type.values.len == 0) { |
| 2562 | }, | 2560 | const only = try mod.intern(.{ .enum_tag = .{ |
| 2563 | else => return null, | 2561 | .ty = ty.toIntern(), |
| 2564 | } | 2562 | .int = try mod.intern(.{ .int = .{ |
| 2565 | }, | 2563 | .ty = enum_type.tag_ty, |
| 2564 | .storage = .{ .u64 = 0 }, | ||
| 2565 | } }), | ||
| 2566 | } }); | ||
| 2567 | return Value.fromInterned(only); | ||
| 2568 | } else { | ||
| 2569 | return Value.fromInterned(enum_type.values.get(ip)[0]); | ||
| 2570 | } | ||
| 2571 | }, | ||
| 2572 | else => return null, | ||
| 2573 | } | ||
| 2574 | }, | ||
| 2575 | } | ||
| 2566 | }, | 2576 | }, |
| 2567 | 2577 | ||
| 2568 | // values, not types | 2578 | // values, not types |
| ... | @@ -2676,7 +2686,8 @@ pub const Type = struct { | ... | @@ -2676,7 +2686,8 @@ pub const Type = struct { |
| 2676 | .type_info, | 2686 | .type_info, |
| 2677 | => true, | 2687 | => true, |
| 2678 | }, | 2688 | }, |
| 2679 | .struct_type => |struct_type| { | 2689 | .struct_type => { |
| 2690 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 2680 | // packed structs cannot be comptime-only because they have a well-defined | 2691 | // packed structs cannot be comptime-only because they have a well-defined |
| 2681 | // memory layout and every field has a well-defined bit pattern. | 2692 | // memory layout and every field has a well-defined bit pattern. |
| 2682 | if (struct_type.layout == .Packed) | 2693 | if (struct_type.layout == .Packed) |
| ... | @@ -2726,38 +2737,40 @@ pub const Type = struct { | ... | @@ -2726,38 +2737,40 @@ pub const Type = struct { |
| 2726 | return false; | 2737 | return false; |
| 2727 | }, | 2738 | }, |
| 2728 | 2739 | ||
| 2729 | .union_type => |union_type| switch (union_type.flagsPtr(ip).requires_comptime) { | 2740 | .union_type => { |
| 2730 | .no, .wip => false, | 2741 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 2731 | .yes => true, | 2742 | switch (union_type.flagsPtr(ip).requires_comptime) { |
| 2732 | .unknown => { | 2743 | .no, .wip => return false, |
| 2733 | // The type is not resolved; assert that we have a Sema. | 2744 | .yes => return true, |
| 2734 | const sema = opt_sema.?; | 2745 | .unknown => { |
| 2746 | // The type is not resolved; assert that we have a Sema. | ||
| 2747 | const sema = opt_sema.?; | ||
| 2735 | 2748 | ||
| 2736 | if (union_type.flagsPtr(ip).status == .field_types_wip) | 2749 | if (union_type.flagsPtr(ip).status == .field_types_wip) |
| 2737 | return false; | 2750 | return false; |
| 2738 | 2751 | ||
| 2739 | union_type.flagsPtr(ip).requires_comptime = .wip; | 2752 | union_type.flagsPtr(ip).requires_comptime = .wip; |
| 2740 | errdefer union_type.flagsPtr(ip).requires_comptime = .unknown; | 2753 | errdefer union_type.flagsPtr(ip).requires_comptime = .unknown; |
| 2741 | 2754 | ||
| 2742 | try sema.resolveTypeFieldsUnion(ty, union_type); | 2755 | try sema.resolveTypeFieldsUnion(ty, union_type); |
| 2743 | 2756 | ||
| 2744 | const union_obj = ip.loadUnionType(union_type); | 2757 | for (0..union_type.field_types.len) |field_idx| { |
| 2745 | for (0..union_obj.field_types.len) |field_idx| { | 2758 | const field_ty = union_type.field_types.get(ip)[field_idx]; |
| 2746 | const field_ty = union_obj.field_types.get(ip)[field_idx]; | 2759 | if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) { |
| 2747 | if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) { | 2760 | union_type.flagsPtr(ip).requires_comptime = .yes; |
| 2748 | union_obj.flagsPtr(ip).requires_comptime = .yes; | 2761 | return true; |
| 2749 | return true; | 2762 | } |
| 2750 | } | 2763 | } |
| 2751 | } | ||
| 2752 | 2764 | ||
| 2753 | union_obj.flagsPtr(ip).requires_comptime = .no; | 2765 | union_type.flagsPtr(ip).requires_comptime = .no; |
| 2754 | return false; | 2766 | return false; |
| 2755 | }, | 2767 | }, |
| 2768 | } | ||
| 2756 | }, | 2769 | }, |
| 2757 | 2770 | ||
| 2758 | .opaque_type => false, | 2771 | .opaque_type => false, |
| 2759 | 2772 | ||
| 2760 | .enum_type => |enum_type| return Type.fromInterned(enum_type.tag_ty).comptimeOnlyAdvanced(mod, opt_sema), | 2773 | .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyAdvanced(mod, opt_sema), |
| 2761 | 2774 | ||
| 2762 | // values, not types | 2775 | // values, not types |
| 2763 | .undef, | 2776 | .undef, |
| ... | @@ -2830,11 +2843,12 @@ pub const Type = struct { | ... | @@ -2830,11 +2843,12 @@ pub const Type = struct { |
| 2830 | 2843 | ||
| 2831 | /// Returns null if the type has no namespace. | 2844 | /// Returns null if the type has no namespace. |
| 2832 | pub fn getNamespaceIndex(ty: Type, mod: *Module) InternPool.OptionalNamespaceIndex { | 2845 | pub fn getNamespaceIndex(ty: Type, mod: *Module) InternPool.OptionalNamespaceIndex { |
| 2833 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2846 | const ip = &mod.intern_pool; |
| 2834 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), | 2847 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2835 | .struct_type => |struct_type| struct_type.namespace, | 2848 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace, |
| 2836 | .union_type => |union_type| union_type.namespace.toOptional(), | 2849 | .struct_type => ip.loadStructType(ty.toIntern()).namespace, |
| 2837 | .enum_type => |enum_type| enum_type.namespace, | 2850 | .union_type => ip.loadUnionType(ty.toIntern()).namespace, |
| 2851 | .enum_type => ip.loadEnumType(ty.toIntern()).namespace, | ||
| 2838 | 2852 | ||
| 2839 | else => .none, | 2853 | else => .none, |
| 2840 | }; | 2854 | }; |
| ... | @@ -2920,16 +2934,18 @@ pub const Type = struct { | ... | @@ -2920,16 +2934,18 @@ pub const Type = struct { |
| 2920 | 2934 | ||
| 2921 | /// Asserts the type is an enum or a union. | 2935 | /// Asserts the type is an enum or a union. |
| 2922 | pub fn intTagType(ty: Type, mod: *Module) Type { | 2936 | pub fn intTagType(ty: Type, mod: *Module) Type { |
| 2923 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2937 | const ip = &mod.intern_pool; |
| 2924 | .union_type => |union_type| Type.fromInterned(union_type.enum_tag_ty).intTagType(mod), | 2938 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2925 | .enum_type => |enum_type| Type.fromInterned(enum_type.tag_ty), | 2939 | .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(mod), |
| 2940 | .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), | ||
| 2926 | else => unreachable, | 2941 | else => unreachable, |
| 2927 | }; | 2942 | }; |
| 2928 | } | 2943 | } |
| 2929 | 2944 | ||
| 2930 | pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool { | 2945 | pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool { |
| 2931 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2946 | const ip = &mod.intern_pool; |
| 2932 | .enum_type => |enum_type| switch (enum_type.tag_mode) { | 2947 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2948 | .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) { | ||
| 2933 | .nonexhaustive => true, | 2949 | .nonexhaustive => true, |
| 2934 | .auto, .explicit => false, | 2950 | .auto, .explicit => false, |
| 2935 | }, | 2951 | }, |
| ... | @@ -2953,21 +2969,21 @@ pub const Type = struct { | ... | @@ -2953,21 +2969,21 @@ pub const Type = struct { |
| 2953 | } | 2969 | } |
| 2954 | 2970 | ||
| 2955 | pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice { | 2971 | pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice { |
| 2956 | return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names; | 2972 | return mod.intern_pool.loadEnumType(ty.toIntern()).names; |
| 2957 | } | 2973 | } |
| 2958 | 2974 | ||
| 2959 | pub fn enumFieldCount(ty: Type, mod: *Module) usize { | 2975 | pub fn enumFieldCount(ty: Type, mod: *Module) usize { |
| 2960 | return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names.len; | 2976 | return mod.intern_pool.loadEnumType(ty.toIntern()).names.len; |
| 2961 | } | 2977 | } |
| 2962 | 2978 | ||
| 2963 | pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString { | 2979 | pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString { |
| 2964 | const ip = &mod.intern_pool; | 2980 | const ip = &mod.intern_pool; |
| 2965 | return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip)[field_index]; | 2981 | return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index]; |
| 2966 | } | 2982 | } |
| 2967 | 2983 | ||
| 2968 | pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 { | 2984 | pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 { |
| 2969 | const ip = &mod.intern_pool; | 2985 | const ip = &mod.intern_pool; |
| 2970 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 2986 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 2971 | return enum_type.nameIndex(ip, field_name); | 2987 | return enum_type.nameIndex(ip, field_name); |
| 2972 | } | 2988 | } |
| 2973 | 2989 | ||
| ... | @@ -2976,7 +2992,7 @@ pub const Type = struct { | ... | @@ -2976,7 +2992,7 @@ pub const Type = struct { |
| 2976 | /// declaration order, or `null` if `enum_tag` does not match any field. | 2992 | /// declaration order, or `null` if `enum_tag` does not match any field. |
| 2977 | pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 { | 2993 | pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 { |
| 2978 | const ip = &mod.intern_pool; | 2994 | const ip = &mod.intern_pool; |
| 2979 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 2995 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 2980 | const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) { | 2996 | const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) { |
| 2981 | .int => enum_tag.toIntern(), | 2997 | .int => enum_tag.toIntern(), |
| 2982 | .enum_tag => |info| info.int, | 2998 | .enum_tag => |info| info.int, |
| ... | @@ -2990,7 +3006,7 @@ pub const Type = struct { | ... | @@ -2990,7 +3006,7 @@ pub const Type = struct { |
| 2990 | pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString { | 3006 | pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString { |
| 2991 | const ip = &mod.intern_pool; | 3007 | const ip = &mod.intern_pool; |
| 2992 | return switch (ip.indexToKey(ty.toIntern())) { | 3008 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2993 | .struct_type => |struct_type| struct_type.fieldName(ip, field_index), | 3009 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, field_index), |
| 2994 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index), | 3010 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index), |
| 2995 | else => unreachable, | 3011 | else => unreachable, |
| 2996 | }; | 3012 | }; |
| ... | @@ -3010,7 +3026,7 @@ pub const Type = struct { | ... | @@ -3010,7 +3026,7 @@ pub const Type = struct { |
| 3010 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { | 3026 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { |
| 3011 | const ip = &mod.intern_pool; | 3027 | const ip = &mod.intern_pool; |
| 3012 | return switch (ip.indexToKey(ty.toIntern())) { | 3028 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3013 | .struct_type => |struct_type| struct_type.field_types.len, | 3029 | .struct_type => ip.loadStructType(ty.toIntern()).field_types.len, |
| 3014 | .anon_struct_type => |anon_struct| anon_struct.types.len, | 3030 | .anon_struct_type => |anon_struct| anon_struct.types.len, |
| 3015 | else => unreachable, | 3031 | else => unreachable, |
| 3016 | }; | 3032 | }; |
| ... | @@ -3020,9 +3036,9 @@ pub const Type = struct { | ... | @@ -3020,9 +3036,9 @@ pub const Type = struct { |
| 3020 | pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type { | 3036 | pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type { |
| 3021 | const ip = &mod.intern_pool; | 3037 | const ip = &mod.intern_pool; |
| 3022 | return switch (ip.indexToKey(ty.toIntern())) { | 3038 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3023 | .struct_type => |struct_type| Type.fromInterned(struct_type.field_types.get(ip)[index]), | 3039 | .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]), |
| 3024 | .union_type => |union_type| { | 3040 | .union_type => { |
| 3025 | const union_obj = ip.loadUnionType(union_type); | 3041 | const union_obj = ip.loadUnionType(ty.toIntern()); |
| 3026 | return Type.fromInterned(union_obj.field_types.get(ip)[index]); | 3042 | return Type.fromInterned(union_obj.field_types.get(ip)[index]); |
| 3027 | }, | 3043 | }, |
| 3028 | .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]), | 3044 | .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]), |
| ... | @@ -3033,7 +3049,8 @@ pub const Type = struct { | ... | @@ -3033,7 +3049,8 @@ pub const Type = struct { |
| 3033 | pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) Alignment { | 3049 | pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) Alignment { |
| 3034 | const ip = &mod.intern_pool; | 3050 | const ip = &mod.intern_pool; |
| 3035 | switch (ip.indexToKey(ty.toIntern())) { | 3051 | switch (ip.indexToKey(ty.toIntern())) { |
| 3036 | .struct_type => |struct_type| { | 3052 | .struct_type => { |
| 3053 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 3037 | assert(struct_type.layout != .Packed); | 3054 | assert(struct_type.layout != .Packed); |
| 3038 | const explicit_align = struct_type.fieldAlign(ip, index); | 3055 | const explicit_align = struct_type.fieldAlign(ip, index); |
| 3039 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]); | 3056 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]); |
| ... | @@ -3042,8 +3059,8 @@ pub const Type = struct { | ... | @@ -3042,8 +3059,8 @@ pub const Type = struct { |
| 3042 | .anon_struct_type => |anon_struct| { | 3059 | .anon_struct_type => |anon_struct| { |
| 3043 | return Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignment(mod); | 3060 | return Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignment(mod); |
| 3044 | }, | 3061 | }, |
| 3045 | .union_type => |union_type| { | 3062 | .union_type => { |
| 3046 | const union_obj = ip.loadUnionType(union_type); | 3063 | const union_obj = ip.loadUnionType(ty.toIntern()); |
| 3047 | return mod.unionFieldNormalAlignment(union_obj, @intCast(index)); | 3064 | return mod.unionFieldNormalAlignment(union_obj, @intCast(index)); |
| 3048 | }, | 3065 | }, |
| 3049 | else => unreachable, | 3066 | else => unreachable, |
| ... | @@ -3053,7 +3070,8 @@ pub const Type = struct { | ... | @@ -3053,7 +3070,8 @@ pub const Type = struct { |
| 3053 | pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value { | 3070 | pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value { |
| 3054 | const ip = &mod.intern_pool; | 3071 | const ip = &mod.intern_pool; |
| 3055 | switch (ip.indexToKey(ty.toIntern())) { | 3072 | switch (ip.indexToKey(ty.toIntern())) { |
| 3056 | .struct_type => |struct_type| { | 3073 | .struct_type => { |
| 3074 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 3057 | const val = struct_type.fieldInit(ip, index); | 3075 | const val = struct_type.fieldInit(ip, index); |
| 3058 | // TODO: avoid using `unreachable` to indicate this. | 3076 | // TODO: avoid using `unreachable` to indicate this. |
| 3059 | if (val == .none) return Value.@"unreachable"; | 3077 | if (val == .none) return Value.@"unreachable"; |
| ... | @@ -3072,7 +3090,8 @@ pub const Type = struct { | ... | @@ -3072,7 +3090,8 @@ pub const Type = struct { |
| 3072 | pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value { | 3090 | pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value { |
| 3073 | const ip = &mod.intern_pool; | 3091 | const ip = &mod.intern_pool; |
| 3074 | switch (ip.indexToKey(ty.toIntern())) { | 3092 | switch (ip.indexToKey(ty.toIntern())) { |
| 3075 | .struct_type => |struct_type| { | 3093 | .struct_type => { |
| 3094 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 3076 | if (struct_type.fieldIsComptime(ip, index)) { | 3095 | if (struct_type.fieldIsComptime(ip, index)) { |
| 3077 | assert(struct_type.haveFieldInits(ip)); | 3096 | assert(struct_type.haveFieldInits(ip)); |
| 3078 | return Value.fromInterned(struct_type.field_inits.get(ip)[index]); | 3097 | return Value.fromInterned(struct_type.field_inits.get(ip)[index]); |
| ... | @@ -3095,7 +3114,7 @@ pub const Type = struct { | ... | @@ -3095,7 +3114,7 @@ pub const Type = struct { |
| 3095 | pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool { | 3114 | pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool { |
| 3096 | const ip = &mod.intern_pool; | 3115 | const ip = &mod.intern_pool; |
| 3097 | return switch (ip.indexToKey(ty.toIntern())) { | 3116 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3098 | .struct_type => |struct_type| struct_type.fieldIsComptime(ip, index), | 3117 | .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index), |
| 3099 | .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none, | 3118 | .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none, |
| 3100 | else => unreachable, | 3119 | else => unreachable, |
| 3101 | }; | 3120 | }; |
| ... | @@ -3110,7 +3129,8 @@ pub const Type = struct { | ... | @@ -3110,7 +3129,8 @@ pub const Type = struct { |
| 3110 | pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 { | 3129 | pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 { |
| 3111 | const ip = &mod.intern_pool; | 3130 | const ip = &mod.intern_pool; |
| 3112 | switch (ip.indexToKey(ty.toIntern())) { | 3131 | switch (ip.indexToKey(ty.toIntern())) { |
| 3113 | .struct_type => |struct_type| { | 3132 | .struct_type => { |
| 3133 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 3114 | assert(struct_type.haveLayout(ip)); | 3134 | assert(struct_type.haveLayout(ip)); |
| 3115 | assert(struct_type.layout != .Packed); | 3135 | assert(struct_type.layout != .Packed); |
| 3116 | return struct_type.offsets.get(ip)[index]; | 3136 | return struct_type.offsets.get(ip)[index]; |
| ... | @@ -3137,11 +3157,11 @@ pub const Type = struct { | ... | @@ -3137,11 +3157,11 @@ pub const Type = struct { |
| 3137 | return offset; | 3157 | return offset; |
| 3138 | }, | 3158 | }, |
| 3139 | 3159 | ||
| 3140 | .union_type => |union_type| { | 3160 | .union_type => { |
| 3161 | const union_type = ip.loadUnionType(ty.toIntern()); | ||
| 3141 | if (!union_type.hasTag(ip)) | 3162 | if (!union_type.hasTag(ip)) |
| 3142 | return 0; | 3163 | return 0; |
| 3143 | const union_obj = ip.loadUnionType(union_type); | 3164 | const layout = mod.getUnionLayout(union_type); |
| 3144 | const layout = mod.getUnionLayout(union_obj); | ||
| 3145 | if (layout.tag_align.compare(.gte, layout.payload_align)) { | 3165 | if (layout.tag_align.compare(.gte, layout.payload_align)) { |
| 3146 | // {Tag, Payload} | 3166 | // {Tag, Payload} |
| 3147 | return layout.payload_align.forward(layout.tag_size); | 3167 | return layout.payload_align.forward(layout.tag_size); |
| ... | @@ -3160,17 +3180,8 @@ pub const Type = struct { | ... | @@ -3160,17 +3180,8 @@ pub const Type = struct { |
| 3160 | } | 3180 | } |
| 3161 | 3181 | ||
| 3162 | pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { | 3182 | pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { |
| 3163 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 3183 | const decl = ty.getOwnerDeclOrNull(mod) orelse return null; |
| 3164 | .struct_type => |struct_type| { | 3184 | return mod.declPtr(decl).srcLoc(mod); |
| 3165 | return mod.declPtr(struct_type.decl.unwrap() orelse return null).srcLoc(mod); | ||
| 3166 | }, | ||
| 3167 | .union_type => |union_type| { | ||
| 3168 | return mod.declPtr(union_type.decl).srcLoc(mod); | ||
| 3169 | }, | ||
| 3170 | .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type), | ||
| 3171 | .enum_type => |enum_type| mod.declPtr(enum_type.decl).srcLoc(mod), | ||
| 3172 | else => null, | ||
| 3173 | }; | ||
| 3174 | } | 3185 | } |
| 3175 | 3186 | ||
| 3176 | pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex { | 3187 | pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex { |
| ... | @@ -3178,11 +3189,12 @@ pub const Type = struct { | ... | @@ -3178,11 +3189,12 @@ pub const Type = struct { |
| 3178 | } | 3189 | } |
| 3179 | 3190 | ||
| 3180 | pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?InternPool.DeclIndex { | 3191 | pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?InternPool.DeclIndex { |
| 3181 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 3192 | const ip = &mod.intern_pool; |
| 3182 | .struct_type => |struct_type| struct_type.decl.unwrap(), | 3193 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3183 | .union_type => |union_type| union_type.decl, | 3194 | .struct_type => ip.loadStructType(ty.toIntern()).decl.unwrap(), |
| 3184 | .opaque_type => |opaque_type| opaque_type.decl, | 3195 | .union_type => ip.loadUnionType(ty.toIntern()).decl, |
| 3185 | .enum_type => |enum_type| enum_type.decl, | 3196 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).decl, |
| 3197 | .enum_type => ip.loadEnumType(ty.toIntern()).decl, | ||
| 3186 | else => null, | 3198 | else => null, |
| 3187 | }; | 3199 | }; |
| 3188 | } | 3200 | } |
| ... | @@ -3194,7 +3206,8 @@ pub const Type = struct { | ... | @@ -3194,7 +3206,8 @@ pub const Type = struct { |
| 3194 | pub fn isTuple(ty: Type, mod: *Module) bool { | 3206 | pub fn isTuple(ty: Type, mod: *Module) bool { |
| 3195 | const ip = &mod.intern_pool; | 3207 | const ip = &mod.intern_pool; |
| 3196 | return switch (ip.indexToKey(ty.toIntern())) { | 3208 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3197 | .struct_type => |struct_type| { | 3209 | .struct_type => { |
| 3210 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 3198 | if (struct_type.layout == .Packed) return false; | 3211 | if (struct_type.layout == .Packed) return false; |
| 3199 | if (struct_type.decl == .none) return false; | 3212 | if (struct_type.decl == .none) return false; |
| 3200 | return struct_type.flagsPtr(ip).is_tuple; | 3213 | return struct_type.flagsPtr(ip).is_tuple; |
| ... | @@ -3215,7 +3228,8 @@ pub const Type = struct { | ... | @@ -3215,7 +3228,8 @@ pub const Type = struct { |
| 3215 | pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool { | 3228 | pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool { |
| 3216 | const ip = &mod.intern_pool; | 3229 | const ip = &mod.intern_pool; |
| 3217 | return switch (ip.indexToKey(ty.toIntern())) { | 3230 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3218 | .struct_type => |struct_type| { | 3231 | .struct_type => { |
| 3232 | const struct_type = ip.loadStructType(ty.toIntern()); | ||
| 3219 | if (struct_type.layout == .Packed) return false; | 3233 | if (struct_type.layout == .Packed) return false; |
| 3220 | if (struct_type.decl == .none) return false; | 3234 | if (struct_type.decl == .none) return false; |
| 3221 | return struct_type.flagsPtr(ip).is_tuple; | 3235 | return struct_type.flagsPtr(ip).is_tuple; |
| ... | @@ -3262,16 +3276,28 @@ pub const Type = struct { | ... | @@ -3262,16 +3276,28 @@ pub const Type = struct { |
| 3262 | } | 3276 | } |
| 3263 | 3277 | ||
| 3264 | pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index { | 3278 | pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index { |
| 3265 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | 3279 | const ip = &zcu.intern_pool; |
| 3266 | inline .struct_type, | 3280 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3267 | .union_type, | 3281 | .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(), |
| 3268 | .enum_type, | 3282 | .union_type => ip.loadUnionType(ty.toIntern()).zir_index, |
| 3269 | .opaque_type, | 3283 | .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(), |
| 3270 | => |info| info.zir_index.unwrap(), | 3284 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index, |
| 3271 | else => null, | 3285 | else => null, |
| 3272 | }; | 3286 | }; |
| 3273 | } | 3287 | } |
| 3274 | 3288 | ||
| 3289 | /// Given a namespace type, returns its list of caotured values. | ||
| 3290 | pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice { | ||
| 3291 | const ip = &zcu.intern_pool; | ||
| 3292 | return switch (ip.indexToKey(ty.toIntern())) { | ||
| 3293 | .struct_type => ip.loadStructType(ty.toIntern()).captures, | ||
| 3294 | .union_type => ip.loadUnionType(ty.toIntern()).captures, | ||
| 3295 | .enum_type => ip.loadEnumType(ty.toIntern()).captures, | ||
| 3296 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).captures, | ||
| 3297 | else => unreachable, | ||
| 3298 | }; | ||
| 3299 | } | ||
| 3300 | |||
| 3275 | pub const @"u1": Type = .{ .ip_index = .u1_type }; | 3301 | pub const @"u1": Type = .{ .ip_index = .u1_type }; |
| 3276 | pub const @"u8": Type = .{ .ip_index = .u8_type }; | 3302 | pub const @"u8": Type = .{ .ip_index = .u8_type }; |
| 3277 | pub const @"u16": Type = .{ .ip_index = .u16_type }; | 3303 | pub const @"u16": Type = .{ .ip_index = .u16_type }; |
test/behavior/enum.zig+21| ... | @@ -1242,3 +1242,24 @@ test "Non-exhaustive enum backed by comptime_int" { | ... | @@ -1242,3 +1242,24 @@ test "Non-exhaustive enum backed by comptime_int" { |
| 1242 | e = @as(E, @enumFromInt(378089457309184723749)); | 1242 | e = @as(E, @enumFromInt(378089457309184723749)); |
| 1243 | try expect(@intFromEnum(e) == 378089457309184723749); | 1243 | try expect(@intFromEnum(e) == 378089457309184723749); |
| 1244 | } | 1244 | } |
| 1245 | |||
| 1246 | test "matching captures causes enum equivalence" { | ||
| 1247 | const S = struct { | ||
| 1248 | fn Nonexhaustive(comptime I: type) type { | ||
| 1249 | const UTag = @Type(.{ .Int = .{ | ||
| 1250 | .signedness = .unsigned, | ||
| 1251 | .bits = @typeInfo(I).Int.bits, | ||
| 1252 | } }); | ||
| 1253 | return enum(UTag) { _ }; | ||
| 1254 | } | ||
| 1255 | }; | ||
| 1256 | |||
| 1257 | comptime assert(S.Nonexhaustive(u8) == S.Nonexhaustive(i8)); | ||
| 1258 | comptime assert(S.Nonexhaustive(u16) == S.Nonexhaustive(i16)); | ||
| 1259 | comptime assert(S.Nonexhaustive(u8) != S.Nonexhaustive(u16)); | ||
| 1260 | |||
| 1261 | const a: S.Nonexhaustive(u8) = @enumFromInt(123); | ||
| 1262 | const b: S.Nonexhaustive(i8) = @enumFromInt(123); | ||
| 1263 | comptime assert(@TypeOf(a) == @TypeOf(b)); | ||
| 1264 | try expect(@intFromEnum(a) == @intFromEnum(b)); | ||
| 1265 | } |
test/behavior/generics.zig+6-2| ... | @@ -371,8 +371,12 @@ test "extern function used as generic parameter" { | ... | @@ -371,8 +371,12 @@ test "extern function used as generic parameter" { |
| 371 | const S = struct { | 371 | const S = struct { |
| 372 | extern fn usedAsGenericParameterFoo() void; | 372 | extern fn usedAsGenericParameterFoo() void; |
| 373 | extern fn usedAsGenericParameterBar() void; | 373 | extern fn usedAsGenericParameterBar() void; |
| 374 | inline fn usedAsGenericParameterBaz(comptime _: anytype) type { | 374 | inline fn usedAsGenericParameterBaz(comptime token: anytype) type { |
| 375 | return struct {}; | 375 | return struct { |
| 376 | comptime { | ||
| 377 | _ = token; | ||
| 378 | } | ||
| 379 | }; | ||
| 376 | } | 380 | } |
| 377 | }; | 381 | }; |
| 378 | try expect(S.usedAsGenericParameterBaz(S.usedAsGenericParameterFoo) != | 382 | try expect(S.usedAsGenericParameterBaz(S.usedAsGenericParameterFoo) != |
test/behavior/src.zig+6-2| ... | @@ -23,8 +23,12 @@ test "@src" { | ... | @@ -23,8 +23,12 @@ test "@src" { |
| 23 | 23 | ||
| 24 | test "@src used as a comptime parameter" { | 24 | test "@src used as a comptime parameter" { |
| 25 | const S = struct { | 25 | const S = struct { |
| 26 | fn Foo(comptime _: std.builtin.SourceLocation) type { | 26 | fn Foo(comptime src: std.builtin.SourceLocation) type { |
| 27 | return struct {}; | 27 | return struct { |
| 28 | comptime { | ||
| 29 | _ = src; | ||
| 30 | } | ||
| 31 | }; | ||
| 28 | } | 32 | } |
| 29 | }; | 33 | }; |
| 30 | const T1 = S.Foo(@src()); | 34 | const T1 = S.Foo(@src()); |
test/behavior/struct.zig+23| ... | @@ -2127,3 +2127,26 @@ test "struct containing optional pointer to array of @This()" { | ... | @@ -2127,3 +2127,26 @@ test "struct containing optional pointer to array of @This()" { |
| 2127 | _ = &s; | 2127 | _ = &s; |
| 2128 | try expect(s.x.?[0].x == null); | 2128 | try expect(s.x.?[0].x == null); |
| 2129 | } | 2129 | } |
| 2130 | |||
| 2131 | test "matching captures causes struct equivalence" { | ||
| 2132 | const S = struct { | ||
| 2133 | fn UnsignedWrapper(comptime I: type) type { | ||
| 2134 | const bits = @typeInfo(I).Int.bits; | ||
| 2135 | return struct { | ||
| 2136 | x: @Type(.{ .Int = .{ | ||
| 2137 | .signedness = .unsigned, | ||
| 2138 | .bits = bits, | ||
| 2139 | } }), | ||
| 2140 | }; | ||
| 2141 | } | ||
| 2142 | }; | ||
| 2143 | |||
| 2144 | comptime assert(S.UnsignedWrapper(u8) == S.UnsignedWrapper(i8)); | ||
| 2145 | comptime assert(S.UnsignedWrapper(u16) == S.UnsignedWrapper(i16)); | ||
| 2146 | comptime assert(S.UnsignedWrapper(u8) != S.UnsignedWrapper(u16)); | ||
| 2147 | |||
| 2148 | const a: S.UnsignedWrapper(u8) = .{ .x = 10 }; | ||
| 2149 | const b: S.UnsignedWrapper(i8) = .{ .x = 10 }; | ||
| 2150 | comptime assert(@TypeOf(a) == @TypeOf(b)); | ||
| 2151 | try expect(a.x == b.x); | ||
| 2152 | } |
test/behavior/type.zig+26| ... | @@ -2,6 +2,7 @@ const std = @import("std"); | ... | @@ -2,6 +2,7 @@ const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const Type = std.builtin.Type; | 3 | const Type = std.builtin.Type; |
| 4 | const testing = std.testing; | 4 | const testing = std.testing; |
| 5 | const assert = std.debug.assert; | ||
| 5 | 6 | ||
| 6 | fn testTypes(comptime types: []const type) !void { | 7 | fn testTypes(comptime types: []const type) !void { |
| 7 | inline for (types) |testType| { | 8 | inline for (types) |testType| { |
| ... | @@ -734,3 +735,28 @@ test "struct field names sliced at comptime from larger string" { | ... | @@ -734,3 +735,28 @@ test "struct field names sliced at comptime from larger string" { |
| 734 | try testing.expectEqualStrings("f3", gen_fields[2].name); | 735 | try testing.expectEqualStrings("f3", gen_fields[2].name); |
| 735 | } | 736 | } |
| 736 | } | 737 | } |
| 738 | |||
| 739 | test "matching captures causes opaque equivalence" { | ||
| 740 | const S = struct { | ||
| 741 | fn UnsignedId(comptime I: type) type { | ||
| 742 | const U = @Type(.{ .Int = .{ | ||
| 743 | .signedness = .unsigned, | ||
| 744 | .bits = @typeInfo(I).Int.bits, | ||
| 745 | } }); | ||
| 746 | return opaque { | ||
| 747 | fn id(x: U) U { | ||
| 748 | return x; | ||
| 749 | } | ||
| 750 | }; | ||
| 751 | } | ||
| 752 | }; | ||
| 753 | |||
| 754 | comptime assert(S.UnsignedId(u8) == S.UnsignedId(i8)); | ||
| 755 | comptime assert(S.UnsignedId(u16) == S.UnsignedId(i16)); | ||
| 756 | comptime assert(S.UnsignedId(u8) != S.UnsignedId(u16)); | ||
| 757 | |||
| 758 | const a = S.UnsignedId(u8).id(123); | ||
| 759 | const b = S.UnsignedId(i8).id(123); | ||
| 760 | comptime assert(@TypeOf(a) == @TypeOf(b)); | ||
| 761 | try testing.expect(a == b); | ||
| 762 | } |
test/behavior/typename.zig+18-9| ... | @@ -164,21 +164,30 @@ test "fn param" { | ... | @@ -164,21 +164,30 @@ test "fn param" { |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | fn TypeFromFn(comptime T: type) type { | 166 | fn TypeFromFn(comptime T: type) type { |
| 167 | _ = T; | 167 | return struct { |
| 168 | return struct {}; | 168 | comptime { |
| 169 | _ = T; | ||
| 170 | } | ||
| 171 | }; | ||
| 169 | } | 172 | } |
| 170 | 173 | ||
| 171 | fn TypeFromFn2(comptime T1: type, comptime T2: type) type { | 174 | fn TypeFromFn2(comptime T1: type, comptime T2: type) type { |
| 172 | _ = T1; | 175 | return struct { |
| 173 | _ = T2; | 176 | comptime { |
| 174 | return struct {}; | 177 | _ = T1; |
| 178 | _ = T2; | ||
| 179 | } | ||
| 180 | }; | ||
| 175 | } | 181 | } |
| 176 | 182 | ||
| 177 | fn TypeFromFnB(comptime T1: type, comptime T2: type, comptime T3: type) type { | 183 | fn TypeFromFnB(comptime T1: type, comptime T2: type, comptime T3: type) type { |
| 178 | _ = T1; | 184 | return struct { |
| 179 | _ = T2; | 185 | comptime { |
| 180 | _ = T3; | 186 | _ = T1; |
| 181 | return struct {}; | 187 | _ = T2; |
| 188 | _ = T3; | ||
| 189 | } | ||
| 190 | }; | ||
| 182 | } | 191 | } |
| 183 | 192 | ||
| 184 | /// Replaces integers in `actual` with '0' before doing the test. | 193 | /// Replaces integers in `actual` with '0' before doing the test. |
test/behavior/union.zig+27| ... | @@ -2273,3 +2273,30 @@ test "create union(enum) from other union(enum)" { | ... | @@ -2273,3 +2273,30 @@ test "create union(enum) from other union(enum)" { |
| 2273 | else => {}, | 2273 | else => {}, |
| 2274 | } | 2274 | } |
| 2275 | } | 2275 | } |
| 2276 | |||
| 2277 | test "matching captures causes union equivalence" { | ||
| 2278 | const S = struct { | ||
| 2279 | fn SignedUnsigned(comptime I: type) type { | ||
| 2280 | const bits = @typeInfo(I).Int.bits; | ||
| 2281 | return union { | ||
| 2282 | u: @Type(.{ .Int = .{ | ||
| 2283 | .signedness = .unsigned, | ||
| 2284 | .bits = bits, | ||
| 2285 | } }), | ||
| 2286 | i: @Type(.{ .Int = .{ | ||
| 2287 | .signedness = .signed, | ||
| 2288 | .bits = bits, | ||
| 2289 | } }), | ||
| 2290 | }; | ||
| 2291 | } | ||
| 2292 | }; | ||
| 2293 | |||
| 2294 | comptime assert(S.SignedUnsigned(u8) == S.SignedUnsigned(i8)); | ||
| 2295 | comptime assert(S.SignedUnsigned(u16) == S.SignedUnsigned(i16)); | ||
| 2296 | comptime assert(S.SignedUnsigned(u8) != S.SignedUnsigned(u16)); | ||
| 2297 | |||
| 2298 | const a: S.SignedUnsigned(u8) = .{ .u = 10 }; | ||
| 2299 | const b: S.SignedUnsigned(i8) = .{ .u = 10 }; | ||
| 2300 | comptime assert(@TypeOf(a) == @TypeOf(b)); | ||
| 2301 | try expect(a.u == b.u); | ||
| 2302 | } |
test/cases/compile_errors/reify_struct.zig+1-1| ... | @@ -74,7 +74,7 @@ comptime { | ... | @@ -74,7 +74,7 @@ comptime { |
| 74 | // target=native | 74 | // target=native |
| 75 | // | 75 | // |
| 76 | // :2:5: error: tuple cannot have non-numeric field 'foo' | 76 | // :2:5: error: tuple cannot have non-numeric field 'foo' |
| 77 | // :16:5: error: tuple field 3 exceeds tuple field count | 77 | // :16:5: error: tuple field name '3' does not match field index 0 |
| 78 | // :30:5: error: comptime field without default initialization value | 78 | // :30:5: error: comptime field without default initialization value |
| 79 | // :44:5: error: extern struct fields cannot be marked comptime | 79 | // :44:5: error: extern struct fields cannot be marked comptime |
| 80 | // :58:5: error: alignment in a packed struct field must be set to 0 | 80 | // :58:5: error: alignment in a packed struct field must be set to 0 |
test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig+1-1| ... | @@ -30,6 +30,6 @@ export fn entry() void { | ... | @@ -30,6 +30,6 @@ export fn entry() void { |
| 30 | // backend=stage2 | 30 | // backend=stage2 |
| 31 | // target=native | 31 | // target=native |
| 32 | // | 32 | // |
| 33 | // :13:16: error: enum field(s) missing in union | 33 | // :13:16: error: enum fields missing in union |
| 34 | // :1:13: note: field 'arst' missing, declared here | 34 | // :1:13: note: field 'arst' missing, declared here |
| 35 | // :1:13: note: enum declared here | 35 | // :1:13: note: enum declared here |
test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig+1-1| ... | @@ -26,7 +26,7 @@ export fn entry() void { | ... | @@ -26,7 +26,7 @@ export fn entry() void { |
| 26 | // backend=stage2 | 26 | // backend=stage2 |
| 27 | // target=native | 27 | // target=native |
| 28 | // | 28 | // |
| 29 | // :12:16: error: enum field(s) missing in union | 29 | // :12:16: error: enum fields missing in union |
| 30 | // :1:13: note: field 'signed' missing, declared here | 30 | // :1:13: note: field 'signed' missing, declared here |
| 31 | // :1:13: note: field 'unsigned' missing, declared here | 31 | // :1:13: note: field 'unsigned' missing, declared here |
| 32 | // :1:13: note: enum declared here | 32 | // :1:13: note: enum declared here |