Hi,
I'm soliciting feedback on a design feature for llvm-ld, loadable linker optimization modules.
The Problem:
The llvm-ld tool expects that the bytecode files it is linking to already have been compile-time optimized appropriately. When it links all the bytecode together, it needs to apply link-time optimizations, if appropriate. The problem is, because of various front-ends involved, it is not reasonable for llvm-ld to "know" which passes to be run. Furthermore, front-ends may have specific passes they need to be run at link time (e.g. C++ template generation, or optimizing exception handling which wouldn't be applicable to modules compiled from C or Scheme or Stacker).
Goal:
Have llvm-ld automatically load (similar to opt --load=libPasses.so ) link-time optimization passes based on the bytecode it is linking.
Issues:
1. Should the loadable module be a native .so or a bytecode library?
2. How does the linker automatically know which loadable modules to load? What
in the bytecode lets it know the modules to load and run?
3. How does llvm-ld find the loadable modules?
4. When do the passes in the loaded module run? Before standard passes, after
them or intermingled?
5. What's the interface between llvm-ld and the passes in the loadable module?
6. How do we identify which passes to run given the various -On options?
Current Thinking On Issues:
1. Only native .so
2. Augment the bytecode to specify the language from which it is compiled.
Provide the necessary module information via the language-specific
configuration files that llvmc uses.
3. Loadable modules need to be installed in the LLVM lib directory like any
other library. Have llvm-ld look there.
4. Standard passes are run first. llvm-ld doesn't run the passes individually,
it just invokes the loaded module to run them for it. That way the module
has complete freedom to run passes it needs.
5. A single function in the loaded module is called. That function is passed
three things: the Module* to be optimized, the optimization level to apply,
and a list of the passes already made (so the module can eliminate redundant
passes). The loaded module may return a Module* to replace the previous one
or null to indicate that the original Module* passed in should be used for
further loaded modules.
6. Leave it up to the loaded module.
Thoughts on this?
Reid