Skip to content

Commit d6c85e5

Browse files
committed
Delete Entrypoints to Bitcode Deserialization
These conveniences allowed a custom collector to escape the data in a bitstream container. But we don't really need them - the user can write their own visitor if need be. And these escaped elements are forcing copies in the visitor interface.
1 parent ec61a6b commit d6c85e5

File tree

3 files changed

+22
-82
lines changed

3 files changed

+22
-82
lines changed

Sources/TSCUtility/BitstreamReader.swift

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,8 @@ import Foundation
1212
import TSCBasic
1313

1414
extension Bitcode {
15-
/// Parse a bitstream from data.
16-
@available(*, deprecated, message: "Use Bitcode.init(bytes:) instead")
17-
public init(data: Data) throws {
18-
precondition(data.count > 4)
19-
try self.init(bytes: ByteString(data))
20-
}
21-
22-
public init(bytes: ByteString) throws {
23-
precondition(bytes.count > 4)
24-
var reader = BitstreamReader(buffer: bytes)
25-
let signature = try reader.readSignature()
26-
var visitor = CollectingVisitor()
27-
try reader.readBlock(id: BitstreamReader.fakeTopLevelBlockID,
28-
abbrevWidth: 2,
29-
abbrevInfo: [],
30-
visitor: &visitor)
31-
self.init(signature: signature,
32-
elements: visitor.finalizeTopLevelElements(),
33-
blockInfo: reader.blockInfo)
34-
}
35-
3615
/// Traverse a bitstream using the specified `visitor`, which will receive
3716
/// callbacks when blocks and records are encountered.
38-
@available(*, deprecated, message: "Use Bitcode.read(bytes:using:) instead")
39-
public static func read<Visitor: BitstreamVisitor>(stream data: Data, using visitor: inout Visitor) throws {
40-
precondition(data.count > 4)
41-
try Self.read(bytes: ByteString(data), using: &visitor)
42-
}
43-
4417
public static func read<Visitor: BitstreamVisitor>(bytes: ByteString, using visitor: inout Visitor) throws {
4518
precondition(bytes.count > 4)
4619
var reader = BitstreamReader(buffer: bytes)
@@ -204,15 +177,21 @@ private struct BitstreamReader {
204177
}
205178
}
206179

207-
mutating func readAbbreviatedRecord(_ abbrev: Bitstream.Abbreviation) throws -> BitcodeElement.Record {
180+
mutating func withAbbreviatedRecord(
181+
_ abbrev: Bitstream.Abbreviation,
182+
body: (BitcodeElement.Record) throws -> Void
183+
) throws {
208184
let code = try readSingleAbbreviatedRecordOperand(abbrev.operands.first!)
209185

210186
let lastOperand = abbrev.operands.last!
211187
let lastRegularOperandIndex: Int = abbrev.operands.endIndex - (lastOperand.isPayload ? 1 : 0)
212188

213-
var fields = [UInt64]()
214-
for op in abbrev.operands[1..<lastRegularOperandIndex] {
215-
fields.append(try readSingleAbbreviatedRecordOperand(op))
189+
// Safety: `lastRegularOperandIndex` is always at least 1.
190+
let fields = UnsafeMutableBufferPointer<UInt64>.allocate(capacity: lastRegularOperandIndex - 1)
191+
defer { fields.deallocate() }
192+
193+
for (idx, op) in abbrev.operands[1..<lastRegularOperandIndex].enumerated() {
194+
fields[idx] = try readSingleAbbreviatedRecordOperand(op)
216195
}
217196

218197
let payload: BitcodeElement.Record.Payload
@@ -234,14 +213,14 @@ private struct BitstreamReader {
234213
case .blob:
235214
let length = Int(try cursor.readVBR(6))
236215
try cursor.advance(toBitAlignment: 32)
237-
payload = .blob(try Data(cursor.read(bytes: length)))
216+
payload = .blob(try cursor.read(bytes: length))
238217
try cursor.advance(toBitAlignment: 32)
239218
default:
240219
fatalError()
241220
}
242221
}
243222

244-
return .init(id: code, fields: fields, payload: payload)
223+
return try body(.init(id: code, fields: UnsafeBufferPointer(fields), payload: payload))
245224
}
246225

247226
mutating func readBlockInfoBlock(abbrevWidth: Int) throws {
@@ -341,17 +320,20 @@ private struct BitstreamReader {
341320
case Bitstream.AbbreviationID.unabbreviatedRecord.rawValue:
342321
let code = try cursor.readVBR(6)
343322
let numOps = try cursor.readVBR(6)
344-
var operands = [UInt64]()
345-
for _ in 0..<numOps {
346-
operands.append(try cursor.readVBR(6))
323+
let operands = UnsafeMutableBufferPointer<UInt64>.allocate(capacity: Int(numOps))
324+
defer { operands.deallocate() }
325+
for i in 0..<Int(numOps) {
326+
operands[i] = try cursor.readVBR(6)
347327
}
348-
try visitor.visit(record: .init(id: code, fields: operands, payload: .none))
328+
try visitor.visit(record: .init(id: code, fields: UnsafeBufferPointer(operands), payload: .none))
349329

350330
case let abbrevID:
351331
guard Int(abbrevID) - 4 < abbrevInfo.count else {
352332
throw Error.noSuchAbbrev(blockID: id, abbrevID: Int(abbrevID))
353333
}
354-
try visitor.visit(record: try readAbbreviatedRecord(abbrevInfo[Int(abbrevID) - 4]))
334+
try withAbbreviatedRecord(abbrevInfo[Int(abbrevID) - 4]) { record in
335+
try visitor.visit(record: record)
336+
}
355337
}
356338
}
357339

Sources/TSCUtility/SerializedDiagnostics.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ public struct SerializedDiagnostics {
4343
/// Serialized diagnostics.
4444
public var diagnostics: [Diagnostic]
4545

46-
@available(*, deprecated, message: "Use SerializedDiagnostics.init(bytes:) instead")
47-
public init(data: Data) throws {
48-
var reader = Reader()
49-
try Bitcode.read(stream: data, using: &reader)
50-
guard let version = reader.versionNumber else { throw Error.noMetadataBlock }
51-
self.versionNumber = version
52-
self.diagnostics = reader.diagnostics
53-
}
54-
5546
public init(bytes: ByteString) throws {
5647
var reader = Reader()
5748
try Bitcode.read(bytes: bytes, using: &reader)

Tests/TSCUtilityTests/BitstreamTests.swift

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -151,39 +151,6 @@ final class BitstreamTests: XCTestCase {
151151
"skipping block: 9"])
152152
}
153153

154-
func testStandardInit() throws {
155-
let bitstreamPath = AbsolutePath(#file).parentDirectory
156-
.appending(components: "Inputs", "serialized.dia")
157-
let contents = try localFileSystem.readFileContents(bitstreamPath)
158-
let bitcode = try Bitcode(bytes: contents)
159-
XCTAssertEqual(bitcode.signature, .init(string: "DIAG"))
160-
XCTAssertEqual(bitcode.elements.count, 18)
161-
guard case .block(let metadataBlock) = bitcode.elements.first else {
162-
XCTFail()
163-
return
164-
}
165-
XCTAssertEqual(metadataBlock.id, 8)
166-
XCTAssertEqual(metadataBlock.elements.count, 1)
167-
guard case .record(let versionRecord) = metadataBlock.elements[0] else {
168-
XCTFail()
169-
return
170-
}
171-
XCTAssertEqual(versionRecord.id, 1)
172-
XCTAssertEqual(versionRecord.fields, [1])
173-
guard case .block(let lastBlock) = bitcode.elements.last else {
174-
XCTFail()
175-
return
176-
}
177-
XCTAssertEqual(lastBlock.id, 9)
178-
XCTAssertEqual(lastBlock.elements.count, 3)
179-
guard case .record(let lastRecord) = lastBlock.elements[2] else {
180-
XCTFail()
181-
return
182-
}
183-
XCTAssertEqual(lastRecord.id, 3)
184-
XCTAssertEqual(lastRecord.fields, [5, 34, 13, 0, 5, 34, 26, 0])
185-
}
186-
187154
func testBufferedWriter() {
188155
let writer = BitstreamWriter()
189156

@@ -312,13 +279,13 @@ final class BitstreamTests: XCTestCase {
312279
mutating func visit(record: BitcodeElement.Record) throws {
313280
switch record.id {
314281
case UInt64(RoundTripRecordID.version.rawValue):
315-
XCTAssertEqual(record.fields, [ 25 ]) // version
282+
XCTAssertEqual(Array(record.fields), [ 25 ]) // version
316283
guard case .none = record.payload else {
317284
XCTFail("Unexpected payload in metadata record!")
318285
return
319286
}
320287
case UInt64(RoundTripRecordID.blob.rawValue):
321-
XCTAssertEqual(record.fields, [
288+
XCTAssertEqual(Array(record.fields), [
322289
42,
323290
43,
324291
44,

0 commit comments

Comments
 (0)