CodeGen: Don't drop thread_local when emitting __thread aliases

CodeGen wouldn't mark the aliasee as thread_local if the aliasee was a
tentative definition.

Even if the definition was already emitted, it would never mark the
alias as thread_local.

This fixes PR21288.

llvm-svn: 219859
This commit is contained in:
David Majnemer 2014-10-15 22:38:23 +00:00
parent 0b15e34bd1
commit bb525f7c20
3 changed files with 23 additions and 10 deletions

View File

@ -523,11 +523,10 @@ static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(
llvm_unreachable("Invalid TLS model!");
}
void CodeGenModule::setTLSMode(llvm::GlobalVariable *GV,
const VarDecl &D) const {
void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const {
assert(D.getTLSKind() && "setting TLS mode on non-TLS var!");
llvm::GlobalVariable::ThreadLocalMode TLM;
llvm::GlobalValue::ThreadLocalMode TLM;
TLM = GetLLVMTLSModel(CodeGenOpts.getDefaultTLSModel());
// Override the TLS model if it is explicitly specified.
@ -1942,10 +1941,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// has internal linkage; all accesses should just be calls to the
// Itanium-specified entry point, which has the normal linkage of the
// variable.
if (const auto *VD = dyn_cast<VarDecl>(D))
if (!VD->isStaticLocal() && VD->getTLSKind() == VarDecl::TLS_Dynamic &&
Context.getTargetInfo().getTriple().isMacOSX())
Linkage = llvm::GlobalValue::InternalLinkage;
if (!D->isStaticLocal() && D->getTLSKind() == VarDecl::TLS_Dynamic &&
Context.getTargetInfo().getTriple().isMacOSX())
Linkage = llvm::GlobalValue::InternalLinkage;
GV->setLinkage(Linkage);
if (D->hasAttr<DLLImportAttr>())
@ -1959,6 +1957,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
setNonAliasAttributes(D, GV);
if (D->getTLSKind() && !GV->isThreadLocal()) {
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
CXXThreadLocals.push_back(std::make_pair(D, GV));
setTLSMode(GV, *D);
}
// Emit the initializer function if necessary.
if (NeedsGlobalCtor || NeedsGlobalDtor)
EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
@ -2326,7 +2330,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
else
Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
llvm::PointerType::getUnqual(DeclTy),
nullptr);
/*D=*/nullptr);
// Create the new alias itself, but don't set a name yet.
auto *GA = llvm::GlobalAlias::create(
@ -2365,6 +2369,10 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
GA->setLinkage(llvm::Function::WeakAnyLinkage);
}
if (const auto *VD = dyn_cast<VarDecl>(D))
if (VD->getTLSKind())
setTLSMode(GA, *VD);
setAliasAttributes(D, GA);
}

View File

@ -652,9 +652,9 @@ public:
/// Set the visibility for the given LLVM GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
/// Set the TLS mode for the given LLVM GlobalVariable for the thread-local
/// Set the TLS mode for the given LLVM GlobalValue for the thread-local
/// variable declaration D.
void setTLSMode(llvm::GlobalVariable *GV, const VarDecl &D) const;
void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const;
static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V) {
switch (V) {

View File

@ -3,6 +3,8 @@
int g0;
// CHECKBASIC: @g0 = common global i32 0
__thread int TL_WITH_ALIAS;
// CHECKBASIC-DAG: @TL_WITH_ALIAS = thread_local global i32 0, align 4
static int bar1 = 42;
// CHECKBASIC: @bar1 = internal global i32 42
@ -10,6 +12,9 @@ extern int g1;
extern int g1 __attribute((alias("g0")));
// CHECKBASIC-DAG: @g1 = alias i32* @g0
extern __thread int __libc_errno __attribute__ ((alias ("TL_WITH_ALIAS")));
// CHECKBASIC-DAG: @__libc_errno = thread_local alias i32* @TL_WITH_ALIAS
void f0(void) { }
extern void f1(void);
extern void f1(void) __attribute((alias("f0")));