Skip to content

Commit 418bd22

Browse files
authored
Merge pull request #80013 from eeckstein/simplify-sil-type
AST/SIL: Refactor and cleanup `AST.Type`, `AST.CanonicalType` and `SIL.Type`
2 parents d74c768 + d31d82c commit 418bd22

21 files changed

+331
-343
lines changed

SwiftCompilerSources/Sources/AST/Type.swift

Lines changed: 115 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre
3030

3131
public let bridged: BridgedASTType
3232

33-
public var type: Type { self }
33+
// Needed to conform to TypeProperties
34+
public var rawType: Type { self }
3435

3536
public init?(bridgedOrNil: BridgedASTType) {
3637
if bridgedOrNil.type == nil {
@@ -47,6 +48,17 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre
4748

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

51+
public var superClassType: Type? {
52+
precondition(isClass)
53+
let bridgedSuperClassTy = bridged.getSuperClassType()
54+
if bridgedSuperClassTy.type != nil {
55+
return Type(bridged: bridgedSuperClassTy)
56+
}
57+
return nil
58+
}
59+
60+
public var builtinVectorElementType: Type { Type(bridged: bridged.getBuiltinVectorElementType()) }
61+
5062
public func subst(with substitutionMap: SubstitutionMap) -> Type {
5163
return Type(bridged: bridged.subst(substitutionMap.bridged))
5264
}
@@ -63,49 +75,123 @@ public struct CanonicalType: TypeProperties, CustomStringConvertible, NoReflecti
6375

6476
public init(bridged: BridgedCanType) { self.bridged = bridged }
6577

66-
public var type: Type { Type(bridged: bridged.getType()) }
78+
public var rawType: Type { Type(bridged: bridged.getRawType()) }
79+
80+
public var instanceTypeOfMetatype: CanonicalType { rawType.instanceTypeOfMetatype.canonical }
81+
82+
public var superClassType: CanonicalType? { rawType.superClassType?.canonical }
83+
84+
public var builtinVectorElementType: CanonicalType { rawType.builtinVectorElementType.canonical }
6785

68-
public var instanceTypeOfMetatype: CanonicalType { type.instanceTypeOfMetatype.canonical }
69-
7086
public func subst(with substitutionMap: SubstitutionMap) -> CanonicalType {
71-
return type.subst(with: substitutionMap).canonical
87+
return rawType.subst(with: substitutionMap).canonical
7288
}
7389

7490
public func subst(type: CanonicalType, with targetType: CanonicalType) -> CanonicalType {
75-
return self.type.subst(type: type.type, with: targetType.type).canonical
91+
return self.rawType.subst(type: type.rawType, with: targetType.rawType).canonical
7692
}
7793
}
7894

79-
/// Contains common properties of AST.Type and AST.CanonicalType
95+
/// Implements the common members of `AST.Type`, `AST.CanonicalType` and `SIL.Type`.
8096
public protocol TypeProperties {
81-
var type: Type { get }
97+
var rawType: Type { get }
8298
}
8399

84100
extension TypeProperties {
85-
public var description: String { String(taking: type.bridged.getDebugDescription()) }
86-
87-
public var isLegalFormalType: Bool { type.bridged.isLegalFormalType() }
88-
public var hasTypeParameter: Bool { type.bridged.hasTypeParameter() }
89-
public var hasLocalArchetype: Bool { type.bridged.hasLocalArchetype() }
90-
public var isExistentialArchetype: Bool { type.bridged.isExistentialArchetype() }
91-
public var isExistentialArchetypeWithError: Bool { type.bridged.isExistentialArchetypeWithError() }
92-
public var isExistential: Bool { type.bridged.isExistential() }
93-
public var isEscapable: Bool { type.bridged.isEscapable() }
94-
public var isNoEscape: Bool { type.bridged.isNoEscape() }
95-
public var isInteger: Bool { type.bridged.isInteger() }
96-
public var isOptional: Bool { type.bridged.isOptional() }
97-
public var isMetatypeType: Bool { type.bridged.isMetatypeType() }
98-
public var isExistentialMetatypeType: Bool { type.bridged.isExistentialMetatypeType() }
101+
public var description: String { String(taking: rawType.bridged.getDebugDescription()) }
102+
103+
//===--------------------------------------------------------------------===//
104+
// Checks for different kinds of types
105+
//===--------------------------------------------------------------------===//
106+
107+
public var isBuiltinInteger: Bool { rawType.bridged.isBuiltinInteger() }
108+
109+
public func isBuiltinInteger(withFixedWidth width: Int) -> Bool {
110+
rawType.bridged.isBuiltinFixedWidthInteger(width)
111+
}
112+
113+
public var isBuiltinFloat: Bool { rawType.bridged.isBuiltinFloat() }
114+
public var isBuiltinVector: Bool { rawType.bridged.isBuiltinVector() }
115+
116+
public var isClass: Bool {
117+
if let nominal = nominal, nominal is ClassDecl {
118+
return true
119+
}
120+
return false
121+
}
122+
123+
public var isStruct: Bool {
124+
if let nominal = nominal, nominal is StructDecl {
125+
return true
126+
}
127+
return false
128+
}
129+
130+
public var isEnum: Bool {
131+
if let nominal = nominal, nominal is EnumDecl {
132+
return true
133+
}
134+
return false
135+
}
136+
137+
public var isTuple: Bool { rawType.bridged.isTuple() }
138+
public var isFunction: Bool { rawType.bridged.isFunction() }
139+
public var isExistentialArchetype: Bool { rawType.bridged.isExistentialArchetype() }
140+
public var isExistentialArchetypeWithError: Bool { rawType.bridged.isExistentialArchetypeWithError() }
141+
public var isExistential: Bool { rawType.bridged.isExistential() }
142+
public var isClassExistential: Bool { rawType.bridged.isClassExistential() }
143+
public var isUnownedStorageType: Bool { return rawType.bridged.isUnownedStorageType() }
144+
public var isMetatype: Bool { rawType.bridged.isMetatypeType() }
145+
public var isExistentialMetatype: Bool { rawType.bridged.isExistentialMetatypeType() }
146+
public var isDynamicSelf: Bool { rawType.bridged.isDynamicSelf()}
147+
148+
/// True if this is the type which represents an integer literal used in a type position.
149+
/// For example `N` in `struct T<let N: Int> {}`
150+
public var isInteger: Bool { rawType.bridged.isInteger() }
151+
152+
public var canBeClass: Type.TraitResult { rawType.bridged.canBeClass().result }
153+
154+
/// True if this the nominal type `Swift.Optional`.
155+
public var isOptional: Bool { rawType.bridged.isOptional() }
156+
157+
/// True if this type is a value type (struct/enum) that defines a `deinit`.
158+
public var isValueTypeWithDeinit: Bool {
159+
if let nominal = nominal, nominal.valueTypeDestructor != nil {
160+
return true
161+
}
162+
return false
163+
}
164+
165+
//===--------------------------------------------------------------------===//
166+
// Type properties
167+
//===--------------------------------------------------------------------===//
168+
169+
public var isLegalFormalType: Bool { rawType.bridged.isLegalFormalType() }
170+
public var hasArchetype: Bool { rawType.bridged.hasArchetype() }
171+
public var hasTypeParameter: Bool { rawType.bridged.hasTypeParameter() }
172+
public var hasLocalArchetype: Bool { rawType.bridged.hasLocalArchetype() }
173+
public var isEscapable: Bool { rawType.bridged.isEscapable() }
174+
public var isNoEscape: Bool { rawType.bridged.isNoEscape() }
175+
99176
public var representationOfMetatype: AST.`Type`.MetatypeRepresentation {
100-
type.bridged.getRepresentationOfMetatype().representation
177+
rawType.bridged.getRepresentationOfMetatype().representation
101178
}
102-
public var invocationGenericSignatureOfFunctionType: GenericSignature {
103-
GenericSignature(bridged: type.bridged.getInvocationGenericSignatureOfFunctionType())
179+
180+
/// Assumes this is a nominal type. Returns a substitution map that sends each
181+
/// generic parameter of the declaration's generic signature to the corresponding
182+
/// generic argument of this nominal type.
183+
///
184+
/// Eg: Array<Int> ---> { Element := Int }
185+
public var contextSubstitutionMap: SubstitutionMap {
186+
SubstitutionMap(bridged: rawType.bridged.getContextSubstitutionMap())
104187
}
105188

106-
public var canBeClass: Type.TraitResult { type.bridged.canBeClass().result }
189+
// True if this type has generic parameters or it is in a context (e.g. an outer type) which has generic parameters.
190+
public var isGenericAtAnyLevel: Bool { rawType.bridged.isGenericAtAnyLevel() }
107191

108-
public var anyNominal: NominalTypeDecl? { type.bridged.getAnyNominal().getAs(NominalTypeDecl.self) }
192+
public var nominal: NominalTypeDecl? {
193+
rawType.bridged.getNominalOrBoundGenericNominal().getAs(NominalTypeDecl.self)
194+
}
109195

110196
/// Performas a global conformance lookup for this type for `protocol`.
111197
/// It checks conditional requirements.
@@ -118,7 +204,7 @@ extension TypeProperties {
118204
/// Returns an invalid conformance if the search failed, otherwise an
119205
/// abstract, concrete or pack conformance, depending on the lookup type.
120206
public func checkConformance(to protocol: ProtocolDecl) -> Conformance {
121-
return Conformance(bridged: type.bridged.checkConformance(`protocol`.bridged))
207+
return Conformance(bridged: rawType.bridged.checkConformance(`protocol`.bridged))
122208
}
123209
}
124210

@@ -174,6 +260,6 @@ extension Type: Equatable {
174260

175261
extension CanonicalType: Equatable {
176262
public static func ==(lhs: CanonicalType, rhs: CanonicalType) -> Bool {
177-
lhs.type == rhs.type
263+
lhs.rawType == rhs.rawType
178264
}
179265
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ private extension PartialApplyInst {
11271127
if self.numArguments == 1,
11281128
let fun = self.referencedFunction,
11291129
fun.thunkKind == .reabstractionThunk || fun.thunkKind == .thunk,
1130-
self.arguments[0].type.isFunction,
1130+
self.arguments[0].type.isLoweredFunction,
11311131
self.arguments[0].type.isReferenceCounted(in: self.parentFunction) || self.callee.type.isThickFunction
11321132
{
11331133
return true

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ private extension AllocStackInst {
179179
/// use %3
180180
/// ```
181181
func optimizeExistential(_ context: SimplifyContext) -> Bool {
182-
guard type.astType.isExistential || type.astType.isExistentialArchetype,
182+
guard type.isExistential || type.isExistentialArchetype,
183183
let concreteFormalType = getConcreteTypeOfExistential()
184184
else {
185185
return false
@@ -266,7 +266,7 @@ private extension AllocStackInst {
266266
}
267267
let concreteType: CanonicalType
268268
if let initExistential {
269-
assert(self.type.astType.isExistential)
269+
assert(self.type.isExistential)
270270
if let cft = initExistential.concreteTypeOfDependentExistentialArchetype {
271271
// Case 1: We will replace the alloc_stack of an existential with the concrete type.
272272
// `alloc_stack $any P` -> `alloc_stack $ConcreteType`
@@ -281,9 +281,9 @@ private extension AllocStackInst {
281281
}
282282
// Case 2: We will replace the alloc_stack of an existential with the existential archetype.
283283
// `alloc_stack $any P` -> `alloc_stack $@opened("...")`
284-
concreteType = initExistential.type.astType
284+
concreteType = initExistential.type.canonicalType
285285
}
286-
} else if self.type.astType.isExistentialArchetype, let cft = self.concreteTypeOfDependentExistentialArchetype {
286+
} else if self.type.isExistentialArchetype, let cft = self.concreteTypeOfDependentExistentialArchetype {
287287
// Case 3: We will replace the alloc_stack of an existential archetype with the concrete type:
288288
// `alloc_stack $@opened("...")` -> `alloc_stack $ConcreteType`
289289
concreteType = cft

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -143,22 +143,22 @@ private extension FullApplySite {
143143
// Note that an opened existential value is address only, so it cannot be a direct result anyway
144144
// (but it can be once we have opaque values).
145145
// Also don't support things like direct `Array<@opened("...")>` return values.
146-
if let singleDirectResult, singleDirectResult.type.astType.hasLocalArchetype {
146+
if let singleDirectResult, singleDirectResult.type.hasLocalArchetype {
147147
return false
148148
}
149-
if let singleDirectErrorResult, singleDirectErrorResult.type.astType.hasLocalArchetype {
149+
if let singleDirectErrorResult, singleDirectErrorResult.type.hasLocalArchetype {
150150
return false
151151
}
152152

153153
return arguments.allSatisfy { value in
154-
let astTy = value.type.astType
154+
let type = value.type
155155
// Allow three cases:
156156
// case 1. the argument _is_ the existential archetype
157-
return astTy.isExistentialArchetype ||
157+
return type.isExistentialArchetype ||
158158
// case 2. the argument _is_ a metatype of the existential archetype
159-
(astTy.isMetatypeType && astTy.instanceTypeOfMetatype.isExistentialArchetype) ||
159+
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype) ||
160160
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
161-
!astTy.hasLocalArchetype
161+
!type.hasLocalArchetype
162162
}
163163
}
164164

@@ -167,19 +167,18 @@ private extension FullApplySite {
167167
_ context: SimplifyContext
168168
) -> [Value] {
169169
let newArgs = arguments.map { (arg) -> Value in
170-
let argTy = arg.type.astType
171-
if argTy.isExistentialArchetype {
170+
if arg.type.isExistentialArchetype {
172171
// case 1. the argument _is_ the existential archetype:
173172
// just insert an address cast to satisfy type equivalence.
174173
let builder = Builder(before: self, context)
175174
let concreteSILType = concreteType.loweredType(in: self.parentFunction)
176175
return builder.createUncheckedAddrCast(from: arg, to: concreteSILType.addressType)
177176
}
178-
if argTy.isMetatypeType, argTy.instanceTypeOfMetatype.isExistentialArchetype {
177+
if arg.type.isMetatype, arg.type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype {
179178
// case 2. the argument _is_ a metatype of the existential archetype:
180179
// re-create the metatype with the concrete type.
181180
let builder = Builder(before: self, context)
182-
return builder.createMetatype(ofInstanceType: concreteType, representation: argTy.representationOfMetatype)
181+
return builder.createMetatype(ofInstanceType: concreteType, representation: arg.type.representationOfMetatype)
183182
}
184183
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
185184
return arg
@@ -194,9 +193,9 @@ private extension FullApplySite {
194193
let openedArcheType = substitutionMap.replacementTypes.first(where: { $0.isExistentialArchetype })!
195194

196195
let newReplacementTypes = substitutionMap.replacementTypes.map {
197-
return $0 == openedArcheType ? concreteType.type : $0
196+
return $0 == openedArcheType ? concreteType.rawType : $0
198197
}
199-
let genSig = callee.type.astType.invocationGenericSignatureOfFunctionType
198+
let genSig = callee.type.invocationGenericSignatureOfFunction
200199
return SubstitutionMap(genericSignature: genSig, replacementTypes: newReplacementTypes)
201200
}
202201
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,12 @@ private extension BuiltinInst {
193193
return
194194
}
195195

196-
guard type.astType.representationOfMetatype == .thick else {
196+
guard type.representationOfMetatype == .thick else {
197197
return
198198
}
199199

200200
let builder = Builder(before: self, context)
201-
let newMetatype = builder.createMetatype(ofInstanceType: type.astType.instanceTypeOfMetatype,
201+
let newMetatype = builder.createMetatype(ofInstanceType: type.canonicalType.instanceTypeOfMetatype,
202202
representation: .thin)
203203
operands[argument].set(to: newMetatype, context)
204204
}
@@ -269,13 +269,11 @@ private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Func
269269
return nil
270270
}
271271

272-
let lhsMetatype = lhsExistential.metatype.type
273-
let rhsMetatype = rhsExistential.metatype.type
274-
if lhsMetatype.isDynamicSelfMetatype != rhsMetatype.isDynamicSelfMetatype {
272+
let lhsTy = lhsExistential.metatype.type.canonicalType.instanceTypeOfMetatype
273+
let rhsTy = rhsExistential.metatype.type.canonicalType.instanceTypeOfMetatype
274+
if lhsTy.isDynamicSelf != rhsTy.isDynamicSelf {
275275
return nil
276276
}
277-
let lhsTy = lhsMetatype.loweredInstanceTypeOfMetatype(in: function)
278-
let rhsTy = rhsMetatype.loweredInstanceTypeOfMetatype(in: function)
279277

280278
// Do we know the exact types? This is not the case e.g. if a type is passed as metatype
281279
// to the function.
@@ -288,14 +286,20 @@ private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Func
288286
// ((Int, Int) -> ())
289287
// (((Int, Int)) -> ())
290288
//
291-
if lhsMetatype == rhsMetatype {
289+
if lhsTy == rhsTy {
292290
return true
293291
}
294292
// Comparing types of different classes which are in a sub-class relation is not handled by the
295293
// cast optimizer (below).
296294
if lhsTy.isClass && rhsTy.isClass && lhsTy.nominal != rhsTy.nominal {
297295
return false
298296
}
297+
298+
// Failing function casts are not supported by the cast optimizer (below).
299+
// (Reason: "Be conservative about function type relationships we may add in the future.")
300+
if lhsTy.isFunction && rhsTy.isFunction && lhsTy != rhsTy && !lhsTy.hasArchetype && !rhsTy.hasArchetype {
301+
return false
302+
}
299303
}
300304

301305
// If casting in either direction doesn't work, the types cannot be equal.

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyCheckedCast.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,12 @@ private extension UnconditionalCheckedCastInst {
7070
// Note that init_existential_metatype is better than unconditional_checked_cast because it does not need
7171
// to do any runtime casting.
7272
func tryOptimizeCastToExistentialMetatype(_ context: SimplifyContext) {
73-
guard targetFormalType.isExistentialMetatypeType,
74-
sourceFormalType.isMetatypeType,
75-
!sourceFormalType.isExistentialMetatypeType
76-
else {
73+
guard targetFormalType.isExistentialMetatype, sourceFormalType.isMetatype else {
7774
return
7875
}
7976

8077
let instanceTy = targetFormalType.instanceTypeOfMetatype
81-
guard let nominal = instanceTy.anyNominal,
78+
guard let nominal = instanceTy.nominal,
8279
let proto = nominal as? ProtocolDecl
8380
else {
8481
return

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyConvertEscapeToNoEscape.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ private extension ConvertEscapeToNoEscapeInst {
2828
/// %3 = thin_to_thick_function %1 to $@noescape () -> ()
2929

3030
func tryCombineWithThinToThickOperand(_ context: SimplifyContext) {
31-
// compiling bridged.getFunctionTypeWithNoEscape crashes the 5.10 Windows compiler
32-
#if !os(Windows)
33-
// TODO: https://github.com/apple/swift/issues/73253
34-
3531
if let thinToThick = fromFunction as? ThinToThickFunctionInst {
3632
let builder = Builder(before: self, context)
3733
let noEscapeFnType = thinToThick.type.getFunctionType(withNoEscape: true)
@@ -40,6 +36,5 @@ private extension ConvertEscapeToNoEscapeInst {
4036
uses.replaceAll(with: newThinToThick, context)
4137
context.erase(instruction: self)
4238
}
43-
#endif
4439
}
4540
}

0 commit comments

Comments
 (0)