authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-07 13:30:59-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-07 13:30:59-05:00
log9acf06d28ac77a52028697dc01f42fd96c230ca9
tree6c90921e6437293e84f137adce8364550f43ebb4
parent3db130ff3d8175adce610f7805a149810cf7989d
parentdb9500a31401c65327a4fd556f50d74ce75fb858
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10803 from ziglang/decl-has-lib-name

stage2: store externs lib name as part of decl

8 files changed, 177 insertions(+), 78 deletions(-)

src/Module.zig+48-4
...@@ -501,11 +501,16 @@ pub const Decl = struct {...@@ -501,11 +501,16 @@ pub const Decl = struct {
501 }501 }
502502
503 pub fn clearValues(decl: *Decl, gpa: Allocator) void {503 pub fn clearValues(decl: *Decl, gpa: Allocator) void {
504 if (decl.getExternFn()) |extern_fn| {
505 extern_fn.deinit(gpa);
506 gpa.destroy(extern_fn);
507 }
504 if (decl.getFunction()) |func| {508 if (decl.getFunction()) |func| {
505 func.deinit(gpa);509 func.deinit(gpa);
506 gpa.destroy(func);510 gpa.destroy(func);
507 }511 }
508 if (decl.getVariable()) |variable| {512 if (decl.getVariable()) |variable| {
513 variable.deinit(gpa);
509 gpa.destroy(variable);514 gpa.destroy(variable);
510 }515 }
511 if (decl.value_arena) |arena_state| {516 if (decl.value_arena) |arena_state| {
...@@ -690,6 +695,17 @@ pub const Decl = struct {...@@ -690,6 +695,17 @@ pub const Decl = struct {
690 return func;695 return func;
691 }696 }
692697
698 /// If the Decl has a value and it is an extern function, returns it,
699 /// otherwise null.
700 pub fn getExternFn(decl: *const Decl) ?*ExternFn {
701 if (!decl.owns_tv) return null;
702 const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data;
703 assert(extern_fn.owner_decl == decl);
704 return extern_fn;
705 }
706
707 /// If the Decl has a value and it is a variable, returns it,
708 /// otherwise null.
693 pub fn getVariable(decl: *Decl) ?*Var {709 pub fn getVariable(decl: *Decl) ?*Var {
694 if (!decl.owns_tv) return null;710 if (!decl.owns_tv) return null;
695 const variable = (decl.val.castTag(.variable) orelse return null).data;711 const variable = (decl.val.castTag(.variable) orelse return null).data;
...@@ -1320,9 +1336,26 @@ pub const Opaque = struct {...@@ -1320,9 +1336,26 @@ pub const Opaque = struct {
1320 }1336 }
1321};1337};
13221338
1339/// Some extern function struct memory is owned by the Decl's TypedValue.Managed
1340/// arena allocator.
1341pub const ExternFn = struct {
1342 /// The Decl that corresponds to the function itself.
1343 owner_decl: *Decl,
1344 /// Library name if specified.
1345 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
1346 /// Allocated with Module's allocator; outlives the ZIR code.
1347 lib_name: ?[*:0]const u8,
1348
1349 pub fn deinit(extern_fn: *ExternFn, gpa: Allocator) void {
1350 if (extern_fn.lib_name) |lib_name| {
1351 gpa.free(mem.sliceTo(lib_name, 0));
1352 }
1353 }
1354};
1355
1323/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.1356/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
1324/// Extern functions do not have this data structure; they are represented by1357/// Extern functions do not have this data structure; they are represented by `ExternFn`
1325/// the `Decl` only, with a `Value` tag of `extern_fn`.1358/// instead.
1326pub const Fn = struct {1359pub const Fn = struct {
1327 /// The Decl that corresponds to the function itself.1360 /// The Decl that corresponds to the function itself.
1328 owner_decl: *Decl,1361 owner_decl: *Decl,
...@@ -1441,9 +1474,20 @@ pub const Var = struct {...@@ -1441,9 +1474,20 @@ pub const Var = struct {
1441 init: Value,1474 init: Value,
1442 owner_decl: *Decl,1475 owner_decl: *Decl,
14431476
1477 /// Library name if specified.
1478 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
1479 /// Allocated with Module's allocator; outlives the ZIR code.
1480 lib_name: ?[*:0]const u8,
1481
1444 is_extern: bool,1482 is_extern: bool,
1445 is_mutable: bool,1483 is_mutable: bool,
1446 is_threadlocal: bool,1484 is_threadlocal: bool,
1485
1486 pub fn deinit(variable: *Var, gpa: Allocator) void {
1487 if (variable.lib_name) |lib_name| {
1488 gpa.free(mem.sliceTo(lib_name, 0));
1489 }
1490 }
1447};1491};
14481492
1449/// The container that structs, enums, unions, and opaques have.1493/// The container that structs, enums, unions, and opaques have.
...@@ -3768,8 +3812,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {...@@ -3768,8 +3812,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
3768 }3812 }
3769 },3813 },
3770 .extern_fn => {3814 .extern_fn => {
3771 const owner_decl = decl_tv.val.castTag(.extern_fn).?.data;3815 const extern_fn = decl_tv.val.castTag(.extern_fn).?.data;
3772 if (decl == owner_decl) {3816 if (extern_fn.owner_decl == decl) {
3773 decl.owns_tv = true;3817 decl.owns_tv = true;
3774 queue_linker_work = true;3818 queue_linker_work = true;
3775 is_extern = true;3819 is_extern = true;
src/Sema.zig+89-55
...@@ -5431,6 +5431,69 @@ fn zirFunc(...@@ -5431,6 +5431,69 @@ fn zirFunc(
5431 );5431 );
5432}5432}
54335433
5434/// Given a library name, examines if the library name should end up in
5435/// `link.File.Options.system_libs` table (for example, libc is always
5436/// specified via dedicated flag `link.File.Options.link_libc` instead),
5437/// and puts it there if it doesn't exist.
5438/// It also dupes the library name which can then be saved as part of the
5439/// respective `Decl` (either `ExternFn` or `Var`).
5440/// The liveness of the duped library name is tied to liveness of `Module`.
5441/// To deallocate, call `deinit` on the respective `Decl` (`ExternFn` or `Var`).
5442fn handleExternLibName(
5443 sema: *Sema,
5444 block: *Block,
5445 src_loc: LazySrcLoc,
5446 lib_name: []const u8,
5447) CompileError![:0]u8 {
5448 blk: {
5449 const mod = sema.mod;
5450 const target = mod.getTarget();
5451 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});
5452 if (target_util.is_libc_lib_name(target, lib_name)) {
5453 if (!mod.comp.bin_file.options.link_libc) {
5454 return sema.fail(
5455 block,
5456 src_loc,
5457 "dependency on libc must be explicitly specified in the build command",
5458 .{},
5459 );
5460 }
5461 mod.comp.bin_file.options.link_libc = true;
5462 break :blk;
5463 }
5464 if (target_util.is_libcpp_lib_name(target, lib_name)) {
5465 if (!mod.comp.bin_file.options.link_libcpp) {
5466 return sema.fail(
5467 block,
5468 src_loc,
5469 "dependency on libc++ must be explicitly specified in the build command",
5470 .{},
5471 );
5472 }
5473 mod.comp.bin_file.options.link_libcpp = true;
5474 break :blk;
5475 }
5476 if (mem.eql(u8, lib_name, "unwind")) {
5477 mod.comp.bin_file.options.link_libunwind = true;
5478 break :blk;
5479 }
5480 if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
5481 return sema.fail(
5482 block,
5483 src_loc,
5484 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
5485 .{ lib_name, lib_name },
5486 );
5487 }
5488 mod.comp.stage1AddLinkLib(lib_name) catch |err| {
5489 return sema.fail(block, src_loc, "unable to add link lib '{s}': {s}", .{
5490 lib_name, @errorName(err),
5491 });
5492 };
5493 }
5494 return sema.gpa.dupeZ(u8, lib_name);
5495}
5496
5434fn funcCommon(5497fn funcCommon(
5435 sema: *Sema,5498 sema: *Sema,
5436 block: *Block,5499 block: *Block,
...@@ -5568,57 +5631,27 @@ fn funcCommon(...@@ -5568,57 +5631,27 @@ fn funcCommon(
5568 });5631 });
5569 };5632 };
55705633
5571 if (opt_lib_name) |lib_name| blk: {5634 if (is_extern) {
5572 const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset };5635 const new_extern_fn = try sema.gpa.create(Module.ExternFn);
5573 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});5636 errdefer sema.gpa.destroy(new_extern_fn);
5574 if (target_util.is_libc_lib_name(target, lib_name)) {5637
5575 if (!mod.comp.bin_file.options.link_libc) {5638 new_extern_fn.* = Module.ExternFn{
5576 return sema.fail(5639 .owner_decl = sema.owner_decl,
5577 block,5640 .lib_name = null,
5578 lib_name_src,
5579 "dependency on libc must be explicitly specified in the build command",
5580 .{},
5581 );
5582 }
5583 mod.comp.bin_file.options.link_libc = true;
5584 break :blk;
5585 }
5586 if (target_util.is_libcpp_lib_name(target, lib_name)) {
5587 if (!mod.comp.bin_file.options.link_libcpp) {
5588 return sema.fail(
5589 block,
5590 lib_name_src,
5591 "dependency on libc++ must be explicitly specified in the build command",
5592 .{},
5593 );
5594 }
5595 mod.comp.bin_file.options.link_libcpp = true;
5596 break :blk;
5597 }
5598 if (mem.eql(u8, lib_name, "unwind")) {
5599 mod.comp.bin_file.options.link_libunwind = true;
5600 break :blk;
5601 }
5602 if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
5603 return sema.fail(
5604 block,
5605 lib_name_src,
5606 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
5607 .{ lib_name, lib_name },
5608 );
5609 }
5610 mod.comp.stage1AddLinkLib(lib_name) catch |err| {
5611 return sema.fail(block, lib_name_src, "unable to add link lib '{s}': {s}", .{
5612 lib_name, @errorName(err),
5613 });
5614 };5641 };
5615 }
56165642
5617 if (is_extern) {5643 if (opt_lib_name) |lib_name| {
5618 return sema.addConstant(5644 new_extern_fn.lib_name = try sema.handleExternLibName(block, .{
5619 fn_ty,5645 .node_offset_lib_name = src_node_offset,
5620 try Value.Tag.extern_fn.create(sema.arena, sema.owner_decl),5646 }, lib_name);
5621 );5647 }
5648
5649 const extern_fn_payload = try sema.arena.create(Value.Payload.ExternFn);
5650 extern_fn_payload.* = .{
5651 .base = .{ .tag = .extern_fn },
5652 .data = new_extern_fn,
5653 };
5654 return sema.addConstant(fn_ty, Value.initPayload(&extern_fn_payload.base));
5622 }5655 }
56235656
5624 if (!has_body) {5657 if (!has_body) {
...@@ -12444,13 +12477,8 @@ fn zirVarExtended(...@@ -12444,13 +12477,8 @@ fn zirVarExtended(
1244412477
12445 try sema.validateVarType(block, mut_src, var_ty, small.is_extern);12478 try sema.validateVarType(block, mut_src, var_ty, small.is_extern);
1244612479
12447 if (lib_name != null) {
12448 // Look at the sema code for functions which has this logic, it just needs to
12449 // be extracted and shared by both var and func
12450 return sema.fail(block, src, "TODO: handle var with lib_name in Sema", .{});
12451 }
12452
12453 const new_var = try sema.gpa.create(Module.Var);12480 const new_var = try sema.gpa.create(Module.Var);
12481 errdefer sema.gpa.destroy(new_var);
1245412482
12455 log.debug("created variable {*} owner_decl: {*} ({s})", .{12483 log.debug("created variable {*} owner_decl: {*} ({s})", .{
12456 new_var, sema.owner_decl, sema.owner_decl.name,12484 new_var, sema.owner_decl, sema.owner_decl.name,
...@@ -12462,7 +12490,13 @@ fn zirVarExtended(...@@ -12462,7 +12490,13 @@ fn zirVarExtended(
12462 .is_extern = small.is_extern,12490 .is_extern = small.is_extern,
12463 .is_mutable = true, // TODO get rid of this unused field12491 .is_mutable = true, // TODO get rid of this unused field
12464 .is_threadlocal = small.is_threadlocal,12492 .is_threadlocal = small.is_threadlocal,
12493 .lib_name = null,
12465 };12494 };
12495
12496 if (lib_name) |lname| {
12497 new_var.lib_name = try sema.handleExternLibName(block, ty_src, lname);
12498 }
12499
12466 const result = try sema.addConstant(12500 const result = try sema.addConstant(
12467 var_ty,12501 var_ty,
12468 try Value.Tag.variable.create(sema.arena, new_var),12502 try Value.Tag.variable.create(sema.arena, new_var),
src/arch/aarch64/CodeGen.zig+9-2
...@@ -1581,8 +1581,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -1581,8 +1581,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
1581 .data = .{ .reg = .x30 },1581 .data = .{ .reg = .x30 },
1582 });1582 });
1583 } else if (func_value.castTag(.extern_fn)) |func_payload| {1583 } else if (func_value.castTag(.extern_fn)) |func_payload| {
1584 const decl = func_payload.data;1584 const extern_fn = func_payload.data;
1585 const n_strx = try macho_file.addExternFn(mem.sliceTo(decl.name, 0));1585 const decl_name = extern_fn.owner_decl.name;
1586 if (extern_fn.lib_name) |lib_name| {
1587 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
1588 decl_name,
1589 lib_name,
1590 });
1591 }
1592 const n_strx = try macho_file.addExternFn(mem.sliceTo(decl_name, 0));
15861593
1587 _ = try self.addInst(.{1594 _ = try self.addInst(.{
1588 .tag = .call_extern,1595 .tag = .call_extern,
src/arch/wasm/CodeGen.zig+3-3
...@@ -952,7 +952,7 @@ pub const DeclGen = struct {...@@ -952,7 +952,7 @@ pub const DeclGen = struct {
952 _ = func_payload;952 _ = func_payload;
953 return self.fail("TODO wasm backend genDecl function pointer", .{});953 return self.fail("TODO wasm backend genDecl function pointer", .{});
954 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {954 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {
955 const ext_decl = extern_fn.data;955 const ext_decl = extern_fn.data.owner_decl;
956 var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target());956 var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target());
957 func_type.deinit(self.gpa);957 func_type.deinit(self.gpa);
958 ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);958 ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
...@@ -978,7 +978,7 @@ pub const DeclGen = struct {...@@ -978,7 +978,7 @@ pub const DeclGen = struct {
978 switch (ty.zigTypeTag()) {978 switch (ty.zigTypeTag()) {
979 .Fn => {979 .Fn => {
980 const fn_decl = switch (val.tag()) {980 const fn_decl = switch (val.tag()) {
981 .extern_fn => val.castTag(.extern_fn).?.data,981 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
982 .function => val.castTag(.function).?.data.owner_decl,982 .function => val.castTag(.function).?.data.owner_decl,
983 else => unreachable,983 else => unreachable,
984 };984 };
...@@ -1776,7 +1776,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1776,7 +1776,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1776 if (func_val.castTag(.function)) |func| {1776 if (func_val.castTag(.function)) |func| {
1777 break :blk func.data.owner_decl;1777 break :blk func.data.owner_decl;
1778 } else if (func_val.castTag(.extern_fn)) |ext_fn| {1778 } else if (func_val.castTag(.extern_fn)) |ext_fn| {
1779 break :blk ext_fn.data;1779 break :blk ext_fn.data.owner_decl;
1780 } else if (func_val.castTag(.decl_ref)) |decl_ref| {1780 } else if (func_val.castTag(.decl_ref)) |decl_ref| {
1781 break :blk decl_ref.data;1781 break :blk decl_ref.data;
1782 }1782 }
src/arch/x86_64/CodeGen.zig+9-2
...@@ -2566,8 +2566,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2566,8 +2566,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2566 .data = undefined,2566 .data = undefined,
2567 });2567 });
2568 } else if (func_value.castTag(.extern_fn)) |func_payload| {2568 } else if (func_value.castTag(.extern_fn)) |func_payload| {
2569 const decl = func_payload.data;2569 const extern_fn = func_payload.data;
2570 const n_strx = try macho_file.addExternFn(mem.sliceTo(decl.name, 0));2570 const decl_name = extern_fn.owner_decl.name;
2571 if (extern_fn.lib_name) |lib_name| {
2572 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
2573 decl_name,
2574 lib_name,
2575 });
2576 }
2577 const n_strx = try macho_file.addExternFn(mem.sliceTo(decl_name, 0));
2571 _ = try self.addInst(.{2578 _ = try self.addInst(.{
2572 .tag = .call_extern,2579 .tag = .call_extern,
2573 .ops = undefined,2580 .ops = undefined,
src/codegen/c.zig+4-4
...@@ -542,8 +542,8 @@ pub const DeclGen = struct {...@@ -542,8 +542,8 @@ pub const DeclGen = struct {
542 try dg.renderDeclName(func.owner_decl, writer);542 try dg.renderDeclName(func.owner_decl, writer);
543 },543 },
544 .extern_fn => {544 .extern_fn => {
545 const decl = val.castTag(.extern_fn).?.data;545 const extern_fn = val.castTag(.extern_fn).?.data;
546 try dg.renderDeclName(decl, writer);546 try dg.renderDeclName(extern_fn.owner_decl, writer);
547 },547 },
548 .int_u64, .one => {548 .int_u64, .one => {
549 try writer.writeAll("((");549 try writer.writeAll("((");
...@@ -681,7 +681,7 @@ pub const DeclGen = struct {...@@ -681,7 +681,7 @@ pub const DeclGen = struct {
681 return dg.renderDeclValue(writer, ty, val, decl);681 return dg.renderDeclValue(writer, ty, val, decl);
682 },682 },
683 .extern_fn => {683 .extern_fn => {
684 const decl = val.castTag(.extern_fn).?.data;684 const decl = val.castTag(.extern_fn).?.data.owner_decl;
685 return dg.renderDeclValue(writer, ty, val, decl);685 return dg.renderDeclValue(writer, ty, val, decl);
686 },686 },
687 else => unreachable,687 else => unreachable,
...@@ -2442,7 +2442,7 @@ fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2442,7 +2442,7 @@ fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {
2442 const fn_decl = fn_decl: {2442 const fn_decl = fn_decl: {
2443 const callee_val = f.air.value(pl_op.operand) orelse break :known;2443 const callee_val = f.air.value(pl_op.operand) orelse break :known;
2444 break :fn_decl switch (callee_val.tag()) {2444 break :fn_decl switch (callee_val.tag()) {
2445 .extern_fn => callee_val.castTag(.extern_fn).?.data,2445 .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,
2446 .function => callee_val.castTag(.function).?.data.owner_decl,2446 .function => callee_val.castTag(.function).?.data.owner_decl,
2447 .decl_ref => callee_val.castTag(.decl_ref).?.data,2447 .decl_ref => callee_val.castTag(.decl_ref).?.data,
2448 else => break :known,2448 else => break :known,
src/codegen/llvm.zig+2-2
...@@ -622,7 +622,7 @@ pub const DeclGen = struct {...@@ -622,7 +622,7 @@ pub const DeclGen = struct {
622 _ = func_payload;622 _ = func_payload;
623 @panic("TODO llvm backend genDecl function pointer");623 @panic("TODO llvm backend genDecl function pointer");
624 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {624 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {
625 _ = try dg.resolveLlvmFunction(extern_fn.data);625 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
626 } else {626 } else {
627 const target = dg.module.getTarget();627 const target = dg.module.getTarget();
628 const global = try dg.resolveGlobalDecl(decl);628 const global = try dg.resolveGlobalDecl(decl);
...@@ -1410,7 +1410,7 @@ pub const DeclGen = struct {...@@ -1410,7 +1410,7 @@ pub const DeclGen = struct {
1410 },1410 },
1411 .Fn => {1411 .Fn => {
1412 const fn_decl = switch (tv.val.tag()) {1412 const fn_decl = switch (tv.val.tag()) {
1413 .extern_fn => tv.val.castTag(.extern_fn).?.data,1413 .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,
1414 .function => tv.val.castTag(.function).?.data.owner_decl,1414 .function => tv.val.castTag(.function).?.data.owner_decl,
1415 else => unreachable,1415 else => unreachable,
1416 };1416 };
src/value.zig+13-6
...@@ -263,9 +263,9 @@ pub const Value = extern union {...@@ -263,9 +263,9 @@ pub const Value = extern union {
263 .int_big_negative,263 .int_big_negative,
264 => Payload.BigInt,264 => Payload.BigInt,
265265
266 .extern_fn,266 .extern_fn => Payload.ExternFn,
267 .decl_ref,267
268 => Payload.Decl,268 .decl_ref => Payload.Decl,
269269
270 .repeated,270 .repeated,
271 .eu_payload,271 .eu_payload,
...@@ -477,7 +477,7 @@ pub const Value = extern union {...@@ -477,7 +477,7 @@ pub const Value = extern union {
477 return Value{ .ptr_otherwise = &new_payload.base };477 return Value{ .ptr_otherwise = &new_payload.base };
478 },478 },
479 .function => return self.copyPayloadShallow(arena, Payload.Function),479 .function => return self.copyPayloadShallow(arena, Payload.Function),
480 .extern_fn => return self.copyPayloadShallow(arena, Payload.Decl),480 .extern_fn => return self.copyPayloadShallow(arena, Payload.ExternFn),
481 .variable => return self.copyPayloadShallow(arena, Payload.Variable),481 .variable => return self.copyPayloadShallow(arena, Payload.Variable),
482 .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl),482 .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl),
483 .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut),483 .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut),
...@@ -1842,9 +1842,10 @@ pub const Value = extern union {...@@ -1842,9 +1842,10 @@ pub const Value = extern union {
1842 pub fn pointerDecl(val: Value) ?*Module.Decl {1842 pub fn pointerDecl(val: Value) ?*Module.Decl {
1843 return switch (val.tag()) {1843 return switch (val.tag()) {
1844 .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl,1844 .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl,
1845 .extern_fn, .decl_ref => val.cast(Payload.Decl).?.data,1845 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
1846 .function => val.castTag(.function).?.data.owner_decl,1846 .function => val.castTag(.function).?.data.owner_decl,
1847 .variable => val.castTag(.variable).?.data.owner_decl,1847 .variable => val.castTag(.variable).?.data.owner_decl,
1848 .decl_ref => val.cast(Payload.Decl).?.data,
1848 else => null,1849 else => null,
1849 };1850 };
1850 }1851 }
...@@ -1911,9 +1912,10 @@ pub const Value = extern union {...@@ -1911,9 +1912,10 @@ pub const Value = extern union {
1911 pub fn markReferencedDeclsAlive(val: Value) void {1912 pub fn markReferencedDeclsAlive(val: Value) void {
1912 switch (val.tag()) {1913 switch (val.tag()) {
1913 .decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.markAlive(),1914 .decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.markAlive(),
1914 .extern_fn, .decl_ref => return val.cast(Payload.Decl).?.data.markAlive(),1915 .extern_fn => return val.castTag(.extern_fn).?.data.owner_decl.markAlive(),
1915 .function => return val.castTag(.function).?.data.owner_decl.markAlive(),1916 .function => return val.castTag(.function).?.data.owner_decl.markAlive(),
1916 .variable => return val.castTag(.variable).?.data.owner_decl.markAlive(),1917 .variable => return val.castTag(.variable).?.data.owner_decl.markAlive(),
1918 .decl_ref => return val.cast(Payload.Decl).?.data.markAlive(),
19171919
1918 .repeated,1920 .repeated,
1919 .eu_payload,1921 .eu_payload,
...@@ -3301,6 +3303,11 @@ pub const Value = extern union {...@@ -3301,6 +3303,11 @@ pub const Value = extern union {
3301 data: *Module.Fn,3303 data: *Module.Fn,
3302 };3304 };
33033305
3306 pub const ExternFn = struct {
3307 base: Payload,
3308 data: *Module.ExternFn,
3309 };
3310
3304 pub const Decl = struct {3311 pub const Decl = struct {
3305 base: Payload,3312 base: Payload,
3306 data: *Module.Decl,3313 data: *Module.Decl,