Skip to content

Commit af38053

Browse files
authored
Merge pull request #15531 from graydon/sort-jobs-dont-assert
2 parents e485c15 + af538f1 commit af38053

File tree

3 files changed

+74
-22
lines changed

3 files changed

+74
-22
lines changed

lib/Driver/ToolChain.cpp

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,17 @@ mergeBatchInputs(ArrayRef<const Job *> jobs,
280280
return false;
281281
}
282282

283-
/// Debugging only: return whether the set of \p jobs is an ordered subsequence
284-
/// of the sequence of top-level input files in the \c Compilation \p C.
285-
static bool
286-
jobsAreSubsequenceOfCompilationInputs(ArrayRef<const Job *> jobs,
287-
Compilation &C) {
288-
llvm::SmallVector<const Job *, 16> sortedJobs;
283+
/// Unfortunately the success or failure of a Swift compilation is currently
284+
/// sensitive to the order in which files are processed, at least in terms of
285+
/// the order of processing extensions (and likely other ways we haven't
286+
/// discovered yet). So long as this is true, we need to make sure any batch job
287+
/// we build names its inputs in an order that's a subsequence of the sequence
288+
/// of inputs the driver was initially invoked with.
289+
static void sortJobsToMatchCompilationInputs(ArrayRef<const Job *> unsortedJobs,
290+
SmallVectorImpl<const Job *> &sortedJobs,
291+
Compilation &C) {
289292
llvm::StringMap<const Job *> jobsByInput;
290-
for (const Job *J : jobs) {
293+
for (const Job *J : unsortedJobs) {
291294
const CompileJobAction *CJA = cast<CompileJobAction>(&J->getSource());
292295
const InputAction* IA = findSingleSwiftInput(CJA);
293296
auto R = jobsByInput.insert(std::make_pair(IA->getInputArg().getValue(),
@@ -300,40 +303,34 @@ jobsAreSubsequenceOfCompilationInputs(ArrayRef<const Job *> jobs,
300303
sortedJobs.push_back(I->second);
301304
}
302305
}
303-
if (sortedJobs.size() != jobs.size())
304-
return false;
305-
for (size_t i = 0; i < sortedJobs.size(); ++i) {
306-
if (sortedJobs[i] != jobs[i])
307-
return false;
308-
}
309-
return true;
310306
}
311307

312308
/// Construct a \c BatchJob by merging the constituent \p jobs' CommandOutput,
313309
/// input \c Job and \c Action members. Call through to \c constructInvocation
314310
/// on \p BatchJob, to build the \c InvocationInfo.
315311
std::unique_ptr<Job>
316-
ToolChain::constructBatchJob(ArrayRef<const Job *> jobs,
312+
ToolChain::constructBatchJob(ArrayRef<const Job *> unsortedJobs,
317313
Compilation &C) const
318314
{
319-
if (jobs.empty())
315+
if (unsortedJobs.empty())
320316
return nullptr;
321317

322-
assert(jobsAreSubsequenceOfCompilationInputs(jobs, C));
318+
llvm::SmallVector<const Job *, 16> sortedJobs;
319+
sortJobsToMatchCompilationInputs(unsortedJobs, sortedJobs, C);
323320

324321
// Synthetic OutputInfo is a slightly-modified version of the initial
325322
// compilation's OI.
326323
auto OI = C.getOutputInfo();
327324
OI.CompilerMode = OutputInfo::Mode::BatchModeCompile;
328325

329-
auto const *executablePath = jobs[0]->getExecutable();
330-
auto outputType = jobs[0]->getOutput().getPrimaryOutputType();
331-
auto output = makeBatchCommandOutput(jobs, C, outputType);
326+
auto const *executablePath = sortedJobs[0]->getExecutable();
327+
auto outputType = sortedJobs[0]->getOutput().getPrimaryOutputType();
328+
auto output = makeBatchCommandOutput(sortedJobs, C, outputType);
332329

333330
llvm::SmallSetVector<const Job *, 16> inputJobs;
334331
llvm::SmallSetVector<const Action *, 16> inputActions;
335332
auto *batchCJA = C.createAction<CompileJobAction>(outputType);
336-
if (mergeBatchInputs(jobs, inputJobs, inputActions, batchCJA))
333+
if (mergeBatchInputs(sortedJobs, inputJobs, inputActions, batchCJA))
337334
return nullptr;
338335

339336
JobContext context{C, inputJobs.getArrayRef(), inputActions.getArrayRef(),
@@ -346,7 +343,7 @@ ToolChain::constructBatchJob(ArrayRef<const Job *> jobs,
346343
std::move(invocationInfo.Arguments),
347344
std::move(invocationInfo.ExtraEnvironment),
348345
std::move(invocationInfo.FilelistInfos),
349-
jobs);
346+
sortedJobs);
350347
}
351348

352349
bool

test/Driver/Inputs/abcd_filemap.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"":
2+
swift-dependencies: "master.yaml"
3+
"a.swift":
4+
object: "a.o"
5+
dependencies: "a.d"
6+
diagnostics: "a.dia"
7+
swift-dependencies: "a.swiftdeps"
8+
"b.swift":
9+
object: "b.o"
10+
dependencies: "b.d"
11+
diagnostics: "b.dia"
12+
swift-dependencies: "b.swiftdeps"
13+
"c.swift":
14+
object: "c.o"
15+
dependencies: "c.d"
16+
diagnostics: "c.dia"
17+
swift-dependencies: "c.swiftdeps"
18+
"d.swift":
19+
object: "d.o"
20+
dependencies: "d.d"
21+
diagnostics: "d.dia"
22+
swift-dependencies: "d.swiftdeps"
23+
"main.swift":
24+
object: "main.o"
25+
dependencies: "main.d"
26+
diagnostics: "main.dia"
27+
swift-dependencies: "main.swiftdeps"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: echo 'class a {}' >%t/a.swift
3+
// RUN: echo 'class b : a {}' >%t/b.swift
4+
// RUN: echo 'class c : b {}' >%t/c.swift
5+
// RUN: echo 'class d : c {}' >%t/d.swift
6+
// RUN: echo 'public func main() {}' >%t/main.swift
7+
//
8+
// First prime the incremental state, but note that we're building in the d c b a (reverse-alphabetical) order.
9+
// RUN: (cd %t && %swiftc_driver -enable-batch-mode -incremental -output-file-map %S/Inputs/abcd_filemap.yaml -module-name main -j 1 d.swift c.swift b.swift a.swift main.swift)
10+
//
11+
// Now perturb the interface of a.swift and delete its output
12+
// RUN: echo 'class a { var x : Int = 10 }' >%t/a.swift
13+
// RUN: rm %t/a.o
14+
//
15+
// Now rebuild, which will rebuild a.swift then do a cascading dep-graph invalidation
16+
// RUN: (cd %t && %swiftc_driver -enable-batch-mode -incremental -output-file-map %S/Inputs/abcd_filemap.yaml -module-name main -j 1 d.swift c.swift b.swift a.swift main.swift -driver-show-incremental -driver-show-job-lifecycle) >%t/out.txt 2>&1
17+
// RUN: %FileCheck %s <%t/out.txt
18+
//
19+
// Check that we saw invalidation happen in alphabetic order
20+
// CHECK: Queuing because of dependencies discovered later: {compile: b.o <= b.swift}
21+
// CHECK: Queuing because of dependencies discovered later: {compile: c.o <= c.swift}
22+
// CHECK: Queuing because of dependencies discovered later: {compile: d.o <= d.swift}
23+
// CHECK: Batchable: {compile: b.o <= b.swift}
24+
// CHECK: Batchable: {compile: c.o <= c.swift}
25+
// CHECK: Batchable: {compile: d.o <= d.swift}
26+
//
27+
// But check that we still issued the job in reverse-alphabetic order
28+
// CHECK: Adding batch job to task queue: {compile: d.o c.o b.o <= d.swift c.swift b.swift}

0 commit comments

Comments
 (0)