// FIXME: Use iterator and sidestep silly type array creation.
-CGFunctionInfo::CGFunctionInfo(const FunctionTypeNoProto *FTNP)
- : IsVariadic(true)
-{
+CGFunctionInfo::CGFunctionInfo(const FunctionTypeNoProto *FTNP) {
ArgTypes.push_back(FTNP->getResultType());
}
-CGFunctionInfo::CGFunctionInfo(const FunctionTypeProto *FTP)
- : IsVariadic(FTP->isVariadic())
-{
+CGFunctionInfo::CGFunctionInfo(const FunctionTypeProto *FTP) {
ArgTypes.push_back(FTP->getResultType());
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTypes.push_back(FTP->getArgType(i));
}
// FIXME: Is there really any reason to have this still?
-CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD)
-{
+CGFunctionInfo::CGFunctionInfo(const FunctionDecl *FD) {
const FunctionType *FTy = FD->getType()->getAsFunctionType();
const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FTy);
ArgTypes.push_back(FTy->getResultType());
if (FTP) {
- IsVariadic = FTP->isVariadic();
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTypes.push_back(FTP->getArgType(i));
- } else {
- IsVariadic = true;
}
}
CGFunctionInfo::CGFunctionInfo(const ObjCMethodDecl *MD,
- const ASTContext &Context)
- : IsVariadic(MD->isVariadic())
-{
+ const ASTContext &Context) {
ArgTypes.push_back(MD->getResultType());
ArgTypes.push_back(MD->getSelfDecl()->getType());
ArgTypes.push_back(Context.getObjCSelType());
ArgTypes.push_back((*i)->getType());
}
-CGFunctionInfo::CGFunctionInfo(QualType ResTy, const CallArgList &Args,
- bool _IsVariadic)
- : IsVariadic(_IsVariadic)
-{
+CGFunctionInfo::CGFunctionInfo(QualType ResTy, const CallArgList &Args) {
ArgTypes.push_back(ResTy);
for (CallArgList::const_iterator i = Args.begin(), e = Args.end();
i != e; ++i)
ArgTypes.push_back(i->second);
}
+CGFunctionInfo::CGFunctionInfo(QualType ResTy, const FunctionArgList &Args) {
+ ArgTypes.push_back(ResTy);
+ for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
+ i != e; ++i)
+ ArgTypes.push_back(i->second);
+}
+
ArgTypeIterator CGFunctionInfo::argtypes_begin() const {
return ArgTypes.begin();
}
/***/
+bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
+ return getABIReturnInfo(RetTy, getTypes()).isStructRet();
+}
+
const llvm::FunctionType *
-CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
+CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) {
std::vector<const llvm::Type*> ArgTys;
const llvm::Type *ResultType = 0;
}
}
- return llvm::FunctionType::get(ResultType, ArgTys, FI.isVariadic());
-}
-
-bool CodeGenModule::ReturnTypeUsesSret(QualType RetTy) {
- return getABIReturnInfo(RetTy, getTypes()).isStructRet();
+ return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
}
void CodeGenModule::ConstructAttributeList(const Decl *TargetDecl,
void CodeGenFunction::EmitFunctionProlog(llvm::Function *Fn,
QualType RetTy,
const FunctionArgList &Args) {
+ CGFunctionInfo FnInfo(RetTy, Args);
+
// Emit allocs for param decls. Give the LLVM Argument nodes names.
llvm::Function::arg_iterator AI = Fn->arg_begin();
}
RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
- QualType RetTy,
+ const CGFunctionInfo &CallInfo,
const CallArgList &CallArgs) {
llvm::SmallVector<llvm::Value*, 16> Args;
// Handle struct-return functions by passing a pointer to the
// location that we would like to return into.
+ QualType RetTy = CallInfo.getReturnType();
ABIArgInfo RetAI = getABIReturnInfo(RetTy, CGM.getTypes());
switch (RetAI.getKind()) {
case ABIArgInfo::StructRet:
}
llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
- const llvm::Type *FnType =
- cast<llvm::PointerType>(Callee->getType())->getElementType();
- CGFunctionInfo CallInfo(RetTy, CallArgs,
- cast<llvm::FunctionType>(FnType)->isVarArg());
// FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set.
CodeGen::AttributeListType AttributeList;
/// CGFunctionInfo - Class to encapsulate the information about a
/// function definition.
class CGFunctionInfo {
- bool IsVariadic;
-
llvm::SmallVector<QualType, 16> ArgTypes;
public:
CGFunctionInfo(const FunctionTypeNoProto *FTNP);
CGFunctionInfo(const FunctionTypeProto *FTP);
CGFunctionInfo(const FunctionDecl *FD);
- CGFunctionInfo(const ObjCMethodDecl *MD,
- const ASTContext &Context);
- CGFunctionInfo(QualType ResTy, const CallArgList &Args,
- bool _IsVariadic);
-
- bool isVariadic() const { return IsVariadic; }
+ CGFunctionInfo(const ObjCMethodDecl *MD, const ASTContext &Context);
+ CGFunctionInfo(QualType ResTy, const CallArgList &Args);
+ CGFunctionInfo(QualType ResTy, const FunctionArgList &Args);
ArgTypeIterator argtypes_begin() const;
ArgTypeIterator argtypes_end() const;
+
+ QualType getReturnType() const { return ArgTypes[0]; }
};
} // end namespace CodeGen
} // end namespace clang
Args.push_back(std::make_pair(EmitAnyExprToTemp(*I),
I->getType()));
- return EmitCall(Callee, ResultType, Args);
+ return EmitCall(Callee, CGFunctionInfo(ResultType, Args), Args);
}
Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
- RValue RV = EmitCall(GetPropertyFn, PD->getType(), Args);
+ RValue RV = EmitCall(GetPropertyFn, CGFunctionInfo(PD->getType(), Args),
+ Args);
// We need to fix the type here. Ivars with copy & retain are
// always objects so we don't need to worry about complex or
// aggregates.
getContext().BoolTy));
Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False),
getContext().BoolTy));
- EmitCall(SetPropertyFn, PD->getType(), Args);
+ EmitCall(SetPropertyFn, CGFunctionInfo(PD->getType(), Args), Args);
} else {
SourceLocation Loc = PD->getLocation();
ValueDecl *Self = OMD->getSelfDecl();
ActualArgs.push_back(std::make_pair(RValue::get(cmd),
CGF.getContext().getObjCSelType()));
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
- return CGF.EmitCall(imp, ResultType, ActualArgs);
+ return CGF.EmitCall(imp, CGFunctionInfo(ResultType, ActualArgs), ActualArgs);
}
/// Generate code for a message send expression.
ActualArgs.push_back(std::make_pair(RValue::get(cmd),
CGF.getContext().getObjCSelType()));
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
- return CGF.EmitCall(imp, ResultType, ActualArgs);
+ return CGF.EmitCall(imp, CGFunctionInfo(ResultType, ActualArgs), ActualArgs);
}
/// Generates a MethodList. Used in construction of a objc_class and
bool isClassMethod = !OMD->isInstanceMethod();
const llvm::FunctionType *MethodTy =
- CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
+ CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()),
+ OMD->isVariadic());
std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
MethodName, isClassMethod);
CGF.getContext().getObjCSelType()));
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
- const llvm::FunctionType *FTy =
- CGM.getTypes().GetFunctionType(CGFunctionInfo(ResultType, ActualArgs,
- false));
+ CGFunctionInfo FnInfo(ResultType, ActualArgs);
+ const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FnInfo, false);
llvm::Constant *Fn;
if (CGM.ReturnTypeUsesSret(ResultType)) {
Fn = ObjCTypes.getSendFn(IsSuper);
}
Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
- return CGF.EmitCall(Fn, ResultType, ActualArgs);
+ return CGF.EmitCall(Fn, FnInfo, ActualArgs);
}
llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
}
llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
- const ObjCContainerDecl *CD) {
+ const ObjCContainerDecl *CD) {
std::string Name;
GetNameForMethod(OMD, CD, Name);
const llvm::FunctionType *MethodTy =
- CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
+ CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()),
+ OMD->isVariadic());
llvm::Function *Method =
llvm::Function::Create(MethodTy,
llvm::GlobalValue::InternalLinkage,
namespace CodeGen {
class CodeGenModule;
class CodeGenTypes;
+ class CGFunctionInfo;
class CGRecordLayout;
/// CodeGenFunction - This class organizes the per-function state that is used
/// specifies both the LLVM arguments and the types they were
/// derived from.
RValue EmitCall(llvm::Value *Callee,
- QualType ResultType,
+ const CGFunctionInfo &FnInfo,
const CallArgList &Args);
RValue EmitCallExpr(const CallExpr *E);
VT.getNumElements());
}
case Type::FunctionNoProto:
- return GetFunctionType(CGFunctionInfo(cast<FunctionTypeNoProto>(&Ty)));
- case Type::FunctionProto:
- return GetFunctionType(CGFunctionInfo(cast<FunctionTypeProto>(&Ty)));
+ return GetFunctionType(CGFunctionInfo(cast<FunctionTypeNoProto>(&Ty)),
+ true);
+ case Type::FunctionProto: {
+ const FunctionTypeProto *FTP = cast<FunctionTypeProto>(&Ty);
+ return GetFunctionType(CGFunctionInfo(FTP), FTP->isVariadic());
+ }
case Type::ASQual:
return
const llvm::Type *ConvertTypeForMem(QualType T);
/// GetFunctionType - Get the LLVM function type for \arg Info.
- const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info);
+ const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info,
+ bool IsVariadic);
const CGRecordLayout *getCGRecordLayout(const TagDecl*) const;
/// Returns a StructType representing an Objective-C object