[llvm] r351314 - [NewPM][TSan] Reiterate the TSan port
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 16 10:35:02 PST 2019
I think there's a typo in the new header you added (should say
ThreadSanitizer instead of MemorySanitizer).
Thanks,
--
Davide
On Wed, Jan 16, 2019 at 1:31 AM Philip Pfaffe via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: pfaffe
> Date: Wed Jan 16 01:28:01 2019
> New Revision: 351314
>
> URL: http://llvm.org/viewvc/llvm-project?rev=351314&view=rev
> Log:
> [NewPM][TSan] Reiterate the TSan port
>
> Summary:
> Second iteration of D56433 which got reverted in rL350719. The problem
> in the previous version was that we dropped the thunk calling the tsan init
> function. The new version keeps the thunk which should appease dyld, but is not
> actually OK wrt. the current semantics of function passes. Hence, add a
> helper to insert the functions only on the first time. The helper
> allows hooking into the insertion to be able to append them to the
> global ctors list.
>
> Reviewers: chandlerc, vitalybuka, fedor.sergeev, leonardchan
>
> Subscribers: hiraditya, bollu, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D56538
>
> Added:
> llvm/trunk/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h
> Modified:
> llvm/trunk/bindings/go/llvm/InstrumentationBindings.cpp
> llvm/trunk/include/llvm/InitializePasses.h
> llvm/trunk/include/llvm/Transforms/Instrumentation.h
> llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h
> llvm/trunk/lib/Passes/PassBuilder.cpp
> llvm/trunk/lib/Passes/PassRegistry.def
> llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp
> llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
> llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp
> llvm/trunk/test/Instrumentation/ThreadSanitizer/tsan_basic.ll
>
> Modified: llvm/trunk/bindings/go/llvm/InstrumentationBindings.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/bindings/go/llvm/InstrumentationBindings.cpp?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/bindings/go/llvm/InstrumentationBindings.cpp (original)
> +++ llvm/trunk/bindings/go/llvm/InstrumentationBindings.cpp Wed Jan 16 01:28:01 2019
> @@ -17,6 +17,7 @@
> #include "llvm/IR/Module.h"
> #include "llvm/Transforms/Instrumentation.h"
> #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
> +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
>
> using namespace llvm;
>
> @@ -29,7 +30,7 @@ void LLVMAddAddressSanitizerModulePass(L
> }
>
> void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM) {
> - unwrap(PM)->add(createThreadSanitizerPass());
> + unwrap(PM)->add(createThreadSanitizerLegacyPassPass());
> }
>
> void LLVMAddMemorySanitizerLegacyPassPass(LLVMPassManagerRef PM) {
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Wed Jan 16 01:28:01 2019
> @@ -392,7 +392,7 @@ void initializeTailDuplicatePass(PassReg
> void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);
> void initializeTargetPassConfigPass(PassRegistry&);
> void initializeTargetTransformInfoWrapperPassPass(PassRegistry&);
> -void initializeThreadSanitizerPass(PassRegistry&);
> +void initializeThreadSanitizerLegacyPassPass(PassRegistry&);
> void initializeTwoAddressInstructionPassPass(PassRegistry&);
> void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
> void initializeUnifyFunctionExitNodesPass(PassRegistry&);
>
> Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Wed Jan 16 01:28:01 2019
> @@ -155,9 +155,6 @@ ModulePass *createAddressSanitizerModule
> FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false,
> bool Recover = false);
>
> -// Insert ThreadSanitizer (race detection) instrumentation
> -FunctionPass *createThreadSanitizerPass();
> -
> // Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
> ModulePass *createDataFlowSanitizerPass(
> const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
>
> Added: llvm/trunk/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h?rev=351314&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h (added)
> +++ llvm/trunk/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h Wed Jan 16 01:28:01 2019
> @@ -0,0 +1,33 @@
> +//===- Transforms/Instrumentation/MemorySanitizer.h - TSan Pass -----------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file defines the thread sanitizer pass.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H
> +#define LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H
> +
> +#include "llvm/IR/PassManager.h"
> +#include "llvm/Pass.h"
> +
> +namespace llvm {
> +// Insert ThreadSanitizer (race detection) instrumentation
> +FunctionPass *createThreadSanitizerLegacyPassPass();
> +
> +/// A function pass for tsan instrumentation.
> +///
> +/// Instruments functions to detect race conditions reads. This function pass
> +/// inserts calls to runtime library functions. If the functions aren't declared
> +/// yet, the pass inserts the declarations. Otherwise the existing globals are
> +struct ThreadSanitizerPass : public PassInfoMixin<ThreadSanitizerPass> {
> + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
> +};
> +} // namespace llvm
> +#endif /* LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H */
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h Wed Jan 16 01:28:01 2019
> @@ -58,6 +58,19 @@ std::pair<Function *, Function *> create
> ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
> StringRef VersionCheckName = StringRef());
>
> +/// Creates sanitizer constructor function lazily. If a constructor and init
> +/// function already exist, this function returns it. Otherwise it calls \c
> +/// createSanitizerCtorAndInitFunctions. The FunctionsCreatedCallback is invoked
> +/// in that case, passing the new Ctor and Init function.
> +///
> +/// \return Returns pair of pointers to constructor, and init functions
> +/// respectively.
> +std::pair<Function *, Function *> getOrCreateSanitizerCtorAndInitFunctions(
> + Module &M, StringRef CtorName, StringRef InitName,
> + ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
> + function_ref<void(Function *, Function *)> FunctionsCreatedCallback,
> + StringRef VersionCheckName = StringRef());
> +
> // Creates and returns a sanitizer init function without argument if it doesn't
> // exist, and adds it to the global constructors list. Otherwise it returns the
> // existing function.
>
> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Wed Jan 16 01:28:01 2019
> @@ -95,6 +95,7 @@
> #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
> #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
> #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
> +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
> #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
> #include "llvm/Transforms/Scalar/ADCE.h"
> #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
>
> Modified: llvm/trunk/lib/Passes/PassRegistry.def
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassRegistry.def (original)
> +++ llvm/trunk/lib/Passes/PassRegistry.def Wed Jan 16 01:28:01 2019
> @@ -232,6 +232,7 @@ FUNCTION_PASS("view-cfg", CFGViewerPass(
> FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
> FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
> FUNCTION_PASS("msan", MemorySanitizerPass())
> +FUNCTION_PASS("tsan", ThreadSanitizerPass())
> #undef FUNCTION_PASS
>
> #ifndef FUNCTION_PASS_WITH_PARAMS
>
> Modified: llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp (original)
> +++ llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp Wed Jan 16 01:28:01 2019
> @@ -113,7 +113,7 @@ void llvm::initializeInstrumentation(Pas
> initializeInstrProfilingLegacyPassPass(Registry);
> initializeMemorySanitizerLegacyPassPass(Registry);
> initializeHWAddressSanitizerPass(Registry);
> - initializeThreadSanitizerPass(Registry);
> + initializeThreadSanitizerLegacyPassPass(Registry);
> initializeSanitizerCoverageModulePass(Registry);
> initializeDataFlowSanitizerPass(Registry);
> initializeEfficiencySanitizerPass(Registry);
>
> Modified: llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp (original)
> +++ llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp Wed Jan 16 01:28:01 2019
> @@ -19,6 +19,7 @@
> // The rest is handled by the run-time library.
> //===----------------------------------------------------------------------===//
>
> +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/SmallString.h"
> #include "llvm/ADT/SmallVector.h"
> @@ -86,15 +87,16 @@ static const char *const kTsanInitName =
> namespace {
>
> /// ThreadSanitizer: instrument the code in module to find races.
> -struct ThreadSanitizer : public FunctionPass {
> - ThreadSanitizer() : FunctionPass(ID) {}
> - StringRef getPassName() const override;
> - void getAnalysisUsage(AnalysisUsage &AU) const override;
> - bool runOnFunction(Function &F) override;
> - bool doInitialization(Module &M) override;
> - static char ID; // Pass identification, replacement for typeid.
> +///
> +/// Instantiating ThreadSanitizer inserts the tsan runtime library API function
> +/// declarations into the module if they don't exist already. Instantiating
> +/// ensures the __tsan_init function is in the list of global constructors for
> +/// the module.
> +struct ThreadSanitizer {
> + ThreadSanitizer(Module &M);
> + bool sanitizeFunction(Function &F, const TargetLibraryInfo &TLI);
>
> - private:
> +private:
> void initializeCallbacks(Module &M);
> bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
> bool instrumentAtomic(Instruction *I, const DataLayout &DL);
> @@ -130,27 +132,55 @@ struct ThreadSanitizer : public Function
> Function *MemmoveFn, *MemcpyFn, *MemsetFn;
> Function *TsanCtorFunction;
> };
> +
> +struct ThreadSanitizerLegacyPass : FunctionPass {
> + ThreadSanitizerLegacyPass() : FunctionPass(ID) {}
> + StringRef getPassName() const override;
> + void getAnalysisUsage(AnalysisUsage &AU) const override;
> + bool runOnFunction(Function &F) override;
> + bool doInitialization(Module &M) override;
> + static char ID; // Pass identification, replacement for typeid.
> +private:
> + Optional<ThreadSanitizer> TSan;
> +};
> } // namespace
>
> -char ThreadSanitizer::ID = 0;
> -INITIALIZE_PASS_BEGIN(
> - ThreadSanitizer, "tsan",
> - "ThreadSanitizer: detects data races.",
> - false, false)
> +PreservedAnalyses ThreadSanitizerPass::run(Function &F,
> + FunctionAnalysisManager &FAM) {
> + ThreadSanitizer TSan(*F.getParent());
> + if (TSan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F)))
> + return PreservedAnalyses::none();
> + return PreservedAnalyses::all();
> +}
> +
> +char ThreadSanitizerLegacyPass::ID = 0;
> +INITIALIZE_PASS_BEGIN(ThreadSanitizerLegacyPass, "tsan",
> + "ThreadSanitizer: detects data races.", false, false)
> INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
> -INITIALIZE_PASS_END(
> - ThreadSanitizer, "tsan",
> - "ThreadSanitizer: detects data races.",
> - false, false)
> +INITIALIZE_PASS_END(ThreadSanitizerLegacyPass, "tsan",
> + "ThreadSanitizer: detects data races.", false, false)
>
> -StringRef ThreadSanitizer::getPassName() const { return "ThreadSanitizer"; }
> +StringRef ThreadSanitizerLegacyPass::getPassName() const {
> + return "ThreadSanitizerLegacyPass";
> +}
>
> -void ThreadSanitizer::getAnalysisUsage(AnalysisUsage &AU) const {
> +void ThreadSanitizerLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
> AU.addRequired<TargetLibraryInfoWrapperPass>();
> }
>
> -FunctionPass *llvm::createThreadSanitizerPass() {
> - return new ThreadSanitizer();
> +bool ThreadSanitizerLegacyPass::doInitialization(Module &M) {
> + TSan.emplace(M);
> + return true;
> +}
> +
> +bool ThreadSanitizerLegacyPass::runOnFunction(Function &F) {
> + auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
> + TSan->sanitizeFunction(F, TLI);
> + return true;
> +}
> +
> +FunctionPass *llvm::createThreadSanitizerLegacyPassPass() {
> + return new ThreadSanitizerLegacyPass();
> }
>
> void ThreadSanitizer::initializeCallbacks(Module &M) {
> @@ -252,16 +282,16 @@ void ThreadSanitizer::initializeCallback
> IRB.getInt32Ty(), IntptrTy));
> }
>
> -bool ThreadSanitizer::doInitialization(Module &M) {
> +ThreadSanitizer::ThreadSanitizer(Module &M) {
> const DataLayout &DL = M.getDataLayout();
> IntptrTy = DL.getIntPtrType(M.getContext());
> - std::tie(TsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions(
> - M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{},
> - /*InitArgs=*/{});
> -
> - appendToGlobalCtors(M, TsanCtorFunction, 0);
> -
> - return true;
> + std::tie(TsanCtorFunction, std::ignore) =
> + getOrCreateSanitizerCtorAndInitFunctions(
> + M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{},
> + /*InitArgs=*/{},
> + // This callback is invoked when the functions are created the first
> + // time. Hook them into the global ctors list in that case:
> + [&](Function *Ctor, Function *) { appendToGlobalCtors(M, Ctor, 0); });
> }
>
> static bool isVtableAccess(Instruction *I) {
> @@ -402,7 +432,8 @@ void ThreadSanitizer::InsertRuntimeIgnor
> }
> }
>
> -bool ThreadSanitizer::runOnFunction(Function &F) {
> +bool ThreadSanitizer::sanitizeFunction(Function &F,
> + const TargetLibraryInfo &TLI) {
> // This is required to prevent instrumenting call to __tsan_init from within
> // the module constructor.
> if (&F == TsanCtorFunction)
> @@ -416,8 +447,6 @@ bool ThreadSanitizer::runOnFunction(Func
> bool HasCalls = false;
> bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread);
> const DataLayout &DL = F.getParent()->getDataLayout();
> - const TargetLibraryInfo *TLI =
> - &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
>
> // Traverse all instructions, collect loads/stores/returns, check for calls.
> for (auto &BB : F) {
> @@ -428,7 +457,7 @@ bool ThreadSanitizer::runOnFunction(Func
> LocalLoadsAndStores.push_back(&Inst);
> else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
> if (CallInst *CI = dyn_cast<CallInst>(&Inst))
> - maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI);
> + maybeMarkSanitizerLibraryCallNoBuiltin(CI, &TLI);
> if (isa<MemIntrinsic>(Inst))
> MemIntrinCalls.push_back(&Inst);
> HasCalls = true;
>
> Modified: llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp Wed Jan 16 01:28:01 2019
> @@ -174,6 +174,28 @@ std::pair<Function *, Function *> llvm::
> return std::make_pair(Ctor, InitFunction);
> }
>
> +std::pair<Function *, Function *>
> +llvm::getOrCreateSanitizerCtorAndInitFunctions(
> + Module &M, StringRef CtorName, StringRef InitName,
> + ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
> + function_ref<void(Function *, Function *)> FunctionsCreatedCallback,
> + StringRef VersionCheckName) {
> + assert(!CtorName.empty() && "Expected ctor function name");
> +
> + if (Function *Ctor = M.getFunction(CtorName))
> + // FIXME: Sink this logic into the module, similar to the handling of
> + // globals. This will make moving to a concurrent model much easier.
> + if (Ctor->arg_size() == 0 ||
> + Ctor->getReturnType() == Type::getVoidTy(M.getContext()))
> + return {Ctor, declareSanitizerInitFunction(M, InitName, InitArgTypes)};
> +
> + Function *Ctor, *InitFunction;
> + std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions(
> + M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName);
> + FunctionsCreatedCallback(Ctor, InitFunction);
> + return std::make_pair(Ctor, InitFunction);
> +}
> +
> Function *llvm::getOrCreateInitFunction(Module &M, StringRef Name) {
> assert(!Name.empty() && "Expected init function name");
> if (Function *F = M.getFunction(Name)) {
>
> Modified: llvm/trunk/test/Instrumentation/ThreadSanitizer/tsan_basic.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/ThreadSanitizer/tsan_basic.ll?rev=351314&r1=351313&r2=351314&view=diff
> ==============================================================================
> --- llvm/trunk/test/Instrumentation/ThreadSanitizer/tsan_basic.ll (original)
> +++ llvm/trunk/test/Instrumentation/ThreadSanitizer/tsan_basic.ll Wed Jan 16 01:28:01 2019
> @@ -1,4 +1,5 @@
> ; RUN: opt < %s -tsan -S | FileCheck %s
> +; RUN: opt < %s -passes=tsan -S | FileCheck %s
>
> target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
> target triple = "x86_64-unknown-linux-gnu"
> @@ -77,6 +78,5 @@ define void @SwiftErrorCall(i8** swifter
> call void @SwiftError(i8** %0)
> ret void
> }
> -
> ; CHECK: define internal void @tsan.module_ctor()
> ; CHECK: call void @__tsan_init()
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
--
Davide
"There are no solved problems; there are only problems that are more
or less solved" -- Henri Poincare
More information about the llvm-commits
mailing list