1 | //===- unittests/Frontend/CodeGenActionTest.cpp --- FrontendAction tests --===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Unit tests for CodeGenAction. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "mlir/IR/Builders.h" |
14 | #include "flang/Frontend/CompilerInstance.h" |
15 | #include "flang/Frontend/FrontendActions.h" |
16 | #include "flang/Frontend/TextDiagnosticPrinter.h" |
17 | |
18 | #include "gtest/gtest.h" |
19 | |
20 | #include <memory> |
21 | |
22 | using namespace Fortran::frontend; |
23 | |
24 | namespace test { |
25 | class DummyDialect : public ::mlir::Dialect { |
26 | explicit DummyDialect(::mlir::MLIRContext *context) |
27 | : ::mlir::Dialect(getDialectNamespace(), context, |
28 | ::mlir::TypeID::get<DummyDialect>()) { |
29 | initialize(); |
30 | } |
31 | |
32 | void initialize(); |
33 | friend class ::mlir::MLIRContext; |
34 | |
35 | public: |
36 | ~DummyDialect() override = default; |
37 | static constexpr ::llvm::StringLiteral getDialectNamespace() { |
38 | return ::llvm::StringLiteral("dummy" ); |
39 | } |
40 | }; |
41 | |
42 | namespace dummy { |
43 | class FakeOp : public ::mlir::Op<FakeOp> { |
44 | public: |
45 | using Op::Op; |
46 | |
47 | static llvm::StringRef getOperationName() { return "dummy.fake" ; } |
48 | |
49 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { return {}; } |
50 | |
51 | static void build( |
52 | ::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState) {} |
53 | }; |
54 | } // namespace dummy |
55 | } // namespace test |
56 | |
57 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::test::DummyDialect) |
58 | MLIR_DEFINE_EXPLICIT_TYPE_ID(::test::DummyDialect) |
59 | |
60 | namespace test { |
61 | |
62 | void DummyDialect::initialize() { addOperations<::test::dummy::FakeOp>(); } |
63 | } // namespace test |
64 | |
65 | // A test CodeGenAction to verify that we gracefully handle failure to convert |
66 | // from MLIR to LLVM IR. |
67 | class LLVMConversionFailureCodeGenAction : public CodeGenAction { |
68 | public: |
69 | LLVMConversionFailureCodeGenAction() |
70 | : CodeGenAction(BackendActionTy::Backend_EmitLL) { |
71 | mlirCtx = std::make_unique<mlir::MLIRContext>(); |
72 | mlirCtx->loadDialect<test::DummyDialect>(); |
73 | |
74 | mlir::Location loc(mlir::UnknownLoc::get(mlirCtx.get())); |
75 | mlirModule = |
76 | std::make_unique<mlir::ModuleOp>(mlir::ModuleOp::create(loc, "mod" )); |
77 | |
78 | mlir::OpBuilder builder(mlirCtx.get()); |
79 | builder.setInsertionPointToStart(&mlirModule->getRegion().front()); |
80 | // Create a fake op to trip conversion to LLVM. |
81 | builder.create<test::dummy::FakeOp>(loc); |
82 | |
83 | llvmCtx = std::make_unique<llvm::LLVMContext>(); |
84 | } |
85 | }; |
86 | |
87 | TEST(CodeGenAction, GracefullyHandleLLVMConversionFailure) { |
88 | std::string diagnosticOutput; |
89 | llvm::raw_string_ostream diagnosticsOS(diagnosticOutput); |
90 | auto diagPrinter = std::make_unique<Fortran::frontend::TextDiagnosticPrinter>( |
91 | diagnosticsOS, new clang::DiagnosticOptions()); |
92 | |
93 | CompilerInstance ci; |
94 | ci.createDiagnostics(diagPrinter.get(), /*ShouldOwnClient=*/false); |
95 | ci.setInvocation(std::make_shared<CompilerInvocation>()); |
96 | ci.setOutputStream(std::make_unique<llvm::raw_null_ostream>()); |
97 | ci.getInvocation().getCodeGenOpts().OptimizationLevel = 0; |
98 | |
99 | FrontendInputFile file("/dev/null" , InputKind()); |
100 | |
101 | LLVMConversionFailureCodeGenAction action; |
102 | action.setInstance(&ci); |
103 | action.setCurrentInput(file); |
104 | |
105 | consumeError(action.execute()); |
106 | ASSERT_EQ(diagnosticsOS.str(), |
107 | "error: Lowering to LLVM IR failed\n" |
108 | "error: failed to create the LLVM module\n" ); |
109 | } |
110 | |