summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/ABIInfo.h32
-rw-r--r--clang/lib/CodeGen/CGCall.cpp289
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.h5
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp46
-rw-r--r--clang/test/CodeGen/x86_64-arguments.c10
-rw-r--r--clang/test/CodeGenCXX/x86_64-arguments.cpp2
6 files changed, 187 insertions, 197 deletions
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 30f99c31e3d..642fddb5c8d 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -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!");
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index f0e107973c1..94cfd98d07d 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -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,42 +752,37 @@ 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:
- if (const llvm::StructType *STy =
- dyn_cast<llvm::StructType>(AI.getCoerceToType()))
- Index += STy->getNumElements();
- else
- ++Index;
- continue; // Skip index increment.
-
- case ABIArgInfo::Indirect:
- if (AI.getIndirectByVal())
- Attributes |= llvm::Attribute::ByVal;
-
- Attributes |=
- llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
- // byval disables readnone and readonly.
- FuncAttrs &= ~(llvm::Attribute::ReadOnly |
- llvm::Attribute::ReadNone);
- break;
-
case ABIArgInfo::Extend:
if (ParamType->isSignedIntegerType())
Attributes |= llvm::Attribute::SExt;
else if (ParamType->isUnsignedIntegerType())
Attributes |= llvm::Attribute::ZExt;
- // FALLS THROUGH
+ // FALL THROUGH
case ABIArgInfo::Direct:
if (RegParm > 0 &&
(ParamType->isIntegerType() || ParamType->isPointerType())) {
RegParm -=
- (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
+ (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()-1; // 1 will be added below.
+ break;
+
+ case ABIArgInfo::Indirect:
+ if (AI.getIndirectByVal())
+ Attributes |= llvm::Attribute::ByVal;
+
+ Attributes |=
+ llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
+ // byval disables readnone and readonly.
+ FuncAttrs &= ~(llvm::Attribute::ReadOnly |
+ llvm::Attribute::ReadNone);
break;
case ABIArgInfo::Ignore:
@@ -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;
}
- 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())));
- }
-
- // 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();
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index c7f48e6c9dd..54019f92439 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -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;
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index e8e4c5c4622..0f0dc0f888a 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -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);
diff --git a/clang/test/CodeGen/x86_64-arguments.c b/clang/test/CodeGen/x86_64-arguments.c
index 04447c12d9c..3bda8875c81 100644
--- a/clang/test/CodeGen/x86_64-arguments.c
+++ b/clang/test/CodeGen/x86_64-arguments.c
@@ -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;
}
diff --git a/clang/test/CodeGenCXX/x86_64-arguments.cpp b/clang/test/CodeGenCXX/x86_64-arguments.cpp
index df0c78ad941..6c42bb81709 100644
--- a/clang/test/CodeGenCXX/x86_64-arguments.cpp
+++ b/clang/test/CodeGenCXX/x86_64-arguments.cpp
@@ -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;
OpenPOWER on IntegriCloud