spec: abi: clarify calling convention for other architectures other than x86
Observing the assembly generated by the following source file in either DMD and LDC:
extern (C) void ccall( size_t a, size_t b, size_t c );
extern (D) void dcall( size_t a, size_t b, size_t c );
//...
ccall( a, b, c ); // RDI, RSI, RDX
dcall( a, b, c ); // RDX, RSI, RDI
The parameters are passed in the reverse order in functions with extern(D)
linkage. Furthermore, on x86 the calling convention seems to be what is
described by the current subsections, not only matching Windows x86, but also
appears to be the same behaviour on System V ABI.
Fixes #20204 .
Signed-off-by: Luís Ferreira [email protected]
For more context: https://godbolt.org/z/sWz4x37bb
Thanks for your pull request, @ljmf00!
Bugzilla references
| Auto-close | Bugzilla | Severity | Description |
|---|---|---|---|
| ✓ | 20204 | normal | need to fix ABI about registers using |
I've always regarded this as an ABI spec violation of both DMD and LDC, unfortunately not that simple to fix mainly because of existing DMD-style inline asm in druntime/Phobos and user code. If given the choice, I'd definitely fix the implementation rather than the spec.
I've always regarded this as an ABI spec violation of both DMD and LDC, unfortunately not that simple to fix mainly because of existing DMD-style inline asm in druntime/Phobos and user code. If given the choice, I'd definitely fix the implementation rather than the spec.
I agree with you because it doesn't make much sense. I don't get the rationale for the x86 special case either. On the other hand, changing the implementation make binaries incompatible leading to a huge breaking change with old shared objects.
I'm kinda divided here, to be honest, but inclined to the "clean way", which is to fix the implementation.
changing the implementation make binaries incompatible leading to a huge breaking change with old shared objects
That's not that big a deal, we have had numerous breaking ABI changes in the past, so binaries compiled with different compiler versions aren't expected to be compatible.
The only real problem I see is that efforts should probably be synchronized across DMD and LDC, in order to tell people that from D 2.100 on (or so), the params aren't reversed for extern(D) anymore (except for 32-bit x86), for both DMD and LDC. So if they've been accessing parameter registers directly in DMD-style inline asm, they need to adapt those, but it'll work with both DMD and LDC at least.
I'm more than happy to finally do this for LDC (I've had a go at this some 5 years ago already).
This parameter reversal has been a PITA at multiple occasions, e.g., https://github.com/dlang/dmd/pull/11630.
changing the implementation make binaries incompatible leading to a huge breaking change with old shared objects
That's not that big a deal, we have had numerous breaking ABI changes in the past, so binaries compiled with different compiler versions aren't expected to be compatible.
The only real problem I see is that efforts should probably be synchronized across DMD and LDC, in order to tell people that from D 2.100 on (or so), the params aren't reversed for
extern(D)anymore (except for 32-bit x86), for both DMD and LDC. So if they've been accessing parameter registers directly in DMD-style inline asm, they need to adapt those, but it'll work with both DMD and LDC at least.I'm more than happy to finally do this for LDC (I've had a go at this some 5 years ago already).
Sure, I can see what I can do about it. I'm not into deep backend stuff like target codegen. What about the 32-bit x86? Why is the calling convention different there too?
This parameter reversal has been a PITA at multiple occasions, e.g., dlang/dmd#11630.
At a first glance, it appears to me that this is being fixed in the wrong place. This parameter reverse order behaviour appears to be intentional on the IR generation: https://github.com/dlang/dmd/blob/master/src/dmd/e2ir.d#L5261