From c9759df016c0fd79fc4fccab3d3fbe851034819f Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 30 Nov 2016 20:19:46 +0000 Subject: [PATCH] Finish adopting ConstantInitBuilder in CGObjCGNU. NFC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@288269 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjCGNU.cpp | 360 +++++++++++++++++----------------- lib/CodeGen/ConstantBuilder.h | 7 + 2 files changed, 187 insertions(+), 180 deletions(-) diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 98295d885f..69e84d1023 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -164,9 +164,8 @@ protected: /// Helper function that generates a constant string and returns a pointer to /// the start of the string. The result of this function can be used anywhere /// where the C code specifies const char*. - llvm::Constant *MakeConstantString(const std::string &Str, - const std::string &Name="") { - ConstantAddress Array = CGM.GetAddrOfConstantCString(Str, Name.c_str()); + llvm::Constant *MakeConstantString(StringRef Str, const char *Name = "") { + ConstantAddress Array = CGM.GetAddrOfConstantCString(Str, Name); return llvm::ConstantExpr::getGetElementPtr(Array.getElementType(), Array.getPointer(), Zeros); } @@ -1530,23 +1529,24 @@ GenerateMethodList(StringRef ClassName, MethodList.addInt(Int32Ty, MethodTypes.size()); // Get the method structure type. - llvm::StructType *ObjCMethodTy = llvm::StructType::get( - PtrToInt8Ty, // Really a selector, but the runtime creates it us. - PtrToInt8Ty, // Method types - IMPTy, //Method pointer - nullptr); + llvm::StructType *ObjCMethodTy = + llvm::StructType::get(CGM.getLLVMContext(), { + PtrToInt8Ty, // Really a selector, but the runtime creates it us. + PtrToInt8Ty, // Method types + IMPTy // Method pointer + }); auto Methods = MethodList.beginArray(); for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) { - llvm::Constant *Method = + llvm::Constant *FnPtr = TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName, MethodSels[i], isClassMethodList)); - assert(Method && "Can't generate metadata for method that doesn't exist"); - llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString()); - Method = llvm::ConstantExpr::getBitCast(Method, - IMPTy); - Methods.add( - llvm::ConstantStruct::get(ObjCMethodTy, {C, MethodTypes[i], Method})); + assert(FnPtr && "Can't generate metadata for method that doesn't exist"); + auto Method = Methods.beginStruct(ObjCMethodTy); + Method.add(MakeConstantString(MethodSels[i].getAsString())); + Method.add(MethodTypes[i]); + Method.addBitCast(FnPtr, IMPTy); + Method.finishAndAddTo(Methods); } Methods.finishAndAddTo(MethodList); @@ -1644,7 +1644,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( // Fill in the structure // isa - Elements.add(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty)); + Elements.addBitCast(MetaClass, PtrToInt8Ty); // super_class Elements.add(SuperClass); // name @@ -1673,7 +1673,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( // sibling_class Elements.add(NULLPtr); // protocols - Elements.add(llvm::ConstantExpr::getBitCast(Protocols, PtrTy)); + Elements.addBitCast(Protocols, PtrTy); // gc_object_type Elements.add(NULLPtr); // abi_version @@ -1746,9 +1746,7 @@ CGObjCGNU::GenerateProtocolList(ArrayRef Protocols) { } else { protocol = value->getValue(); } - llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol, - PtrToInt8Ty); - Elements.add(Ptr); + Elements.addBitCast(protocol, PtrToInt8Ty); } Elements.finishAndAddTo(ProtocolList); return ProtocolList.finishAndCreateGlobal(".objc_protocol_list", @@ -1959,11 +1957,11 @@ void CGObjCGNU::GenerateProtocolHolderCategory() { Elements.add(MakeConstantString(CategoryName)); Elements.add(MakeConstantString(ClassName)); // Instance method list - Elements.add(llvm::ConstantExpr::getBitCast(GenerateMethodList( - ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy)); + Elements.addBitCast(GenerateMethodList( + ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy); // Class method list - Elements.add(llvm::ConstantExpr::getBitCast(GenerateMethodList( - ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy)); + Elements.addBitCast(GenerateMethodList( + ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy); // Protocol list ConstantInitBuilder ProtocolListBuilder(CGM); @@ -1973,15 +1971,13 @@ void CGObjCGNU::GenerateProtocolHolderCategory() { auto ProtocolElements = ProtocolList.beginArray(PtrTy); for (auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end(); iter != endIter ; iter++) { - llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(), - PtrTy); - ProtocolElements.add(Ptr); + ProtocolElements.addBitCast(iter->getValue(), PtrTy); } ProtocolElements.finishAndAddTo(ProtocolList); - Elements.add(llvm::ConstantExpr::getBitCast( + Elements.addBitCast( ProtocolList.finishAndCreateGlobal(".objc_protocol_list", CGM.getPointerAlign()), - PtrTy)); + PtrTy); Categories.push_back(llvm::ConstantExpr::getBitCast( Elements.finishAndCreateGlobal("", CGM.getPointerAlign()), PtrTy)); @@ -2066,18 +2062,17 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Elements.add(MakeConstantString(CategoryName)); Elements.add(MakeConstantString(ClassName)); // Instance method list - Elements.add(llvm::ConstantExpr::getBitCast( + Elements.addBitCast( GenerateMethodList(ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes, false), - PtrTy)); + PtrTy); // Class method list - Elements.add(llvm::ConstantExpr::getBitCast( - GenerateMethodList(ClassName, CategoryName, - ClassMethodSels, ClassMethodTypes, true), - PtrTy)); + Elements.addBitCast( + GenerateMethodList(ClassName, CategoryName, ClassMethodSels, + ClassMethodTypes, true), + PtrTy); // Protocol list - Elements.add(llvm::ConstantExpr::getBitCast( - GenerateProtocolList(Protocols), PtrTy)); + Elements.addBitCast(GenerateProtocolList(Protocols), PtrTy); Categories.push_back(llvm::ConstantExpr::getBitCast( Elements.finishAndCreateGlobal("", CGM.getPointerAlign()), PtrTy)); @@ -2406,173 +2401,179 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { // Add all referenced protocols to a category. GenerateProtocolHolderCategory(); - llvm::StructType *SelStructTy = dyn_cast( - SelectorTy->getElementType()); - llvm::Type *SelStructPtrTy = SelectorTy; - if (!SelStructTy) { - SelStructTy = llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, nullptr); - SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy); + llvm::StructType *selStructTy = + dyn_cast(SelectorTy->getElementType()); + llvm::Type *selStructPtrTy = SelectorTy; + if (!selStructTy) { + selStructTy = llvm::StructType::get(CGM.getLLVMContext(), + { PtrToInt8Ty, PtrToInt8Ty }); + selStructPtrTy = llvm::PointerType::getUnqual(selStructTy); } - std::vector Elements; - llvm::Constant *Statics = NULLPtr; // Generate statics list: + llvm::Constant *statics = NULLPtr; if (!ConstantStrings.empty()) { - llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty, - ConstantStrings.size() + 1); - ConstantStrings.push_back(NULLPtr); - - StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass; - - if (StringClass.empty()) StringClass = "NXConstantString"; - - Elements.push_back(MakeConstantString(StringClass, - ".objc_static_class_name")); - Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, - ConstantStrings)); - Statics = MakeGlobal(llvm::ConstantStruct::getAnon(Elements), - CGM.getPointerAlign(), ".objc_statics"); - llvm::Type *StaticsListPtrTy = Statics->getType(); - llvm::ArrayType *StaticsListArrayTy = - llvm::ArrayType::get(StaticsListPtrTy, 2); - Elements.clear(); - Elements.push_back(Statics); - Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy)); - Statics = MakeGlobal(llvm::ConstantArray::get(StaticsListArrayTy, Elements), - CGM.getPointerAlign(), ".objc_statics_ptr"); - Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy); - } - // Array of classes, categories, and constant objects - llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty, - Classes.size() + Categories.size() + 2); - llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelStructPtrTy, - llvm::Type::getInt16Ty(VMContext), - llvm::Type::getInt16Ty(VMContext), - ClassListTy, nullptr); - - Elements.clear(); + llvm::GlobalVariable *fileStatics = [&] { + ConstantInitBuilder builder(CGM); + auto staticsStruct = builder.beginStruct(); + + StringRef stringClass = CGM.getLangOpts().ObjCConstantStringClass; + if (stringClass.empty()) stringClass = "NXConstantString"; + staticsStruct.add(MakeConstantString(stringClass, + ".objc_static_class_name")); + + auto array = staticsStruct.beginArray(); + array.addAll(ConstantStrings); + array.add(NULLPtr); + array.finishAndAddTo(staticsStruct); + + return staticsStruct.finishAndCreateGlobal(".objc_statics", + CGM.getPointerAlign()); + }(); + + ConstantInitBuilder builder(CGM); + auto allStaticsArray = builder.beginArray(fileStatics->getType()); + allStaticsArray.add(fileStatics); + allStaticsArray.addNullPointer(fileStatics->getType()); + + statics = allStaticsArray.finishAndCreateGlobal(".objc_statics_ptr", + CGM.getPointerAlign()); + statics = llvm::ConstantExpr::getBitCast(statics, PtrTy); + } + + // Array of classes, categories, and constant objects. + + SmallVector selectorAliases; + unsigned selectorCount; + // Pointer to an array of selectors used in this module. - ConstantInitBuilder SelectorBuilder(CGM); - auto Selectors = SelectorBuilder.beginArray(SelStructTy); - std::vector SelectorAliases; - for (SelectorMap::iterator iter = SelectorTable.begin(), - iterEnd = SelectorTable.end(); iter != iterEnd ; ++iter) { - - std::string SelNameStr = iter->first.getAsString(); - llvm::Constant *SelName = ExportUniqueString(SelNameStr, ".objc_sel_name"); - - SmallVectorImpl &Types = iter->second; - for (SmallVectorImpl::iterator i = Types.begin(), - e = Types.end() ; i!=e ; i++) { - - llvm::Constant *SelectorTypeEncoding = NULLPtr; - if (!i->first.empty()) - SelectorTypeEncoding = MakeConstantString(i->first, ".objc_sel_types"); - - auto SelStruct = Selectors.beginStruct(SelStructTy); - SelStruct.add(SelName); - SelStruct.add(SelectorTypeEncoding); - SelStruct.finishAndAddTo(Selectors); - - // Store the selector alias for later replacement - SelectorAliases.push_back(i->second); + llvm::GlobalVariable *selectorList = [&] { + ConstantInitBuilder builder(CGM); + auto selectors = builder.beginArray(selStructTy); + for (auto &entry : SelectorTable) { + + std::string selNameStr = entry.first.getAsString(); + llvm::Constant *selName = ExportUniqueString(selNameStr, ".objc_sel_name"); + + for (TypedSelector &sel : entry.second) { + llvm::Constant *selectorTypeEncoding = NULLPtr; + if (!sel.first.empty()) + selectorTypeEncoding = + MakeConstantString(sel.first, ".objc_sel_types"); + + auto selStruct = selectors.beginStruct(selStructTy); + selStruct.add(selName); + selStruct.add(selectorTypeEncoding); + selStruct.finishAndAddTo(selectors); + + // Store the selector alias for later replacement + selectorAliases.push_back(sel.second); + } } - } - unsigned SelectorCount = Selectors.size(); - // NULL-terminate the selector list. This should not actually be required, - // because the selector list has a length field. Unfortunately, the GCC - // runtime decides to ignore the length field and expects a NULL terminator, - // and GCC cooperates with this by always setting the length to 0. - { - auto SelStruct = Selectors.beginStruct(SelStructTy); - SelStruct.add(NULLPtr); - SelStruct.add(NULLPtr); - SelStruct.finishAndAddTo(Selectors); - } - // Number of static selectors - Elements.push_back(llvm::ConstantInt::get(LongTy, SelectorCount)); - llvm::GlobalVariable *SelectorList = - Selectors.finishAndCreateGlobal(".objc_selector_list", - CGM.getPointerAlign()); - Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, - SelStructPtrTy)); + // Remember the number of entries in the selector table. + selectorCount = selectors.size(); - // Now that all of the static selectors exist, create pointers to them. - for (unsigned int i=0 ; igetValueType(), SelectorList, makeArrayRef(Idxs, 2)); + llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr( + selectorList->getValueType(), selectorList, idxs); // If selectors are defined as an opaque type, cast the pointer to this // type. - SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, SelectorTy); - SelectorAliases[i]->replaceAllUsesWith(SelPtr); - SelectorAliases[i]->eraseFromParent(); - } - - // Number of classes defined. - Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), - Classes.size())); - // Number of categories defined - Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), - Categories.size())); - // Create an array of classes, then categories, then static object instances - Classes.insert(Classes.end(), Categories.begin(), Categories.end()); - // NULL-terminated list of static object instances (mainly constant strings) - Classes.push_back(Statics); - Classes.push_back(NULLPtr); - llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes); - Elements.push_back(ClassList); - // Construct the symbol table - llvm::Constant *SymTab = - MakeGlobal(llvm::ConstantStruct::get(SymTabTy, Elements), - CGM.getPointerAlign()); + selPtr = llvm::ConstantExpr::getBitCast(selPtr, SelectorTy); + selectorAliases[i]->replaceAllUsesWith(selPtr); + selectorAliases[i]->eraseFromParent(); + } + + llvm::GlobalVariable *symtab = [&] { + ConstantInitBuilder builder(CGM); + auto symtab = builder.beginStruct(); + + // Number of static selectors + symtab.addInt(LongTy, selectorCount); + + symtab.addBitCast(selectorList, selStructPtrTy); + + // Number of classes defined. + symtab.addInt(CGM.Int16Ty, Classes.size()); + // Number of categories defined + symtab.addInt(CGM.Int16Ty, Categories.size()); + + // Create an array of classes, then categories, then static object instances + auto classList = symtab.beginArray(PtrToInt8Ty); + classList.addAll(Classes); + classList.addAll(Categories); + // NULL-terminated list of static object instances (mainly constant strings) + classList.add(statics); + classList.add(NULLPtr); + classList.finishAndAddTo(symtab); + + // Construct the symbol table. + return symtab.finishAndCreateGlobal("", CGM.getPointerAlign()); + }(); // The symbol table is contained in a module which has some version-checking // constants - llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy, - PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), - (RuntimeVersion >= 10) ? IntTy : nullptr, nullptr); - Elements.clear(); - // Runtime version, used for ABI compatibility checking. - Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion)); - // sizeof(ModuleTy) - llvm::DataLayout td(&TheModule); - Elements.push_back( - llvm::ConstantInt::get(LongTy, - td.getTypeSizeInBits(ModuleTy) / - CGM.getContext().getCharWidth())); - - // The path to the source file where this module was declared - SourceManager &SM = CGM.getContext().getSourceManager(); - const FileEntry *mainFile = SM.getFileEntryForID(SM.getMainFileID()); - std::string path = + llvm::Constant *module = [&] { + llvm::Type *moduleEltTys[] = { + LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy + }; + llvm::StructType *moduleTy = + llvm::StructType::get(CGM.getLLVMContext(), + makeArrayRef(moduleEltTys).drop_back(unsigned(RuntimeVersion < 10))); + + ConstantInitBuilder builder(CGM); + auto module = builder.beginStruct(moduleTy); + // Runtime version, used for ABI compatibility checking. + module.addInt(LongTy, RuntimeVersion); + // sizeof(ModuleTy) + module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy)); + + // The path to the source file where this module was declared + SourceManager &SM = CGM.getContext().getSourceManager(); + const FileEntry *mainFile = SM.getFileEntryForID(SM.getMainFileID()); + std::string path = (Twine(mainFile->getDir()->getName()) + "/" + mainFile->getName()).str(); - Elements.push_back(MakeConstantString(path, ".objc_source_file_name")); - Elements.push_back(SymTab); + module.add(MakeConstantString(path, ".objc_source_file_name")); + module.add(symtab); - if (RuntimeVersion >= 10) - switch (CGM.getLangOpts().getGC()) { + if (RuntimeVersion >= 10) { + switch (CGM.getLangOpts().getGC()) { case LangOptions::GCOnly: - Elements.push_back(llvm::ConstantInt::get(IntTy, 2)); + module.addInt(IntTy, 2); break; case LangOptions::NonGC: if (CGM.getLangOpts().ObjCAutoRefCount) - Elements.push_back(llvm::ConstantInt::get(IntTy, 1)); + module.addInt(IntTy, 1); else - Elements.push_back(llvm::ConstantInt::get(IntTy, 0)); + module.addInt(IntTy, 0); break; case LangOptions::HybridGC: - Elements.push_back(llvm::ConstantInt::get(IntTy, 1)); + module.addInt(IntTy, 1); break; + } } - llvm::Value *Module = - MakeGlobal(llvm::ConstantStruct::get(ModuleTy, Elements), - CGM.getPointerAlign()); + return module.finishAndCreateGlobal("", CGM.getPointerAlign()); + }(); // Create the load function calling the runtime entry point with the module // structure @@ -2586,10 +2587,9 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { Builder.SetInsertPoint(EntryBB); llvm::FunctionType *FT = - llvm::FunctionType::get(Builder.getVoidTy(), - llvm::PointerType::getUnqual(ModuleTy), true); + llvm::FunctionType::get(Builder.getVoidTy(), module->getType(), true); llvm::Value *Register = CGM.CreateRuntimeFunction(FT, "__objc_exec_class"); - Builder.CreateCall(Register, Module); + Builder.CreateCall(Register, module); if (!ClassAliases.empty()) { llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty}; diff --git a/lib/CodeGen/ConstantBuilder.h b/lib/CodeGen/ConstantBuilder.h index 727023bf48..bedab3e201 100644 --- a/lib/CodeGen/ConstantBuilder.h +++ b/lib/CodeGen/ConstantBuilder.h @@ -155,6 +155,13 @@ public: add(llvm::ConstantExpr::getBitCast(value, type)); } + /// Add a bunch of new values to this initializer. + void addAll(ArrayRef values) { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + Builder.Buffer.append(values.begin(), values.end()); + } + /// An opaque class to hold the abstract position of a placeholder. class PlaceholderPosition { size_t Index; -- 2.40.0