From 3e030b4c04546229c81449fde66f71b23b3fc550 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 18 Feb 2009 03:44:19 +0000 Subject: [PATCH] x86_64 ABI: Two bug fixes. 1. Return of _Complex long double used wrong type. 2. va_arg of types passed in two SSE registers didn't account for extra space in register save area. Down to 18 failures on gcc/compat/x86_64. Combined 32/64 results are: -- === gcc Summary === # of expected passes 1292 # of unexpected failures 34 # of unsupported tests 2 -- git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64880 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index f687a5bc46..84e894a40a 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -752,7 +752,9 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, // %st1. case ComplexX87: assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification."); - ResType = llvm::VectorType::get(llvm::Type::X86_FP80Ty, 2); + ResType = llvm::StructType::get(llvm::Type::X86_FP80Ty, + llvm::Type::X86_FP80Ty, + NULL); break; } @@ -1028,6 +1030,12 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // copying to a temporary location in case the parameter is passed // in different register classes or requires an alignment greater // than 8 for general purpose registers and 16 for XMM registers. + // + // FIXME: This really results in shameful code when we end up + // needing to collect arguments from different places; often what + // should result in a simple assembling of a structure from + // scattered addresses has many more loads than necessary. Can we + // clean this up? const llvm::Type *LTy = CGF.ConvertTypeForMem(Ty); llvm::Value *RegAddr = CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(VAListAddr, 3), @@ -1060,9 +1068,33 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, RegAddr = CGF.Builder.CreateBitCast(RegAddr, llvm::PointerType::getUnqual(LTy)); } else { - RegAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset); - RegAddr = CGF.Builder.CreateBitCast(RegAddr, - llvm::PointerType::getUnqual(LTy)); + if (neededSSE == 1) { + RegAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset); + RegAddr = CGF.Builder.CreateBitCast(RegAddr, + llvm::PointerType::getUnqual(LTy)); + } else { + assert(neededSSE == 2 && "Invalid number of needed registers!"); + // SSE registers are spaced 16 bytes apart in the register save + // area, we need to collect the two eightbytes together. + llvm::Value *RegAddrLo = CGF.Builder.CreateGEP(RegAddr, fp_offset); + llvm::Value *RegAddrHi = + CGF.Builder.CreateGEP(RegAddrLo, + llvm::ConstantInt::get(llvm::Type::Int32Ty, 16)); + const llvm::Type *DblPtrTy = + llvm::PointerType::getUnqual(llvm::Type::DoubleTy); + const llvm::StructType *ST = llvm::StructType::get(llvm::Type::DoubleTy, + llvm::Type::DoubleTy, + NULL); + llvm::Value *V, *Tmp = CGF.CreateTempAlloca(ST); + V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo, + DblPtrTy)); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0)); + V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrHi, + DblPtrTy)); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + RegAddr = CGF.Builder.CreateBitCast(Tmp, + llvm::PointerType::getUnqual(LTy)); + } } // AMD64-ABI 3.5.7p5: Step 5. Set: -- 2.40.0