110317da2SKareem Ergawy //===- unittests/Frontend/CodeGenActionTest.cpp --- FrontendAction tests --===// 210317da2SKareem Ergawy // 310317da2SKareem Ergawy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 410317da2SKareem Ergawy // See https://llvm.org/LICENSE.txt for license information. 510317da2SKareem Ergawy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 610317da2SKareem Ergawy // 710317da2SKareem Ergawy //===----------------------------------------------------------------------===// 810317da2SKareem Ergawy // 910317da2SKareem Ergawy // Unit tests for CodeGenAction. 1010317da2SKareem Ergawy // 1110317da2SKareem Ergawy //===----------------------------------------------------------------------===// 1210317da2SKareem Ergawy 1310317da2SKareem Ergawy #include "mlir/IR/Builders.h" 1410317da2SKareem Ergawy #include "flang/Frontend/CompilerInstance.h" 1510317da2SKareem Ergawy #include "flang/Frontend/FrontendActions.h" 1610317da2SKareem Ergawy #include "flang/Frontend/TextDiagnosticPrinter.h" 1710317da2SKareem Ergawy 1810317da2SKareem Ergawy #include "gtest/gtest.h" 1910317da2SKareem Ergawy 2010317da2SKareem Ergawy #include <memory> 2110317da2SKareem Ergawy 2210317da2SKareem Ergawy using namespace Fortran::frontend; 2310317da2SKareem Ergawy 2410317da2SKareem Ergawy namespace test { 2510317da2SKareem Ergawy class DummyDialect : public ::mlir::Dialect { 2610317da2SKareem Ergawy explicit DummyDialect(::mlir::MLIRContext *context) 2710317da2SKareem Ergawy : ::mlir::Dialect(getDialectNamespace(), context, 2810317da2SKareem Ergawy ::mlir::TypeID::get<DummyDialect>()) { 2910317da2SKareem Ergawy initialize(); 3010317da2SKareem Ergawy } 3110317da2SKareem Ergawy 3210317da2SKareem Ergawy void initialize(); 3310317da2SKareem Ergawy friend class ::mlir::MLIRContext; 3410317da2SKareem Ergawy 3510317da2SKareem Ergawy public: 3610317da2SKareem Ergawy ~DummyDialect() override = default; 3710317da2SKareem Ergawy static constexpr ::llvm::StringLiteral getDialectNamespace() { 3810317da2SKareem Ergawy return ::llvm::StringLiteral("dummy"); 3910317da2SKareem Ergawy } 4010317da2SKareem Ergawy }; 4110317da2SKareem Ergawy 4210317da2SKareem Ergawy namespace dummy { 4310317da2SKareem Ergawy class FakeOp : public ::mlir::Op<FakeOp> { 4410317da2SKareem Ergawy public: 4510317da2SKareem Ergawy using Op::Op; 4610317da2SKareem Ergawy 4710317da2SKareem Ergawy static llvm::StringRef getOperationName() { return "dummy.fake"; } 4810317da2SKareem Ergawy 4910317da2SKareem Ergawy static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { return {}; } 5010317da2SKareem Ergawy 5110317da2SKareem Ergawy static void build( 5210317da2SKareem Ergawy ::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState) {} 5310317da2SKareem Ergawy }; 5410317da2SKareem Ergawy } // namespace dummy 5510317da2SKareem Ergawy } // namespace test 5610317da2SKareem Ergawy 5710317da2SKareem Ergawy MLIR_DECLARE_EXPLICIT_TYPE_ID(::test::DummyDialect) 5810317da2SKareem Ergawy MLIR_DEFINE_EXPLICIT_TYPE_ID(::test::DummyDialect) 5910317da2SKareem Ergawy 6010317da2SKareem Ergawy namespace test { 6110317da2SKareem Ergawy 6210317da2SKareem Ergawy void DummyDialect::initialize() { addOperations<::test::dummy::FakeOp>(); } 6310317da2SKareem Ergawy } // namespace test 6410317da2SKareem Ergawy 6510317da2SKareem Ergawy // A test CodeGenAction to verify that we gracefully handle failure to convert 6610317da2SKareem Ergawy // from MLIR to LLVM IR. 6710317da2SKareem Ergawy class LLVMConversionFailureCodeGenAction : public CodeGenAction { 6810317da2SKareem Ergawy public: 6910317da2SKareem Ergawy LLVMConversionFailureCodeGenAction() 7010317da2SKareem Ergawy : CodeGenAction(BackendActionTy::Backend_EmitLL) { 7110317da2SKareem Ergawy mlirCtx = std::make_unique<mlir::MLIRContext>(); 7210317da2SKareem Ergawy mlirCtx->loadDialect<test::DummyDialect>(); 7310317da2SKareem Ergawy 7410317da2SKareem Ergawy mlir::Location loc(mlir::UnknownLoc::get(mlirCtx.get())); 75*c870632eSMatthias Springer mlirModule = mlir::ModuleOp::create(loc, "mod"); 7610317da2SKareem Ergawy 7710317da2SKareem Ergawy mlir::OpBuilder builder(mlirCtx.get()); 7810317da2SKareem Ergawy builder.setInsertionPointToStart(&mlirModule->getRegion().front()); 7910317da2SKareem Ergawy // Create a fake op to trip conversion to LLVM. 8010317da2SKareem Ergawy builder.create<test::dummy::FakeOp>(loc); 8110317da2SKareem Ergawy 8210317da2SKareem Ergawy llvmCtx = std::make_unique<llvm::LLVMContext>(); 8310317da2SKareem Ergawy } 8410317da2SKareem Ergawy }; 8510317da2SKareem Ergawy 8610317da2SKareem Ergawy TEST(CodeGenAction, GracefullyHandleLLVMConversionFailure) { 8710317da2SKareem Ergawy std::string diagnosticOutput; 8810317da2SKareem Ergawy llvm::raw_string_ostream diagnosticsOS(diagnosticOutput); 8910317da2SKareem Ergawy auto diagPrinter = std::make_unique<Fortran::frontend::TextDiagnosticPrinter>( 9010317da2SKareem Ergawy diagnosticsOS, new clang::DiagnosticOptions()); 9110317da2SKareem Ergawy 9210317da2SKareem Ergawy CompilerInstance ci; 9310317da2SKareem Ergawy ci.createDiagnostics(diagPrinter.get(), /*ShouldOwnClient=*/false); 9410317da2SKareem Ergawy ci.setInvocation(std::make_shared<CompilerInvocation>()); 9510317da2SKareem Ergawy ci.setOutputStream(std::make_unique<llvm::raw_null_ostream>()); 9610317da2SKareem Ergawy ci.getInvocation().getCodeGenOpts().OptimizationLevel = 0; 9710317da2SKareem Ergawy 9810317da2SKareem Ergawy FrontendInputFile file("/dev/null", InputKind()); 9910317da2SKareem Ergawy 10010317da2SKareem Ergawy LLVMConversionFailureCodeGenAction action; 10110317da2SKareem Ergawy action.setInstance(&ci); 10210317da2SKareem Ergawy action.setCurrentInput(file); 10310317da2SKareem Ergawy 10410317da2SKareem Ergawy consumeError(action.execute()); 105d5dd7d23SYoungsuk Kim ASSERT_EQ(diagnosticOutput, 10610317da2SKareem Ergawy "error: Lowering to LLVM IR failed\n" 10710317da2SKareem Ergawy "error: failed to create the LLVM module\n"); 10810317da2SKareem Ergawy } 109