Skip to content

Fixes for assorted SILGen bugs #6543

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
merged 8 commits into from
Jan 4, 2017
Merged
22 changes: 22 additions & 0 deletions lib/SIL/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2209,6 +2209,28 @@ namespace {
substObjectType));
}

/// Metatypes get DynamicSelfType stripped off the instance type.
CanType visitMetatypeType(CanMetatypeType origType) {
CanType origInstanceType = origType.getInstanceType();
CanType substInstanceType = origInstanceType.subst(
Subst, Conformances, None)->getCanonicalType();

// If the substitution didn't change anything, we know that the
// original type was a lowered type, so we're good.
if (origInstanceType == substInstanceType) {
return origType;
}

// If this is a DynamicSelf metatype, turn it into a metatype of the
// underlying self type.
if (auto dynamicSelf = dyn_cast<DynamicSelfType>(substInstanceType)) {
substInstanceType = dynamicSelf.getSelfType();
}

return CanMetatypeType::get(substInstanceType,
origType->getRepresentation());
}

/// Any other type is would be a valid type in the AST. Just
/// apply the substitution on the AST level and then lower that.
CanType visitType(CanType origType) {
Expand Down
28 changes: 2 additions & 26 deletions lib/SIL/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,30 +1235,6 @@ void TypeConverter::insert(TypeKey k, const TypeLowering *tl) {
Types[k.getCachingKey()] = tl;
}

#ifndef NDEBUG
/// Is this type a lowered type?
static bool isLoweredType(CanType type) {
if (isa<LValueType>(type) || isa<InOutType>(type))
return false;
if (isa<AnyFunctionType>(type))
return false;
if (auto tuple = dyn_cast<TupleType>(type)) {
for (auto elt : tuple.getElementTypes())
if (!isLoweredType(elt))
return false;
return true;
}
OptionalTypeKind optKind;
if (auto objectType = type.getAnyOptionalObjectType(optKind)) {
return (optKind == OTK_Optional && isLoweredType(objectType));
}
if (auto meta = dyn_cast<AnyMetatypeType>(type)) {
return meta->hasRepresentation();
}
return true;
}
#endif

/// Lower each of the elements of the substituted type according to
/// the abstraction pattern of the given original type.
static CanTupleType getLoweredTupleType(TypeConverter &tc,
Expand Down Expand Up @@ -1525,7 +1501,7 @@ const TypeLowering &TypeConverter::getTypeLowering(SILType type) {
const TypeLowering &
TypeConverter::getTypeLoweringForLoweredType(TypeKey key) {
auto type = key.SubstType;
assert(isLoweredType(type) && "type is not lowered!");
assert(type->isLegalSILType() && "type is not lowered!");
(void)type;

// Re-using uncurry level 0 is reasonable because our uncurrying
Expand All @@ -1542,7 +1518,7 @@ TypeConverter::getTypeLoweringForLoweredType(TypeKey key) {
const TypeLowering &
TypeConverter::getTypeLoweringForUncachedLoweredType(TypeKey key) {
assert(!find(key) && "re-entrant or already cached");
assert(isLoweredType(key.SubstType) && "type is not already lowered");
assert(key.SubstType->isLegalSILType() && "type is not already lowered");

#ifndef NDEBUG
// Catch reentrancy bugs.
Expand Down
30 changes: 29 additions & 1 deletion lib/SILGen/ArgumentSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,35 @@ bool ArgumentSource::requiresCalleeToEvaluate() {
case Kind::LValue:
return false;
case Kind::Expr:
return isa<TupleShuffleExpr>(asKnownExpr());
// FIXME: TupleShuffleExprs come in two flavors:
//
// 1) as apply arguments, where they're used to insert default
// argument value and collect varargs
//
// 2) as tuple conversions, where they can introduce, eliminate
// and re-order fields
//
// Case 1) must be emitted by ArgEmitter, and Case 2) must be
// emitted by RValueEmitter.
//
// It would be good to split up TupleShuffleExpr into these two
// cases, and simplify ArgEmitter since it no longer has to deal
// with re-ordering. However for now, SubscriptExpr emits the
// index argument via the RValueEmitter, so the RValueEmitter has
// to know about varargs, duplicating some of the logic in
// ArgEmitter.
//
// Once this is fixed, we can also consider allowing subscripts
// to have default arguments.
if (auto *shuffleExpr = dyn_cast<TupleShuffleExpr>(asKnownExpr())) {
for (auto index : shuffleExpr->getElementMapping()) {
if (index == TupleShuffleExpr::DefaultInitialize ||
index == TupleShuffleExpr::CallerDefaultInitialize ||
index == TupleShuffleExpr::Variadic)
return true;
}
}
return false;
}

llvm_unreachable("Unhandled Kind in switch.");
Expand Down
3 changes: 3 additions & 0 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,9 @@ void SILGenModule::emitSourceFile(SourceFile *sf, unsigned startElem) {
for (Decl *D : llvm::makeArrayRef(sf->Decls).slice(startElem))
visit(D);

for (Decl *D : sf->LocalTypeDecls)
visit(D);

// Mark any conformances as "used".
for (auto conformance : sf->getUsedConformances())
useConformance(ProtocolConformanceRef(conformance));
Expand Down
15 changes: 8 additions & 7 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,14 +558,14 @@ class Callee {
assert(level <= Constant.uncurryLevel
&& "uncurrying past natural uncurry level of method");

auto constant = Constant.atUncurryLevel(level);
constant = Constant.atUncurryLevel(level);
// Lower the substituted type from the AST, which should have any generic
// parameters in the original signature erased to their upper bounds.
auto objcFormalType = SubstFormalType.withExtInfo(
SubstFormalType->getExtInfo()
.withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod));
auto fnType = gen.SGM.M.Types
.getUncachedSILFunctionTypeForConstant(constant, objcFormalType);
.getUncachedSILFunctionTypeForConstant(*constant, objcFormalType);

auto closureType =
replaceSelfTypeForDynamicLookup(gen.getASTContext(), fnType,
Expand All @@ -574,9 +574,9 @@ class Callee {

SILValue fn = gen.B.createDynamicMethod(Loc,
SelfValue,
constant,
*constant,
SILType::getPrimitiveObjectType(closureType),
/*volatile*/ constant.isForeign);
/*volatile*/ Constant.isForeign);
mv = ManagedValue::forUnmanaged(fn);
break;
}
Expand Down Expand Up @@ -4694,15 +4694,16 @@ static RValue emitApplyAllocatingInitializer(SILGenFunction &SGF,
{
// Determine the self metatype type.
CanSILFunctionType substFnType =
SGF.getLoweredType(substFormalType, /*uncurryLevel=*/1)
.castTo<SILFunctionType>();
initConstant.SILFnType->substGenericArgs(SGF.SGM.M, subs);
SILType selfParamMetaTy = substFnType->getSelfParameter().getSILType();

if (overriddenSelfType) {
// If the 'self' type has been overridden, form a metatype to the
// overriding 'Self' type.
Type overriddenSelfMetaType =
MetatypeType::get(overriddenSelfType, SGF.getASTContext());
MetatypeType::get(overriddenSelfType,
selfParamMetaTy.castTo<MetatypeType>()
->getRepresentation());
selfMetaTy =
SGF.getLoweredType(overriddenSelfMetaType->getCanonicalType());
} else {
Expand Down
18 changes: 8 additions & 10 deletions lib/SILGen/SILGenDynamicCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,20 +357,18 @@ adjustForConditionalCheckedCastOperand(SILLocation loc, ManagedValue src,
}

std::unique_ptr<TemporaryInitialization> init;
SGFContext ctx;
if (requiresAddress) {
init = SGF.emitTemporary(loc, srcAbstractTL);


if (hasAbstraction)
src = SGF.emitSubstToOrigValue(loc, src, abstraction, sourceType);

// Okay, if all we need to do is drop the value in an address,
// this is easy.
if (!hasAbstraction) {
SGF.B.emitStoreValueOperation(loc, src.forward(SGF), init->getAddress(),
StoreOwnershipQualifier::Init);
init->finishInitialization(SGF);
return init->getManagedAddress();
}

ctx = SGFContext(init.get());
SGF.B.emitStoreValueOperation(loc, src.forward(SGF), init->getAddress(),
StoreOwnershipQualifier::Init);
init->finishInitialization(SGF);
return init->getManagedAddress();
}

assert(hasAbstraction);
Expand Down
5 changes: 4 additions & 1 deletion lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1545,7 +1545,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
llvm_unreachable("Not yet implemented");
}

void visitNominalTypeDecl(NominalTypeDecl *D);
void visitFuncDecl(FuncDecl *D);
void visitPatternBindingDecl(PatternBindingDecl *D);

Expand All @@ -1554,6 +1553,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
std::unique_ptr<Initialization>
emitPatternBindingInitialization(Pattern *P, JumpDest failureDest);

void visitNominalTypeDecl(NominalTypeDecl *D) {
// No lowering support needed.
}

void visitTypeAliasDecl(TypeAliasDecl *D) {
// No lowering support needed.
}
Expand Down
9 changes: 5 additions & 4 deletions lib/SILGen/SILGenLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -831,10 +831,11 @@ namespace {
return true;
}

// If the declaration is dynamically dispatched through a protocol,
// we have to use materializeForSet.
if (isa<ProtocolDecl>(decl->getDeclContext()))
return true;
// If the declaration is dynamically dispatched through a
// non-ObjC protocol, we have to use materializeForSet.
if (auto *protoDecl = dyn_cast<ProtocolDecl>(decl->getDeclContext()))
if (!protoDecl->isObjC())
return true;

return false;
}
Expand Down
Loading