Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Windows: Return current thread’s _Init_thread_epoch from __emutls_get…
…_address. Fixes function level static variables.
  • Loading branch information
marsupial authored and Axel-Naumann committed Jul 6, 2017
commit a96d2b3fc9c973b9003dcb09f2f88bf444a1434d
12 changes: 12 additions & 0 deletions interpreter/cling/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@

using namespace clang;

extern "C" void* __emutls_get_address(struct __emutls_control*);

namespace {

// Forward cxa_atexit for global d'tors.
Expand Down Expand Up @@ -267,6 +269,16 @@ namespace cling {
}
}
}
#ifdef LLVM_ON_WIN32
// FIXME: Using emulated TLS LLVM doesn't respect external TLS data.
// By passing itself as the argument to __emutls_get_address, it can
// return a pointer to the current thread's _Init_thread_epoch.
// This obviously handles only one case, and would need to be rethought
// to properly support extern __declspec(thread), though hopefully that
// construct is dubious enough to never be used .
m_Executor->addSymbol("__emutls_v._Init_thread_epoch",
utils::FunctionToVoidPtr(&__emutls_get_address), true);
#endif
}

// Disable suggestions for ROOT
Expand Down
8 changes: 8 additions & 0 deletions interpreter/cling/lib/Utils/EmuTLS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,14 @@ emutls_get_address_array(uintptr_t index) {
}

extern "C" void* __emutls_get_address(__emutls_control* control) {
#ifdef _WIN32
// FIXME: Using emulated TLS LLVM doesn't respect external TLS data.
// To get arround this Interpreter::Initialize binds
// "__emutls_v._Init_thread_epoch" to &__emutls_get_address to mark that
// the current thread's _Init_thread_epoch should be returned.
if (reinterpret_cast<void*>(control) == cling::utils::FunctionToVoidPtr(&__emutls_get_address))
return &_Init_thread_epoch;
#endif
uintptr_t index = emutls_get_index(control);
emutls_address_array* array = emutls_get_address_array(index--);
if (array->data[index] == NULL)
Expand Down
40 changes: 33 additions & 7 deletions interpreter/cling/test/CodeGeneration/TLSVars.C
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling -Xclang -verify | FileCheck %s
// RUN: cat %s | %cling -Xclang -verify 2>&1 | FileCheck %s

// Test whether the TLS data is properly handled

Expand All @@ -17,10 +17,10 @@
#include <stdlib.h>

thread_local unsigned int TLSCounter = 1;
std::mutex WriteMutex;
// std::mutex WriteMutex;

static void WriteValue(const char* Name, unsigned Val) {
std::lock_guard<std::mutex> Lock(WriteMutex);
// std::lock_guard<std::mutex> Lock(WriteMutex);
printf("TLSCounter for '%s' : %u\n", Name, Val);
}

Expand All @@ -45,10 +45,36 @@ WriteValue("main", TLSCounter);


// CHECK: TLSCounter for 'A' : 2
// CHECK: TLSCounter for 'B' : 2
// CHECK: TLSCounter for '10' : 12
// CHECK: TLSCounter for '5' : 7
// CHECK: TLSCounter for 'main' : 1
// CHECK-NEXT: TLSCounter for 'B' : 2
// CHECK-NEXT: TLSCounter for '10' : 12
// CHECK-NEXT: TLSCounter for '5' : 7
// CHECK-NEXT: TLSCounter for 'main' : 1

// Below is predominately for Windows
struct TERD {
const char *Name;
TERD(const char *N) : Name(N) { printf("TERD::TERD::%s\n", Name); }
~TERD() { printf("TERD::~TERD::%s\n", Name); }
};
static TERD& inst01() {
static TERD st01("inst01");
return st01;
}
static TERD& inst02() {
static TERD st02("inst02");
return st02;
}

inst01();
// CHECK-NEXT: TERD::TERD::inst01
std::thread(&inst01).join();

std::thread(&inst02).join();
// CHECK-NEXT: TERD::TERD::inst02
inst02();

// expected-no-diagnostics
.q

// CHECK-NEXT: TERD::~TERD::inst02
// CHECK-NEXT: TERD::~TERD::inst01