llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Konstantinos Parasyris (koparasy) <details> <summary>Changes</summary> Clang now supports lowering .cir cc1 input to LLVM IR, assembly, and objects. The lowering does not execute the cir-to-cir passes; it only translates the input CIR to LLVM IR, assembly, and objects. This assumes that the input CIR is well-formed and valid and emitted the way -emit-cir emits this today. There will be some future PR that enables emission earlier and allows the pipeline to apply CIR passes before lowering to LLVM IR, assembly, and objects. --- Full diff: https://github.com/llvm/llvm-project/pull/232506.diff 9 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticCodeGenKinds.td (+3) - (modified) clang/include/clang/Basic/DiagnosticFrontendKinds.td (-2) - (modified) clang/include/clang/CIR/LowerToLLVM.h (+3) - (modified) clang/lib/CIR/FrontendAction/CIRGenAction.cpp (+15-18) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+4-10) - (modified) clang/test/CIR/Input/cir-input-invalid.cir (+5-2) - (added) clang/test/CIR/Input/cir-input-lower-error.cir (+24) - (added) clang/test/CIR/Input/cir-input-lower.cpp (+54) - (removed) clang/test/CIR/Input/cir-input-unsupported.cir (-29) ``````````diff diff --git a/clang/include/clang/Basic/DiagnosticCodeGenKinds.td b/clang/include/clang/Basic/DiagnosticCodeGenKinds.td index c8b8bb38b20ea2..d01f8bcbf481be 100644 --- a/clang/include/clang/Basic/DiagnosticCodeGenKinds.td +++ b/clang/include/clang/Basic/DiagnosticCodeGenKinds.td @@ -27,6 +27,9 @@ def err_cir_verification_failed_pre_passes : Error< "CIR module verification error before running CIR-to-CIR passes">, DefaultFatal; +def err_cir_to_llvm_lowering_failed : Error< + "lowering ClangIR to LLVM IR failed">, DefaultFatal; + // Diagnostics relayed from MLIR-side passes/verifier through the // clang::DiagnosticsEngine. The full message text comes from MLIR. def err_cir_mlir_diagnostic : Error<"%0">; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 66eeb08034bf4b..3df87215a0476d 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -146,8 +146,6 @@ def err_fe_action_not_available : Error< "action %0 not compiled in">; def err_fe_cir_not_built : Error<"clang IR support not available, rebuild " "clang with -DCLANG_ENABLE_CIR=ON">; -def err_fe_cir_input_unsupported : Error< - "support for ClangIR input is not yet implemented">; def err_invalid_cir : Error<"invalid ClangIR input">; def err_cir_input_missing_triple : Error< "missing target triple in ClangIR input">; diff --git a/clang/include/clang/CIR/LowerToLLVM.h b/clang/include/clang/CIR/LowerToLLVM.h index d97ac5265c282b..f746a5e211c3bc 100644 --- a/clang/include/clang/CIR/LowerToLLVM.h +++ b/clang/include/clang/CIR/LowerToLLVM.h @@ -28,6 +28,9 @@ class ModuleOp; namespace cir { namespace direct { +/// Lowers \p mlirModule, a CIR module, to an LLVM module in \p llvmCtx. +/// Returns null if lowering fails; the error has then been reported through +/// the MLIR diagnostic engine of \p mlirModule's context. std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, bool enableOpenMP, diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index c1f7c5117c54bb..b0d35d0ddc56ad 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -173,6 +173,13 @@ static void emitCIRModuleOutput( std::unique_ptr<llvm::Module> LLVMModule = lowerFromCIRToLLVMIR(MlirModule, LLVMCtx, EnableOpenMP, mlirSaveTempsOutFile, &CI.getVirtualFileSystem()); + if (!LLVMModule) { + // Lowering errors are already routed through the MLIR diagnostic + // handler. Only emit the generic error if nothing was reported. + if (!CI.getDiagnostics().hasErrorOccurred()) + CI.getDiagnostics().Report(diag::err_cir_to_llvm_lowering_failed); + return; + } LLVMModule->setDataLayout(CI.getTarget().getDataLayoutString()); @@ -432,24 +439,14 @@ void CIRGenAction::ExecuteAction() { return; } - switch (Action) { - case OutputType::EmitCIR: - // The CIR-to-CIR pipeline is not run: CIR printed by -emit-cir has already - // been through it, and its lowering passes are not idempotent. - printCIRModule(*Module, *OS); - break; - case OutputType::EmitCIRBC: - if (failed(mlir::writeBytecodeToFile(*Module, *OS)) && - !Diags.hasErrorOccurred()) - Diags.Report(diag::err_cir_bc_write_failed); - break; - case OutputType::EmitLLVM: - case OutputType::EmitBC: - case OutputType::EmitObj: - case OutputType::EmitAssembly: - Diags.Report(diag::err_fe_cir_input_unsupported); - break; - } + // The CIR-to-CIR pipeline is not run: CIR printed by -emit-cir has already + // been through it, and its lowering passes are not idempotent. + // TODO: Decide from a pipeline-stage attribute on the module which passes + // still have to run, once -emit-cir can stop before ABI lowering. + BackendDiagnosticConsumer DiagConsumer(Diags, CI.getCodeGenOpts()); + DiagConsumer.setSourceManager(&SM); + emitCIRModuleOutput(Action, CI, *Module, *Ctx, LinkModules, DiagConsumer, + std::move(OS)); } static std::unique_ptr<raw_pwrite_stream> diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index ddfc28da80388d..60ad37198fcfbe 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -6441,11 +6441,10 @@ lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, LLVMContext &llvmCtx, (void)mlir::applyPassManagerCLOptions(pm); - if (mlir::failed(pm.run(mlirModule))) { - // FIXME: Handle any errors where they occurs and return a nullptr here. - report_fatal_error( - "The pass manager failed to lower CIR to LLVMIR dialect!"); - } + // The failing pass has already reported its error through the MLIR + // diagnostic engine. + if (mlir::failed(pm.run(mlirModule))) + return nullptr; if (!mlirSaveTempsOutFile.empty()) { std::error_code ec; @@ -6465,11 +6464,6 @@ lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, LLVMContext &llvmCtx, std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR( mlirModule, llvmCtx, moduleName, /*disableVerification=*/false, fs); - if (!llvmModule) { - // FIXME: Handle any errors where they occurs and return a nullptr here. - report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!"); - } - return llvmModule; } } // namespace direct diff --git a/clang/test/CIR/Input/cir-input-invalid.cir b/clang/test/CIR/Input/cir-input-invalid.cir index 1a791d843bb0a4..cc64546eed3580 100644 --- a/clang/test/CIR/Input/cir-input-invalid.cir +++ b/clang/test/CIR/Input/cir-input-invalid.cir @@ -1,6 +1,5 @@ // Invalid ClangIR input is diagnosed, not crashed on, before any output is -// produced. Backend outputs, which are not supported from ClangIR input yet, -// report the same errors. +// produced. Backend outputs report the same errors. // RUN: rm -rf %t && split-file %s %t @@ -12,6 +11,8 @@ // RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %t/verifier.cir -o - 2>&1 \ // RUN: | FileCheck %s --check-prefix=VERIFIER --implicit-check-not=error: +// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj %t/verifier.cir -o /dev/null 2>&1 \ +// RUN: | FileCheck %s --check-prefix=VERIFIER --implicit-check-not=error: // VERIFIER: verifier.cir:5:5: error: 'cir.return' op returns '!cir.int<s, 64>' but enclosing function returns '!cir.int<s, 32>' // Ops in CIR emitted by CIRGen are located in the original source, which is not @@ -33,6 +34,8 @@ // RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %t/mismatch.cir -o - 2>&1 \ // RUN: | FileCheck %s --check-prefix=MISMATCH --implicit-check-not=error: +// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj %t/mismatch.cir -o /dev/null 2>&1 \ +// RUN: | FileCheck %s --check-prefix=MISMATCH --implicit-check-not=error: // MISMATCH: error: target triple 'aarch64-unknown-linux-gnu' of ClangIR input does not match the target 'x86_64-unknown-linux-gnu' //--- syntax.cir diff --git a/clang/test/CIR/Input/cir-input-lower-error.cir b/clang/test/CIR/Input/cir-input-lower-error.cir new file mode 100644 index 00000000000000..2f135bdd0f9a39 --- /dev/null +++ b/clang/test/CIR/Input/cir-input-lower-error.cir @@ -0,0 +1,24 @@ +// Errors from lowering ClangIR input to LLVM IR are diagnosed, not crashed on. +// The ctor region of @gs is only removed by LoweringPrepare, which is not run +// on ClangIR input. + +// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - 2>&1 \ +// RUN: | FileCheck %s --implicit-check-not=error: +// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj %s -o /dev/null 2>&1 \ +// RUN: | FileCheck %s --implicit-check-not=error: + +// No partial output is left behind. +// RUN: rm -f %t.o && not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj %s -o %t.o 2>/dev/null +// RUN: not ls %t.o + +// CHECK: cir-input-lower-error.cir:[[@LINE+6]]:3: error: GlobalOp ctor and dtor regions should be removed in LoweringPrepare +// CHECK: cir-input-lower-error.cir:[[@LINE+5]]:3: error: failed to legalize operation 'cir.global' + +!rec_S = !cir.struct<"S" {data !cir.int<s, 32>}> +module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { + cir.func private @_ZN1SC1Ev(!cir.ptr<!rec_S>) + cir.global external @gs = #cir.zero : !rec_S ctor { + %0 = cir.get_global @gs : !cir.ptr<!rec_S> + cir.call @_ZN1SC1Ev(%0) : (!cir.ptr<!rec_S>) -> () + } +} diff --git a/clang/test/CIR/Input/cir-input-lower.cpp b/clang/test/CIR/Input/cir-input-lower.cpp new file mode 100644 index 00000000000000..0459deed07c2db --- /dev/null +++ b/clang/test/CIR/Input/cir-input-lower.cpp @@ -0,0 +1,54 @@ +// Lowering ClangIR input to LLVM IR, assembly, bitcode or an object gives the +// same result as compiling the source directly. The CIR-to-CIR pipeline is not +// run again on input printed by -emit-cir, whose lowering passes are not +// idempotent; the code below exercises the calling convention, global +// constructor and TLS wrapper lowering. + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.direct.ll +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %t.cir -o %t.ll +// RUN: diff %t.direct.ll %t.ll + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -S %s -o %t.direct.s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -S %t.cir -o %t.s +// RUN: diff %t.direct.s %t.s + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-obj %s -o %t.direct.o +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj %t.cir -o %t.o +// RUN: cmp %t.direct.o %t.o + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm-bc %s -o %t.direct.bc +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc %t.cir -o %t.bc +// RUN: cmp %t.direct.bc %t.bc + +// Without -o, the output is named after the input. +// RUN: rm -rf %t.dir && mkdir -p %t.dir && cd %t.dir +// RUN: cp %t.cir input.cir +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj input.cir +// RUN: cmp %t.direct.o input.o + +// Code generation options still come from the command line. +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -emit-cir %s -o %t.O2.cir +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -emit-llvm %s -o %t.O2.direct.ll +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -emit-llvm -x cir %t.O2.cir -o %t.O2.ll +// RUN: diff %t.O2.direct.ll %t.O2.ll + +typedef float v2f __attribute__((vector_size(8))); + +v2f mk(float a) { return (v2f){a, a}; } + +struct S { + S(); + ~S(); + int v; +}; + +S gs; + +thread_local int tl = 3; + +int get() { + static S local; + return local.v + tl; +} diff --git a/clang/test/CIR/Input/cir-input-unsupported.cir b/clang/test/CIR/Input/cir-input-unsupported.cir deleted file mode 100644 index b087871af1d04e..00000000000000 --- a/clang/test/CIR/Input/cir-input-unsupported.cir +++ /dev/null @@ -1,29 +0,0 @@ -// A .cir input is routed to the ClangIR frontend action instead of being -// parsed as C. Only -emit-cir is supported from ClangIR input so far, so every -// other CIR action reports a single diagnostic. - -// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -x cir %s -o - 2>&1 \ -// RUN: | FileCheck %s --implicit-check-not=error: -// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-obj -x cir %s -o /dev/null 2>&1 \ -// RUN: | FileCheck %s --implicit-check-not=error: -// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -S -x cir %s -o - 2>&1 \ -// RUN: | FileCheck %s --implicit-check-not=error: -// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm-bc -x cir %s -o /dev/null 2>&1 \ -// RUN: | FileCheck %s --implicit-check-not=error: - -// ClangIR input implies -fclangir. -// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -x cir %s -o - 2>&1 \ -// RUN: | FileCheck %s --implicit-check-not=error: - -// The .cir extension selects ClangIR input without -x. -// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj %s -o /dev/null 2>&1 \ -// RUN: | FileCheck %s --implicit-check-not=error: - -// CHECK: error: support for ClangIR input is not yet implemented - -!s32i = !cir.int<s, 32> -module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { - cir.func @f(%arg0: !s32i) -> !s32i { - cir.return %arg0 : !s32i - } -} `````````` </details> https://github.com/llvm/llvm-project/pull/232506 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
