| ... | ... | @@ -1136,7 +1136,7 @@ pub const Key = union(enum) { |
| 1136 | 1136 | var a_ty_info = ip.indexToFuncType(a_info.ty).?; |
| 1137 | 1137 | a_ty_info.return_type = ip.errorUnionPayload(a_ty_info.return_type); |
| 1138 | 1138 | var b_ty_info = ip.indexToFuncType(b_info.ty).?; |
| 1139 | | b_ty_info.return_type = ip.errorUnionPayload(a_ty_info.return_type); |
| 1139 | b_ty_info.return_type = ip.errorUnionPayload(b_ty_info.return_type); |
| 1140 | 1140 | return a_ty_info.eql(b_ty_info, ip); |
| 1141 | 1141 | }, |
| 1142 | 1142 | |
| ... | ... | @@ -4657,7 +4657,12 @@ pub fn getErrorSetType( |
| 4657 | 4657 | } |
| 4658 | 4658 | |
| 4659 | 4659 | pub const GetFuncInstanceKey = struct { |
| 4660 | /// Has the length of the instance function (may be lesser than |
| 4661 | /// comptime_args). |
| 4660 | 4662 | param_types: []Index, |
| 4663 | /// Has the length of generic_owner's parameters (may be greater than |
| 4664 | /// param_types). |
| 4665 | comptime_args: []const Index, |
| 4661 | 4666 | noalias_bits: u32, |
| 4662 | 4667 | bare_return_type: Index, |
| 4663 | 4668 | cc: std.builtin.CallingConvention, |
| ... | ... | @@ -4665,12 +4670,12 @@ pub const GetFuncInstanceKey = struct { |
| 4665 | 4670 | is_noinline: bool, |
| 4666 | 4671 | generic_owner: Index, |
| 4667 | 4672 | inferred_error_set: bool, |
| 4668 | | comptime_args: []const Index, |
| 4669 | 4673 | generation: u32, |
| 4670 | 4674 | }; |
| 4671 | 4675 | |
| 4672 | 4676 | pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index { |
| 4673 | | if (arg.inferred_error_set) @panic("TODO"); |
| 4677 | if (arg.inferred_error_set) |
| 4678 | return getFuncInstanceIes(ip, gpa, arg); |
| 4674 | 4679 | |
| 4675 | 4680 | const func_ty = try ip.getFuncType(gpa, .{ |
| 4676 | 4681 | .param_types = arg.param_types, |
| ... | ... | @@ -4693,7 +4698,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4693 | 4698 | const prev_extra_len = ip.extra.items.len; |
| 4694 | 4699 | errdefer ip.extra.items.len = prev_extra_len; |
| 4695 | 4700 | |
| 4696 | | const func_instance_extra_index = ip.addExtraAssumeCapacity(Tag.FuncInstance{ |
| 4701 | const func_extra_index = ip.addExtraAssumeCapacity(Tag.FuncInstance{ |
| 4697 | 4702 | .analysis = .{ |
| 4698 | 4703 | .state = if (arg.cc == .Inline) .inline_only else .none, |
| 4699 | 4704 | .is_cold = false, |
| ... | ... | @@ -4712,7 +4717,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4712 | 4717 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args)); |
| 4713 | 4718 | |
| 4714 | 4719 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ |
| 4715 | | .func = extraFuncInstance(ip, func_instance_extra_index), |
| 4720 | .func = extraFuncInstance(ip, func_extra_index), |
| 4716 | 4721 | }, KeyAdapter{ .intern_pool = ip }); |
| 4717 | 4722 | errdefer _ = ip.map.pop(); |
| 4718 | 4723 | |
| ... | ... | @@ -4721,10 +4726,164 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4721 | 4726 | return @enumFromInt(gop.index); |
| 4722 | 4727 | } |
| 4723 | 4728 | |
| 4724 | | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 4725 | 4729 | const func_index: Index = @enumFromInt(ip.items.len); |
| 4726 | 4730 | |
| 4727 | | const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(arg.generic_owner)); |
| 4731 | try ip.items.append(gpa, .{ |
| 4732 | .tag = .func_instance, |
| 4733 | .data = func_extra_index, |
| 4734 | }); |
| 4735 | errdefer ip.items.len -= 1; |
| 4736 | |
| 4737 | return finishFuncInstance( |
| 4738 | ip, |
| 4739 | gpa, |
| 4740 | arg.generic_owner, |
| 4741 | func_index, |
| 4742 | func_extra_index, |
| 4743 | arg.generation, |
| 4744 | func_ty, |
| 4745 | ); |
| 4746 | } |
| 4747 | |
| 4748 | /// This function exists separately than `getFuncInstance` because it needs to |
| 4749 | /// create 4 new items in the InternPool atomically before it can look for an |
| 4750 | /// existing item in the map. |
| 4751 | pub fn getFuncInstanceIes( |
| 4752 | ip: *InternPool, |
| 4753 | gpa: Allocator, |
| 4754 | arg: GetFuncInstanceKey, |
| 4755 | ) Allocator.Error!Index { |
| 4756 | // Validate input parameters. |
| 4757 | assert(arg.inferred_error_set); |
| 4758 | assert(arg.bare_return_type != .none); |
| 4759 | for (arg.param_types) |param_type| assert(param_type != .none); |
| 4760 | |
| 4761 | // The strategy here is to add the function decl unconditionally, then to |
| 4762 | // ask if it already exists, and if so, revert the lengths of the mutated |
| 4763 | // arrays. This is similar to what `getOrPutTrailingString` does. |
| 4764 | const prev_extra_len = ip.extra.items.len; |
| 4765 | const params_len: u32 = @intCast(arg.param_types.len); |
| 4766 | |
| 4767 | try ip.map.ensureUnusedCapacity(gpa, 4); |
| 4768 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncInstance).Struct.fields.len + |
| 4769 | 1 + // inferred_error_set |
| 4770 | arg.comptime_args.len + |
| 4771 | @typeInfo(Tag.ErrorUnionType).Struct.fields.len + |
| 4772 | @typeInfo(Tag.TypeFunction).Struct.fields.len + |
| 4773 | @intFromBool(arg.noalias_bits != 0) + |
| 4774 | params_len); |
| 4775 | try ip.items.ensureUnusedCapacity(gpa, 4); |
| 4776 | |
| 4777 | const func_index: Index = @enumFromInt(ip.items.len); |
| 4778 | const error_union_type: Index = @enumFromInt(ip.items.len + 1); |
| 4779 | const error_set_type: Index = @enumFromInt(ip.items.len + 2); |
| 4780 | const func_ty: Index = @enumFromInt(ip.items.len + 3); |
| 4781 | |
| 4782 | const func_extra_index = ip.addExtraAssumeCapacity(Tag.FuncInstance{ |
| 4783 | .analysis = .{ |
| 4784 | .state = if (arg.cc == .Inline) .inline_only else .none, |
| 4785 | .is_cold = false, |
| 4786 | .is_noinline = arg.is_noinline, |
| 4787 | .calls_or_awaits_errorable_fn = false, |
| 4788 | .stack_alignment = .none, |
| 4789 | .inferred_error_set = true, |
| 4790 | }, |
| 4791 | // This is populated after we create the Decl below. It is not read |
| 4792 | // by equality or hashing functions. |
| 4793 | .owner_decl = undefined, |
| 4794 | .ty = func_ty, |
| 4795 | .branch_quota = 0, |
| 4796 | .generic_owner = arg.generic_owner, |
| 4797 | }); |
| 4798 | ip.extra.appendAssumeCapacity(@intFromEnum(Index.none)); // resolved error set |
| 4799 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args)); |
| 4800 | |
| 4801 | const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{ |
| 4802 | .params_len = params_len, |
| 4803 | .return_type = error_union_type, |
| 4804 | .flags = .{ |
| 4805 | .alignment = arg.alignment, |
| 4806 | .cc = arg.cc, |
| 4807 | .is_var_args = false, |
| 4808 | .has_comptime_bits = false, |
| 4809 | .has_noalias_bits = arg.noalias_bits != 0, |
| 4810 | .is_generic = false, |
| 4811 | .is_noinline = arg.is_noinline, |
| 4812 | .align_is_generic = false, |
| 4813 | .cc_is_generic = false, |
| 4814 | .section_is_generic = false, |
| 4815 | .addrspace_is_generic = false, |
| 4816 | }, |
| 4817 | }); |
| 4818 | // no comptime_bits because has_comptime_bits is false |
| 4819 | if (arg.noalias_bits != 0) ip.extra.appendAssumeCapacity(arg.noalias_bits); |
| 4820 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.param_types)); |
| 4821 | |
| 4822 | // TODO: add appendSliceAssumeCapacity to MultiArrayList. |
| 4823 | ip.items.appendAssumeCapacity(.{ |
| 4824 | .tag = .func_instance, |
| 4825 | .data = func_extra_index, |
| 4826 | }); |
| 4827 | ip.items.appendAssumeCapacity(.{ |
| 4828 | .tag = .type_error_union, |
| 4829 | .data = ip.addExtraAssumeCapacity(Tag.ErrorUnionType{ |
| 4830 | .error_set_type = error_set_type, |
| 4831 | .payload_type = arg.bare_return_type, |
| 4832 | }), |
| 4833 | }); |
| 4834 | ip.items.appendAssumeCapacity(.{ |
| 4835 | .tag = .type_inferred_error_set, |
| 4836 | .data = @intFromEnum(func_index), |
| 4837 | }); |
| 4838 | ip.items.appendAssumeCapacity(.{ |
| 4839 | .tag = .type_function, |
| 4840 | .data = func_type_extra_index, |
| 4841 | }); |
| 4842 | |
| 4843 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 4844 | const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{ |
| 4845 | .func = extraFuncInstance(ip, func_extra_index), |
| 4846 | }, adapter); |
| 4847 | if (gop.found_existing) { |
| 4848 | // Hot path: undo the additions to our two arrays. |
| 4849 | ip.items.len -= 4; |
| 4850 | ip.extra.items.len = prev_extra_len; |
| 4851 | return @enumFromInt(gop.index); |
| 4852 | } |
| 4853 | |
| 4854 | // Synchronize the map with items. |
| 4855 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ .error_union_type = .{ |
| 4856 | .error_set_type = error_set_type, |
| 4857 | .payload_type = arg.bare_return_type, |
| 4858 | } }, adapter).found_existing); |
| 4859 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ |
| 4860 | .inferred_error_set_type = func_index, |
| 4861 | }, adapter).found_existing); |
| 4862 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ |
| 4863 | .func_type = extraFuncType(ip, func_type_extra_index), |
| 4864 | }, adapter).found_existing); |
| 4865 | |
| 4866 | return finishFuncInstance( |
| 4867 | ip, |
| 4868 | gpa, |
| 4869 | arg.generic_owner, |
| 4870 | func_index, |
| 4871 | func_extra_index, |
| 4872 | arg.generation, |
| 4873 | func_ty, |
| 4874 | ); |
| 4875 | } |
| 4876 | |
| 4877 | fn finishFuncInstance( |
| 4878 | ip: *InternPool, |
| 4879 | gpa: Allocator, |
| 4880 | generic_owner: Index, |
| 4881 | func_index: Index, |
| 4882 | func_extra_index: u32, |
| 4883 | generation: u32, |
| 4884 | func_ty: Index, |
| 4885 | ) Allocator.Error!Index { |
| 4886 | const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner)); |
| 4728 | 4887 | const decl_index = try ip.createDecl(gpa, .{ |
| 4729 | 4888 | .name = undefined, |
| 4730 | 4889 | .src_namespace = fn_owner_decl.src_namespace, |
| ... | ... | @@ -4741,7 +4900,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4741 | 4900 | .deletion_flag = false, |
| 4742 | 4901 | .zir_decl_index = fn_owner_decl.zir_decl_index, |
| 4743 | 4902 | .src_scope = fn_owner_decl.src_scope, |
| 4744 | | .generation = arg.generation, |
| 4903 | .generation = generation, |
| 4745 | 4904 | .is_pub = fn_owner_decl.is_pub, |
| 4746 | 4905 | .is_exported = fn_owner_decl.is_exported, |
| 4747 | 4906 | .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace, |
| ... | ... | @@ -4753,7 +4912,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4753 | 4912 | |
| 4754 | 4913 | // Populate the owner_decl field which was left undefined until now. |
| 4755 | 4914 | ip.extra.items[ |
| 4756 | | func_instance_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_decl").? |
| 4915 | func_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_decl").? |
| 4757 | 4916 | ] = @intFromEnum(decl_index); |
| 4758 | 4917 | |
| 4759 | 4918 | // TODO: improve this name |
| ... | ... | @@ -4762,11 +4921,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4762 | 4921 | fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), |
| 4763 | 4922 | }); |
| 4764 | 4923 | |
| 4765 | | ip.items.appendAssumeCapacity(.{ |
| 4766 | | .tag = .func_instance, |
| 4767 | | .data = func_instance_extra_index, |
| 4768 | | }); |
| 4769 | | |
| 4770 | 4924 | return func_index; |
| 4771 | 4925 | } |
| 4772 | 4926 | |