Skip to content

Commit 88ecaad

Browse files
authored
Merge pull request #6543 from slavapestov/small-silgen-fixes
Fixes for assorted SILGen bugs
2 parents 7258861 + 3b388df commit 88ecaad

25 files changed

+451
-111
lines changed

lib/SIL/SILFunctionType.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,6 +2209,28 @@ namespace {
22092209
substObjectType));
22102210
}
22112211

2212+
/// Metatypes get DynamicSelfType stripped off the instance type.
2213+
CanType visitMetatypeType(CanMetatypeType origType) {
2214+
CanType origInstanceType = origType.getInstanceType();
2215+
CanType substInstanceType = origInstanceType.subst(
2216+
Subst, Conformances, None)->getCanonicalType();
2217+
2218+
// If the substitution didn't change anything, we know that the
2219+
// original type was a lowered type, so we're good.
2220+
if (origInstanceType == substInstanceType) {
2221+
return origType;
2222+
}
2223+
2224+
// If this is a DynamicSelf metatype, turn it into a metatype of the
2225+
// underlying self type.
2226+
if (auto dynamicSelf = dyn_cast<DynamicSelfType>(substInstanceType)) {
2227+
substInstanceType = dynamicSelf.getSelfType();
2228+
}
2229+
2230+
return CanMetatypeType::get(substInstanceType,
2231+
origType->getRepresentation());
2232+
}
2233+
22122234
/// Any other type is would be a valid type in the AST. Just
22132235
/// apply the substitution on the AST level and then lower that.
22142236
CanType visitType(CanType origType) {

lib/SIL/TypeLowering.cpp

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,30 +1235,6 @@ void TypeConverter::insert(TypeKey k, const TypeLowering *tl) {
12351235
Types[k.getCachingKey()] = tl;
12361236
}
12371237

1238-
#ifndef NDEBUG
1239-
/// Is this type a lowered type?
1240-
static bool isLoweredType(CanType type) {
1241-
if (isa<LValueType>(type) || isa<InOutType>(type))
1242-
return false;
1243-
if (isa<AnyFunctionType>(type))
1244-
return false;
1245-
if (auto tuple = dyn_cast<TupleType>(type)) {
1246-
for (auto elt : tuple.getElementTypes())
1247-
if (!isLoweredType(elt))
1248-
return false;
1249-
return true;
1250-
}
1251-
OptionalTypeKind optKind;
1252-
if (auto objectType = type.getAnyOptionalObjectType(optKind)) {
1253-
return (optKind == OTK_Optional && isLoweredType(objectType));
1254-
}
1255-
if (auto meta = dyn_cast<AnyMetatypeType>(type)) {
1256-
return meta->hasRepresentation();
1257-
}
1258-
return true;
1259-
}
1260-
#endif
1261-
12621238
/// Lower each of the elements of the substituted type according to
12631239
/// the abstraction pattern of the given original type.
12641240
static CanTupleType getLoweredTupleType(TypeConverter &tc,
@@ -1525,7 +1501,7 @@ const TypeLowering &TypeConverter::getTypeLowering(SILType type) {
15251501
const TypeLowering &
15261502
TypeConverter::getTypeLoweringForLoweredType(TypeKey key) {
15271503
auto type = key.SubstType;
1528-
assert(isLoweredType(type) && "type is not lowered!");
1504+
assert(type->isLegalSILType() && "type is not lowered!");
15291505
(void)type;
15301506

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

15471523
#ifndef NDEBUG
15481524
// Catch reentrancy bugs.

lib/SILGen/ArgumentSource.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,35 @@ bool ArgumentSource::requiresCalleeToEvaluate() {
5555
case Kind::LValue:
5656
return false;
5757
case Kind::Expr:
58-
return isa<TupleShuffleExpr>(asKnownExpr());
58+
// FIXME: TupleShuffleExprs come in two flavors:
59+
//
60+
// 1) as apply arguments, where they're used to insert default
61+
// argument value and collect varargs
62+
//
63+
// 2) as tuple conversions, where they can introduce, eliminate
64+
// and re-order fields
65+
//
66+
// Case 1) must be emitted by ArgEmitter, and Case 2) must be
67+
// emitted by RValueEmitter.
68+
//
69+
// It would be good to split up TupleShuffleExpr into these two
70+
// cases, and simplify ArgEmitter since it no longer has to deal
71+
// with re-ordering. However for now, SubscriptExpr emits the
72+
// index argument via the RValueEmitter, so the RValueEmitter has
73+
// to know about varargs, duplicating some of the logic in
74+
// ArgEmitter.
75+
//
76+
// Once this is fixed, we can also consider allowing subscripts
77+
// to have default arguments.
78+
if (auto *shuffleExpr = dyn_cast<TupleShuffleExpr>(asKnownExpr())) {
79+
for (auto index : shuffleExpr->getElementMapping()) {
80+
if (index == TupleShuffleExpr::DefaultInitialize ||
81+
index == TupleShuffleExpr::CallerDefaultInitialize ||
82+
index == TupleShuffleExpr::Variadic)
83+
return true;
84+
}
85+
}
86+
return false;
5987
}
6088

6189
llvm_unreachable("Unhandled Kind in switch.");

lib/SILGen/SILGen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,9 @@ void SILGenModule::emitSourceFile(SourceFile *sf, unsigned startElem) {
14081408
for (Decl *D : llvm::makeArrayRef(sf->Decls).slice(startElem))
14091409
visit(D);
14101410

1411+
for (Decl *D : sf->LocalTypeDecls)
1412+
visit(D);
1413+
14111414
// Mark any conformances as "used".
14121415
for (auto conformance : sf->getUsedConformances())
14131416
useConformance(ProtocolConformanceRef(conformance));

lib/SILGen/SILGenApply.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -558,14 +558,14 @@ class Callee {
558558
assert(level <= Constant.uncurryLevel
559559
&& "uncurrying past natural uncurry level of method");
560560

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

570570
auto closureType =
571571
replaceSelfTypeForDynamicLookup(gen.getASTContext(), fnType,
@@ -574,9 +574,9 @@ class Callee {
574574

575575
SILValue fn = gen.B.createDynamicMethod(Loc,
576576
SelfValue,
577-
constant,
577+
*constant,
578578
SILType::getPrimitiveObjectType(closureType),
579-
/*volatile*/ constant.isForeign);
579+
/*volatile*/ Constant.isForeign);
580580
mv = ManagedValue::forUnmanaged(fn);
581581
break;
582582
}
@@ -4694,15 +4694,16 @@ static RValue emitApplyAllocatingInitializer(SILGenFunction &SGF,
46944694
{
46954695
// Determine the self metatype type.
46964696
CanSILFunctionType substFnType =
4697-
SGF.getLoweredType(substFormalType, /*uncurryLevel=*/1)
4698-
.castTo<SILFunctionType>();
4697+
initConstant.SILFnType->substGenericArgs(SGF.SGM.M, subs);
46994698
SILType selfParamMetaTy = substFnType->getSelfParameter().getSILType();
47004699

47014700
if (overriddenSelfType) {
47024701
// If the 'self' type has been overridden, form a metatype to the
47034702
// overriding 'Self' type.
47044703
Type overriddenSelfMetaType =
4705-
MetatypeType::get(overriddenSelfType, SGF.getASTContext());
4704+
MetatypeType::get(overriddenSelfType,
4705+
selfParamMetaTy.castTo<MetatypeType>()
4706+
->getRepresentation());
47064707
selfMetaTy =
47074708
SGF.getLoweredType(overriddenSelfMetaType->getCanonicalType());
47084709
} else {

lib/SILGen/SILGenDynamicCast.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,20 +357,18 @@ adjustForConditionalCheckedCastOperand(SILLocation loc, ManagedValue src,
357357
}
358358

359359
std::unique_ptr<TemporaryInitialization> init;
360-
SGFContext ctx;
361360
if (requiresAddress) {
362361
init = SGF.emitTemporary(loc, srcAbstractTL);
363-
362+
363+
if (hasAbstraction)
364+
src = SGF.emitSubstToOrigValue(loc, src, abstraction, sourceType);
365+
364366
// Okay, if all we need to do is drop the value in an address,
365367
// this is easy.
366-
if (!hasAbstraction) {
367-
SGF.B.emitStoreValueOperation(loc, src.forward(SGF), init->getAddress(),
368-
StoreOwnershipQualifier::Init);
369-
init->finishInitialization(SGF);
370-
return init->getManagedAddress();
371-
}
372-
373-
ctx = SGFContext(init.get());
368+
SGF.B.emitStoreValueOperation(loc, src.forward(SGF), init->getAddress(),
369+
StoreOwnershipQualifier::Init);
370+
init->finishInitialization(SGF);
371+
return init->getManagedAddress();
374372
}
375373

376374
assert(hasAbstraction);

lib/SILGen/SILGenFunction.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
15451545
llvm_unreachable("Not yet implemented");
15461546
}
15471547

1548-
void visitNominalTypeDecl(NominalTypeDecl *D);
15491548
void visitFuncDecl(FuncDecl *D);
15501549
void visitPatternBindingDecl(PatternBindingDecl *D);
15511550

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

1556+
void visitNominalTypeDecl(NominalTypeDecl *D) {
1557+
// No lowering support needed.
1558+
}
1559+
15571560
void visitTypeAliasDecl(TypeAliasDecl *D) {
15581561
// No lowering support needed.
15591562
}

lib/SILGen/SILGenLValue.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -831,10 +831,11 @@ namespace {
831831
return true;
832832
}
833833

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

839840
return false;
840841
}

0 commit comments

Comments
 (0)