//===- unittests/Frontend/CodeGenActionTest.cpp --- FrontendAction tests --===// // // 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 // //===----------------------------------------------------------------------===// // // Unit tests for CodeGenAction. // //===----------------------------------------------------------------------===// #include "mlir/IR/Builders.h" #include "flang/Frontend/CompilerInstance.h" #include "flang/Frontend/FrontendActions.h" #include "flang/Frontend/TextDiagnosticPrinter.h" #include "gtest/gtest.h" #include using namespace Fortran::frontend; namespace test { class DummyDialect : public ::mlir::Dialect { explicit DummyDialect(::mlir::MLIRContext *context) : ::mlir::Dialect(getDialectNamespace(), context, ::mlir::TypeID::get()) { initialize(); } void initialize(); friend class ::mlir::MLIRContext; public: ~DummyDialect() override = default; static constexpr ::llvm::StringLiteral getDialectNamespace() { return ::llvm::StringLiteral("dummy"); } }; namespace dummy { class FakeOp : public ::mlir::Op { public: using Op::Op; static llvm::StringRef getOperationName() { return "dummy.fake"; } static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { return {}; } static void build( ::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState) {} }; } // namespace dummy } // namespace test MLIR_DECLARE_EXPLICIT_TYPE_ID(::test::DummyDialect) MLIR_DEFINE_EXPLICIT_TYPE_ID(::test::DummyDialect) namespace test { void DummyDialect::initialize() { addOperations<::test::dummy::FakeOp>(); } } // namespace test // A test CodeGenAction to verify that we gracefully handle failure to convert // from MLIR to LLVM IR. class LLVMConversionFailureCodeGenAction : public CodeGenAction { public: LLVMConversionFailureCodeGenAction() : CodeGenAction(BackendActionTy::Backend_EmitLL) { mlirCtx = std::make_unique(); mlirCtx->loadDialect(); mlir::Location loc(mlir::UnknownLoc::get(mlirCtx.get())); mlirModule = mlir::ModuleOp::create(loc, "mod"); mlir::OpBuilder builder(mlirCtx.get()); builder.setInsertionPointToStart(&mlirModule->getRegion().front()); // Create a fake op to trip conversion to LLVM. builder.create(loc); llvmCtx = std::make_unique(); } }; TEST(CodeGenAction, GracefullyHandleLLVMConversionFailure) { std::string diagnosticOutput; llvm::raw_string_ostream diagnosticsOS(diagnosticOutput); auto diagPrinter = std::make_unique( diagnosticsOS, new clang::DiagnosticOptions()); CompilerInstance ci; ci.createDiagnostics(diagPrinter.get(), /*ShouldOwnClient=*/false); ci.setInvocation(std::make_shared()); ci.setOutputStream(std::make_unique()); ci.getInvocation().getCodeGenOpts().OptimizationLevel = 0; FrontendInputFile file("/dev/null", InputKind()); LLVMConversionFailureCodeGenAction action; action.setInstance(&ci); action.setCurrentInput(file); consumeError(action.execute()); ASSERT_EQ(diagnosticOutput, "error: Lowering to LLVM IR failed\n" "error: failed to create the LLVM module\n"); }