From 088959a28b0a47ccdc385955543b5b52c589fad5 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Sat, 11 Feb 2012 20:10:52 +0000 Subject: [PATCH] objective-c translator. more modern abi stuff, focusing on ivar related meta-data. llvm-svn: 150310 --- clang/lib/Rewrite/RewriteModernObjC.cpp | 279 +++--------------------- 1 file changed, 33 insertions(+), 246 deletions(-) diff --git a/clang/lib/Rewrite/RewriteModernObjC.cpp b/clang/lib/Rewrite/RewriteModernObjC.cpp index 939f81d71ec4..a981ffdf6e72 100644 --- a/clang/lib/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Rewrite/RewriteModernObjC.cpp @@ -626,9 +626,6 @@ void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) { ConstantStringClassReference = FVD; return; } - } else if (ObjCInterfaceDecl *ID = dyn_cast(D)) { - if (ID->isThisDeclarationADefinition()) - RewriteInterfaceDecl(ID); } else if (ObjCCategoryDecl *CD = dyn_cast(D)) { RewriteCategoryDecl(CD); } else if (ObjCProtocolDecl *PD = dyn_cast(D)) { @@ -1183,6 +1180,15 @@ void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) { } void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { + // Do not synthesize more than once. + if (ObjCSynthesizedStructs.count(ClassDecl)) + return; + // Make sure super class's are written before current class is written. + ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass(); + while (SuperClass) { + RewriteInterfaceDecl(SuperClass); + SuperClass = SuperClass->getSuperClass(); + } std::string ResultStr; if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) { // we haven't seen a forward decl - generate a typedef. @@ -1215,6 +1221,9 @@ void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { // Lastly, comment out the @end. ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), "/* @end */"); + // Mark this struct as having been generated. + if (!ObjCSynthesizedStructs.insert(ClassDecl)) + llvm_unreachable("struct already synthesize- RewriteInterfaceDecl"); } Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { @@ -3128,9 +3137,6 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); assert(CDecl->getName() != "" && "Name missing in SynthesizeObjCInternalStruct"); - // Do not synthesize more than once. - if (ObjCSynthesizedStructs.count(CDecl)) - return; ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); SmallVector IVars; for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); @@ -3171,15 +3177,14 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); Result += "\t"; Result += TypeString; Result += " "; Result += IvarDecl->getNameAsString(); + if (IvarDecl->isBitField()) { + Result += " : "; Result += utostr(IvarDecl->getBitWidthValue(*Context)); + } Result += ";\n"; } Result += "};\n"; endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); ReplaceText(LocStart, endBuf-startBuf, Result); - - // Mark this struct as having been generated. - if (!ObjCSynthesizedStructs.insert(CDecl)) - llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct"); } //===----------------------------------------------------------------------===// @@ -3195,8 +3200,19 @@ void RewriteModernObjC::RewriteImplementations() { int CatDefCount = CategoryImplementation.size(); // Rewrite implemented methods - for (int i = 0; i < ClsDefCount; i++) - RewriteImplementationDecl(ClassImplementation[i]); + for (int i = 0; i < ClsDefCount; i++) { + ObjCImplementationDecl *OIMP = ClassImplementation[i]; + ObjCInterfaceDecl *CDecl = OIMP->getClassInterface(); + if (CDecl->isImplicitInterfaceDecl()) + assert(false && + "Legacy implicit interface rewriting not supported in moder abi"); + // Write struct declaration for the class matching its ivar declarations. + // Note that for modern abi, this is postponed until implementation decl. + // because class extensions and the implementation might declare their own + // private ivars. + RewriteInterfaceDecl(CDecl); + RewriteImplementationDecl(OIMP); + } for (int i = 0; i < CatDefCount; i++) RewriteImplementationDecl(CategoryImplementation[i]); @@ -5458,8 +5474,10 @@ static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj, RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString); Result += "\""; Result += QuoteIvarTypeString; Result += "\", "; - // FIXME: what should the alignment be? - unsigned Align = 0; + // FIXME. this alignment represents the host alignment and need be changed to + // represent the target alignment. + unsigned Align = Context->getTypeAlign(IvarDecl->getType())/8; + Align = llvm::Log2_32(Align); Result += llvm::utostr(Align); Result += ", "; CharUnits Size = Context->getTypeSizeInChars(IvarDecl->getType()); Result += llvm::utostr(Size.getQuantity()); @@ -5678,6 +5696,7 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, if (CDecl->isImplicitInterfaceDecl()) assert(false && "Legacy implicit interface rewriting not supported in moder abi"); + WriteModernMetadataDeclarations(Result); SmallVector IVars; @@ -5692,238 +5711,6 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, Write__ivar_list_t_initializer(*this, Context, Result, IVars, "_OBJC_INSTANCE_VARIABLES_", CDecl->getNameAsString()); - - // FIXME. Handle modern abi's private ivars declared in @implementation. - // Build _objc_ivar_list metadata for classes ivars if needed - unsigned NumIvars = CDecl->ivar_size(); - - if (NumIvars > 0) { - - /* struct { - int ivar_count; - struct _objc_ivar ivar_list[nIvars]; - }; - */ - Result += "\nstatic struct {\n"; - Result += "\tint ivar_count;\n"; - Result += "\tstruct _objc_ivar ivar_list["; - Result += utostr(NumIvars); - Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; - Result += IDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " - "{\n\t"; - Result += utostr(NumIvars); - Result += "\n"; - - ObjCInterfaceDecl::ivar_iterator IVI, IVE; - SmallVector IVars; - if (!IDecl->ivar_empty()) { - for (ObjCInterfaceDecl::ivar_iterator - IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); - IV != IVEnd; ++IV) - IVars.push_back(*IV); - IVI = IDecl->ivar_begin(); - IVE = IDecl->ivar_end(); - } else { - IVI = CDecl->ivar_begin(); - IVE = CDecl->ivar_end(); - } - Result += "\t,{{\""; - Result += (*IVI)->getNameAsString(); - Result += "\", \""; - std::string TmpString, StrEncoding; - Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); - QuoteDoublequotes(TmpString, StrEncoding); - Result += StrEncoding; - Result += "\", "; - RewriteIvarOffsetComputation(*IVI, Result); - Result += "}\n"; - for (++IVI; IVI != IVE; ++IVI) { - Result += "\t ,{\""; - Result += (*IVI)->getNameAsString(); - Result += "\", \""; - std::string TmpString, StrEncoding; - Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); - QuoteDoublequotes(TmpString, StrEncoding); - Result += StrEncoding; - Result += "\", "; - RewriteIvarOffsetComputation((*IVI), Result); - Result += "}\n"; - } - - Result += "\t }\n};\n"; - } - - // Build _objc_method_list for class's instance methods if needed - SmallVector - InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); - - // If any of our property implementations have associated getters or - // setters, produce metadata for them as well. - for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), - PropEnd = IDecl->propimpl_end(); - Prop != PropEnd; ++Prop) { - if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) - continue; - if (!(*Prop)->getPropertyIvarDecl()) - continue; - ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); - if (!PD) - continue; - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) - if (!Getter->isDefined()) - InstanceMethods.push_back(Getter); - if (PD->isReadOnly()) - continue; - if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) - if (!Setter->isDefined()) - InstanceMethods.push_back(Setter); - } - RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), - true, "", IDecl->getName(), Result); - - // Build _objc_method_list for class's class methods if needed - RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), - false, "", IDecl->getName(), Result); - - // Protocols referenced in class declaration? - RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), - "CLASS", CDecl->getName(), Result); - - // Declaration of class/meta-class metadata - /* struct _objc_class { - struct _objc_class *isa; // or const char *root_class_name when metadata - const char *super_class_name; - char *name; - long version; - long info; - long instance_size; - struct _objc_ivar_list *ivars; - struct _objc_method_list *methods; - struct objc_cache *cache; - struct objc_protocol_list *protocols; - const char *ivar_layout; - struct _objc_class_ext *ext; - }; - */ - static bool objc_class = false; - if (!objc_class) { - Result += "\nstruct _objc_class {\n"; - Result += "\tstruct _objc_class *isa;\n"; - Result += "\tconst char *super_class_name;\n"; - Result += "\tchar *name;\n"; - Result += "\tlong version;\n"; - Result += "\tlong info;\n"; - Result += "\tlong instance_size;\n"; - Result += "\tstruct _objc_ivar_list *ivars;\n"; - Result += "\tstruct _objc_method_list *methods;\n"; - Result += "\tstruct objc_cache *cache;\n"; - Result += "\tstruct _objc_protocol_list *protocols;\n"; - Result += "\tconst char *ivar_layout;\n"; - Result += "\tstruct _objc_class_ext *ext;\n"; - Result += "};\n"; - objc_class = true; - } - - // Meta-class metadata generation. - ObjCInterfaceDecl *RootClass = 0; - ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); - while (SuperClass) { - RootClass = SuperClass; - SuperClass = SuperClass->getSuperClass(); - } - SuperClass = CDecl->getSuperClass(); - - Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; - Result += CDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " - "{\n\t(struct _objc_class *)\""; - Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); - Result += "\""; - - if (SuperClass) { - Result += ", \""; - Result += SuperClass->getNameAsString(); - Result += "\", \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - else { - Result += ", 0, \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. - // 'info' field is initialized to CLS_META(2) for metaclass - Result += ", 0,2, sizeof(struct _objc_class), 0"; - if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { - Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; - Result += IDecl->getNameAsString(); - Result += "\n"; - } - else - Result += ", 0\n"; - if (CDecl->protocol_begin() != CDecl->protocol_end()) { - Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; - Result += CDecl->getNameAsString(); - Result += ",0,0\n"; - } - else - Result += "\t,0,0,0,0\n"; - Result += "};\n"; - - // class metadata generation. - Result += "\nstatic struct _objc_class _OBJC_CLASS_"; - Result += CDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " - "{\n\t&_OBJC_METACLASS_"; - Result += CDecl->getNameAsString(); - if (SuperClass) { - Result += ", \""; - Result += SuperClass->getNameAsString(); - Result += "\", \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - else { - Result += ", 0, \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - // 'info' field is initialized to CLS_CLASS(1) for class - Result += ", 0,1"; - if (!ObjCSynthesizedStructs.count(CDecl)) - Result += ",0"; - else { - // class has size. Must synthesize its size. - Result += ",sizeof(struct "; - Result += CDecl->getNameAsString(); - if (LangOpts.MicrosoftExt) - Result += "_IMPL"; - Result += ")"; - } - if (NumIvars > 0) { - Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; - Result += CDecl->getNameAsString(); - Result += "\n\t"; - } - else - Result += ",0"; - if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { - Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; - Result += CDecl->getNameAsString(); - Result += ", 0\n\t"; - } - else - Result += ",0,0"; - if (CDecl->protocol_begin() != CDecl->protocol_end()) { - Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; - Result += CDecl->getNameAsString(); - Result += ", 0,0\n"; - } - else - Result += ",0,0,0\n"; - Result += "};\n"; } void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {