Skip to content

Commit

Permalink
Reimplement materializeForSet emission in SILGen instead of
Browse files Browse the repository at this point in the history
the type-checker.  The strategy for now is to just use this
for protocol witness thunk emission, where it is required
when generating a materializeForSet for storage that is
either implemented in a protocol extension or requires
reabstraction to the requirement's pattern.

Eventually, this should be generalized to the point that
we can use it for all materializeForSet emission, which
I don't think will take much.  However, that's not really
the sort of instability we want to embrace for the current
release.

WIP towards rdar://21836671; currently disabled, so NFC.

Swift SVN r31072
  • Loading branch information
rjmccall committed Aug 7, 2015
1 parent 9f10b69 commit 807f7f5
Show file tree
Hide file tree
Showing 7 changed files with 916 additions and 108 deletions.
1 change: 1 addition & 0 deletions include/swift/SIL/TypeLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ class TypeConverter {
AbstractionPattern getAbstractionPattern(AbstractStorageDecl *storage);
AbstractionPattern getAbstractionPattern(VarDecl *var);
AbstractionPattern getAbstractionPattern(SubscriptDecl *subscript);
AbstractionPattern getIndicesAbstractionPattern(SubscriptDecl *subscript);
AbstractionPattern getAbstractionPattern(EnumElementDecl *element);

SILType getLoweredTypeOfGlobal(VarDecl *var);
Expand Down
7 changes: 7 additions & 0 deletions lib/SIL/AbstractionPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,16 @@ AbstractionPattern TypeConverter::getAbstractionPattern(AbstractStorageDecl *dec

AbstractionPattern TypeConverter::getAbstractionPattern(SubscriptDecl *decl) {
// TODO: honor the declared type?
// TODO: use interface types
return AbstractionPattern(decl->getElementType());
}

AbstractionPattern
TypeConverter::getIndicesAbstractionPattern(SubscriptDecl *decl) {
// TODO: use interface types
return AbstractionPattern(decl->getIndicesType());
}

bool AbstractionPattern::isOpaqueType(CanGenericSignature signature,
CanGenericTypeParamType type) {
// Enormous hack! We need to be asking the signature about this
Expand Down
31 changes: 31 additions & 0 deletions lib/SILGen/LValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,37 @@ class LValue {
Path.emplace_back(new T(std::forward<As>(args)...));
}

/// Add a member component to the access path of this lvalue.
void addMemberComponent(SILGenFunction &gen, SILLocation loc,
AbstractStorageDecl *storage,
ArrayRef<Substitution> subs,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
AccessStrategy accessStrategy,
CanType formalRValueType,
RValue &&indices);

void addMemberVarComponent(SILGenFunction &gen, SILLocation loc,
VarDecl *var,
ArrayRef<Substitution> subs,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
AccessStrategy accessStrategy,
CanType formalRValueType);

void addMemberSubscriptComponent(SILGenFunction &gen, SILLocation loc,
SubscriptDecl *subscript,
ArrayRef<Substitution> subs,
bool isSuper,
AccessKind accessKind,
AccessSemantics accessSemantics,
AccessStrategy accessStrategy,
CanType formalRValueType,
RValue &&indices,
Expr *indexExprForDiagnostics = nullptr);

/// Add a subst-to-orig reabstraction component. That is, given
/// that this l-value trafficks in values following the substituted
/// abstraction pattern, make an l-value trafficking in values
Expand Down
86 changes: 41 additions & 45 deletions lib/SILGen/RValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,61 +49,57 @@ namespace {
class ExplodeTupleValue
: public CanTypeVisitor<ExplodeTupleValue,
/*RetTy=*/ void,
/*Args...=*/ ManagedValue, SILLocation>
/*Args...=*/ ManagedValue>
{
public:
std::vector<ManagedValue> &values;
SILGenFunction &gen;
SILLocation loc;

ExplodeTupleValue(std::vector<ManagedValue> &values,
SILGenFunction &gen)
: values(values), gen(gen)
SILGenFunction &gen, SILLocation loc)
: values(values), gen(gen), loc(loc)
{
}

void visitType(CanType t, ManagedValue v, SILLocation l) {
void visitType(CanType formalType, ManagedValue v) {
values.push_back(v);
}

void visitTupleType(CanTupleType t, ManagedValue mv, SILLocation l) {
bool IsPlusZero = mv.isPlusZeroRValueOrTrivial();

SILValue v = mv.forward(gen);
if (v.getType().isAddressOnly(gen.F.getModule())) {
// Destructure address-only types by addressing the individual members.
for (unsigned i = 0, size = t->getNumElements(); i < size; ++i) {
CanType fieldCanTy = t.getElementType(i);
auto &fieldTI = gen.getTypeLowering(fieldCanTy);
SILType fieldTy = fieldTI.getLoweredType();
SILValue member = gen.B.createTupleElementAddr(l, v, i,
fieldTy.getAddressType());
assert(fieldTI.getSemanticType() == fieldTy);
if (fieldTI.isLoadable() && !isa<InOutType>(fieldCanTy))
member = gen.B.createLoad(l, member);

// If we're returning a +1 value, emit a cleanup for the member to cover
// for the cleanup we disabled for the tuple aggregate.
auto SubValue = IsPlusZero ? ManagedValue::forUnmanaged(member)
: gen.emitManagedRValueWithCleanup(member, fieldTI);

visit(fieldCanTy, SubValue, l);
}
} else {
// Extract the elements from loadable tuples.
for (unsigned i = 0, size = t->getNumElements(); i < size; ++i) {
CanType fieldCanTy = t.getElementType(i);
auto &fieldTI = gen.getTypeLowering(fieldCanTy);
assert(fieldTI.isLoadable());
SILValue member = gen.B.createTupleExtract(l, v, i,
fieldTI.getLoweredType());

// If we're returning a +1 value, emit a cleanup for the member to cover
// for the cleanup we disabled for the tuple aggregate.
auto SubValue = IsPlusZero ? ManagedValue::forUnmanaged(member)
: gen.emitManagedRValueWithCleanup(member, fieldTI);

visit(fieldCanTy, SubValue, l);
void visitTupleType(CanTupleType tupleFormalType, ManagedValue tupleMV) {
bool isPlusZero = tupleMV.isPlusZeroRValueOrTrivial();
SILValue tuple = tupleMV.forward(gen);

for (auto i : indices(tupleFormalType->getElements())) {
CanType eltFormalType = tupleFormalType.getElementType(i);
assert(eltFormalType->isMaterializable());

auto eltTy = tuple.getType().getTupleElementType(i);
assert(eltTy.isAddress() == tuple.getType().isAddress());
auto &eltTI = gen.getTypeLowering(eltTy);

// Project the element.
SILValue elt;
if (tuple.getType().isObject()) {
assert(eltTI.isLoadable());
elt = gen.B.createTupleExtract(loc, tuple, i, eltTy);
} else {
elt = gen.B.createTupleElementAddr(loc, tuple, i, eltTy);

// RValue has an invariant that loadable values have been
// loaded. Except it's not really an invariant, because
// argument emission likes to lie sometimes.
if (eltTI.isLoadable()) {
elt = gen.B.createLoad(loc, elt);
}
}

// If we're returning a +1 value, emit a cleanup for the member
// to cover for the cleanup we disabled for the tuple aggregate.
auto eltMV = isPlusZero ? ManagedValue::forUnmanaged(elt)
: gen.emitManagedRValueWithCleanup(elt, eltTI);

visit(eltFormalType, eltMV);
}
}
};
Expand Down Expand Up @@ -375,7 +371,7 @@ RValue::RValue(SILGenFunction &gen, SILLocation l, CanType formalType,
return;
}

ExplodeTupleValue(values, gen).visit(type, v, l);
ExplodeTupleValue(values, gen, l).visit(formalType, v);
assert(values.size() == getRValueSize(type));
}

Expand All @@ -389,7 +385,7 @@ RValue::RValue(SILGenFunction &gen, Expr *expr, ManagedValue v)
}

assert(v && "creating r-value with consumed value");
ExplodeTupleValue(values, gen).visit(type, v, expr);
ExplodeTupleValue(values, gen, expr).visit(type, v);
assert(values.size() == getRValueSize(type));
}

Expand All @@ -416,7 +412,7 @@ void RValue::addElement(SILGenFunction &gen, ManagedValue element,
assert(!isUsed() && "rvalue already used");
--elementsToBeAdded;

ExplodeTupleValue(values, gen).visit(formalType, element, l);
ExplodeTupleValue(values, gen, l).visit(formalType, element);

assert(!isComplete() || values.size() == getRValueSize(type));
}
Expand Down
5 changes: 5 additions & 0 deletions lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
bool isSuper, bool isDirectAccessorUse,
RValue &&optionalSubscripts,
SILValue buffer, SILValue callbackStorage);
bool maybeEmitMaterializeForSetThunk(ProtocolConformance *conformance,
FuncDecl *requirement,
FuncDecl *witness,
ArrayRef<Substitution> witnessSubs,
ArrayRef<ManagedValue> params);

SILDeclRef getAddressorDeclRef(AbstractStorageDecl *decl,
AccessKind accessKind,
Expand Down
Loading

0 comments on commit 807f7f5

Please sign in to comment.