diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 64 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 12 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/runtime-dllstorage.cpp | 158 |
8 files changed, 238 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index eb5d481bb7a..8d9d0b21bfe 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -237,7 +237,8 @@ void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD, llvm::FunctionType::get(IntTy, dtorStub->getType(), false); llvm::Constant *atexit = - CGM.CreateRuntimeFunction(atexitTy, "atexit"); + CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeSet(), + /*Local=*/true); if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit)) atexitFn->setDoesNotThrow(); diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index d155df6d4cf..7b7880e07a9 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -221,10 +221,9 @@ const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) { static llvm::Constant *getPersonalityFn(CodeGenModule &CGM, const EHPersonality &Personality) { - llvm::Constant *Fn = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true), - Personality.PersonalityFn); - return Fn; + return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true), + Personality.PersonalityFn, + llvm::AttributeSet(), /*Local=*/true); } static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM, diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 9aa952d82bb..932b8a129e6 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1811,7 +1811,8 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM, // If the target runtime doesn't naturally support ARC, emit weak // references to the runtime support library. We don't really // permit this to fail, but we need a particular relocation style. - if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC()) { + if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC() && + !CGM.getTriple().isOSBinFormatCOFF()) { f->setLinkage(llvm::Function::ExternalWeakLinkage); } else if (fnName == "objc_retain" || fnName == "objc_release") { // If we have Native ARC, set nonlazybind attribute for these APIs for 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; } diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index be45bb8ea44..d4c096ed67b 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -876,10 +876,11 @@ public: } /// Create a new runtime function with the specified type and name. - llvm::Constant *CreateRuntimeFunction(llvm::FunctionType *Ty, - StringRef Name, - llvm::AttributeSet ExtraAttrs = - llvm::AttributeSet()); + llvm::Constant * + CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, + llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(), + bool Local = false); + /// Create a new compiler builtin function with the specified type and name. llvm::Constant *CreateBuiltinFunction(llvm::FunctionType *Ty, StringRef Name, diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 963b1403f5b..26c486af120 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3899,7 +3899,8 @@ static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) { llvm::FunctionType *fnTy = llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); llvm::Constant *fnRef = - CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate"); + CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate", + llvm::AttributeSet(), /*Local=*/true); llvm::Function *fn = dyn_cast<llvm::Function>(fnRef); if (fn && fn->empty()) { diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index eb40a45c80d..1576483770a 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2204,7 +2204,8 @@ static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, CGF.IntTy, DtorStub->getType(), /*IsVarArg=*/false); llvm::Constant *TLRegDtor = - CGF.CGM.CreateRuntimeFunction(TLRegDtorTy, "__tlregdtor"); + CGF.CGM.CreateRuntimeFunction(TLRegDtorTy, "__tlregdtor", + llvm::AttributeSet(), /*Local=*/true); if (llvm::Function *TLRegDtorFn = dyn_cast<llvm::Function>(TLRegDtor)) TLRegDtorFn->setDoesNotThrow(); @@ -2302,7 +2303,8 @@ static llvm::Constant *getInitThreadHeaderFn(CodeGenModule &CGM) { FTy, "_Init_thread_header", llvm::AttributeSet::get(CGM.getLLVMContext(), llvm::AttributeSet::FunctionIndex, - llvm::Attribute::NoUnwind)); + llvm::Attribute::NoUnwind), + /*Local=*/true); } static llvm::Constant *getInitThreadFooterFn(CodeGenModule &CGM) { @@ -2313,7 +2315,8 @@ static llvm::Constant *getInitThreadFooterFn(CodeGenModule &CGM) { FTy, "_Init_thread_footer", llvm::AttributeSet::get(CGM.getLLVMContext(), llvm::AttributeSet::FunctionIndex, - llvm::Attribute::NoUnwind)); + llvm::Attribute::NoUnwind), + /*Local=*/true); } static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) { @@ -2324,7 +2327,8 @@ static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) { FTy, "_Init_thread_abort", llvm::AttributeSet::get(CGM.getLLVMContext(), llvm::AttributeSet::FunctionIndex, - llvm::Attribute::NoUnwind)); + llvm::Attribute::NoUnwind), + /*Local=*/true); } namespace { diff --git a/clang/test/CodeGenCXX/runtime-dllstorage.cpp b/clang/test/CodeGenCXX/runtime-dllstorage.cpp new file mode 100644 index 00000000000..76c002c0e40 --- /dev/null +++ b/clang/test/CodeGenCXX/runtime-dllstorage.cpp @@ -0,0 +1,158 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-DYNAMIC +// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-STATIC + +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-NODECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-NODECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IMPORT-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IMPORT-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-DECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-DECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IA-ATEXIT +// %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IA-ATEXIT + +// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA +// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA +// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA +// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA + +#if defined(IMPORT_DECLARATIONS) +namespace __cxxabiv1 { +extern "C" { +__declspec(dllimport) void __cxa_guard_acquire(unsigned long long *); +__declspec(dllimport) unsigned char *__cxa_allocate_exception(unsigned long); +} +extern "C" __declspec(dllimport) void __cxa_guard_release(unsigned long long *); +} +namespace std { +__declspec(dllimport) __declspec(noreturn) void terminate(); +} +#elif defined(EXPORT_DECLARATIONS) +namespace __cxxabiv1 { +extern "C" { +__declspec(dllexport) void __cxa_guard_acquire(unsigned long long *); +__declspec(dllexport) unsigned char *__cxa_allocate_exception(unsigned long); +} +extern "C" void __declspec(dllexport) __cxa_guard_release(unsigned long long *); +} +namespace std { +__declspec(dllexport) __declspec(noreturn) void terminate(); +} +#elif defined(DECL) +namespace __cxxabiv1 { +extern "C" unsigned char *__cxa_allocate_exception(unsigned long); +} +namespace std { +__declspec(noreturn) void terminate(); +} +#else +namespace std { +__declspec(noreturn) void terminate(); +} +#endif + +struct s { + s() = default; + s(unsigned char) { throw 0; } + int m() const; +}; + +struct t { + ~t(); + int m() const; +}; + +struct u { + ~u(); +}; + +s o; +thread_local t t; +u v; +__declspec(thread) s q; + +void __declspec(noinline) f() { + throw 0; +} + +void g(); +void __declspec(noinline) h() { + try { + g(); + } catch (const int &) { + return; + } catch (...) { + throw; + } +} + +void i() { + s r(static_cast<unsigned char>('\t')); +} + +int j() { + static thread_local struct t v; + static struct t *w = new struct t; + return w->m() ? v.m() : w->m(); +} + +void k() noexcept { + g(); +} + +void l() { + std::terminate(); +} + +// CHECK-MS-DAG: @_Init_thread_epoch = external thread_local global i32 +// CHECK-MS-DAG: declare i32 @__tlregdtor(void ()*) +// CHECK-MS-DAG: declare i32 @atexit(void ()*) +// CHECK-MS-DYNAMIC-DAG: declare dllimport {{.*}} void @_CxxThrowException +// CHECK-MS-STATIC-DAG: declare {{.*}} void @_CxxThrowException +// CHECK-MS-DAG: declare noalias i8* @"\01??2@YAPAXI@Z" +// CHECK-MS-DAG: declare void @_Init_thread_header(i32*) +// CHECK-MS-DAG: declare void @_Init_thread_footer(i32*) + +// CHECK-IA-DAG: declare i32 @__gxx_personality_v0(...) +// CHECK-IA-DAG: define linkonce_odr hidden void @__clang_call_terminate(i8*) + +// CHECK-DYNAMIC-IA-DAG: declare dllimport i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// CHECK-DYNAMIC-IA-DAG: declare dllimport i32 @__cxa_atexit(void (i8*)*, i8*, i8*) +// CHECK-DYNAMIC-IA-DECL-DAG: declare i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-NODECL-DAG: declare dllimport i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-IMPORT-DAG: declare dllimport i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-EXPORT-DAG: declare dllimport i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-DAG: declare dllimport void @__cxa_throw(i8*, i8*, i8*) +// CHECK-DYNAMIC-DECL-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*) +// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*) +// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*) +// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllexport i32 @__cxa_guard_acquire(i64*) +// CHECK-IA-DAG: declare noalias i8* @_Znwj(i32) +// CHECK-DYNAMIC-DECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYANMIC-IA-DAG: declare dllimport void @_ZSt9terminatev() +// CHECK-DYNAMIC-NODECL-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @_ZSt9terminatev() +// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllexport void @_ZSt9terminatev() + +// CHECK-STATIC-IA-DAG: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// CHECK-STATIC-IA-DAG: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) +// CHECK-STATIC-IA-DAG: declare i8* @__cxa_allocate_exception(i32) +// CHECK-STATIC-IA-DAG: declare void @__cxa_throw(i8*, i8*, i8*) +// CHECK-STATIC-DECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-STATIC-NODECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-STATIC-IMPORT-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-STATIC-EXPORT-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-IA-DAG: declare noalias i8* @_Znwj(i32) +// CHECK-STATIC-DECL-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-NODECL-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-IMPORT-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-EXPORT-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-STATIC-NODECL-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-STATIC-IMPORT-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-STATIC-EXPORT-IA-DAG: declare dllexport void @_ZSt9terminatev() + |