diff --git a/clang/include/clang/CIR/CIRToCIRPasses.h b/clang/include/clang/CIR/CIRToCIRPasses.h index ec6d75332bed9..061b4462ed846 100644 --- a/clang/include/clang/CIR/CIRToCIRPasses.h +++ b/clang/include/clang/CIR/CIRToCIRPasses.h @@ -32,7 +32,8 @@ namespace cir { mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirCtx, clang::ASTContext &astCtx, bool enableVerifier, - bool enableIdiomRecognizer, bool enableCIRSimplify); + bool enableIdiomRecognizer, bool enableCIRSimplify, + bool enableCallingConvLowering); } // namespace cir diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h index d441dfcbc6c14..31332e968309f 100644 --- a/clang/include/clang/CIR/Dialect/Passes.h +++ b/clang/include/clang/CIR/Dialect/Passes.h @@ -34,6 +34,9 @@ std::unique_ptr createGotoSolverPass(); std::unique_ptr createIdiomRecognizerPass(); std::unique_ptr createIdiomRecognizerPass(clang::ASTContext *astCtx); +/// Create a pass to lower ABI-independent function definitions/calls. +std::unique_ptr createCallConvLoweringPass(); + void populateCIRPreLoweringPasses(mlir::OpPassManager &pm); //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/Passes.td b/clang/include/clang/CIR/Dialect/Passes.td index 32cd182aacec7..7f08221c965ca 100644 --- a/clang/include/clang/CIR/Dialect/Passes.td +++ b/clang/include/clang/CIR/Dialect/Passes.td @@ -195,4 +195,15 @@ def IdiomRecognizer : Pass<"cir-idiom-recognizer", "mlir::ModuleOp"> { let dependentDialects = ["cir::CIRDialect"]; } +def CallConvLowering : Pass<"cir-call-conv-lowering"> { + let summary = "Handle calling conventions for CIR functions"; + let description = [{ + This pass lowers CIR function definitions and calls according to the + calling conventions for the target architecture. This pass is necessary + to properly lower CIR functions to LLVM IR. + }]; + let constructor = "mlir::createCallConvLoweringPass()"; + let dependentDialects = ["cir::CIRDialect"]; +} + #endif // CLANG_CIR_DIALECT_PASSES_TD diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index f7f51bc37c98d..26028fd82087c 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -426,6 +426,9 @@ class FrontendOptions { LLVM_PREFERRED_TYPE(bool) unsigned ClangIREnableIdiomRecognizer : 1; + // Enable Clang IR call conv lowering pass. + unsigned ClangIRCallConvLowering : 1; + CodeCompleteOptions CodeCompleteOpts; /// Specifies the output format of the AST. diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 215d4e885709c..a787c3fbcddae 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -3355,6 +3355,14 @@ def clangir_enable_idiom_recognizer : Flag<["-"], "clangir-enable-idiom-recogniz HelpText<"ClangIR: Enable Idiom Recognizer pass">, MarshallingInfoFlag>; +// FIXME(cir): Remove this option once all pre-existing tests are compatible with +// the calling convention lowering pass. +defm clangir_call_conv_lowering : BoolFOption<"clangir-call-conv-lowering", + FrontendOpts<"ClangIRCallConvLowering">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[], [ClangOption, CC1Option], "">>; + defm clangir : BoolFOption<"clangir", FrontendOpts<"UseClangIRPipeline">, DefaultFalse, PosFlag, diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt index 411bbc386b9d1..205e59dbb9eb4 100644 --- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_library(MLIRCIRTransforms LoweringPrepare.cpp GotoSolver.cpp IdiomRecognizer.cpp + CallConvLowering.cpp DEPENDS MLIRCIRPassIncGen diff --git a/clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp b/clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp new file mode 100644 index 0000000000000..1c166d5bd0c09 --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp @@ -0,0 +1,58 @@ +//===- CallConvLowering.cpp - Rewrites functions according to call convs --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/IR/BuiltinOps.h" +#include "mlir/Pass/Pass.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" + +#define GEN_PASS_DEF_CALLCONVLOWERING +#include "clang/CIR/Dialect/Passes.h.inc" + +namespace cir { + +struct CallConvLowering { + CallConvLowering(mlir::ModuleOp module) : module(module) {} + + void lower(FuncOp op) { + // TODO(cir): Implement calling convention lowering for function definitions + // and calls once the upstream LowerModule has the necessary APIs. + } + +private: + mlir::ModuleOp module; +}; + +//===----------------------------------------------------------------------===// +// Pass +//===----------------------------------------------------------------------===// + +struct CallConvLoweringPass + : ::impl::CallConvLoweringBase { + using CallConvLoweringBase::CallConvLoweringBase; + + void runOnOperation() override; + llvm::StringRef getArgument() const override { + return "cir-call-conv-lowering"; + }; +}; + +void CallConvLoweringPass::runOnOperation() { + auto module = mlir::dyn_cast(getOperation()); + CallConvLowering cc(module); + module.walk([&](FuncOp op) { cc.lower(op); }); +} + +} // namespace cir + +namespace mlir { + +std::unique_ptr createCallConvLoweringPass() { + return std::make_unique(); +} + +} // namespace mlir diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index ab273539b1ce2..5d4e70d6724e1 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -122,7 +122,8 @@ class CIRGenConsumer : public clang::ASTConsumer { // Setup and run CIR pipeline. if (runCIRToCIRPasses( MlirModule, MlirCtx, C, !FEOptions.ClangIRDisableCIRVerifier, - FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0) + FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0, + FEOptions.ClangIRCallConvLowering) .failed()) { CI.getDiagnostics().Report(diag::err_cir_to_cir_transform_failed); return; diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp index 7b93356a34c38..1cc00610d3fdb 100644 --- a/clang/lib/CIR/Lowering/CIRPasses.cpp +++ b/clang/lib/CIR/Lowering/CIRPasses.cpp @@ -20,7 +20,8 @@ namespace cir { mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext, clang::ASTContext &astContext, bool enableVerifier, - bool enableIdiomRecognizer, bool enableCIRSimplify) { + bool enableIdiomRecognizer, bool enableCIRSimplify, + bool enableCallConvLowering) { llvm::TimeTraceScope scope("CIR To CIR Passes"); @@ -37,6 +38,11 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext, pm.addPass(mlir::createCXXABILoweringPass()); pm.addPass(mlir::createLoweringPreparePass(&astContext)); + // FIXME(cir): This pass should run by default, but it is lacking support for + // several code bits. Once it's more mature, we should fix this. + if (enableCallConvLowering) + pm.addPass(mlir::createCallConvLoweringPass()); + pm.enableVerifier(enableVerifier); (void)mlir::applyPassManagerCLOptions(pm); return pm.run(theModule); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index db82695f87d6b..e3edee10767e7 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5112,6 +5112,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fclangir)) CmdArgs.push_back("-fclangir"); + if (Args.hasArg(options::OPT_fclangir_call_conv_lowering)) + CmdArgs.push_back("-fclangir-call-conv-lowering"); + if (IsOpenMPDevice) { // We have to pass the triple of the host if compiling for an OpenMP device. std::string NormalizedTriple = diff --git a/clang/test/CIR/Transforms/call-conv-lowering-pass.cpp b/clang/test/CIR/Transforms/call-conv-lowering-pass.cpp new file mode 100644 index 0000000000000..5581a45e83071 --- /dev/null +++ b/clang/test/CIR/Transforms/call-conv-lowering-pass.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -fclangir-call-conv-lowering -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +// CHECK: cir.func {{.*}}@_Z5emptyv() +void empty() {}