@@ -33,13 +33,23 @@ let mandatoryPerformanceOptimizations = ModulePass(name: "mandatory-performance-
3333 // For embedded Swift, optimize all the functions (there cannot be any
3434 // generics, type metadata, etc.)
3535 if moduleContext. options. enableEmbeddedSwift {
36+ // We need to specialize all vtables which are referenced from non-generic contexts. Beside
37+ // `alloc_ref`s of generic classes in non-generic functions, we also need to specialize generic
38+ // superclasses of non-generic classes. E.g. `class Derived : Base<Int> {}`
39+ specializeVTablesOfSuperclasses ( moduleContext)
40+
3641 worklist. addAllNonGenericFunctions ( of: moduleContext)
3742 } else {
3843 worklist. addAllPerformanceAnnotatedFunctions ( of: moduleContext)
3944 worklist. addAllAnnotatedGlobalInitOnceFunctions ( of: moduleContext)
4045 }
4146
4247 optimizeFunctionsTopDown ( using: & worklist, moduleContext)
48+
49+ if moduleContext. options. enableEmbeddedSwift {
50+ // Print errors for generic functions in vtables, which is not allowed in embedded Swift.
51+ checkVTablesForGenericFunctions ( moduleContext)
52+ }
4353}
4454
4555private func optimizeFunctionsTopDown( using worklist: inout FunctionWorklist ,
@@ -92,11 +102,15 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ modu
92102 // Embedded Swift specific transformations
93103 case let alloc as AllocRefInst :
94104 if context. options. enableEmbeddedSwift {
95- specializeVTableAndAddEntriesToWorklist ( for: alloc. type, in: function, context, moduleContext, & worklist)
105+ specializeVTableAndAddEntriesToWorklist ( for: alloc. type, in: function,
106+ errorLocation: alloc. location,
107+ moduleContext, & worklist)
96108 }
97109 case let metatype as MetatypeInst :
98110 if context. options. enableEmbeddedSwift {
99- specializeVTableAndAddEntriesToWorklist ( for: metatype. type, in: function, context, moduleContext, & worklist)
111+ specializeVTableAndAddEntriesToWorklist ( for: metatype. type, in: function,
112+ errorLocation: metatype. location,
113+ moduleContext, & worklist)
100114 }
101115 case let classMethod as ClassMethodInst :
102116 if context. options. enableEmbeddedSwift {
@@ -144,18 +158,23 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ modu
144158}
145159
146160private func specializeVTableAndAddEntriesToWorklist( for type: Type , in function: Function ,
147- _ context: FunctionPassContext , _ moduleContext: ModulePassContext ,
161+ errorLocation: Location ,
162+ _ moduleContext: ModulePassContext ,
148163 _ worklist: inout FunctionWorklist ) {
149164 let vTablesCountBefore = moduleContext. vTables. count
150165
151- guard context . specializeVTable ( for : type, in : function ) != nil else {
166+ guard specializeVTable ( forClassType : type, errorLocation : errorLocation , moduleContext ) != nil else {
152167 return
153168 }
154169
155170 // More than one new vtable might have been created (superclasses), process them all
156171 let vTables = moduleContext. vTables
157172 for i in vTablesCountBefore ..< vTables. count {
158- for entry in vTables [ i] . entries {
173+ for entry in vTables [ i] . entries
174+ // A new vtable can still contain a generic function if the method couldn't be specialized for some reason
175+ // and an error has been printed. Exclude generic functions to not run into an assert later.
176+ where !entry. implementation. isGeneric
177+ {
159178 worklist. pushIfNotVisited ( entry. implementation)
160179 }
161180 }
@@ -240,6 +259,14 @@ private func shouldInline(apply: FullApplySite, callee: Function, alreadyInlined
240259 return false
241260}
242261
262+ private func checkVTablesForGenericFunctions( _ context: ModulePassContext ) {
263+ for vTable in context. vTables where !vTable. class. isGenericAtAnyLevel {
264+ for entry in vTable. entries where entry. implementation. isGeneric {
265+ context. diagnosticEngine. diagnose ( entry. methodDecl. location. sourceLoc, . non_final_generic_class_function)
266+ }
267+ }
268+ }
269+
243270private extension FullApplySite {
244271 func resultIsUsedInGlobalInitialization( ) -> SmallProjectionPath ? {
245272 guard parentFunction. isGlobalInitOnceFunction,
0 commit comments