Skip to content

[sil] Add SILBuilder helpers for updating passes to handle both ossa … #21824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 18 additions & 29 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1370,41 +1370,30 @@ class SILBuilder {
getModule(), getSILDebugLocation(Loc), Operand));
}

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

void
emitDestructureValueOperation(SILLocation Loc, SILValue Operand,
function_ref<void(unsigned, SILValue)> Func) {
// Do a quick check to see if we have a tuple without elements. In that
// case, bail early since we are not going to ever invoke Func.
if (auto TTy = Operand->getType().castTo<TupleType>())
if (0 == TTy->getNumElements())
return;

auto *Destructure = emitDestructureValueOperation(Loc, Operand);
auto Results = Destructure->getResults();
// TODO: For some reason, llvm::enumerate(Results) does not
// compile.
for (unsigned i : indices(Results)) {
Func(i, Results[i]);
}
}
emitDestructureValueOperation(SILLocation loc, SILValue operand,
function_ref<void(unsigned, SILValue)> func);

void
emitShallowDestructureValueOperation(SILLocation Loc, SILValue Operand,
llvm::SmallVectorImpl<SILValue> &Result);
void emitDestructureValueOperation(SILLocation loc, SILValue operand,
SmallVectorImpl<SILValue> &result);

void emitShallowDestructureAddressOperation(
SILLocation Loc, SILValue Operand,
llvm::SmallVectorImpl<SILValue> &Result);
void emitDestructureAddressOperation(SILLocation loc, SILValue operand,
SmallVectorImpl<SILValue> &result);

ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILType MethodTy) {
Expand Down
61 changes: 39 additions & 22 deletions lib/SIL/SILBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,54 +502,71 @@ ValueMetatypeInst *SILBuilder::createValueMetatype(SILLocation Loc,
}

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

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

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

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

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

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

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

void SILBuilder::emitDestructureValueOperation(
SILLocation loc, SILValue operand,
function_ref<void(unsigned, SILValue)> func) {
// Do a quick check to see if we have a tuple without elements. In that
// case, bail early since we are not going to ever invoke Func.
if (auto tupleType = operand->getType().castTo<TupleType>())
if (0 == tupleType->getNumElements())
return;

SmallVector<SILValue, 8> results;
emitDestructureValueOperation(loc, operand, results);

for (auto p : llvm::enumerate(results)) {
func(p.index(), p.value());
}
}

DebugValueInst *SILBuilder::createDebugValue(SILLocation Loc, SILValue src,
SILDebugVariable Var) {
assert(isLoadableOrOpaque(src->getType()));
Expand Down
8 changes: 4 additions & 4 deletions lib/SILGen/SILGenPoly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,11 +673,11 @@ static void explodeTuple(SILGenFunction &SGF, SILLocation loc,
bool isPlusOne = managedTuple.hasCleanup();

if (managedTuple.getType().isAddress()) {
SGF.B.emitShallowDestructureAddressOperation(loc, managedTuple.forward(SGF),
elements);
SGF.B.emitDestructureAddressOperation(loc, managedTuple.forward(SGF),
elements);
} else {
SGF.B.emitShallowDestructureValueOperation(loc, managedTuple.forward(SGF),
elements);
SGF.B.emitDestructureValueOperation(loc, managedTuple.forward(SGF),
elements);
}

for (auto element : elements) {
Expand Down