Description
In rust, a static variable is essentially the same thing as a #define
, and to achieve the same sort of optimizations about knowing the symbol at compile time we use the available_externally
linkage from LLVM. What this means is that the source crate defining a static will always compile the version of the static into its own data section of the executable.
When an external crate then links to this source crate, it will import statics as they're used. Each static is imported in a manner like:
@original.source.name = available_externally i32 3
Where original.source.name
is the name of the symbol in original crate, and 3
is the actual value of the constant. What this means is that LLVM can optimize based on the value of the constant (because we specify it explicitly, we loaded it from the serialized ast of the external crate). The reason we do this is so that a static has one and only one address. The available_externally
linkage means that no symbol will be emitted into the crate. If LLVM determines that it needs the symbol (such as you took the address of the static), then it will link against it, otherwise LLVM optimizes it all out.
In theory, we could also apply this available_externally
optimization to functions as well. What this would mean is that the source crate would provide definitions for all #[inline]
functions, and then all crates linking against this crate would use available_externally
. I would hope that this meant that LLVM would attempt to inline the function, but if LLVM didn't decide to inline the function it wouldn't recompile it or emit a symbol for it.
In theory this means smaller crates because all non-inlined calls to an #[inline]
function would result in cross-crate calls.
I'm a little doubtful that this would provide an actual size benefit, and I'm also unsure of whether LLVM would even optimize like this. I'm only taking my vague understanding of the linkage mode and applying it to what seems reasonable for functions. Regardless, this may be an interesting project for anyone wishing to really take a bite out of dealing with LLVM, learning compiler internals, and possibly providing a nice reduction in binary size without losing any performance.