Hello everybody. Here comes the second round of inline asm discussion related to LDC, the LLVM D Compiler. Last time was about naked inline asm and the problems it poses for a backend like LLVM. Since revision 920 in our mercurial tree, naked inline asm support is good enough that Don's Bigint code from Tango now works. This is a great step forward...
I implemented it by using a feature in LLVM that allows you to insert raw assembly at the codeunit level, and modified the asm processor to support generating that as well. It wasn't that big a job really, isn't completely finished yet, and still needs a lot of testing of course ;) Now Christian Kamm also finished the last ABI / calling-convention bits we were missing on x86-32 Linux. This naturally lead us to try out defining the "controversial" D_InlineAsm_X86 version identifier... Now in Tango there's a bunch of code, like the following (copied from tango.math.IEEE.d) real ldexp(real n, int exp) /* intrinsic */ { version(Really_D_InlineAsm_X86) { asm { fild exp; fld n; fscale; fstp ST(1), ST(0); } } else { return tango.stdc.math.ldexpl(n, exp); } } This code assumes that the value of ST(0) is preserved after the asm block ends and that the compiler simply inserts a return instruction as appropriate. This doesn't work with LLVM. For the function to be valid in codegen, we must insert a return instruction in the LLVM IR code after the block, and the only choices we have for the value to return is an undefined value. This kind of code usually works when the program isn't optimized, however, if optimization is enabled, a caller of ldexp will most likely notice that the return value is undefined or a constant, and so has a lot of freedom to do what it wants. Breaking the way the return value is received in the process. This is almost exactly the same problem I had with naked inline asm, and the only fix is to somehow generate an inline asm expression (that's what llvm has, not statements like D), that produces the right return value. Something a bit like: return asm { ... } Since D has no way to express this directly, it means we would have to analyze the inline asm and somehow capture the right registers etc. This is not something I want to implement right now, if ever... The LLVM people are not interested in adding some kind of feature to allow this, since the inline asm expressions already suffice for normal GCC (which has inline asm expressions) C/C++ code. Now the real question is, does this code even have well defined semantics in terms of the D spec? and if not, could we possibly specify it as implementation specific behaviour. Everything is in place to specify the D_InlineAsm_X86 version identifier in LDC, but a lot of asm still isn't going to work, due to reasons like this. I hope to hear some feedback on how to move on from here. Thank you all, Tomas Lindquist Olsen and the LDC Team.