diff options
-rw-r--r-- | clang/lib/CodeGen/ABIInfo.h | 32 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 289 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 46 | ||||
-rw-r--r-- | clang/test/CodeGen/x86_64-arguments.c | 10 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/x86_64-arguments.cpp | 2 |
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; |