On 01/09/12 20:05, Iain Buclaw wrote:
> On 9 January 2012 18:15, Artur Skawina <[email protected]> wrote:
>>
>> [1] I guess omitting the frame pointer manipulation for (at least) just
>> nonthrowing leaf functions that don't use any stack slots wouldn't be easy?
>> (the vector extensions will probably make this even more important...)
>
> I think the tweaks I've made for extern(D) - frame pointer turned on
> unless naked - trumps all other checks for whether it is ok to omit
> frame pointer. For extern(C) at least for x86, the frame pointer is
> omitted by default as is the default for that particular backend.
Didn't realize extern(C) would influence this, other than changing name
mangling and calling convention - will have to try it. I'm afraid it
could cause symbol collisions with the "real" C code (for wrappers). [1]
The cases i'm worried about are things like virtual methods - imagine eg
a gui toolkit where every widget has certain properties (x,width,hidden etc)
which are implemented using getters, which in many cases should be just
"mov IMM, eax; ret" or "mov OFF(eax), eax; ret" -- this is what the C
compiler will emit; setting up the frame pointer just adds overhead and
inlining cannot help here.
SIMD code can have similar properties - only access data passed via
pointers, never calling other functions nor spilling.
> Will need to fix the inline asm in phobos and druntime to be C calling
> convention friendly, then can drop all relevant attempts at matching
> the DMD calling convention.
Do I understand correctly that you want to ignore the "official" D abi,
and go with an incompatible one, as a long term goal? That has downsides,
but as i think the "D ABI" will end up being changed and gdc is currently
not compatible anyway - maybe it's a reasonable option.
But gdc's D abi won't be fully compatible with the C one, right? Then,
avoiding some of C's mistakes would be a good idea (name mangling,
default to regparm etc)
I have porting the runtime/phobos asms to gcc asm on my to-do list, will
try to get to that within two weeks. What would be the preferred way -
version() guards? if yes - what version? Or would you prefer replacing
the asms, if the changes are not going to be merged upstream anyway?
artur
[1] Maybe extern(C) would work for the following case, but i think i'll
wait with trying it until LTO fails to build this, so far it's working. :)
A D main module with this:
---------------------------------------------
[...]
const char* guname = glib.get_user_name();
805139f: e8 5c 02 00 00 call 8051600 <char*
GLib2.get_user_name()>
[...]
---------------------------------------------
built with a "glib" module containing:
---------------------------------------------
[...]
extern (C) char* g_get_user_name();
char* get_user_name() {
return g_get_user_name();
}
[...]
---------------------------------------------
results in the above call going through this "function":
---------------------------------------------
08051600 <char* GLib2.get_user_name()>:
8051600: 55 push %ebp
8051601: 89 e5 mov %esp,%ebp
8051603: 5d pop %ebp
8051604: e9 c7 f1 ff ff jmp 80507d0 <g_get_user_name@plt>
---------------------------------------------
So clearly the compiler gets confused, it does a good job of optimizing
the tail call (this also works when the called functions takes args, btw),
but then fails to kill the ebp-related code.
If i use a D alias, instead of a wrapper, i get a direct call via PLT;
compiling with LTO also results in code that does not use this stub
- at least until GDC's LTO will decide it's missing some symbols and
fail to link. :)