[cfe-commits] r63326 - /cfe/trunk/lib/CodeGen/CGObjCMac.cpp
Fariborz Jahanian
fjahanian at apple.com
Thu Jan 29 11:24:31 PST 2009
Author: fjahanian
Date: Thu Jan 29 13:24:30 2009
New Revision: 63326
URL: http://llvm.org/viewvc/llvm-project?rev=63326&view=rev
Log:
Protocol meta-data for objc2's non-fragile abi.
Lot more to do in this area.
Modified:
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=63326&r1=63325&r2=63326&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Thu Jan 29 13:24:30 2009
@@ -358,6 +358,11 @@
const ObjCContainerDecl *OCD,
const ObjCCommonTypesHelper &ObjCTypes);
+ /// GetProtocolRef - Return a reference to the internal protocol
+ /// description, creating an empty one if it has not been
+ /// defined. The return value has type ProtocolPtrTy.
+ llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
+
public:
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
{ }
@@ -366,6 +371,19 @@
virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD=0);
+
+ virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
+
+ /// GetOrEmitProtocol - Get the protocol object for the given
+ /// declaration, emitting it if necessary. The return value has type
+ /// ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
+
+ /// 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.
+ virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
};
class CGObjCMac : public CGObjCCommonMac {
@@ -453,13 +471,13 @@
/// 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);
+ virtual 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);
+ virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
/// EmitProtocolExtension - Generate the protocol extension
/// structure used to store optional instance and class methods, and
@@ -480,12 +498,7 @@
/// for the given selector.
llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
- /// GetProtocolRef - Return a reference to the internal protocol
- /// description, creating an empty one if it has not been
- /// defined. The return value has type ProtocolPtrTy.
- llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
-
-public:
+ public:
CGObjCMac(CodeGen::CodeGenModule &cgm);
virtual llvm::Function *ModuleInitFunction();
@@ -517,9 +530,7 @@
virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD);
-
- virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
-
+
virtual llvm::Function *GetPropertyGetFunction();
virtual llvm::Function *GetPropertySetFunction();
virtual llvm::Function *EnumerationMutationFunction();
@@ -577,6 +588,23 @@
const ObjCIvarDecl *Ivar,
unsigned long int offset);
+ /// GetOrEmitProtocol - Get the protocol object for the given
+ /// declaration, emitting it if necessary. The return value has type
+ /// ProtocolPtrTy.
+ virtual 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.
+ virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
+
+ /// EmitProtocolList - Generate the list of referenced
+ /// protocols. The return value has type ProtocolListPtrTy.
+ llvm::Constant *EmitProtocolList(const std::string &Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end);
+
public:
CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
// FIXME. All stubs for now!
@@ -613,8 +641,6 @@
const ObjCProtocolDecl *PD)
{ return 0; }
- virtual void GenerateProtocol(const ObjCProtocolDecl *PD){ return; }
-
virtual llvm::Function *GetPropertyGetFunction(){ return 0; }
virtual llvm::Function *GetPropertySetFunction()
{ return 0; }
@@ -795,7 +821,7 @@
ObjCTypes.ExternalProtocolPtrTy);
}
-void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
+void CGObjCCommonMac::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.
@@ -808,7 +834,7 @@
GetOrEmitProtocol(PD);
}
-llvm::Constant *CGObjCMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
+llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
if (DefinedProtocols.count(PD->getIdentifier()))
return GetOrEmitProtocol(PD);
return GetOrEmitProtocolRef(PD);
@@ -2984,7 +3010,7 @@
CGM.getModule().addTypeName("struct._protocol_t",
ProtocolnfABITy);
- // struct _objc_protocol_list {
+ // struct _protocol_list_t {
// long protocol_count; // Note, this is 32/64 bit
// struct _protocol_t[protocol_count];
// }
@@ -3153,7 +3179,7 @@
/// const uint8_t * const ivarLayout;
/// const char *const name;
/// const struct _method_list_t * const baseMethods;
-/// const struct _objc_protocol_list *const baseProtocols;
+/// const struct _protocol_list_t *const baseProtocols;
/// const struct _ivar_list_t *const ivars;
/// const uint8_t * const weakIvarLayout;
/// const struct _prop_list_t * const properties;
@@ -3170,6 +3196,7 @@
Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
// FIXME. For 64bit targets add 0 here.
+ // FIXME. ivarLayout is currently null!
Values[ 3] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Values[ 4] = GetClassName(ID->getIdentifier());
// const struct _method_list_t * const baseMethods;
@@ -3205,14 +3232,21 @@
}
}
}
- // FIXME. Section may always be .data
Values[ 5] = EmitMethodList(MethodListName,
"__DATA, __objc_const", Methods);
- Values[ 6] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
+
+ const ObjCInterfaceDecl *OID = ID->getClassInterface();
+ assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
+ Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
+ + OID->getNameAsString(),
+ OID->protocol_begin(),
+ OID->protocol_end());
+
if (flags & CLS_META)
Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
else
Values[ 7] = EmitIvarList(ID);
+ // FIXME. weakIvarLayout is currently null.
Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
if (flags & CLS_META)
Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
@@ -3485,7 +3519,11 @@
Values[3] = EmitMethodList(MethodListName,
"__DATA, __objc_const",
Methods);
- Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
+ Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
+ + Interface->getNameAsString(),
+ Interface->protocol_begin(),
+ Interface->protocol_end());
+
const ObjCCategoryDecl *Category =
Interface->FindCategoryDeclaration(OCD->getIdentifier());
std::string ExtName(Interface->getNameAsString() + "_$_" +
@@ -3692,7 +3730,181 @@
UsedGlobals.push_back(GV);
return llvm::ConstantExpr::getBitCast(GV,
ObjCTypes.IvarListnfABIPtrTy);
-}
+}
+
+llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
+ const ObjCProtocolDecl *PD) {
+ llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
+
+ if (!Entry) {
+ // 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.ProtocolnfABITy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString(),
+ &CGM.getModule());
+ Entry->setSection("__DATA,__datacoal_nt,coalesced");
+ UsedGlobals.push_back(Entry);
+ // FIXME: Is this necessary? Why only for protocol?
+ Entry->setAlignment(4);
+ }
+
+ return Entry;
+}
+
+/// GetOrEmitProtocol - Generate the protocol meta-data:
+/// @code
+/// struct _protocol_t {
+/// id isa; // NULL
+/// const char * const protocol_name;
+/// const struct _protocol_list_t * protocol_list; // super protocols
+/// const struct method_list_t * const instance_methods;
+/// const struct method_list_t * const class_methods;
+/// const struct method_list_t *optionalInstanceMethods;
+/// const struct method_list_t *optionalClassMethods;
+/// const struct _prop_list_t * properties;
+/// const uint32_t size; // sizeof(struct _protocol_t)
+/// const uint32_t flags; // = 0
+/// }
+/// @endcode
+///
+
+llvm::Constant *CGObjCNonFragileABIMac::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;
+
+ const char *ProtocolName = PD->getNameAsCString();
+
+ // Construct method lists.
+ std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
+ std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
+ for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(),
+ e = PD->instmeth_end(); i != e; ++i) {
+ ObjCMethodDecl *MD = *i;
+ llvm::Constant *C = GetMethodConstant(MD);
+ if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptInstanceMethods.push_back(C);
+ } else {
+ InstanceMethods.push_back(C);
+ }
+ }
+
+ for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(),
+ e = PD->classmeth_end(); i != e; ++i) {
+ ObjCMethodDecl *MD = *i;
+ llvm::Constant *C = GetMethodConstant(MD);
+ if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptClassMethods.push_back(C);
+ } else {
+ ClassMethods.push_back(C);
+ }
+ }
+
+ std::vector<llvm::Constant*> Values(10);
+ // isa is NULL
+ Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
+ Values[1] = GetClassName(PD->getIdentifier());
+ Values[2] = EmitProtocolList(
+ "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(),
+ PD->protocol_begin(),
+ PD->protocol_end());
+
+ Values[3] = EmitMethodList("\01l_OBJC_$_INSTANCE_METHODS_"
+ + PD->getNameAsString(),
+ "__DATA, __objc_const",
+ InstanceMethods);
+ Values[4] = EmitMethodList("\01l_OBJC_$_CLASS_METHODS_"
+ + PD->getNameAsString(),
+ "__DATA, __objc_const",
+ ClassMethods);
+ Values[5] = EmitMethodList("\01l_OBJC_$_INSTANCE_METHODS_OPT_"
+ + PD->getNameAsString(),
+ "__DATA, __objc_const",
+ OptInstanceMethods);
+ Values[6] = EmitMethodList("\01l_OBJC_$_CLASS_METHODS_OPT_"
+ + PD->getNameAsString(),
+ "__DATA, __objc_const",
+ OptClassMethods);
+ Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(),
+ 0, PD, ObjCTypes);
+ uint32_t Size =
+ CGM.getTargetData().getTypePaddedSize(ObjCTypes.ProtocolnfABITy);
+ Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
+ Values);
+
+ if (Entry) {
+ // Already created, fix the linkage and update the initializer.
+ Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
+ Entry->setInitializer(Init);
+ } else {
+ Entry =
+ new llvm::GlobalVariable(ObjCTypes.ProtocolnfABITy, false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName,
+ &CGM.getModule());
+ Entry->setSection("__DATA,__datacoal_nt,coalesced");
+ // FIXME: Is this necessary? Why only for protocol?
+ Entry->setAlignment(4);
+ }
+ return Entry;
+}
+
+/// EmitProtocolList - Generate protocol list meta-data:
+/// @code
+/// struct _protocol_list_t {
+/// long protocol_count; // Note, this is 32/64 bit
+/// struct _protocol_t[protocol_count];
+/// }
+/// @endcode
+///
+llvm::Constant *
+CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end) {
+ std::vector<llvm::Constant*> ProtocolRefs;
+
+ for (; begin != end; ++begin)
+ ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
+
+ // Just return null for empty protocol lists
+ if (ProtocolRefs.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
+
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
+ if (GV)
+ return GV;
+ // This list is null terminated.
+ ProtocolRefs.push_back(llvm::Constant::getNullValue(
+ ObjCTypes.ProtocolListnfABIPtrTy));
+
+ std::vector<llvm::Constant*> Values(2);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
+ Values[1] =
+ llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolListnfABIPtrTy,
+ ProtocolRefs.size()),
+ ProtocolRefs);
+
+ llvm::Constant *Init = llvm::ConstantStruct::get(Values);
+ GV = new llvm::GlobalVariable(Init->getType(), false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ Name,
+ &CGM.getModule());
+ GV->setSection("__DATA, __objc_const");
+ UsedGlobals.push_back(GV);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
+}
+
/* *** */
CodeGen::CGObjCRuntime *
More information about the cfe-commits
mailing list