aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGObjCMac.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-01-24 20:21:50 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-01-24 20:21:50 +0000
commit058a1b7f9d7d3498783f7d24e73235c4ba7ee851 (patch)
tree3d464a20973d585939c48a801fd13cf72bcb09fa /lib/CodeGen/CGObjCMac.cpp
parent31e21e05623ce9d11b1a893fecb87ad349df6c7d (diff)
This patch builds the meta-class object for each
implemented class in objc2's nonfrigile abi. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62929 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r--lib/CodeGen/CGObjCMac.cpp246
1 files changed, 171 insertions, 75 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 1b0027a96b..a7c6aee562 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -344,6 +344,10 @@ protected:
llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
const Decl *Container);
+ /// GetClassName - Return a unique constant for the given selector's
+ /// name. The return value has type char *.
+ llvm::Constant *GetClassName(IdentifierInfo *Ident);
+
public:
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
{ }
@@ -475,10 +479,6 @@ private:
/// 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 *.
- llvm::Constant *GetClassName(IdentifierInfo *Ident);
-
public:
CGObjCMac(CodeGen::CodeGenModule &cgm);
@@ -547,6 +547,16 @@ private:
/// processing a translation unit.
void FinishNonFragileABIModule();
+ llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
+ unsigned InstanceStart,
+ unsigned InstanceSize,
+ const ObjCImplementationDecl *ID);
+ void BuildClassMetaData(std::string &ClassName,
+ llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
+ llvm::Constant *ClassRoGV);
+
+
+
public:
CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
// FIXME. All stubs for now!
@@ -2207,7 +2217,7 @@ llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) {
return Builder.CreateLoad(Entry, false, "tmp");
}
-llvm::Constant *CGObjCMac::GetClassName(IdentifierInfo *Ident) {
+llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
llvm::GlobalVariable *&Entry = ClassNames[Ident];
if (!Entry) {
@@ -2971,12 +2981,14 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul
// uint32 count;
// struct _iver_t list[count];
// }
- IvarListnfABIPtrTy = llvm::StructType::get(IntTy,
- IntTy,
- llvm::ArrayType::get(
- IvarnfABITy, 0),
- NULL);
- CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABIPtrTy);
+ IvarListnfABITy = llvm::StructType::get(IntTy,
+ IntTy,
+ llvm::ArrayType::get(
+ IvarnfABITy, 0),
+ NULL);
+ CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
+
+ IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
// struct _class_ro_t {
// uint32_t const flags;
@@ -3083,6 +3095,101 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
}
+// Metadata flags
+enum MetaDataDlags {
+ CLS = 0x0,
+ CLS_META = 0x1,
+ CLS_ROOT = 0x2,
+ CLS_HIDDEN = 0x10,
+ CLS_EXCEPTION = 0x20
+};
+/// BuildClassRoTInitializer - generate meta-data for:
+/// struct _class_ro_t {
+/// uint32_t const flags;
+/// uint32_t const instanceStart;
+/// uint32_t const instanceSize;
+/// uint32_t const reserved; // only when building for 64bit targets
+/// 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 _ivar_list_t *const ivars;
+/// const uint8_t * const weakIvarLayout;
+/// const struct _prop_list_t * const properties;
+/// }
+///
+llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
+ unsigned flags,
+ unsigned InstanceStart,
+ unsigned InstanceSize,
+ const ObjCImplementationDecl *ID) {
+ std::string ClassName = ID->getNameAsString();
+ std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
+ Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
+ Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
+ Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
+ // FIXME. For 64bit targets add 0 here.
+ Values[ 3] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+ Values[ 4] = GetClassName(ID->getIdentifier());
+ Values[ 5] = llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
+ Values[ 6] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
+ Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
+ Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+ Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
+ Values);
+ llvm::GlobalVariable *CLASS_RO_GV =
+ new llvm::GlobalVariable(ObjCTypes.ClassRonfABITy, false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ (flags & CLS_META) ?
+ std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
+ std::string("\01l_OBJC_CLASS_RO_$_")+ClassName,
+ &CGM.getModule());
+ CLASS_RO_GV->setSection(".section __DATA,__data,regular,no_dead_strip");
+ UsedGlobals.push_back(CLASS_RO_GV);
+ return CLASS_RO_GV;
+}
+
+/// BuildClassMetaData - This routine defines that to-level meta-data
+/// for the given ClassName for:
+/// struct _class_t {
+/// struct _class_t *isa;
+/// struct _class_t * const superclass;
+/// void *cache;
+/// IMP *vtable;
+/// struct class_ro_t *ro;
+/// }
+///
+void CGObjCNonFragileABIMac::BuildClassMetaData(std::string &ClassName,
+ llvm::Constant *IsAGV,
+ llvm::Constant *SuperClassGV,
+ llvm::Constant *ClassRoGV) {
+ std::vector<llvm::Constant*> Values(5);
+ Values[0] = IsAGV;
+ Values[1] = SuperClassGV;
+ Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
+ Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
+ Values[4] = ClassRoGV; // &CLASS_RO_GV
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
+ Values);
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(ClassName);
+ if (GV)
+ GV->setInitializer(Init);
+ else
+ GV =
+ new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ Init,
+ ClassName,
+ &CGM.getModule());
+ GV->setSection(".section __DATA,__data,regular,no_dead_strip");
+ UsedGlobals.push_back(GV);
+ // FIXME! why?
+ GV->setAlignment(32);
+
+}
+
void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
std::string ClassName = ID->getNameAsString();
if (!ObjCEmptyCacheVar) {
@@ -3105,70 +3212,59 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
&CGM.getModule());
UsedGlobals.push_back(ObjCEmptyVtableVar);
}
-
- std::vector<llvm::Constant*> Values(11); // 11 for 64bit targets!
- // Generate following meta-data:
- // struct _class_ro_t {
- // uint32_t const flags;
- // uint32_t const instanceStart;
- // uint32_t const instanceSize;
- // uint32_t const reserved; // only when building for 64bit targets
- // 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 _ivar_list_t *const ivars;
- // const uint8_t * const weakIvarLayout;
- // const struct _prop_list_t * const properties;
- // }
- Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
- Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
- Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
- Values[ 3] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
- // FIXME. For 64bit targets add 0 here.
- Values[ 4] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- Values[ 5] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- Values[ 6] = llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
- Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
- Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
- Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- Values[10] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
- Values);
- llvm::GlobalVariable *CLASS_RO_GV =
- new llvm::GlobalVariable(ObjCTypes.ClassRonfABITy, false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- std::string("\01l_OBJC_CLASS_RO_$_")+ClassName,
- &CGM.getModule());
- CLASS_RO_GV->setSection(".section __DATA,__data,regular,no_dead_strip");
- UsedGlobals.push_back(CLASS_RO_GV);
-
- // Generate following meta-data:
- // struct _class_t {
- // struct _class_t *isa;
- // struct _class_t * const superclass;
- // void *cache;
- // IMP *vtable;
- // struct class_ro_t *ro;
- // }
- Values.resize(5);
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
- Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
- Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
- Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
- Values[4] = CLASS_RO_GV; // &CLASS_RO_GV
- Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, Values);
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false,
- llvm::GlobalValue::ExternalLinkage,
- Init,
- std::string("\01_OBJC_CLASS_$_")+ClassName,
- &CGM.getModule());
- GV->setSection(".section __DATA,__data,regular,no_dead_strip");
- UsedGlobals.push_back(GV);
- // FIXME! why?
- GV->setAlignment(32);
+ uint32_t InstanceStart =
+ CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassnfABITy);
+ uint32_t InstanceSize = InstanceStart;
+ uint32_t flags = CLS_META;
+ std::string ObjCMetaClassName("\01_OBJC_METACLASS_$_");
+ std::string ObjCClassName("\01_OBJC_CLASS_$_");
+
+ llvm::GlobalVariable *SuperClassGV, *IsAGV;
+
+ if (ID->getClassInterface() && !ID->getClassInterface()->getSuperClass()) {
+ // class is root
+ flags |= CLS_ROOT;
+ std::string SuperClassName = ObjCClassName + ClassName;
+ SuperClassGV = CGM.getModule().getGlobalVariable(SuperClassName);
+ if (!SuperClassGV)
+ SuperClassGV =
+ new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ SuperClassName,
+ &CGM.getModule());
+ UsedGlobals.push_back(SuperClassGV);
+ std::string IsAClassName = ObjCMetaClassName + ClassName;
+ IsAGV = CGM.getModule().getGlobalVariable(IsAClassName);
+ if (!IsAGV)
+ IsAGV =
+ new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ IsAClassName,
+ &CGM.getModule());
+ UsedGlobals.push_back(IsAGV);
+ } else {
+ // Not a root.
+ std::string RootClassName =
+ ID->getClassInterface()->getSuperClass()->getNameAsString();
+ std::string SuperClassName = ObjCMetaClassName + RootClassName;
+ SuperClassGV = CGM.getModule().getGlobalVariable(SuperClassName);
+ if (!SuperClassGV)
+ SuperClassGV =
+ new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ SuperClassName,
+ &CGM.getModule());
+ UsedGlobals.push_back(SuperClassGV);
+ IsAGV = SuperClassGV;
+ }
+ llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
+ InstanceStart,
+ InstanceSize,ID);
+ std::string MetaClassName = ObjCMetaClassName + ClassName;
+ BuildClassMetaData(MetaClassName, IsAGV, SuperClassGV, CLASS_RO_GV);
}
/* *** */