Skip to content
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: 9 additions & 0 deletions SwiftCompilerSources/Sources/AST/Type.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre

public var instanceTypeOfMetatype: Type { Type(bridged: bridged.getInstanceTypeOfMetatype()) }

public var staticTypeOfDynamicSelf: Type { Type(bridged: bridged.getStaticTypeOfDynamicSelf()) }

public var interfaceTypeOfArchetype: Type { Type(bridged: bridged.getInterfaceTypeOfArchetype()) }

public var superClassType: Type? {
precondition(isClass)
let bridgedSuperClassTy = bridged.getSuperClassType()
Expand Down Expand Up @@ -136,10 +140,14 @@ extension TypeProperties {

public var isTuple: Bool { rawType.bridged.isTuple() }
public var isFunction: Bool { rawType.bridged.isFunction() }
public var isArchetype: Bool { rawType.bridged.isArchetype() }
public var isExistentialArchetype: Bool { rawType.bridged.isExistentialArchetype() }
public var isExistentialArchetypeWithError: Bool { rawType.bridged.isExistentialArchetypeWithError() }
public var isRootArchetype: Bool { rawType.interfaceTypeOfArchetype.isGenericTypeParameter }
public var isRootExistentialArchetype: Bool { isExistentialArchetype && isRootArchetype }
public var isExistential: Bool { rawType.bridged.isExistential() }
public var isClassExistential: Bool { rawType.bridged.isClassExistential() }
public var isGenericTypeParameter: Bool { rawType.bridged.isGenericTypeParam() }
public var isUnownedStorageType: Bool { return rawType.bridged.isUnownedStorageType() }
public var isMetatype: Bool { rawType.bridged.isMetatypeType() }
public var isExistentialMetatype: Bool { rawType.bridged.isExistentialMetatypeType() }
Expand Down Expand Up @@ -187,6 +195,7 @@ extension TypeProperties {
public var isEscapable: Bool { rawType.bridged.isEscapable() }
public var isNoEscape: Bool { rawType.bridged.isNoEscape() }
public var isBuiltinType: Bool { rawType.bridged.isBuiltinType() }
public var archetypeRequiresClass: Bool { rawType.bridged.archetypeRequiresClass() }

public var representationOfMetatype: AST.`Type`.MetatypeRepresentation {
rawType.bridged.getRepresentationOfMetatype().representation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ private extension AllocStackInst {
/// use %3
/// ```
func optimizeExistential(_ context: SimplifyContext) -> Bool {
guard type.isExistential || type.isExistentialArchetype,
// TODO: support non-root existential archetypes
guard type.isExistential || type.isRootExistentialArchetype,
let concreteFormalType = getConcreteTypeOfExistential()
else {
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ private extension FullApplySite {
// Make sure that existential archetype _is_ a replacement type and not e.g. _contained_ in a
// replacement type, like
// apply %1<Array<@opened("...")>()
guard substitutionMap.replacementTypes.contains(where: { $0.isExistentialArchetype }),
substitutionMap.replacementTypes.allSatisfy({ $0.isExistentialArchetype || !$0.hasLocalArchetype })
// TODO: support non-root existential archetypes
guard substitutionMap.replacementTypes.contains(where: { $0.isRootExistentialArchetype }),
substitutionMap.replacementTypes.allSatisfy({ $0.isRootExistentialArchetype || !$0.hasLocalArchetype })
else {
return false
}
Expand All @@ -191,9 +192,9 @@ private extension FullApplySite {
let type = value.type
// Allow three cases:
// case 1. the argument _is_ the existential archetype
return type.isExistentialArchetype ||
return type.isRootExistentialArchetype ||
// case 2. the argument _is_ a metatype of the existential archetype
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype) ||
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isRootExistentialArchetype) ||
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
!type.hasLocalArchetype
}
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -3100,11 +3100,14 @@ struct BridgedASTType {
BRIDGED_INLINE bool isGenericAtAnyLevel() const;
BRIDGED_INLINE bool hasTypeParameter() const;
BRIDGED_INLINE bool hasLocalArchetype() const;
BRIDGED_INLINE bool isArchetype() const;
BRIDGED_INLINE bool archetypeRequiresClass() const;
BRIDGED_INLINE bool isExistentialArchetype() const;
BRIDGED_INLINE bool isExistentialArchetypeWithError() const;
BRIDGED_INLINE bool isExistential() const;
BRIDGED_INLINE bool isDynamicSelf() const;
BRIDGED_INLINE bool isClassExistential() const;
BRIDGED_INLINE bool isGenericTypeParam() const;
BRIDGED_INLINE bool isEscapable() const;
BRIDGED_INLINE bool isNoEscape() const;
BRIDGED_INLINE bool isInteger() const;
Expand All @@ -3129,6 +3132,8 @@ struct BridgedASTType {
BRIDGED_INLINE TraitResult canBeClass() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedDeclObj getAnyNominal() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getInstanceTypeOfMetatype() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getStaticTypeOfDynamicSelf() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getInterfaceTypeOfArchetype() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getSuperClassType() const;
BRIDGED_INLINE MetatypeRepresentation getRepresentationOfMetatype() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap getContextSubstitutionMap() const;
Expand Down
20 changes: 20 additions & 0 deletions include/swift/AST/ASTBridgingImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,14 @@ bool BridgedASTType::hasLocalArchetype() const {
return unbridged()->hasLocalArchetype();
}

bool BridgedASTType::isArchetype() const {
return unbridged()->is<swift::ArchetypeType>();
}

bool BridgedASTType::archetypeRequiresClass() const {
return unbridged()->castTo<swift::ArchetypeType>()->requiresClass();
}

bool BridgedASTType::isExistentialArchetype() const {
return unbridged()->is<swift::ExistentialArchetypeType>();
}
Expand All @@ -443,6 +451,10 @@ bool BridgedASTType::isClassExistential() const {
return unbridged()->isClassExistentialType();
}

bool BridgedASTType::isGenericTypeParam() const {
return unbridged()->is<swift::GenericTypeParamType>();
}

bool BridgedASTType::isEscapable() const {
return unbridged()->isEscapable();
}
Expand Down Expand Up @@ -551,6 +563,14 @@ BridgedASTType BridgedASTType::getInstanceTypeOfMetatype() const {
return {unbridged()->getAs<swift::AnyMetatypeType>()->getInstanceType().getPointer()};
}

BridgedASTType BridgedASTType::getStaticTypeOfDynamicSelf() const {
return {unbridged()->getAs<swift::DynamicSelfType>()->getSelfType().getPointer()};
}

BridgedASTType BridgedASTType::getInterfaceTypeOfArchetype() const {
return {unbridged()->getAs<swift::ArchetypeType>()->getInterfaceType().getPointer()};
}

BridgedASTType BridgedASTType::getSuperClassType() const {
return {unbridged()->getSuperclass().getPointer()};
}
Expand Down
34 changes: 34 additions & 0 deletions test/SILOptimizer/simplify_alloc_stack.sil
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,27 @@ public struct S {}
protocol P {
}

protocol Q {
associatedtype A
}

public class C2: P {}

public struct T: P {
let c: C
let s: S

struct A {
var y: String
}
}

public struct U: Q {
let s: String

struct A {
var y: String
}
}

public struct T1: P {
Expand Down Expand Up @@ -235,6 +251,24 @@ bb0(%0 : @owned $T):
return %r
}

// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
// CHECK: alloc_stack {{.*}}@opened
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (@owned U.A) -> () {
bb0(%0 : @owned $U.A):
%1 = metatype $@thick U.Type
%2 = init_existential_metatype %1, $@thick Q.Type
%3 = open_existential_metatype %2 to $@thick (@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).Type
%4 = alloc_stack $(@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).A
%5 = unchecked_addr_cast %4 to $*U.A
store %0 to [init] %5
destroy_addr %4
dealloc_stack %4
%r = tuple ()
return %r
}

// CHECK-LABEL: sil [ossa] @replace_existential_with_concrete_type1 :
// CHECK: [[S:%.*]] = alloc_stack $T
// CHECK-NOT: init_existential_addr
Expand Down
31 changes: 31 additions & 0 deletions test/SILOptimizer/simplify_apply.sil
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ struct GenS<T> {
var x: Int
}

protocol P2 {
associatedtype A: Q
}

protocol Q {
}

public struct S2: P2 {
var x: String
struct A: Q {
var y: String
}
}

sil @cl : $@convention(thin) () -> Int

// CHECK-LABEL: sil [ossa] @thick_to_thin :
Expand Down Expand Up @@ -60,6 +74,7 @@ sil_vtable Bar {
}

sil @createit : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type, Int) -> @out τ_0_0
sil @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
sil @useGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (GenS<τ_0_0>) -> ()
sil @returnGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> GenS<τ_0_0>

Expand Down Expand Up @@ -124,6 +139,22 @@ bb0(%0 : $Int):
return %11
}

// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
// CHECK: apply %{{[0-9]+}}<@opened
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (Int) -> @out any Q {
bb0(%0 : $*any Q, %1 : $Int):
%2 = metatype $@thick S2.Type
%3 = init_existential_metatype %2, $@thick any P2.Type
%4 = open_existential_metatype %3 to $@thick (@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).Type
%6 = function_ref @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
%7 = init_existential_addr %0, $(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A
%8 = apply %6<(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A>(%7, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
%11 = tuple ()
return %11
}

// CHECK-LABEL: sil [ossa] @dont_replace_returned_embedded_archetype :
// CHECK: apply %{{[0-9]+}}<@opened
// CHECK: } // end sil function 'dont_replace_returned_embedded_archetype'
Expand Down