]> granicus.if.org Git - clang/commitdiff
IRGen for initialization/destruction of
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 28 Apr 2010 21:28:56 +0000 (21:28 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 28 Apr 2010 21:28:56 +0000 (21:28 +0000)
ivar class objects (NeXt runtime).
(radar 7900343).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102533 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjC.cpp
lib/CodeGen/CGObjCMac.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h

index 3c1dca01e12b7068399902f6fd1a9aded75f97fa..3ce1a65132f3e114cb54e38ec07781f58afd8d46 100644 (file)
@@ -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++;
index 429b13c50ad8c26568e61e92fc575bee5c5737cb..fdb9d0759a978c9d7c933c45f2a2fd1490c4890d 100644 (file)
@@ -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;
index e4e98efbfaf4999a6e8f8adbd8421054bd8efd42..0cd0bd9fe3e12e739110e7c62d8be04f95f95c57 100644 (file)
@@ -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.
index 825ca8ba04d0b3a4389ef2edc043dd220bc5ad32..cc90a2855deed797fe083db84a1f67c491b299a8 100644 (file)
@@ -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;
   }
index b0abc492a853231f6d1866fc60d1161065f839d2..aa30635bfa4c385b39d01757287a62526aa3f2fb 100644 (file)
@@ -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.