void VisitObjCMessageExpr(ObjCMessageExpr* Node);
void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+ void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
};
}
fprintf(F, " ");
fprintf(F, "%s", Node->getProtocol()->getName());
}
+
+void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+ DumpExpr(Node);
+
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Node->getDecl())) {
+ fprintf(F, " MethodDecl=\"%s\"", MD->getSelector().getName().c_str());
+ } else {
+ ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(Node->getDecl());
+ fprintf(F, " PropertyDecl=\"%s\"", PD->getName());
+ }
+}
+
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//
return EmitCall(Callee, ResultType, Args);
}
+// FIXME: Merge the following two functions.
+void CodeGenFunction::EmitCallArg(RValue RV, QualType Ty,
+ CallArgList &Args) {
+ llvm::Value *ArgValue;
+
+ if (RV.isScalar()) {
+ ArgValue = RV.getScalarVal();
+ } else if (RV.isComplex()) {
+ // Make a temporary alloca to pass the argument.
+ ArgValue = CreateTempAlloca(ConvertType(Ty));
+ StoreComplexToAddr(RV.getComplexVal(), ArgValue, false);
+ } else {
+ ArgValue = RV.getAggregateAddr();
+ }
+
+ Args.push_back(std::make_pair(ArgValue, Ty));
+}
+
void CodeGenFunction::EmitCallArg(const Expr *E, CallArgList &Args) {
QualType ArgTy = E->getType();
llvm::Value *ArgValue;
&& "Invalid assignment");
LValue LHS = CGF.EmitLValue(E->getLHS());
- // Codegen the RHS so that it stores directly into the LHS.
- CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
-
- if (DestPtr == 0)
- return;
-
- // If the result of the assignment is used, copy the RHS there also.
- EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType());
+ // We have to special case property setters, otherwise we must have
+ // a simple lvalue (no aggregates inside vectors, bitfields).
+ if (LHS.isPropertyRef()) {
+ // FIXME: Volatility?
+ llvm::Value *AggLoc = DestPtr;
+ if (!AggLoc)
+ AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType()));
+ CGF.EmitAggExpr(E->getRHS(), AggLoc, false);
+ CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(),
+ RValue::getAggregate(AggLoc));
+ } else {
+ // Codegen the RHS so that it stores directly into the LHS.
+ CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
+
+ if (DestPtr == 0)
+ return;
+
+ // If the result of the assignment is used, copy the RHS there also.
+ EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType());
+ }
}
void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
Emitter.EmitStoreOfComplex(Val, DestAddr, DestIsVolatile);
}
+/// StoreComplexToAddr - Store a complex number into the specified address.
+void CodeGenFunction::StoreComplexToAddr(ComplexPairTy V,
+ llvm::Value *DestAddr,
+ bool DestIsVolatile) {
+ ComplexExprEmitter(*this).EmitStoreOfComplex(V, DestAddr, DestIsVolatile);
+}
+
/// LoadComplexFromAddr - Load a complex number from the specified address.
ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr,
bool SrcIsVolatile) {
if (isSuperMessage) {
// super is only valid in an Objective-C method
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
- return Runtime.GenerateMessageSendSuper(*this, E,
+ return Runtime.GenerateMessageSendSuper(*this, E->getType(),
+ E->getSelector(),
OMD->getClassInterface(),
Receiver,
isClassMessage,
Args);
}
- return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage, Args);
+ return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(),
+ Receiver, isClassMessage, Args);
}
/// StartObjCMethod - Begin emission of an ObjCMethod. This generates
S = cast<ObjCPropertyDecl>(E->getDecl())->getGetterName();
}
- // FIXME: Improve location information.
- SourceLocation Loc = E->getLocation();
- // PropertyRefExprs are always instance messages.
- // FIXME: Is there any reason to try and pass the method here?
- ObjCMessageExpr GetExpr(const_cast<Expr*>(E->getBase()),
- S, E->getType(), 0, Loc, Loc,
- 0, 0);
-
- return EmitObjCMessageExpr(&GetExpr);
+ return CGM.getObjCRuntime().
+ GenerateMessageSend(*this, E->getType(), S,
+ EmitScalarExpr(E->getBase()),
+ false, CallArgList());
}
void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
RValue Src) {
- ErrorUnsupported(E, "Objective-C property setter call");
+ Selector S;
+ if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(E->getDecl())) {
+ S = PD->getSetterName();
+ } else {
+ // FIXME: How can we have a method decl here?
+ ErrorUnsupported(E, "Objective-C property setter call");
+ return;
+ }
+
+ CallArgList Args;
+ EmitCallArg(Src, E->getType(), Args);
+ CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S,
+ EmitScalarExpr(E->getBase()),
+ false, Args);
}
CGObjCRuntime::~CGObjCRuntime() {}
virtual llvm::Constant *GenerateConstantString(const std::string &String);
virtual CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
bool IsClassMessage,
///should be called.
CodeGen::RValue
CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs) {
const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
- const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+ const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
// TODO: This should be cached, not looked up every time.
llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
- llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
+ llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
std::vector<const llvm::Type*> impArgTypes;
impArgTypes.push_back(Receiver->getType());
impArgTypes.push_back(SelectorTy);
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);
+ return CGF.EmitCall(imp, ResultType, ActualArgs);
}
/// Generate code for a message send expression.
CodeGen::RValue
CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs) {
- const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
- llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
+ const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
+ llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
// Look up the method implementation.
std::vector<const llvm::Type*> impArgTypes;
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);
+ return CGF.EmitCall(imp, ResultType, ActualArgs);
}
/// Generates a MethodList. Used in construction of a objc_class and
const ObjCInterfaceDecl *ID);
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Arg0,
QualType Arg0Ty,
bool IsSuper,
virtual llvm::Constant *GenerateConstantString(const std::string &String);
virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
bool IsClassMessage,
/// which class's method should be called.
CodeGen::RValue
CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
bool IsClassMessage,
CGF.Builder.CreateStore(Target,
CGF.Builder.CreateStructGEP(ObjCSuper, 1));
- return EmitMessageSend(CGF, E,
+ return EmitMessageSend(CGF, ResultType, Sel,
ObjCSuper, ObjCTypes.SuperPtrCTy,
true, CallArgs);
}
/// Generate code for a message send expression.
CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs) {
llvm::Value *Arg0 =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
- return EmitMessageSend(CGF, E,
+ return EmitMessageSend(CGF, ResultType, Sel,
Arg0, CGF.getContext().getObjCIdType(),
false, CallArgs);
}
CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Arg0,
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()),
+ ActualArgs.push_back(std::make_pair(EmitSelector(CGF.Builder, Sel),
CGF.getContext().getObjCSelType()));
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
// parameter and set the structure return flag. See
// getMessageSendFn().
- const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+ const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
return CGF.EmitCall(ObjCTypes.getMessageSendFn(IsSuper, ReturnTy),
- E->getType(),
- ActualArgs);
+ ResultType, ActualArgs);
}
llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
/// Generate an Objective-C message send operation.
virtual CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs) = 0;
/// object.
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Self,
bool IsClassMessage,
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
+ /// CallArgList - Type for representing both the value and type of
+ /// arguments in a call.
typedef llvm::SmallVector<std::pair<llvm::Value*, QualType>, 16> CallArgList;
+
+ /// EmitCallArg - Emit the given expression and append the result
+ /// onto the given Args list.
void EmitCallArg(const Expr *E, CallArgList &Args);
+
+ /// EmitCallArg - Append the appropriate call argument for the given
+ /// rvalue and type onto the Args list.
+ void EmitCallArg(RValue RV, QualType Ty, CallArgList &Args);
+
+ /// EmitCall - Generate a call of the given function, expecting the
+ /// given result type, and using the given argument list which
+ /// specifies both the LLVM arguments and the types they were
+ /// derived from.
RValue EmitCall(llvm::Value *Callee,
QualType ResultType,
const CallArgList &Args);
/// of complex type, storing into the specified Value*.
void EmitComplexExprIntoAddr(const Expr *E, llvm::Value *DestAddr,
bool DestIsVolatile);
+
+ /// StoreComplexToAddr - Store a complex number into the specified address.
+ void StoreComplexToAddr(ComplexPairTy V, llvm::Value *DestAddr,
+ bool DestIsVolatile);
/// LoadComplexFromAddr - Load a complex number from the specified address.
ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile);
// FIXME: The logic for looking up nullary and unary selectors should be
// shared with the code in ActOnInstanceMessage.
-
+
+ // FIXME: This logic is not correct, we should search for
+ // properties first. Additionally, the AST node doesn't currently
+ // have enough information to store the setter argument.
+#if 0
// Before we look for explicit property declarations, we check for
// nullary methods (which allow '.' notation).
Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
return new ObjCPropertyRefExpr(MD, MD->getResultType(),
MemberLoc, BaseExpr);
}
+#endif
// FIXME: Need to deal with setter methods that take 1 argument. E.g.:
// @interface NSBundle : NSObject {}