diff options
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 454 |
1 files changed, 248 insertions, 206 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index bf606a616582..d125b370a07a 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -15,6 +15,7 @@ #include "CGDebugInfo.h" #include "CodeGenFunction.h" #include "CGCall.h" +#include "CGCXXABI.h" #include "CGObjCRuntime.h" #include "Mangle.h" #include "TargetInfo.h" @@ -41,6 +42,17 @@ using namespace clang; using namespace CodeGen; +static CGCXXABI &createCXXABI(CodeGenModule &CGM) { + switch (CGM.getContext().Target.getCXXABI()) { + case CXXABI_ARM: return *CreateARMCXXABI(CGM); + case CXXABI_Itanium: return *CreateItaniumCXXABI(CGM); + case CXXABI_Microsoft: return *CreateMicrosoftCXXABI(CGM); + } + + llvm_unreachable("invalid C++ ABI kind"); + return *CreateItaniumCXXABI(CGM); +} + CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, llvm::Module &M, const llvm::TargetData &TD, @@ -48,11 +60,15 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, : BlockModule(C, M, TD, Types, *this), Context(C), Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M), TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags), - Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()), - VTables(*this), Runtime(0), ABI(0), - CFConstantStringClassRef(0), - NSConstantStringClassRef(0), - VMContext(M.getContext()) { + ABI(createCXXABI(*this)), + Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI), + VTables(*this), Runtime(0), + CFConstantStringClassRef(0), NSConstantStringClassRef(0), + VMContext(M.getContext()), + NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0), + NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), + BlockObjectAssignDecl(0), BlockObjectDisposeDecl(0), + BlockObjectAssign(0), BlockObjectDispose(0){ if (!Features.ObjC1) Runtime = 0; @@ -63,17 +79,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, else Runtime = CreateMacObjCRuntime(*this); - if (!Features.CPlusPlus) - ABI = 0; - else createCXXABI(); - // If debug info generation is enabled, create the CGDebugInfo object. DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0; } CodeGenModule::~CodeGenModule() { delete Runtime; - delete ABI; + delete &ABI; delete DebugInfo; } @@ -86,13 +98,6 @@ void CodeGenModule::createObjCRuntime() { Runtime = CreateMacObjCRuntime(*this); } -void CodeGenModule::createCXXABI() { - if (Context.Target.getCXXABI() == "microsoft") - ABI = CreateMicrosoftCXXABI(*this); - else - ABI = CreateItaniumCXXABI(*this); -} - void CodeGenModule::Release() { EmitDeferred(); EmitCXXGlobalInitFunc(); @@ -141,17 +146,17 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type, LangOptions::VisibilityMode CodeGenModule::getDeclVisibilityMode(const Decl *D) const { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) - if (VD->getStorageClass() == VarDecl::PrivateExtern) + if (VD->getStorageClass() == SC_PrivateExtern) return LangOptions::Hidden; if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) { switch (attr->getVisibility()) { default: assert(0 && "Unknown visibility!"); - case VisibilityAttr::DefaultVisibility: + case VisibilityAttr::Default: return LangOptions::Default; - case VisibilityAttr::HiddenVisibility: + case VisibilityAttr::Hidden: return LangOptions::Hidden; - case VisibilityAttr::ProtectedVisibility: + case VisibilityAttr::Protected: return LangOptions::Protected; } } @@ -187,9 +192,11 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const { return LangOptions::Hidden; } - // This decl should have the same visibility as its parent. + // If this decl is contained in a class, it should have the same visibility + // as the parent class. if (const DeclContext *DC = D->getDeclContext()) - return getDeclVisibilityMode(cast<Decl>(DC)); + if (DC->isRecord()) + return getDeclVisibilityMode(cast<Decl>(DC)); return getLangOptions().getVisibilityMode(); } @@ -213,6 +220,67 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, } } +/// Set the symbol visibility of type information (vtable and RTTI) +/// associated with the given type. +void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV, + const CXXRecordDecl *RD, + bool IsForRTTI) const { + setGlobalVisibility(GV, RD); + + if (!CodeGenOpts.HiddenWeakVTables) + return; + + // We want to drop the visibility to hidden for weak type symbols. + // This isn't possible if there might be unresolved references + // elsewhere that rely on this symbol being visible. + + // This should be kept roughly in sync with setThunkVisibility + // in CGVTables.cpp. + + // Preconditions. + if (GV->getLinkage() != llvm::GlobalVariable::WeakODRLinkage || + GV->getVisibility() != llvm::GlobalVariable::DefaultVisibility) + return; + + // Don't override an explicit visibility attribute. + if (RD->hasAttr<VisibilityAttr>()) + return; + + switch (RD->getTemplateSpecializationKind()) { + // We have to disable the optimization if this is an EI definition + // because there might be EI declarations in other shared objects. + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitInstantiationDeclaration: + return; + + // Every use of a non-template class's type information has to emit it. + case TSK_Undeclared: + break; + + // In theory, implicit instantiations can ignore the possibility of + // an explicit instantiation declaration because there necessarily + // must be an EI definition somewhere with default visibility. In + // practice, it's possible to have an explicit instantiation for + // an arbitrary template class, and linkers aren't necessarily able + // to deal with mixed-visibility symbols. + case TSK_ExplicitSpecialization: + case TSK_ImplicitInstantiation: + if (!CodeGenOpts.HiddenWeakTemplateVTables) + return; + break; + } + + // If there's a key function, there may be translation units + // that don't have the key function's definition. But ignore + // this if we're emitting RTTI under -fno-rtti. + if (!IsForRTTI || Features.RTTI) + if (Context.getKeyFunction(RD)) + return; + + // Otherwise, drop the visibility to hidden. + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); +} + llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) { const NamedDecl *ND = cast<NamedDecl>(GD.getDecl()); @@ -220,7 +288,7 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) { if (!Str.empty()) return Str; - if (!getMangleContext().shouldMangleDeclName(ND)) { + if (!getCXXABI().getMangleContext().shouldMangleDeclName(ND)) { IdentifierInfo *II = ND->getIdentifier(); assert(II && "Attempt to mangle unnamed decl."); @@ -230,13 +298,13 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) { llvm::SmallString<256> Buffer; if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND)) - getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer); + getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer); else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND)) - getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer); + getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer); else if (const BlockDecl *BD = dyn_cast<BlockDecl>(ND)) - getMangleContext().mangleBlock(GD, BD, Buffer); + getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer); else - getMangleContext().mangleName(ND, Buffer); + getCXXABI().getMangleContext().mangleName(ND, Buffer); // Allocate space for the mangled name. size_t Length = Buffer.size(); @@ -250,7 +318,7 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) { void CodeGenModule::getMangledName(GlobalDecl GD, MangleBuffer &Buffer, const BlockDecl *BD) { - getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer()); + getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer()); } llvm::GlobalValue *CodeGenModule::GetGlobalValue(llvm::StringRef Name) { @@ -319,68 +387,9 @@ void CodeGenModule::EmitAnnotations() { gv->setSection("llvm.metadata"); } -static CodeGenModule::GVALinkage -GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD, - const LangOptions &Features) { - CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal; - - Linkage L = FD->getLinkage(); - if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus && - FD->getType()->getLinkage() == UniqueExternalLinkage) - L = UniqueExternalLinkage; - - switch (L) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: - return CodeGenModule::GVA_Internal; - - case ExternalLinkage: - switch (FD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - External = CodeGenModule::GVA_StrongExternal; - break; - - case TSK_ExplicitInstantiationDefinition: - return CodeGenModule::GVA_ExplicitTemplateInstantiation; - - case TSK_ExplicitInstantiationDeclaration: - case TSK_ImplicitInstantiation: - External = CodeGenModule::GVA_TemplateInstantiation; - break; - } - } - - if (!FD->isInlined()) - return External; - - if (!Features.CPlusPlus || FD->hasAttr<GNUInlineAttr>()) { - // GNU or C99 inline semantics. Determine whether this symbol should be - // externally visible. - if (FD->isInlineDefinitionExternallyVisible()) - return External; - - // C99 inline semantics, where the symbol is not externally visible. - return CodeGenModule::GVA_C99Inline; - } - - // C++0x [temp.explicit]p9: - // [ Note: The intent is that an inline function that is the subject of - // an explicit instantiation declaration will still be implicitly - // instantiated when used so that the body can be considered for - // inlining, but that no out-of-line copy of the inline function would be - // generated in the translation unit. -- end note ] - if (FD->getTemplateSpecializationKind() - == TSK_ExplicitInstantiationDeclaration) - return CodeGenModule::GVA_C99Inline; - - return CodeGenModule::GVA_CXXInline; -} - llvm::GlobalValue::LinkageTypes CodeGenModule::getFunctionLinkage(const FunctionDecl *D) { - GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features); + GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); if (Linkage == GVA_Internal) return llvm::Function::InternalLinkage; @@ -454,12 +463,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, else if (Features.getStackProtectorMode() == LangOptions::SSPReq) F->addFnAttr(llvm::Attribute::StackProtectReq); - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) { - unsigned width = Context.Target.getCharWidth(); - F->setAlignment(AA->getAlignment() / width); - while ((AA = AA->getNext<AlignedAttr>())) - F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width)); - } + unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); + if (alignment) + F->setAlignment(alignment); + // C++ ABI requires 2-byte alignment for member functions. if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D)) F->setAlignment(2); @@ -638,102 +645,12 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, return llvm::ConstantStruct::get(VMContext, Fields, 4, false); } -static CodeGenModule::GVALinkage -GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) { - // If this is a static data member, compute the kind of template - // specialization. Otherwise, this variable is not part of a - // template. - TemplateSpecializationKind TSK = TSK_Undeclared; - if (VD->isStaticDataMember()) - TSK = VD->getTemplateSpecializationKind(); - - Linkage L = VD->getLinkage(); - if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus && - VD->getType()->getLinkage() == UniqueExternalLinkage) - L = UniqueExternalLinkage; - - switch (L) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: - return CodeGenModule::GVA_Internal; - - case ExternalLinkage: - switch (TSK) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - return CodeGenModule::GVA_StrongExternal; - - case TSK_ExplicitInstantiationDeclaration: - llvm_unreachable("Variable should not be instantiated"); - // Fall through to treat this like any other instantiation. - - case TSK_ExplicitInstantiationDefinition: - return CodeGenModule::GVA_ExplicitTemplateInstantiation; - - case TSK_ImplicitInstantiation: - return CodeGenModule::GVA_TemplateInstantiation; - } - } - - return CodeGenModule::GVA_StrongExternal; -} - bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { - // Never defer when EmitAllDecls is specified or the decl has - // attribute used. - if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>()) - return false; - - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) { - // Constructors and destructors should never be deferred. - if (FD->hasAttr<ConstructorAttr>() || - FD->hasAttr<DestructorAttr>()) - return false; - - // The key function for a class must never be deferred. - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Global)) { - const CXXRecordDecl *RD = MD->getParent(); - if (MD->isOutOfLine() && RD->isDynamicClass()) { - const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD); - if (KeyFunction && - KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl()) - return false; - } - } - - GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features); - - // static, static inline, always_inline, and extern inline functions can - // always be deferred. Normal inline functions can be deferred in C99/C++. - // Implicit template instantiations can also be deferred in C++. - if (Linkage == GVA_Internal || Linkage == GVA_C99Inline || - Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) - return true; + // Never defer when EmitAllDecls is specified. + if (Features.EmitAllDecls) return false; - } - const VarDecl *VD = cast<VarDecl>(Global); - assert(VD->isFileVarDecl() && "Invalid decl"); - - // We never want to defer structs that have non-trivial constructors or - // destructors. - - // FIXME: Handle references. - if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - if (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()) - return false; - } - } - - GVALinkage L = GetLinkageForVariable(getContext(), VD); - if (L == GVA_Internal || L == GVA_TemplateInstantiation) { - if (!(VD->getInit() && VD->getInit()->HasSideEffects(Context))) - return true; - } - - return false; + return !getContext().DeclMustBeEmitted(Global); } llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) { @@ -774,6 +691,15 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Ignore declarations, they will be emitted on their first use. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) { + if (FD->getIdentifier()) { + llvm::StringRef Name = FD->getName(); + if (Name == "_Block_object_assign") { + BlockObjectAssignDecl = FD; + } else if (Name == "_Block_object_dispose") { + BlockObjectDisposeDecl = FD; + } + } + // Forward declarations are emitted lazily on first use. if (!FD->isThisDeclarationADefinition()) return; @@ -781,6 +707,16 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { const VarDecl *VD = cast<VarDecl>(Global); assert(VD->isFileVarDecl() && "Cannot emit local var decl as global."); + if (VD->getIdentifier()) { + llvm::StringRef Name = VD->getName(); + if (Name == "_NSConcreteGlobalBlock") { + NSConcreteGlobalBlockDecl = VD; + } else if (Name == "_NSConcreteStackBlock") { + NSConcreteStackBlockDecl = VD; + } + } + + if (VD->isThisDeclarationADefinition() != VarDecl::Definition) return; } @@ -792,6 +728,14 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { EmitGlobalDefinition(GD); return; } + + // If we're deferring emission of a C++ variable with an + // initializer, remember the order in which it appeared in the file. + if (getLangOptions().CPlusPlus && isa<VarDecl>(Global) && + cast<VarDecl>(Global)->hasInit()) { + DelayedCXXInitPosition[Global] = CXXGlobalInits.size(); + CXXGlobalInits.push_back(0); + } // If the value has already been used, add it directly to the // DeferredDeclsToEmit list. @@ -816,7 +760,8 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // At -O0, don't generate IR for functions with available_externally // linkage. - if (CodeGenOpts.OptimizationLevel == 0 && + if (CodeGenOpts.OptimizationLevel == 0 && + !Function->hasAttr<AlwaysInlineAttr>() && getFunctionLinkage(Function) == llvm::Function::AvailableExternallyLinkage) return; @@ -1021,7 +966,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(llvm::StringRef MangledName, GV->setConstant(DeclIsConstantGlobal(Context, D)); // FIXME: Merge with other attribute handling code. - if (D->getStorageClass() == VarDecl::PrivateExtern) + if (D->getStorageClass() == SC_PrivateExtern) GV->setVisibility(llvm::GlobalValue::HiddenVisibility); if (D->hasAttr<WeakAttr>() || @@ -1174,6 +1119,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { ErrorUnsupported(D, "static initializer"); Init = llvm::UndefValue::get(getTypes().ConvertType(T)); } + } else { + // We don't need an initializer, so remove the entry for the delayed + // initializer position (just in case this entry was delayed). + if (getLangOptions().CPlusPlus) + DelayedCXXInitPosition.erase(D); } } @@ -1235,7 +1185,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); // Set the llvm linkage type as appropriate. - GVALinkage Linkage = GetLinkageForVariable(getContext(), D); + GVALinkage Linkage = getContext().GetGVALinkageForVariable(D); if (Linkage == GVA_Internal) GV->setLinkage(llvm::Function::InternalLinkage); else if (D->hasAttr<DLLImportAttr>()) @@ -1254,7 +1204,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); else if (!getLangOptions().CPlusPlus && !CodeGenOpts.NoCommon && !D->hasExternalStorage() && !D->getInit() && - !D->getAttr<SectionAttr>()) { + !D->getAttr<SectionAttr>() && !D->isThreadSpecified()) { + // Thread local vars aren't considered common linkage. GV->setLinkage(llvm::GlobalVariable::CommonLinkage); // common vars aren't constant even if declared const. GV->setConstant(false); @@ -1293,6 +1244,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, // TODO: Do invokes ever occur in C code? If so, we should handle them too. llvm::Value::use_iterator I = UI++; // Increment before the CI is erased. llvm::CallInst *CI = dyn_cast<llvm::CallInst>(*I); + if (!CI) continue; // FIXME: when we allow Invoke, just do CallSite CS(*I) llvm::CallSite CS(CI); if (!CI || !CS.isCallee(I)) continue; @@ -1343,7 +1295,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl()); const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD); - getMangleContext().mangleInitDiscriminator(); + getCXXABI().getMangleContext().mangleInitDiscriminator(); // Get or create the prototype for the function. llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); @@ -1528,18 +1480,18 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map, bool TargetIsLSB, bool &IsUTF16, unsigned &StringLength) { - unsigned NumBytes = Literal->getByteLength(); + llvm::StringRef String = Literal->getString(); + unsigned NumBytes = String.size(); // Check for simple case. if (!Literal->containsNonAsciiOrNull()) { StringLength = NumBytes; - return Map.GetOrCreateValue(llvm::StringRef(Literal->getStrData(), - StringLength)); + return Map.GetOrCreateValue(String); } // Otherwise, convert the UTF8 literals into a byte string. llvm::SmallVector<UTF16, 128> ToBuf(NumBytes); - const UTF8 *FromPtr = (UTF8 *)Literal->getStrData(); + const UTF8 *FromPtr = (UTF8 *)String.data(); UTF16 *ToPtr = &ToBuf[0]; ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, @@ -1552,8 +1504,7 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map, // this duplicate code. assert(Result == sourceIllegal && "UTF-8 to UTF-16 conversion failed"); StringLength = NumBytes; - return Map.GetOrCreateValue(llvm::StringRef(Literal->getStrData(), - StringLength)); + return Map.GetOrCreateValue(String); } // ConvertUTF8toUTF16 returns the length in ToPtr. @@ -1753,20 +1704,17 @@ CodeGenModule::GetAddrOfConstantNSString(const StringLiteral *Literal) { /// GetStringForStringLiteral - Return the appropriate bytes for a /// string literal, properly padded to match the literal type. std::string CodeGenModule::GetStringForStringLiteral(const StringLiteral *E) { - const char *StrData = E->getStrData(); - unsigned Len = E->getByteLength(); - const ConstantArrayType *CAT = getContext().getAsConstantArrayType(E->getType()); assert(CAT && "String isn't pointer or array!"); // Resize the string to the right size. - std::string Str(StrData, StrData+Len); uint64_t RealLen = CAT->getSize().getZExtValue(); if (E->isWide()) RealLen *= getContext().Target.getWCharWidth()/8; + std::string Str = E->getString().str(); Str.resize(RealLen, '\0'); return Str; @@ -1894,7 +1842,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { D->getLocation(), D->getLocation(), cxxSelector, getContext().VoidTy, 0, - DC, true, false, true, + DC, true, false, true, false, ObjCMethodDecl::Required); D->addInstanceMethod(DTORMethod); CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false); @@ -1906,7 +1854,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { D->getLocation(), D->getLocation(), cxxSelector, getContext().getObjCIdType(), 0, - DC, true, false, true, + DC, true, false, true, false, ObjCMethodDecl::Required); D->addInstanceMethod(CTORMethod); CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true); @@ -1993,9 +1941,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Forward declarations, no (immediate) code generation. case Decl::ObjCClass: case Decl::ObjCForwardProtocol: - case Decl::ObjCCategory: case Decl::ObjCInterface: break; + + case Decl::ObjCCategory: { + ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); + if (CD->IsClassExtension() && CD->hasSynthBitfield()) + Context.ResetObjCLayout(CD->getClassInterface()); + break; + } + case Decl::ObjCProtocol: Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D)); @@ -2009,6 +1964,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::ObjCImplementation: { ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D); + if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield()) + Context.ResetObjCLayout(OMD->getClassInterface()); EmitObjCPropertyImplementations(OMD); EmitObjCIvarInitializations(OMD); Runtime->GenerateClass(OMD); @@ -2118,3 +2075,88 @@ void CodeGenFunction::EmitDeclMetadata() { } } } + +///@name Custom Runtime Function Interfaces +///@{ +// +// FIXME: These can be eliminated once we can have clients just get the required +// AST nodes from the builtin tables. + +llvm::Constant *CodeGenModule::getBlockObjectDispose() { + if (BlockObjectDispose) + return BlockObjectDispose; + + // If we saw an explicit decl, use that. + if (BlockObjectDisposeDecl) { + return BlockObjectDispose = GetAddrOfFunction( + BlockObjectDisposeDecl, + getTypes().GetFunctionType(BlockObjectDisposeDecl)); + } + + // Otherwise construct the function by hand. + const llvm::FunctionType *FTy; + std::vector<const llvm::Type*> ArgTys; + const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); + ArgTys.push_back(PtrToInt8Ty); + ArgTys.push_back(llvm::Type::getInt32Ty(VMContext)); + FTy = llvm::FunctionType::get(ResultType, ArgTys, false); + return BlockObjectDispose = + CreateRuntimeFunction(FTy, "_Block_object_dispose"); +} + +llvm::Constant *CodeGenModule::getBlockObjectAssign() { + if (BlockObjectAssign) + return BlockObjectAssign; + + // If we saw an explicit decl, use that. + if (BlockObjectAssignDecl) { + return BlockObjectAssign = GetAddrOfFunction( + BlockObjectAssignDecl, + getTypes().GetFunctionType(BlockObjectAssignDecl)); + } + + // Otherwise construct the function by hand. + const llvm::FunctionType *FTy; + std::vector<const llvm::Type*> ArgTys; + const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); + ArgTys.push_back(PtrToInt8Ty); + ArgTys.push_back(PtrToInt8Ty); + ArgTys.push_back(llvm::Type::getInt32Ty(VMContext)); + FTy = llvm::FunctionType::get(ResultType, ArgTys, false); + return BlockObjectAssign = + CreateRuntimeFunction(FTy, "_Block_object_assign"); +} + +llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { + if (NSConcreteGlobalBlock) + return NSConcreteGlobalBlock; + + // If we saw an explicit decl, use that. + if (NSConcreteGlobalBlockDecl) { + return NSConcreteGlobalBlock = GetAddrOfGlobalVar( + NSConcreteGlobalBlockDecl, + getTypes().ConvertType(NSConcreteGlobalBlockDecl->getType())); + } + + // Otherwise construct the variable by hand. + return NSConcreteGlobalBlock = CreateRuntimeVariable( + PtrToInt8Ty, "_NSConcreteGlobalBlock"); +} + +llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { + if (NSConcreteStackBlock) + return NSConcreteStackBlock; + + // If we saw an explicit decl, use that. + if (NSConcreteStackBlockDecl) { + return NSConcreteStackBlock = GetAddrOfGlobalVar( + NSConcreteStackBlockDecl, + getTypes().ConvertType(NSConcreteStackBlockDecl->getType())); + } + + // Otherwise construct the variable by hand. + return NSConcreteStackBlock = CreateRuntimeVariable( + PtrToInt8Ty, "_NSConcreteStackBlock"); +} + +///@} |