Skip to content

Commit fa6f078

Browse files
committed
Continue tidying up Initialization, NFC:
- Privatize "kind" in the base Initialization class. - Simplify canForwardInBranch() to just isSingleBuffer(). There is only one client of it (which avoids emitting the formation of an optional temporary) and the only cases we're dropping is for "_" patterns and single element tuple patterns, which are not worth optimizing for. - Change getSubInitializationsForTuple() into a virtual method since it has wildly different behavior based on the subclass and requires otherwise private implementation details of those subclasses to implement it. - Simplify subclasses based on these changes. Swift SVN r27463
1 parent 020fe78 commit fa6f078

File tree

3 files changed

+101
-98
lines changed

3 files changed

+101
-98
lines changed

lib/SILGen/Initialization.h

+29-18
Original file line numberDiff line numberDiff line change
@@ -56,32 +56,26 @@ class Initialization {
5656
/// This Initialization performs a semantic translation on its
5757
/// operand and cannot be directly stored to.
5858
Translating,
59-
/// This Initialization is for a tuple of sub-initializations, which can
60-
/// be accessed with getSubInitializations().
59+
/// This Initialization is for a tuple of sub-initializations.
6160
Tuple,
6261
/// This Initialization is for a refutable match, which occurs in refutable
6362
/// pattern contexts.
6463
Refutable
6564
};
66-
65+
private:
6766
/// The Kind of initialization.
6867
const Kind kind;
68+
public:
6969

7070
Initialization(Kind kind) : kind(kind) {}
7171
virtual ~Initialization() {}
7272

73-
/// Return true if this initialization can be forwarded down along
74-
/// multiple branches of a conditional branch.
75-
bool canForwardInBranch() const;
76-
77-
/// Return true if we can get the addresses of elements with the
78-
/// 'getSubInitializationsForTuple' method. Subclasses can override this to
79-
/// disable this behavior.
80-
virtual bool canSplitIntoSubelementAddresses() const {
81-
return true;
73+
/// Return true if this initialization is a simple address in memory.
74+
bool isSingleBuffer() const {
75+
return kind == Kind::SingleBuffer;
8276
}
83-
84-
/// If this initialization represents a single contiguous buffer, return the
77+
78+
/// If this initialization represents a single contiguous buffer, return the
8579
/// SILValue of that buffer's address. If not, returns an invalid SILValue.
8680
virtual SILValue getAddressOrNull() const = 0;
8781

@@ -101,6 +95,12 @@ class Initialization {
10195
return SILValue();
10296
}
10397

98+
/// Return true if we can get the addresses of elements with the
99+
/// 'getSubInitializationsForTuple' method. Subclasses can override this to
100+
/// enable this behavior.
101+
virtual bool canSplitIntoSubelementAddresses() const {
102+
return false;
103+
}
104104

105105
/// If this initialization represents an aggregation of sub-initializations,
106106
/// return the sub-initializations. If it represents a single
@@ -113,10 +113,13 @@ class Initialization {
113113
/// is given to this vector.
114114
/// \param Loc The location with which the single initialization should be
115115
/// associated.
116-
ArrayRef<InitializationPtr>
116+
virtual ArrayRef<InitializationPtr>
117117
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
118118
SmallVectorImpl<InitializationPtr> &buf,
119-
SILLocation Loc);
119+
SILLocation Loc) {
120+
assert(0&&"Must implement if canSplitIntoSubelementAddresses returns true");
121+
abort();
122+
}
120123

121124
/// Perform post-initialization bookkeeping for this initialization.
122125
virtual void finishInitialization(SILGenFunction &gen) {}
@@ -145,13 +148,21 @@ class SingleBufferInitialization : public Initialization {
145148
SingleBufferInitialization()
146149
: Initialization(Initialization::Kind::SingleBuffer)
147150
{}
148-
149-
virtual ~SingleBufferInitialization();
150151

151152
// SingleBufferInitializations always have an address.
152153
SILValue getAddressForInPlaceInitialization() const override {
153154
return getAddress();
154155
}
156+
157+
bool canSplitIntoSubelementAddresses() const override {
158+
return true;
159+
}
160+
161+
ArrayRef<InitializationPtr>
162+
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
163+
SmallVectorImpl<InitializationPtr> &buf,
164+
SILLocation Loc) override;
165+
155166

