diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-01-24 20:21:50 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-01-24 20:21:50 +0000 |
commit | 058a1b7f9d7d3498783f7d24e73235c4ba7ee851 (patch) | |
tree | 3d464a20973d585939c48a801fd13cf72bcb09fa /lib/CodeGen/CGObjCMac.cpp | |
parent | 31e21e05623ce9d11b1a893fecb87ad349df6c7d (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.cpp | 246 |
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); } /* *** */ |