@@ -157,10 +157,14 @@ namespace {
157
157
uint32_t /* DeclID*/ NextDefaultWitnessTableID = 1 ;
158
158
159
159
// / Give each SILBasicBlock a unique ID.
160
- llvm::DenseMap<const SILBasicBlock*, unsigned > BasicBlockMap;
160
+ llvm::DenseMap<const SILBasicBlock *, unsigned > BasicBlockMap;
161
161
162
- // / Functions that we've emitted a reference to.
163
- llvm::SmallSet<const SILFunction *, 16 > FuncsToDeclare;
162
+ // / Functions that we've emitted a reference to. If the key maps
163
+ // / to true, we want to emit a declaration only.
164
+ llvm::DenseMap<const SILFunction *, bool > FuncsToEmit;
165
+
166
+ // / Additional functions we might need to serialize.
167
+ llvm::SmallVector<const SILFunction *, 16 > Worklist;
164
168
165
169
std::array<unsigned , 256 > SILAbbrCodes;
166
170
template <typename Layout>
@@ -175,6 +179,12 @@ namespace {
175
179
176
180
bool ShouldSerializeAll;
177
181
182
+ void addMandatorySILFunction (const SILFunction *F,
183
+ bool emitDeclarationsForOnoneSupport);
184
+ void addReferencedSILFunction (const SILFunction *F,
185
+ bool DeclOnly = false );
186
+ void processSILFunctionWorklist ();
187
+
178
188
// / Helper function to update ListOfValues for MethodInst. Format:
179
189
// / Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC), and an operand.
180
190
void handleMethodInst (const MethodInst *MI, SILValue operand,
@@ -207,7 +217,7 @@ namespace {
207
217
208
218
// / Helper function to determine if given the current state of the
209
219
// / deserialization if the function body for F should be deserialized.
210
- bool shouldEmitFunctionBody (const SILFunction & F);
220
+ bool shouldEmitFunctionBody (const SILFunction * F);
211
221
212
222
public:
213
223
SILSerializer (Serializer &S, ASTContext &Ctx,
@@ -218,6 +228,69 @@ namespace {
218
228
};
219
229
} // end anonymous namespace
220
230
231
+ void SILSerializer::addMandatorySILFunction (const SILFunction *F,
232
+ bool emitDeclarationsForOnoneSupport) {
233
+ // If this function is not fragile, don't do anything.
234
+ if (!shouldEmitFunctionBody (F))
235
+ return ;
236
+
237
+ auto iter = FuncsToEmit.find (F);
238
+ if (iter != FuncsToEmit.end ()) {
239
+ // We've already visited this function. Make sure that we decided
240
+ // to emit its body the first time around.
241
+ assert (iter->second == emitDeclarationsForOnoneSupport
242
+ && " Already emitting declaration" );
243
+ return ;
244
+ }
245
+
246
+ // We haven't seen this function before. Record that we want to
247
+ // emit its body, and add it to the worklist.
248
+ FuncsToEmit[F] = emitDeclarationsForOnoneSupport;
249
+ if (!emitDeclarationsForOnoneSupport)
250
+ Worklist.push_back (F);
251
+ }
252
+
253
+ void SILSerializer::addReferencedSILFunction (const SILFunction *F,
254
+ bool DeclOnly) {
255
+ assert (F != nullptr );
256
+
257
+ if (FuncsToEmit.count (F) > 0 )
258
+ return ;
259
+
260
+ // We haven't seen this function before. Let's see if we should
261
+ // serialize the body or just the declaration.
262
+ if (shouldEmitFunctionBody (F)) {
263
+ FuncsToEmit[F] = false ;
264
+ Worklist.push_back (F);
265
+ return ;
266
+ }
267
+
268
+ // If we referenced a non-fragile shared function from a fragile
269
+ // function, serialize it too. In practice, it will either be a
270
+ // thunk, or an optimizer specialization. In both cases, we don't
271
+ // have enough information at the time we emit the function to
272
+ // know if it should be marked fragile or not.
273
+ if (F->getLinkage () == SILLinkage::Shared && !DeclOnly) {
274
+ FuncsToEmit[F] = false ;
275
+ Worklist.push_back (F);
276
+ return ;
277
+ }
278
+
279
+ // Ok, we just need to emit a declaration.
280
+ FuncsToEmit[F] = true ;
281
+ }
282
+
283
+ void SILSerializer::processSILFunctionWorklist () {
284
+ while (Worklist.size () > 0 ) {
285
+ const SILFunction *F = Worklist.back ();
286
+ Worklist.pop_back ();
287
+ assert (F != nullptr );
288
+
289
+ assert (FuncsToEmit.count (F) > 0 );
290
+ writeSILFunction (*F, FuncsToEmit[F]);
291
+ }
292
+ }
293
+
221
294
// / We enumerate all values in a SILFunction beforehand to correctly
222
295
// / handle forward references of values.
223
296
ValueID SILSerializer::addValueRef (const ValueBase *Val) {
@@ -943,7 +1016,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
943
1016
S.addIdentifierRef (Ctx.getIdentifier (ReferencedFunction->getName ())));
944
1017
945
1018
// Make sure we declare the referenced function.
946
- FuncsToDeclare. insert (ReferencedFunction);
1019
+ addReferencedSILFunction (ReferencedFunction);
947
1020
break ;
948
1021
}
949
1022
case ValueKind::DeallocPartialRefInst:
@@ -1558,7 +1631,7 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) {
1558
1631
for (auto &entry : vt.getEntries ()) {
1559
1632
SmallVector<ValueID, 4 > ListOfValues;
1560
1633
handleSILDeclRef (S, entry.first , ListOfValues);
1561
- FuncsToDeclare. insert (entry.second );
1634
+ addReferencedSILFunction (entry.second , true );
1562
1635
// Each entry is a pair of SILDeclRef and SILFunction.
1563
1636
VTableEntryLayout::emitRecord (Out, ScratchRecord,
1564
1637
SILAbbrCodes[VTableEntryLayout::Code],
@@ -1619,9 +1692,9 @@ void SILSerializer::writeSILWitnessTable(const SILWitnessTable &wt) {
1619
1692
auto &methodWitness = entry.getMethodWitness ();
1620
1693
SmallVector<ValueID, 4 > ListOfValues;
1621
1694
handleSILDeclRef (S, methodWitness.Requirement , ListOfValues);
1622
- FuncsToDeclare.insert (methodWitness.Witness );
1623
1695
IdentifierID witnessID = 0 ;
1624
1696
if (SILFunction *witness = methodWitness.Witness ) {
1697
+ addReferencedSILFunction (witness, true );
1625
1698
witnessID = S.addIdentifierRef (Ctx.getIdentifier (witness->getName ()));
1626
1699
}
1627
1700
WitnessMethodEntryLayout::emitRecord (Out, ScratchRecord,
@@ -1656,7 +1729,7 @@ writeSILDefaultWitnessTable(const SILDefaultWitnessTable &wt) {
1656
1729
SmallVector<ValueID, 4 > ListOfValues;
1657
1730
handleSILDeclRef (S, entry.getRequirement (), ListOfValues);
1658
1731
SILFunction *witness = entry.getWitness ();
1659
- FuncsToDeclare. insert (witness);
1732
+ addReferencedSILFunction (witness, true );
1660
1733
IdentifierID witnessID = S.addIdentifierRef (
1661
1734
Ctx.getIdentifier (witness->getName ()));
1662
1735
DefaultWitnessTableEntryLayout::emitRecord (Out, ScratchRecord,
@@ -1668,17 +1741,19 @@ writeSILDefaultWitnessTable(const SILDefaultWitnessTable &wt) {
1668
1741
}
1669
1742
1670
1743
// / Helper function for whether to emit a function body.
1671
- bool SILSerializer::shouldEmitFunctionBody (const SILFunction &F) {
1744
+ bool SILSerializer::shouldEmitFunctionBody (const SILFunction *F) {
1745
+ // If we are asked to serialize everything, go ahead and do it.
1746
+ if (ShouldSerializeAll)
1747
+ return true ;
1748
+
1672
1749
// If F is a declaration, it has no body to emit...
1673
- if (F. isExternalDeclaration ())
1750
+ if (F-> isExternalDeclaration ())
1674
1751
return false ;
1675
1752
1676
1753
// If F is transparent, we should always emit its body.
1677
- if (F. isFragile ())
1754
+ if (F-> isFragile ())
1678
1755
return true ;
1679
1756
1680
- // Otherwise serialize the body of the function only if we are asked to
1681
- // serialize everything.
1682
1757
return false ;
1683
1758
}
1684
1759
@@ -1769,29 +1844,33 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
1769
1844
// Go through all the SILFunctions in SILMod and write out any
1770
1845
// mandatory function bodies.
1771
1846
for (const SILFunction &F : *SILMod) {
1772
- if (shouldEmitFunctionBody (F) || ShouldSerializeAll) {
1773
- if (emitDeclarationsForOnoneSupport) {
1774
- // Only declarations of whitelisted pre-specializations from with
1775
- // public linkage need to be serialized as they will be used
1776
- // by UsePrespecializations pass during -Onone compilation to
1777
- // check for availability of concrete pre-specializations.
1778
- if (!hasPublicVisibility (F.getLinkage ()) ||
1779
- !isWhitelistedSpecialization (F.getName ()))
1780
- continue ;
1781
- }
1782
- writeSILFunction (F, emitDeclarationsForOnoneSupport);
1847
+ if (emitDeclarationsForOnoneSupport) {
1848
+ // Only declarations of whitelisted pre-specializations from with
1849
+ // public linkage need to be serialized as they will be used
1850
+ // by UsePrespecializations pass during -Onone compilation to
1851
+ // check for availability of concrete pre-specializations.
1852
+ if (!hasPublicVisibility (F.getLinkage ()) ||
1853
+ !isWhitelistedSpecialization (F.getName ()))
1854
+ continue ;
1783
1855
}
1784
- }
1785
1856
1786
- if (ShouldSerializeAll)
1787
- return ;
1857
+ addMandatorySILFunction (&F, emitDeclarationsForOnoneSupport);
1858
+ processSILFunctionWorklist ();
1859
+ }
1788
1860
1789
1861
// Now write function declarations for every function we've
1790
1862
// emitted a reference to without emitting a function body for.
1791
1863
for (const SILFunction &F : *SILMod) {
1792
- if (!shouldEmitFunctionBody (F) && FuncsToDeclare.count (&F))
1864
+ auto iter = FuncsToEmit.find (&F);
1865
+ if (iter != FuncsToEmit.end () && iter->second ) {
1866
+ assert ((emitDeclarationsForOnoneSupport ||
1867
+ !shouldEmitFunctionBody (&F)) &&
1868
+ " Should have emitted function body earlier" );
1793
1869
writeSILFunction (F, true );
1870
+ }
1794
1871
}
1872
+
1873
+ assert (Worklist.empty () && " Did not emit everything in worklist" );
1795
1874
}
1796
1875
1797
1876
void SILSerializer::writeSILModule (const SILModule *SILMod) {
0 commit comments