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
21namespace 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.
37class StatementContext {
38public:
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
98private:
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.

source code of flang/include/flang/Lower/StatementContext.h