From 54d1ccbfcf19ddf39444f1b4018dd79487cc847b Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 27 Jan 2009 01:36:03 +0000 Subject: [PATCH] Implement support for coercion to wider types during ABI handling. - Code quality is poor, but simple. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63083 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 76 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index cd781781f9..9e632c0e27 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Attributes.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetData.h" using namespace clang; using namespace CodeGen; @@ -935,6 +936,71 @@ void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn, assert(AI == Fn->arg_end() && "Argument mismatch!"); } +/// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as +/// a pointer to an object of type \arg Ty. +/// +/// This safely handles the case when the src type is smaller than the +/// destination type; in this situation the values of bits which not +/// present in the src are undefined. +static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, + const llvm::Type *Ty, + CodeGenFunction &CGF) { + const llvm::Type *SrcTy = + cast(SrcPtr->getType())->getElementType(); + unsigned SrcSize = CGF.CGM.getTargetData().getTypePaddedSize(SrcTy); + unsigned DstSize = CGF.CGM.getTargetData().getTypePaddedSize(Ty); + + // If load is legal, just bitcase the src pointer. + if (SrcSize == DstSize) { + llvm::Value *Casted = + CGF.Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(Ty)); + return CGF.Builder.CreateLoad(Casted); + } else { + assert(SrcSize < DstSize && "Coercion is losing source bits!"); + + // Otherwise do coercion through memory. This is stupid, but + // simple. + llvm::Value *Tmp = CGF.CreateTempAlloca(Ty); + llvm::Value *Casted = + CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(SrcTy)); + CGF.Builder.CreateStore(CGF.Builder.CreateLoad(SrcPtr), Casted); + return CGF.Builder.CreateLoad(Tmp); + } +} + +/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src, +/// where the source and destination may have different types. +/// +/// This safely handles the case when the src type is larger than the +/// destination type; the upper bits of the src will be lost. +static void CreateCoercedStore(llvm::Value *Src, + llvm::Value *DstPtr, + CodeGenFunction &CGF) { + const llvm::Type *SrcTy = Src->getType(); + const llvm::Type *DstTy = + cast(DstPtr->getType())->getElementType(); + + unsigned SrcSize = CGF.CGM.getTargetData().getTypePaddedSize(SrcTy); + unsigned DstSize = CGF.CGM.getTargetData().getTypePaddedSize(DstTy); + + // If store is legal, just bitcase the src pointer. + if (SrcSize == DstSize) { + llvm::Value *Casted = + CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy)); + CGF.Builder.CreateStore(Src, Casted); + } else { + assert(SrcSize > DstSize && "Coercion is missing bits!"); + + // Otherwise do coercion through memory. This is stupid, but + // simple. + llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy); + CGF.Builder.CreateStore(Src, Tmp); + llvm::Value *Casted = + CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(DstTy)); + CGF.Builder.CreateStore(CGF.Builder.CreateLoad(Casted), DstPtr); + } +} + void CodeGenFunction::EmitFunctionEpilog(QualType RetTy, llvm::Value *ReturnValue) { llvm::Value *RV = 0; @@ -965,9 +1031,7 @@ void CodeGenFunction::EmitFunctionEpilog(QualType RetTy, break; case ABIArgInfo::Coerce: { - const llvm::Type *CoerceToPTy = - llvm::PointerType::getUnqual(RetAI.getCoerceToType()); - RV = Builder.CreateLoad(Builder.CreateBitCast(ReturnValue, CoerceToPTy)); + RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this); break; } @@ -1073,10 +1137,8 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, return RValue::get(0); case ABIArgInfo::Coerce: { - const llvm::Type *CoerceToPTy = - llvm::PointerType::getUnqual(RetAI.getCoerceToType()); - llvm::Value *V = CreateTempAlloca(ConvertType(RetTy), "tmp"); - Builder.CreateStore(CI, Builder.CreateBitCast(V, CoerceToPTy)); + llvm::Value *V = CreateTempAlloca(ConvertType(RetTy), "coerce"); + CreateCoercedStore(CI, V, *this); if (RetTy->isAnyComplexType()) return RValue::getComplex(LoadComplexFromAddr(V, false)); else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) -- 2.40.0