diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 37e8c56b2d295..a5d034eacd6ac 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1786,14 +1786,14 @@ def fmemory_profile_use_EQ : Joined<["-"], "fmemory-profile-use=">, HelpText<"Use memory profile for profile-guided memory optimization">, MarshallingInfoString>; +def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group, + MetaVarName<"">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, + HelpText<"Turn on runtime checks for various forms of undefined " + "or suspicious behavior. See user manual for available checks">; // Begin sanitizer flags. These should all be core options exposed in all driver // modes. let Flags = [CC1Option, CoreOption] in { -def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group, - MetaVarName<"">, - HelpText<"Turn on runtime checks for various forms of undefined " - "or suspicious behavior. See user manual for available checks">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group, Flags<[CoreOption, NoXarchOption]>; diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index bdc75f51b7a28..22ebf38dc4161 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -36,6 +36,7 @@ void Flang::addFortranDialectOptions(const ArgList &Args, options::OPT_fopenmp, options::OPT_fopenmp_version_EQ, options::OPT_fopenacc, + options::OPT_fsanitize_EQ, options::OPT_finput_charset_EQ, options::OPT_fimplicit_none, options::OPT_fno_implicit_none, diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h index 5cbe1d6e157f2..1959cd1a0bd78 100644 --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -35,7 +35,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines, ProgramReturn, ImplicitNoneTypeNever, ImplicitNoneTypeAlways, ForwardRefImplicitNone, OpenAccessAppend, BOZAsDefaultInteger, DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat, - SaveMainProgram, SaveBigMainProgramVariables, + SaveMainProgram, SaveBigMainProgramVariables, TSan, DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking, ForwardRefImplicitNoneData) @@ -56,6 +56,7 @@ class LanguageFeatureControl { disable_.set(LanguageFeature::OldDebugLines); disable_.set(LanguageFeature::OpenACC); disable_.set(LanguageFeature::OpenMP); + disable_.set(LanguageFeature::TSan); disable_.set(LanguageFeature::CUDA); // !@cuf disable_.set(LanguageFeature::ImplicitNoneTypeNever); disable_.set(LanguageFeature::ImplicitNoneTypeAlways); diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index b1f0d27a925ed..6d422ba22ffda 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -726,6 +726,10 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, res.getFrontendOpts().features.Enable( Fortran::common::LanguageFeature::OpenACC); } + if (args.hasArg(clang::driver::options::OPT_fsanitize_EQ) && llvm::StringRef(args.getLastArg(clang::driver::options::OPT_fsanitize_EQ)->getValue()) == "thread" ) { + res.getFrontendOpts().features.Enable( + Fortran::common::LanguageFeature::TSan); + } if (args.hasArg(clang::driver::options::OPT_fopenmp)) { // By default OpenMP is set to 1.1 version res.getLangOpts().OpenMPVersion = 11; diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 0154fd29bf810..cab3dbaf872b7 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -63,6 +63,9 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/TargetParser/TargetParser.h" #include "llvm/Transforms/Utils/ModuleUtils.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" + #include #include @@ -913,6 +916,11 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { else mpm = pb.buildPerModuleDefaultPipeline(level); + if (this->getInstance().getInvocation().getFrontendOpts().features.IsEnabled( + Fortran::common::LanguageFeature::TSan)) { + mpm.addPass(llvm::ModuleThreadSanitizerPass()); + mpm.addPass(llvm::createModuleToFunctionPassAdaptor(llvm::ThreadSanitizerPass())); + } if (action == BackendActionTy::Backend_EmitBC) mpm.addPass(llvm::BitcodeWriterPass(os)); diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt index 0b2e3943c1068..63d73c04a972a 100644 --- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt +++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt @@ -1,3 +1,7 @@ +set(LLVM_LINK_COMPONENTS + Instrumentation +) + add_flang_library(FIRCodeGen BoxedProcedure.cpp CGOps.cpp diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp index ce35eefb63fa2..8fa51a9ad64f0 100644 --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -516,7 +516,7 @@ bool ThreadSanitizer::sanitizeFunction(Function &F, SmallVector MemIntrinCalls; bool Res = false; bool HasCalls = false; - bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread); + bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread) || true; const DataLayout &DL = F.getParent()->getDataLayout(); // Traverse all instructions, collect loads/stores/returns, check for calls.