Skip to content

Commit 60bdd23

Browse files
authored
Merge pull request #1201 from compnerd/bitcode
SwiftDriver: migrate LLVM bitcode support from tools-support-core
2 parents ee1dd77 + 0c7effc commit 60bdd23

11 files changed

+1437
-10
lines changed

Sources/SwiftDriver/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ add_library(SwiftDriver
3434
Execution/ParsableOutput.swift
3535
Execution/ProcessProtocol.swift
3636

37+
"IncrementalCompilation/Bitcode/Bitcode.swift"
38+
"IncrementalCompilation/Bitcode/BitcodeElement.swift"
39+
"IncrementalCompilation/Bitcode/Bits.swift"
40+
"IncrementalCompilation/Bitcode/Bitstream.swift"
41+
"IncrementalCompilation/Bitcode/BitstreamReader.swift"
42+
"IncrementalCompilation/Bitcode/BitstreamVisitor.swift"
43+
"IncrementalCompilation/Bitcode/BitstreamWriter.swift"
44+
"IncrementalCompilation/Bitcode/BlockInfo.swift"
45+
3746
"IncrementalCompilation/BuildRecord.swift"
3847
"IncrementalCompilation/BuildRecordInfo.swift"
3948
"IncrementalCompilation/DependencyGraphDotFileWriter.swift"
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//===--------------- BitCode.swift - LLVM BitCode Helpers ----------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import struct TSCBasic.ByteString
14+
15+
public struct Bitcode {
16+
public let signature: Bitcode.Signature
17+
public let elements: [BitcodeElement]
18+
public let blockInfo: [UInt64:BlockInfo]
19+
}
20+
21+
extension Bitcode {
22+
public struct Signature: Equatable {
23+
private var value: UInt32
24+
25+
public init(value: UInt32) {
26+
self.value = value
27+
}
28+
29+
public init(string: String) {
30+
precondition(string.utf8.count == 4)
31+
var result: UInt32 = 0
32+
for byte in string.utf8.reversed() {
33+
result <<= 8
34+
result |= UInt32(byte)
35+
}
36+
self.value = result
37+
}
38+
}
39+
}
40+
41+
extension Bitcode {
42+
/// Traverse a bitstream using the specified `visitor`, which will receive
43+
/// callbacks when blocks and records are encountered.
44+
public static func read<Visitor: BitstreamVisitor>(bytes: ByteString, using visitor: inout Visitor) throws {
45+
precondition(bytes.count > 4)
46+
var reader = BitstreamReader(buffer: bytes)
47+
try visitor.validate(signature: reader.readSignature())
48+
try reader.readBlock(id: BitstreamReader.fakeTopLevelBlockID,
49+
abbrevWidth: 2,
50+
abbrevInfo: [],
51+
visitor: &visitor)
52+
}
53+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===--------------- BitcodeElement.swift - LLVM Bitcode Elements --------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
public enum BitcodeElement {
14+
public struct Block {
15+
public var id: UInt64
16+
public var elements: [BitcodeElement]
17+
}
18+
19+
/// A record element.
20+
///
21+
/// - Warning: A `Record` element's fields and payload only live as long as
22+
/// the `visit` function that provides them is called. To persist
23+
/// a record, always make a copy of it.
24+
public struct Record {
25+
public enum Payload {
26+
case none
27+
case array([UInt64])
28+
case char6String(String)
29+
case blob(ArraySlice<UInt8>)
30+
}
31+
32+
public var id: UInt64
33+
public var fields: UnsafeBufferPointer<UInt64>
34+
public var payload: Payload
35+
}
36+
37+
case block(Block)
38+
case record(Record)
39+
}
40+
41+
extension BitcodeElement.Record.Payload: CustomStringConvertible {
42+
public var description: String {
43+
switch self {
44+
case .none:
45+
return "none"
46+
case .array(let vals):
47+
return "array(\(vals))"
48+
case .char6String(let s):
49+
return "char6String(\(s))"
50+
case .blob(let s):
51+
return "blob(\(s.count) bytes)"
52+
}
53+
}
54+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//===--------------- Bits.swift - Bitstream helpers ----------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import struct TSCBasic.ByteString
14+
15+
struct Bits: RandomAccessCollection {
16+
var buffer: ByteString
17+
18+
var startIndex: Int { return 0 }
19+
var endIndex: Int { return buffer.count * 8 }
20+
21+
subscript(index: Int) -> UInt8 {
22+
let byte = buffer.contents[index / 8]
23+
return (byte >> UInt8(index % 8)) & 1
24+
}
25+
26+
func readBits(atOffset offset: Int, count: Int) -> UInt64 {
27+
precondition(count >= 0 && count <= 64)
28+
precondition(offset >= 0)
29+
precondition(offset &+ count >= offset)
30+
precondition(offset &+ count <= self.endIndex)
31+
32+
return buffer.contents.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
33+
let upperBound = offset &+ count
34+
let topByteIndex = upperBound >> 3
35+
var result: UInt64 = 0
36+
if upperBound & 7 != 0 {
37+
let mask: UInt8 = (1 << UInt8(upperBound & 7)) &- 1
38+
result = UInt64(bytes[topByteIndex] & mask)
39+
}
40+
for i in ((offset >> 3)..<(upperBound >> 3)).reversed() {
41+
result <<= 8
42+
result |= UInt64(bytes[i])
43+
}
44+
if offset & 7 != 0 {
45+
result >>= UInt64(offset & 7)
46+
}
47+
return result
48+
}
49+
}
50+
}
51+
52+
extension Bits {
53+
struct Cursor {
54+
enum Error: Swift.Error { case bufferOverflow }
55+
56+
let buffer: Bits
57+
private var offset: Int = 0
58+
59+
init(buffer: Bits) {
60+
self.buffer = buffer
61+
}
62+
63+
init(buffer: ByteString) {
64+
self.init(buffer: Bits(buffer: buffer))
65+
}
66+
67+
var isAtStart: Bool {
68+
return offset == buffer.startIndex
69+
}
70+
71+
var isAtEnd: Bool {
72+
return offset == buffer.count
73+
}
74+
75+
func peek(_ count: Int) throws -> UInt64 {
76+
if buffer.count - offset < count { throw Error.bufferOverflow }
77+
return buffer.readBits(atOffset: offset, count: count)
78+
}
79+
80+
mutating func read(_ count: Int) throws -> UInt64 {
81+
defer { offset += count }
82+
return try peek(count)
83+
}
84+
85+
mutating func read(bytes count: Int) throws -> ArraySlice<UInt8> {
86+
precondition(count >= 0)
87+
precondition(offset & 0b111 == 0)
88+
let newOffset = offset &+ (count << 3)
89+
precondition(newOffset >= offset)
90+
if newOffset > buffer.count { throw Error.bufferOverflow }
91+
defer { offset = newOffset }
92+
return buffer.buffer.contents.dropFirst(offset >> 3).prefix((newOffset - offset) >> 3)
93+
}
94+
95+
mutating func skip(bytes count: Int) throws {
96+
precondition(count >= 0)
97+
precondition(offset & 0b111 == 0)
98+
let newOffset = offset &+ (count << 3)
99+
precondition(newOffset >= offset)
100+
if newOffset > buffer.count { throw Error.bufferOverflow }
101+
offset = newOffset
102+
}
103+
104+
mutating func advance(toBitAlignment align: Int) throws {
105+
precondition(align > 0)
106+
precondition(offset &+ (align&-1) >= offset)
107+
precondition(align & (align &- 1) == 0)
108+
if offset % align == 0 { return }
109+
offset = (offset &+ align) & ~(align &- 1)
110+
if offset > buffer.count { throw Error.bufferOverflow }
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)