From 6d72f971afdffbd7b098ab3d606a67f4075c6de3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 9 Jul 2023 16:51:23 -0700 Subject: [PATCH] InternPool: implement getExternFunc --- src/Air.zig | 2 +- src/InternPool.zig | 32 +++-- src/Sema.zig | 285 ++++++++++++++++++++++++++++++--------------- src/type.zig | 2 +- 4 files changed, 205 insertions(+), 116 deletions(-) diff --git a/src/Air.zig b/src/Air.zig index ab845538bd..0368674ea0 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -1436,7 +1436,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) .call, .call_always_tail, .call_never_tail, .call_never_inline => { const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip); - return ip.funcReturnType(callee_ty.toIntern()).toType(); + return ip.funcTypeReturnType(callee_ty.toIntern()).toType(); }, .slice_elem_val, .ptr_elem_val, .array_elem_val => { diff --git a/src/InternPool.zig b/src/InternPool.zig index a2409df518..93a44005cf 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -4393,22 +4393,20 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat return @enumFromInt(ip.items.len - 1); } -pub const GetExternFuncKey = struct { - param_types: []const Index, - noalias_bits: u32, - return_type: Index, - cc: std.builtin.CallingConvention, - alignment: Alignment, - is_var_args: bool, - decl: Module.Decl.Index, - lib_name: OptionalNullTerminatedString, -}; - -pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) Allocator.Error!Index { - _ = ip; - _ = gpa; - _ = key; - @panic("TODO"); +pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Allocator.Error!Index { + const adapter: KeyAdapter = .{ .intern_pool = ip }; + const gop = try ip.map.getOrPutAdapted(gpa, Key{ .extern_func = key }, adapter); + if (gop.found_existing) return @enumFromInt(gop.index); + errdefer _ = ip.map.pop(); + const prev_extra_len = ip.extra.items.len; + const extra_index = try ip.addExtra(gpa, @as(Tag.ExternFunc, key)); + errdefer ip.extra.items.len = prev_extra_len; + try ip.items.append(gpa, .{ + .tag = .extern_func, + .data = extra_index, + }); + errdefer ip.items.len -= 1; + return @enumFromInt(ip.items.len - 1); } pub const GetFuncDeclKey = struct { @@ -6375,7 +6373,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 { }; } -pub fn funcReturnType(ip: *const InternPool, ty: Index) Index { +pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index { const item = ip.items.get(@intFromEnum(ty)); const child_item = switch (item.tag) { .type_pointer => ip.items.get(ip.extra.items[ diff --git a/src/Sema.zig b/src/Sema.zig index d8c55e5aeb..2357833874 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8767,92 +8767,63 @@ fn funcCommon( const param_types = block.params.items(.ty); - const opt_func_index: InternPool.Index = i: { - if (!is_source_decl) { - assert(has_body); - assert(!is_generic); - assert(comptime_bits == 0); - assert(cc != null); - assert(section != .generic); - assert(address_space != null); - assert(!var_args); - break :i try ip.getFuncInstance(gpa, .{ - .param_types = param_types, - .noalias_bits = noalias_bits, - .bare_return_type = bare_return_type.toIntern(), - .cc = cc_resolved, - .alignment = alignment.?, - .is_noinline = is_noinline, - .inferred_error_set = inferred_error_set, - .generic_owner = sema.generic_owner, - }); - } + if (!is_source_decl) { + assert(has_body); + assert(!is_generic); + assert(comptime_bits == 0); + assert(cc != null); + assert(section != .generic); + assert(address_space != null); + assert(!var_args); + const func_index = try ip.getFuncInstance(gpa, .{ + .param_types = param_types, + .noalias_bits = noalias_bits, + .bare_return_type = bare_return_type.toIntern(), + .cc = cc_resolved, + .alignment = alignment.?, + .is_noinline = is_noinline, + .inferred_error_set = inferred_error_set, + .generic_owner = sema.generic_owner, + }); + return finishFunc( + sema, + block, + func_index, + .none, + ret_poison, + bare_return_type, + ret_ty_src, + cc_resolved, + is_source_decl, + ret_ty_requires_comptime, + func_inst, + cc_src, + is_noinline, + is_generic, + final_is_generic, + ); + } - // extern_func and func_decl functions take ownership of `sema.owner_decl`. + // extern_func and func_decl functions take ownership of `sema.owner_decl`. + sema.owner_decl.@"linksection" = switch (section) { + .generic => .none, + .default => .none, + .explicit => |section_name| section_name.toOptional(), + }; + sema.owner_decl.alignment = alignment orelse .none; + sema.owner_decl.@"addrspace" = address_space orelse .generic; - sema.owner_decl.@"linksection" = switch (section) { - .generic => .none, - .default => .none, - .explicit => |section_name| section_name.toOptional(), - }; - sema.owner_decl.alignment = alignment orelse .none; - sema.owner_decl.@"addrspace" = address_space orelse .generic; + if (inferred_error_set) { + assert(!is_extern); + assert(has_body); + try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); + const func_index = try ip.getFuncDeclIes(gpa, .{ + .owner_decl = sema.owner_decl_index, - if (is_extern) { - assert(comptime_bits == 0); - assert(cc != null); - assert(section != .generic); - assert(address_space != null); - assert(!is_generic); - break :i try ip.getExternFunc(gpa, .{ - .param_types = param_types, - .noalias_bits = noalias_bits, - .return_type = bare_return_type.toIntern(), - .cc = cc_resolved, - .alignment = alignment.?, - .is_var_args = var_args, - .decl = sema.owner_decl_index, - .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString( - gpa, - try sema.handleExternLibName(block, .{ - .node_offset_lib_name = src_node_offset, - }, lib_name), - )).toOptional() else .none, - }); - } - - if (!has_body) break :i .none; - - if (inferred_error_set) { - try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); - break :i try ip.getFuncDeclIes(gpa, .{ - .owner_decl = sema.owner_decl_index, - - .param_types = param_types, - .noalias_bits = noalias_bits, - .comptime_bits = comptime_bits, - .bare_return_type = bare_return_type.toIntern(), - .cc = cc, - .alignment = alignment, - .section_is_generic = section == .generic, - .addrspace_is_generic = address_space == null, - .is_var_args = var_args, - .is_generic = final_is_generic, - .is_noinline = is_noinline, - - .zir_body_inst = func_inst, - .lbrace_line = src_locs.lbrace_line, - .rbrace_line = src_locs.rbrace_line, - .lbrace_column = @as(u16, @truncate(src_locs.columns)), - .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), - }); - } - - const func_ty = try ip.getFuncType(gpa, .{ .param_types = param_types, .noalias_bits = noalias_bits, .comptime_bits = comptime_bits, - .return_type = bare_return_type.toIntern(), + .bare_return_type = bare_return_type.toIntern(), .cc = cc, .alignment = alignment, .section_is_generic = section == .generic, @@ -8860,9 +8831,83 @@ fn funcCommon( .is_var_args = var_args, .is_generic = final_is_generic, .is_noinline = is_noinline, - }); - break :i try ip.getFuncDecl(gpa, .{ + .zir_body_inst = func_inst, + .lbrace_line = src_locs.lbrace_line, + .rbrace_line = src_locs.rbrace_line, + .lbrace_column = @as(u16, @truncate(src_locs.columns)), + .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), + }); + return finishFunc( + sema, + block, + func_index, + .none, + ret_poison, + bare_return_type, + ret_ty_src, + cc_resolved, + is_source_decl, + ret_ty_requires_comptime, + func_inst, + cc_src, + is_noinline, + is_generic, + final_is_generic, + ); + } + + const func_ty = try ip.getFuncType(gpa, .{ + .param_types = param_types, + .noalias_bits = noalias_bits, + .comptime_bits = comptime_bits, + .return_type = bare_return_type.toIntern(), + .cc = cc, + .alignment = alignment, + .section_is_generic = section == .generic, + .addrspace_is_generic = address_space == null, + .is_var_args = var_args, + .is_generic = final_is_generic, + .is_noinline = is_noinline, + }); + + if (is_extern) { + assert(comptime_bits == 0); + assert(cc != null); + assert(section != .generic); + assert(address_space != null); + assert(!is_generic); + const func_index = try ip.getExternFunc(gpa, .{ + .ty = func_ty, + .decl = sema.owner_decl_index, + .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString( + gpa, + try sema.handleExternLibName(block, .{ + .node_offset_lib_name = src_node_offset, + }, lib_name), + )).toOptional() else .none, + }); + return finishFunc( + sema, + block, + func_index, + func_ty, + ret_poison, + bare_return_type, + ret_ty_src, + cc_resolved, + is_source_decl, + ret_ty_requires_comptime, + func_inst, + cc_src, + is_noinline, + is_generic, + final_is_generic, + ); + } + + if (has_body) { + const func_index = try ip.getFuncDecl(gpa, .{ .owner_decl = sema.owner_decl_index, .ty = func_ty, .cc = cc, @@ -8873,12 +8918,70 @@ fn funcCommon( .lbrace_column = @as(u16, @truncate(src_locs.columns)), .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), }); - }; + return finishFunc( + sema, + block, + func_index, + func_ty, + ret_poison, + bare_return_type, + ret_ty_src, + cc_resolved, + is_source_decl, + ret_ty_requires_comptime, + func_inst, + cc_src, + is_noinline, + is_generic, + final_is_generic, + ); + } + + return finishFunc( + sema, + block, + .none, + func_ty, + ret_poison, + bare_return_type, + ret_ty_src, + cc_resolved, + is_source_decl, + ret_ty_requires_comptime, + func_inst, + cc_src, + is_noinline, + is_generic, + final_is_generic, + ); +} + +fn finishFunc( + sema: *Sema, + block: *Block, + opt_func_index: InternPool.Index, + func_ty: InternPool.Index, + ret_poison: bool, + bare_return_type: Type, + ret_ty_src: LazySrcLoc, + cc_resolved: std.builtin.CallingConvention, + is_source_decl: bool, + ret_ty_requires_comptime: bool, + func_inst: Zir.Inst.Index, + cc_src: LazySrcLoc, + is_noinline: bool, + is_generic: bool, + final_is_generic: bool, +) CompileError!Air.Inst.Ref { + const mod = sema.mod; + const ip = &mod.intern_pool; + const gpa = sema.gpa; + const target = mod.getTarget(); const return_type: Type = if (opt_func_index == .none or ret_poison) bare_return_type else - ip.funcReturnType(ip.typeOf(opt_func_index)).toType(); + ip.funcTypeReturnType(ip.typeOf(opt_func_index)).toType(); if (!return_type.isValidReturnType(mod)) { const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else ""; @@ -8998,19 +9101,7 @@ fn funcCommon( _ = try sema.resolveTypeFields(unresolved_stack_trace_ty); } - return Air.internedToRef(if (opt_func_index == .none) try ip.getFuncType(gpa, .{ - .param_types = param_types, - .noalias_bits = noalias_bits, - .comptime_bits = comptime_bits, - .return_type = return_type.toIntern(), - .cc = cc, - .alignment = alignment, - .section_is_generic = section == .generic, - .addrspace_is_generic = address_space == null, - .is_var_args = var_args, - .is_generic = final_is_generic, - .is_noinline = is_noinline, - }) else opt_func_index); + return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty); } fn zirParam( diff --git a/src/type.zig b/src/type.zig index d9d4270ed0..a5483c2128 100644 --- a/src/type.zig +++ b/src/type.zig @@ -2364,7 +2364,7 @@ pub const Type = struct { /// Asserts the type is a function or a function pointer. pub fn fnReturnType(ty: Type, mod: *Module) Type { - return mod.intern_pool.funcReturnType(ty.toIntern()).toType(); + return mod.intern_pool.funcTypeReturnType(ty.toIntern()).toType(); } /// Asserts the type is a function.