Skip to content

Commit 9c5b3a1

Browse files
authored
Merge pull request swiftlang#39223 from eeckstein/fix-serialization-5.5
[5.5] Serialization: include global variables in the worklist-processing
2 parents c1f6b9d + 83184a9 commit 9c5b3a1

File tree

3 files changed

+73
-30
lines changed

3 files changed

+73
-30
lines changed

lib/Serialization/SerializeSIL.cpp

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,9 @@ namespace {
221221
DifferentiabilityWitnessesToEmit;
222222

223223
/// Additional functions we might need to serialize.
224-
llvm::SmallVector<const SILFunction *, 16> Worklist;
224+
llvm::SmallVector<const SILFunction *, 16> functionWorklist;
225+
226+
llvm::SmallVector<const SILGlobalVariable *, 16> globalWorklist;
225227

226228
/// String storage for temporarily created strings which are referenced from
227229
/// the tables.
@@ -244,7 +246,9 @@ namespace {
244246
bool emitDeclarationsForOnoneSupport);
245247
void addReferencedSILFunction(const SILFunction *F,
246248
bool DeclOnly = false);
247-
void processSILFunctionWorklist();
249+
void addReferencedGlobalVariable(const SILGlobalVariable *gl);
250+
251+
void processWorklists();
248252

249253
/// Helper function to update ListOfValues for MethodInst. Format:
250254
/// Attr, SILDeclRef (DeclID, Kind, uncurryLevel), and an operand.
@@ -334,7 +338,7 @@ void SILSerializer::addMandatorySILFunction(const SILFunction *F,
334338
// Function body should be serialized unless it is a KeepAsPublic function
335339
// (which is typically a pre-specialization).
336340
if (!emitDeclarationsForOnoneSupport)
337-
Worklist.push_back(F);
341+
functionWorklist.push_back(F);
338342
}
339343

340344
void SILSerializer::addReferencedSILFunction(const SILFunction *F,
@@ -348,7 +352,7 @@ void SILSerializer::addReferencedSILFunction(const SILFunction *F,
348352
// serialize the body or just the declaration.
349353
if (shouldEmitFunctionBody(F)) {
350354
FuncsToEmit[F] = false;
351-
Worklist.push_back(F);
355+
functionWorklist.push_back(F);
352356
return;
353357
}
354358

@@ -357,23 +361,35 @@ void SILSerializer::addReferencedSILFunction(const SILFunction *F,
357361
F->hasForeignBody());
358362

359363
FuncsToEmit[F] = false;
360-
Worklist.push_back(F);
364+
functionWorklist.push_back(F);
361365
return;
362366
}
363367

364368
// Ok, we just need to emit a declaration.
365369
FuncsToEmit[F] = true;
366370
}
367371

368-
void SILSerializer::processSILFunctionWorklist() {
369-
while (!Worklist.empty()) {
370-
const SILFunction *F = Worklist.back();
371-
Worklist.pop_back();
372-
assert(F != nullptr);
372+
void SILSerializer::addReferencedGlobalVariable(const SILGlobalVariable *gl) {
373+
if (GlobalsToEmit.insert(gl).second)
374+
globalWorklist.push_back(gl);
375+
}
373376

374-
assert(FuncsToEmit.count(F) > 0);
375-
writeSILFunction(*F, FuncsToEmit[F]);
376-
}
377+
378+
void SILSerializer::processWorklists() {
379+
do {
380+
while (!functionWorklist.empty()) {
381+
const SILFunction *F = functionWorklist.pop_back_val();
382+
assert(F != nullptr);
383+
384+
assert(FuncsToEmit.count(F) > 0);
385+
writeSILFunction(*F, FuncsToEmit[F]);
386+
}
387+
while (!globalWorklist.empty()) {
388+
const SILGlobalVariable *gl = globalWorklist.pop_back_val();
389+
assert(GlobalsToEmit.count(gl) > 0);
390+
writeSILGlobalVar(*gl);
391+
}
392+
} while (!functionWorklist.empty());
377393
}
378394

379395
/// We enumerate all values in a SILFunction beforehand to correctly
@@ -1116,7 +1132,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
11161132
// Format: Name and type. Use SILOneOperandLayout.
11171133
const AllocGlobalInst *AGI = cast<AllocGlobalInst>(&SI);
11181134
auto *G = AGI->getReferencedGlobal();
1119-
GlobalsToEmit.insert(G);
1135+
addReferencedGlobalVariable(G);
11201136
SILOneOperandLayout::emitRecord(Out, ScratchRecord,
11211137
SILAbbrCodes[SILOneOperandLayout::Code],
11221138
(unsigned)SI.getKind(), 0, 0, 0,
@@ -1128,7 +1144,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
11281144
// Format: Name and type. Use SILOneOperandLayout.
11291145
const GlobalAccessInst *GI = cast<GlobalAccessInst>(&SI);
11301146
auto *G = GI->getReferencedGlobal();
1131-
GlobalsToEmit.insert(G);
1147+
addReferencedGlobalVariable(G);
11321148
SILOneOperandLayout::emitRecord(Out, ScratchRecord,
11331149
SILAbbrCodes[SILOneOperandLayout::Code],
11341150
(unsigned)SI.getKind(), 0,
@@ -2816,6 +2832,12 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
28162832
writeSILDefaultWitnessTable(wt);
28172833
}
28182834

2835+
// Add global variables that must be emitted to the list.
2836+
for (const SILGlobalVariable &g : SILMod->getSILGlobals()) {
2837+
if (g.isSerialized() || ShouldSerializeAll)
2838+
addReferencedGlobalVariable(&g);
2839+
}
2840+
28192841
// Emit only declarations if it is a module with pre-specializations.
28202842
// And only do it in optimized builds.
28212843
bool emitDeclarationsForOnoneSupport =
@@ -2835,7 +2857,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
28352857
}
28362858

28372859
addMandatorySILFunction(&F, emitDeclarationsForOnoneSupport);
2838-
processSILFunctionWorklist();
2860+
processWorklists();
28392861
}
28402862

28412863
// Write out differentiability witnesses.
@@ -2854,7 +2876,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
28542876
// Process SIL functions referenced by differentiability witnesses.
28552877
// Note: this is necessary despite processing `FuncsToEmit` below because
28562878
// `Worklist` is processed separately.
2857-
processSILFunctionWorklist();
2879+
processWorklists();
28582880

28592881
// Now write function declarations for every function we've
28602882
// emitted a reference to without emitting a function body for.
@@ -2868,16 +2890,8 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
28682890
}
28692891
}
28702892

