From: John McCall Date: Wed, 30 Nov 2016 23:15:55 +0000 (+0000) Subject: Fix some layering violations where CGObjCMac's NSString emission was X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cd21d541397eadab33d94b3a0c476f96afc3477f;p=platform%2Fupstream%2Fllvm.git Fix some layering violations where CGObjCMac's NSString emission was performed at the CodeGenModule level. Would be NFC except we now also use a different uniquing structure so that we don't get spurious conflicts if you ask for both an NSString and a CFString for the same content (which is possible with builtins). llvm-svn: 288287 --- diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 338fdee..593067c 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -888,6 +888,15 @@ protected: /// DefinedNonLazyCategories - List of defined "non-lazy" categories. SmallVector DefinedNonLazyCategories; + /// Cached reference to the class for constant strings. This value has type + /// int * but is actually an Obj-C class pointer. + llvm::WeakVH ConstantStringClassRef; + + /// \brief The LLVM type corresponding to NSConstantString. + llvm::StructType *NSConstantStringType = nullptr; + + llvm::StringMap NSConstantStringMap; + /// GetNameForMethod - Return a name for the given method. /// \param[out] NameOut - The return value. void GetNameForMethod(const ObjCMethodDecl *OMD, @@ -1054,6 +1063,7 @@ public: } ConstantAddress GenerateConstantString(const StringLiteral *SL) override; + ConstantAddress GenerateConstantNSString(const StringLiteral *SL); llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD=nullptr) override; @@ -1070,6 +1080,9 @@ public: /// forward references will be filled in with empty bodies if no /// definition is seen. The return value has type ProtocolPtrTy. virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; + + virtual llvm::Constant *getNSConstantStringClassRef() = 0; + llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, const CGBlockInfo &blockInfo) override; llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, @@ -1266,6 +1279,8 @@ private: public: CGObjCMac(CodeGen::CodeGenModule &cgm); + llvm::Constant *getNSConstantStringClassRef() override; + llvm::Function *ModuleInitFunction() override; CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, @@ -1536,7 +1551,9 @@ private: public: CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); - // FIXME. All stubs for now! + + llvm::Constant *getNSConstantStringClassRef() override; + llvm::Function *ModuleInitFunction() override; CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, @@ -1846,11 +1863,115 @@ llvm::Constant *CGObjCMac::GetEHType(QualType T) { }; */ -ConstantAddress CGObjCCommonMac::GenerateConstantString( - const StringLiteral *SL) { - return (CGM.getLangOpts().NoConstantCFStrings == 0 ? - CGM.GetAddrOfConstantCFString(SL) : - CGM.GetAddrOfConstantString(SL)); +ConstantAddress +CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) { + return (!CGM.getLangOpts().NoConstantCFStrings + ? CGM.GetAddrOfConstantCFString(SL) + : GenerateConstantNSString(SL)); +} + +static llvm::StringMapEntry & +GetConstantStringEntry(llvm::StringMap &Map, + const StringLiteral *Literal, unsigned &StringLength) { + StringRef String = Literal->getString(); + StringLength = String.size(); + return *Map.insert(std::make_pair(String, nullptr)).first; +} + +llvm::Constant *CGObjCMac::getNSConstantStringClassRef() { + if (llvm::Value *V = ConstantStringClassRef) + return cast(V); + + auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; + std::string str = + StringClass.empty() ? "_NSConstantStringClassReference" + : "_" + StringClass + "ClassReference"; + + llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0); + auto GV = CGM.CreateRuntimeVariable(PTy, str); + auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo()); + ConstantStringClassRef = V; + return V; +} + +llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() { + if (llvm::Value *V = ConstantStringClassRef) + return cast(V); + + auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; + std::string str = + StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" + : "OBJC_CLASS_$_" + StringClass; + auto GV = GetClassGlobal(str); + + // Make sure the result is of the correct type. + auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo()); + + ConstantStringClassRef = V; + return V; +} + +ConstantAddress +CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) { + unsigned StringLength = 0; + llvm::StringMapEntry &Entry = + GetConstantStringEntry(NSConstantStringMap, Literal, StringLength); + + if (auto *C = Entry.second) + return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment())); + + // If we don't already have it, get _NSConstantStringClassReference. + llvm::Constant *Class = getNSConstantStringClassRef(); + + // If we don't already have it, construct the type for a constant NSString. + if (!NSConstantStringType) { + NSConstantStringType = + llvm::StructType::create({ + CGM.Int32Ty->getPointerTo(), + CGM.Int8PtrTy, + CGM.IntTy + }, "struct.__builtin_NSString"); + } + + ConstantInitBuilder Builder(CGM); + auto Fields = Builder.beginStruct(NSConstantStringType); + + // Class pointer. + Fields.add(Class); + + // String pointer. + llvm::Constant *C = + llvm::ConstantDataArray::getString(VMContext, Entry.first()); + + llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage; + bool isConstant = !CGM.getLangOpts().WritableStrings; + + auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant, + Linkage, C, ".str"); + GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + // Don't enforce the target's minimum global alignment, since the only use + // of the string is via this class initializer. + GV->setAlignment(1); + Fields.addBitCast(GV, CGM.Int8PtrTy); + + // String length. + Fields.addInt(CGM.IntTy, StringLength); + + // The struct. + CharUnits Alignment = CGM.getPointerAlign(); + GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment, + /*constant*/ true, + llvm::GlobalVariable::PrivateLinkage); + const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip"; + const char *NSStringNonFragileABISection = + "__DATA,__objc_stringobj,regular,no_dead_strip"; + // FIXME. Fix section. + GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile() + ? NSStringNonFragileABISection + : NSStringSection); + Entry.second = GV; + + return ConstantAddress(GV, Alignment); } enum { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 9ea11b8..e9cfb5e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3131,14 +3131,6 @@ GetConstantCFStringEntry(llvm::StringMap &Map, nullptr)).first; } -static llvm::StringMapEntry & -GetConstantStringEntry(llvm::StringMap &Map, - const StringLiteral *Literal, unsigned &StringLength) { - StringRef String = Literal->getString(); - StringLength = String.size(); - return *Map.insert(std::make_pair(String, nullptr)).first; -} - ConstantAddress CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { unsigned StringLength = 0; @@ -3265,120 +3257,6 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { return ConstantAddress(GV, Alignment); } -ConstantAddress -CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { - unsigned StringLength = 0; - llvm::StringMapEntry &Entry = - GetConstantStringEntry(CFConstantStringMap, Literal, StringLength); - - if (auto *C = Entry.second) - return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment())); - - llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); - llvm::Constant *Zeros[] = { Zero, Zero }; - llvm::Value *V; - // If we don't already have it, get _NSConstantStringClassReference. - if (!ConstantStringClassRef) { - std::string StringClass(getLangOpts().ObjCConstantStringClass); - llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); - llvm::Constant *GV; - if (LangOpts.ObjCRuntime.isNonFragile()) { - std::string str = - StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" - : "OBJC_CLASS_$_" + StringClass; - GV = getObjCRuntime().GetClassGlobal(str); - // Make sure the result is of the correct type. - llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); - V = llvm::ConstantExpr::getBitCast(GV, PTy); - ConstantStringClassRef = V; - } else { - std::string str = - StringClass.empty() ? "_NSConstantStringClassReference" - : "_" + StringClass + "ClassReference"; - llvm::Type *PTy = llvm::ArrayType::get(Ty, 0); - GV = CreateRuntimeVariable(PTy, str); - // Decay array -> ptr - V = llvm::ConstantExpr::getGetElementPtr(PTy, GV, Zeros); - ConstantStringClassRef = V; - } - } else - V = ConstantStringClassRef; - - if (!NSConstantStringType) { - // Construct the type for a constant NSString. - RecordDecl *D = Context.buildImplicitRecord("__builtin_NSString"); - D->startDefinition(); - - QualType FieldTypes[3]; - - // const int *isa; - FieldTypes[0] = Context.getPointerType(Context.IntTy.withConst()); - // const char *str; - FieldTypes[1] = Context.getPointerType(Context.CharTy.withConst()); - // unsigned int length; - FieldTypes[2] = Context.UnsignedIntTy; - - // Create fields - for (unsigned i = 0; i < 3; ++i) { - FieldDecl *Field = FieldDecl::Create(Context, D, - SourceLocation(), - SourceLocation(), nullptr, - FieldTypes[i], /*TInfo=*/nullptr, - /*BitWidth=*/nullptr, - /*Mutable=*/false, - ICIS_NoInit); - Field->setAccess(AS_public); - D->addDecl(Field); - } - - D->completeDefinition(); - QualType NSTy = Context.getTagDeclType(D); - NSConstantStringType = cast(getTypes().ConvertType(NSTy)); - } - - ConstantInitBuilder Builder(*this); - auto Fields = Builder.beginStruct(NSConstantStringType); - - // Class pointer. - Fields.add(cast(V)); - - // String pointer. - llvm::Constant *C = - llvm::ConstantDataArray::getString(VMContext, Entry.first()); - - llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage; - bool isConstant = !LangOpts.WritableStrings; - - auto *GV = new llvm::GlobalVariable(getModule(), C->getType(), isConstant, - Linkage, C, ".str"); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - // Don't enforce the target's minimum global alignment, since the only use - // of the string is via this class initializer. - CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy); - GV->setAlignment(Align.getQuantity()); - Fields.add( - llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros)); - - // String length. - Fields.addInt(IntTy, StringLength); - - // The struct. - CharUnits Alignment = getPointerAlign(); - GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment, - /*constant*/ true, - llvm::GlobalVariable::PrivateLinkage); - const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip"; - const char *NSStringNonFragileABISection = - "__DATA,__objc_stringobj,regular,no_dead_strip"; - // FIXME. Fix section. - GV->setSection(LangOpts.ObjCRuntime.isNonFragile() - ? NSStringNonFragileABISection - : NSStringSection); - Entry.second = GV; - - return ConstantAddress(GV, Alignment); -} - QualType CodeGenModule::getObjCFastEnumerationStateType() { if (ObjCFastEnumerationStateType.isNull()) { RecordDecl *D = Context.buildImplicitRecord("__objcFastEnumerationState"); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 7def774..c7ef80e 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -434,13 +434,6 @@ private: /// int * but is actually an Obj-C class pointer. llvm::WeakVH CFConstantStringClassRef; - /// Cached reference to the class for constant strings. This value has type - /// int * but is actually an Obj-C class pointer. - llvm::WeakVH ConstantStringClassRef; - - /// \brief The LLVM type corresponding to NSConstantString. - llvm::StructType *NSConstantStringType = nullptr; - /// \brief The type used to describe the state of a fast enumeration in /// Objective-C's for..in loop. QualType ObjCFastEnumerationStateType;