xref: /llvm-project/flang/include/flang/Optimizer/Builder/MutableBox.h (revision c91ba04328e1ded6f284469a7828d181324d4e30)
1 //===-- MutableBox.h -- MutableBox utilities  -----------------------------===//
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_OPTIMIZER_BUILDER_MUTABLEBOX_H
14 #define FORTRAN_OPTIMIZER_BUILDER_MUTABLEBOX_H
15 
16 #include "flang/Optimizer/Builder/BoxValue.h"
17 #include "flang/Runtime/allocator-registry-consts.h"
18 #include "llvm/ADT/StringRef.h"
19 
20 namespace mlir {
21 class Value;
22 class ValueRange;
23 class Type;
24 class Location;
25 } // namespace mlir
26 
27 namespace fir {
28 class FirOpBuilder;
29 class MutableBoxValue;
30 class ExtendedValue;
31 } // namespace fir
32 
33 namespace fir::factory {
34 
35 /// Create a fir.box of type \p boxType that can be used to initialize an
36 /// allocatable variable. Initialization of such variable has to be done at the
37 /// beginning of the variable lifetime by storing the created box in the memory
38 /// for the variable box.
39 /// \p nonDeferredParams must provide the non deferred LEN parameters so that
40 /// they can already be placed in the unallocated box (inquiries about these
41 /// parameters are legal even in unallocated state).
42 /// \p typeSourceBox provides the dynamic type information when the box is
43 /// created for a polymorphic temporary.
44 mlir::Value createUnallocatedBox(fir::FirOpBuilder &builder, mlir::Location loc,
45                                  mlir::Type boxType,
46                                  mlir::ValueRange nonDeferredParams,
47                                  mlir::Value typeSourceBox = {},
48                                  unsigned allocator = kDefaultAllocator);
49 
50 /// Create a MutableBoxValue for a temporary allocatable.
51 /// The created MutableBoxValue wraps a fir.ref<fir.box<fir.heap<type>>> and is
52 /// initialized to unallocated/diassociated status. An optional name can be
53 /// given to the created !fir.ref<fir.box>.
54 fir::MutableBoxValue createTempMutableBox(fir::FirOpBuilder &builder,
55                                           mlir::Location loc, mlir::Type type,
56                                           llvm::StringRef name = {},
57                                           mlir::Value sourceBox = {},
58                                           bool isPolymorphic = false);
59 
60 /// Update a MutableBoxValue to describe entity \p source (that must be in
61 /// memory). If \lbounds is not empty, it is used to defined the MutableBoxValue
62 /// lower bounds, otherwise, the lower bounds from \p source are used.
63 void associateMutableBox(fir::FirOpBuilder &builder, mlir::Location loc,
64                          const fir::MutableBoxValue &box,
65                          const fir::ExtendedValue &source,
66                          mlir::ValueRange lbounds);
67 
68 /// Update a MutableBoxValue to describe entity \p source (that must be in
69 /// memory) with a new array layout given by \p lbounds and \p ubounds.
70 /// \p source must be known to be contiguous at compile time, or it must have
71 /// rank 1 (constraint from Fortran 2018 standard 10.2.2.3 point 9).
72 void associateMutableBoxWithRemap(fir::FirOpBuilder &builder,
73                                   mlir::Location loc,
74                                   const fir::MutableBoxValue &box,
75                                   const fir::ExtendedValue &source,
76                                   mlir::ValueRange lbounds,
77                                   mlir::ValueRange ubounds);
78 
79 /// Set the association status of a MutableBoxValue to
80 /// disassociated/unallocated. Nothing is done with the entity that was
81 /// previously associated/allocated. The function generates code that sets the
82 /// address field of the MutableBoxValue to zero.
83 void disassociateMutableBox(fir::FirOpBuilder &builder, mlir::Location loc,
84                             const fir::MutableBoxValue &box,
85                             bool polymorphicSetType = true,
86                             unsigned allocator = kDefaultAllocator);
87 
88 /// Generate code to conditionally reallocate a MutableBoxValue with a new
89 /// shape, lower bounds, and LEN parameters if it is unallocated or if its
90 /// current shape or deferred  LEN parameters do not match the provided ones.
91 /// Lower bounds are only used if the entity needs to be allocated, otherwise,
92 /// the MutableBoxValue will keep its current lower bounds.
93 /// If the MutableBoxValue is an array, the provided shape can be empty, in
94 /// which case the MutableBoxValue must already be allocated at runtime and its
95 /// shape and lower bounds will be kept. If \p shape is empty, only a LEN
96 /// parameter mismatch can trigger a reallocation. See Fortran 10.2.1.3 point 3
97 /// that this function is implementing for more details. The polymorphic
98 /// requirements are not yet covered by this function.
99 struct MutableBoxReallocation {
100   fir::ExtendedValue newValue;
101   mlir::Value oldAddress;
102   mlir::Value wasReallocated;
103   mlir::Value oldAddressWasAllocated;
104 };
105 
106 /// Type of a callback invoked on every storage pointer produced
107 /// in different branches by genReallocIfNeeded(). The argument
108 /// is an ExtendedValue for the storage pointer.
109 /// For example, when genReallocIfNeeded() is used for a LHS allocatable
110 /// array in an assignment, the callback performs the actual assignment
111 /// via the given storage pointer, so we end up generating array_updates and
112 /// array_merge_stores in each branch.
113 using ReallocStorageHandlerFunc = std::function<void(fir::ExtendedValue)>;
114 
115 MutableBoxReallocation
116 genReallocIfNeeded(fir::FirOpBuilder &builder, mlir::Location loc,
117                    const fir::MutableBoxValue &box, mlir::ValueRange shape,
118                    mlir::ValueRange lenParams,
119                    ReallocStorageHandlerFunc storageHandler = {});
120 
121 void finalizeRealloc(fir::FirOpBuilder &builder, mlir::Location loc,
122                      const fir::MutableBoxValue &box, mlir::ValueRange lbounds,
123                      bool takeLboundsIfRealloc,
124                      const MutableBoxReallocation &realloc);
125 
126 /// Deallocate a mutable box with fir.freemem if it is allocated or associated.
127 /// This only deallocates the storage and does not call finalization, the
128 /// mutable box is not nullified.
129 void genFreememIfAllocated(fir::FirOpBuilder &builder, mlir::Location loc,
130                            const fir::MutableBoxValue &box);
131 
132 void genInlinedAllocation(fir::FirOpBuilder &builder, mlir::Location loc,
133                           const fir::MutableBoxValue &box,
134                           mlir::ValueRange lbounds, mlir::ValueRange extents,
135                           mlir::ValueRange lenParams, llvm::StringRef allocName,
136                           bool mustBeHeap = false);
137 
138 /// Deallocate an mutable box storage with fir.freemem without calling any
139 /// final procedures. The mutable box is not nullified.
140 mlir::Value genFreemem(fir::FirOpBuilder &builder, mlir::Location loc,
141                        const fir::MutableBoxValue &box);
142 
143 /// When the MutableBoxValue was passed as a fir.ref<fir.box> to a call that may
144 /// have modified it, update the MutableBoxValue according to the
145 /// fir.ref<fir.box> value.
146 void syncMutableBoxFromIRBox(fir::FirOpBuilder &builder, mlir::Location loc,
147                              const fir::MutableBoxValue &box);
148 
149 /// Read all mutable properties into a normal symbol box.
150 /// It is OK to call this on unassociated/unallocated boxes but any use of the
151 /// resulting values will be undefined (only the base address will be guaranteed
152 /// to be null).
153 fir::ExtendedValue genMutableBoxRead(fir::FirOpBuilder &builder,
154                                      mlir::Location loc,
155                                      const fir::MutableBoxValue &box,
156                                      bool mayBePolymorphic = true,
157                                      bool preserveLowerBounds = true);
158 
159 /// Returns the fir.ref<fir.box<T>> of a MutableBoxValue filled with the current
160 /// association / allocation properties. If the fir.ref<fir.box> already exists
161 /// and is-up to date, this is a no-op, otherwise, code will be generated to
162 /// fill it.
163 mlir::Value getMutableIRBox(fir::FirOpBuilder &builder, mlir::Location loc,
164                             const fir::MutableBoxValue &box);
165 
166 /// Generate allocation or association status test and returns the resulting
167 /// i1. This is testing this for a valid/non-null base address value.
168 mlir::Value genIsAllocatedOrAssociatedTest(fir::FirOpBuilder &builder,
169                                            mlir::Location loc,
170                                            const fir::MutableBoxValue &box);
171 
172 /// Generate allocation or association status test and returns the resulting
173 /// i1. This is testing this for a valid/non-null base address value.
174 mlir::Value genIsNotAllocatedOrAssociatedTest(fir::FirOpBuilder &builder,
175                                               mlir::Location loc,
176                                               const fir::MutableBoxValue &box);
177 
178 /// Generate an unallocated box of the given \p boxTy
179 /// and store it into a temporary storage.
180 /// Return address of the temporary storage.
181 mlir::Value genNullBoxStorage(fir::FirOpBuilder &builder, mlir::Location loc,
182                               mlir::Type boxTy);
183 
184 } // namespace fir::factory
185 
186 #endif // FORTRAN_OPTIMIZER_BUILDER_MUTABLEBOX_H
187