Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- StatementContext.h --------------------------------------*- C++ -*-===// |
---|---|
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 | // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef FORTRAN_LOWER_STATEMENTCONTEXT_H |
14 | #define FORTRAN_LOWER_STATEMENTCONTEXT_H |
15 | |
16 | #include "llvm/ADT/STLExtras.h" |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include <functional> |
19 | #include <optional> |
20 | |
21 | namespace Fortran::lower { |
22 | |
23 | /// When lowering a statement, temporaries for intermediate results may be |
24 | /// allocated on the heap. A StatementContext enables their deallocation |
25 | /// with one of several explicit finalize calls, or with an implicit |
26 | /// call to finalizeAndPop() at the end of the context. A context may prohibit |
27 | /// temporary allocation. Otherwise, an initial "outer" context scope may have |
28 | /// nested context scopes, which must make explicit subscope finalize calls. |
29 | /// |
30 | /// In addition to being useful for individual action statement contexts, a |
31 | /// StatementContext is also useful for construct blocks delimited by a pair |
32 | /// of statements such as (block-stmt, end-block-stmt), or a program unit |
33 | /// delimited by a pair of statements such as (subroutine-stmt, end-subroutine- |
34 | /// stmt). Attached cleanup code for these contexts may include stack |
35 | /// management code, deallocation code, and finalization of derived type |
36 | /// entities in the context. |
37 | class StatementContext { |
38 | public: |
39 | explicit StatementContext(bool cleanupProhibited = false) { |
40 | if (cleanupProhibited) |
41 | return; |
42 | cufs.push_back({}); |
43 | } |
44 | |
45 | ~StatementContext() { |
46 | if (!cufs.empty()) |
47 | finalizeAndPop(); |
48 | assert(cufs.empty() && "invalid StatementContext destructor call"); |
49 | } |
50 | |
51 | using CleanupFunction = std::function<void()>; |
52 | |
53 | /// Push a context subscope. |
54 | void pushScope() { |
55 | assert(!cufs.empty() && "invalid pushScope statement context"); |
56 | cufs.push_back({}); |
57 | } |
58 | |
59 | /// Append a cleanup function to the "list" of cleanup functions. |
60 | void attachCleanup(CleanupFunction cuf) { |
61 | assert(!cufs.empty() && "invalid attachCleanup statement context"); |
62 | if (cufs.back()) { |
63 | CleanupFunction oldCleanup = *cufs.back(); |
64 | cufs.back() = [=]() { |
65 | cuf(); |
66 | oldCleanup(); |
67 | }; |
68 | } else { |
69 | cufs.back() = cuf; |
70 | } |
71 | } |
72 | |
73 | /// Make cleanup calls. Retain the stack top list for a repeat call. |
74 | void finalizeAndKeep() { |
75 | assert(!cufs.empty() && "invalid finalize statement context"); |
76 | if (cufs.back()) |
77 | (*cufs.back())(); |
78 | } |
79 | |
80 | /// Make cleanup calls. Clear the stack top list. |
81 | void finalizeAndReset() { |
82 | finalizeAndKeep(); |
83 | cufs.back().reset(); |
84 | } |
85 | |
86 | /// Make cleanup calls. Pop the stack top list. |
87 | void finalizeAndPop() { |
88 | finalizeAndKeep(); |
89 | cufs.pop_back(); |
90 | } |
91 | |
92 | bool hasCode() const { |
93 | return !cufs.empty() && llvm::any_of(cufs, [](auto &opt) -> bool { |
94 | return opt.has_value(); |
95 | }); |
96 | } |
97 | |
98 | private: |
99 | // A statement context should never be copied or moved. |
100 | StatementContext(const StatementContext &) = delete; |
101 | StatementContext &operator=(const StatementContext &) = delete; |
102 | StatementContext(StatementContext &&) = delete; |
103 | |
104 | // Stack of cleanup function "lists" (nested cleanup function calls). |
105 | llvm::SmallVector<std::optional<CleanupFunction>> cufs; |
106 | }; |
107 | |
108 | } // namespace Fortran::lower |
109 | |
110 | #endif // FORTRAN_LOWER_STATEMENTCONTEXT_H |
111 |
Warning: This file is not a C or C++ file. It does not have highlighting.