SILGen: Handle abstraction differences in stored property access.

When we produce a physical LValue with an abstraction difference, cap off the LValue with a logical "OrigToSubstComponent", which enacts the abstraction change on load or store, and introduces a writeback for the property when used in an @inout context.

Swift SVN r11498
This commit is contained in:
Joe Groff
2013-12-20 02:25:11 +00:00
parent b29748a6be
commit 706e7baac4
4 changed files with 138 additions and 10 deletions

View File

@@ -198,10 +198,6 @@ SILGenFunction::Writeback::Writeback(SILLocation loc,
{
}
LValue SILGenFunction::emitLValue(Expr *e) {
return SILGenLValue(*this).visit(e);
}
RValue SILGenFunction::emitLValueAsRValue(Expr *e) {
LValue lv = emitLValue(e);
return RValue(*this, e, emitAddressOfLValue(e, lv));
@@ -448,6 +444,64 @@ namespace {
return std::unique_ptr<LogicalPathComponent>(clone);
}
};
/// Remap an lvalue referencing a generic type to an lvalue of its substituted
/// type in a concrete context.
class OrigToSubstComponent : public LogicalPathComponent {
AbstractionPattern origType;
CanType substType;
public:
OrigToSubstComponent(SILGenFunction &gen,
AbstractionPattern origType, CanType substType)
: LogicalPathComponent(getUnsubstitutedTypeData(gen, substType)),
origType(origType), substType(substType)
{}
bool isSettable() const override {
return true;
}
void set(SILGenFunction &gen, SILLocation loc,
RValueSource &&rvalue, SILValue base) const override {
// Map the value to the original abstraction level.
ManagedValue mv = std::move(rvalue).getAsSingleValue(gen);
mv = gen.emitSubstToOrigValue(loc, mv, origType, substType);
// Store to the base.
mv.assignInto(gen, loc, base);
}
ManagedValue get(SILGenFunction &gen, SILLocation loc,
SILValue base, SGFContext c) const override {
// Load the original value.
ManagedValue baseVal = gen.emitLoad(loc, base,
gen.getTypeLowering(base.getType()),
SGFContext(),
IsNotTake);
// Map the base value to its substituted representation.
return gen.emitOrigToSubstValue(loc, baseVal,
origType, substType, c);
}
std::unique_ptr<LogicalPathComponent>
clone(SILGenFunction &gen, SILLocation loc) const override {
LogicalPathComponent *clone
= new OrigToSubstComponent(gen, origType, substType);
return std::unique_ptr<LogicalPathComponent>(clone);
}
};
}
LValue SILGenFunction::emitLValue(Expr *e) {
LValue r = SILGenLValue(*this).visit(e);
// If the final component is physical with an abstraction change, introduce a
// reabstraction component.
if (r.isLastComponentPhysical()) {
if (r.getOrigFormalType().getAsType() != r.getSubstFormalType())
r.add<OrigToSubstComponent>(*this, r.getOrigFormalType(),
r.getSubstFormalType());
}
return r;
}
LValue SILGenLValue::visitRec(Expr *e) {