| author | |
| committer | |
| log | 6ac204714236eaeaea5dc66afddbe158966b2532 |
| tree | 3e0a8b35ba2aa6ec803861cfc9a6b0d8fe80e49f |
| parent | 47531b7d9389c45af3e46b623235792f14a40ff2 |
4 files changed, 57 insertions(+), 20 deletions(-)
src/AstGen.zig+8-1| ... | ... | @@ -1081,6 +1081,7 @@ fn fnProtoExpr( |
| 1081 | 1081 | .is_var_args = is_var_args, |
| 1082 | 1082 | .is_inferred_error = false, |
| 1083 | 1083 | .is_test = false, |
| 1084 | .is_extern = false, | |
| 1084 | 1085 | }); |
| 1085 | 1086 | return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node); |
| 1086 | 1087 | } |
| ... | ... | @@ -2807,6 +2808,7 @@ fn fnDecl( |
| 2807 | 2808 | .is_var_args = is_var_args, |
| 2808 | 2809 | .is_inferred_error = false, |
| 2809 | 2810 | .is_test = false, |
| 2811 | .is_extern = true, | |
| 2810 | 2812 | }); |
| 2811 | 2813 | } else func: { |
| 2812 | 2814 | if (is_var_args) { |
| ... | ... | @@ -2883,6 +2885,7 @@ fn fnDecl( |
| 2883 | 2885 | .is_var_args = is_var_args, |
| 2884 | 2886 | .is_inferred_error = is_inferred_error, |
| 2885 | 2887 | .is_test = false, |
| 2888 | .is_extern = false, | |
| 2886 | 2889 | }); |
| 2887 | 2890 | }; |
| 2888 | 2891 | |
| ... | ... | @@ -3223,6 +3226,7 @@ fn testDecl( |
| 3223 | 3226 | .is_var_args = false, |
| 3224 | 3227 | .is_inferred_error = true, |
| 3225 | 3228 | .is_test = true, |
| 3229 | .is_extern = false, | |
| 3226 | 3230 | }); |
| 3227 | 3231 | |
| 3228 | 3232 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); |
| ... | ... | @@ -7973,6 +7977,7 @@ const GenZir = struct { |
| 7973 | 7977 | is_var_args: bool, |
| 7974 | 7978 | is_inferred_error: bool, |
| 7975 | 7979 | is_test: bool, |
| 7980 | is_extern: bool, | |
| 7976 | 7981 | }) !Zir.Inst.Ref { |
| 7977 | 7982 | assert(args.src_node != 0); |
| 7978 | 7983 | assert(args.ret_ty != .none); |
| ... | ... | @@ -8010,7 +8015,8 @@ const GenZir = struct { |
| 8010 | 8015 | } |
| 8011 | 8016 | |
| 8012 | 8017 | if (args.cc != .none or args.lib_name != 0 or |
| 8013 | args.is_var_args or args.is_test or args.align_inst != .none) | |
| 8018 | args.is_var_args or args.is_test or args.align_inst != .none or | |
| 8019 | args.is_extern) | |
| 8014 | 8020 | { |
| 8015 | 8021 | try astgen.extra.ensureUnusedCapacity( |
| 8016 | 8022 | gpa, |
| ... | ... | @@ -8051,6 +8057,7 @@ const GenZir = struct { |
| 8051 | 8057 | .has_cc = args.cc != .none, |
| 8052 | 8058 | .has_align = args.align_inst != .none, |
| 8053 | 8059 | .is_test = args.is_test, |
| 8060 | .is_extern = args.is_extern, | |
| 8054 | 8061 | }), |
| 8055 | 8062 | .operand = payload_index, |
| 8056 | 8063 | } }, |
src/Module.zig+29-14| ... | ... | @@ -282,13 +282,10 @@ pub const Decl = struct { |
| 282 | 282 | |
| 283 | 283 | pub fn destroy(decl: *Decl, module: *Module) void { |
| 284 | 284 | const gpa = module.gpa; |
| 285 | log.debug("destroy Decl {*} ({s})", .{ decl, decl.name }); | |
| 285 | log.debug("destroy {*} ({s})", .{ decl, decl.name }); | |
| 286 | 286 | decl.clearName(gpa); |
| 287 | 287 | if (decl.has_tv) { |
| 288 | if (decl.getFunction()) |func| { | |
| 289 | func.deinit(gpa); | |
| 290 | gpa.destroy(func); | |
| 291 | } else if (decl.val.getTypeNamespace()) |namespace| { | |
| 288 | if (decl.val.getTypeNamespace()) |namespace| { | |
| 292 | 289 | if (namespace.getDecl() == decl) { |
| 293 | 290 | namespace.clearDecls(module); |
| 294 | 291 | } |
| ... | ... | @@ -470,7 +467,6 @@ pub const Decl = struct { |
| 470 | 467 | /// otherwise null. |
| 471 | 468 | pub fn getFunction(decl: *Decl) ?*Fn { |
| 472 | 469 | if (!decl.has_tv) return null; |
| 473 | if (decl.ty.zigTypeTag() != .Fn) return null; | |
| 474 | 470 | const func = (decl.val.castTag(.function) orelse return null).data; |
| 475 | 471 | if (func.owner_decl != decl) return null; |
| 476 | 472 | return func; |
| ... | ... | @@ -2960,17 +2956,26 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 2960 | 2956 | decl.clearValues(gpa); |
| 2961 | 2957 | } |
| 2962 | 2958 | |
| 2963 | const new_variable = try decl_arena.allocator.create(Var); | |
| 2964 | new_variable.* = .{ | |
| 2965 | .owner_decl = decl, | |
| 2966 | .init = try decl_tv.val.copy(&decl_arena.allocator), | |
| 2967 | .is_extern = is_extern, | |
| 2968 | .is_mutable = is_mutable, | |
| 2969 | .is_threadlocal = is_threadlocal, | |
| 2959 | const copied_val = try decl_tv.val.copy(&decl_arena.allocator); | |
| 2960 | const is_extern_fn = copied_val.tag() == .extern_fn; | |
| 2961 | ||
| 2962 | // TODO: also avoid allocating this Var structure if `!is_mutable`. | |
| 2963 | // I think this will require adjusting Sema to copy the value or something | |
| 2964 | // like that; otherwise it causes use of undefined value when freeing resources. | |
| 2965 | const decl_val: Value = if (is_extern_fn) copied_val else blk: { | |
| 2966 | const new_variable = try decl_arena.allocator.create(Var); | |
| 2967 | new_variable.* = .{ | |
| 2968 | .owner_decl = decl, | |
| 2969 | .init = copied_val, | |
| 2970 | .is_extern = is_extern, | |
| 2971 | .is_mutable = is_mutable, | |
| 2972 | .is_threadlocal = is_threadlocal, | |
| 2973 | }; | |
| 2974 | break :blk try Value.Tag.variable.create(&decl_arena.allocator, new_variable); | |
| 2970 | 2975 | }; |
| 2971 | 2976 | |
| 2972 | 2977 | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); |
| 2973 | decl.val = try Value.Tag.variable.create(&decl_arena.allocator, new_variable); | |
| 2978 | decl.val = decl_val; | |
| 2974 | 2979 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 2975 | 2980 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 2976 | 2981 | decl.has_tv = true; |
| ... | ... | @@ -2984,6 +2989,16 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 2984 | 2989 | // The scope needs to have the decl in it. |
| 2985 | 2990 | try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); |
| 2986 | 2991 | } |
| 2992 | ||
| 2993 | if (decl.val.tag() == .extern_fn) { | |
| 2994 | try mod.comp.bin_file.allocateDeclIndexes(decl); | |
| 2995 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); | |
| 2996 | ||
| 2997 | if (type_changed and mod.emit_h != null) { | |
| 2998 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); | |
| 2999 | } | |
| 3000 | } | |
| 3001 | ||
| 2987 | 3002 | return type_changed; |
| 2988 | 3003 | } |
| 2989 | 3004 | } |
src/Sema.zig+14-4| ... | ... | @@ -2819,6 +2819,7 @@ fn zirFunc( |
| 2819 | 2819 | Value.initTag(.null_value), |
| 2820 | 2820 | false, |
| 2821 | 2821 | inferred_error_set, |
| 2822 | false, | |
| 2822 | 2823 | src_locs, |
| 2823 | 2824 | null, |
| 2824 | 2825 | ); |
| ... | ... | @@ -2835,6 +2836,7 @@ fn funcCommon( |
| 2835 | 2836 | align_val: Value, |
| 2836 | 2837 | var_args: bool, |
| 2837 | 2838 | inferred_error_set: bool, |
| 2839 | is_extern: bool, | |
| 2838 | 2840 | src_locs: Zir.Inst.Func.SrcLocs, |
| 2839 | 2841 | opt_lib_name: ?[]const u8, |
| 2840 | 2842 | ) InnerError!*Inst { |
| ... | ... | @@ -2885,10 +2887,6 @@ fn funcCommon( |
| 2885 | 2887 | }); |
| 2886 | 2888 | }; |
| 2887 | 2889 | |
| 2888 | if (body_inst == 0) { | |
| 2889 | return mod.constType(sema.arena, src, fn_ty); | |
| 2890 | } | |
| 2891 | ||
| 2892 | 2890 | if (opt_lib_name) |lib_name| blk: { |
| 2893 | 2891 | const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset }; |
| 2894 | 2892 | log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); |
| ... | ... | @@ -2930,6 +2928,17 @@ fn funcCommon( |
| 2930 | 2928 | } |
| 2931 | 2929 | } |
| 2932 | 2930 | |
| 2931 | if (is_extern) { | |
| 2932 | return sema.mod.constInst(sema.arena, src, .{ | |
| 2933 | .ty = fn_ty, | |
| 2934 | .val = try Value.Tag.extern_fn.create(sema.arena, sema.owner_decl), | |
| 2935 | }); | |
| 2936 | } | |
| 2937 | ||
| 2938 | if (body_inst == 0) { | |
| 2939 | return mod.constType(sema.arena, src, fn_ty); | |
| 2940 | } | |
| 2941 | ||
| 2933 | 2942 | const is_inline = fn_ty.fnCallingConvention() == .Inline; |
| 2934 | 2943 | const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued; |
| 2935 | 2944 | |
| ... | ... | @@ -5795,6 +5804,7 @@ fn zirFuncExtended( |
| 5795 | 5804 | align_val, |
| 5796 | 5805 | small.is_var_args, |
| 5797 | 5806 | small.is_inferred_error, |
| 5807 | small.is_extern, | |
| 5798 | 5808 | src_locs, |
| 5799 | 5809 | lib_name, |
| 5800 | 5810 | ); |
src/Zir.zig+6-1| ... | ... | @@ -2217,7 +2217,8 @@ pub const Inst = struct { |
| 2217 | 2217 | has_cc: bool, |
| 2218 | 2218 | has_align: bool, |
| 2219 | 2219 | is_test: bool, |
| 2220 | _: u10 = undefined, | |
| 2220 | is_extern: bool, | |
| 2221 | _: u9 = undefined, | |
| 2221 | 2222 | }; |
| 2222 | 2223 | }; |
| 2223 | 2224 | |
| ... | ... | @@ -4103,6 +4104,7 @@ const Writer = struct { |
| 4103 | 4104 | extra.data.return_type, |
| 4104 | 4105 | inferred_error_set, |
| 4105 | 4106 | false, |
| 4107 | false, | |
| 4106 | 4108 | .none, |
| 4107 | 4109 | .none, |
| 4108 | 4110 | body, |
| ... | ... | @@ -4150,6 +4152,7 @@ const Writer = struct { |
| 4150 | 4152 | extra.data.return_type, |
| 4151 | 4153 | small.is_inferred_error, |
| 4152 | 4154 | small.is_var_args, |
| 4155 | small.is_extern, | |
| 4153 | 4156 | cc, |
| 4154 | 4157 | align_inst, |
| 4155 | 4158 | body, |
| ... | ... | @@ -4232,6 +4235,7 @@ const Writer = struct { |
| 4232 | 4235 | ret_ty: Inst.Ref, |
| 4233 | 4236 | inferred_error_set: bool, |
| 4234 | 4237 | var_args: bool, |
| 4238 | is_extern: bool, | |
| 4235 | 4239 | cc: Inst.Ref, |
| 4236 | 4240 | align_inst: Inst.Ref, |
| 4237 | 4241 | body: []const Inst.Index, |
| ... | ... | @@ -4248,6 +4252,7 @@ const Writer = struct { |
| 4248 | 4252 | try self.writeOptionalInstRef(stream, ", cc=", cc); |
| 4249 | 4253 | try self.writeOptionalInstRef(stream, ", align=", align_inst); |
| 4250 | 4254 | try self.writeFlag(stream, ", vargs", var_args); |
| 4255 | try self.writeFlag(stream, ", extern", is_extern); | |
| 4251 | 4256 | try self.writeFlag(stream, ", inferror", inferred_error_set); |
| 4252 | 4257 | |
| 4253 | 4258 | if (body.len == 0) { |