156167
void copyOrInitValueInto(ManagedValue explodedElement, bool isInit,
157168
SILLocation loc, SILGenFunction &gen) override {

lib/SILGen/SILGenDecl.cpp

+70-73
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,30 @@ namespace {
4646

4747
SILValue getAddressOrNull() const override { return SILValue(); }
4848

49+
bool canSplitIntoSubelementAddresses() const override {
50+
return true;
51+
}
52+
53+
ArrayRef<InitializationPtr>
54+
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
55+
SmallVectorImpl<InitializationPtr> &buf,
56+
SILLocation Loc) override {
57+
// "Destructure" an ignored binding into multiple ignored bindings.
58+
for (auto fieldType : cast<TupleType>(type)->getElementTypes()) {
59+
(void) fieldType;
60+
buf.push_back(InitializationPtr(new BlackHoleInitialization()));
61+
}
62+
return buf;
63+
}
64+
4965
void copyOrInitValueInto(ManagedValue explodedElement, bool isInit,
5066
SILLocation loc, SILGenFunction &gen) override {
5167
/// This just ignores the provided value.
5268
}
53-
5469
};
55-
70+
} // end anonymous namespace
71+
72+
namespace {
5673
/// An Initialization of a tuple pattern, such as "var (a,b)".
5774
class TupleInitialization : public Initialization {
5875
public:
@@ -69,8 +86,15 @@ namespace {
6986
else
7087
return SILValue();
7188
}
72-
73-
ArrayRef<InitializationPtr> getSubInitializations() const {
89+
90+
bool canSplitIntoSubelementAddresses() const override {
91+
return true;
92+
}
93+
94+
ArrayRef<InitializationPtr>
95+
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
96+
SmallVectorImpl<InitializationPtr> &buf,
97+
SILLocation Loc) override {
7498
return subInitializations;
7599
}
76100

@@ -83,75 +107,9 @@ namespace {
83107
SILLocation loc, SILGenFunction &gen) override {
84108
llvm_unreachable("tuple initialization not destructured?!");
85109
}
86-
87110
};
88-
}
89-
90-
bool Initialization::canForwardInBranch() const {
91-
switch (kind) {
92-
case Kind::Ignored:
93-
case Kind::SingleBuffer:
94-
return true;
95-
96-
// These initializations expect to be activated exactly once.
97-
case Kind::LetValue:
98-
case Kind::Translating:
99-
case Kind::Refutable:
100-
return false;
101-
102-
case Kind::Tuple:
103-
for (auto &subinit : ((TupleInitialization*)this)->getSubInitializations()){
104-
if (!subinit->canForwardInBranch())
105-
return false;
106-
}
107-
return true;
108-
}
109-
llvm_unreachable("bad initialization kind!");
110-
}
111-
112-
ArrayRef<InitializationPtr>
113-
Initialization::getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
114-
SmallVectorImpl<InitializationPtr> &buf,
115-
SILLocation Loc) {
116-
assert(canSplitIntoSubelementAddresses() && "Client shouldn't call this");
117-
switch (kind) {
118-
case Kind::Tuple:
119-
return ((TupleInitialization*)this)->getSubInitializations();
120-
121-
case Kind::Ignored:
122-
// "Destructure" an ignored binding into multiple ignored bindings.
123-
for (auto fieldType : cast<TupleType>(type)->getElementTypes()) {
124-
(void) fieldType;
125-
buf.push_back(InitializationPtr(new BlackHoleInitialization()));
126-
}
127-
return buf;
128-
case Kind::LetValue:
129-
case Kind::SingleBuffer: {
130-
// Destructure the buffer into per-element buffers.
131-
auto tupleTy = cast<TupleType>(type);
132-
SILValue baseAddr = getAddress();
133-
for (unsigned i = 0, size = tupleTy->getNumElements(); i < size; ++i) {
134-
auto fieldType = tupleTy.getElementType(i);
135-
SILType fieldTy = gen.getLoweredType(fieldType).getAddressType();
136-
SILValue fieldAddr = gen.B.createTupleElementAddr(Loc,
137-
baseAddr, i,
138-
fieldTy);
111+
} // end anonymous namespace
139112

140-
buf.push_back(InitializationPtr(new
141-
KnownAddressInitialization(fieldAddr)));
142-
}
143-
finishInitialization(gen);
144-
return buf;
145-
}
146-
case Kind::Translating:
147-
// This could actually be done by collecting translated values, if
148-
// we introduce new needs for translating initializations.
149-
llvm_unreachable("cannot destructure a translating initialization");
150-
case Kind::Refutable:
151-
llvm_unreachable("cannot destructure a refutable initialization");
152-
}
153-
llvm_unreachable("bad initialization kind");
154-
}
155113

