Skip to content

Commit 3551c43

Browse files
committed
[sil] Add SILBuilder helpers for updating passes to handle both ossa and non-ossa code.
Specifically we add a groups of APIs for destructure operations. The destructure helpers are a family of functions built around emitDestructureValueOperation. These in ossa produce destructures and pass the results off to the caller in some manner that hides the internal destructure instruction. In non-ossa, the appropriate projections are created and passed off to the caller.
1 parent b3a2052 commit 3551c43

File tree

3 files changed

+61
-55
lines changed

3 files changed

+61
-55
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,41 +1370,30 @@ class SILBuilder {
13701370
getModule(), getSILDebugLocation(Loc), Operand));
13711371
}
13721372

1373-
MultipleValueInstruction *emitDestructureValueOperation(SILLocation Loc,
1374-
SILValue Operand) {
1375-
SILType OpTy = Operand->getType();
1376-
if (OpTy.is<TupleType>())
1377-
return createDestructureTuple(Loc, Operand);
1378-
if (OpTy.getStructOrBoundGenericStruct())
1379-
return createDestructureStruct(Loc, Operand);
1373+
MultipleValueInstruction *emitDestructureValueOperation(SILLocation loc,
1374+
SILValue operand) {
1375+
// If you hit this assert, you are using the wrong method. Use instead:
1376+
//
1377+
// emitDestructureValueOperation(SILLocation, SILValue,
1378+
// SmallVectorImpl<SILValue> &);
1379+
assert(hasOwnership() && "Expected to be called in ownership code only.");
1380+
SILType opTy = operand->getType();
1381+
if (opTy.is<TupleType>())
1382+
return createDestructureTuple(loc, operand);
1383+
if (opTy.getStructOrBoundGenericStruct())
1384+
return createDestructureStruct(loc, operand);
13801385
llvm_unreachable("Can not emit a destructure for this type of operand.");
13811386
}
13821387

13831388
void
1384-
emitDestructureValueOperation(SILLocation Loc, SILValue Operand,
1385-
function_ref<void(unsigned, SILValue)> Func) {
1386-
// Do a quick check to see if we have a tuple without elements. In that
1387-
// case, bail early since we are not going to ever invoke Func.
1388-
if (auto TTy = Operand->getType().castTo<TupleType>())
1389-
if (0 == TTy->getNumElements())
1390-
return;
1391-
1392-
auto *Destructure = emitDestructureValueOperation(Loc, Operand);
1393-
auto Results = Destructure->getResults();
1394-
// TODO: For some reason, llvm::enumerate(Results) does not
1395-
// compile.
1396-
for (unsigned i : indices(Results)) {
1397-
Func(i, Results[i]);
1398-
}
1399-
}
1389+
emitDestructureValueOperation(SILLocation loc, SILValue operand,
1390+
function_ref<void(unsigned, SILValue)> func);
14001391

1401-
void
1402-
emitShallowDestructureValueOperation(SILLocation Loc, SILValue Operand,
1403-
llvm::SmallVectorImpl<SILValue> &Result);
1392+
void emitDestructureValueOperation(SILLocation loc, SILValue operand,
1393+
SmallVectorImpl<SILValue> &result);
14041394

1405-
void emitShallowDestructureAddressOperation(
1406-
SILLocation Loc, SILValue Operand,
1407-
llvm::SmallVectorImpl<SILValue> &Result);
1395+
void emitDestructureAddressOperation(SILLocation loc, SILValue operand,
1396+
SmallVectorImpl<SILValue> &result);
14081397

14091398
ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
14101399
SILDeclRef Member, SILType MethodTy) {

lib/SIL/SILBuilder.cpp

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -502,54 +502,71 @@ ValueMetatypeInst *SILBuilder::createValueMetatype(SILLocation Loc,
502502
}
503503

504504
// TODO: This should really be an operation on type lowering.
505-
void SILBuilder::emitShallowDestructureValueOperation(
506-
SILLocation Loc, SILValue V, llvm::SmallVectorImpl<SILValue> &Results) {
505+
void SILBuilder::emitDestructureValueOperation(
506+
SILLocation loc, SILValue v, SmallVectorImpl<SILValue> &results) {
507507
// Once destructure is allowed everywhere, remove the projection code.
508508

509509
// If we do not have a tuple or a struct, add to our results list and return.
510-
SILType Ty = V->getType();
511-
if (!(Ty.is<TupleType>() || Ty.getStructOrBoundGenericStruct())) {
512-
Results.emplace_back(V);
510+
SILType type = v->getType();
511+
if (!(type.is<TupleType>() || type.getStructOrBoundGenericStruct())) {
512+
results.emplace_back(v);
513513
return;
514514
}
515515

516516
// Otherwise, we want to destructure add the destructure and return.
517517
if (getFunction().hasOwnership()) {
518-
auto *DI = emitDestructureValueOperation(Loc, V);
519-
copy(DI->getResults(), std::back_inserter(Results));
518+
auto *i = emitDestructureValueOperation(loc, v);
519+
copy(i->getResults(), std::back_inserter(results));
520520
return;
521521
}
522522

523523
// In non qualified ownership SIL, drop back to using projection code.
524-
llvm::SmallVector<Projection, 16> Projections;
525-
Projection::getFirstLevelProjections(V->getType(), getModule(), Projections);
526-
transform(Projections, std::back_inserter(Results),
527-
[&](const Projection &P) -> SILValue {
528-
return P.createObjectProjection(*this, Loc, V).get();
524+
SmallVector<Projection, 16> projections;
525+
Projection::getFirstLevelProjections(v->getType(), getModule(), projections);
526+
transform(projections, std::back_inserter(results),
527+
[&](const Projection &p) -> SILValue {
528+
return p.createObjectProjection(*this, loc, v).get();
529529
});
530530
}
531531

532532
// TODO: Can we put this on type lowering? It would take a little bit of work
533533
// since we would need to be able to handle aggregate trivial types which is not
534534
// represented today in TypeLowering.
535-
void SILBuilder::emitShallowDestructureAddressOperation(
536-
SILLocation Loc, SILValue V, llvm::SmallVectorImpl<SILValue> &Results) {
535+
void SILBuilder::emitDestructureAddressOperation(
536+
SILLocation loc, SILValue v, SmallVectorImpl<SILValue> &results) {
537537

538538
// If we do not have a tuple or a struct, add to our results list.
539-
SILType Ty = V->getType();
540-
if (!(Ty.is<TupleType>() || Ty.getStructOrBoundGenericStruct())) {
541-
Results.emplace_back(V);
539+
SILType type = v->getType();
540+
if (!(type.is<TupleType>() || type.getStructOrBoundGenericStruct())) {
541+
results.emplace_back(v);
542542
return;
543543
}
544544

545-
llvm::SmallVector<Projection, 16> Projections;
546-
Projection::getFirstLevelProjections(V->getType(), getModule(), Projections);
547-
transform(Projections, std::back_inserter(Results),
548-
[&](const Projection &P) -> SILValue {
549-
return P.createAddressProjection(*this, Loc, V).get();
545+
SmallVector<Projection, 16> projections;
546+
Projection::getFirstLevelProjections(v->getType(), getModule(), projections);
547+
transform(projections, std::back_inserter(results),
548+
[&](const Projection &p) -> SILValue {
549+
return p.createAddressProjection(*this, loc, v).get();
550550
});
551551
}
552552

553+
void SILBuilder::emitDestructureValueOperation(
554+
SILLocation loc, SILValue operand,
555+
function_ref<void(unsigned, SILValue)> func) {
556+
// Do a quick check to see if we have a tuple without elements. In that
557+
// case, bail early since we are not going to ever invoke Func.
558+
if (auto tupleType = operand->getType().castTo<TupleType>())
559+
if (0 == tupleType->getNumElements())
560+
return;
561+
562+
SmallVector<SILValue, 8> results;
563+
emitDestructureValueOperation(loc, operand, results);
564+
565+
for (auto p : llvm::enumerate(results)) {
566+
func(p.index(), p.value());
567+
}
568+
}
569+
553570
DebugValueInst *SILBuilder::createDebugValue(SILLocation Loc, SILValue src,
554571
SILDebugVariable Var) {
555572
assert(isLoadableOrOpaque(src->getType()));

lib/SILGen/SILGenPoly.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,11 +673,11 @@ static void explodeTuple(SILGenFunction &SGF, SILLocation loc,
673673
bool isPlusOne = managedTuple.hasCleanup();
674674

675675
if (managedTuple.getType().isAddress()) {
676-
SGF.B.emitShallowDestructureAddressOperation(loc, managedTuple.forward(SGF),
677-
elements);
676+
SGF.B.emitDestructureAddressOperation(loc, managedTuple.forward(SGF),
677+
elements);
678678
} else {
679-
SGF.B.emitShallowDestructureValueOperation(loc, managedTuple.forward(SGF),
680-
elements);
679+
SGF.B.emitDestructureValueOperation(loc, managedTuple.forward(SGF),
680+
elements);
681681
}
682682

683683
for (auto element : elements) {

0 commit comments

Comments
 (0)