// type.
FnType = FnType->getAsPointerType()->getPointeeType();
QualType ResultType = FnType->getAsFunctionType()->getResultType();
+ return EmitCallExprExt(Callee, ResultType, ArgBeg, ArgEnd, 0, 0);
+}
+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;
// Handle struct-return functions by passing a pointer to the location that
// FIXME: set the stret attribute on the argument.
}
+ Args.insert(Args.end(), ExtraArgs, ExtraArgs + NumExtraArgs);
+
for (CallExpr::const_arg_iterator I = ArgBeg; I != ArgEnd; ++I) {
QualType ArgTy = I->getType();
if (hasAggregateLLVMType(ResultType))
ParamAttrList.push_back(
llvm::ParamAttrsWithIndex::get(1, llvm::ParamAttr::StructRet));
- unsigned increment = hasAggregateLLVMType(ResultType) ? 2 : 1;
+ unsigned increment = NumExtraArgs + (hasAggregateLLVMType(ResultType) ? 2 : 1);
unsigned i = 0;
for (CallExpr::const_arg_iterator I = ArgBeg; I != ArgEnd; ++I, ++i) {
}
void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
- RValue RV = RValue::getAggregate(CGF.EmitObjCMessageExpr(E));
+ RValue RV = CGF.EmitObjCMessageExpr(E);
+ assert(RV.isAggregate() && "Return value must be aggregate value!");
// If the result is ignored, don't copy from the value.
if (DestPtr == 0)
+ // FIXME: If the source is volatile, we must read from it.
return;
EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
return llvm::ConstantInt::get(EC->getInitVal());
return EmitLoadOfLValue(E);
}
- Value *VisitObjCMessageExpr(ObjCMessageExpr *E);
Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E);
Value *VisitObjCProtocolExpr(ObjCProtocolExpr *E);
Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { return EmitLoadOfLValue(E);}
Value *VisitCallExpr(const CallExpr *E) {
return CGF.EmitCallExpr(E).getScalarVal();
}
-
+
+ Value *VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ return CGF.EmitObjCMessageExpr(E).getScalarVal();
+ }
+
Value *VisitStmtExpr(const StmtExpr *E);
// Unary Operators.
return Builder.CreateShuffleVector(V1, V2, SV, "shuffle");
}
-Value *ScalarExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
- return CGF.EmitObjCMessageExpr(E);
-}
-
Value *ScalarExprEmitter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
return CGF.EmitObjCSelectorExpr(E);
}
}
-llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
+RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
// Only the lookup mechanism and first two arguments of the method
// implementation vary between runtimes. We can get the receiver and
// arguments in generic code.
Receiver = EmitScalarExpr(E->getReceiver());
}
- // Process the arguments
- unsigned ArgC = E->getNumArgs();
- llvm::SmallVector<llvm::Value*, 16> Args;
- for (unsigned i = 0; i != ArgC; ++i) {
- const Expr *ArgExpr = E->getArg(i);
- QualType ArgTy = ArgExpr->getType();
- if (!hasAggregateLLVMType(ArgTy)) {
- // Scalar argument is passed by-value.
- Args.push_back(EmitScalarExpr(ArgExpr));
- } else if (ArgTy->isAnyComplexType()) {
- // Make a temporary alloca to pass the argument.
- llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
- EmitComplexExprIntoAddr(ArgExpr, DestMem, false);
- Args.push_back(DestMem);
- } else {
- llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
- EmitAggExpr(ArgExpr, DestMem, false);
- Args.push_back(DestMem);
- }
- }
-
if (isSuperMessage) {
// super is only valid in an Objective-C method
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
- return Runtime.GenerateMessageSendSuper(Builder, ConvertType(E->getType()),
- OMD->getClassInterface()->getSuperClass(),
- Receiver, E->getSelector(),
- &Args[0], Args.size());
+ return Runtime.GenerateMessageSendSuper(*this, E,
+ OMD->getClassInterface()->getSuperClass(),
+ Receiver);
}
- return Runtime.GenerateMessageSend(Builder, ConvertType(E->getType()),
- Receiver, E->getSelector(),
- &Args[0], Args.size());
+ return Runtime.GenerateMessageSend(*this, E, Receiver);
}
/// Generate an Objective-C method. An Objective-C method is a C function with
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
+#include "CodeGenFunction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
public:
CGObjCGNU(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const std::string &String);
- virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC);
- virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
- const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC);
+ virtual CodeGen::RValue
+ GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ llvm::Value *Receiver);
+ virtual CodeGen::RValue
+ GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ const ObjCInterfaceDecl *Super,
+ llvm::Value *Receiver);
virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
const ObjCInterfaceDecl *OID);
virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
///Generates a message send where the super is the receiver. This is a message
///send to self with special delivery semantics indicating which class's method
///should be called.
-llvm::Value *CGObjCGNU::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
- const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) {
+CodeGen::RValue
+CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ const ObjCInterfaceDecl *SuperClass,
+ llvm::Value *Receiver) {
+ const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
// TODO: This should be cached, not looked up every time.
- llvm::Value *ReceiverClass = GetClass(Builder, SuperClass);
- llvm::Value *cmd = GetSelector(Builder, Sel);
+ llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
+ llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
std::vector<const llvm::Type*> impArgTypes;
impArgTypes.push_back(Receiver->getType());
impArgTypes.push_back(SelectorTy);
// Construct the structure used to look up the IMP
llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(),
IdTy, NULL);
- llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
+ llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy);
// FIXME: volatility
- Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
- Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
+ CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+ CGF.Builder.CreateStore(ReceiverClass, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
// Get the IMP
llvm::Constant *lookupFunction =
llvm::PointerType::getUnqual(ObjCSuperTy),
SelectorTy, NULL);
llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
- llvm::Value *imp = Builder.CreateCall(lookupFunction, lookupArgs,
+ llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs,
lookupArgs+2);
// Call the method
- llvm::SmallVector<llvm::Value*, 8> callArgs;
- callArgs.push_back(Receiver);
- callArgs.push_back(cmd);
- callArgs.insert(callArgs.end(), ArgV, ArgV+ArgC);
- return Builder.CreateCall(imp, callArgs.begin(), callArgs.end());
+ llvm::Value *Args[2];
+ Args[0] = Receiver;
+ Args[1] = cmd;
+ return CGF.EmitCallExprExt(imp, E->getType(), E->arg_begin(), E->arg_end(),
+ Args, 2);
}
/// Generate code for a message send expression.
-llvm::Value *CGObjCGNU::GenerateMessageSend(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) {
- llvm::Value *cmd = GetSelector(Builder, Sel);
+CodeGen::RValue
+CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ llvm::Value *Receiver) {
+ const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+ llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
// Look up the method implementation.
std::vector<const llvm::Type*> impArgTypes;
TheModule.getOrInsertFunction("objc_msg_lookup",
llvm::PointerType::getUnqual(impType),
Receiver->getType(), SelectorTy, NULL);
- llvm::Value *imp = Builder.CreateCall2(lookupFunction, Receiver, cmd);
+ llvm::Value *imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
// Call the method.
- llvm::SmallVector<llvm::Value*, 16> Args;
- if (!ReturnTy->isSingleValueType()) {
- llvm::Value *Return = Builder.CreateAlloca(ReturnTy);
- Args.push_back(Return);
- }
- Args.push_back(Receiver);
- Args.push_back(cmd);
- Args.insert(Args.end(), ArgV, ArgV+ArgC);
- if (!ReturnTy->isSingleValueType()) {
- Builder.CreateCall(imp, Args.begin(), Args.end());
- return Args[0];
- }
- return Builder.CreateCall(imp, Args.begin(), Args.end());
+ llvm::Value *Args[2];
+ Args[0] = Receiver;
+ Args[1] = cmd;
+ return CGF.EmitCallExprExt(imp, E->getType(), E->arg_begin(), E->arg_end(),
+ Args, 2);
}
/// Generates a MethodList. Used in construction of a objc_class and
CGObjCMac(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const std::string &String);
- virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC);
-
- virtual llvm::Value *
- GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
+ virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ llvm::Value *Receiver);
+
+ virtual CodeGen::RValue
+ GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC);
+ llvm::Value *Receiver);
virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
const ObjCInterfaceDecl *ID);
/// Generates a message send where the super is the receiver. This is
/// a message send to self with special delivery semantics indicating
/// which class's method should be called.
-llvm::Value *
-CGObjCMac::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
+CodeGen::RValue
+CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) {
+ llvm::Value *Receiver) {
assert(0 && "Cannot generate message send to super for Mac runtime.");
- return 0;
+ return CodeGen::RValue::get(0);
}
/// Generate code for a message send expression.
-llvm::Value *CGObjCMac::GenerateMessageSend(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) {
+CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ llvm::Value *Receiver) {
+ const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
llvm::Function *F = ObjCTypes.getMessageSendFn();
- llvm::Value **Args = new llvm::Value*[ArgC+2];
- Args[0] = Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
- Args[1] = EmitSelector(Builder, Sel);
- std::copy(ArgV, ArgV+ArgC, Args+2);
+ llvm::Value *Args[2];
+ Args[0] = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
+ Args[1] = EmitSelector(CGF.Builder, E->getSelector());
std::vector<const llvm::Type*> Params;
Params.push_back(ObjCTypes.ObjectPtrTy);
true);
llvm::Type *PCallFTy = llvm::PointerType::getUnqual(CallFTy);
llvm::Constant *C = llvm::ConstantExpr::getBitCast(F, PCallFTy);
- llvm::CallInst *CI = Builder.CreateCall(C,
- Args, Args+ArgC+2, "tmp");
- delete[] Args;
- return Builder.CreateBitCast(CI, ReturnTy, "tmp");
+ return CGF.EmitCallExprExt(C, E->getType(),
+ E->arg_begin(),
+ E->arg_end(),
+ Args, 2);
}
llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
i = OMD->param_begin(), e = OMD->param_end();
i != e; ++i) {
const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
- if (Ty->isFirstClassType()) {
+ if (Ty->isSingleValueType()) {
ArgTys.push_back(Ty);
} else {
ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
Name,
&CGM.getModule());
- if (useStructRet)
+ unsigned Offset = 3; // Return plus self and selector implicit args.
+ if (useStructRet) {
Method->addParamAttr(1, llvm::ParamAttr::StructRet);
+ ++Offset;
+ }
+
+ // FIXME: This is horrible, we need to be reusing the machinery in
+ // CodeGenModule.cpp (SetFunctionAttributes).
+ for (ObjCMethodDecl::param_const_iterator
+ i = OMD->param_begin(), e = OMD->param_end();
+ i != e; ++i, ++Offset) {
+ const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
+ if (!Ty->isSingleValueType())
+ Method->addParamAttr(Offset, llvm::ParamAttr::ByVal);
+ }
return Method;
}
#include "llvm/Support/IRBuilder.h"
#include <string>
+#include "CGValue.h"
+
namespace llvm {
class Constant;
class Type;
}
namespace clang {
+ namespace CodeGen {
+ class CodeGenFunction;
+ }
+
class ObjCCategoryImplDecl;
class ObjCImplementationDecl;
class ObjCInterfaceDecl;
+ class ObjCMessageExpr;
class ObjCMethodDecl;
class ObjCProtocolDecl;
class Selector;
virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0;
/// Generate an Objective-C message send operation.
- virtual llvm::Value *GenerateMessageSend(BuilderType &Builder,
- const llvm::Type *ReturnTy,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) = 0;
+ virtual CodeGen::RValue
+ GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ llvm::Value *Receiver) = 0;
/// Generate an Objective-C message send operation to the super
/// class.
- virtual llvm::Value *
- GenerateMessageSendSuper(llvm::IRBuilder<true> &Builder,
- const llvm::Type *ReturnTy,
- const ObjCInterfaceDecl *SuperClassName,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) = 0;
+ virtual CodeGen::RValue
+ GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ const ObjCMessageExpr *E,
+ const ObjCInterfaceDecl *SuperClass,
+ llvm::Value *Receiver) = 0;
/// Emit the code to return the named protocol as an object, as in a
/// @protocol expression.
#include <vector>
#include <map>
+#include "CGValue.h"
+
namespace llvm {
class BasicBlock;
class Module;
}
-#include "CGValue.h"
-
namespace clang {
class ASTContext;
class Decl;
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);
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E);
- llvm::Value *EmitObjCMessageExpr(const ObjCMessageExpr *E);
+ RValue EmitObjCMessageExpr(const ObjCMessageExpr *E);
//===--------------------------------------------------------------------===//