| author | |
| committer | |
| log | 9acf06d28ac77a52028697dc01f42fd96c230ca9 |
| tree | 6c90921e6437293e84f137adce8364550f43ebb4 |
| parent | 3db130ff3d8175adce610f7805a149810cf7989d |
| parent | db9500a31401c65327a4fd556f50d74ce75fb858 |
| signature |
stage2: store externs lib name as part of decl8 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 | } |
| 502 | 502 | ||
| 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 | } |
| 692 | 697 | ||
| 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 | }; |
| 1322 | 1338 | ||
| 1339 | /// Some extern function struct memory is owned by the Decl's TypedValue.Managed | ||
| 1340 | /// arena allocator. | ||
| 1341 | pub 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 by | 1357 | /// 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. |
| 1326 | pub const Fn = struct { | 1359 | pub 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, |
| 1443 | 1476 | ||
| 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 | }; |
| 1448 | 1492 | ||
| 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 | } |
| 5433 | 5433 | ||
| 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`). | ||
| 5442 | fn 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 | |||
| 5434 | fn funcCommon( | 5497 | fn 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 | }; |
| 5570 | 5633 | ||
| 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 | } | ||
| 5616 | 5642 | ||
| 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 | } |
| 5623 | 5656 | ||
| 5624 | if (!has_body) { | 5657 | if (!has_body) { |
| ... | @@ -12444,13 +12477,8 @@ fn zirVarExtended( | ... | @@ -12444,13 +12477,8 @@ fn zirVarExtended( |
| 12444 | 12477 | ||
| 12445 | try sema.validateVarType(block, mut_src, var_ty, small.is_extern); | 12478 | try sema.validateVarType(block, mut_src, var_ty, small.is_extern); |
| 12446 | 12479 | ||
| 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); | ||
| 12454 | 12482 | ||
| 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 field | 12491 | .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)); | ||
| 1586 | 1593 | ||
| 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, |
| 265 | 265 | ||
| 266 | .extern_fn, | 266 | .extern_fn => Payload.ExternFn, |
| 267 | .decl_ref, | 267 | |
| 268 | => Payload.Decl, | 268 | .decl_ref => Payload.Decl, |
| 269 | 269 | ||
| 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(), | ||
| 1917 | 1919 | ||
| 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 | }; |
| 3303 | 3305 | ||
| 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, |