authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-09 16:51:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-18 19:02:05-07:00
log6d72f971afdffbd7b098ab3d606a67f4075c6de3
tree6180b246e4c1f00c18f3b14f02d20f56a218290c
parent8fd77395d66e2fe376959d59e0879decdfea6907

InternPool: implement getExternFunc


4 files changed, 205 insertions(+), 116 deletions(-)

src/Air.zig+1-1
...@@ -1436,7 +1436,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1436,7 +1436,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
14361436
1437 .call, .call_always_tail, .call_never_tail, .call_never_inline => {1437 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
1438 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);1438 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1439 return ip.funcReturnType(callee_ty.toIntern()).toType();1439 return ip.funcTypeReturnType(callee_ty.toIntern()).toType();
1440 },1440 },
14411441
1442 .slice_elem_val, .ptr_elem_val, .array_elem_val => {1442 .slice_elem_val, .ptr_elem_val, .array_elem_val => {
src/InternPool.zig+15-17
...@@ -4393,22 +4393,20 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat...@@ -4393,22 +4393,20 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat
4393 return @enumFromInt(ip.items.len - 1);4393 return @enumFromInt(ip.items.len - 1);
4394}4394}
43954395
4396pub const GetExternFuncKey = struct {4396pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Allocator.Error!Index {
4397 param_types: []const Index,4397 const adapter: KeyAdapter = .{ .intern_pool = ip };
4398 noalias_bits: u32,4398 const gop = try ip.map.getOrPutAdapted(gpa, Key{ .extern_func = key }, adapter);
4399 return_type: Index,4399 if (gop.found_existing) return @enumFromInt(gop.index);
4400 cc: std.builtin.CallingConvention,4400 errdefer _ = ip.map.pop();
4401 alignment: Alignment,4401 const prev_extra_len = ip.extra.items.len;
4402 is_var_args: bool,4402 const extra_index = try ip.addExtra(gpa, @as(Tag.ExternFunc, key));
4403 decl: Module.Decl.Index,4403 errdefer ip.extra.items.len = prev_extra_len;
4404 lib_name: OptionalNullTerminatedString,4404 try ip.items.append(gpa, .{
4405};4405 .tag = .extern_func,
44064406 .data = extra_index,
4407pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) Allocator.Error!Index {4407 });
4408 _ = ip;4408 errdefer ip.items.len -= 1;
4409 _ = gpa;4409 return @enumFromInt(ip.items.len - 1);
4410 _ = key;
4411 @panic("TODO");
4412}4410}
44134411
4414pub const GetFuncDeclKey = struct {4412pub const GetFuncDeclKey = struct {
...@@ -6375,7 +6373,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {...@@ -6375,7 +6373,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
6375 };6373 };
6376}6374}
63776375
6378pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {6376pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
6379 const item = ip.items.get(@intFromEnum(ty));6377 const item = ip.items.get(@intFromEnum(ty));
6380 const child_item = switch (item.tag) {6378 const child_item = switch (item.tag) {
6381 .type_pointer => ip.items.get(ip.extra.items[6379 .type_pointer => ip.items.get(ip.extra.items[
src/Sema.zig+188-97
...@@ -8767,92 +8767,63 @@ fn funcCommon(...@@ -8767,92 +8767,63 @@ fn funcCommon(
87678767
8768 const param_types = block.params.items(.ty);8768 const param_types = block.params.items(.ty);
87698769
8770 const opt_func_index: InternPool.Index = i: {8770 if (!is_source_decl) {
8771 if (!is_source_decl) {8771 assert(has_body);
8772 assert(has_body);8772 assert(!is_generic);
8773 assert(!is_generic);8773 assert(comptime_bits == 0);
8774 assert(comptime_bits == 0);8774 assert(cc != null);
8775 assert(cc != null);8775 assert(section != .generic);
8776 assert(section != .generic);8776 assert(address_space != null);
8777 assert(address_space != null);8777 assert(!var_args);
8778 assert(!var_args);8778 const func_index = try ip.getFuncInstance(gpa, .{
8779 break :i try ip.getFuncInstance(gpa, .{8779 .param_types = param_types,
8780 .param_types = param_types,8780 .noalias_bits = noalias_bits,
8781 .noalias_bits = noalias_bits,8781 .bare_return_type = bare_return_type.toIntern(),
8782 .bare_return_type = bare_return_type.toIntern(),8782 .cc = cc_resolved,
8783 .cc = cc_resolved,8783 .alignment = alignment.?,
8784 .alignment = alignment.?,8784 .is_noinline = is_noinline,
8785 .is_noinline = is_noinline,8785 .inferred_error_set = inferred_error_set,
8786 .inferred_error_set = inferred_error_set,8786 .generic_owner = sema.generic_owner,
8787 .generic_owner = sema.generic_owner,8787 });
8788 });8788 return finishFunc(
8789 }8789 sema,
87908790 block,
8791 // extern_func and func_decl functions take ownership of `sema.owner_decl`.8791 func_index,
87928792 .none,
8793 sema.owner_decl.@"linksection" = switch (section) {8793 ret_poison,
8794 .generic => .none,8794 bare_return_type,
8795 .default => .none,8795 ret_ty_src,
8796 .explicit => |section_name| section_name.toOptional(),8796 cc_resolved,
8797 };8797 is_source_decl,
8798 sema.owner_decl.alignment = alignment orelse .none;8798 ret_ty_requires_comptime,
8799 sema.owner_decl.@"addrspace" = address_space orelse .generic;8799 func_inst,
88008800 cc_src,
8801 if (is_extern) {8801 is_noinline,
8802 assert(comptime_bits == 0);8802 is_generic,
8803 assert(cc != null);8803 final_is_generic,
8804 assert(section != .generic);8804 );
8805 assert(address_space != null);8805 }
8806 assert(!is_generic);
8807 break :i try ip.getExternFunc(gpa, .{
8808 .param_types = param_types,
8809 .noalias_bits = noalias_bits,
8810 .return_type = bare_return_type.toIntern(),
8811 .cc = cc_resolved,
8812 .alignment = alignment.?,
8813 .is_var_args = var_args,
8814 .decl = sema.owner_decl_index,
8815 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
8816 gpa,
8817 try sema.handleExternLibName(block, .{
8818 .node_offset_lib_name = src_node_offset,
8819 }, lib_name),
8820 )).toOptional() else .none,
8821 });
8822 }
8823
8824 if (!has_body) break :i .none;
8825
8826 if (inferred_error_set) {
8827 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
8828 break :i try ip.getFuncDeclIes(gpa, .{
8829 .owner_decl = sema.owner_decl_index,
88308806
8831 .param_types = param_types,8807 // extern_func and func_decl functions take ownership of `sema.owner_decl`.
8832 .noalias_bits = noalias_bits,8808 sema.owner_decl.@"linksection" = switch (section) {
8833 .comptime_bits = comptime_bits,8809 .generic => .none,
8834 .bare_return_type = bare_return_type.toIntern(),8810 .default => .none,
8835 .cc = cc,8811 .explicit => |section_name| section_name.toOptional(),
8836 .alignment = alignment,8812 };
8837 .section_is_generic = section == .generic,8813 sema.owner_decl.alignment = alignment orelse .none;
8838 .addrspace_is_generic = address_space == null,8814 sema.owner_decl.@"addrspace" = address_space orelse .generic;
8839 .is_var_args = var_args,8815
8840 .is_generic = final_is_generic,8816 if (inferred_error_set) {
8841 .is_noinline = is_noinline,8817 assert(!is_extern);
88428818 assert(has_body);
8843 .zir_body_inst = func_inst,8819 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
8844 .lbrace_line = src_locs.lbrace_line,8820 const func_index = try ip.getFuncDeclIes(gpa, .{
8845 .rbrace_line = src_locs.rbrace_line,8821 .owner_decl = sema.owner_decl_index,
8846 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
8847 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
8848 });
8849 }
88508822
8851 const func_ty = try ip.getFuncType(gpa, .{
8852 .param_types = param_types,8823 .param_types = param_types,
8853 .noalias_bits = noalias_bits,8824 .noalias_bits = noalias_bits,
8854 .comptime_bits = comptime_bits,8825 .comptime_bits = comptime_bits,
8855 .return_type = bare_return_type.toIntern(),8826 .bare_return_type = bare_return_type.toIntern(),
8856 .cc = cc,8827 .cc = cc,
8857 .alignment = alignment,8828 .alignment = alignment,
8858 .section_is_generic = section == .generic,8829 .section_is_generic = section == .generic,
...@@ -8860,9 +8831,83 @@ fn funcCommon(...@@ -8860,9 +8831,83 @@ fn funcCommon(
8860 .is_var_args = var_args,8831 .is_var_args = var_args,
8861 .is_generic = final_is_generic,8832 .is_generic = final_is_generic,
8862 .is_noinline = is_noinline,8833 .is_noinline = is_noinline,
8834
8835 .zir_body_inst = func_inst,
8836 .lbrace_line = src_locs.lbrace_line,
8837 .rbrace_line = src_locs.rbrace_line,
8838 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
8839 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
8863 });8840 });
8841 return finishFunc(
8842 sema,
8843 block,
8844 func_index,
8845 .none,
8846 ret_poison,
8847 bare_return_type,
8848 ret_ty_src,
8849 cc_resolved,
8850 is_source_decl,
8851 ret_ty_requires_comptime,
8852 func_inst,
8853 cc_src,
8854 is_noinline,
8855 is_generic,
8856 final_is_generic,
8857 );
8858 }
88648859
8865 break :i try ip.getFuncDecl(gpa, .{8860 const func_ty = try ip.getFuncType(gpa, .{
8861 .param_types = param_types,
8862 .noalias_bits = noalias_bits,
8863 .comptime_bits = comptime_bits,
8864 .return_type = bare_return_type.toIntern(),
8865 .cc = cc,
8866 .alignment = alignment,
8867 .section_is_generic = section == .generic,
8868 .addrspace_is_generic = address_space == null,
8869 .is_var_args = var_args,
8870 .is_generic = final_is_generic,
8871 .is_noinline = is_noinline,
8872 });
8873
8874 if (is_extern) {
8875 assert(comptime_bits == 0);
8876 assert(cc != null);
8877 assert(section != .generic);
8878 assert(address_space != null);
8879 assert(!is_generic);
8880 const func_index = try ip.getExternFunc(gpa, .{
8881 .ty = func_ty,
8882 .decl = sema.owner_decl_index,
8883 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
8884 gpa,
8885 try sema.handleExternLibName(block, .{
8886 .node_offset_lib_name = src_node_offset,
8887 }, lib_name),
8888 )).toOptional() else .none,
8889 });
8890 return finishFunc(
8891 sema,
8892 block,
8893 func_index,
8894 func_ty,
8895 ret_poison,
8896 bare_return_type,
8897 ret_ty_src,
8898 cc_resolved,
8899 is_source_decl,
8900 ret_ty_requires_comptime,
8901 func_inst,
8902 cc_src,
8903 is_noinline,
8904 is_generic,
8905 final_is_generic,
8906 );
8907 }
8908
8909 if (has_body) {
8910 const func_index = try ip.getFuncDecl(gpa, .{
8866 .owner_decl = sema.owner_decl_index,8911 .owner_decl = sema.owner_decl_index,
8867 .ty = func_ty,8912 .ty = func_ty,
8868 .cc = cc,8913 .cc = cc,
...@@ -8873,12 +8918,70 @@ fn funcCommon(...@@ -8873,12 +8918,70 @@ fn funcCommon(
8873 .lbrace_column = @as(u16, @truncate(src_locs.columns)),8918 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
8874 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),8919 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
8875 });8920 });
8876 };8921 return finishFunc(
8922 sema,
8923 block,
8924 func_index,
8925 func_ty,
8926 ret_poison,
8927 bare_return_type,
8928 ret_ty_src,
8929 cc_resolved,
8930 is_source_decl,
8931 ret_ty_requires_comptime,
8932 func_inst,
8933 cc_src,
8934 is_noinline,
8935 is_generic,
8936 final_is_generic,
8937 );
8938 }
8939
8940 return finishFunc(
8941 sema,
8942 block,
8943 .none,
8944 func_ty,
8945 ret_poison,
8946 bare_return_type,
8947 ret_ty_src,
8948 cc_resolved,
8949 is_source_decl,
8950 ret_ty_requires_comptime,
8951 func_inst,
8952 cc_src,
8953 is_noinline,
8954 is_generic,
8955 final_is_generic,
8956 );
8957}
8958
8959fn finishFunc(
8960 sema: *Sema,
8961 block: *Block,
8962 opt_func_index: InternPool.Index,
8963 func_ty: InternPool.Index,
8964 ret_poison: bool,
8965 bare_return_type: Type,
8966 ret_ty_src: LazySrcLoc,
8967 cc_resolved: std.builtin.CallingConvention,
8968 is_source_decl: bool,
8969 ret_ty_requires_comptime: bool,
8970 func_inst: Zir.Inst.Index,
8971 cc_src: LazySrcLoc,
8972 is_noinline: bool,
8973 is_generic: bool,
8974 final_is_generic: bool,
8975) CompileError!Air.Inst.Ref {
8976 const mod = sema.mod;
8977 const ip = &mod.intern_pool;
8978 const gpa = sema.gpa;
8979 const target = mod.getTarget();
88778980
8878 const return_type: Type = if (opt_func_index == .none or ret_poison)8981 const return_type: Type = if (opt_func_index == .none or ret_poison)
8879 bare_return_type8982 bare_return_type
8880 else8983 else
8881 ip.funcReturnType(ip.typeOf(opt_func_index)).toType();8984 ip.funcTypeReturnType(ip.typeOf(opt_func_index)).toType();
88828985
8883 if (!return_type.isValidReturnType(mod)) {8986 if (!return_type.isValidReturnType(mod)) {
8884 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";8987 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
...@@ -8998,19 +9101,7 @@ fn funcCommon(...@@ -8998,19 +9101,7 @@ fn funcCommon(
8998 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);9101 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
8999 }9102 }
90009103
9001 return Air.internedToRef(if (opt_func_index == .none) try ip.getFuncType(gpa, .{9104 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
9002 .param_types = param_types,
9003 .noalias_bits = noalias_bits,
9004 .comptime_bits = comptime_bits,
9005 .return_type = return_type.toIntern(),
9006 .cc = cc,
9007 .alignment = alignment,
9008 .section_is_generic = section == .generic,
9009 .addrspace_is_generic = address_space == null,
9010 .is_var_args = var_args,
9011 .is_generic = final_is_generic,
9012 .is_noinline = is_noinline,
9013 }) else opt_func_index);
9014}9105}
90159106
9016fn zirParam(9107fn zirParam(
src/type.zig+1-1
...@@ -2364,7 +2364,7 @@ pub const Type = struct {...@@ -2364,7 +2364,7 @@ pub const Type = struct {
23642364
2365 /// Asserts the type is a function or a function pointer.2365 /// Asserts the type is a function or a function pointer.
2366 pub fn fnReturnType(ty: Type, mod: *Module) Type {2366 pub fn fnReturnType(ty: Type, mod: *Module) Type {
2367 return mod.intern_pool.funcReturnType(ty.toIntern()).toType();2367 return mod.intern_pool.funcTypeReturnType(ty.toIntern()).toType();
2368 }2368 }
23692369
2370 /// Asserts the type is a function.2370 /// Asserts the type is a function.