Skip to content

SIL: Use a TypeExpansionContext in SIL lowering to expand opaque type archetypes as part of lowering #28044

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion include/swift/AST/SubstitutionMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/AST/GenericSignature.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeExpansionContext.h"
#include "swift/Basic/Debug.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
Expand Down Expand Up @@ -176,7 +177,13 @@ class SubstitutionMap {
SubstitutionMap subst(TypeSubstitutionFn subs,
LookupConformanceFn conformances,
SubstOptions options=None) const;


/// Apply type expansion lowering to all types in the substitution map. Opaque
/// archetypes will be lowered to their underlying types if the type expansion
/// context allows.
SubstitutionMap mapIntoTypeExpansionContext(
TypeExpansionContext context) const;

/// Create a substitution map for a protocol conformance.
static SubstitutionMap
getProtocolSubstitutions(ProtocolDecl *protocol,
Expand Down
145 changes: 145 additions & 0 deletions include/swift/AST/TypeExpansionContext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
//===--- TypeExpansionContext.h - Swift Type Expansion Context --*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypeExpansionContext class.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_TYPEEXPANSIONCONTEXT_H
#define SWIFT_TYPEEXPANSIONCONTEXT_H

#include "swift/AST/ResilienceExpansion.h"
#include "llvm/ADT/DenseMap.h"

namespace swift {
class DeclContext;
class SILFunction;

/// Describes the context in which SIL types should eventually be expanded.
/// Required for lowering resilient types and deciding whether to look through
/// opaque result types to their underlying type.
class TypeExpansionContext {
ResilienceExpansion expansion;
// The context (module, function, ...) we are expanding the type in.
const DeclContext *inContext;
// Is the context in which we are expanding in the whole module.
bool isContextWholeModule;

// The minimal expansion.
TypeExpansionContext() {
inContext = nullptr;
expansion = ResilienceExpansion::Minimal;
isContextWholeModule = false;
}

public:

// Infer the expansion for the SIL function.
TypeExpansionContext(const SILFunction &f);

TypeExpansionContext(ResilienceExpansion expansion,
const DeclContext *inContext, bool isWholeModuleContext)
: expansion(expansion), inContext(inContext),
isContextWholeModule(isWholeModuleContext) {}

ResilienceExpansion getResilienceExpansion() const { return expansion; }

const DeclContext *getContext() const { return inContext; }

bool isWholeModuleContext() const { return isContextWholeModule; }

bool shouldLookThroughOpaqueTypeArchetypes() const {
return inContext != nullptr;
}

bool isMinimal() const { return *this == TypeExpansionContext(); }

static TypeExpansionContext minimal() {
return TypeExpansionContext();
}

static TypeExpansionContext maximal(const DeclContext *inContext,
bool isContextWholeModule) {
return TypeExpansionContext(ResilienceExpansion::Maximal, inContext,
isContextWholeModule);
}

static TypeExpansionContext maximalResilienceExpansionOnly() {
return maximal(nullptr, false);
}

static TypeExpansionContext
noOpaqueTypeArchetypesSubstitution(ResilienceExpansion expansion) {
return TypeExpansionContext(expansion, nullptr, false);
}

bool operator==(const TypeExpansionContext &other) const {
assert(other.inContext != this->inContext ||
other.isContextWholeModule == this->isContextWholeModule);
return other.inContext == this->inContext &&
other.expansion == this->expansion;
}

bool operator<(const TypeExpansionContext other) const {
assert(other.inContext != this->inContext ||
other.isContextWholeModule == this->isContextWholeModule);
if (this->expansion == other.expansion)
return this->inContext < other.inContext;
return this->expansion < other.expansion;
}

bool operator>(const TypeExpansionContext other) const {
assert(other.inContext != this->inContext ||
other.isContextWholeModule == this->isContextWholeModule);
if (this->expansion == other.expansion)
return this->inContext > other.inContext;
return this->expansion > other.expansion;
}

uintptr_t getHashKey() const {
uintptr_t key = (uintptr_t)inContext | (uintptr_t)expansion;
return key;
}
};

} // namespace swift

namespace llvm {
template <> struct DenseMapInfo<swift::TypeExpansionContext> {
using TypeExpansionContext = swift::TypeExpansionContext;

static TypeExpansionContext getEmptyKey() {
return TypeExpansionContext(
swift::ResilienceExpansion::Minimal,
reinterpret_cast<swift::DeclContext *>(
DenseMapInfo<swift::DeclContext *>::getEmptyKey()),
false);
}
static TypeExpansionContext getTombstoneKey() {
return TypeExpansionContext(
swift::ResilienceExpansion::Minimal,
reinterpret_cast<swift::DeclContext *>(
DenseMapInfo<swift::DeclContext *>::getTombstoneKey()),
false);
}

static unsigned getHashValue(TypeExpansionContext val) {
return DenseMapInfo<uintptr_t>::getHashValue(val.getHashKey());
}

static bool isEqual(TypeExpansionContext LHS, TypeExpansionContext RHS) {
return LHS == RHS;
}
};
} // namespace llvm

#endif
34 changes: 28 additions & 6 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeExpansionContext.h"
#include "swift/Basic/ArrayRefView.h"
#include "swift/Basic/Debug.h"
#include "swift/Basic/InlineBitfield.h"
Expand Down Expand Up @@ -582,7 +583,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
bool hasOpaqueArchetype() const {
return getRecursiveProperties().hasOpaqueArchetype();
}

/// Determine whether the type has any stored properties or enum cases that
/// involve an opaque type.
bool hasOpaqueArchetypePropertiesOrCases();

/// Determine whether the type is an opened existential type.
///
/// To determine whether there is an opened existential type
Expand Down Expand Up @@ -3687,6 +3691,17 @@ enum class SILCoroutineKind : uint8_t {

class SILFunctionConventions;


CanType substOpaqueTypesWithUnderlyingTypes(CanType type,
TypeExpansionContext context,
bool allowLoweredTypes = false);
ProtocolConformanceRef
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType,
TypeExpansionContext context);
namespace Lowering {
class TypeConverter;
};

/// SILFunctionType - The lowered type of a function value, suitable
/// for use by SIL.
///
Expand Down Expand Up @@ -4205,10 +4220,14 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
SILFunction &context) const;

CanSILFunctionType substGenericArgs(SILModule &silModule,
SubstitutionMap subs);
SubstitutionMap subs,
TypeExpansionContext context);
CanSILFunctionType substGenericArgs(SILModule &silModule,
TypeSubstitutionFn subs,
LookupConformanceFn conformances);
LookupConformanceFn conformances,
TypeExpansionContext context);
CanSILFunctionType substituteOpaqueArchetypes(Lowering::TypeConverter &TC,
TypeExpansionContext context);

