summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-08-30 05:35:15 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-08-30 05:35:15 +0000
commit4b8c6db92792e8eab93f79d46e56b443bc882cbb (patch)
treee50212f2bc5f55a2b790f5746662494f79c2f72b
parentc722b8565c733b315f079d6e8db7f58e92917049 (diff)
downloadbcm5719-llvm-4b8c6db92792e8eab93f79d46e56b443bc882cbb.tar.gz
bcm5719-llvm-4b8c6db92792e8eab93f79d46e56b443bc882cbb.zip
Add Objective-C property setter support.
- Change Obj-C runtime message API, drop the ObjCMessageExpr arg in favor of just result type and selector. Necessary so it can be reused in situations where we don't want to cons up an ObjCMessageExpr. - Update aggregate binary assignment to know about special property ref lvalues. - Add CodeGenFunction::EmitCallArg overload which takes an already emitted rvalue. Add CodeGenFunction::StoreComplexIntoAddr. Disabled logic in Sema for parsing Objective-C dot-syntax that accesses methods. This code does not search in the correct order and the AST node has no way of properly representing its results. Updated StmtDumper to print a bit more information about ObjCPropertyRefExprs. llvm-svn: 55561
-rw-r--r--clang/lib/AST/StmtDumper.cpp13
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp18
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp28
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp7
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp34
-rw-r--r--clang/lib/CodeGen/CGObjCGNU.cpp24
-rw-r--r--clang/lib/CodeGen/CGObjCMac.cpp30
-rw-r--r--clang/lib/CodeGen/CGObjCRuntime.h6
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h18
-rw-r--r--clang/lib/Sema/SemaExpr.cpp7
10 files changed, 139 insertions, 46 deletions
diff --git a/clang/lib/AST/StmtDumper.cpp b/clang/lib/AST/StmtDumper.cpp
index 0ccf2017542..af19b61cd64 100644
--- a/clang/lib/AST/StmtDumper.cpp
+++ b/clang/lib/AST/StmtDumper.cpp
@@ -136,6 +136,7 @@ namespace {
void VisitObjCMessageExpr(ObjCMessageExpr* Node);
void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+ void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
};
}
@@ -449,6 +450,18 @@ void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *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
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index c8aa26155e2..e1893493b06 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -830,6 +830,24 @@ RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType,
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;
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index d335ea9c3fb..11eb9fc1157 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -264,14 +264,26 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
&& "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) {
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 3e1f695c79e..abd0ca8527e 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -546,6 +546,13 @@ void CodeGenFunction::EmitComplexExprIntoAddr(const Expr *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) {
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 2a808f8e059..79b50114b77 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -86,13 +86,15 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
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
@@ -234,20 +236,28 @@ RValue CodeGenFunction::EmitObjCPropertyGet(const ObjCPropertyRefExpr *E) {
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() {}
diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp
index e5a5d053314..4565fbfeb0e 100644
--- a/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -96,13 +96,15 @@ public:
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,
@@ -239,16 +241,17 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) {
///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);
@@ -282,18 +285,19 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
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;
@@ -328,7 +332,7 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
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
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 3b4309d8941..ef4196e11fc 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -219,7 +219,8 @@ private:
const ObjCInterfaceDecl *ID);
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
llvm::Value *Arg0,
QualType Arg0Ty,
bool IsSuper,
@@ -337,14 +338,16 @@ public:
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,
@@ -428,7 +431,8 @@ llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) {
/// 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,
@@ -460,34 +464,35 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
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());
@@ -496,10 +501,9 @@ CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
// 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,
diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h
index 54591a331c6..c0044e9a94d 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.h
+++ b/clang/lib/CodeGen/CGObjCRuntime.h
@@ -81,7 +81,8 @@ public:
/// 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;
@@ -91,7 +92,8 @@ public:
/// object.
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- const ObjCMessageExpr *E,
+ QualType ResultType,
+ Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Self,
bool IsClassMessage,
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index e00c66552f6..c8421e609a5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -299,8 +299,22 @@ public:
// 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);
@@ -366,6 +380,10 @@ public:
/// 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);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 5169ce13111..ba13e7fe66c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -869,7 +869,11 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
// 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);
@@ -886,6 +890,7 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
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 {}
OpenPOWER on IntegriCloud