https://github.com/jprotze created 
https://github.com/llvm/llvm-project/pull/74643

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?

>From d04b05a69025c33aae027c07eda2c0c51b0b9426 Mon Sep 17 00:00:00 2001
From: Joachim Jenke <je...@itc.rwth-aachen.de>
Date: Tue, 14 Nov 2023 13:54:41 +0100
Subject: [PATCH 1/3] Initial Flang+TSan tests

---
 flang/lib/Frontend/FrontendActions.cpp                  | 5 +++++
 flang/lib/Optimizer/CodeGen/CMakeLists.txt              | 4 ++++
 llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp | 2 +-
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Frontend/FrontendActions.cpp 
b/flang/lib/Frontend/FrontendActions.cpp
index 1be95cc27f42c..ffbd7eaac6ea9 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,8 @@ void 
CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
   else
     mpm = pb.buildPerModuleDefaultPipeline(level);
 
+  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.

>From 4dbbd7de3b0788665282e8ff3e7f79c46320da4c Mon Sep 17 00:00:00 2001
From: Joachim Jenke <je...@itc.rwth-aachen.de>
Date: Wed, 15 Nov 2023 15:47:26 +0100
Subject: [PATCH 2/3] Propagate Tsan flag to fc1 and apply Tsan pass
 conditionally

---
 clang/include/clang/Driver/Options.td         | 8 ++++----
 clang/lib/Driver/ToolChains/Flang.cpp         | 1 +
 flang/include/flang/Common/Fortran-features.h | 3 ++-
 flang/lib/Frontend/CompilerInvocation.cpp     | 4 ++++
 flang/lib/Frontend/FrontendActions.cpp        | 7 +++++--
 5 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 0eec2b3526376..b99fe4e4a24f4 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, 
CLOption, 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 ffbd7eaac6ea9..423e121cdf3dc 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -1076,8 +1076,11 @@ void 
CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
   else
     mpm = pb.buildPerModuleDefaultPipeline(level);
 
-  mpm.addPass(llvm::ModuleThreadSanitizerPass());
-  
mpm.addPass(llvm::createModuleToFunctionPassAdaptor(llvm::ThreadSanitizerPass()));
+  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));
 

>From 03c22524ecf8851951d37f6282b3cd43edb8607e Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tom...@itc.rwth-aachen.de>
Date: Wed, 6 Dec 2023 18:23:18 +0100
Subject: [PATCH 3/3] Fix fsanitize option not known to clang

---
 clang/include/clang/Driver/Options.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index b99fe4e4a24f4..2fcc31495cdb5 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2164,7 +2164,7 @@ def fmemory_profile_use_EQ : Joined<["-"], 
"fmemory-profile-use=">,
     MarshallingInfoString<CodeGenOpts<"MemoryProfileUsePath">>;
 
 def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
-                   MetaVarName<"<check>">, Visibility<[ClangOption, CC1Option, 
CLOption, FlangOption, FC1Option]>,
+                   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

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to