diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 64 |
1 files changed, 58 insertions, 6 deletions
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<FunctionDecl>(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<NamespaceDecl>(Result); + if (auto LSD = dyn_cast<LinkageSpecDecl>(Result)) + for (const auto &Result : LSD->lookup(&NS)) + if ((ND = dyn_cast<NamespaceDecl>(Result))) + break; + + if (ND) + for (const auto &Result : ND->lookup(&CXXII)) + if (const auto *FD = dyn_cast<FunctionDecl>(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<llvm::Function>(C)) - if (F->empty()) + /*DontDefer=*/false, /*IsThunk=*/false, + ExtraAttrs); + + if (auto *F = dyn_cast<llvm::Function>(C)) { + if (F->empty()) { F->setCallingConv(getRuntimeCC()); + + if (!Local && getTriple().isOSBinFormatCOFF() && + !getCodeGenOpts().LTOVisibilityPublicStd) { + const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name); + if (!FD || FD->hasAttr<DLLImportAttr>()) { + F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); + F->setLinkage(llvm::GlobalValue::ExternalLinkage); + } + } + } + } + return C; } |