[clang] [llvm] [flang] [Flang][WIP/RFC] Enable TSan for Flang (PR #74643)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 6 11:02:50 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-driver
Author: Joachim (jprotze)
<details>
<summary>Changes</summary>
This patch enables ThreadSanitizer analysis for Fortran codes compiled with Flang. The patch is marked as WIP/RFC since it is at the moment a prove of concept.
Open questions from our side:
- Is it the right place to run the ThreadSanitizer pass?
- The ThreadSanitizer pass assumes the ThreadSanitizer attribute on each function to be instrumented. Clang adds this attribute during the CodeGen, if no (no)ThreadSanitizer is already attached to the function and if the function is not blacklisted. For this PoC we simply disabled the check for the attribute. We see different options for an actual solution:
- run a separate pass before the TSan pass that adds the attribute to all functions while considering the blacklist
- add a new flag to the TSan pass to skip the check and set the flag when the TSan pass is launched from Flang
- What is the best way to pass through all the different Sanitizer flags?
---
Full diff: https://github.com/llvm/llvm-project/pull/74643.diff
7 Files Affected:
- (modified) clang/include/clang/Driver/Options.td (+4-4)
- (modified) clang/lib/Driver/ToolChains/Flang.cpp (+1)
- (modified) flang/include/flang/Common/Fortran-features.h (+2-1)
- (modified) flang/lib/Frontend/CompilerInvocation.cpp (+4)
- (modified) flang/lib/Frontend/FrontendActions.cpp (+8)
- (modified) flang/lib/Optimizer/CodeGen/CMakeLists.txt (+4)
- (modified) llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp (+1-1)
``````````diff
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0eec2b3526376..2fcc31495cdb5 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2163,14 +2163,14 @@ def fmemory_profile_use_EQ : Joined<["-"], "fmemory-profile-use=">,
HelpText<"Use memory profile for profile-guided memory optimization">,
MarshallingInfoString<CodeGenOpts<"MemoryProfileUsePath">>;
+def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
+ MetaVarName<"<check>">, 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 Visibility = [ClangOption, CC1Option, CLOption] in {
-def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
- MetaVarName<"<check>">,
- 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<f_clang_Group>,
Visibility<[ClangOption, CLOption]>;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 9b21fe952af7a..7d433455f24cc 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -38,6 +38,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 a6b19e9833fc5..d3d4556b9cdbf 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, NullActualForAllocatable,
ActualIntegerConvertedToSmallerKind, HollerithOrCharacterAsBOZ,
@@ -65,6 +65,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 c623969a21e5e..6b3c0706c9273 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -862,6 +862,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 1be95cc27f42c..423e121cdf3dc 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -67,6 +67,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 <memory>
#include <system_error>
@@ -1073,6 +1076,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 0daa97b00dfa0..2d48c873ff4a1 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 8ee0bca7e354f..bd720634e467e 100644
--- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -511,7 +511,7 @@ bool ThreadSanitizer::sanitizeFunction(Function &F,
SmallVector<Instruction*, 8> 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.
``````````
</details>
https://github.com/llvm/llvm-project/pull/74643
More information about the cfe-commits
mailing list