Skip to content

Commit

Permalink
Merge pull request #6543 from slavapestov/small-silgen-fixes
Browse files Browse the repository at this point in the history
Fixes for assorted SILGen bugs
  • Loading branch information
slavapestov committed Jan 4, 2017
2 parents 7258861 + 3b388df commit 88ecaad
Show file tree
Hide file tree
Showing 25 changed files with 451 additions and 111 deletions.
22 changes: 22 additions & 0 deletions lib/SIL/SILFunctionType.cpp
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
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
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
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
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
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
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
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

0 comments on commit 88ecaad

Please sign in to comment.