From: Daniel Dunbar Date: Fri, 13 Feb 2009 17:46:31 +0000 (+0000) Subject: x86_64 ABI: Support va_arg passed in mixed registers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55e5d8956be516d66db2196bd0ce3c30ebf5fbf0;p=clang x86_64 ABI: Support va_arg passed in mixed registers. - Now at 1274 passes on gcc compat suite vs 1262. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64469 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index d05c9ff4b9..808d9f2c46 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -963,7 +963,28 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(VAListAddr, 3), "reg_save_area"); if (neededInt && neededSSE) { - assert(0 && "FIXME: Implement support for va_arg in mixed regs"); + // FIXME: Cleanup. + assert(AI.isCoerce() && "Unexpected ABI info for mixed regs"); + const llvm::StructType *ST = cast(AI.getCoerceToType()); + llvm::Value *Tmp = CGF.CreateTempAlloca(ST); + assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs"); + const llvm::Type *TyLo = ST->getElementType(0); + const llvm::Type *TyHi = ST->getElementType(1); + assert((TyLo->isFloatingPoint() ^ TyHi->isFloatingPoint()) && + "Unexpected ABI info for mixed regs"); + const llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo); + const llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi); + llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset); + llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset); + llvm::Value *RegLoAddr = TyLo->isFloatingPoint() ? FPAddr : GPAddr; + llvm::Value *RegHiAddr = TyLo->isFloatingPoint() ? GPAddr : FPAddr; + llvm::Value *V = + CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegLoAddr, PTyLo)); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0)); + V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegHiAddr, PTyHi)); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + + RegAddr = CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(LTy)); } else if (neededInt) { RegAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset); RegAddr = CGF.Builder.CreateBitCast(RegAddr,