Skip to content

Commit

Permalink
Fix thunk return value in case of int64 or double for Win64
Browse files Browse the repository at this point in the history
Note:
Win64 X64 uses registry rax for 1,2,4,8 bytes long int or struct return value
it uses xmm0 for float (single) or double floating point values
it uses a pointer passed as hidden first parameter (rcx) for anything else returned by value and copy the pointer to rax.

To pass a double back we use a call to a function taking double & returning double (fakeReturnDouble)
Any of these actions (passing 1 double or returning 1 double) would load xmm0, and we're done.
Except the function is no-op and could be entirely eliminated by aggressive optimizer.
It's thus vital to lay the function into another file and avoid any sort of link time optimization.

TO DO: This code currently does nothing for passing a short struct back by value in rax...
If the structure is long or odd sized, its address is expected as (hidden) first parameter (rcx), rather than on stack.
So the code does not look quite right yet wrt Win64 X64 ABI.

TO DO: the same kind of changes should be applied to X64 system V ABI
  • Loading branch information
nicolas-cellier-aka-nice committed Sep 11, 2016
1 parent 5b17a27 commit ddf2aa4
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 22 deletions.
26 changes: 4 additions & 22 deletions platforms/Cross/plugins/IA32ABI/x64win64ia32abicc.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,29 +234,11 @@ extern void saveFloatRegsWin64(long long xmm0,long long xmm1,long long xmm2, lon

case retword: return vmcc.rvs.valword;

case retword64: {
long vhigh = vmcc.rvs.valleint64.high;
#if _MSC_VER
_asm mov edx, dword ptr vhigh;
#elif __GNUC__
asm("mov %0,%%edx" : : "m"(vhigh));
#else
# error need to load edx with vmcc.rvs.valleint64.high on this compiler
#endif
return vmcc.rvs.valleint64.low;
}
case retword64: return (((unsigned long long)vmcc.rvs.valleint64.high) << 32) | (unsigned int)vmcc.rvs.valleint64.low;

case retdouble: {
double valflt64 = vmcc.rvs.valflt64;
#if _MSC_VER
_asm fld qword ptr valflt64;
#elif __GNUC__
asm("fldl %0" : : "m"(valflt64));
#else
# error need to load %f0 with vmcc.rvs.valflt64 on this compiler
#endif
return 0;
}
case retdouble:
fakeReturnDouble( vmcc.rvs.valflt64 );
return 0;

case retstruct: memcpy( (void *)(stackp[1]),
vmcc.rvs.valstruct.addr,
Expand Down
4 changes: 4 additions & 0 deletions platforms/Cross/plugins/IA32ABI/x64win64stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ void saveFloatRegsWin64(double xmm0,double xmm1,double xmm2, double xmm3,double
fpargs[2]=xmm2;
fpargs[3]=xmm3;
}
double fakeReturnDouble(double xmm0)
{
return xmm0;
}
#endif
#endif

0 comments on commit ddf2aa4

Please sign in to comment.