[cfe-commits] r55307 - in /cfe/trunk/lib/CodeGen: CGObjC.cpp CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h
Daniel Dunbar
daniel at zuster.org
Mon Aug 25 01:19:25 PDT 2008
Author: ddunbar
Date: Mon Aug 25 03:19:24 2008
New Revision: 55307
URL: http://llvm.org/viewvc/llvm-project?rev=55307&view=rev
Log:
Fix Obj-C super sends inside class methods.
- NeXT loads the super class at runtime; this required changing the
runtime interface to pass more information down.
Modified:
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CGObjCRuntime.h
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=55307&r1=55306&r2=55307&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Aug 25 03:19:24 2008
@@ -50,6 +50,7 @@
CGObjCRuntime &Runtime = CGM.getObjCRuntime();
const Expr *ReceiverExpr = E->getReceiver();
bool isSuperMessage = false;
+ bool isClassMessage = false;
// Find the receiver
llvm::Value *Receiver;
if (!ReceiverExpr) {
@@ -60,11 +61,13 @@
if (!OID) {
assert(!strcmp(E->getClassName()->getName(), "super") &&
"Unexpected missing class interface in message send.");
- OID = E->getMethodDecl()->getClassInterface();
isSuperMessage = true;
+ Receiver = LoadObjCSelf();
+ } else {
+ Receiver = Runtime.GetClass(Builder, OID);
}
-
- Receiver = Runtime.GetClass(Builder, OID);
+
+ isClassMessage = true;
} else if (const PredefinedExpr *PDE =
dyn_cast<PredefinedExpr>(E->getReceiver())) {
assert(PDE->getIdentType() == PredefinedExpr::ObjCSuper);
@@ -78,10 +81,11 @@
// super is only valid in an Objective-C method
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
return Runtime.GenerateMessageSendSuper(*this, E,
- OMD->getClassInterface()->getSuperClass(),
- Receiver);
+ OMD->getClassInterface(),
+ Receiver,
+ isClassMessage);
}
- return Runtime.GenerateMessageSend(*this, E, Receiver);
+ return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage);
}
/// Generate an Objective-C method. An Objective-C method is a C function with
Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=55307&r1=55306&r2=55307&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Mon Aug 25 03:19:24 2008
@@ -97,12 +97,14 @@
virtual CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- llvm::Value *Receiver);
+ llvm::Value *Receiver,
+ bool IsClassMessage);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- const ObjCInterfaceDecl *Super,
- llvm::Value *Receiver);
+ const ObjCInterfaceDecl *Class,
+ llvm::Value *Receiver,
+ bool IsClassMessage);
virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
const ObjCInterfaceDecl *OID);
virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
@@ -236,8 +238,10 @@
CodeGen::RValue
CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver) {
+ const ObjCInterfaceDecl *Class,
+ llvm::Value *Receiver,
+ bool IsClassMessage) {
+ const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
// TODO: This should be cached, not looked up every time.
llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
@@ -280,7 +284,8 @@
CodeGen::RValue
CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- llvm::Value *Receiver) {
+ llvm::Value *Receiver,
+ bool IsClassMessage) {
const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=55307&r1=55306&r2=55307&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon Aug 25 03:19:24 2008
@@ -220,9 +220,14 @@
llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
bool ForClass,
const llvm::Type *InterfaceTy);
-
+
+ /// EmitMetaClass - Emit a forward reference to the class structure
+ /// for the metaclass of the given interface. The return value has
+ /// type ClassPtrTy.
+ llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
+
/// EmitMetaClass - Emit a class structure for the metaclass of the
- /// given implementation. return value has type ClassPtrTy.
+ /// given implementation. The return value has type ClassPtrTy.
llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
llvm::Constant *Protocols,
const llvm::Type *InterfaceTy);
@@ -316,13 +321,15 @@
virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- llvm::Value *Receiver);
+ llvm::Value *Receiver,
+ bool IsClassMessage);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver);
+ const ObjCInterfaceDecl *Class,
+ llvm::Value *Receiver,
+ bool IsClassMessage);
virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
const ObjCInterfaceDecl *ID);
@@ -403,12 +410,9 @@
CodeGen::RValue
CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver) {
- // FIXME: This should be cached, not looked up every time. Meh. We
- // should just make sure the optimizer hits it.
- llvm::Value *ReceiverClass = EmitClassRef(CGF.Builder, SuperClass);
-
+ const ObjCInterfaceDecl *Class,
+ llvm::Value *Receiver,
+ bool IsClassMessage) {
// Create and init a super structure; this is a (receiver, class)
// pair we will pass to objc_msgSendSuper.
llvm::Value *ObjCSuper =
@@ -417,16 +421,28 @@
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
CGF.Builder.CreateStore(ReceiverAsObject,
CGF.Builder.CreateStructGEP(ObjCSuper, 0));
- CGF.Builder.CreateStore(ReceiverClass,
- CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+ // If this is a class message the metaclass is passed as the target.
+ llvm::Value *Target;
+ if (IsClassMessage) {
+ llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
+ llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
+ llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
+ Target = Super;
+ } else {
+ Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
+ }
+ CGF.Builder.CreateStore(Target,
+ CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+
return EmitMessageSend(CGF, E, ObjCSuper, true);
}
/// Generate code for a message send expression.
CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- llvm::Value *Receiver) {
+ llvm::Value *Receiver,
+ bool IsClassMessage) {
llvm::Value *Arg0 =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
return EmitMessageSend(CGF, E, Arg0, false);
@@ -972,12 +988,22 @@
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Values);
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- std::string("\01L_OBJC_METACLASS_")+ClassName,
- &CGM.getModule());
+ std::string Name("\01L_OBJC_METACLASS_");
+ Name += ClassName;
+
+ // Check for a forward reference.
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward metaclass reference has incorrect type.");
+ GV->setLinkage(llvm::GlobalValue::InternalLinkage);
+ GV->setInitializer(Init);
+ } else {
+ GV = new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
+ llvm::GlobalValue::InternalLinkage,
+ Init, Name,
+ &CGM.getModule());
+ }
GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
UsedGlobals.push_back(GV);
// FIXME: Why?
@@ -986,6 +1012,31 @@
return GV;
}
+llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
+ std::string Name("\01L_OBJC_METACLASS_");
+ Name += ID->getName();
+
+ // FIXME: Should we look these up somewhere other than the
+ // module. Its a bit silly since we only generate these while
+ // processing an implementation, so exactly one pointer would work
+ // if know when we entered/exitted an implementation block.
+
+ // Check for an existing forward reference.
+ if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name)) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward metaclass reference has incorrect type.");
+ return GV;
+ } else {
+ // Generate as an external reference to keep a consistent
+ // module. This will be patched up when we emit the metaclass.
+ return new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ Name,
+ &CGM.getModule());
+ }
+}
+
/*
struct objc_class_ext {
uint32_t size;
Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=55307&r1=55306&r2=55307&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Mon Aug 25 03:19:24 2008
@@ -80,15 +80,18 @@
virtual CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- llvm::Value *Receiver) = 0;
+ llvm::Value *Receiver,
+ bool IsClassMessage) = 0;
/// Generate an Objective-C message send operation to the super
- /// class.
+ /// class initiated in a method for Class and with the given Self
+ /// object.
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMessageExpr *E,
- const ObjCInterfaceDecl *SuperClass,
- llvm::Value *Receiver) = 0;
+ const ObjCInterfaceDecl *Class,
+ llvm::Value *Self,
+ bool IsClassMessage) = 0;
/// Emit the code to return the named protocol as an object, as in a
/// @protocol expression.
More information about the cfe-commits
mailing list