Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Integrate LLD, the LLVM cross-linker #2028

Closed
kinke opened this issue Mar 8, 2017 · 25 comments
Closed

Feature: Integrate LLD, the LLVM cross-linker #2028

kinke opened this issue Mar 8, 2017 · 25 comments

Comments

@kinke
Copy link
Member

kinke commented Mar 8, 2017

My tests some weeks ago with LLD 3.9 on Win64 have shown that it really works out-of-the-box as drop-in replacement (lld-link.exe for DLLs and executables, llvm-lib.exe for static libraries) for Microsoft's tools, reading the same environment variables etc. All tests passed except for our CDB debugging tests, as debuginfos on Windows (.pdb) aren't implemented yet, that's the only drawback.

While LLD is supposed to be compact & fast and naturally allows for LLVM goodness like LTO, I see the primary advantage in getting rid of LDC's dependency on a target linker and gaining the ability to directly cross-compile and -link. All you need are the target system libs + target druntime/Phobos, and you'll be able to generate shared libs and executables for about any target supported by LLVM. No need for an external cross-linker or linking natively / in an emulator.

By linking the LLD library into LDC directly, we should be able to forward pretty much unchanged command lines to one of the 3 drivers, depending on targeted platform, instead of invoking the external linker (which should still be possible via cmdline option).
Without relying on an external LLD executable, detecting the MSVC++ installation and setting up the environment variables on Windows will have to be moved from the currently used batch files to LDC itself.

@JohanEngelen
Copy link
Member

This'd be really great.

How do you propose to expose this to the user? Add a -link-with-lld/-internal-linker cmdline flag?

@kinke
Copy link
Member Author

kinke commented Mar 8, 2017

In the long run and assuming LLD will turn out nearly perfectly compatible (in terms of command-line semantics, incl. .pdb generation) to the 3 system linkers, I'd prefer it to be the default setting and letting users specify an external linker to be invoked via -linker= and archiver/librarian via -archiver= (or so).
In the meantime, exposing it opt-in via something like your proposals sounds good.

@kinke
Copy link
Member Author

kinke commented Mar 8, 2017

@JohanEngelen: Wrt. your question in the forum, I assume(d) LLD features LTO directly, not requiring any plugin.

I simply cloned the lld repo into llvm/tools, rebuilt LLVM, hacked LDC to make use of the LLVM tools (link.exe => lld-link.exe, lib.exe => llvm-lib.exe) and ran our test-suite. :)

Edit: Oh wait, there's a 27M LTO.dll file in the LLVM installation directory. So apparently built & installed by default on Windows.
Edit2: I (willingly) included LLD (and unknowingly LTO.dll) in the prebuilt LLVM 3.9.1 for AppVeyor. I guess that basically makes LTO on Windows testable via AppVeyor.

@JohanEngelen
Copy link
Member

JohanEngelen commented Mar 8, 2017

Wrt. your question in the forum, I assume LLD features LTO directly, not requiring any plugin.

Yeah :)

Edit: see http://releases.llvm.org/3.9.0/tools/lld/docs/ReleaseNotes.html#link-time-optimization

@kinke
Copy link
Member Author

kinke commented Mar 17, 2017

@klickverbot etc.: What's the rationale for using gcc as linker driver on non-Windows instead of ld directly? As LLD is a drop-in replacement for ld, integrating it would be simpler if we invoked the system ld.

@dnadlinger
Copy link
Member

What's the rationale for using gcc as linker driver on non-Windows

@kinke: D programs implicitly link against the C runtime. Using gcc as the linker driver makes sure the C runtime (whatever it might be for the system/target in question) is linked automatically.

@dnadlinger
Copy link
Member

(Other languages – e.g. Rust, … – tend to do the same.)

@kinke
Copy link
Member Author

kinke commented Mar 20, 2017

I thought locating the MS tools and setting up the MSVC environment variables on Windows would be a pain. Comparing this with how it's done on Linux (on Ubuntu, gcc -> collect2 -> ld, with a huge and extremely ugly command line viewable via gcc -v -o foo foo.obj), it's actually a bliss. Integrating LLD for Windows targets would now take a couple of minutes (mainly figuring out the needed LLD libs), but that's exactly the platform which still needs some work (.pdb). So I'll let this rest for the time being.

@WebDrake
Copy link
Contributor

@kinke: D programs implicitly link against the C runtime. Using gcc as the linker driver makes sure the C runtime (whatever it might be for the system/target in question) is linked automatically.

But that nevertheless produces quite a strong constraint on usage options. Could it make sense to instead allow the user to specify a choice of linker (with gcc being the default) together with an option to specify the location of the C runtime to use, for the cases where the chosen linker doesn't automatically know?

