-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy pathInitialization.h
185 lines (155 loc) · 6.96 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
//===--- 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:
enum class Kind {
/// This Initialization is for a _ binding or other ignored value; the
/// corresponding result can be discarded.
Ignored,
/// This Initialization is to bind a 'let' declaration into VarLocs
/// directly.
LetValue,
/// This Initialization is for a single buffer with a physical address,
/// which can be accessed with getAddress() and stored to.
SingleBuffer,
/// This Initialization performs a semantic translation on its
/// operand and cannot be directly stored to.
Translating,
/// This Initialization is for a tuple of sub-initializations, which can
/// be accessed with getSubInitializations().
Tuple
};
/// The Kind of initialization.
const Kind kind;
Initialization(Kind kind) : kind(kind) {}
virtual ~Initialization() {}
/// Return true if this initialization can be forwarded down along
/// multiple branches of a conditional branch.
bool canForwardInBranch() const;
/// Return true if we can get the addresses of elements with the
/// 'getSubInitializationsForTuple' method.
bool canSplitIntoSubelementAddresses() const {
return kind != Kind::LetValue || hasAddress();
}
/// 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 true if this initialization represents a single contiguous buffer.
bool hasAddress() const { return getAddressOrNull().isValid(); }
/// 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() {
SILValue address = getAddressOrNull();
assert(address && "initialization does not represent a single buffer");
return address;
}
/// 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.
ArrayRef<InitializationPtr>
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
SmallVectorImpl<InitializationPtr> &buf,
SILLocation Loc);
/// 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()
: Initialization(Initialization::Kind::SingleBuffer)
{}
virtual ~SingleBufferInitialization();
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);
};
/// 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());
}
};
} // end namespace Lowering
} // end namespace swift
#endif