[cfe-commits] r55560 - in /cfe/trunk/lib/CodeGen: CGExpr.cpp CGObjC.cpp CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h CodeGenFunction.h
Daniel Dunbar
daniel at zuster.org
Fri Aug 29 20:02:32 PDT 2008
Author: ddunbar
Date: Fri Aug 29 22:02:31 2008
New Revision: 55560
URL: http://llvm.org/viewvc/llvm-project?rev=55560&view=rev
Log:
Refactor handling of calls:
- Added CodeGenFunction::EmitCall which just takes the callee, return
type, and a list of (Value*,QualType) pairs.
- Added CodeGenFunction::EmitCallArg which handles emitting code for
a call argument and turning it into an appropriate
(Value*,QualType) pair.
- Changed Objective-C runtime interface so that the actual emission
of arguments for message sends is (once again) done in the code to
emit a message send.
No intended functionality change, this is prep work for better ABI
support and for Objective-C property setter support.
Modified:
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CGObjCRuntime.h
cfe/trunk/lib/CodeGen/CodeGenFunction.h
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=55560&r1=55559&r2=55560&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Aug 29 22:02:31 2008
@@ -822,66 +822,77 @@
// type.
FnType = FnType->getAsPointerType()->getPointeeType();
QualType ResultType = FnType->getAsFunctionType()->getResultType();
- return EmitCallExprExt(Callee, ResultType, ArgBeg, ArgEnd, 0, 0);
+
+ CallArgList Args;
+ for (CallExpr::const_arg_iterator I = ArgBeg; I != ArgEnd; ++I)
+ EmitCallArg(*I, Args);
+
+ return EmitCall(Callee, ResultType, Args);
}
-RValue CodeGenFunction::EmitCallExprExt(llvm::Value *Callee,
- QualType ResultType,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd,
- llvm::Value **ExtraArgs,
- unsigned NumExtraArgs) {
- llvm::SmallVector<llvm::Value*, 16> Args;
+void CodeGenFunction::EmitCallArg(const Expr *E, CallArgList &Args) {
+ QualType ArgTy = E->getType();
+ llvm::Value *ArgValue;
+
+ if (!hasAggregateLLVMType(ArgTy)) {
+ // Scalar argument is passed by-value.
+ ArgValue = EmitScalarExpr(E);
+ } else if (ArgTy->isAnyComplexType()) {
+ // Make a temporary alloca to pass the argument.
+ ArgValue = CreateTempAlloca(ConvertType(ArgTy));
+ EmitComplexExprIntoAddr(E, ArgValue, false);
+ } else {
+ ArgValue = CreateTempAlloca(ConvertType(ArgTy));
+ EmitAggExpr(E, ArgValue, false);
+ }
+ Args.push_back(std::make_pair(ArgValue, E->getType()));
+}
+
+RValue CodeGenFunction::EmitCall(llvm::Value *Callee,
+ QualType ResultType,
+ const CallArgList &CallArgs) {
+ llvm::SmallVector<llvm::Value*, 16> Args;
+ llvm::Value *TempArg0 = 0;
+
// Handle struct-return functions by passing a pointer to the location that
// we would like to return into.
if (hasAggregateLLVMType(ResultType)) {
// Create a temporary alloca to hold the result of the call. :(
- Args.push_back(CreateTempAlloca(ConvertType(ResultType)));
- // FIXME: set the stret attribute on the argument.
+ TempArg0 = CreateTempAlloca(ConvertType(ResultType));
+ Args.push_back(TempArg0);
}
- Args.insert(Args.end(), ExtraArgs, ExtraArgs + NumExtraArgs);
-
- for (CallExpr::const_arg_iterator I = ArgBeg; I != ArgEnd; ++I) {
- QualType ArgTy = I->getType();
-
- if (!hasAggregateLLVMType(ArgTy)) {
- // Scalar argument is passed by-value.
- Args.push_back(EmitScalarExpr(*I));
- } else if (ArgTy->isAnyComplexType()) {
- // Make a temporary alloca to pass the argument.
- llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
- EmitComplexExprIntoAddr(*I, DestMem, false);
- Args.push_back(DestMem);
- } else {
- llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
- EmitAggExpr(*I, DestMem, false);
- Args.push_back(DestMem);
- }
- }
+ for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
+ I != E; ++I)
+ Args.push_back(I->first);
llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
// Note that there is parallel code in SetFunctionAttributes in CodeGenModule
llvm::SmallVector<llvm::ParamAttrsWithIndex, 8> ParamAttrList;
- if (hasAggregateLLVMType(ResultType))
+ unsigned Index = 1;
+ if (TempArg0) {
ParamAttrList.push_back(
- llvm::ParamAttrsWithIndex::get(1, llvm::ParamAttr::StructRet));
- unsigned increment = NumExtraArgs + (hasAggregateLLVMType(ResultType) ? 2 : 1);
-
- unsigned i = 0;
- for (CallExpr::const_arg_iterator I = ArgBeg; I != ArgEnd; ++I, ++i) {
- QualType ParamType = I->getType();
+ llvm::ParamAttrsWithIndex::get(Index, llvm::ParamAttr::StructRet));
+ ++Index;
+ }
+
+ for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
+ I != E; ++I, ++Index) {
+ QualType ParamType = I->second;
unsigned ParamAttrs = 0;
if (ParamType->isRecordType())
ParamAttrs |= llvm::ParamAttr::ByVal;
- if (ParamType->isSignedIntegerType() && ParamType->isPromotableIntegerType())
- ParamAttrs |= llvm::ParamAttr::SExt;
- if (ParamType->isUnsignedIntegerType() && ParamType->isPromotableIntegerType())
- ParamAttrs |= llvm::ParamAttr::ZExt;
+ if (ParamType->isPromotableIntegerType()) {
+ if (ParamType->isSignedIntegerType()) {
+ ParamAttrs |= llvm::ParamAttr::SExt;
+ } else if (ParamType->isUnsignedIntegerType()) {
+ ParamAttrs |= llvm::ParamAttr::ZExt;
+ }
+ }
if (ParamAttrs)
- ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(i + increment,
+ ParamAttrList.push_back(llvm::ParamAttrsWithIndex::get(Index,
ParamAttrs));
}
CI->setParamAttrs(llvm::PAListPtr::get(ParamAttrList.begin(),
@@ -892,15 +903,15 @@
if (CI->getType() != llvm::Type::VoidTy)
CI->setName("call");
else if (ResultType->isAnyComplexType())
- return RValue::getComplex(LoadComplexFromAddr(Args[0], false));
+ return RValue::getComplex(LoadComplexFromAddr(TempArg0, false));
else if (hasAggregateLLVMType(ResultType))
// Struct return.
- return RValue::getAggregate(Args[0]);
+ return RValue::getAggregate(TempArg0);
else {
// void return.
assert(ResultType->isVoidType() && "Should only have a void expr here");
CI = 0;
}
- return RValue::get(CI);
+ return RValue::get(CI);
}
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=55560&r1=55559&r2=55560&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Fri Aug 29 22:02:31 2008
@@ -78,15 +78,21 @@
Receiver = EmitScalarExpr(E->getReceiver());
}
+ CallArgList Args;
+ for (CallExpr::const_arg_iterator i = E->arg_begin(), e = E->arg_end();
+ i != e; ++i)
+ EmitCallArg(*i, Args);
+
if (isSuperMessage) {
// super is only valid in an Objective-C method
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
return Runtime.GenerateMessageSendSuper(*this, E,
OMD->getClassInterface(),
Receiver,
- isClassMessage);
+ isClassMessage,
+ Args);
}
- return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage);
+ return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage, Args);
}
/// StartObjCMethod - Begin emission of an ObjCMethod. This generates
Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=55560&r1=55559&r2=55560&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Fri Aug 29 22:02:31 2008
@@ -98,13 +98,15 @@
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
llvm::Value *Receiver,
- bool IsClassMessage);
+ bool IsClassMessage,
+ const CallArgList &CallArgs);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
- bool IsClassMessage);
+ bool IsClassMessage,
+ const CallArgList &CallArgs);
virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
const ObjCInterfaceDecl *OID);
virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
@@ -240,7 +242,8 @@
const ObjCMessageExpr *E,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
- bool IsClassMessage) {
+ bool IsClassMessage,
+ const CallArgList &CallArgs) {
const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
// TODO: This should be cached, not looked up every time.
@@ -273,11 +276,13 @@
lookupArgs+2);
// Call the method
- llvm::Value *Args[2];
- Args[0] = Receiver;
- Args[1] = cmd;
- return CGF.EmitCallExprExt(imp, E->getType(), E->arg_begin(), E->arg_end(),
- Args, 2);
+ CallArgList ActualArgs;
+ ActualArgs.push_back(std::make_pair(Receiver,
+ CGF.getContext().getObjCIdType()));
+ ActualArgs.push_back(std::make_pair(cmd,
+ CGF.getContext().getObjCSelType()));
+ ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+ return CGF.EmitCall(imp, E->getType(), ActualArgs);
}
/// Generate code for a message send expression.
@@ -285,7 +290,8 @@
CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
llvm::Value *Receiver,
- bool IsClassMessage) {
+ bool IsClassMessage,
+ const CallArgList &CallArgs) {
const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
@@ -316,11 +322,13 @@
llvm::Value *imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
// Call the method.
- llvm::Value *Args[2];
- Args[0] = Receiver;
- Args[1] = cmd;
- return CGF.EmitCallExprExt(imp, E->getType(), E->arg_begin(), E->arg_end(),
- Args, 2);
+ CallArgList ActualArgs;
+ ActualArgs.push_back(std::make_pair(Receiver,
+ CGF.getContext().getObjCIdType()));
+ ActualArgs.push_back(std::make_pair(cmd,
+ CGF.getContext().getObjCSelType()));
+ ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+ return CGF.EmitCall(imp, E->getType(), ActualArgs);
}
/// Generates a MethodList. Used in construction of a objc_class and
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=55560&r1=55559&r2=55560&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Aug 29 22:02:31 2008
@@ -55,6 +55,11 @@
/// (typeof(Protocol))
const llvm::Type *ExternalProtocolPtrTy;
+ // SuperCTy - clang type for struct objc_super.
+ QualType SuperCTy;
+ // SuperPtrCTy - clang type for struct objc_super *.
+ QualType SuperPtrCTy;
+
/// SuperTy - LLVM type for struct objc_super.
const llvm::StructType *SuperTy;
/// SuperPtrTy - LLVM type for struct objc_super *.
@@ -216,7 +221,9 @@
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
llvm::Value *Arg0,
- bool IsSuper);
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs);
/// EmitIvarList - Emit the ivar list for the given
/// implementation. If ForClass is true the list of class ivars
@@ -332,14 +339,16 @@
virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
llvm::Value *Receiver,
- bool IsClassMessage);
+ bool IsClassMessage,
+ const CallArgList &CallArgs);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
- bool IsClassMessage);
+ bool IsClassMessage,
+ const CallArgList &CallArgs);
virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
const ObjCInterfaceDecl *ID);
@@ -422,7 +431,8 @@
const ObjCMessageExpr *E,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
- bool IsClassMessage) {
+ bool IsClassMessage,
+ const CallArgList &CallArgs) {
// Create and init a super structure; this is a (receiver, class)
// pair we will pass to objc_msgSendSuper.
llvm::Value *ObjCSuper =
@@ -442,42 +452,54 @@
} else {
Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
}
+ // FIXME: We shouldn't need to do this cast, rectify the ASTContext
+ // and ObjCTypes types.
+ const llvm::Type *ClassTy =
+ CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
+ Target = CGF.Builder.CreateBitCast(Target, ClassTy);
CGF.Builder.CreateStore(Target,
CGF.Builder.CreateStructGEP(ObjCSuper, 1));
- return EmitMessageSend(CGF, E, ObjCSuper, true);
+ return EmitMessageSend(CGF, E,
+ ObjCSuper, ObjCTypes.SuperPtrCTy,
+ true, CallArgs);
}
/// Generate code for a message send expression.
CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
llvm::Value *Receiver,
- bool IsClassMessage) {
+ bool IsClassMessage,
+ const CallArgList &CallArgs) {
llvm::Value *Arg0 =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
- return EmitMessageSend(CGF, E, Arg0, false);
+ return EmitMessageSend(CGF, E,
+ Arg0, CGF.getContext().getObjCIdType(),
+ false, CallArgs);
}
CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
llvm::Value *Arg0,
- bool IsSuper) {
- llvm::Value *Args[2];
- Args[0] = Arg0;
- Args[1] = EmitSelector(CGF.Builder, E->getSelector());
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs) {
+ CallArgList ActualArgs;
+ ActualArgs.push_back(std::make_pair(Arg0, Arg0Ty));
+ ActualArgs.push_back(std::make_pair(EmitSelector(CGF.Builder,
+ E->getSelector()),
+ CGF.getContext().getObjCSelType()));
+ ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
// FIXME: This is a hack, we are implicitly coordinating with
// EmitCallExprExt, which will move the return type to the first
// parameter and set the structure return flag. See
// getMessageSendFn().
-
const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
- return CGF.EmitCallExprExt(ObjCTypes.getMessageSendFn(IsSuper, ReturnTy),
- E->getType(),
- E->arg_begin(),
- E->arg_end(),
- Args, 2);
+ return CGF.EmitCall(ObjCTypes.getMessageSendFn(IsSuper, ReturnTy),
+ E->getType(),
+ ActualArgs);
}
llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
@@ -1820,12 +1842,27 @@
NULL);
CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
- SuperTy =
- llvm::StructType::get(ObjectPtrTy,
- ClassPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_super",
- SuperTy);
+ // I'm not sure I like this. The implicit coordination is a bit
+ // gross. We should solve this in a reasonable fashion because this
+ // is a pretty common task (match some runtime data structure with
+ // an LLVM data structure).
+
+ // FIXME: This is leaked.
+ // FIXME: Merge with rewriter code?
+ RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
+ SourceLocation(),
+ &Ctx.Idents.get("_objc_super"), 0);
+ FieldDecl *FieldDecls[2];
+ FieldDecls[0] = FieldDecl::Create(Ctx, SourceLocation(), 0,
+ Ctx.getObjCIdType());
+ FieldDecls[1] = FieldDecl::Create(Ctx, SourceLocation(), 0,
+ Ctx.getObjCClassType());
+ RD->defineBody(FieldDecls, 2);
+
+ SuperCTy = Ctx.getTagDeclType(RD);
+ SuperPtrCTy = Ctx.getPointerType(SuperCTy);
+
+ SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
// Global metadata structures
Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=55560&r1=55559&r2=55560&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Fri Aug 29 22:02:31 2008
@@ -43,6 +43,8 @@
class ObjCProtocolDecl;
class Selector;
+ typedef llvm::SmallVector<std::pair<llvm::Value*, QualType>, 16> CallArgList;
+
namespace CodeGen {
class CodeGenModule;
@@ -81,7 +83,8 @@
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
llvm::Value *Receiver,
- bool IsClassMessage) = 0;
+ bool IsClassMessage,
+ const CallArgList &CallArgs) = 0;
/// Generate an Objective-C message send operation to the super
/// class initiated in a method for Class and with the given Self
@@ -91,7 +94,8 @@
const ObjCMessageExpr *E,
const ObjCInterfaceDecl *Class,
llvm::Value *Self,
- bool IsClassMessage) = 0;
+ bool IsClassMessage,
+ const CallArgList &CallArgs) = 0;
/// Emit the code to return the named protocol as an object, as in a
/// @protocol expression.
@@ -120,7 +124,7 @@
/// return true, otherwise instance variables will be accessed directly from
/// the structure. If this returns true then @defs is invalid for this
/// runtime and a warning should be generated.
- virtual bool LateBoundIVars() { return false; }
+ virtual bool LateBoundIVars() const { return false; }
};
/// Creates an instance of an Objective-C runtime class.
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=55560&r1=55559&r2=55560&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Aug 29 22:02:31 2008
@@ -299,6 +299,12 @@
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
+ typedef llvm::SmallVector<std::pair<llvm::Value*, QualType>, 16> CallArgList;
+ void EmitCallArg(const Expr *E, CallArgList &Args);
+ RValue EmitCall(llvm::Value *Callee,
+ QualType ResultType,
+ const CallArgList &Args);
+
RValue EmitCallExpr(const CallExpr *E);
RValue EmitCallExpr(Expr *FnExpr, CallExpr::const_arg_iterator ArgBeg,
@@ -308,13 +314,6 @@
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd);
- RValue EmitCallExprExt(llvm::Value *Callee,
- QualType ResultType,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd,
- llvm::Value **ExtraArgs,
- unsigned NumExtraArgs);
-
RValue EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
More information about the cfe-commits
mailing list