| ... | ... | @@ -5430,6 +5430,69 @@ fn zirFunc( |
| 5430 | 5430 | ); |
| 5431 | 5431 | } |
| 5432 | 5432 | |
| 5433 | /// Given a library name, examines if the library name should end up in |
| 5434 | /// `link.File.Options.system_libs` table (for example, libc is always |
| 5435 | /// specified via dedicated flag `link.File.Options.link_libc` instead), |
| 5436 | /// and puts it there if it doesn't exist. |
| 5437 | /// It also dupes the library name which can then be saved as part of the |
| 5438 | /// respective `Decl` (either `ExternFn` or `Var`). |
| 5439 | /// The liveness of the duped library name is tied to liveness of `Module`. |
| 5440 | /// To deallocate, call `deinit` on the respective `Decl` (`ExternFn` or `Var`). |
| 5441 | fn handleExternLibName( |
| 5442 | sema: *Sema, |
| 5443 | block: *Block, |
| 5444 | src_loc: LazySrcLoc, |
| 5445 | lib_name: []const u8, |
| 5446 | ) CompileError![:0]u8 { |
| 5447 | blk: { |
| 5448 | const mod = sema.mod; |
| 5449 | const target = mod.getTarget(); |
| 5450 | log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); |
| 5451 | if (target_util.is_libc_lib_name(target, lib_name)) { |
| 5452 | if (!mod.comp.bin_file.options.link_libc) { |
| 5453 | return sema.fail( |
| 5454 | block, |
| 5455 | src_loc, |
| 5456 | "dependency on libc must be explicitly specified in the build command", |
| 5457 | .{}, |
| 5458 | ); |
| 5459 | } |
| 5460 | mod.comp.bin_file.options.link_libc = true; |
| 5461 | break :blk; |
| 5462 | } |
| 5463 | if (target_util.is_libcpp_lib_name(target, lib_name)) { |
| 5464 | if (!mod.comp.bin_file.options.link_libcpp) { |
| 5465 | return sema.fail( |
| 5466 | block, |
| 5467 | src_loc, |
| 5468 | "dependency on libc++ must be explicitly specified in the build command", |
| 5469 | .{}, |
| 5470 | ); |
| 5471 | } |
| 5472 | mod.comp.bin_file.options.link_libcpp = true; |
| 5473 | break :blk; |
| 5474 | } |
| 5475 | if (mem.eql(u8, lib_name, "unwind")) { |
| 5476 | mod.comp.bin_file.options.link_libunwind = true; |
| 5477 | break :blk; |
| 5478 | } |
| 5479 | if (!target.isWasm() and !mod.comp.bin_file.options.pic) { |
| 5480 | return sema.fail( |
| 5481 | block, |
| 5482 | src_loc, |
| 5483 | "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.", |
| 5484 | .{ lib_name, lib_name }, |
| 5485 | ); |
| 5486 | } |
| 5487 | mod.comp.stage1AddLinkLib(lib_name) catch |err| { |
| 5488 | return sema.fail(block, src_loc, "unable to add link lib '{s}': {s}", .{ |
| 5489 | lib_name, @errorName(err), |
| 5490 | }); |
| 5491 | }; |
| 5492 | } |
| 5493 | return sema.gpa.dupeZ(u8, lib_name); |
| 5494 | } |
| 5495 | |
| 5433 | 5496 | fn funcCommon( |
| 5434 | 5497 | sema: *Sema, |
| 5435 | 5498 | block: *Block, |
| ... | ... | @@ -5567,65 +5630,21 @@ fn funcCommon( |
| 5567 | 5630 | }); |
| 5568 | 5631 | }; |
| 5569 | 5632 | |
| 5570 | | if (opt_lib_name) |lib_name| blk: { |
| 5571 | | const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset }; |
| 5572 | | log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); |
| 5573 | | if (target_util.is_libc_lib_name(target, lib_name)) { |
| 5574 | | if (!mod.comp.bin_file.options.link_libc) { |
| 5575 | | return sema.fail( |
| 5576 | | block, |
| 5577 | | lib_name_src, |
| 5578 | | "dependency on libc must be explicitly specified in the build command", |
| 5579 | | .{}, |
| 5580 | | ); |
| 5581 | | } |
| 5582 | | mod.comp.bin_file.options.link_libc = true; |
| 5583 | | break :blk; |
| 5584 | | } |
| 5585 | | if (target_util.is_libcpp_lib_name(target, lib_name)) { |
| 5586 | | if (!mod.comp.bin_file.options.link_libcpp) { |
| 5587 | | return sema.fail( |
| 5588 | | block, |
| 5589 | | lib_name_src, |
| 5590 | | "dependency on libc++ must be explicitly specified in the build command", |
| 5591 | | .{}, |
| 5592 | | ); |
| 5593 | | } |
| 5594 | | mod.comp.bin_file.options.link_libcpp = true; |
| 5595 | | break :blk; |
| 5596 | | } |
| 5597 | | if (mem.eql(u8, lib_name, "unwind")) { |
| 5598 | | mod.comp.bin_file.options.link_libunwind = true; |
| 5599 | | break :blk; |
| 5600 | | } |
| 5601 | | if (!target.isWasm() and !mod.comp.bin_file.options.pic) { |
| 5602 | | return sema.fail( |
| 5603 | | block, |
| 5604 | | lib_name_src, |
| 5605 | | "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.", |
| 5606 | | .{ lib_name, lib_name }, |
| 5607 | | ); |
| 5608 | | } |
| 5609 | | mod.comp.stage1AddLinkLib(lib_name) catch |err| { |
| 5610 | | return sema.fail(block, lib_name_src, "unable to add link lib '{s}': {s}", .{ |
| 5611 | | lib_name, @errorName(err), |
| 5612 | | }); |
| 5613 | | }; |
| 5614 | | } |
| 5615 | | |
| 5616 | 5633 | if (is_extern) { |
| 5617 | 5634 | const new_extern_fn = try sema.gpa.create(Module.ExternFn); |
| 5618 | 5635 | errdefer sema.gpa.destroy(new_extern_fn); |
| 5619 | 5636 | |
| 5620 | | const lib_name: ?[*:0]const u8 = if (opt_lib_name) |lib_name| blk: { |
| 5621 | | break :blk try sema.gpa.dupeZ(u8, lib_name); |
| 5622 | | } else null; |
| 5623 | | |
| 5624 | 5637 | new_extern_fn.* = Module.ExternFn{ |
| 5625 | 5638 | .owner_decl = sema.owner_decl, |
| 5626 | | .lib_name = lib_name, |
| 5639 | .lib_name = null, |
| 5627 | 5640 | }; |
| 5628 | 5641 | |
| 5642 | if (opt_lib_name) |lib_name| { |
| 5643 | new_extern_fn.lib_name = try sema.handleExternLibName(block, .{ |
| 5644 | .node_offset_lib_name = src_node_offset, |
| 5645 | }, lib_name); |
| 5646 | } |
| 5647 | |
| 5629 | 5648 | const extern_fn_payload = try sema.arena.create(Value.Payload.ExternFn); |
| 5630 | 5649 | extern_fn_payload.* = .{ |
| 5631 | 5650 | .base = .{ .tag = .extern_fn }, |
| ... | ... | @@ -12456,13 +12475,8 @@ fn zirVarExtended( |
| 12456 | 12475 | |
| 12457 | 12476 | try sema.validateVarType(block, mut_src, var_ty, small.is_extern); |
| 12458 | 12477 | |
| 12459 | | if (lib_name != null) { |
| 12460 | | // Look at the sema code for functions which has this logic, it just needs to |
| 12461 | | // be extracted and shared by both var and func |
| 12462 | | return sema.fail(block, src, "TODO: handle var with lib_name in Sema", .{}); |
| 12463 | | } |
| 12464 | | |
| 12465 | 12478 | const new_var = try sema.gpa.create(Module.Var); |
| 12479 | errdefer sema.gpa.destroy(new_var); |
| 12466 | 12480 | |
| 12467 | 12481 | log.debug("created variable {*} owner_decl: {*} ({s})", .{ |
| 12468 | 12482 | new_var, sema.owner_decl, sema.owner_decl.name, |
| ... | ... | @@ -12474,7 +12488,13 @@ fn zirVarExtended( |
| 12474 | 12488 | .is_extern = small.is_extern, |
| 12475 | 12489 | .is_mutable = true, // TODO get rid of this unused field |
| 12476 | 12490 | .is_threadlocal = small.is_threadlocal, |
| 12491 | .lib_name = null, |
| 12477 | 12492 | }; |
| 12493 | |
| 12494 | if (lib_name) |lname| { |
| 12495 | new_var.lib_name = try sema.handleExternLibName(block, ty_src, lname); |
| 12496 | } |
| 12497 | |
| 12478 | 12498 | const result = try sema.addConstant( |
| 12479 | 12499 | var_ty, |
| 12480 | 12500 | try Value.Tag.variable.create(sema.arena, new_var), |