| ... | @@ -5430,6 +5430,69 @@ fn zirFunc( | ... | @@ -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 | fn funcCommon( | 5496 | fn funcCommon( |
| 5434 | sema: *Sema, | 5497 | sema: *Sema, |
| 5435 | block: *Block, | 5498 | block: *Block, |
| ... | @@ -5567,65 +5630,21 @@ fn funcCommon( | ... | @@ -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 | if (is_extern) { | 5633 | if (is_extern) { |
| 5617 | const new_extern_fn = try sema.gpa.create(Module.ExternFn); | 5634 | const new_extern_fn = try sema.gpa.create(Module.ExternFn); |
| 5618 | errdefer sema.gpa.destroy(new_extern_fn); | 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 | new_extern_fn.* = Module.ExternFn{ | 5637 | new_extern_fn.* = Module.ExternFn{ |
| 5625 | .owner_decl = sema.owner_decl, | 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 | const extern_fn_payload = try sema.arena.create(Value.Payload.ExternFn); | 5648 | const extern_fn_payload = try sema.arena.create(Value.Payload.ExternFn); |
| 5630 | extern_fn_payload.* = .{ | 5649 | extern_fn_payload.* = .{ |
| 5631 | .base = .{ .tag = .extern_fn }, | 5650 | .base = .{ .tag = .extern_fn }, |
| ... | @@ -12456,13 +12475,8 @@ fn zirVarExtended( | ... | @@ -12456,13 +12475,8 @@ fn zirVarExtended( |
| 12456 | | 12475 | |
| 12457 | try sema.validateVarType(block, mut_src, var_ty, small.is_extern); | 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 | const new_var = try sema.gpa.create(Module.Var); | 12478 | const new_var = try sema.gpa.create(Module.Var); |
| | 12479 | errdefer sema.gpa.destroy(new_var); |
| 12466 | | 12480 | |
| 12467 | log.debug("created variable {*} owner_decl: {*} ({s})", .{ | 12481 | log.debug("created variable {*} owner_decl: {*} ({s})", .{ |
| 12468 | new_var, sema.owner_decl, sema.owner_decl.name, | 12482 | new_var, sema.owner_decl, sema.owner_decl.name, |
| ... | @@ -12474,7 +12488,13 @@ fn zirVarExtended( | ... | @@ -12474,7 +12488,13 @@ fn zirVarExtended( |
| 12474 | .is_extern = small.is_extern, | 12488 | .is_extern = small.is_extern, |
| 12475 | .is_mutable = true, // TODO get rid of this unused field | 12489 | .is_mutable = true, // TODO get rid of this unused field |
| 12476 | .is_threadlocal = small.is_threadlocal, | 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 | const result = try sema.addConstant( | 12498 | const result = try sema.addConstant( |
| 12479 | var_ty, | 12499 | var_ty, |
| 12480 | try Value.Tag.variable.create(sema.arena, new_var), | 12500 | try Value.Tag.variable.create(sema.arena, new_var), |