summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp21
-rw-r--r--clang/lib/CodeGen/CGObjCGNU.cpp18
-rw-r--r--clang/lib/CodeGen/CGObjCMac.cpp44
-rw-r--r--clang/lib/CodeGen/CGObjCRuntime.h23
4 files changed, 58 insertions, 48 deletions
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index df3226d128a..54b4e19c572 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -48,13 +48,18 @@ llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
// Find the receiver
llvm::Value *Receiver;
if (!ReceiverExpr) {
- const char * classname = E->getClassName()->getName();
- if (!strcmp(classname, "super")) {
- classname = E->getMethodDecl()->getClassInterface()->getName();
+ const ObjCInterfaceDecl *OID = E->getClassInfo().first;
+
+ // Very special case, super send in class method. The receiver is
+ // self (the class object) and the send uses super semantics.
+ if (!OID) {
+ assert(!strcmp(E->getClassName()->getName(), "super") &&
+ "Unexpected missing class interface in message send.");
+ OID = E->getMethodDecl()->getClassInterface();
+ isSuperMessage = true;
}
- llvm::Value *ClassName = CGM.GetAddrOfConstantCString(classname);
- ClassName = Builder.CreateStructGEP(ClassName, 0);
- Receiver = Runtime.LookupClass(Builder, ClassName);
+
+ Receiver = Runtime.GetClass(Builder, OID);
} else if (const PredefinedExpr *PDE =
dyn_cast<PredefinedExpr>(E->getReceiver())) {
assert(PDE->getIdentType() == PredefinedExpr::ObjCSuper);
@@ -88,10 +93,8 @@ llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
if (isSuperMessage) {
// super is only valid in an Objective-C method
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
- const char *SuperClass =
- OMD->getClassInterface()->getSuperClass()->getName();
return Runtime.GenerateMessageSendSuper(Builder, ConvertType(E->getType()),
- SuperClass,
+ OMD->getClassInterface()->getSuperClass(),
Receiver, E->getSelector(),
&Args[0], Args.size());
}
diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp
index 4c678c9f8fb..7257f8d5691 100644
--- a/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -101,13 +101,13 @@ public:
unsigned ArgC);
virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
const llvm::Type *ReturnTy,
- const char *SuperClassName,
+ const ObjCInterfaceDecl *SuperClass,
llvm::Value *Receiver,
Selector Sel,
llvm::Value** ArgV,
unsigned ArgC);
- virtual llvm::Value *LookupClass(llvm::IRBuilder<> &Builder,
- llvm::Value *ClassName);
+ virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
+ const ObjCInterfaceDecl *OID);
virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD);
@@ -170,8 +170,11 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
}
// This has to perform the lookup every time, since posing and related
// techniques can modify the name -> class mapping.
-llvm::Value *CGObjCGNU::LookupClass(llvm::IRBuilder<> &Builder,
- llvm::Value *ClassName) {
+llvm::Value *CGObjCGNU::GetClass(llvm::IRBuilder<> &Builder,
+ const ObjCInterfaceDecl *OID) {
+ llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getName());
+ ClassName = Builder.CreateStructGEP(ClassName, 0);
+
llvm::Constant *ClassLookupFn =
TheModule.getOrInsertFunction("objc_lookup_class", IdTy, PtrToInt8Ty,
NULL);
@@ -235,14 +238,13 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) {
///should be called.
llvm::Value *CGObjCGNU::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
const llvm::Type *ReturnTy,
- const char *SuperClassName,
+ const ObjCInterfaceDecl *SuperClass,
llvm::Value *Receiver,
Selector Sel,
llvm::Value** ArgV,
unsigned ArgC) {
// TODO: This should be cached, not looked up every time.
- llvm::Value *ReceiverClass = LookupClass(Builder,
- MakeConstantString(SuperClassName));
+ llvm::Value *ReceiverClass = GetClass(Builder, SuperClass);
llvm::Value *cmd = GetSelector(Builder, Sel);
std::vector<const llvm::Type*> impArgTypes;
impArgTypes.push_back(Receiver->getType());
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index b307148955d..61b9534759a 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -205,16 +205,17 @@ public:
llvm::Value** ArgV,
unsigned ArgC);
- virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
- const llvm::Type *ReturnTy,
- const char *SuperClassName,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC);
-
- virtual llvm::Value *LookupClass(llvm::IRBuilder<> &Builder,
- llvm::Value *ClassName);
+ 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 llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
+ const ObjCInterfaceDecl *SuperClass);
virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
@@ -260,10 +261,10 @@ CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm)
EmitImageInfo();
}
-// This has to perform the lookup every time, since posing and related
-// techniques can modify the name -> class mapping.
-llvm::Value *CGObjCMac::LookupClass(llvm::IRBuilder<> &Builder,
- llvm::Value *ClassName) {
+/// GetClass - Return a reference to the class for the given interface
+/// decl.
+llvm::Value *CGObjCMac::GetClass(llvm::IRBuilder<> &Builder,
+ const ObjCInterfaceDecl *OID) {
assert(0 && "Cannot lookup classes on Mac runtime.");
return 0;
}
@@ -323,13 +324,14 @@ llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) {
/// 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,
- const char *SuperClassName,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) {
+llvm::Value *
+CGObjCMac::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
+ const llvm::Type *ReturnTy,
+ const ObjCInterfaceDecl *SuperClass,
+ llvm::Value *Receiver,
+ Selector Sel,
+ llvm::Value** ArgV,
+ unsigned ArgC) {
assert(0 && "Cannot generate message send to super for Mac runtime.");
return 0;
}
diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h
index 83ca0e638c9..368e5ae1059 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.h
+++ b/clang/lib/CodeGen/CGObjCRuntime.h
@@ -31,6 +31,7 @@ namespace llvm {
namespace clang {
class ObjCCategoryImplDecl;
class ObjCImplementationDecl;
+ class ObjCInterfaceDecl;
class ObjCMethodDecl;
class ObjCProtocolDecl;
class Selector;
@@ -78,13 +79,14 @@ public:
/// Generate an Objective-C message send operation to the super
/// class.
- virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<true> &Builder,
- const llvm::Type *ReturnTy,
- const char *SuperClassName,
- llvm::Value *Receiver,
- Selector Sel,
- llvm::Value** ArgV,
- unsigned ArgC) = 0;
+ 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;
/// Emit the code to return the named protocol as an object, as in a
/// @protocol expression.
@@ -104,9 +106,10 @@ public:
// parameters are passed.
virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD) = 0;
- /// Look up the class for the specified name
- virtual llvm::Value *LookupClass(BuilderType &Builder,
- llvm::Value *ClassName) = 0;
+ /// GetClass - Return a reference to the class for the given
+ /// interface decl.
+ virtual llvm::Value *GetClass(BuilderType &Builder,
+ const ObjCInterfaceDecl *OID) = 0;
/// If instance variable addresses are determined at runtime then this should
/// return true, otherwise instance variables will be accessed directly from
OpenPOWER on IntegriCloud