169 changes: 114 additions & 55 deletions clang/unittests/CodeGen/TBAAMetadataTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@
//===----------------------------------------------------------------------===//

#include "IRMatchers.h"
#include "TestCompiler.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Parse/ParseAST.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
#include <memory>
Expand All @@ -21,17 +27,82 @@ using namespace llvm;

namespace {

struct TBAATestCompiler : public TestCompiler {
TBAATestCompiler(clang::LangOptions LO, clang::CodeGenOptions CGO)
: TestCompiler(LO, CGO) {}
static clang::CodeGenOptions getCommonCodeGenOpts() {
clang::CodeGenOptions CGOpts;
CGOpts.StructPathTBAA = 1;
CGOpts.OptimizationLevel = 1;
return CGOpts;
struct TestCompiler {
LLVMContext Context;
clang::CompilerInstance compiler;
clang::CodeGenerator *CG = nullptr;
llvm::Module *M = nullptr;
unsigned PtrSize = 0;

void init(const char *TestProgram) {
compiler.createDiagnostics();
compiler.getCodeGenOpts().StructPathTBAA = 1;
compiler.getCodeGenOpts().OptimizationLevel = 1;

std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple());
llvm::Triple Tr(TrStr);
Tr.setOS(Triple::Linux);
Tr.setVendor(Triple::VendorType::UnknownVendor);
Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment);
compiler.getTargetOpts().Triple = Tr.getTriple();
compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
compiler.getDiagnostics(),
std::make_shared<clang::TargetOptions>(compiler.getTargetOpts())));

const clang::TargetInfo &TInfo = compiler.getTarget();
PtrSize = TInfo.getPointerWidth(0) / 8;

compiler.createFileManager();
compiler.createSourceManager(compiler.getFileManager());
compiler.createPreprocessor(clang::TU_Prefix);

compiler.createASTContext();

CG = CreateLLVMCodeGen(
compiler.getDiagnostics(),
"main-module",
compiler.getHeaderSearchOpts(),
compiler.getPreprocessorOpts(),
compiler.getCodeGenOpts(),
Context);
compiler.setASTConsumer(std::unique_ptr<clang::ASTConsumer>(CG));

compiler.createSema(clang::TU_Prefix, nullptr);

clang::SourceManager &sm = compiler.getSourceManager();
sm.setMainFileID(sm.createFileID(
llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User));
}

const BasicBlock *compile() {
clang::ParseAST(compiler.getSema(), false, false);
M = CG->GetModule();

// Do not expect more than one function definition.
auto FuncPtr = M->begin();
for (; FuncPtr != M->end(); ++FuncPtr)
if (!FuncPtr->isDeclaration())
break;
assert(FuncPtr != M->end());
const llvm::Function &Func = *FuncPtr;
++FuncPtr;
for (; FuncPtr != M->end(); ++FuncPtr)
if (!FuncPtr->isDeclaration())
break;
assert(FuncPtr == M->end());

// The function must consist of single basic block.
auto BBPtr = Func.begin();
assert(Func.begin() != Func.end());
const BasicBlock &BB = *BBPtr;
++BBPtr;
assert(BBPtr == Func.end());

return &BB;
}
};


auto OmnipotentCharC = MMTuple(
MMString("omnipotent char"),
MMTuple(
Expand Down Expand Up @@ -61,8 +132,8 @@ TEST(TBAAMetadataTest, BasicTypes) {
}
)**";

clang::LangOptions LO;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().C11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -157,9 +228,8 @@ TEST(TBAAMetadataTest, CFields) {
}
)**";

clang::LangOptions LO;
LO.C11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().C11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -279,9 +349,8 @@ TEST(TBAAMetadataTest, CTypedefFields) {
}
)**";

clang::LangOptions LO;
LO.C11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().C11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -372,9 +441,8 @@ TEST(TBAAMetadataTest, CTypedefFields2) {
}
)**";

clang::LangOptions LO;
LO.C11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().C11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -466,9 +534,8 @@ TEST(TBAAMetadataTest, CTypedefFields3) {
}
)**";

clang::LangOptions LO;
LO.C11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().C11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -568,10 +635,9 @@ TEST(TBAAMetadataTest, CXXFields) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -691,10 +757,9 @@ TEST(TBAAMetadataTest, CXXTypedefFields) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -792,10 +857,9 @@ TEST(TBAAMetadataTest, StructureFields) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -874,10 +938,9 @@ TEST(TBAAMetadataTest, ArrayFields) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -953,10 +1016,9 @@ TEST(TBAAMetadataTest, BaseClass) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -1032,10 +1094,9 @@ TEST(TBAAMetadataTest, PolymorphicClass) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -1109,10 +1170,9 @@ TEST(TBAAMetadataTest, VirtualBase) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down Expand Up @@ -1195,10 +1255,9 @@ TEST(TBAAMetadataTest, TemplSpec) {
}
)**";

