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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55560 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 2f0158a..3b4309d 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -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