2871-
// Add global variables that must be emitted to the list.
2872-
for (const SILGlobalVariable &g : SILMod->getSILGlobals())
2873-
if (g.isSerialized() || ShouldSerializeAll)
2874-
GlobalsToEmit.insert(&g);
2875-
2876-
// Now write out all referenced global variables.
2877-
for (auto *g : GlobalsToEmit)
2878-
writeSILGlobalVar(*g);
2879-
2880-
assert(Worklist.empty() && "Did not emit everything in worklist");
2893+
assert(functionWorklist.empty() && globalWorklist.empty() &&
2894+
"Did not emit everything in worklists");
28812895
}
28822896

28832897
void SILSerializer::writeSILModule(const SILModule *SILMod) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-sil-opt %s -serialize -o /dev/null
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
7+
// Check that we don't crash if a serialiable function is referenced from the
8+
// initializer of a global variable.
9+
10+
sil_global [serialized] @globalFuncPtr : $@callee_guaranteed () -> () = {
11+
%0 = function_ref @calledFromFuncPtr : $@convention(thin) () -> ()
12+
%initval = thin_to_thick_function %0 : $@convention(thin) () -> () to $@callee_guaranteed () -> ()
13+
}
14+
15+
sil @caller : $@convention(thin) () -> () {
16+
bb0:
17+
%0 = global_addr @globalFuncPtr : $*@callee_guaranteed () -> ()
18+
%7 = tuple ()
19+
return %7 : $()
20+
}
21+
22+
sil shared [serializable] @calledFromFuncPtr : $@convention(thin) () -> () {
23+
bb0:
24+
%6 = tuple ()
25+
return %6 : $()
26+
}

tools/sil-opt/SILOpt.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ EmitVerboseSIL("emit-verbose-sil",
228228
static llvm::cl::opt<bool>
229229
EmitSIB("emit-sib", llvm::cl::desc("Emit serialized AST + SIL file(s)"));
230230

231+
static llvm::cl::opt<bool>
232+
Serialize("serialize", llvm::cl::desc("Emit serialized AST + SIL file(s)"));
233+
231234
static llvm::cl::opt<std::string>
232235
ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path"));
233236

@@ -564,7 +567,7 @@ int main(int argc, char **argv) {
564567
}
565568
}
566569

567-
if (EmitSIB) {
570+
if (EmitSIB || Serialize) {
568571
llvm::SmallString<128> OutputFile;
569572
if (OutputFilename.size()) {
570573
OutputFile = OutputFilename;
@@ -580,8 +583,8 @@ int main(int argc, char **argv) {
580583

581584
SerializationOptions serializationOpts;
582585
serializationOpts.OutputPath = OutputFile.c_str();
583-
serializationOpts.SerializeAllSIL = true;
584-
serializationOpts.IsSIB = true;
586+
serializationOpts.SerializeAllSIL = EmitSIB;
587+
serializationOpts.IsSIB = EmitSIB;
585588

586589
serialize(CI.getMainModule(), serializationOpts, SILMod.get());
587590
} else {

0 commit comments

Comments
 (0)