Fix cfloat return on x86_64: only perform ABI transformation for non-extern(D)

functions.
There's no need to waste cycles with extern(D), which we get to define
ourselves. Fixes tests/mini/asm8.d. (Since the asm abiret code already assumed
{xmm0, xmm1} returns)
This commit is contained in:
Frits van Bommel
2009-02-26 23:35:39 +01:00
parent 4f51adc810
commit 03ce6604a0
3 changed files with 66 additions and 52 deletions

View File

@@ -180,7 +180,8 @@ struct X86_64_cfloat_rewrite : ABIRetRewrite
// test if rewrite applies to function
bool test(TypeFunction* tf)
{
return (tf->next->toBasetype() == Type::tcomplex32);
return (tf->linkage != LINKd)
&& (tf->next->toBasetype() == Type::tcomplex32);
}
};

View File

@@ -279,7 +279,7 @@ void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl)
// For compatibility, use the GCC/LLVM-GCC way for extern(C/Windows)
// extern(C) cfloat -> %xmm0 (extract two floats)
as->out_c = "={xmm0},";
asmblock->retty = LLStructType::get(LLType::DoubleTy, NULL);;
asmblock->retty = LLType::DoubleTy;
asmblock->retfixup = &x86_64_cfloatRetFixup;
} else if (rt->iscomplex()) {
// cdouble and extern(D) cfloat -> re=%xmm0, im=%xmm1

View File

@@ -118,29 +118,31 @@ cfloat cf()
}
else version (X86_64)
{
version(all) {
asm
{
movss XMM0, [one_f];
movss XMM1, [two_f];
}
} else {
// Code for when LDC becomes ABI-compatible with GCC
// regarding cfloat returns.
asm {
movd EAX, [one_f];
movd ECX, [two_f];
// invalid operand size :(
//shl RCX, 32;
//or RAX, RCX;
pushq RAX;
mov [RSP + 4], EAX;
popq RAX;
movd XMM0, RAX;
}
asm
{
movss XMM0, [one_f];
movss XMM1, [two_f];
}
}
else static assert(0, "todo");
}
extern(C) cfloat cf_C()
{
version(X86)
{
asm { fld1; fld two_f; }
}
else version (X86_64)
{
asm {
mov EAX, [one_f];
mov ECX, [two_f];
shl RCX, 32;
or RAX, RCX;
movd XMM0, RAX;
}
}
else static assert(0, "todo");
@@ -160,33 +162,41 @@ cfloat cf2()
}
else version (X86_64)
{
version(all) {
asm
{
naked;
movss XMM0, [one_f];
movss XMM1, [two_f];
ret;
}
} else {
// Code for when LDC becomes ABI-compatible with GCC
// regarding cfloat returns.
asm {
naked;
mov EAX, [one_f];
mov ECX, [two_f];
// invalid operand size :(
//shl RCX, 32;
//or RAX, RCX;
pushq RAX;
mov [RSP + 4], EAX;
popq RAX;
movd RAX, XMM0;
ret;
}
asm
{
naked;
movss XMM0, [one_f];
movss XMM1, [two_f];
ret;
}
}
else static assert(0, "todo");
}
extern(C) cfloat cf2_C()
{
version(X86)
{
asm
{
naked;
fld1;
fld two_f;
ret;
}
}
else version (X86_64)
{
asm {
naked;
mov EAX, [one_f];
mov ECX, [two_f];
shl RCX, 32;
or RAX, RCX;
movd XMM0, RAX;
ret;
}
}
else static assert(0, "todo");
@@ -369,6 +379,9 @@ void main()
assert(cf() == 1+2i);
assert(cf2() == 1+2i);
assert(cf_C() == 1+2i);
assert(cf2_C() == 1+2i);
assert(cd() == 1+2i);
assert(cd2() == 1+2i);