Vested (though speculative) interest: it might be a good idea for the snap-packaged LDC to insist on linking against the C runtime from the core snap, instead of the host system.

@dnadlinger
Copy link
Member

Could it make sense to instead allow the user to specify a choice of linker

Exists today in the form of the CC environment variable and other hidden options.

together with an option to specify the location of the C runtime to use, for the cases where the chosen linker doesn't automatically know?

There doesn't need to be an option for that, just add it to the linker flags, or point LDC to a wrapper ("driver", in case you feel fancy) script for the linker executable that adds the appropriate option.

@WebDrake
Copy link
Contributor

Exists today in the form of the CC environment variable and other hidden options.

So LDC actually uses the CC environment variable as its linker driver? Perhaps it would be as well to stop so explicitly talking about the use of gcc as the linker? Or is there a stronger assumption about what CC is in practice?

@dnadlinger
Copy link
Member

Perhaps it would be as well to stop so explicitly talking about the use of gcc as the linker?

Yes – well, as long as it is able to resolve it to an actual executable path. Apart from Windows/MSVC, though, LDC assumes a GCC-compatible command line syntax for the linker, so talking about gcc is probably quite warranted.

@WebDrake
Copy link
Contributor

LDC assumes a GCC-compatible command line syntax for the linker, so talking about gcc is probably quite warranted.

That's what I suspected. But could one invoke LDC specifying CC=ld (plus appropriate linker flags) and expect it to succesfully invoke ld as the linker?

@kinke
Copy link
Member Author

kinke commented Apr 10, 2017

Nope, that's exactly the problem, see https://github.com/ldc-developers/ldc/blob/master/driver/linker.cpp#L289. The -shared flag for instance has totally different semantics for gcc and ld.

@dnadlinger
Copy link
Member

But could one invoke LDC specifying CC=ld (plus appropriate linker flags) and expect it to succesfully invoke ld as the linker?

Unfortunately no, as it will translate -L into -Xlinker and so on, which ld won't understand. If you wanted to submit a PR that adds a flag to specify the linker type, though, I would certainly merge it.

@WebDrake
Copy link
Contributor

Good to know, I'll keep that in mind if I find a concrete use-case. In the short term, though, the suggestion to integrate LLD seems more enticing ... ;-)

@dnadlinger
Copy link
Member

Oh, we won't be using LLD by default on Linux in the near future. Right now, it isn't even compatible enough with the various weird and wonderful binutils quirks to be used as the default linker for a distro.

@WebDrake
Copy link
Contributor

Ah, so this feature request is essentially Windows-centric for the foreseeable future ... ?

@dnadlinger
Copy link
Member

dnadlinger commented Apr 10, 2017

It could definitely be available as an option for experimentation (especially w.r.t cross compiling). I don't think we should enable it by default on Linux any time soon, though, as you can still find people complaining about bugs here and there right now. It would be a high-risk-low-reward type of decision.

@kinke
Copy link
Member Author

kinke commented Apr 11, 2017

Fully agreed, although the reward in form of built-in LTO and bitcode-linkability would be a nice-to-have. I guess it's the same for OSX and all other non-Windows hosts.

All what's needed as prerequisite for cross-compilation experiments (to non-Windows targets, we're already prepared for MSVC targets from arbitrary hosts) is an ld-compatible linker output interface in addition to the current gcc and link.exe ones, which may be easier than I thought after a quick glance.

Creating a cross-compilation LDC package (once LLD is integrated after the ld-interface is implemented) should be rather straight-forward then:

  • Examine ld command line used by a native gcc/clang. Copy over system libs, init object files etc. and add appropriate linker switches to the LDC config file for the target triple of interest.
  • Build druntime and Phobos for the target and include it in the package.

@kinke
Copy link
Member Author

kinke commented May 27, 2017

Progress in #2142 - LLD for MSVC targets integrated and ld linker driver implemented as preparation for LLD for the other targets.

@d-random-contributor
Copy link

I have an impression that LTO is only for elf target, it's not listed on the windows support page and gold options don't follow ms link format.

@kinke
Copy link
Member Author

kinke commented Jun 5, 2017

In lld master, there's a COFF/LTO.cpp file which isn't there for release_39 and release_40, i.e., it'll be in LLD 5.0.

@kinke
Copy link
Member Author

kinke commented Dec 10, 2017

Update: For full integration, we'd only need to merge #2203, but see the limitations there.

@kinke
Copy link
Member Author

kinke commented Apr 16, 2018

'Fully' integrated now with #2203, i.e., for Windows COFF, Linux ELF and Mac Mach-O binary formats.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants