in Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraph.swift [809:924]
mutating func visit(record: BitcodeElement.Record) throws {
guard let kind = RecordID(rawValue: record.id) else {
throw ReadError.unknownRecord
}
var malformedError: ReadError {.init(forMalformed: kind)}
func stringIndex(field i: Int) throws -> Int {
let u = record.fields[i]
guard u < UInt64(internedStringTable.count) else {
throw malformedError
}
return Int(u)
}
func internedString(field i: Int) throws -> InternedString {
try InternedString(deserializedIndex: stringIndex(field: i))
}
func nonemptyInternedString(field i: Int) throws -> InternedString? {
let s = try internedString(field: i)
return s.isEmpty ? nil : s
}
func dependencyKey(kindCodeField: Int,
declAspectField: Int,
contextField: Int,
identifierField: Int
) throws -> DependencyKey {
let kindCode = record.fields[kindCodeField]
guard let declAspect = DependencyKey.DeclAspect(record.fields[declAspectField])
else {
throw malformedError
}
let context = try internedString(field: contextField)
let identifier = try internedString(field: identifierField)
let designator = try DependencyKey.Designator(
kindCode: kindCode, context: context, name: identifier,
internedStringTable: internedStringTable, fileSystem: fileSystem)
return DependencyKey(aspect: declAspect, designator: designator)
}
switch kind {
case .metadata:
// If we've already read metadata, this is an unexpected duplicate.
guard self.majorVersion == nil, self.minorVersion == nil, self.compilerVersionString == nil else {
throw ReadError.unexpectedMetadataRecord
}
guard record.fields.count == 3,
case .blob(let compilerVersionBlob) = record.payload
else { throw malformedError }
self.majorVersion = record.fields[0]
self.minorVersion = record.fields[1]
let stringCount = record.fields[2]
internedStringTable.reserveCapacity(Int(stringCount))
self.compilerVersionString = String(decoding: compilerVersionBlob, as: UTF8.self)
case .moduleDepGraphNode:
guard record.fields.count == 6
else {
throw malformedError
}
let key = try dependencyKey(kindCodeField: 0,
declAspectField: 1,
contextField: 2,
identifierField: 3)
let depSourceFileOrNone = try nonemptyInternedString(field: 4)
let defLoc: DefinitionLocation = try depSourceFileOrNone.map {
internedFile -> DefinitionLocation in
let pathString = internedFile.lookup(in: internedStringTable)
let pathHandle = try VirtualPath.intern(path: pathString)
guard let source = DependencySource(ifAppropriateFor: pathHandle,
internedString: internedFile)
else {
throw ReadError.unknownDependencySourceExtension
}
return .known(source)
}
?? .unknown
let fingerprint = try nonemptyInternedString(field: 5)
self.finalize(node: Node(key: key,
fingerprint: fingerprint,
definitionLocation: defLoc))
case .dependsOnNode:
guard record.fields.count == 4
else {
throw malformedError
}
self.currentDefKey = try dependencyKey(
kindCodeField: 0,
declAspectField: 1,
contextField: 2,
identifierField: 3)
case .useIDNode:
guard let key = self.currentDefKey,
record.fields.count == 1 else {
throw malformedError
}
self.nodeUses.append( (key, Int(record.fields[0])) )
case .externalDepNode:
guard record.fields.count == 2
else {
throw malformedError
}
let path = try internedString(field: 0)
let fingerprint = try nonemptyInternedString(field: 1)
fingerprintedExternalDependencies.insert(
FingerprintedExternalDependency(
ExternalDependency(fileName: path, internedStringTable),
fingerprint))
case .identifierNode:
guard record.fields.count == 0,
case .blob(let identifierBlob) = record.payload
else {
throw malformedError
}
_ = (String(decoding: identifierBlob, as: UTF8.self)).intern(in: internedStringTable)
}
}