From 6cb074493420dcc1922e2a1d066806dae3051172 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 15 Dec 2016 06:59:05 +0000 Subject: CodeGen: fix runtime function dll storage Properly attribute DLL storage to runtime functions. When generating the runtime function, scan for an existing declaration which may provide an explicit declaration (local storage) or a DLL import or export storage from the user. Honour that if available. Otherwise, if building with a local visibility of the public or standard namespaces (-flto-visibility-public-std), give the symbols local storage (it indicates a /MT[d] link, so static runtime). Otherwise, assume that the link is dynamic, and give the runtime function dllimport storage. This allows for implementations to get the correct storage as long as they are properly declared, the user to override the import storage, and in case no explicit storage is given, use of the import storage. llvm-svn: 289776 --- clang/lib/CodeGen/CodeGenModule.cpp | 64 +++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 6 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 78f43bdef99..404cbae1d83 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2038,18 +2038,70 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, IsForDefinition); } +static const FunctionDecl * +GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) { + TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); + DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); + + IdentifierInfo &CII = C.Idents.get(Name); + for (const auto &Result : DC->lookup(&CII)) + if (const auto FD = dyn_cast(Result)) + return FD; + + if (!C.getLangOpts().CPlusPlus) + return nullptr; + + // Demangle the premangled name from getTerminateFn() + IdentifierInfo &CXXII = + (Name == "_ZSt9terminatev" || Name == "\01?terminate@@YAXXZ") + ? C.Idents.get("terminate") + : C.Idents.get(Name); + + for (const auto &N : {"__cxxabiv1", "std"}) { + IdentifierInfo &NS = C.Idents.get(N); + for (const auto &Result : DC->lookup(&NS)) { + NamespaceDecl *ND = dyn_cast(Result); + if (auto LSD = dyn_cast(Result)) + for (const auto &Result : LSD->lookup(&NS)) + if ((ND = dyn_cast(Result))) + break; + + if (ND) + for (const auto &Result : ND->lookup(&CXXII)) + if (const auto *FD = dyn_cast(Result)) + return FD; + } + } + + return nullptr; +} + /// CreateRuntimeFunction - Create a new runtime function with the specified /// type and name. llvm::Constant * -CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, - StringRef Name, - llvm::AttributeSet ExtraAttrs) { +CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, + llvm::AttributeSet ExtraAttrs, + bool Local) { llvm::Constant *C = GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false, - /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs); - if (auto *F = dyn_cast(C)) - if (F->empty()) + /*DontDefer=*/false, /*IsThunk=*/false, + ExtraAttrs); + + if (auto *F = dyn_cast(C)) { + if (F->empty()) { F->setCallingConv(getRuntimeCC()); + + if (!Local && getTriple().isOSBinFormatCOFF() && + !getCodeGenOpts().LTOVisibilityPublicStd) { + const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name); + if (!FD || FD->hasAttr()) { + F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); + F->setLinkage(llvm::GlobalValue::ExternalLinkage); + } + } + } + } + return C; } -- cgit v1.2.3