aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGObjCMac.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-10-29 22:36:39 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-10-29 22:36:39 +0000
commit0c0e7a65214d0b4af68336d6d2fdce525695146a (patch)
tree5bc1b3bb8073bd45c73ab9b0b26f62a571abef46 /lib/CodeGen/CGObjCMac.cpp
parentfdc0372eda30952b03f3fd4269dbc4b2acfdfa55 (diff)
NeXT: Emit protocol objects lazily.
- That is, the metadata for a protocol is only emitted if that protocol is actually used in the translation unit. This is important because Objective-C headers frequently contain a large number of protocol definitions, only a few of which will be used in any given file. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58400 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r--lib/CodeGen/CGObjCMac.cpp97
1 files changed, 76 insertions, 21 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index b993a91bf9..d5a21bb769 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -21,6 +21,7 @@
#include "clang/Basic/LangOptions.h"
#include "llvm/Module.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Target/TargetData.h"
#include <sstream>
@@ -219,6 +220,10 @@ private:
/// empty structure whose initializer is filled in when/if defined.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
+ /// DefinedProtocols - Protocols which have actually been
+ /// defined. We should not need this, see FIXME in GenerateProtocol.
+ llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
+
/// DefinedClasses - List of defined classes.
std::vector<llvm::GlobalValue*> DefinedClasses;
@@ -316,6 +321,17 @@ private:
ObjCPropertyDecl * const *begin,
ObjCPropertyDecl * const *end);
+ /// GetOrEmitProtocol - Get the protocol object for the given
+ /// declaration, emitting it if necessary. The return value has type
+ /// ProtocolPtrTy.
+ llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
+
+ /// GetOrEmitProtocolRef - Get a forward reference to the protocol
+ /// object for the given declaration, emitting it if needed. These
+ /// forward references will be filled in with empty bodies if no
+ /// definition is seen. The return value has type ProtocolPtrTy.
+ llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
+
/// EmitProtocolExtension - Generate the protocol extension
/// structure used to store optional instance and class methods, and
/// protocol properties. The return value has type
@@ -337,8 +353,8 @@ private:
/// GetProtocolRef - Return a reference to the internal protocol
/// description, creating an empty one if it has not been
- /// defined. The return value has type pointer-to ProtocolTy.
- llvm::GlobalVariable *GetProtocolRef(const ObjCProtocolDecl *PD);
+ /// defined. The return value has type ProtocolPtrTy.
+ llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
/// GetClassName - Return a unique constant for the given selector's
/// name. The return value has type char *.
@@ -506,7 +522,7 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
// and ObjCTypes types.
const llvm::Type *ClassTy =
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
- Target = CGF.Builder.CreateBitCast(Target, ClassTy);
+ Target = CGF.Builder.CreateBitCast(Target, ClassTy);
CGF.Builder.CreateStore(Target,
CGF.Builder.CreateStructGEP(ObjCSuper, 1));
@@ -572,6 +588,25 @@ llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
ObjCTypes.ExternalProtocolPtrTy);
}
+void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
+ // FIXME: We shouldn't need this, the protocol decl should contain
+ // enough information to tell us whether this was a declaration or a
+ // definition.
+ DefinedProtocols.insert(PD->getIdentifier());
+
+ // If we have generated a forward reference to this protocol, emit
+ // it now. Otherwise do nothing, the protocol objects are lazily
+ // emitted.
+ if (Protocols.count(PD->getIdentifier()))
+ GetOrEmitProtocol(PD);
+}
+
+llvm::Constant *CGObjCMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
+ if (DefinedProtocols.count(PD->getIdentifier()))
+ return GetOrEmitProtocol(PD);
+ return GetOrEmitProtocolRef(PD);
+}
+
/*
// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
struct _objc_protocol {
@@ -584,7 +619,13 @@ llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
See EmitProtocolExtension().
*/
-void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
+llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
+ llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
+
+ // Early exit if a defining object has already been generated.
+ if (Entry && Entry->hasInitializer())
+ return Entry;
+
// FIXME: I don't understand why gcc generates this, or where it is
// resolved. Investigate. Its also wasteful to look this up over and
// over.
@@ -637,9 +678,9 @@ void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Values);
- llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
if (Entry) {
- // Already created, just update the initializer
+ // Already created, fix the linkage and update the initializer.
+ Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Entry->setInitializer(Init);
} else {
Entry =
@@ -653,25 +694,21 @@ void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
// FIXME: Is this necessary? Why only for protocol?
Entry->setAlignment(4);
}
+
+ return Entry;
}
-llvm::GlobalVariable *CGObjCMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
+llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
if (!Entry) {
- std::vector<llvm::Constant*> Values(5);
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
- Values[1] = GetClassName(PD->getIdentifier());
- Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
- Values[3] = Values[4] =
- llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
- Values);
-
+ // We use the initializer as a marker of whether this is a forward
+ // reference or not. At module finalization we add the empty
+ // contents for protocols which were referenced but never defined.
Entry =
new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
- llvm::GlobalValue::InternalLinkage,
- Init,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
std::string("\01L_OBJC_PROTOCOL_")+PD->getName(),
&CGM.getModule());
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
@@ -1510,7 +1547,8 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
// Allocate memory for the exception data and rethrow pointer.
llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
"exceptiondata.ptr");
- llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy, "_rethrow");
+ llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
+ "_rethrow");
// Enter a new try block and call setjmp.
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
@@ -1988,8 +2026,25 @@ void CGObjCMac::GetNameForMethod(const ObjCMethodDecl *D,
void CGObjCMac::FinishModule() {
EmitModuleInfo();
- std::vector<llvm::Constant*> Used;
+ // Emit the dummy bodies for any protocols which were referenced but
+ // never defined.
+ for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
+ i = Protocols.begin(), e = Protocols.end(); i != e; ++i) {
+ if (i->second->hasInitializer())
+ continue;
+ std::vector<llvm::Constant*> Values(5);
+ Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
+ Values[1] = GetClassName(i->first);
+ Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
+ Values[3] = Values[4] =
+ llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
+ i->second->setLinkage(llvm::GlobalValue::InternalLinkage);
+ i->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
+ Values));
+ }
+
+ std::vector<llvm::Constant*> Used;
for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(),
e = UsedGlobals.end(); i != e; ++i) {
Used.push_back(llvm::ConstantExpr::getBitCast(*i, ObjCTypes.Int8PtrTy));
@@ -2086,7 +2141,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
ProtocolExtensionTy);
ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
- // Handle recursive construction of Protocl and ProtocolList types
+ // Handle recursive construction of Protocol and ProtocolList types
llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get();
llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();