Skip to content

Commit 07f5b8d

Browse files
authored
Merge pull request #10987 from rjmccall/bridging-peephole
2 parents 0bba7d9 + 80b180a commit 07f5b8d

34 files changed

+1667
-495
lines changed

include/swift/Basic/ExternalUnion.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#ifndef SWIFT_BASIC_EXTERNALUNION_H
2323
#define SWIFT_BASIC_EXTERNALUNION_H
2424

25-
#include "llvm/Support/Compiler.h"
25+
#include "llvm/Support/ErrorHandling.h"
2626
#include "swift/Basic/type_traits.h"
2727
#include <utility>
2828
#include <assert.h>
@@ -160,6 +160,26 @@ class BasicExternalUnion {
160160
return reinterpret_cast<const T &>(Storage);
161161
}
162162

163+
/// Destruct the current union member.
164+
template <class T>
165+
void resetToEmptyWithoutIndex() {
166+
constexpr int typeIndex = indexOf<T, Members...>::value;
167+
static_assert(typeIndex != -1, "type not in union");
168+
169+
reinterpret_cast<T&>(Storage).T::~T();
170+
}
171+
172+
/// Destroy the current union member.
173+
template <class T>
174+
void resetToEmpty(int oldIndex, int newIndex) {
175+
constexpr int typeIndex = indexOf<T, Members...>::value;
176+
static_assert(typeIndex != -1, "type not in union");
177+
assert(oldIndex == typeIndex && "current kind is wrong for value");
178+
assert(newIndex == -1 && "new kind is not in union");
179+
180+
reinterpret_cast<T&>(Storage).T::~T();
181+
}
182+
163183
/// Copy-construct the union from another union.
164184
void copyConstruct(int index, const BasicExternalUnion &other) {
165185
if (index != -1) {
@@ -252,6 +272,18 @@ class ExternalUnion {
252272
#endif
253273
}
254274

275+
/// Destroy the current member of the union and switch to a member
276+
/// that has no storage.
277+
template <class T>
278+
void resetToEmpty(Kind curKind, Kind newKind) {
279+
#ifndef NDEBUG
280+
return Union.template resetToEmpty<T>(GetIndexForKind(curKind),
281+
GetIndexForKind(newKind));
282+
#else
283+
return Union.template resetToEmptyWithoutIndex<T>();
284+
#endif
285+
}
286+
255287
/// Return a reference to a union member, asserting that the current
256288
/// kind is right.
257289
template <class T>
@@ -299,7 +331,7 @@ class ExternalUnion {
299331
/// Destroy the union from another union.
300332
void destruct(Kind kind) {
301333
Union.destruct(GetIndexForKind(kind));
302-
}
334+
}
303335
};
304336

305337
/// A helper class for defining special members.

lib/SILGen/ArgumentSource.cpp

Lines changed: 183 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,49 @@ RValue &ArgumentSource::forceAndPeekRValue(SILGenFunction &SGF) & {
2626
return peekRValue();
2727
}
2828

29-
auto expr = asKnownExpr();
29+
// Extract an r-value.
30+
SILLocation loc = getLocation();
31+
RValue value = std::move(*this).getAsRValue(SGF);
32+
33+
// Destroy the current state.
34+
Storage.destruct(StoredKind);
35+
36+
// Emplace the r-value back into the source.
3037
StoredKind = Kind::RValue;
31-
new (&Storage.TheRV.Value) RValue(SGF.emitRValue(expr));
32-
Storage.TheRV.Loc = expr;
33-
return Storage.TheRV.Value;
38+
Storage.emplaceAggregate<RValueStorage>(StoredKind, std::move(value), loc);
39+
40+
return peekRValue();
3441
}
3542

3643
RValue &ArgumentSource::peekRValue() & {
3744
assert(isRValue() && "Undefined behavior to call this method without the "
3845
"ArgumentSource actually being an RValue");
39-
return Storage.TheRV.Value;
46+
return Storage.get<RValueStorage>(StoredKind).Value;
4047
}
4148

