diff options
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 49 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 34 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 1 |
5 files changed, 92 insertions, 0 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 3c1dca01e1..3ce1a65132 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -397,6 +397,55 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, FinishFunction(); } +void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, + ObjCMethodDecl *MD, + bool ctor) { + llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> IvarInitializers; + MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface()); + StartObjCMethod(MD, IMP->getClassInterface()); + for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(), + E = IMP->init_end(); B != E; ++B) { + CXXBaseOrMemberInitializer *Member = (*B); + IvarInitializers.push_back(Member); + } + if (ctor) { + for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) { + CXXBaseOrMemberInitializer *IvarInit = IvarInitializers[I]; + FieldDecl *Field = IvarInit->getMember(); + QualType FieldType = Field->getType(); + if (CGM.getContext().getAsConstantArrayType(FieldType)) + assert(false && "Construction objc arrays NYI"); + ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); + EmitAggExpr(IvarInit->getInit(), LV.getAddress(), + LV.isVolatileQualified(), false, true); + } + // constructor returns 'self'. + CodeGenTypes &Types = CGM.getTypes(); + QualType IdTy(CGM.getContext().getObjCIdType()); + llvm::Value *SelfAsId = + Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); + EmitReturnOfRValue(RValue::get(SelfAsId), IdTy); + } + else { + // dtor + for (size_t i = IvarInitializers.size(); i > 0; --i) { + FieldDecl *Field = IvarInitializers[i - 1]->getMember(); + QualType FieldType = Field->getType(); + if (CGM.getContext().getAsConstantArrayType(FieldType)) + assert(false && "Destructing objc arrays NYI"); + ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); + LValue LV = EmitLValueForIvar(TypeOfSelfObject(), + LoadObjCSelf(), Ivar, 0); + const RecordType *RT = FieldType->getAs<RecordType>(); + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + EmitCXXDestructorCall(FieldClassDecl->getDestructor(CGM.getContext()), + Dtor_Complete, LV.getAddress()); + } + } + FinishFunction(); +} + bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) { CGFunctionInfo::const_arg_iterator it = FI.arg_begin(); it++; it++; diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 429b13c50a..fdb9d0759a 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -2083,6 +2083,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { Interface->protocol_begin(), Interface->protocol_end()); unsigned Flags = eClassFlags_Factory; + if (ID->getNumIvarInitializers()) + Flags |= eClassFlags_HasCXXStructors; unsigned Size = CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8; @@ -4497,6 +4499,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden; if (classIsHidden) flags |= OBJC2_CLS_HIDDEN; + if (ID->getNumIvarInitializers()) + flags |= eClassFlags_ABI2_HasCXXStructors; if (!ID->getClassInterface()->getSuperClass()) { // class is root flags |= CLS_ROOT; @@ -4531,6 +4535,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { flags = CLS; if (classIsHidden) flags |= OBJC2_CLS_HIDDEN; + if (ID->getNumIvarInitializers()) + flags |= eClassFlags_ABI2_HasCXXStructors; if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface())) flags |= CLS_EXCEPTION; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index e4e98efbfa..0cd0bd9fe3 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -473,6 +473,8 @@ public: /// GenerateObjCGetter - Synthesize an Objective-C property getter function. void GenerateObjCGetter(ObjCImplementationDecl *IMP, const ObjCPropertyImplDecl *PID); + void GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, + ObjCMethodDecl *MD, bool ctor); /// GenerateObjCSetter - Synthesize an Objective-C property setter function /// for the given property. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 825ca8ba04..cc90a2855d 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1820,6 +1820,39 @@ void CodeGenModule::EmitObjCPropertyImplementations(const } } +/// EmitObjCIvarInitializations - Emit information for ivar initialization +/// for an implementation. +void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { + if (!Features.NeXTRuntime || D->getNumIvarInitializers() == 0) + return; + DeclContext* DC = const_cast<DeclContext*>(dyn_cast<DeclContext>(D)); + assert(DC && "EmitObjCIvarInitializations - null DeclContext"); + IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct"); + Selector cxxSelector = getContext().Selectors.getSelector(0, &II); + ObjCMethodDecl *DTORMethod = ObjCMethodDecl::Create(getContext(), + D->getLocation(), + D->getLocation(), cxxSelector, + getContext().VoidTy, 0, + DC, true, false, true, + ObjCMethodDecl::Required); + D->addInstanceMethod(DTORMethod); + CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false); + + II = &getContext().Idents.get(".cxx_construct"); + cxxSelector = getContext().Selectors.getSelector(0, &II); + // The constructor returns 'self'. + ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(), + D->getLocation(), + D->getLocation(), cxxSelector, + getContext().getObjCIdType(), 0, + DC, true, false, true, + ObjCMethodDecl::Required); + D->addInstanceMethod(CTORMethod); + CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true); + + +} + /// EmitNamespace - Emit all declarations in a namespace. void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) { for (RecordDecl::decl_iterator I = ND->decls_begin(), E = ND->decls_end(); @@ -1916,6 +1949,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::ObjCImplementation: { ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D); EmitObjCPropertyImplementations(OMD); + EmitObjCIvarInitializations(OMD); Runtime->GenerateClass(OMD); break; } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index b0abc492a8..aa30635bfa 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -482,6 +482,7 @@ private: void EmitGlobalVarDefinition(const VarDecl *D); void EmitAliasDefinition(GlobalDecl GD); void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); + void EmitObjCIvarInitializations(ObjCImplementationDecl *D); // C++ related functions. |