From 03ce6604a0ae1aaff2bda8884d535e23f71c4cc6 Mon Sep 17 00:00:00 2001 From: Frits van Bommel Date: Thu, 26 Feb 2009 23:35:39 +0100 Subject: [PATCH] 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) --- gen/abi.cpp | 3 +- gen/naked.cpp | 2 +- tests/mini/asm8.d | 113 ++++++++++++++++++++++++++-------------------- 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/gen/abi.cpp b/gen/abi.cpp index d62ebcd9..ccd07489 100644 --- a/gen/abi.cpp +++ b/gen/abi.cpp @@ -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); } }; diff --git a/gen/naked.cpp b/gen/naked.cpp index 0ae6f8ed..de030a03 100644 --- a/gen/naked.cpp +++ b/gen/naked.cpp @@ -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 diff --git a/tests/mini/asm8.d b/tests/mini/asm8.d index 6f4b4008..aab13cf7 100644 --- a/tests/mini/asm8.d +++ b/tests/mini/asm8.d @@ -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);