@@ -71,6 +71,7 @@ class CrossModuleOptimization {
71
71
: M(M), conservative(conservative), everything(everything) { }
72
72
73
73
void serializeFunctionsInModule ();
74
+ void serializeTablesInModule ();
74
75
75
76
private:
76
77
bool canSerializeFunction (SILFunction *function,
@@ -188,6 +189,35 @@ void CrossModuleOptimization::serializeFunctionsInModule() {
188
189
}
189
190
}
190
191
192
+ void CrossModuleOptimization::serializeTablesInModule () {
193
+ if (!M.getOptions ().EnableSerializePackage )
194
+ return ;
195
+
196
+ for (const auto &vt : M.getVTables ()) {
197
+ if (!vt->isSerialized () &&
198
+ vt->getClass ()->getEffectiveAccess () >= AccessLevel::Package) {
199
+ vt->setSerialized (IsSerialized);
200
+ }
201
+ }
202
+
203
+ for (auto &wt : M.getWitnessTables ()) {
204
+ if (!wt.isSerialized () && (wt.getLinkage () == SILLinkage::Package ||
205
+ wt.getLinkage () == SILLinkage::Public)) {
206
+ for (auto &entry : wt.getEntries ()) {
207
+ // Entries in witness table with package linkage are not serialized
208
+ // (by default only entries in public witness table are; \see
209
+ // SILWitnessTable::conformanceIsSerialized), so serialize them here
210
+ // if package-cmo is enabled (otherwise nil).
211
+ if (entry.getKind () == SILWitnessTable::Method &&
212
+ !entry.getMethodWitness ().Witness ->isSerialized ())
213
+ entry.getMethodWitness ().Witness ->setSerialized (IsSerialized);
214
+ }
215
+ // Then serialize the witness table itself.
216
+ wt.setSerialized (IsSerialized);
217
+ }
218
+ }
219
+ }
220
+
191
221
// / Recursively walk the call graph and select functions to be serialized.
192
222
// /
193
223
// / The results are stored in \p canSerializeFlags and the result for \p
@@ -280,9 +310,21 @@ bool CrossModuleOptimization::canSerializeInstruction(SILInstruction *inst,
280
310
// public functions, because that can increase code size. E.g. if the
281
311
// function is completely inlined afterwards.
282
312
// Also, when emitting TBD files, we cannot introduce a new public symbol.
283
- if ((conservative || M.getOptions ().emitTBD ) &&
284
- !hasPublicOrPackageVisibility (callee->getLinkage (), M.getOptions ().EnableSerializePackage )) {
285
- return false ;
313
+ if (conservative || M.getOptions ().emitTBD ) {
314
+ // In package-cmo, serialize this inst if its referenced function has
315
+ // package+ linkage, or is a definition with shared linkage.
316
+ // For example, `public func foo() { print("") }` is a function with
317
+ // public linkage which contains `print`, which is a definition with
318
+ // shared linkage, thus should be serialized.
319
+ if (M.getOptions ().EnableSerializePackage ) {
320
+ if (!(hasPublicOrPackageVisibility (callee->getLinkage (),
321
+ /* includePackage*/ true ) ||
322
+ (hasSharedVisibility (callee->getLinkage ()) &&
323
+ callee->isDefinition ())))
324
+ return false ;
325
+ } else if (!hasPublicVisibility (callee->getLinkage ())) {
326
+ return false ;
327
+ }
286
328
}
287
329
288
330
// In some project configurations imported C functions are not necessarily
@@ -374,7 +416,7 @@ bool CrossModuleOptimization::canSerializeType(SILType type) {
374
416
[this ](Type rawSubType) {
375
417
CanType subType = rawSubType->getCanonicalType ();
376
418
if (NominalTypeDecl *subNT = subType->getNominalOrBoundGenericNominal ()) {
377
-
419
+
378
420
if (conservative && subNT->getEffectiveAccess () < AccessLevel::Package) {
379
421
return true ;
380
422
}
@@ -482,6 +524,12 @@ bool CrossModuleOptimization::shouldSerialize(SILFunction *function) {
482
524
483
525
if (function->getLinkage () == SILLinkage::Shared)
484
526
return true ;
527
+ } else if (function->getModule ().getOptions ().EnableSerializePackage &&
528
+ (function->getLinkage () == SILLinkage::Package ||
529
+ function->getLinkage () == SILLinkage::Public)) {
530
+ // If package-cmo is enabled, we should not limit the amount of inlining
531
+ // as checked with CMOFunctionSizeLimit below.
532
+ return true ;
485
533
}
486
534
487
535
// Also serialize "small" non-generic functions.
@@ -503,7 +551,7 @@ void CrossModuleOptimization::serializeFunction(SILFunction *function,
503
551
const FunctionFlags &canSerializeFlags) {
504
552
if (function->isSerialized ())
505
553
return ;
506
-
554
+
507
555
if (!canSerializeFlags.lookup (function))
508
556
return ;
509
557
@@ -699,7 +747,10 @@ class CrossModuleOptimizationPass: public SILModuleTransform {
699
747
void run () override {
700
748
701
749
auto &M = *getModule ();
702
- if (M.getSwiftModule ()->isResilient ())
750
+ if (M.getSwiftModule ()->isResilient () &&
751
+ // FIXME: need to properly lower type when this is enabled
752
+ // else leads to assert fail.
753
+ !M.getOptions ().EnableSerializePackage )
703
754
return ;
704
755
if (!M.isWholeModule ())
705
756
return ;
@@ -727,6 +778,7 @@ class CrossModuleOptimizationPass: public SILModuleTransform {
727
778
728
779
CrossModuleOptimization CMO (M, conservative, everything);
729
780
CMO.serializeFunctionsInModule ();
781
+ CMO.serializeTablesInModule ();
730
782
}
731
783
};
732
784
0 commit comments