Implement support for coercion to wider types during ABI handling.

- Code quality is poor, but simple.

llvm-svn: 63083
This commit is contained in:
Daniel Dunbar 2009-01-27 01:36:03 +00:00
parent 725fb43012
commit 0f4aa3cbb1
1 changed files with 69 additions and 7 deletions

View File

@ -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<llvm::PointerType>(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<llvm::PointerType>(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))