5. 如何開始
# Install cmake and ninja
brew install cmake ninja
mkdir swift-source
cd swift-source
# Clone Swift project to local
git clone https://github.com/apple/swift.git
${ROOT} : swift-source here
12. 檔案架構
# Original source file
${ROOT}/swift/stdlib/public/core
# Converted swift files from gyb
${ROOT}/build/Ninja-RelWithDebInfoAssert/
swift-macosx-x86_64/stdlib/public/core/8
27. Attributes
• @inlinable :expose not interface but source code, work
when -O
• @_transparent: must do inline even when -Onone
• @_fixed_layout: Processed at SIL stage. It tells compiler
that access properties by offset is possible without
looking up metadata.
28. Attributes
• @usableFromInline : Temporarily change scope only
during inline stage. Include @inlinable
@_fixed_layout
public struct Bool {
@usableFromInline
internal var _value: Builtin.Int1
// …
29. What is Builtin ?
Builtin.Int1
Builtin.trunc_Int8_Int1(zero._value)
Builtin.s_to_u_checked_trunc_Int2048_Int8(x)
30. Integer Again
public struct Int
: FixedWidthInteger, SignedInteger,
_ExpressibleByBuiltinIntegerLiteral {
public init(_builtinIntegerLiteral x:
_MaxBuiltinIntegerType) {
_value =
Builtin.s_to_s_checked_trunc_Int2048_Int64(x).0
}
31. +
public static func +(lhs: Int, rhs: Int) -> Int {
var lhs = lhs
lhs += rhs
return lhs
}
33. You may surprise…
• Int is a struct in standard library
• + is a global function declared in standard library
• What an inefficient way !! Do we really implement basic
arithmetic operations by cross-module function calls?
34.
35. ObjC & Swift Compilation
Clang
Frontend
ObjC
LLVM
LLVM IR Machine Code
Swift
Frontend
Swift
IRGen
SIL Machine Code
LLVM
LLVM IR
38. llvm::Intrinsic::ID
swift::getLLVMIntrinsicIDForBuiltinWithOverflow(BuiltinValue
Kind ID) {
switch (ID) {
default: break;
case BuiltinValueKind::SAddOver:
return llvm::Intrinsic::sadd_with_overflow;
case BuiltinValueKind::UAddOver:
return llvm::Intrinsic::uadd_with_overflow;
case BuiltinValueKind::SSubOver:
return llvm::Intrinsic::ssub_with_overflow;
case BuiltinValueKind::USubOver:
return llvm::Intrinsic::usub_with_overflow;
case BuiltinValueKind::SMulOver:
return llvm::Intrinsic::smul_with_overflow;
case BuiltinValueKind::UMulOver:
return llvm::Intrinsic::umul_with_overflow;
}
llvm_unreachable("Cannot convert the overflow builtin to
llvm intrinsic.");
}
${ROOT}/swift/lib/AST/Builtin.cpp
39. Builtin is a portal
LLVM IR Builtin
Builtin.type
Builtin.method
Standard
Library
TYPE
METHOD
SIL stage
40. How To Use Builtin.
// builtin_add.swift
import Swift
let (result, overflow) =
Builtin.sadd_with_overflow_Int64(1._value, 2._value,
true._getBuiltinLogicValue())
print(Int(result))
$swiftc -parse-stdlib builtin_add.swift && ./builtin_add
41. @usableFromInline
// builtin_add.swift
import Swift
let (result, overflow) =
Builtin.sadd_with_overflow_Int64(1._value, 2._value,
true._value)
print(Int(result))
error: '_value' is inaccessible due to 'internal' protection level
48. for-in EnumeratedSequence
extension EnumeratedSequence {
public struct Iterator {
internal var _base: Base.Iterator
internal var _count: Int
internal init(_base: Base.Iterator) {
self._base = _base
self._count = 0
}
}
}
49. for-in EnumeratedSequence
extension EnumeratedSequence.Iterator: IteratorProtocol, Sequence
{
public typealias Element = (offset: Int, element: Base.Element)
public mutating func next() -> Element? {
guard let b = _base.next() else { return nil }
let result = (offset: _count, element: b)
_count += 1
return result
}
}
50. Map
public func map<T>(
_ transform: (Element) throws -> T
) rethrows -> [T] {
let initialCapacity = underestimatedCount
var result = ContiguousArray<T>()
result.reserveCapacity(initialCapacity)
var iterator = self.makeIterator()
// lower half of map func
51. Map
// upper half of map func
for _ in 0..<initialCapacity {
result.append(try transform(iterator.next()!))
}
while let element = iterator.next() {
result.append(try transform(element))
}
return Array(result)
}
52. Reduce
public func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult:
(_ partialResult: Result, Element) throws -> Result
) rethrows -> Result {
var accumulator = initialResult
for element in self {
accumulator = try nextPartialResult(accumulator,
element)
}
return accumulator
}
53. Reduce Into
public func reduce<Result>(
into initialResult: Result,
_ updateAccumulatingResult:
(_ partialResult: inout Result, Element) throws ->
()
) rethrows -> Result {
var accumulator = initialResult
for element in self {
try updateAccumulatingResult(&accumulator, element)
}
return accumulator
}
}
54. flatMap
public func flatMap<SegmentOfResult : Sequence>(
_ transform: (Element) throws -> SegmentOfResult
) rethrows -> [SegmentOfResult.Element] {
var result: [SegmentOfResult.Element] = []
for element in self {
result.append(contentsOf: try
transform(element))
}
return result
}
56. public func _compactMap<ElementOfResult>(
_ transform: (Element) throws ->
ElementOfResult?
) rethrows -> [ElementOfResult] {
var result: [ElementOfResult] = []
for element in self {
if let newElement = try transform(element) {
result.append(newElement)
}
}
return result
}
84. Array Is Not Thread Safe
import Dispatch
var array = [Int]()
DispatchQueue.concurrentPerform(iterations: 50)
{ index in
let last = array.last ?? 0
array.append(last + 1)
}
print("array count: (array.count)")
85. var array = [1, 2, 3, 4, 5]
let arrayAccessQueue = DispatchQueue(label: "array",
qos: .utility, attributes: .concurrent)
// read
var readValue: Int = 0
arrayAccessQueue.sync {
readValue = array[0]
}
// write
arrayAccessQueue.async(flags: .barrier) {
array.append(6)
}
// thread_safe_access_array.swift
97. Test Standard Library Only
./llvm/utils/lit/lit.py -sv ${BUILD_ROOT}/swift-
macosx-x86_64/test-macosx-x86_64/stdlib
A full-test run is suggested in the first place
./llvm/utils/lit/lit.py -sv ${BUILD_ROOT}/
swift-macosx-x86_64/validation-test-macosx-
x86_64/stdlib
101. ${BUILD_ROOT} ninja swift-stdlib
Thanks to ninja, lets build standard library only
sh ${BUILD_RTTO}/validation-test-macosx-x86_64/
stdlib/Output/SequenceType.swift.gyb.script
And do test!!