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();
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,
// 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
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;
}
}
/// 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,
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()) {
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();
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) {
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) {
FTy, "_Init_thread_abort",
llvm::AttributeSet::get(CGM.getLLVMContext(),
llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind));
+ llvm::Attribute::NoUnwind),
+ /*Local=*/true);
}
namespace {
--- /dev/null
+// 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()
+