We've run into a tricky situation in our work on the Crack compiler and I'm
hoping that someone on this list can help us find the best solution.
We're currently trying to implement "module caching" for Crack, similar to the
feature in Python where module bitcode is persisted at compile time. When we
import a module, before compiling the module we check for a bitcode file
matching the source -- if a bitcode file exists, we load it and extract
compile-time metadata from it, saving us a compile step.
The problem here is that the StructType objects in the cached module are
different from those referenced by the compiler, so when we try to reference
entities in the cached module we get an assertion failure due to type
incompatibility. Specifically, this is currently happening when we reference
a global variable in the cached module from an array initializer in the
importing module which is still being compiled.
We can't easily just use the linker to manage all of this because we still
want to be able to persist that new module independently for later use. There
may be other reasons, too: seperate modules is a fundamental assumption of our
design. We currently use the linker only at the end of an AOT build.
So from what I can see, our possible solutions are:
1) duplicate the LinkModule internal code and copy the module we load from
bitcode to a new module with the correct types mapped.
2) duplicate BitcodeReader and create a version that reuses existing
3) destructively convert all of the types in the imported module to our
Needless to say, none if these are especially attractive. Is there a better
way to do this? Are any of these options clearly better or worse than the
Also, when loading named StructTypes, would it be possible for LLVM to reuse
an existing type with the same name assuming the existing type is isomorphic?
This seems like it would be a win all around.