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