-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy pathInitialization.h
240 lines (197 loc) · 8.44 KB
/
Initialization.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
//===--- Initialization.h - Buffer initialization. --------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// A storage structure for representing a buffer or collection of buffers to
// be initialized.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_LOWERING_INITIALIZATION_H
#define SWIFT_LOWERING_INITIALIZATION_H
#include "RValue.h"
#include <memory>
namespace swift {
namespace Lowering {
class ManagedValue;
class SILGenFunction;
class Initialization;
using InitializationPtr = std::unique_ptr<Initialization>;
/// Initialization - Abstract base class for initialization buffers. An
/// initialization represents an uninitialized buffer or a tuple of
/// uninitialized buffers that must be initialized with the result of an
/// expression, such as in a var declaration or return statement. An
/// initialization may also have partial cleanups that should be disabled and
/// replaced when the buffer is initialized; for instance, a freshly allocated
/// box with an uninitialized value must be deallocated with `dealloc_ref`, but
/// once the box is fully initialized, both the box and the contained value can
/// be cleaned up together with `release`.
///
/// FIXME: provide a reset() operation to support multiple
/// initialization paths.
class Initialization {
public:
Initialization() {}
virtual ~Initialization() {}
/// Return true if this initialization is a simple address in memory.
virtual bool isSingleBuffer() const {
return false;
}
/// If this initialization represents a single contiguous buffer, return the
/// SILValue of that buffer's address. If not, returns an invalid SILValue.
virtual SILValue getAddressOrNull() const = 0;
/// Returns the address of the single contiguous buffer represented by this
/// initialization. Once the address has been stored to,
/// finishInitialization must be called.
SILValue getAddress() const {
SILValue address = getAddressOrNull();
assert(address && "initialization does not represent a single buffer");
return address;
}
/// If this initialization has an address we can directly emit into, return
/// it. Otherwise, return a null SILValue.
virtual SILValue getAddressForInPlaceInitialization() const {
return SILValue();
}
/// Return true if we can get the addresses of elements with the
/// 'getSubInitializationsForTuple' method. Subclasses can override this to
/// enable this behavior.
virtual bool canSplitIntoSubelementAddresses() const {
return false;
}
/// If this initialization represents an aggregation of sub-initializations,
/// return the sub-initializations. If it represents a single
/// initialization of tuple type, explode it into initializations for each
/// individual tuple element. In either case, once all the sub-initializations
/// have been initialized and finalized with finishInitialization,
/// finishInitialization must then be called on this aggregate initialization.
///
/// \param buf - If new Initializations need to be created, their ownership
/// is given to this vector.
/// \param Loc The location with which the single initialization should be
/// associated.
virtual MutableArrayRef<InitializationPtr>
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
SmallVectorImpl<InitializationPtr> &buf,
SILLocation Loc) {
llvm_unreachable("Must implement if canSplitIntoSubelementAddresses"
"returns true");
}
/// Perform post-initialization bookkeeping for this initialization.
virtual void finishInitialization(SILGenFunction &gen) {}
/// When emitting an exploded RValue into an initialization, this method is
/// called once per scalar value in the explosion.
///
/// If this is an *copy* of the rvalue into this initialization then isInit is
/// false. If it is an *initialization* of the memory in the initialization,
/// then isInit is true.
virtual void copyOrInitValueInto(ManagedValue explodedElement, bool isInit,
SILLocation loc, SILGenFunction &gen) = 0;
private:
Initialization(const Initialization &) = delete;
Initialization(Initialization &&) = delete;
virtual void _anchor();
};
/// Abstract base class for single-buffer initializations. These are
/// initializations that have an addressable memory object to be stored into.
class SingleBufferInitialization : public Initialization {
public:
SingleBufferInitialization() {}
bool isSingleBuffer() const override {
return true;
}
// SingleBufferInitializations always have an address.
SILValue getAddressForInPlaceInitialization() const override {
return getAddress();
}
bool canSplitIntoSubelementAddresses() const override {
return true;
}
MutableArrayRef<InitializationPtr>
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
SmallVectorImpl<InitializationPtr> &buf,
SILLocation Loc) override;
void copyOrInitValueInto(ManagedValue explodedElement, bool isInit,
SILLocation loc, SILGenFunction &gen) override {
copyOrInitValueIntoSingleBuffer(explodedElement, isInit, getAddress(),
loc, gen);
}
/// Emit the exploded element into a buffer at the specified address.
static void copyOrInitValueIntoSingleBuffer(ManagedValue explodedElement,
bool isInit,
SILValue BufferAddress,
SILLocation loc,
SILGenFunction &gen);
};
/// This is an initialization for a specific address in memory.
class KnownAddressInitialization : public SingleBufferInitialization {
/// The physical address of the global.
SILValue address;
virtual void anchor() const;
public:
KnownAddressInitialization(SILValue address) : address(address) {}
SILValue getAddressOrNull() const override {
return address;
}
};
/// Abstract base class for single-buffer initializations.
class TemporaryInitialization : public SingleBufferInitialization {
SILValue Addr;
CleanupHandle Cleanup;
public:
TemporaryInitialization(SILValue addr, CleanupHandle cleanup)
: Addr(addr), Cleanup(cleanup) {}
void finishInitialization(SILGenFunction &gen) override;
SILValue getAddressOrNull() const override {
return Addr;
}
SILValue getAddress() const {
return Addr;
}
/// Returns the cleanup corresponding to the value of the temporary.
CleanupHandle getInitializedCleanup() const { return Cleanup; }
ManagedValue getManagedAddress() const {
return ManagedValue(getAddress(), getInitializedCleanup());
}
};
/// An initialization which accumulates several other initializations
/// into a tuple.
class TupleInitialization : public Initialization {
public:
/// The sub-Initializations aggregated by this tuple initialization.
/// The TupleInitialization object takes ownership of Initializations pushed
/// here.
SmallVector<InitializationPtr, 4> SubInitializations;
TupleInitialization() {}
SILValue getAddressOrNull() const override {
if (SubInitializations.size() == 1)
return SubInitializations[0]->getAddressOrNull();
else
return SILValue();
}
bool canSplitIntoSubelementAddresses() const override {
return true;
}
MutableArrayRef<InitializationPtr>
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
SmallVectorImpl<InitializationPtr> &buf,
SILLocation Loc) override {
return SubInitializations;
}
void finishInitialization(SILGenFunction &gen) override {
for (auto &sub : SubInitializations)
sub->finishInitialization(gen);
}
void copyOrInitValueInto(ManagedValue valueMV, bool isInit, SILLocation loc,
SILGenFunction &SGF) override;
};
} // end namespace Lowering
} // end namespace swift
#endif