156114
namespace {
157115
class CleanupClosureConstant : public Cleanup {
@@ -184,8 +142,25 @@ void SILGenFunction::visitFuncDecl(FuncDecl *fd) {
184142
}
185143
}
186144

187-
SingleBufferInitialization::~SingleBufferInitialization() {
188-
// vtable anchor.
145+
ArrayRef<InitializationPtr> SingleBufferInitialization::
146+
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
147+
SmallVectorImpl<InitializationPtr> &buf,
148+
SILLocation Loc) {
149+
// Destructure the buffer into per-element buffers.
150+
auto tupleTy = cast<TupleType>(type);
151+
SILValue baseAddr = getAddress();
152+
for (unsigned i = 0, size = tupleTy->getNumElements(); i < size; ++i) {
153+
auto fieldType = tupleTy.getElementType(i);
154+
SILType fieldTy = gen.getLoweredType(fieldType).getAddressType();
155+
SILValue fieldAddr = gen.B.createTupleElementAddr(Loc,
156+
baseAddr, i,
157+
fieldTy);
158+
159+
buf.push_back(InitializationPtr(new
160+
KnownAddressInitialization(fieldAddr)));
161+
}
162+
finishInitialization(gen);
163+
return buf;
189164
}
190165

191166
void SingleBufferInitialization::
@@ -408,6 +383,28 @@ class LetValueInitialization : public Initialization {
408383
return hasAddress();
409384
}
410385

386+
ArrayRef<InitializationPtr>
387+
getSubInitializationsForTuple(SILGenFunction &gen, CanType type,
388+
SmallVectorImpl<InitializationPtr> &buf,
389+
SILLocation Loc) override {
390+
// Destructure the buffer into per-element buffers.
391+
auto tupleTy = cast<TupleType>(type);
392+
SILValue baseAddr = getAddress();
393+
for (unsigned i = 0, size = tupleTy->getNumElements(); i < size; ++i) {
394+
auto fieldType = tupleTy.getElementType(i);
395+
SILType fieldTy = gen.getLoweredType(fieldType).getAddressType();
396+
SILValue fieldAddr = gen.B.createTupleElementAddr(Loc,
397+
baseAddr, i,
398+
fieldTy);
399+
400+
buf.push_back(InitializationPtr(new
401+
KnownAddressInitialization(fieldAddr)));
402+
}
403+
finishInitialization(gen);
404+
return buf;
405+
}
406+
407+
411408
void emitDebugValue(SILValue v, SILGenFunction &gen) {
412409
// Emit a debug_value[_addr] instruction to record the start of this value's
413410
// lifetime.

lib/SILGen/SILGenExpr.cpp

+2-7
Original file line numberDiff line numberDiff line change
@@ -2869,7 +2869,7 @@ RValue RValueEmitter::visitOptionalEvaluationExpr(OptionalEvaluationExpr *E,
28692869

28702870
std::unique_ptr<TemporaryInitialization> optTemp;
28712871
Initialization *optInit = C.getEmitInto();
2872-
bool usingProvidedContext = optInit && optInit->canForwardInBranch();
2872+
bool usingProvidedContext = optInit && optInit->isSingleBuffer();
28732873
if (!usingProvidedContext) {
28742874
optTemp = SGF.emitTemporary(E, optTL);
28752875
optInit = optTemp.get();
@@ -2903,12 +2903,7 @@ RValue RValueEmitter::visitOptionalEvaluationExpr(OptionalEvaluationExpr *E,
29032903
SGF.B.emitBlock(failureBB);
29042904

29052905
// FIXME: reset optInit here?
2906-
2907-
SILValue resultAddr = optInit->getAddressOrNull();
2908-
assert(resultAddr || optInit->kind == Initialization::Kind::Ignored);
2909-
if (resultAddr) {
2910-
SGF.emitInjectOptionalNothingInto(E, resultAddr, optTL);
2911-
}
2906+
SGF.emitInjectOptionalNothingInto(E, optInit->getAddress(), optTL);
29122907

29132908
// FIXME: finish optInit within a conditional scope.
29142909

0 commit comments

Comments
 (0)