Closed
Description
To generate code for extern "C" fn foo()
, rustc
will create a Rust function and wrap it inside a function exposing the C ABI. This is bad for compile-time, but more importantly it makes it very hard to write functions like memset
, memcpy
and memmove
for freestanding Rust because LLVM will kindly replace their body with a call to the intrinsic, and then lower that to an infinitely recursive function.
Activity
nikomatsakis commentedon Oct 28, 2013
Can you elaborate on what leads to an infinitely recursing function?
thestinger commentedon Oct 28, 2013
@nikomatsakis: LLVM's
loop-idiom
pass replaces loops with thememset
andmemcpy
intrinsics. It's hardcoded to not to this in functions with the namememset
ormemcpy
. Inlining is interleaved with the other passes so it's not enough thatloop-idiom
runs late.eholk commentedon Nov 21, 2013
Out of curiosity, is there even still a need for these wrappers? Rust seems to support multiple calling conventions without any trouble. I believe used to the challenge was we needed to pass things like a task pointer around, but now I think Rust get's these from TLS.
thestinger commentedon Nov 21, 2013
@eholk: I think the only reason the wrappers exist is that Rust doesn't currently know how to output the ABI <-> ABI casts directly inside the function it's generating. The code generation for function bodies just assumes it's directly using the parameters and only knows about the Rust ABI.
brson commentedon Jan 30, 2014
Can we run LLVM passes in different orders to make the inlining issues go away?
thestinger commentedon Jan 30, 2014
@brson: I don't think so. The
inline
pass is placed long beforeloop-idiom
, but LLVM actually spreads out the inlining process. If we mess with the passes by splitting them up (run a module pass with onlyinline
first) or changing the order, we'll also likely hurt compile-time and/or performance. This is quite feasibly fixable with some refactoring work in trans.18 remaining items