SILType substInterfaceType(SILModule &M,
SILType interfaceType) const;
Expand Down Expand Up @@ -4963,9 +4982,12 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
public:
const DeclContext *inContext;
ResilienceExpansion contextExpansion;
bool isContextWholeModule;
ReplaceOpaqueTypesWithUnderlyingTypes(const DeclContext *inContext,
ResilienceExpansion contextExpansion)
: inContext(inContext), contextExpansion(contextExpansion) {}
ResilienceExpansion contextExpansion,
bool isWholeModuleContext)
: inContext(inContext), contextExpansion(contextExpansion),
isContextWholeModule(isWholeModuleContext) {}

/// TypeSubstitutionFn
Type operator()(SubstitutableType *maybeOpaqueType) const;
Expand Down Expand Up @@ -5752,5 +5774,5 @@ struct DenseMapInfo<swift::BuiltinIntegerWidth> {
};

}

#endif
27 changes: 17 additions & 10 deletions include/swift/SIL/Projection.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ class Projection {
///
/// WARNING: This is not a constant time operation because it is implemented
/// in terms of getVarDecl, which requests all BaseType's stored properties.
SILType getType(SILType BaseType, SILModule &M) const;
SILType getType(SILType BaseType, SILModule &M,
TypeExpansionContext context) const;

VarDecl *getVarDecl(SILType BaseType) const {
assert(isValid());
Expand Down Expand Up @@ -402,6 +403,7 @@ class Projection {
/// Given a specific SILType, return all first level projections if it is an
/// aggregate.
static void getFirstLevelProjections(SILType V, SILModule &Mod,
TypeExpansionContext context,
llvm::SmallVectorImpl<Projection> &Out);

/// Is this cast which only allows for equality?
Expand Down Expand Up @@ -584,6 +586,7 @@ class ProjectionPath {
/// is a leaf node in the type tree.
static void expandTypeIntoLeafProjectionPaths(SILType BaseType,
SILModule *Mod,
TypeExpansionContext context,
ProjectionPathList &P);

/// Return true if the given projection paths in \p CPaths does not cover
Expand Down Expand Up @@ -626,26 +629,27 @@ class ProjectionPath {
SILType getBaseType() const { return BaseType; }

/// Returns the most derived type of the projection path.
SILType getMostDerivedType(SILModule &M) {
SILType getMostDerivedType(SILModule &M, TypeExpansionContext context) {
if (Path.empty())
return getBaseType();
if (MostDerivedType)
return MostDerivedType;
MostDerivedType = getDerivedType(Path.size(), M);
MostDerivedType = getDerivedType(Path.size(), M, context);
return MostDerivedType;
}

/// Returns the ith derived type of the path. This is zero indexed with 0
/// being the base type and n consisting of applying the up to n projections
/// to the base type.
SILType getDerivedType(unsigned i, SILModule &M) const {
SILType getDerivedType(unsigned i, SILModule &M,
TypeExpansionContext context) const {
assert(i <= Path.size());
SILType IterTy = getBaseType();
if (i == 0)
return IterTy;
for (unsigned j : range(i)) {
auto &Proj = Path[j];
IterTy = Proj.getType(IterTy, M);
IterTy = Proj.getType(IterTy, M, context);
}
return IterTy;
}
Expand All @@ -671,10 +675,11 @@ class ProjectionPath {
const_reverse_iterator rbegin() const { return Path.rbegin(); }
const_reverse_iterator rend() const { return Path.rend(); }

void verify(SILModule &M);
void verify(SILModule &M, TypeExpansionContext context);

raw_ostream &print(raw_ostream &OS, SILModule &M) const;
void dump(SILModule &M) const;
raw_ostream &print(raw_ostream &OS, SILModule &M,
TypeExpansionContext context) const;
void dump(SILModule &M, TypeExpansionContext context) const;
};

/// Returns the hashcode for the new projection path.
Expand Down Expand Up @@ -813,9 +818,11 @@ class ProjectionTreeNode {
llvm::SmallVectorImpl<ValueNodePair> &Worklist,
SILValue Value);

void createNextLevelChildren(ProjectionTree &Tree);
void createNextLevelChildren(ProjectionTree &Tree, TypeExpansionContext context);

void createNextLevelChildrenForStruct(ProjectionTree &Tree, StructDecl *SD);
void createNextLevelChildrenForStruct(ProjectionTree &Tree,
TypeExpansionContext context,
StructDecl *SD);

void createNextLevelChildrenForTuple(ProjectionTree &Tree, TupleType *TT);
};
Expand Down
3 changes: 2 additions & 1 deletion include/swift/SIL/SILBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
/// Allocate a new argument of type \p Ty and append it to the argument
/// list. Optionally you can pass in a value decl parameter.
SILFunctionArgument *createFunctionArgument(SILType Ty,
const ValueDecl *D = nullptr);
const ValueDecl *D = nullptr,
bool disableEntryBlockVerification = false);

SILFunctionArgument *insertFunctionArgument(unsigned Index, SILType Ty,
ValueOwnershipKind OwnershipKind,
Expand Down
Loading