forked from OSchip/llvm-project
Kill off the 'coerce' ABI passing form. Now 'direct' and 'extend' always
have a "coerce to" type which often matches the default lowering of Clang type to LLVM IR type, but the coerce case can be handled by making them not be the same. This simplifies things and fixes issues where X86-64 abi lowering would return coerce after making preferred types exactly match up. This caused us to compile: typedef float v4f32 __attribute__((__vector_size__(16))); v4f32 foo(v4f32 X) { return X+X; } into this code at -O0: define <4 x float> @foo(<4 x float> %X.coerce) nounwind { entry: %retval = alloca <4 x float>, align 16 ; <<4 x float>*> [#uses=2] %coerce = alloca <4 x float>, align 16 ; <<4 x float>*> [#uses=2] %X.addr = alloca <4 x float>, align 16 ; <<4 x float>*> [#uses=3] store <4 x float> %X.coerce, <4 x float>* %coerce %X = load <4 x float>* %coerce ; <<4 x float>> [#uses=1] store <4 x float> %X, <4 x float>* %X.addr %tmp = load <4 x float>* %X.addr ; <<4 x float>> [#uses=1] %tmp1 = load <4 x float>* %X.addr ; <<4 x float>> [#uses=1] %add = fadd <4 x float> %tmp, %tmp1 ; <<4 x float>> [#uses=1] store <4 x float> %add, <4 x float>* %retval %0 = load <4 x float>* %retval ; <<4 x float>> [#uses=1] ret <4 x float> %0 } Now we get: define <4 x float> @foo(<4 x float> %X) nounwind { entry: %X.addr = alloca <4 x float>, align 16 ; <<4 x float>*> [#uses=3] store <4 x float> %X, <4 x float>* %X.addr %tmp = load <4 x float>* %X.addr ; <<4 x float>> [#uses=1] %tmp1 = load <4 x float>* %X.addr ; <<4 x float>> [#uses=1] %add = fadd <4 x float> %tmp, %tmp1 ; <<4 x float>> [#uses=1] ret <4 x float> %add } This implements rdar://8248065 llvm-svn: 109733
This commit is contained in:
parent
9fa15c3608
commit
fe34c1d53e
|
@ -38,17 +38,13 @@ namespace clang {
|
|||
class ABIArgInfo {
|
||||
public:
|
||||
enum Kind {
|
||||
Direct, /// Pass the argument directly using the normal
|
||||
/// converted LLVM type. Complex and structure types
|
||||
/// are passed using first class aggregates.
|
||||
Direct, /// Pass the argument directly using the normal converted LLVM
|
||||
/// type, or by coercing to another specified type
|
||||
/// (stored in 'CoerceToType').
|
||||
|
||||
Extend, /// Valid only for integer argument types. Same as 'direct'
|
||||
/// but also emit a zero/sign extension attribute.
|
||||
|
||||
Coerce, /// Only valid for aggregate return types, the argument
|
||||
/// should be accessed by coercion to a provided type.
|
||||
|
||||
|
||||
Indirect, /// Pass the argument indirectly via a hidden pointer
|
||||
/// with the specified alignment (0 indicates default
|
||||
/// alignment).
|
||||
|
@ -79,8 +75,8 @@ namespace clang {
|
|||
public:
|
||||
ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
|
||||
|
||||
static ABIArgInfo getDirect() {
|
||||
return ABIArgInfo(Direct);
|
||||
static ABIArgInfo getDirect(const llvm::Type *T = 0) {
|
||||
return ABIArgInfo(Direct, T);
|
||||
}
|
||||
static ABIArgInfo getExtend() {
|
||||
return ABIArgInfo(Extend);
|
||||
|
@ -88,9 +84,6 @@ namespace clang {
|
|||
static ABIArgInfo getIgnore() {
|
||||
return ABIArgInfo(Ignore);
|
||||
}
|
||||
static ABIArgInfo getCoerce(const llvm::Type *T) {
|
||||
return ABIArgInfo(Coerce, T);
|
||||
}
|
||||
static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true) {
|
||||
return ABIArgInfo(Indirect, 0, Alignment, ByVal);
|
||||
}
|
||||
|
@ -102,16 +95,23 @@ namespace clang {
|
|||
bool isDirect() const { return TheKind == Direct; }
|
||||
bool isExtend() const { return TheKind == Extend; }
|
||||
bool isIgnore() const { return TheKind == Ignore; }
|
||||
bool isCoerce() const { return TheKind == Coerce; }
|
||||
bool isIndirect() const { return TheKind == Indirect; }
|
||||
bool isExpand() const { return TheKind == Expand; }
|
||||
|
||||
// Coerce accessors
|
||||
bool canHaveCoerceToType() const {
|
||||
return TheKind == Direct || TheKind == Extend;
|
||||
}
|
||||
|
||||
// Direct/Extend accessors
|
||||
const llvm::Type *getCoerceToType() const {
|
||||
assert(TheKind == Coerce && "Invalid kind!");
|
||||
assert(canHaveCoerceToType() && "Invalid kind!");
|
||||
return TypeData;
|
||||
}
|
||||
|
||||
|
||||
void setCoerceToType(const llvm::Type *T) {
|
||||
assert(canHaveCoerceToType() && "Invalid kind!");
|
||||
TypeData = T;
|
||||
}
|
||||
// Indirect accessors
|
||||
unsigned getIndirectAlign() const {
|
||||
assert(TheKind == Indirect && "Invalid kind!");
|
||||
|
|
|
@ -245,6 +245,18 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
|
|||
|
||||
// Compute ABI information.
|
||||
getABIInfo().computeInfo(*FI);
|
||||
|
||||
// Loop over all of the computed argument and return value info. If any of
|
||||
// them are direct or extend without a specified coerce type, specify the
|
||||
// default now.
|
||||
ABIArgInfo &RetInfo = FI->getReturnInfo();
|
||||
if (RetInfo.canHaveCoerceToType() && RetInfo.getCoerceToType() == 0)
|
||||
RetInfo.setCoerceToType(ConvertTypeRecursive(FI->getReturnType()));
|
||||
|
||||
for (CGFunctionInfo::arg_iterator I = FI->arg_begin(), E = FI->arg_end();
|
||||
I != E; ++I)
|
||||
if (I->info.canHaveCoerceToType() && I->info.getCoerceToType() == 0)
|
||||
I->info.setCoerceToType(ConvertTypeRecursive(I->type));
|
||||
|
||||
// If this is a top-level call and ConvertTypeRecursive hit unresolved pointer
|
||||
// types, resolve them now. These pointers may point to this function, which
|
||||
|
@ -592,7 +604,7 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
|
|||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct:
|
||||
ResultType = ConvertType(RetTy, IsRecursive);
|
||||
ResultType = RetAI.getCoerceToType();
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Indirect: {
|
||||
|
@ -606,10 +618,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
|
|||
case ABIArgInfo::Ignore:
|
||||
ResultType = llvm::Type::getVoidTy(getLLVMContext());
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Coerce:
|
||||
ResultType = RetAI.getCoerceToType();
|
||||
break;
|
||||
}
|
||||
|
||||
for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
|
||||
|
@ -620,7 +628,15 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
|
|||
case ABIArgInfo::Ignore:
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Coerce: {
|
||||
case ABIArgInfo::Indirect: {
|
||||
// indirect arguments are always on the stack, which is addr space #0.
|
||||
const llvm::Type *LTy = ConvertTypeForMem(it->type, IsRecursive);
|
||||
ArgTys.push_back(llvm::PointerType::getUnqual(LTy));
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct:
|
||||
// If the coerce-to type is a first class aggregate, flatten it. Either
|
||||
// way is semantically identical, but fast-isel and the optimizer
|
||||
// generally likes scalar values better than FCAs.
|
||||
|
@ -632,19 +648,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
|
|||
ArgTys.push_back(ArgTy);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Indirect: {
|
||||
// indirect arguments are always on the stack, which is addr space #0.
|
||||
const llvm::Type *LTy = ConvertTypeForMem(it->type, IsRecursive);
|
||||
ArgTys.push_back(llvm::PointerType::getUnqual(LTy));
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct:
|
||||
ArgTys.push_back(ConvertType(it->type, IsRecursive));
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Expand:
|
||||
GetExpandedTypes(it->type, ArgTys, IsRecursive);
|
||||
|
@ -713,8 +716,9 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
|||
RetAttrs |= llvm::Attribute::SExt;
|
||||
else if (RetTy->hasUnsignedIntegerRepresentation())
|
||||
RetAttrs |= llvm::Attribute::ZExt;
|
||||
// FALLTHROUGH
|
||||
break;
|
||||
case ABIArgInfo::Direct:
|
||||
case ABIArgInfo::Ignore:
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Indirect:
|
||||
|
@ -726,10 +730,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
|||
llvm::Attribute::ReadNone);
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Ignore:
|
||||
case ABIArgInfo::Coerce:
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Expand:
|
||||
assert(0 && "Invalid ABI kind for return argument");
|
||||
}
|
||||
|
@ -752,15 +752,27 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
|||
// 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
|
||||
// have the corresponding parameter variable. It doesn't make
|
||||
// sense to do it here because parameters are so fucked up.
|
||||
|
||||
switch (AI.getKind()) {
|
||||
case ABIArgInfo::Coerce:
|
||||
case ABIArgInfo::Extend:
|
||||
if (ParamType->isSignedIntegerType())
|
||||
Attributes |= llvm::Attribute::SExt;
|
||||
else if (ParamType->isUnsignedIntegerType())
|
||||
Attributes |= llvm::Attribute::ZExt;
|
||||
// FALL THROUGH
|
||||
case ABIArgInfo::Direct:
|
||||
if (RegParm > 0 &&
|
||||
(ParamType->isIntegerType() || ParamType->isPointerType())) {
|
||||
RegParm -=
|
||||
(Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
|
||||
if (RegParm >= 0)
|
||||
Attributes |= llvm::Attribute::InReg;
|
||||
}
|
||||
// FIXME: handle sseregparm someday...
|
||||
|
||||
if (const llvm::StructType *STy =
|
||||
dyn_cast<llvm::StructType>(AI.getCoerceToType()))
|
||||
Index += STy->getNumElements();
|
||||
else
|
||||
++Index;
|
||||
continue; // Skip index increment.
|
||||
dyn_cast<llvm::StructType>(AI.getCoerceToType()))
|
||||
Index += STy->getNumElements()-1; // 1 will be added below.
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Indirect:
|
||||
if (AI.getIndirectByVal())
|
||||
|
@ -773,23 +785,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
|||
llvm::Attribute::ReadNone);
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
if (ParamType->isSignedIntegerType())
|
||||
Attributes |= llvm::Attribute::SExt;
|
||||
else if (ParamType->isUnsignedIntegerType())
|
||||
Attributes |= llvm::Attribute::ZExt;
|
||||
// FALLS THROUGH
|
||||
case ABIArgInfo::Direct:
|
||||
if (RegParm > 0 &&
|
||||
(ParamType->isIntegerType() || ParamType->isPointerType())) {
|
||||
RegParm -=
|
||||
(Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
|
||||
if (RegParm >= 0)
|
||||
Attributes |= llvm::Attribute::InReg;
|
||||
}
|
||||
// FIXME: handle sseregparm someday...
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Ignore:
|
||||
// Skip increment, no matching LLVM parameter.
|
||||
continue;
|
||||
|
@ -871,15 +866,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
|
|||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct: {
|
||||
assert(AI != Fn->arg_end() && "Argument mismatch!");
|
||||
llvm::Value *V = AI;
|
||||
if (hasAggregateLLVMType(Ty)) {
|
||||
// Create a temporary alloca to hold the argument; the rest of
|
||||
// codegen expects to access aggregates & complex values by
|
||||
// reference.
|
||||
V = CreateMemTemp(Ty);
|
||||
Builder.CreateStore(AI, V);
|
||||
} else {
|
||||
// If we have the trivial case, handle it with no muss and fuss.
|
||||
if (!isa<llvm::StructType>(ArgI.getCoerceToType()) &&
|
||||
ArgI.getCoerceToType() == ConvertType(Ty)) {
|
||||
assert(AI != Fn->arg_end() && "Argument mismatch!");
|
||||
llvm::Value *V = AI;
|
||||
|
||||
if (Arg->getType().isRestrictQualified())
|
||||
AI->addAttr(llvm::Attribute::NoAlias);
|
||||
|
||||
|
@ -888,40 +880,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
|
|||
// "void a(x) short x; {..."
|
||||
V = EmitScalarConversion(V, Ty, Arg->getType());
|
||||
}
|
||||
}
|
||||
EmitParmDecl(*Arg, V);
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Expand: {
|
||||
// If this structure was expanded into multiple arguments then
|
||||
// we need to create a temporary and reconstruct it from the
|
||||
// arguments.
|
||||
llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr");
|
||||
// FIXME: What are the right qualifiers here?
|
||||
llvm::Function::arg_iterator End =
|
||||
ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
|
||||
EmitParmDecl(*Arg, Temp);
|
||||
|
||||
// Name the arguments used in expansion and increment AI.
|
||||
unsigned Index = 0;
|
||||
for (; AI != End; ++AI, ++Index)
|
||||
AI->setName(Arg->getName() + "." + llvm::Twine(Index));
|
||||
continue;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Ignore:
|
||||
// Initialize the local variable appropriately.
|
||||
if (hasAggregateLLVMType(Ty)) {
|
||||
EmitParmDecl(*Arg, CreateMemTemp(Ty));
|
||||
} else {
|
||||
EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())));
|
||||
EmitParmDecl(*Arg, V);
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip increment, no matching LLVM parameter.
|
||||
continue;
|
||||
|
||||
case ABIArgInfo::Coerce: {
|
||||
llvm::AllocaInst *Alloca = CreateMemTemp(Ty, "coerce");
|
||||
|
||||
// The alignment we need to use is the max of the requested alignment for
|
||||
|
@ -968,6 +930,33 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
|
|||
EmitParmDecl(*Arg, V);
|
||||
continue; // Skip ++AI increment, already done.
|
||||
}
|
||||
|
||||
case ABIArgInfo::Expand: {
|
||||
// If this structure was expanded into multiple arguments then
|
||||
// we need to create a temporary and reconstruct it from the
|
||||
// arguments.
|
||||
llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr");
|
||||
// FIXME: What are the right qualifiers here?
|
||||
llvm::Function::arg_iterator End =
|
||||
ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
|
||||
EmitParmDecl(*Arg, Temp);
|
||||
|
||||
// Name the arguments used in expansion and increment AI.
|
||||
unsigned Index = 0;
|
||||
for (; AI != End; ++AI, ++Index)
|
||||
AI->setName(Arg->getName() + "." + llvm::Twine(Index));
|
||||
continue;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Ignore:
|
||||
// Initialize the local variable appropriately.
|
||||
if (hasAggregateLLVMType(Ty))
|
||||
EmitParmDecl(*Arg, CreateMemTemp(Ty));
|
||||
else
|
||||
EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())));
|
||||
|
||||
// Skip increment, no matching LLVM parameter.
|
||||
continue;
|
||||
}
|
||||
|
||||
++AI;
|
||||
|
@ -1001,38 +990,39 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
|
|||
break;
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct: {
|
||||
// The internal return value temp always will have pointer-to-return-type
|
||||
// type, just do a load.
|
||||
|
||||
// If the instruction right before the insertion point is a store to the
|
||||
// return value, we can elide the load, zap the store, and usually zap the
|
||||
// alloca.
|
||||
llvm::BasicBlock *InsertBB = Builder.GetInsertBlock();
|
||||
llvm::StoreInst *SI = 0;
|
||||
if (InsertBB->empty() ||
|
||||
!(SI = dyn_cast<llvm::StoreInst>(&InsertBB->back())) ||
|
||||
SI->getPointerOperand() != ReturnValue || SI->isVolatile()) {
|
||||
RV = Builder.CreateLoad(ReturnValue);
|
||||
} else {
|
||||
// Get the stored value and nuke the now-dead store.
|
||||
RetDbgLoc = SI->getDebugLoc();
|
||||
RV = SI->getValueOperand();
|
||||
SI->eraseFromParent();
|
||||
|
||||
// If that was the only use of the return value, nuke it as well now.
|
||||
if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
|
||||
cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
|
||||
ReturnValue = 0;
|
||||
case ABIArgInfo::Direct:
|
||||
|
||||
if (RetAI.getCoerceToType() == ConvertType(RetTy)) {
|
||||
// The internal return value temp always will have pointer-to-return-type
|
||||
// type, just do a load.
|
||||
|
||||
// If the instruction right before the insertion point is a store to the
|
||||
// return value, we can elide the load, zap the store, and usually zap the
|
||||
// alloca.
|
||||
llvm::BasicBlock *InsertBB = Builder.GetInsertBlock();
|
||||
llvm::StoreInst *SI = 0;
|
||||
if (InsertBB->empty() ||
|
||||
!(SI = dyn_cast<llvm::StoreInst>(&InsertBB->back())) ||
|
||||
SI->getPointerOperand() != ReturnValue || SI->isVolatile()) {
|
||||
RV = Builder.CreateLoad(ReturnValue);
|
||||
} else {
|
||||
// Get the stored value and nuke the now-dead store.
|
||||
RetDbgLoc = SI->getDebugLoc();
|
||||
RV = SI->getValueOperand();
|
||||
SI->eraseFromParent();
|
||||
|
||||
// If that was the only use of the return value, nuke it as well now.
|
||||
if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
|
||||
cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
|
||||
ReturnValue = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ABIArgInfo::Ignore:
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Coerce:
|
||||
RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this);
|
||||
case ABIArgInfo::Ignore:
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Expand:
|
||||
|
@ -1145,24 +1135,20 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
|||
}
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct:
|
||||
if (RV.isScalar()) {
|
||||
Args.push_back(RV.getScalarVal());
|
||||
} else if (RV.isComplex()) {
|
||||
llvm::Value *Tmp = llvm::UndefValue::get(ConvertType(I->second));
|
||||
Tmp = Builder.CreateInsertValue(Tmp, RV.getComplexVal().first, 0);
|
||||
Tmp = Builder.CreateInsertValue(Tmp, RV.getComplexVal().second, 1);
|
||||
Args.push_back(Tmp);
|
||||
} else {
|
||||
Args.push_back(Builder.CreateLoad(RV.getAggregateAddr()));
|
||||
}
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Ignore:
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct: {
|
||||
if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
|
||||
ArgInfo.getCoerceToType() == ConvertType(info_it->type)) {
|
||||
if (RV.isScalar())
|
||||
Args.push_back(RV.getScalarVal());
|
||||
else
|
||||
Args.push_back(Builder.CreateLoad(RV.getAggregateAddr()));
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Coerce: {
|
||||
// FIXME: Avoid the conversion through memory if possible.
|
||||
llvm::Value *SrcPtr;
|
||||
if (RV.isScalar()) {
|
||||
|
@ -1286,32 +1272,33 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
|||
return RValue::getAggregate(Args[0]);
|
||||
return RValue::get(EmitLoadOfScalar(Args[0], false, RetTy));
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct:
|
||||
if (RetTy->isAnyComplexType()) {
|
||||
llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
|
||||
llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
|
||||
return RValue::getComplex(std::make_pair(Real, Imag));
|
||||
}
|
||||
if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
|
||||
llvm::Value *DestPtr = ReturnValue.getValue();
|
||||
bool DestIsVolatile = ReturnValue.isVolatile();
|
||||
|
||||
if (!DestPtr) {
|
||||
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
|
||||
DestIsVolatile = false;
|
||||
}
|
||||
Builder.CreateStore(CI, DestPtr, DestIsVolatile);
|
||||
return RValue::getAggregate(DestPtr);
|
||||
}
|
||||
return RValue::get(CI);
|
||||
|
||||
case ABIArgInfo::Ignore:
|
||||
// If we are ignoring an argument that had a result, make sure to
|
||||
// construct the appropriate return value for our caller.
|
||||
return GetUndefRValue(RetTy);
|
||||
|
||||
case ABIArgInfo::Extend:
|
||||
case ABIArgInfo::Direct: {
|
||||
if (RetAI.getCoerceToType() == ConvertType(RetTy)) {
|
||||
if (RetTy->isAnyComplexType()) {
|
||||
llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
|
||||
llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
|
||||
return RValue::getComplex(std::make_pair(Real, Imag));
|
||||
}
|
||||
if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
|
||||
llvm::Value *DestPtr = ReturnValue.getValue();
|
||||
bool DestIsVolatile = ReturnValue.isVolatile();
|
||||
|
||||
case ABIArgInfo::Coerce: {
|
||||
if (!DestPtr) {
|
||||
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
|
||||
DestIsVolatile = false;
|
||||
}
|
||||
Builder.CreateStore(CI, DestPtr, DestIsVolatile);
|
||||
return RValue::getAggregate(DestPtr);
|
||||
}
|
||||
return RValue::get(CI);
|
||||
}
|
||||
|
||||
llvm::Value *DestPtr = ReturnValue.getValue();
|
||||
bool DestIsVolatile = ReturnValue.isVolatile();
|
||||
|
||||
|
|
|
@ -14,13 +14,12 @@
|
|||
#ifndef CLANG_CODEGEN_CODEGENTYPES_H
|
||||
#define CLANG_CODEGEN_CODEGENTYPES_H
|
||||
|
||||
#include "CGCall.h"
|
||||
#include "GlobalDecl.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <vector>
|
||||
|
||||
#include "CGCall.h"
|
||||
#include "GlobalDecl.h"
|
||||
|
||||
namespace llvm {
|
||||
class FunctionType;
|
||||
class Module;
|
||||
|
|
|
@ -56,7 +56,11 @@ void ABIArgInfo::dump() const {
|
|||
OS << "(ABIArgInfo Kind=";
|
||||
switch (TheKind) {
|
||||
case Direct:
|
||||
OS << "Direct";
|
||||
OS << "Direct Type=";
|
||||
if (const llvm::Type *Ty = getCoerceToType())
|
||||
Ty->print(OS);
|
||||
else
|
||||
OS << "null";
|
||||
break;
|
||||
case Extend:
|
||||
OS << "Extend";
|
||||
|
@ -64,10 +68,6 @@ void ABIArgInfo::dump() const {
|
|||
case Ignore:
|
||||
OS << "Ignore";
|
||||
break;
|
||||
case Coerce:
|
||||
OS << "Coerce Type=";
|
||||
getCoerceToType()->print(OS);
|
||||
break;
|
||||
case Indirect:
|
||||
OS << "Indirect Align=" << getIndirectAlign()
|
||||
<< " Byal=" << getIndirectByVal();
|
||||
|
@ -451,14 +451,14 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
// registers and we need to make sure to pick a type the LLVM
|
||||
// backend will like.
|
||||
if (Size == 128)
|
||||
return ABIArgInfo::getCoerce(llvm::VectorType::get(
|
||||
return ABIArgInfo::getDirect(llvm::VectorType::get(
|
||||
llvm::Type::getInt64Ty(getVMContext()), 2));
|
||||
|
||||
// Always return in register if it fits in a general purpose
|
||||
// register, or if it is 64 bits and has a single element.
|
||||
if ((Size == 8 || Size == 16 || Size == 32) ||
|
||||
(Size == 64 && VT->getNumElements() == 1))
|
||||
return ABIArgInfo::getCoerce(llvm::IntegerType::get(getVMContext(),
|
||||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
|
||||
Size));
|
||||
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
|
@ -491,7 +491,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
// bit-fields can adjust that to be larger than the single
|
||||
// element type.
|
||||
uint64_t Size = getContext().getTypeSize(RetTy);
|
||||
return ABIArgInfo::getCoerce(
|
||||
return ABIArgInfo::getDirect(
|
||||
llvm::IntegerType::get(getVMContext(), (unsigned)Size));
|
||||
}
|
||||
|
||||
|
@ -499,20 +499,20 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
assert(getContext().getTypeSize(RetTy) ==
|
||||
getContext().getTypeSize(SeltTy) &&
|
||||
"Unexpect single element structure size!");
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getFloatTy(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getFloatTy(getVMContext()));
|
||||
}
|
||||
|
||||
if (BT->getKind() == BuiltinType::Double) {
|
||||
assert(getContext().getTypeSize(RetTy) ==
|
||||
getContext().getTypeSize(SeltTy) &&
|
||||
"Unexpect single element structure size!");
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getDoubleTy(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getDoubleTy(getVMContext()));
|
||||
}
|
||||
} else if (SeltTy->isPointerType()) {
|
||||
// FIXME: It would be really nice if this could come out as the proper
|
||||
// pointer type.
|
||||
const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(getVMContext());
|
||||
return ABIArgInfo::getCoerce(PtrTy);
|
||||
return ABIArgInfo::getDirect(PtrTy);
|
||||
} else if (SeltTy->isVectorType()) {
|
||||
// 64- and 128-bit vectors are never returned in a
|
||||
// register when inside a structure.
|
||||
|
@ -528,7 +528,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
// in a register.
|
||||
if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) {
|
||||
uint64_t Size = getContext().getTypeSize(RetTy);
|
||||
return ABIArgInfo::getCoerce(llvm::IntegerType::get(getVMContext(),Size));
|
||||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size));
|
||||
}
|
||||
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
|
@ -1139,7 +1139,7 @@ ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty,
|
|||
CoerceTo = llvm::Type::getFloatTy(CoerceTo->getContext());
|
||||
}
|
||||
|
||||
return ABIArgInfo::getCoerce(CoerceTo);
|
||||
return ABIArgInfo::getDirect(CoerceTo);
|
||||
}
|
||||
|
||||
ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
|
||||
|
@ -1195,8 +1195,6 @@ const llvm::Type *X86_64ABIInfo::Get16ByteVectorType(QualType Ty) const {
|
|||
STy = dyn_cast<llvm::StructType>(IRType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If the preferred type is a 16-byte vector, prefer to pass it.
|
||||
if (const llvm::VectorType *VT = dyn_cast<llvm::VectorType>(IRType)){
|
||||
const llvm::Type *EltTy = VT->getElementType();
|
||||
|
@ -1622,7 +1620,7 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
|
|||
"reg_save_area");
|
||||
if (neededInt && neededSSE) {
|
||||
// FIXME: Cleanup.
|
||||
assert(AI.isCoerce() && "Unexpected ABI info for mixed regs");
|
||||
assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
|
||||
const llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType());
|
||||
llvm::Value *Tmp = CGF.CreateTempAlloca(ST);
|
||||
assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs");
|
||||
|
@ -1948,7 +1946,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
|
|||
LLVMFields.push_back(llvm::ArrayType::get(ElemTy, SizeRegs));
|
||||
const llvm::Type* STy = llvm::StructType::get(getVMContext(), LLVMFields,
|
||||
true);
|
||||
return ABIArgInfo::getCoerce(STy);
|
||||
return ABIArgInfo::getDirect(STy);
|
||||
}
|
||||
|
||||
static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
|
||||
|
@ -2064,7 +2062,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
// FIXME: Consider using 2 x vector types if the back end handles them
|
||||
// correctly.
|
||||
if (RetTy->isAnyComplexType())
|
||||
return ABIArgInfo::getCoerce(llvm::IntegerType::get(getVMContext(),
|
||||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
|
||||
getContext().getTypeSize(RetTy)));
|
||||
|
||||
// Integer like structures are returned in r0.
|
||||
|
@ -2072,10 +2070,10 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
// Return in the smallest viable integer type.
|
||||
uint64_t Size = getContext().getTypeSize(RetTy);
|
||||
if (Size <= 8)
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
|
||||
if (Size <= 16)
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(getVMContext()));
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
|
||||
}
|
||||
|
||||
// Otherwise return in memory.
|
||||
|
@ -2093,10 +2091,10 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
if (Size <= 32) {
|
||||
// Return in the smallest viable integer type.
|
||||
if (Size <= 8)
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
|
||||
if (Size <= 16)
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(getVMContext()));
|
||||
return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
|
||||
return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
|
||||
}
|
||||
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
|
|
|
@ -152,10 +152,16 @@ struct f23S f24(struct f23S *X, struct f24s *P2) {
|
|||
// CHECK: define %struct.f24s @f24(%struct.f23S* %X, %struct.f24s* %P2)
|
||||
}
|
||||
|
||||
// rdar://8248065
|
||||
typedef float v4f32 __attribute__((__vector_size__(16)));
|
||||
|
||||
v4f32 f25(v4f32 X) {
|
||||
// CHECK: define <4 x float> @f25(<4 x float> %X.coerce)
|
||||
// CHECK: define <4 x float> @f25(<4 x float> %X)
|
||||
// CHECK-NOT: alloca
|
||||
// CHECK: %X.addr = alloca <4 x float>
|
||||
// CHECK-NOT: alloca
|
||||
// CHECK: store <4 x float> %X, <4 x float>* %X.addr
|
||||
// CHECK-NOT: store
|
||||
// CHECK: ret <4 x float>
|
||||
return X+X;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ struct s3_0 {};
|
|||
struct s3_1 { struct s3_0 a; long b; };
|
||||
void f3(struct s3_1 x) {}
|
||||
|
||||
// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a.coerce)
|
||||
// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a)
|
||||
// CHECK: define {{.*}} @_Z4f4_1M2s4FivE(i64 %a.coerce0, i64 %a.coerce1)
|
||||
struct s4 {};
|
||||
typedef int s4::* s4_mdp;
|
||||
|
|
Loading…
Reference in New Issue