| ... | @@ -1136,7 +1136,7 @@ pub const Key = union(enum) { | ... | @@ -1136,7 +1136,7 @@ pub const Key = union(enum) { |
| 1136 | var a_ty_info = ip.indexToFuncType(a_info.ty).?; | 1136 | var a_ty_info = ip.indexToFuncType(a_info.ty).?; |
| 1137 | a_ty_info.return_type = ip.errorUnionPayload(a_ty_info.return_type); | 1137 | a_ty_info.return_type = ip.errorUnionPayload(a_ty_info.return_type); |
| 1138 | var b_ty_info = ip.indexToFuncType(b_info.ty).?; | 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 | return a_ty_info.eql(b_ty_info, ip); | 1140 | return a_ty_info.eql(b_ty_info, ip); |
| 1141 | }, | 1141 | }, |
| 1142 | | 1142 | |
| ... | @@ -4657,7 +4657,12 @@ pub fn getErrorSetType( | ... | @@ -4657,7 +4657,12 @@ pub fn getErrorSetType( |
| 4657 | } | 4657 | } |
| 4658 | | 4658 | |
| 4659 | pub const GetFuncInstanceKey = struct { | 4659 | pub const GetFuncInstanceKey = struct { |
| | 4660 | /// Has the length of the instance function (may be lesser than |
| | 4661 | /// comptime_args). |
| 4660 | param_types: []Index, | 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 | noalias_bits: u32, | 4666 | noalias_bits: u32, |
| 4662 | bare_return_type: Index, | 4667 | bare_return_type: Index, |
| 4663 | cc: std.builtin.CallingConvention, | 4668 | cc: std.builtin.CallingConvention, |
| ... | @@ -4665,12 +4670,12 @@ pub const GetFuncInstanceKey = struct { | ... | @@ -4665,12 +4670,12 @@ pub const GetFuncInstanceKey = struct { |
| 4665 | is_noinline: bool, | 4670 | is_noinline: bool, |
| 4666 | generic_owner: Index, | 4671 | generic_owner: Index, |
| 4667 | inferred_error_set: bool, | 4672 | inferred_error_set: bool, |
| 4668 | comptime_args: []const Index, | | |
| 4669 | generation: u32, | 4673 | generation: u32, |
| 4670 | }; | 4674 | }; |
| 4671 | | 4675 | |
| 4672 | pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index { | 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 | const func_ty = try ip.getFuncType(gpa, .{ | 4680 | const func_ty = try ip.getFuncType(gpa, .{ |
| 4676 | .param_types = arg.param_types, | 4681 | .param_types = arg.param_types, |
| ... | @@ -4693,7 +4698,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) | ... | @@ -4693,7 +4698,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4693 | const prev_extra_len = ip.extra.items.len; | 4698 | const prev_extra_len = ip.extra.items.len; |
| 4694 | errdefer ip.extra.items.len = prev_extra_len; | 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 | .analysis = .{ | 4702 | .analysis = .{ |
| 4698 | .state = if (arg.cc == .Inline) .inline_only else .none, | 4703 | .state = if (arg.cc == .Inline) .inline_only else .none, |
| 4699 | .is_cold = false, | 4704 | .is_cold = false, |
| ... | @@ -4712,7 +4717,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) | ... | @@ -4712,7 +4717,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4712 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args)); | 4717 | ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args)); |
| 4713 | | 4718 | |
| 4714 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ | 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 | }, KeyAdapter{ .intern_pool = ip }); | 4721 | }, KeyAdapter{ .intern_pool = ip }); |
| 4717 | errdefer _ = ip.map.pop(); | 4722 | errdefer _ = ip.map.pop(); |
| 4718 | | 4723 | |
| ... | @@ -4721,10 +4726,164 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) | ... | @@ -4721,10 +4726,164 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4721 | return @enumFromInt(gop.index); | 4726 | return @enumFromInt(gop.index); |
| 4722 | } | 4727 | } |
| 4723 | | 4728 | |
| 4724 | try ip.items.ensureUnusedCapacity(gpa, 1); | | |
| 4725 | const func_index: Index = @enumFromInt(ip.items.len); | 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 | const decl_index = try ip.createDecl(gpa, .{ | 4887 | const decl_index = try ip.createDecl(gpa, .{ |
| 4729 | .name = undefined, | 4888 | .name = undefined, |
| 4730 | .src_namespace = fn_owner_decl.src_namespace, | 4889 | .src_namespace = fn_owner_decl.src_namespace, |
| ... | @@ -4741,7 +4900,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) | ... | @@ -4741,7 +4900,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4741 | .deletion_flag = false, | 4900 | .deletion_flag = false, |
| 4742 | .zir_decl_index = fn_owner_decl.zir_decl_index, | 4901 | .zir_decl_index = fn_owner_decl.zir_decl_index, |
| 4743 | .src_scope = fn_owner_decl.src_scope, | 4902 | .src_scope = fn_owner_decl.src_scope, |
| 4744 | .generation = arg.generation, | 4903 | .generation = generation, |
| 4745 | .is_pub = fn_owner_decl.is_pub, | 4904 | .is_pub = fn_owner_decl.is_pub, |
| 4746 | .is_exported = fn_owner_decl.is_exported, | 4905 | .is_exported = fn_owner_decl.is_exported, |
| 4747 | .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace, | 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,7 +4912,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4753 | | 4912 | |
| 4754 | // Populate the owner_decl field which was left undefined until now. | 4913 | // Populate the owner_decl field which was left undefined until now. |
| 4755 | ip.extra.items[ | 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 | ] = @intFromEnum(decl_index); | 4916 | ] = @intFromEnum(decl_index); |
| 4758 | | 4917 | |
| 4759 | // TODO: improve this name | 4918 | // TODO: improve this name |
| ... | @@ -4762,11 +4921,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) | ... | @@ -4762,11 +4921,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 4762 | fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), | 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 | return func_index; | 4924 | return func_index; |
| 4771 | } | 4925 | } |
| 4772 | | 4926 | |