clang::LangOptions LO;
LO.CPlusPlus = 1;
LO.CPlusPlus11 = 1;
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
TestCompiler Compiler;
Compiler.compiler.getLangOpts().CPlusPlus = 1;
Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
Compiler.init(TestProgram);
const BasicBlock *BB = Compiler.compile();

Expand Down
112 changes: 0 additions & 112 deletions clang/unittests/CodeGen/TestCompiler.h

This file was deleted.

25 changes: 18 additions & 7 deletions compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1122,27 +1122,35 @@ static void *init_cond(void *c, bool force = false) {
return (void*)cond;
}

namespace {
struct CondMutexUnlockCtx {
ScopedInterceptor *si;
ThreadState *thr;
uptr pc;
void *m;
void *c;
void *t;
int (*fn)(void *c, void *m, void *abstime);

int Cancel() const { return fn(c, m, t); }
void Unlock() const;
};

static void cond_mutex_unlock(CondMutexUnlockCtx *arg) {
void CondMutexUnlockCtx::Unlock() const {
// pthread_cond_wait interceptor has enabled async signal delivery
// (see BlockingCall below). Disable async signals since we are running
// tsan code. Also ScopedInterceptor and BlockingCall destructors won't run
// since the thread is cancelled, so we have to manually execute them
// (the thread still can run some user code due to pthread_cleanup_push).
ThreadSignalContext *ctx = SigCtx(arg->thr);
ThreadSignalContext *ctx = SigCtx(thr);
CHECK_EQ(atomic_load(&ctx->in_blocking_func, memory_order_relaxed), 1);
atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
MutexPostLock(arg->thr, arg->pc, (uptr)arg->m, MutexFlagDoPreLockOnPostLock);
MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
// Undo BlockingCall ctor effects.
arg->thr->ignore_interceptors--;
arg->si->~ScopedInterceptor();
thr->ignore_interceptors--;
si->~ScopedInterceptor();
}
} // namespace

INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
void *cond = init_cond(c, true);
Expand All @@ -1156,15 +1164,18 @@ static int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si,
void *m, void *t) {
MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
MutexUnlock(thr, pc, (uptr)m);
CondMutexUnlockCtx arg = {si, thr, pc, m};
CondMutexUnlockCtx arg = {si, thr, pc, m, c, t, fn};
int res = 0;
// This ensures that we handle mutex lock even in case of pthread_cancel.
// See test/tsan/cond_cancel.cpp.
{
// Enable signal delivery while the thread is blocked.
BlockingCall bc(thr);
res = call_pthread_cancel_with_cleanup(
fn, c, m, t, (void (*)(void *arg))cond_mutex_unlock, &arg);
[](void *arg) -> int {
return ((const CondMutexUnlockCtx *)arg)->Cancel();
},
[](void *arg) { ((const CondMutexUnlockCtx *)arg)->Unlock(); }, &arg);
}
if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m);
MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
Expand Down
5 changes: 2 additions & 3 deletions compiler-rt/lib/tsan/rtl/tsan_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -1040,9 +1040,8 @@ int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
uptr ExtractLongJmpSp(uptr *env);
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size);

int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
void *abstime), void *c, void *m, void *abstime,
void(*cleanup)(void *arg), void *arg);
int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
void (*cleanup)(void *arg), void *arg);

void DestroyThreadState();
void PlatformCleanUpThreadState(ThreadState *thr);
Expand Down
7 changes: 3 additions & 4 deletions compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,14 +443,13 @@ void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {

// Note: this function runs with async signals enabled,
// so it must not touch any tsan state.
int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
void *abstime), void *c, void *m, void *abstime,
void(*cleanup)(void *arg), void *arg) {
int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
void (*cleanup)(void *arg), void *arg) {
// pthread_cleanup_push/pop are hardcore macros mess.
// We can't intercept nor call them w/o including pthread.h.
int res;
pthread_cleanup_push(cleanup, arg);
res = fn(c, m, abstime);
res = fn(arg);
pthread_cleanup_pop(0);
return res;
}
Expand Down
7 changes: 3 additions & 4 deletions compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,13 @@ void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
#if !SANITIZER_GO
// Note: this function runs with async signals enabled,
// so it must not touch any tsan state.
int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
void *abstime), void *c, void *m, void *abstime,
void(*cleanup)(void *arg), void *arg) {
int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
void (*cleanup)(void *arg), void *arg) {
// pthread_cleanup_push/pop are hardcore macros mess.
// We can't intercept nor call them w/o including pthread.h.
int res;
pthread_cleanup_push(cleanup, arg);
res = fn(c, m, abstime);
res = fn(arg);
pthread_cleanup_pop(0);
return res;
}
Expand Down