From 6ac204714236eaeaea5dc66afddbe158966b2532 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 7 May 2021 16:05:44 -0700 Subject: stage2: implement extern functions --- src/Module.zig | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index d84b4e2f35..1b935f65a9 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -282,13 +282,10 @@ pub const Decl = struct { pub fn destroy(decl: *Decl, module: *Module) void { const gpa = module.gpa; - log.debug("destroy Decl {*} ({s})", .{ decl, decl.name }); + log.debug("destroy {*} ({s})", .{ decl, decl.name }); decl.clearName(gpa); if (decl.has_tv) { - if (decl.getFunction()) |func| { - func.deinit(gpa); - gpa.destroy(func); - } else if (decl.val.getTypeNamespace()) |namespace| { + if (decl.val.getTypeNamespace()) |namespace| { if (namespace.getDecl() == decl) { namespace.clearDecls(module); } @@ -470,7 +467,6 @@ pub const Decl = struct { /// otherwise null. pub fn getFunction(decl: *Decl) ?*Fn { if (!decl.has_tv) return null; - if (decl.ty.zigTypeTag() != .Fn) return null; const func = (decl.val.castTag(.function) orelse return null).data; if (func.owner_decl != decl) return null; return func; @@ -2960,17 +2956,26 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { decl.clearValues(gpa); } - const new_variable = try decl_arena.allocator.create(Var); - new_variable.* = .{ - .owner_decl = decl, - .init = try decl_tv.val.copy(&decl_arena.allocator), - .is_extern = is_extern, - .is_mutable = is_mutable, - .is_threadlocal = is_threadlocal, + const copied_val = try decl_tv.val.copy(&decl_arena.allocator); + const is_extern_fn = copied_val.tag() == .extern_fn; + + // TODO: also avoid allocating this Var structure if `!is_mutable`. + // I think this will require adjusting Sema to copy the value or something + // like that; otherwise it causes use of undefined value when freeing resources. + const decl_val: Value = if (is_extern_fn) copied_val else blk: { + const new_variable = try decl_arena.allocator.create(Var); + new_variable.* = .{ + .owner_decl = decl, + .init = copied_val, + .is_extern = is_extern, + .is_mutable = is_mutable, + .is_threadlocal = is_threadlocal, + }; + break :blk try Value.Tag.variable.create(&decl_arena.allocator, new_variable); }; decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); - decl.val = try Value.Tag.variable.create(&decl_arena.allocator, new_variable); + decl.val = decl_val; decl.align_val = try align_val.copy(&decl_arena.allocator); decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); decl.has_tv = true; @@ -2984,6 +2989,16 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { // The scope needs to have the decl in it. try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); } + + if (decl.val.tag() == .extern_fn) { + try mod.comp.bin_file.allocateDeclIndexes(decl); + try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); + + if (type_changed and mod.emit_h != null) { + try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); + } + } + return type_changed; } } -- cgit v1.2.3