From 2bb5ddaff86ee73d2cea7ec1835978afc88a83f0 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 23 Apr 2010 17:41:07 +0000 Subject: [PATCH] More work toward implementing NeXt's -fno-constant-cfstrings - wip. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102189 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 15 ++++++ include/clang/Basic/TargetInfo.h | 6 +++ include/clang/Frontend/PCHBitCodes.h | 4 +- include/clang/Frontend/PCHReader.h | 2 +- lib/AST/ASTContext.cpp | 40 ++++++++++++++ lib/CodeGen/CodeGenModule.cpp | 78 +++++++++++++++++++++++++++- lib/CodeGen/CodeGenModule.h | 4 ++ lib/Frontend/PCHReader.cpp | 11 ++-- lib/Frontend/PCHWriter.cpp | 6 +-- 9 files changed, 152 insertions(+), 14 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ec17b943af..1a39889911 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -165,6 +165,8 @@ class ASTContext { QualType ObjCConstantStringType; RecordDecl *CFConstantStringTypeDecl; + RecordDecl *NSConstantStringTypeDecl; + RecordDecl *ObjCFastEnumerationStateTypeDecl; /// \brief The type for the C FILE type. @@ -689,6 +691,19 @@ public: // constant CFStrings. QualType getCFConstantStringType(); + // getNSConstantStringType - Return the C structure type used to represent + // constant NSStrings. + QualType getNSConstantStringType(); + /// Get the structure type used to representation NSStrings, or NULL + /// if it hasn't yet been built. + QualType getRawNSConstantStringType() { + if (NSConstantStringTypeDecl) + return getTagDeclType(NSConstantStringTypeDecl); + return QualType(); + } + void setNSConstantStringType(QualType T); + + /// Get the structure type used to representation CFStrings, or NULL /// if it hasn't yet been built. QualType getRawCFConstantStringType() { diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 81c780c9be..455b745270 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -339,6 +339,12 @@ public: return "__DATA,__cfstring"; } + /// getNSStringSection - Return the section to use for NSString + /// literals, or 0 if no special section is used. + virtual const char *getNSStringSection() const { + return "__OBJC,__cstring_object,regular,no_dead_strip"; + } + /// isValidSectionSpecifier - This is an optional hook that targets can /// implement to perform semantic checking on attribute((section("foo"))) /// specifiers. In this case, "foo" is passed in to be checked. If the diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index f975c497be..457e63332f 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -453,7 +453,9 @@ namespace clang { /// \brief Block extedned descriptor type for Blocks CodeGen SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13, /// \brief Objective-C "SEL" redefinition type - SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14 + SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14, + /// \brief NSConstantString type + SPECIAL_TYPE_NS_CONSTANT_STRING = 15 }; /// \brief Record codes for each kind of declaration. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index e324228e92..c2352301ca 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -436,7 +436,7 @@ private: std::deque PendingIdentifierInfos; /// \brief FIXME: document! - llvm::SmallVector SpecialTypes; + llvm::SmallVector SpecialTypes; /// \brief Contains declarations and definitions that will be /// "interesting" to the ASTConsumer, when we get that AST consumer. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7431a23cdd..2737347857 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -41,6 +41,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, Builtin::Context &builtins, bool FreeMem, unsigned size_reserve) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), + NSConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t), @@ -2906,6 +2907,45 @@ void ASTContext::setCFConstantStringType(QualType T) { CFConstantStringTypeDecl = Rec->getDecl(); } +// getNSConstantStringType - Return the type used for constant NSStrings. +QualType ASTContext::getNSConstantStringType() { + if (!NSConstantStringTypeDecl) { + NSConstantStringTypeDecl = + CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("__builtin_NSString")); + NSConstantStringTypeDecl->startDefinition(); + + QualType FieldTypes[3]; + + // const int *isa; + FieldTypes[0] = getPointerType(IntTy.withConst()); + // const char *str; + FieldTypes[1] = getPointerType(CharTy.withConst()); + // unsigned int length; + FieldTypes[2] = UnsignedIntTy; + + // Create fields + for (unsigned i = 0; i < 3; ++i) { + FieldDecl *Field = FieldDecl::Create(*this, NSConstantStringTypeDecl, + SourceLocation(), 0, + FieldTypes[i], /*TInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false); + NSConstantStringTypeDecl->addDecl(Field); + } + + NSConstantStringTypeDecl->completeDefinition(); + } + + return getTagDeclType(NSConstantStringTypeDecl); +} + +void ASTContext::setNSConstantStringType(QualType T) { + const RecordType *Rec = T->getAs(); + assert(Rec && "Invalid NSConstantStringType"); + NSConstantStringTypeDecl = Rec->getDecl(); +} + QualType ASTContext::getObjCFastEnumerationStateType() { if (!ObjCFastEnumerationStateTypeDecl) { ObjCFastEnumerationStateTypeDecl = diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index b140837337..ee02e9374e 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -50,6 +50,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()), MangleCtx(C, diags), VTables(*this), Runtime(0), CFConstantStringClassRef(0), + NSConstantStringClassRef(0), VMContext(M.getContext()) { if (!Features.ObjC1) @@ -1595,8 +1596,81 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { llvm::Constant * CodeGenModule::GetAddrOfConstantNSString(const StringLiteral *Literal) { - // FIXME. This is temporary so -fno-constant-cfstrings same as old. - return GetAddrOfConstantCFString(Literal); + unsigned StringLength = 0; + bool isUTF16 = false; + llvm::StringMapEntry &Entry = + GetConstantCFStringEntry(CFConstantStringMap, Literal, + getTargetData().isLittleEndian(), + isUTF16, StringLength); + + if (llvm::Constant *C = Entry.getValue()) + return C; + + llvm::Constant *Zero = + llvm::Constant::getNullValue(llvm::Type::getInt32Ty(VMContext)); + llvm::Constant *Zeros[] = { Zero, Zero }; + + // If we don't already have it, get __NSConstantStringClassReference. + if (!NSConstantStringClassRef) { + const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); + Ty = llvm::ArrayType::get(Ty, 0); + llvm::Constant *GV = CreateRuntimeVariable(Ty, + "__NSConstantStringClassReference"); + // Decay array -> ptr + NSConstantStringClassRef = + llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2); + } + + QualType NSTy = getContext().getNSConstantStringType(); + + const llvm::StructType *STy = + cast(getTypes().ConvertType(NSTy)); + + std::vector Fields(3); + + // Class pointer. + Fields[0] = NSConstantStringClassRef; + + // String pointer. + llvm::Constant *C = llvm::ConstantArray::get(VMContext, Entry.getKey().str()); + + llvm::GlobalValue::LinkageTypes Linkage; + bool isConstant; + if (isUTF16) { + // FIXME: why do utf strings get "_" labels instead of "L" labels? + Linkage = llvm::GlobalValue::InternalLinkage; + // Note: -fwritable-strings doesn't make unicode NSStrings writable, but + // does make plain ascii ones writable. + isConstant = true; + } else { + Linkage = llvm::GlobalValue::PrivateLinkage; + isConstant = !Features.WritableStrings; + } + + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C, + ".str"); + if (isUTF16) { + CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy); + GV->setAlignment(Align.getQuantity()); + } + Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2); + + // String length. + const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy); + Fields[2] = llvm::ConstantInt::get(Ty, StringLength); + + // The struct. + C = llvm::ConstantStruct::get(STy, Fields); + GV = new llvm::GlobalVariable(getModule(), C->getType(), true, + llvm::GlobalVariable::PrivateLinkage, C, + "_unnamed_nsstring_"); + // FIXME. Fix section. + if (const char *Sect = getContext().Target.getNSStringSection()) + GV->setSection(Sect); + Entry.setValue(GV); + + return GV; } /// GetStringForStringLiteral - Return the appropriate bytes for a diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 7e52f76b3c..238b36d3d2 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -147,6 +147,10 @@ class CodeGenModule : public BlockModule { /// strings. This value has type int * but is actually an Obj-C class pointer. llvm::Constant *CFConstantStringClassRef; + /// NSConstantStringClassRef - Cached reference to the class for constant + /// strings. This value has type int * but is actually an Obj-C class pointer. + llvm::Constant *NSConstantStringClassRef; + /// Lazily create the Objective-C runtime void createObjCRuntime(); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 8e9f5243a9..ae57ce581d 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1766,17 +1766,16 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { if (unsigned ObjCClassRedef = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); -#if 0 - // FIXME. Accommodate for this in several PCH/Index tests - if (unsigned ObjCSelRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) - Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); -#endif if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR]) Context->setBlockDescriptorType(GetType(String)); if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR]) Context->setBlockDescriptorExtendedType(GetType(String)); + if (unsigned ObjCSelRedef + = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) + Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); + if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_NS_CONSTANT_STRING]) + Context->setNSConstantStringType(GetType(String)); } /// \brief Retrieve the name of the original source file name diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index b8d13cb597..633532fdab 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -2095,12 +2095,10 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.getsigjmp_bufType(), Record); AddTypeRef(Context.ObjCIdRedefinitionType, Record); AddTypeRef(Context.ObjCClassRedefinitionType, Record); -#if 0 - // FIXME. Accommodate for this in several PCH/Indexer tests - AddTypeRef(Context.ObjCSelRedefinitionType, Record); -#endif AddTypeRef(Context.getRawBlockdescriptorType(), Record); AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record); + AddTypeRef(Context.ObjCSelRedefinitionType, Record); + AddTypeRef(Context.getRawNSConstantStringType(), Record); Stream.EmitRecord(pch::SPECIAL_TYPES, Record); // Keep writing types and declarations until all types and -- 2.40.0