aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r--lib/CodeGen/CGCall.cpp198
1 files changed, 122 insertions, 76 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 82ee4fc1ee36..7d2b9d355ec6 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -67,39 +67,68 @@ static CanQualType GetReturnType(QualType RetTy) {
return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType();
}
-/// Arrange the argument and result information for a value of the
-/// given unprototyped function type.
+/// Arrange the argument and result information for a value of the given
+/// unprototyped freestanding function type.
const CGFunctionInfo &
-CodeGenTypes::arrangeFunctionType(CanQual<FunctionNoProtoType> FTNP) {
+CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) {
// When translating an unprototyped function type, always use a
// variadic type.
- return arrangeFunctionType(FTNP->getResultType().getUnqualifiedType(),
- ArrayRef<CanQualType>(),
- FTNP->getExtInfo(),
- RequiredArgs(0));
+ return arrangeLLVMFunctionInfo(FTNP->getResultType().getUnqualifiedType(),
+ ArrayRef<CanQualType>(),
+ FTNP->getExtInfo(),
+ RequiredArgs(0));
}
-/// Arrange the argument and result information for a value of the
-/// given function type, on top of any implicit parameters already
-/// stored.
-static const CGFunctionInfo &arrangeFunctionType(CodeGenTypes &CGT,
- SmallVectorImpl<CanQualType> &argTypes,
- CanQual<FunctionProtoType> FTP) {
- RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, argTypes.size());
+/// Arrange the LLVM function layout for a value of the given function
+/// type, on top of any implicit parameters already stored. Use the
+/// given ExtInfo instead of the ExtInfo from the function type.
+static const CGFunctionInfo &arrangeLLVMFunctionInfo(CodeGenTypes &CGT,
+ SmallVectorImpl<CanQualType> &prefix,
+ CanQual<FunctionProtoType> FTP,
+ FunctionType::ExtInfo extInfo) {
+ RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size());
// FIXME: Kill copy.
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
- argTypes.push_back(FTP->getArgType(i));
+ prefix.push_back(FTP->getArgType(i));
CanQualType resultType = FTP->getResultType().getUnqualifiedType();
- return CGT.arrangeFunctionType(resultType, argTypes,
- FTP->getExtInfo(), required);
+ return CGT.arrangeLLVMFunctionInfo(resultType, prefix, extInfo, required);
+}
+
+/// Arrange the argument and result information for a free function (i.e.
+/// not a C++ or ObjC instance method) of the given type.
+static const CGFunctionInfo &arrangeFreeFunctionType(CodeGenTypes &CGT,
+ SmallVectorImpl<CanQualType> &prefix,
+ CanQual<FunctionProtoType> FTP) {
+ return arrangeLLVMFunctionInfo(CGT, prefix, FTP, FTP->getExtInfo());
+}
+
+/// Given the formal ext-info of a C++ instance method, adjust it
+/// according to the C++ ABI in effect.
+static void adjustCXXMethodInfo(CodeGenTypes &CGT,
+ FunctionType::ExtInfo &extInfo,
+ bool isVariadic) {
+ if (extInfo.getCC() == CC_Default) {
+ CallingConv CC = CGT.getContext().getDefaultCXXMethodCallConv(isVariadic);
+ extInfo = extInfo.withCallingConv(CC);
+ }
+}
+
+/// Arrange the argument and result information for a free function (i.e.
+/// not a C++ or ObjC instance method) of the given type.
+static const CGFunctionInfo &arrangeCXXMethodType(CodeGenTypes &CGT,
+ SmallVectorImpl<CanQualType> &prefix,
+ CanQual<FunctionProtoType> FTP) {
+ FunctionType::ExtInfo extInfo = FTP->getExtInfo();
+ adjustCXXMethodInfo(CGT, extInfo, FTP->isVariadic());
+ return arrangeLLVMFunctionInfo(CGT, prefix, FTP, extInfo);
}
/// Arrange the argument and result information for a value of the
-/// given function type.
+/// given freestanding function type.
const CGFunctionInfo &
-CodeGenTypes::arrangeFunctionType(CanQual<FunctionProtoType> FTP) {
+CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) {
SmallVector<CanQualType, 16> argTypes;
- return ::arrangeFunctionType(*this, argTypes, FTP);
+ return ::arrangeFreeFunctionType(*this, argTypes, FTP);
}
static CallingConv getCallingConventionForDecl(const Decl *D) {
@@ -134,7 +163,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
// Add the 'this' pointer.
argTypes.push_back(GetThisType(Context, RD));
- return ::arrangeFunctionType(*this, argTypes,
+ return ::arrangeCXXMethodType(*this, argTypes,
FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
}
@@ -154,7 +183,7 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
return arrangeCXXMethodType(MD->getParent(), prototype.getTypePtr());
}
- return arrangeFunctionType(prototype);
+ return arrangeFreeFunctionType(prototype);
}
/// Arrange the argument and result information for a declaration
@@ -176,7 +205,9 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
argTypes.push_back(FTP->getArgType(i));
- return arrangeFunctionType(resultType, argTypes, FTP->getExtInfo(), required);
+ FunctionType::ExtInfo extInfo = FTP->getExtInfo();
+ adjustCXXMethodInfo(*this, extInfo, FTP->isVariadic());
+ return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo, required);
}
/// Arrange the argument and result information for a declaration,
@@ -193,9 +224,12 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
CanQual<FunctionProtoType> FTP = GetFormalType(D);
assert(FTP->getNumArgs() == 0 && "dtor with formal parameters");
+ assert(FTP->isVariadic() == 0 && "dtor with formal parameters");
- return arrangeFunctionType(resultType, argTypes, FTP->getExtInfo(),
- RequiredArgs::All);
+ FunctionType::ExtInfo extInfo = FTP->getExtInfo();
+ adjustCXXMethodInfo(*this, extInfo, false);
+ return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo,
+ RequiredArgs::All);
}
/// Arrange the argument and result information for the declaration or
@@ -214,14 +248,14 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) {
// non-variadic type.
if (isa<FunctionNoProtoType>(FTy)) {
CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>();
- return arrangeFunctionType(noProto->getResultType(),
- ArrayRef<CanQualType>(),
- noProto->getExtInfo(),
- RequiredArgs::All);
+ return arrangeLLVMFunctionInfo(noProto->getResultType(),
+ ArrayRef<CanQualType>(),
+ noProto->getExtInfo(),
+ RequiredArgs::All);
}
assert(isa<FunctionProtoType>(FTy));
- return arrangeFunctionType(FTy.getAs<FunctionProtoType>());
+ return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>());
}
/// Arrange the argument and result information for the declaration or
@@ -261,8 +295,8 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
RequiredArgs required =
(MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All);
- return arrangeFunctionType(GetReturnType(MD->getResultType()), argTys,
- einfo, required);
+ return arrangeLLVMFunctionInfo(GetReturnType(MD->getResultType()), argTys,
+ einfo, required);
}
const CGFunctionInfo &
@@ -284,8 +318,8 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
/// because the function might be unprototyped, in which case it's
/// target-dependent in crazy ways.
const CGFunctionInfo &
-CodeGenTypes::arrangeFunctionCall(const CallArgList &args,
- const FunctionType *fnType) {
+CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
+ const FunctionType *fnType) {
RequiredArgs required = RequiredArgs::All;
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) {
if (proto->isVariadic())
@@ -295,22 +329,39 @@ CodeGenTypes::arrangeFunctionCall(const CallArgList &args,
required = RequiredArgs(0);
}
- return arrangeFunctionCall(fnType->getResultType(), args,
- fnType->getExtInfo(), required);
+ return arrangeFreeFunctionCall(fnType->getResultType(), args,
+ fnType->getExtInfo(), required);
+}
+
+const CGFunctionInfo &
+CodeGenTypes::arrangeFreeFunctionCall(QualType resultType,
+ const CallArgList &args,
+ FunctionType::ExtInfo info,
+ RequiredArgs required) {
+ // FIXME: Kill copy.
+ SmallVector<CanQualType, 16> argTypes;
+ for (CallArgList::const_iterator i = args.begin(), e = args.end();
+ i != e; ++i)
+ argTypes.push_back(Context.getCanonicalParamType(i->Ty));
+ return arrangeLLVMFunctionInfo(GetReturnType(resultType), argTypes, info,
+ required);
}
+/// Arrange a call to a C++ method, passing the given arguments.
const CGFunctionInfo &
-CodeGenTypes::arrangeFunctionCall(QualType resultType,
- const CallArgList &args,
- const FunctionType::ExtInfo &info,
- RequiredArgs required) {
+CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args,
+ const FunctionProtoType *FPT,
+ RequiredArgs required) {
// FIXME: Kill copy.
SmallVector<CanQualType, 16> argTypes;
for (CallArgList::const_iterator i = args.begin(), e = args.end();
i != e; ++i)
argTypes.push_back(Context.getCanonicalParamType(i->Ty));
- return arrangeFunctionType(GetReturnType(resultType), argTypes, info,
- required);
+
+ FunctionType::ExtInfo info = FPT->getExtInfo();
+ adjustCXXMethodInfo(*this, info, FPT->isVariadic());
+ return arrangeLLVMFunctionInfo(GetReturnType(FPT->getResultType()),
+ argTypes, info, required);
}
const CGFunctionInfo &
@@ -326,23 +377,23 @@ CodeGenTypes::arrangeFunctionDeclaration(QualType resultType,
RequiredArgs required =
(isVariadic ? RequiredArgs(args.size()) : RequiredArgs::All);
- return arrangeFunctionType(GetReturnType(resultType), argTypes, info,
- required);
+ return arrangeLLVMFunctionInfo(GetReturnType(resultType), argTypes, info,
+ required);
}
const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
- return arrangeFunctionType(getContext().VoidTy, ArrayRef<CanQualType>(),
- FunctionType::ExtInfo(), RequiredArgs::All);
+ return arrangeLLVMFunctionInfo(getContext().VoidTy, ArrayRef<CanQualType>(),
+ FunctionType::ExtInfo(), RequiredArgs::All);
}
/// Arrange the argument and result information for an abstract value
/// of a given function type. This is the method which all of the
/// above functions ultimately defer to.
const CGFunctionInfo &
-CodeGenTypes::arrangeFunctionType(CanQualType resultType,
- ArrayRef<CanQualType> argTypes,
- const FunctionType::ExtInfo &info,
- RequiredArgs required) {
+CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
+ ArrayRef<CanQualType> argTypes,
+ FunctionType::ExtInfo info,
+ RequiredArgs required) {
#ifndef NDEBUG
for (ArrayRef<CanQualType>::const_iterator
I = argTypes.begin(), E = argTypes.end(); I != E; ++I)
@@ -445,10 +496,9 @@ void CodeGenTypes::GetExpandedTypes(QualType type,
} else {
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
- const FieldDecl *FD = *i;
- assert(!FD->isBitField() &&
+ assert(!i->isBitField() &&
"Cannot expand structure with bit-field members.");
- GetExpandedTypes(FD->getType(), expandedTypes);
+ GetExpandedTypes(i->getType(), expandedTypes);
}
}
} else if (const ComplexType *CT = type->getAs<ComplexType>()) {
@@ -933,14 +983,18 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
case ABIArgInfo::Ignore:
break;
- case ABIArgInfo::Indirect:
- PAL.push_back(llvm::AttributeWithIndex::get(Index,
- llvm::Attribute::StructRet));
+ case ABIArgInfo::Indirect: {
+ llvm::Attributes SRETAttrs = llvm::Attribute::StructRet;
+ if (RetAI.getInReg())
+ SRETAttrs |= llvm::Attribute::InReg;
+ PAL.push_back(llvm::AttributeWithIndex::get(Index, SRETAttrs));
+
++Index;
// sret disables readnone and readonly
FuncAttrs &= ~(llvm::Attribute::ReadOnly |
llvm::Attribute::ReadNone);
break;
+ }
case ABIArgInfo::Expand:
llvm_unreachable("Invalid ABI kind for return argument");
@@ -949,14 +1003,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
if (RetAttrs)
PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs));
- // FIXME: RegParm should be reduced in case of global register variable.
- signed RegParm;
- if (FI.getHasRegParm())
- RegParm = FI.getRegParm();
- else
- RegParm = CodeGenOpts.NumRegisterParameters;
-
- unsigned PointerWidth = getContext().getTargetInfo().getPointerWidth(0);
for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
ie = FI.arg_end(); it != ie; ++it) {
QualType ParamType = it->type;
@@ -974,22 +1020,22 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
Attrs |= llvm::Attribute::ZExt;
// FALL THROUGH
case ABIArgInfo::Direct:
- if (RegParm > 0 &&
- (ParamType->isIntegerType() || ParamType->isPointerType() ||
- ParamType->isReferenceType())) {
- RegParm -=
- (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
- if (RegParm >= 0)
+ if (AI.getInReg())
Attrs |= llvm::Attribute::InReg;
- }
+
// FIXME: handle sseregparm someday...
// Increment Index if there is padding.
Index += (AI.getPaddingType() != 0);
if (llvm::StructType *STy =
- dyn_cast<llvm::StructType>(AI.getCoerceToType()))
- Index += STy->getNumElements()-1; // 1 will be added below.
+ dyn_cast<llvm::StructType>(AI.getCoerceToType())) {
+ unsigned Extra = STy->getNumElements()-1; // 1 will be added below.
+ if (Attrs != llvm::Attribute::None)
+ for (unsigned I = 0; I < Extra; ++I)
+ PAL.push_back(llvm::AttributeWithIndex::get(Index + I, Attrs));
+ Index += Extra;
+ }
break;
case ABIArgInfo::Indirect:
@@ -1355,7 +1401,8 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF,
llvm::Value *result) {
// This is only applicable to a method with an immutable 'self'.
- const ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(CGF.CurCodeDecl);
+ const ObjCMethodDecl *method =
+ dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl);
if (!method) return 0;
const VarDecl *self = method->getSelfDecl();
if (!self->getType().isConstQualified()) return 0;
@@ -2066,8 +2113,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList, CallingConv);
- llvm::AttrListPtr Attrs = llvm::AttrListPtr::get(AttributeList.begin(),
- AttributeList.end());
+ llvm::AttrListPtr Attrs = llvm::AttrListPtr::get(AttributeList);
llvm::BasicBlock *InvokeDest = 0;
if (!(Attrs.getFnAttributes() & llvm::Attribute::NoUnwind))