PVS-Studio
Requested trial license for PVS-Studio. Will try to check C++ code in Swift. Here’s how to generate compile_commands.json
needed to run PVS-studio:
swift/utils/build-script <other options> --extra-cmake-options='-DCMAKE_EXPORT_COMPILATION_COMMANDS=ON'
Run PVS-studio analyzer (current directory is swift
). Analyzes took 34 hours on my M1 MacBook Pro.
pvs-studio-analyzer analyze -f ../build/Ninja-ReleaseAssert/swift-macosx-arm64/compile_commands.json -l ~/.config/PVS-Studio/PVS-Studio.lic -o pvs.log
Convert PVS-studio’s log into human readable format:
plog-converter -a GA:1,2 -t tasklist -o project.tasks pvs.log
Experimented with implementing firstIndex(of:)
of UnsafeBufferPointer
with SIMD
. Have to benchmark it to see if it’s better/faster then code generated by library implementation.
extension UnsafeBufferPointer<Int8> {
func firstIndex(of element: Self.Element) -> Self.Index? {
//print("count=\(count)")
guard let pointer = baseAddress else { return nil }
let address = Int(bitPattern: pointer) // Any guarantee Int is same wide as pointer
var i = 0
let stride = MemoryLayout<Int8>.stride // or alignment? jump to Int(bitPattern:) in headers
let simd4Int8Stride = MemoryLayout<SIMD4<Int8>>.stride
assert(simd4Int8Stride == stride * SIMD4<Int8>.scalarCount) // Memory layout of SIMD4<Int8> should match one of 4 Int words
let simd4Int8Sample = SIMD4<Int8>(repeating: element)
let simd4Int8MaskAllFalse = SIMDMask<SIMD4<Int8>>(arrayLiteral: false, false, false, false) // Why SIMDMask needs SignedInteger?
// Bytes up to beginning of a SIMD4
while (address &+ i) % simd4Int8Stride != 0 && i < count {
guard self[i] != element else { return i }
i &+= 1
}
// Full SIMD4
// print("Full SIMD4")
while (i &+ simd4Int8Stride) < count {
let simd4: SIMD4<Int8> = UnsafePointer(
bitPattern: address &+ i
)!/*._unsafelyUnwrappedUnchecked*/.pointee
//let simd4 = SIMD4<Int8>(array[address+i..<address+i+4])
// Where is functionality to search for Scalar in SIMD?
// We have sum(), min(), max() but don't have firstIndex(of: Scalar)
guard (simd4 .== simd4Int8Sample) == simd4Int8MaskAllFalse else {
var offset = 0
while offset < simd4.scalarCount && simd4[offset] != element {
offset += 1
}
if offset < simd4.scalarCount {
return i + offset
} else {
fatalError()
}
}
i &+= simd4Int8Stride
}
// Rest bytes up to end
//print("Rest bytes up to end i=\(i)")
while i < count {
guard self[i] != element else { return i }
i &+= 1
}
return nil
}
}