mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
MandatoryPerformanceOptimizations: support default methods for class existentials
For example:
```
protocol P: AnyObject {
func foo()
}
extension P {
func foo() {}
}
class C: P {}
let e: any P = C()
```
Such default methods are SILGen'd with a generic self argument. Therefore we need to specialize such witness methods, even if the conforming type is not generic.
rdar://145855851
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import AST
|
||||
import SIL
|
||||
|
||||
/// Performs mandatory optimizations for performance-annotated functions, and global
|
||||
@@ -39,11 +40,6 @@ let mandatoryPerformanceOptimizations = ModulePass(name: "mandatory-performance-
|
||||
}
|
||||
|
||||
optimizeFunctionsTopDown(using: &worklist, moduleContext)
|
||||
|
||||
if moduleContext.options.enableEmbeddedSwift {
|
||||
// Print errors for generic functions in vtables, which is not allowed in embedded Swift.
|
||||
checkVTablesForGenericFunctions(moduleContext)
|
||||
}
|
||||
}
|
||||
|
||||
private func optimizeFunctionsTopDown(using worklist: inout FunctionWorklist,
|
||||
@@ -131,9 +127,27 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ modu
|
||||
|
||||
case let initExRef as InitExistentialRefInst:
|
||||
if context.options.enableEmbeddedSwift {
|
||||
specializeWitnessTables(for: initExRef, moduleContext, &worklist)
|
||||
for c in initExRef.conformances where c.isConcrete {
|
||||
specializeWitnessTable(for: c, moduleContext) {
|
||||
worklist.addWitnessMethods(of: $0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case let bi as BuiltinInst:
|
||||
switch bi.id {
|
||||
case .BuildOrdinaryTaskExecutorRef,
|
||||
.BuildOrdinarySerialExecutorRef,
|
||||
.BuildComplexEqualitySerialExecutorRef:
|
||||
specializeWitnessTable(for: bi.substitutionMap.conformances[0], moduleContext) {
|
||||
worklist.addWitnessMethods(of: $0)
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// We need to de-virtualize deinits of non-copyable types to be able to specialize the deinitializers.
|
||||
case let destroyValue as DestroyValueInst:
|
||||
if !devirtualizeDeinits(of: destroyValue, simplifyCtxt) {
|
||||
@@ -282,47 +296,6 @@ private func shouldInline(apply: FullApplySite, callee: Function, alreadyInlined
|
||||
return false
|
||||
}
|
||||
|
||||
private func specializeWitnessTables(for initExRef: InitExistentialRefInst, _ context: ModulePassContext,
|
||||
_ worklist: inout FunctionWorklist)
|
||||
{
|
||||
for c in initExRef.conformances where c.isConcrete {
|
||||
let conformance = c.isInherited ? c.inheritedConformance : c
|
||||
let origWitnessTable = context.lookupWitnessTable(for: conformance)
|
||||
if conformance.isSpecialized {
|
||||
if origWitnessTable == nil {
|
||||
specializeWitnessTable(forConformance: conformance, errorLocation: initExRef.location, context) {
|
||||
worklist.addWitnessMethods(of: $0)
|
||||
}
|
||||
}
|
||||
} else if let origWitnessTable {
|
||||
checkForGenericMethods(in: origWitnessTable, errorLocation: initExRef.location, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func checkForGenericMethods(in witnessTable: WitnessTable,
|
||||
errorLocation: Location,
|
||||
_ context: ModulePassContext)
|
||||
{
|
||||
for entry in witnessTable.entries {
|
||||
if case .method(let requirement, let witness) = entry,
|
||||
let witness,
|
||||
witness.isGeneric
|
||||
{
|
||||
context.diagnosticEngine.diagnose(.cannot_specialize_witness_method, requirement, at: errorLocation)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func checkVTablesForGenericFunctions(_ context: ModulePassContext) {
|
||||
for vTable in context.vTables where !vTable.class.isGenericAtAnyLevel {
|
||||
for entry in vTable.entries where entry.implementation.isGeneric {
|
||||
context.diagnosticEngine.diagnose(.non_final_generic_class_function, at: entry.methodDecl.location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension FullApplySite {
|
||||
func resultIsUsedInGlobalInitialization() -> SmallProjectionPath? {
|
||||
guard parentFunction.isGlobalInitOnceFunction,
|
||||
|
||||
Reference in New Issue
Block a user