Skip to content

Commit 742c398

Browse files
author
David Ungar
committed
Source-range-based dependencies
Frontend outputs source-as-compiled, and source-ranges file with function body ranges and ranges that were unparsed in secondaries. Driver computes diffs for each source file. If diffs are in function bodies, only recompiles that one file. Else if diffs are in what another file did not parse, then the other file need not be rebuilt.
1 parent 63c1f84 commit 742c398

40 files changed

+2762
-235
lines changed

Diff for: include/swift/AST/DiagnosticsDriver.def

+21
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,31 @@ WARNING(warn_opt_remark_disabled, none,
163163
WARNING(warn_ignoring_batch_mode,none,
164164
"ignoring '-enable-batch-mode' because '%0' was also specified", (StringRef))
165165

166+
WARNING(warn_ignoring_source_range_dependencies,none,
167+
"ignoring '-enable-source-range-dependencies' because '%0' was also specified", (StringRef))
168+
169+
WARNING(warn_bad_swift_ranges_header,none,
170+
"ignoring '-enable-source-range-dependencies' because of bad header in '%0'", (StringRef))
171+
172+
WARNING(warn_bad_swift_ranges_format,none,
173+
"ignoring '-enable-source-range-dependencies' because of bad format '%1' in '%0'", (StringRef, StringRef))
174+
166175
WARNING(warn_use_filelists_deprecated, none,
167176
"the option '-driver-use-filelists' is deprecated; use "
168177
"'-driver-filelist-threshold=0' instead", ())
169178

179+
WARNING(warn_unable_to_load_swift_ranges, none,
180+
"unable to load swift ranges file \"%0\", %1",
181+
(StringRef, StringRef))
182+
183+
WARNING(warn_unable_to_load_compiled_swift, none,
184+
"unable to load previously compiled swift file \"%0\", %1",
185+
(StringRef, StringRef))
186+
187+
WARNING(warn_unable_to_load_primary, none,
188+
"unable to load primary swift file \"%0\", %1",
189+
(StringRef, StringRef))
190+
170191
ERROR(cannot_find_migration_script, none,
171192
"missing migration script from path '%0'", (StringRef))
172193

Diff for: include/swift/AST/DiagnosticsFrontend.def

+16
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ ERROR(error_mode_cannot_emit_dependencies,none,
116116
"this mode does not support emitting dependency files", ())
117117
ERROR(error_mode_cannot_emit_reference_dependencies,none,
118118
"this mode does not support emitting reference dependency files", ())
119+
ERROR(error_mode_cannot_emit_swift_ranges,none,
120+
"this mode does not support emitting unparsed ranges files", ())
121+
ERROR(error_mode_cannot_emit_compiled_source,none,
122+
"this mode does not support emitting compiled source files", ())
119123
ERROR(error_mode_cannot_emit_header,none,
120124
"this mode does not support emitting Objective-C headers", ())
121125
ERROR(error_mode_cannot_emit_loaded_module_trace,none,
@@ -134,6 +138,10 @@ ERROR(cannot_emit_ir_skipping_function_bodies,none,
134138

135139
WARNING(emit_reference_dependencies_without_primary_file,none,
136140
"ignoring -emit-reference-dependencies (requires -primary-file)", ())
141+
WARNING(emit_swift_ranges_without_primary_file,none,
142+
"ignoring -emit-swift-ranges (requires -primary-file)", ())
143+
WARNING(emit_compiled_source_without_primary_file,none,
144+
"ignoring -emit-compiled-source (requires -primary-file)", ())
137145

138146
ERROR(error_bad_module_name,none,
139147
"module name \"%0\" is not a valid identifier"
@@ -279,6 +287,14 @@ ERROR(error_invalid_debug_prefix_map, none,
279287
"invalid argument '%0' to -debug-prefix-map; it must be of the form "
280288
"'original=remapped'", (StringRef))
281289

290+
291+
ERROR(error_unable_to_write_swift_ranges_file, none,
292+
"unable to write unparsed ranges file '$0': %1", (StringRef, StringRef))
293+
294+
ERROR(error_unable_to_write_compiled_source_file, none,
295+
"unable to write compiled source file: '$0': %1", (StringRef, StringRef))
296+
297+
282298
ERROR(invalid_vfs_overlay_file,none,
283299
"invalid virtual overlay file '%0'", (StringRef))
284300

Diff for: include/swift/AST/IncrementalRanges.h

+277
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
//===------------- IncrementalRanges.h -----------------------------*- C++
2+
//-*-===//
3+
//
4+
// This source file is part of the Swift.org open source project
5+
//
6+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
7+
// Licensed under Apache License v2.0 with Runtime Library Exception
8+
//
9+
// See https://swift.org/LICENSE.txt for license information
10+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef SWIFT_AST_INCREMENTALRANGES_H
15+
#define SWIFT_AST_INCREMENTALRANGES_H
16+
17+
// Summary: TBD
18+
19+
#include "swift/Basic/LLVM.h"
20+
#include "swift/Basic/NullablePtr.h"
21+
#include "swift/Basic/SourceLoc.h"
22+
#include "swift/Basic/StringExtras.h"
23+
#include "llvm/Support/YAMLTraits.h"
24+
#include <vector>
25+
26+
namespace swift {
27+
class PersistentParserState;
28+
class SourceManager;
29+
class DiagnosticEngine;
30+
class SourceFile;
31+
} // namespace swift
32+
33+
//==============================================================================
34+
// MARK: Range types
35+
//==============================================================================
36+
37+
namespace swift {
38+
namespace incremental_ranges {
39+
40+
struct SerializableSourceRange;
41+
42+
typedef std::vector<SerializableSourceRange> Ranges;
43+
typedef std::map<std::string, Ranges> RangesByFilename;
44+
} // namespace incremental_ranges
45+
} // namespace swift
46+
47+
//==============================================================================
48+
// MARK: SerializableSourceLocation
49+
//==============================================================================
50+
namespace swift {
51+
namespace incremental_ranges {
52+
53+
/// 1-origin
54+
struct SerializableSourceLocation {
55+
uint64_t line = 0;
56+
uint64_t column = 0;
57+
58+
SerializableSourceLocation(const SourceLoc loc, const SourceManager &SM);
59+
SerializableSourceLocation(uint64_t line, uint64_t column)
60+
: line(line), column(column) {}
61+
SerializableSourceLocation() = default;
62+
static const SerializableSourceLocation endOfAnyFile;
63+
64+
bool operator< (const SerializableSourceLocation &x) const {
65+
return line < x.line ? true
66+
: line > x.line ? false
67+
: column < x.column;
68+
}
69+
bool operator==(const SerializableSourceLocation &x) const {
70+
return line == x.line && column == x.column;
71+
}
72+
bool operator<=(const SerializableSourceLocation &x) const {
73+
return *this < x || *this == x;
74+
}
75+
void print(raw_ostream &out) const;
76+
void dump() const;
77+
};
78+
79+
} // namespace incremental_ranges
80+
} // namespace swift
81+
82+
template <>
83+
struct llvm::yaml::MappingTraits<
84+
swift::incremental_ranges::SerializableSourceLocation> {
85+
static const bool flow = true;
86+
static void
87+
mapping(llvm::yaml::IO &io,
88+
swift::incremental_ranges::SerializableSourceLocation &loc) {
89+
io.mapRequired("line", loc.line), io.mapRequired("column", loc.column);
90+
}
91+
};
92+
//==============================================================================
93+
// MARK: SerializableSourceRange
94+
//==============================================================================
95+
96+
namespace swift {
97+
namespace incremental_ranges {
98+
/// half-open, to facilitate representing empty ranges
99+
struct SerializableSourceRange {
100+
SerializableSourceLocation start, end;
101+
102+
SerializableSourceRange(const CharSourceRange r, const SourceManager &SM);
103+
SerializableSourceRange(SerializableSourceLocation start,
104+
SerializableSourceLocation end);
105+
SerializableSourceRange() = default;
106+
107+
static const SerializableSourceRange wholeFile;
108+
static Ranges RangesForWholeFile();
109+
110+
bool isEmpty() const { return start == end; }
111+
112+
bool overlaps(const SerializableSourceRange &x) const {
113+
return start < x.end && x.start < end;
114+
}
115+
bool operator==(const SerializableSourceRange &x) const {
116+
return start == x.start && end == x.end;
117+
}
118+
bool isImproperSubsetOf(const SerializableSourceRange &) const;
119+
bool properlyPreceeds(const SerializableSourceRange &) const;
120+
static bool isProperlySorted(ArrayRef<SerializableSourceRange>);
121+
122+
bool
123+
isImproperSubsetOfAny(ArrayRef<SerializableSourceRange> supersetRanges) const;
124+
bool isImproperSubsetOfAnySlowlyAndSimply(
125+
ArrayRef<SerializableSourceRange> supersetRanges) const;
126+
127+
/// Optimized for fewer ranges in the subset
128+
/// Return first outlier found in subset not in superset
129+
static Optional<SerializableSourceRange>
130+
findOutlierIfAny(ArrayRef<SerializableSourceRange> subset,
131+
ArrayRef<SerializableSourceRange> superset);
132+
133+
static Ranges findAllOutliers(ArrayRef<SerializableSourceRange> subset,
134+
ArrayRef<SerializableSourceRange> superset);
135+
136+
std::string printString() const;
137+
void print(raw_ostream &out) const;
138+
void dump() const;
139+
};
140+
141+
} // namespace incremental_ranges
142+
} // namespace swift
143+
144+
145+
template <>
146+
struct llvm::yaml::MappingTraits<
147+
swift::incremental_ranges::SerializableSourceRange> {
148+
static const bool flow = true;
149+
static void mapping(llvm::yaml::IO &io,
150+
swift::incremental_ranges::SerializableSourceRange &sr) {
151+
io.mapRequired("start", sr.start), io.mapRequired("end", sr.end);
152+
}
153+
};
154+
155+
//==============================================================================
156+
// MARK: SwiftRangesFileContents
157+
//==============================================================================
158+
159+
namespace swift {
160+
namespace incremental_ranges {
161+
162+
struct SwiftRangesFileContents {
163+
RangesByFilename unparsedRangesByNonPrimary;
164+
Ranges noninlinableFunctionBodies;
165+
166+
SwiftRangesFileContents() : SwiftRangesFileContents({}, {}) {}
167+
168+
SwiftRangesFileContents(RangesByFilename &&unparsedRangesByNonPrimary,
169+
Ranges &&noninlinableFunctionBodies)
170+
: unparsedRangesByNonPrimary(std::move(unparsedRangesByNonPrimary)),
171+
noninlinableFunctionBodies(std::move(noninlinableFunctionBodies)) {}
172+
173+
static Optional<SwiftRangesFileContents>
174+
load(const StringRef primaryPath, const llvm::MemoryBuffer &swiftRangesBuffer,
175+
const bool showIncrementalBuildDecisions, DiagnosticEngine &diags);
176+
177+
void dump(StringRef primary) const;
178+
179+
static constexpr const char *header = "### Swift source ranges file v0 ###\n";
180+
};
181+
} // namespace incremental_ranges
182+
} // namespace swift
183+
184+
template <>
185+
struct llvm::yaml::MappingTraits<
186+
swift::incremental_ranges::SwiftRangesFileContents> {
187+
static void
188+
mapping(llvm::yaml::IO &io,
189+
swift::incremental_ranges::SwiftRangesFileContents &srfc) {
190+
io.mapRequired("unparsedRangesByNonPrimary",
191+
srfc.unparsedRangesByNonPrimary);
192+
io.mapRequired("noninlinableFunctionBodies",
193+
srfc.noninlinableFunctionBodies);
194+
}
195+
};
196+
197+
LLVM_YAML_IS_SEQUENCE_VECTOR(swift::incremental_ranges::SerializableSourceRange)
198+
LLVM_YAML_IS_STRING_MAP(swift::incremental_ranges::Ranges)
199+
LLVM_YAML_IS_STRING_MAP(swift::incremental_ranges::RangesByFilename)
200+
201+
//==============================================================================
202+
// MARK: SwiftRangesEmitter
203+
//==============================================================================
204+
namespace swift {
205+
namespace incremental_ranges {
206+
207+
class SwiftRangesEmitter {
208+
const StringRef outputPath;
209+
SourceFile *const primaryFile;
210+
const PersistentParserState &persistentState;
211+
const SourceManager &sourceMgr;
212+
DiagnosticEngine &diags;
213+
214+
public:
215+
SwiftRangesEmitter(StringRef outputPath, SourceFile *primaryFile,
216+
const PersistentParserState &persistentState,
217+
const SourceManager &sourceMgr, DiagnosticEngine &diags)
218+
: outputPath(outputPath), primaryFile(primaryFile),
219+
persistentState(persistentState), sourceMgr(sourceMgr), diags(diags) {}
220+
221+
/// True for error
222+
bool emit() const;
223+
224+
public:
225+
void emitRanges(llvm::raw_ostream &out) const;
226+
227+
private:
228+
RangesByFilename collectSerializedUnparsedRangesByNonPrimary() const;
229+
230+
Ranges collectSortedSerializedNoninlinableFunctionBodies() const;
231+
std::vector<CharSourceRange> collectNoninlinableFunctionBodies() const;
232+
233+
std::map<std::string, std::vector<CharSourceRange>>
234+
collectUnparsedRanges() const;
235+
std::vector<CharSourceRange>
236+
sortRanges(std::vector<CharSourceRange> ranges) const;
237+
238+
/// Assuming \p ranges is sorted, coalesce overlapping ranges in place and
239+
/// return end of the resultant vector.
240+
std::vector<CharSourceRange>
241+
coalesceSortedRanges(std::vector<CharSourceRange>) const;
242+
243+
std::vector<SerializableSourceRange>
244+
serializeRanges(std::vector<CharSourceRange> ranges) const;
245+
246+
bool isImmediatelyBeforeOrOverlapping(CharSourceRange prev,
247+
CharSourceRange next) const;
248+
};
249+
} // namespace incremental_ranges
250+
} // namespace swift
251+
252+
//==============================================================================
253+
// MARK: CompiledSourceEmitter
254+
//==============================================================================
255+
namespace swift {
256+
namespace incremental_ranges {
257+
258+
class CompiledSourceEmitter {
259+
const StringRef outputPath;
260+
const SourceFile *const primaryFile;
261+
const SourceManager &sourceMgr;
262+
DiagnosticEngine &diags;
263+
264+
public:
265+
CompiledSourceEmitter(StringRef outputPath, const SourceFile *primaryFile,
266+
const SourceManager &sourceMgr, DiagnosticEngine &diags)
267+
: outputPath(outputPath), primaryFile(primaryFile), sourceMgr(sourceMgr),
268+
diags(diags) {}
269+
270+
/// True for error
271+
bool emit();
272+
};
273+
274+
} // namespace incremental_ranges
275+
} // namespace swift
276+
277+
#endif // SWIFT_AST_INCREMENTALRANGES_H

Diff for: include/swift/Basic/FileTypes.def

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ TYPE("llvm-bc", LLVM_BC, "bc", "")
5959
TYPE("diagnostics", SerializedDiagnostics, "dia", "")
6060
TYPE("objc-header", ObjCHeader, "h", "")
6161
TYPE("swift-dependencies", SwiftDeps, "swiftdeps", "")
62+
TYPE("swift-ranges", SwiftRanges, "swiftranges", "")
63+
TYPE("compiled-source", CompiledSource, "compiledsource", "")
6264
TYPE("remap", Remapping, "remap", "")
6365
TYPE("imported-modules", ImportedModules, "importedmodules", "")
6466
TYPE("tbd", TBD, "tbd", "")

Diff for: include/swift/Basic/FileTypes.h

+9
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ static inline void forAllTypes(llvm::function_ref<void(file_types::ID)> fn) {
6363
fn(static_cast<ID>(i));
6464
}
6565

66+
static inline void
67+
forEachIncrementalOutputType(llvm::function_ref<void(file_types::ID)> fn) {
68+
static const std::vector<file_types::ID> incrementalOutputTypes = {
69+
file_types::TY_SwiftDeps, file_types::TY_SwiftRanges,
70+
file_types::TY_CompiledSource};
71+
for (auto type : incrementalOutputTypes)
72+
fn(type);
73+
}
74+
6675
} // end namespace file_types
6776
} // end namespace swift
6877

0 commit comments

Comments
 (0)