4249
void ArgumentSource::rewriteType(CanType newType) & {
43-
assert(!isLValue());
44-
if (isRValue()) {
45-
Storage.TheRV.Value.rewriteType(newType);
46-
} else {
47-
Expr *expr = Storage.TheExpr;
50+
switch (StoredKind) {
51+
case Kind::Invalid:
52+
llvm_unreachable("argument source is invalid");
53+
case Kind::LValue:
54+
llvm_unreachable("cannot rewrite type of l-value");
55+
case Kind::Tuple:
56+
llvm_unreachable("cannot rewrite type of tuple");
57+
case Kind::RValue:
58+
Storage.get<RValueStorage>(StoredKind).Value.rewriteType(newType);
59+
return;
60+
case Kind::Expr:
61+
Expr *expr = Storage.get<Expr*>(StoredKind);
4862
if (expr->getType()->isEqual(newType)) return;
4963
llvm_unreachable("unimplemented! hope it doesn't happen");
5064
}
65+
llvm_unreachable("bad kind");
5166
}
5267

53-
bool ArgumentSource::requiresCalleeToEvaluate() {
68+
bool ArgumentSource::requiresCalleeToEvaluate() const {
5469
switch (StoredKind) {
70+
case Kind::Invalid:
71+
llvm_unreachable("argument source is invalid");
5572
case Kind::RValue:
5673
case Kind::LValue:
5774
return false;
@@ -85,38 +102,103 @@ bool ArgumentSource::requiresCalleeToEvaluate() {
85102
}
86103
}
87104
return false;
105+
case Kind::Tuple:
106+
for (auto &source : Storage.get<TupleStorage>(StoredKind).Elements) {
107+
if (source.requiresCalleeToEvaluate())
108+
return true;
109+
}
110+
return false;
88111
}
89-
90-
llvm_unreachable("Unhandled Kind in switch.");
112+
llvm_unreachable("bad kind");
91113
}
92114

93115
RValue ArgumentSource::getAsRValue(SILGenFunction &SGF, SGFContext C) && {
94-
assert(!isLValue());
95-
if (isRValue())
116+
switch (StoredKind) {
117+
case Kind::Invalid:
118+
llvm_unreachable("argument source is invalid");
119+
case Kind::LValue:
120+
llvm_unreachable("cannot get l-value as r-value");
121+
case Kind::RValue:
96122
return std::move(*this).asKnownRValue();
123+
case Kind::Expr:
124+
return SGF.emitRValue(std::move(*this).asKnownExpr(), C);
125+
case Kind::Tuple:
126+
return std::move(*this).getKnownTupleAsRValue(SGF, C);
127+
}
128+
llvm_unreachable("bad kind");
129+
}
130+
131+
RValue
132+
ArgumentSource::getKnownTupleAsRValue(SILGenFunction &SGF, SGFContext C) && {
133+
134+
return std::move(*this).withKnownTupleElementSources<RValue>(
135+
[&](SILLocation loc, CanTupleType type,
136+
MutableArrayRef<ArgumentSource> elements) {
137+
// If there's a target initialization, and we can split it, do so.
138+
if (auto init = C.getEmitInto()) {
139+
if (init->canSplitIntoTupleElements()) {
140+
// Split the tuple.
141+
SmallVector<InitializationPtr, 4> scratch;
142+
auto eltInits = init->splitIntoTupleElements(SGF, loc, type, scratch);
143+
144+
// Emit each element into the corresponding element initialization.
145+
for (auto i : indices(eltInits)) {
146+
std::move(elements[i]).forwardInto(SGF, eltInits[i].get());
147+
}
148+
149+
// Finish initialization.
150+
init->finishInitialization(SGF);
97151

98-
return SGF.emitRValue(std::move(*this).asKnownExpr(), C);
152+
return RValue::forInContext();
153+
}
154+
}
155+
156+
// Otherwise, emit all of the elements into a single big r-value.
157+
RValue result(type);
158+
for (auto &element : elements) {
159+
result.addElement(std::move(element).getAsRValue(SGF));
160+
}
161+
return result;
162+
});
99163
}
100164

101165
ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &SGF,
102166
SGFContext C) && {
103-
if (isRValue()) {
104-
auto loc = getKnownRValueLocation();
105-
return std::move(*this).asKnownRValue().getAsSingleValue(SGF, loc);
106-
}
107-
if (isLValue()) {
167+
switch (StoredKind) {
168+
case Kind::Invalid:
169+
llvm_unreachable("argument source is invalid");
170+
case Kind::LValue: {
108171
auto loc = getKnownLValueLocation();
109172
return SGF.emitAddressOfLValue(loc, std::move(*this).asKnownLValue(),
110173
AccessKind::ReadWrite);
111174
}
112-
113-
auto e = std::move(*this).asKnownExpr();
114-
if (e->getType()->is<InOutType>()) {
115-
return SGF.emitAddressOfLValue(e, SGF.emitLValue(e, AccessKind::ReadWrite),
116-
AccessKind::ReadWrite);
117-
} else {
118-
return SGF.emitRValueAsSingleValue(e, C);
175+
case Kind::RValue: {
176+
auto loc = getKnownRValueLocation();
177+
if (auto init = C.getEmitInto()) {
178+
std::move(*this).asKnownRValue().forwardInto(SGF, loc, init);
179+
return ManagedValue::forInContext();
180+
} else {
181+
return std::move(*this).asKnownRValue().getAsSingleValue(SGF, loc);
182+
}
183+
}
184+
case Kind::Expr: {
185+
auto e = std::move(*this).asKnownExpr();
186+
if (e->getType()->is<InOutType>()) {
187+
return SGF.emitAddressOfLValue(e, SGF.emitLValue(e, AccessKind::ReadWrite),
188+
AccessKind::ReadWrite);
189+
} else {
190+
return SGF.emitRValueAsSingleValue(e, C);
191+
}
192+
}
193+
case Kind::Tuple: {
194+
auto loc = getKnownTupleLocation();
195+
auto rvalue = std::move(*this).getKnownTupleAsRValue(SGF, C);
196+
if (rvalue.isInContext())
197+
return ManagedValue::forInContext();
198+
return std::move(rvalue).getAsSingleValue(SGF, loc);
199+
}
119200
}
201+
llvm_unreachable("bad kind");
120202
}
121203

122204

@@ -131,40 +213,58 @@ ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &SGF,
131213
ManagedValue ArgumentSource::getConverted(SILGenFunction &SGF,
132214
const Conversion &conversion,
133215
SGFContext C) && {
134-
assert(!isLValue());
135-
136-
if (isRValue()) {
137-
auto loc = getKnownRValueLocation();
138-
auto result = std::move(*this).asKnownRValue().getAsSingleValue(SGF, loc);
139-
return conversion.emit(SGF, loc, result, C);
216+
switch (StoredKind) {
217+
case Kind::Invalid:
218+
llvm_unreachable("argument source is invalid");
219+
case Kind::LValue:
220+
llvm_unreachable("cannot get converted l-value");
221+
case Kind::RValue:
222+
case Kind::Expr:
223+
case Kind::Tuple:
224+
return SGF.emitConvertedRValue(getLocation(), conversion, C,
225+
[&](SILGenFunction &SGF, SILLocation loc, SGFContext C) {
226+
return std::move(*this).getAsSingleValue(SGF, C);
227+
});
140228
}
141-
142-
auto e = std::move(*this).asKnownExpr();
143-
assert(!e->getType()->is<InOutType>());
144-
return SGF.emitConvertedRValue(e, conversion, C);
229+
llvm_unreachable("bad kind");
145230
}
146231

147232
void ArgumentSource::forwardInto(SILGenFunction &SGF, Initialization *dest) && {
148-
assert(!isLValue());
149-
if (isRValue()) {
233+
switch (StoredKind) {
234+
case Kind::Invalid:
235+
llvm_unreachable("argument source is invalid");
236+
case Kind::LValue:
237+
llvm_unreachable("cannot forward an l-value");
238+
case Kind::RValue: {
150239
auto loc = getKnownRValueLocation();
151-
return std::move(*this).asKnownRValue().forwardInto(SGF, loc, dest);
240+
std::move(*this).asKnownRValue().forwardInto(SGF, loc, dest);
241+
return;
152242
}
153-
154-
auto e = std::move(*this).asKnownExpr();
155-
return SGF.emitExprInto(e, dest);
243+
case Kind::Expr: {
244+
auto e = std::move(*this).asKnownExpr();
245+
SGF.emitExprInto(e, dest);
246+
return;
247+
}
248+
case Kind::Tuple: {
249+
auto loc = getKnownTupleLocation();
250+
auto rvalue = std::move(*this).getKnownTupleAsRValue(SGF, SGFContext(dest));
251+
if (!rvalue.isInContext())
252+
std::move(rvalue).forwardInto(SGF, loc, dest);
253+
return;
254+
}
255+
}
256+
llvm_unreachable("bad kind");
156257
}
157258

158259
ManagedValue ArgumentSource::materialize(SILGenFunction &SGF) && {
159-
assert(!isLValue());
160260
if (isRValue()) {
161261
auto loc = getKnownRValueLocation();
162262
return std::move(*this).asKnownRValue().materialize(SGF, loc);
163263
}
164264

165-
auto expr = std::move(*this).asKnownExpr();
166-
auto temp = SGF.emitTemporary(expr, SGF.getTypeLowering(expr->getType()));
167-
SGF.emitExprInto(expr, temp.get());
265+
auto loc = getLocation();
266+
auto temp = SGF.emitTemporary(loc, SGF.getTypeLowering(getSubstType()));
267+
std::move(*this).forwardInto(SGF, temp.get());
168268
return temp->getManagedAddress();
169269
}
170270

@@ -245,3 +345,38 @@ SILType ArgumentSource::getSILSubstType(SILGenFunction &SGF) const & {
245345
AbstractionPattern origType(funcType->getGenericSignature(), substType);
246346
return SGF.getLoweredType(origType, substType);
247347
}
348+
349+
void ArgumentSource::dump() const {
350+
dump(llvm::errs());
351+
}
352+
void ArgumentSource::dump(raw_ostream &out, unsigned indent) const {
353+
out.indent(indent) << "ArgumentSource::";
354+
switch (StoredKind) {
355+
case Kind::Invalid:
356+
out << "Invalid\n";
357+
return;
358+
case Kind::LValue:
359+
out << "LValue\n";
360+
Storage.get<LValueStorage>(StoredKind).Value.dump(out, indent + 2);
361+
return;
362+
case Kind::Tuple: {
363+
out << "Tuple\n";
364+
auto &storage = Storage.get<TupleStorage>(StoredKind);
365+
storage.SubstType.dump(out, indent + 2);
366+
for (auto &elt : storage.Elements) {
367+
elt.dump(out, indent + 2);
368+
out << '\n';
369+
}
370+
return;
371+
}
372+
case Kind::RValue:
373+
out << "RValue\n";
374+
Storage.get<RValueStorage>(StoredKind).Value.dump(out, indent + 2);
375+
return;
376+
case Kind::Expr:
377+
out << "Expr\n";
378+
Storage.get<Expr*>(StoredKind)->dump(out); // FIXME: indent
379+
return;
380+
}
381+
llvm_unreachable("bad kind");
382+
}

0 commit comments

Comments
 (0)