From f6b4ce962458854e2b52cd77374a8f398d1becba Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Tue, 4 Jun 2024 05:35:39 +0800 Subject: [PATCH] [CIR][Pipeline] Support -fclangir-analysis-only (#638) Close https://github.com/llvm/clangir/issues/633. This patch introduces `-fclangir-analysis-only` option to allow the users to consume the AST to the CIR (and potential analysis passes, this can be done by specifying `-Xclang -fclangir-lifetime-check=""` now or some default value in following patches) and also generating the LLVM IR by the traditional code gen path. This will be helpful to use CIR with real world projects without worrying the correctness and completeness of CIR CodeGen part. --- .../clang/CIRFrontendAction/CIRGenAction.h | 3 +++ .../clang/CIRFrontendAction/CIRGenConsumer.h | 0 clang/include/clang/Driver/Options.td | 5 ++++ .../include/clang/Frontend/FrontendOptions.h | 7 +++++- clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 8 ++++++ clang/lib/CodeGen/CMakeLists.txt | 8 ++++++ clang/lib/CodeGen/CodeGenAction.cpp | 25 +++++++++++++++---- clang/lib/Driver/ToolChains/Clang.cpp | 9 +++++++ clang/lib/Frontend/CompilerInvocation.cpp | 4 +-- clang/test/CIR/CodeGen/analysis-only.cpp | 8 ++++++ .../CIR/Transforms/lifetime-check-agg.cpp | 1 + clang/test/CIR/analysis-only.cpp | 2 ++ 12 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 clang/include/clang/CIRFrontendAction/CIRGenConsumer.h create mode 100644 clang/test/CIR/CodeGen/analysis-only.cpp create mode 100644 clang/test/CIR/analysis-only.cpp diff --git a/clang/include/clang/CIRFrontendAction/CIRGenAction.h b/clang/include/clang/CIRFrontendAction/CIRGenAction.h index 74d5e5e32611..bcfca9bfcd89 100644 --- a/clang/include/clang/CIRFrontendAction/CIRGenAction.h +++ b/clang/include/clang/CIRFrontendAction/CIRGenAction.h @@ -120,6 +120,9 @@ class EmitObjAction : public CIRGenAction { EmitObjAction(mlir::MLIRContext *mlirCtx = nullptr); }; +std::unique_ptr +createCIRAnalysisOnlyConsumer(clang::CompilerInstance &); + } // namespace cir #endif diff --git a/clang/include/clang/CIRFrontendAction/CIRGenConsumer.h b/clang/include/clang/CIRFrontendAction/CIRGenConsumer.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index c6d5005d2c9d..2061d6ab1e8b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3062,6 +3062,11 @@ defm clangir_direct_lowering : BoolFOption<"clangir-direct-lowering", FrontendOpts<"ClangIRDirectLowering">, DefaultTrue, PosFlag, NegFlag>; +defm clangir_analysis_only : BoolFOption<"clangir-analysis-only", + FrontendOpts<"ClangIRAnalysisOnly">, DefaultFalse, + PosFlag, + NegFlag>; def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>, Group, HelpText<"Build ASTs and then lower to ClangIR, emit the .cir file">; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 5bff487c2068..5bcf873ff98f 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -451,6 +451,10 @@ class FrontendOptions { // Enable Clang IR call conv lowering pass. unsigned ClangIREnableCallConvLowering : 1; + // Enable Clang IR analysis only pipeline that uses tranditional code gen + // pipeline. + unsigned ClangIRAnalysisOnly : 1; + CodeCompleteOptions CodeCompleteOpts; /// Specifies the output format of the AST. @@ -650,7 +654,8 @@ class FrontendOptions { ClangIRDisablePasses(false), ClangIRDisableCIRVerifier(false), ClangIRDisableEmitCXXDefault(false), ClangIRLifetimeCheck(false), ClangIRIdiomRecognizer(false), ClangIRLibOpt(false), - TimeTraceGranularity(500), TimeTraceVerbose(false) {} + ClangIRAnalysisOnly(false), TimeTraceGranularity(500), + TimeTraceVerbose(false) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index ce412ff42f8f..682e9ded4efd 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -471,3 +471,11 @@ EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *_MLIRContext) void EmitObjAction::anchor() {} EmitObjAction::EmitObjAction(mlir::MLIRContext *_MLIRContext) : CIRGenAction(OutputType::EmitObj, _MLIRContext) {} + +std::unique_ptr +cir::createCIRAnalysisOnlyConsumer(clang::CompilerInstance &ci) { + return std::make_unique( + CIRGenAction::OutputType::None, ci.getDiagnostics(), + &ci.getVirtualFileSystem(), ci.getHeaderSearchOpts(), ci.getCodeGenOpts(), + ci.getTargetOpts(), ci.getLangOpts(), ci.getFrontendOpts(), nullptr); +} diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 868ec847b963..2327420ec673 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -54,6 +54,13 @@ if(MSVC AND NOT CMAKE_CXX_COMPILER_ID MATCHES Clang endif() endif() +set(conditional_link_libs) +if(CLANG_ENABLE_CIR) +list(APPEND conditional_link_libs + clangCIRFrontendAction + ) +endif() + add_clang_library(clangCodeGen ABIInfo.cpp ABIInfoImpl.cpp @@ -158,4 +165,5 @@ add_clang_library(clangCodeGen clangFrontend clangLex clangSerialization + ${conditional_link_libs} ) diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index c9f9b688d0d8..93836f4cabe5 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -21,6 +21,10 @@ #include "clang/Basic/LangStandard.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Config/config.h" +#if CLANG_ENABLE_CIR +#include "clang/CIRFrontendAction/CIRGenAction.h" +#endif #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Driver/DriverDiagnostic.h" @@ -1030,14 +1034,25 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); } + std::vector> AdditionalConsumers; + AdditionalConsumers.reserve(2); + if (CI.getFrontendOpts().GenReducedBMI && !CI.getFrontendOpts().ModuleOutputPath.empty()) { - std::vector> Consumers(2); - Consumers[0] = std::make_unique( + + AdditionalConsumers.push_back(std::make_unique( CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().ModuleOutputPath); - Consumers[1] = std::move(Result); - return std::make_unique(std::move(Consumers)); + CI.getFrontendOpts().ModuleOutputPath)); + } + +#if CLANG_ENABLE_CIR + if (CI.getFrontendOpts().ClangIRAnalysisOnly) + AdditionalConsumers.push_back(cir::createCIRAnalysisOnlyConsumer(CI)); +#endif + + if (!AdditionalConsumers.empty()) { + AdditionalConsumers.push_back(std::move(Result)); + return std::make_unique(std::move(AdditionalConsumers)); } return std::move(Result); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 99a5565b9e18..b8c094b13254 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5161,6 +5161,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fclangir-idiom-recognizer"); } + if (Args.hasArg(options::OPT_fclangir_analysis_only)) { + CmdArgs.push_back("-fclangir-analysis-only"); + + // TODO: We should pass some default analysis configuration here. + + // TODO2: Should we emit some diagnostics if the configurations conflict + // with each other? + } + if (IsOpenMPDevice) { // We have to pass the triple of the host if compiling for an OpenMP device. std::string NormalizedTriple = diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 8e0880f796d3..45bee654fc82 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3056,8 +3056,8 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (Args.hasArg(OPT_clangir_verify_diagnostics)) Opts.ClangIRVerifyDiags = true; - if (Args.hasArg(OPT_fclangir_call_conv_lowering)) - Opts.ClangIREnableCallConvLowering = true; + if (Args.hasArg(OPT_fclangir_analysis_only)) + Opts.ClangIRAnalysisOnly = true; if (const Arg *A = Args.getLastArg(OPT_fclangir_lifetime_check, OPT_fclangir_lifetime_check_EQ)) { diff --git a/clang/test/CIR/CodeGen/analysis-only.cpp b/clang/test/CIR/CodeGen/analysis-only.cpp new file mode 100644 index 000000000000..7f427f0de92f --- /dev/null +++ b/clang/test/CIR/CodeGen/analysis-only.cpp @@ -0,0 +1,8 @@ +// Check `-fclangir-analysis-only` would generate code correctly. +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir-analysis-only -std=c++20 \ +// RUN: -O2 -emit-llvm %s -o - | FileCheck %s + +extern "C" void foo() {} + +// CHECK: define{{.*}} @foo( + diff --git a/clang/test/CIR/Transforms/lifetime-check-agg.cpp b/clang/test/CIR/Transforms/lifetime-check-agg.cpp index fb89c0e6fd8f..ebfe00c2ad56 100644 --- a/clang/test/CIR/Transforms/lifetime-check-agg.cpp +++ b/clang/test/CIR/Transforms/lifetime-check-agg.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -clangir-disable-emit-cxx-default -fclangir-lifetime-check="history=all;remarks=all" -clangir-verify-diagnostics -emit-cir %s -o %t.cir +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir-analysis-only -fclangir-lifetime-check="history=all;remarks=all" %s -clangir-verify-diagnostics -emit-obj -o /dev/null typedef enum SType { INFO_ENUM_0 = 9, diff --git a/clang/test/CIR/analysis-only.cpp b/clang/test/CIR/analysis-only.cpp new file mode 100644 index 000000000000..7dc58250b91b --- /dev/null +++ b/clang/test/CIR/analysis-only.cpp @@ -0,0 +1,2 @@ +// RUN: %clang %s -fclangir-analysis-only -### -c %s 2>&1 | FileCheck %s +// CHECK: "-fclangir-analysis-only"