Skip to content

Commit c10fb27

Browse files
authored
Merge pull request #299 from owenv/update-deps-reading
Update SourceFileDependencyGraph deserialzation
2 parents 0197dae + 650b302 commit c10fb27

File tree

7 files changed

+151
-556
lines changed

7 files changed

+151
-556
lines changed

Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/SwiftDriver/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ add_library(SwiftDriver
7777
Toolchains/Toolchain.swift
7878
Toolchains/WebAssemblyToolchain.swift
7979

80-
Utilities/Bits.swift
81-
Utilities/Bitstream.swift
8280
Utilities/DOTJobGraphSerializer.swift
8381
Utilities/DateAdditions.swift
8482
Utilities/Diagnostics.swift

Sources/SwiftDriver/Incremental Compilation/SourceFileDependencyGraph.swift

Lines changed: 121 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
import Foundation
13+
import TSCUtility
1314

1415
@_spi(Testing) public struct SourceFileDependencyGraph {
1516
public static let sourceFileProvidesInterfaceSequenceNumber: Int = 0
@@ -91,8 +92,6 @@ extension SourceFileDependencyGraph {
9192
}
9293

9394
extension SourceFileDependencyGraph {
94-
private static let recordBlockId = 8
95-
9695
private enum RecordKind: UInt64 {
9796
case metadata = 1
9897
case sourceFileDepGraphNode
@@ -116,8 +115,9 @@ extension SourceFileDependencyGraph {
116115
case bogusNameOrContext
117116
case unknownKind
118117
}
119-
120-
public static func read(from swiftDeps: ModuleDependencyGraph.SwiftDeps
118+
119+
// FIXME: This should accept a FileSystem parameter.
120+
static func read(from swiftDeps: ModuleDependencyGraph.SwiftDeps
121121
) throws -> Self {
122122
guard let path = swiftDeps.file.absolutePath
123123
else {
@@ -132,93 +132,133 @@ extension SourceFileDependencyGraph {
132132
compilerVersionString = ""
133133
allNodes = nodesForTesting
134134
}
135-
136-
public init(pathString: String) throws {
135+
136+
// FIXME: This should accept a FileSystem parameter.
137+
@_spi(Testing) public init(pathString: String) throws {
137138
let data = try Data(contentsOf: URL(fileURLWithPath: pathString))
138139
try self.init(data: data)
139140
}
140-
141-
public init(data: Data) throws {
142-
// FIXME: visit blocks and records incrementally instead of reading the
143-
// entire file up front.
144-
let bitcode = try Bitcode(data: data)
145-
guard bitcode.signature == .init(string: "DEPS") else { throw ReadError.badMagic }
146-
147-
guard bitcode.elements.count == 1,
148-
case .block(let recordBlock) = bitcode.elements.first,
149-
recordBlock.id == Self.recordBlockId else { throw ReadError.noRecordBlock }
150-
151-
guard case .record(let metadataRecord) = recordBlock.elements.first,
152-
RecordKind(rawValue: metadataRecord.id) == .metadata,
153-
metadataRecord.fields.count == 2,
154-
case .blob(let compilerVersionBlob) = metadataRecord.payload,
155-
let compilerVersionString = String(data: compilerVersionBlob, encoding: .utf8)
156-
else { throw ReadError.malformedMetadataRecord }
157-
158-
self.majorVersion = metadataRecord.fields[0]
159-
self.minorVersion = metadataRecord.fields[1]
160-
self.compilerVersionString = compilerVersionString
161-
162-
var nodes: [Node] = []
163-
var node: Node? = nil
164-
var identifiers: [String] = [""] // The empty string is hardcoded as identifiers[0]
165-
var sequenceNumber = 0
166-
for element in recordBlock.elements.dropFirst() {
167-
guard case .record(let record) = element else { throw ReadError.unexpectedSubblock }
168-
guard let kind = RecordKind(rawValue: record.id) else { throw ReadError.unknownRecord }
169-
switch kind {
170-
case .metadata:
171-
throw ReadError.unexpectedMetadataRecord
172-
case .sourceFileDepGraphNode:
173-
if let node = node {
174-
nodes.append(node)
141+
142+
@_spi(Testing) public init(data: Data,
143+
fromSwiftModule extractFromSwiftModule: Bool = false) throws {
144+
struct Visitor: BitstreamVisitor {
145+
let extractFromSwiftModule: Bool
146+
147+
init(extractFromSwiftModule: Bool) {
148+
self.extractFromSwiftModule = extractFromSwiftModule
149+
}
150+
151+
var nodes: [Node] = []
152+
var majorVersion: UInt64?
153+
var minorVersion: UInt64?
154+
var compilerVersionString: String?
155+
156+
private var node: Node? = nil
157+
private var identifiers: [String] = [""] // The empty string is hardcoded as identifiers[0]
158+
private var sequenceNumber = 0
159+
160+
func validate(signature: Bitcode.Signature) throws {
161+
if extractFromSwiftModule {
162+
guard signature == .init(value: 0x0EA89CE2) else { throw ReadError.badMagic }
163+
} else {
164+
guard signature == .init(string: "DEPS") else { throw ReadError.badMagic }
175165
}
176-
let kindCode = record.fields[0]
177-
guard record.fields.count == 5,
178-
let declAspect = DependencyKey.DeclAspect(record.fields[1]),
179-
record.fields[2] < identifiers.count,
180-
record.fields[3] < identifiers.count else {
181-
throw ReadError.malformedSourceFileDepGraphNodeRecord
166+
}
167+
168+
mutating func shouldEnterBlock(id: UInt64) throws -> Bool {
169+
if extractFromSwiftModule {
170+
// Enter the top-level module block, and the incremental info
171+
// subblock, ignoring the rest of the file.
172+
return id == /*Module block*/ 8 || id == /*Incremental record block*/ 196
173+
} else {
174+
guard id == /*Incremental record block*/ 8 else {
175+
throw ReadError.unexpectedSubblock
176+
}
177+
return true
182178
}
183-
let context = identifiers[Int(record.fields[2])]
184-
let identifier = identifiers[Int(record.fields[3])]
185-
let isProvides = record.fields[4] != 0
186-
let designator = try DependencyKey.Designator(
187-
kindCode: kindCode, context: context, name: identifier)
188-
let key = DependencyKey(aspect: declAspect, designator: designator)
189-
node = Node(key: key,
190-
fingerprint: nil,
191-
sequenceNumber: sequenceNumber,
192-
defsIDependUpon: [],
193-
isProvides: isProvides)
194-
sequenceNumber += 1
195-
case .fingerprintNode:
196-
guard node != nil,
197-
record.fields.count == 0,
198-
case .blob(let fingerprintBlob) = record.payload,
199-
let fingerprint = String(data: fingerprintBlob, encoding: .utf8) else {
200-
throw ReadError.malformedFingerprintRecord
179+
}
180+
181+
mutating func didExitBlock() throws {
182+
// Finalize the current node if needed.
183+
if let node = node {
184+
nodes.append(node)
185+
self.node = nil
201186
}
202-
node?.fingerprint = fingerprint
203-
case .dependsOnDefinitionNode:
204-
guard node != nil,
205-
record.fields.count == 1 else { throw ReadError.malformedDependsOnDefinitionRecord }
206-
node?.defsIDependUpon.append(Int(record.fields[0]))
207-
case .identifierNode:
208-
guard record.fields.count == 0,
209-
case .blob(let identifierBlob) = record.payload,
210-
let identifier = String(data: identifierBlob, encoding: .utf8) else {
211-
throw ReadError.malformedIdentifierRecord
187+
}
188+
189+
mutating func visit(record: BitcodeElement.Record) throws {
190+
guard let kind = RecordKind(rawValue: record.id) else { throw ReadError.unknownRecord }
191+
switch kind {
192+
case .metadata:
193+
// If we've already read metadata, this is an unexpected duplicate.
194+
guard majorVersion == nil, minorVersion == nil, compilerVersionString == nil else {
195+
throw ReadError.unexpectedMetadataRecord
196+
}
197+
guard record.fields.count == 2,
198+
case .blob(let compilerVersionBlob) = record.payload,
199+
let compilerVersionString = String(data: compilerVersionBlob, encoding: .utf8)
200+
else { throw ReadError.malformedMetadataRecord }
201+
202+
self.majorVersion = record.fields[0]
203+
self.minorVersion = record.fields[1]
204+
self.compilerVersionString = compilerVersionString
205+
case .sourceFileDepGraphNode:
206+
if let node = node {
207+
nodes.append(node)
208+
}
209+
let kindCode = record.fields[0]
210+
guard record.fields.count == 5,
211+
let declAspect = DependencyKey.DeclAspect(record.fields[1]),
212+
record.fields[2] < identifiers.count,
213+
record.fields[3] < identifiers.count else {
214+
throw ReadError.malformedSourceFileDepGraphNodeRecord
215+
}
216+
let context = identifiers[Int(record.fields[2])]
217+
let identifier = identifiers[Int(record.fields[3])]
218+
let isProvides = record.fields[4] != 0
219+
let designator = try DependencyKey.Designator(
220+
kindCode: kindCode, context: context, name: identifier)
221+
let key = DependencyKey(aspect: declAspect, designator: designator)
222+
node = Node(key: key,
223+
fingerprint: nil,
224+
sequenceNumber: sequenceNumber,
225+
defsIDependUpon: [],
226+
isProvides: isProvides)
227+
sequenceNumber += 1
228+
case .fingerprintNode:
229+
guard node != nil,
230+
record.fields.count == 0,
231+
case .blob(let fingerprintBlob) = record.payload,
232+
let fingerprint = String(data: fingerprintBlob, encoding: .utf8) else {
233+
throw ReadError.malformedFingerprintRecord
234+
}
235+
node?.fingerprint = fingerprint
236+
case .dependsOnDefinitionNode:
237+
guard node != nil,
238+
record.fields.count == 1 else { throw ReadError.malformedDependsOnDefinitionRecord }
239+
node?.defsIDependUpon.append(Int(record.fields[0]))
240+
case .identifierNode:
241+
guard record.fields.count == 0,
242+
case .blob(let identifierBlob) = record.payload,
243+
let identifier = String(data: identifierBlob, encoding: .utf8) else {
244+
throw ReadError.malformedIdentifierRecord
245+
}
246+
identifiers.append(identifier)
212247
}
213-
identifiers.append(identifier)
214248
}
215249
}
216-
217-
if let node = node {
218-
nodes.append(node)
250+
251+
var visitor = Visitor(extractFromSwiftModule: extractFromSwiftModule)
252+
try Bitcode.read(stream: data, using: &visitor)
253+
guard let major = visitor.majorVersion,
254+
let minor = visitor.minorVersion,
255+
let versionString = visitor.compilerVersionString else {
256+
throw ReadError.malformedMetadataRecord
219257
}
220-
221-
self.allNodes = nodes
258+
self.majorVersion = major
259+
self.minorVersion = minor
260+
self.compilerVersionString = versionString
261+
self.allNodes = visitor.nodes
222262
}
223263
}
224264

Sources/SwiftDriver/Utilities/Bits.swift

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)