Skip to content

SwiftCompilerSources: rework bridging #69039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,13 @@ How to build the swift compiler modules. Possible values are
compiler, provided in `SWIFT_NATIVE_SWIFT_TOOLS_PATH`
]=] OFF)

option(BRIDGING_MODE [=[
How swift-C++ bridging code is compiled:
INLINE: uses full swift C++ interop and briding functions are inlined
PURE: uses limited C++ interp an bridging functions are not inlined
DEFAULT: based on the build configuration
]=] DEFAULT)

# The following only works with the Ninja generator in CMake >= 3.0.
set(SWIFT_PARALLEL_LINK_JOBS "" CACHE STRING
"Define the maximum number of linker jobs for swift.")
Expand Down Expand Up @@ -390,6 +397,17 @@ set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY
${SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default}
CACHE STRING "MSVC Runtime Library for the standard library")


if(BRIDGING_MODE STREQUAL "DEFAULT" OR NOT BRIDGING_MODE)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
# In debug builds, to workaround a problem with LLDB's `po` command (rdar://115770255).
# On windows to workaround a build problem.
set(BRIDGING_MODE "PURE")
else()
set(BRIDGING_MODE "INLINE")
endif()
endif()

is_build_type_optimized("${SWIFT_STDLIB_BUILD_TYPE}" swift_optimized)
if(swift_optimized)
set(SWIFT_STDLIB_ASSERTIONS_default FALSE)
Expand Down
14 changes: 7 additions & 7 deletions SwiftCompilerSources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ function(add_swift_compiler_modules_library name)
"-Xfrontend" "-validate-tbd-against-ir=none"
"-Xfrontend" "-enable-experimental-cxx-interop"
"-Xcc" "-std=c++17"
"-Xcc" "-DCOMPILED_WITH_SWIFT"
"-Xcc" "-UIBOutlet" "-Xcc" "-UIBAction" "-Xcc" "-UIBInspectable")
if (NOT BOOTSTRAPPING_MODE STREQUAL "HOSTTOOLS")
list(APPEND swift_compile_options "-Xfrontend" "-disable-implicit-string-processing-module-import")
Expand All @@ -91,6 +92,10 @@ function(add_swift_compiler_modules_library name)
list(APPEND swift_compile_options "-Xcc" "-DNDEBUG")
endif()

if("${BRIDGING_MODE}" STREQUAL "PURE")
list(APPEND swift_compile_options "-Xcc" "-DPURE_BRIDGING_MODE")
endif()

if(NOT SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT)
list(APPEND swift_compile_options "-Xfrontend" "-disable-legacy-type-info")
endif()
Expand Down Expand Up @@ -237,16 +242,11 @@ else()
# defined in include/swift/module.modulemap
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/HeaderDependencies.cpp.tmp"
"
#include \"Basic/BridgedSwiftObject.h\"
#include \"Basic/BasicBridging.h\"
#include \"Basic/SourceLoc.h\"
#define COMPILED_WITH_SWIFT

#include \"Basic/BasicBridging.h\"
#include \"AST/ASTBridging.h\"
#include \"AST/DiagnosticEngine.h\"
#include \"AST/DiagnosticConsumer.h\"

#include \"SIL/SILBridging.h\"

#include \"SILOptimizer/OptimizerBridging.h\"

#include \"Parse/RegexParserBridging.h\"
Expand Down
40 changes: 24 additions & 16 deletions SwiftCompilerSources/Sources/AST/DiagnosticEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ import Basic
public typealias DiagID = BridgedDiagID

public protocol DiagnosticArgument {
func _withBridgedDiagnosticArgument(_ fn: (swift.DiagnosticArgument) -> Void)
func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void)
}
extension String: DiagnosticArgument {
public func _withBridgedDiagnosticArgument(_ fn: (swift.DiagnosticArgument) -> Void) {
_withStringRef { fn(swift.DiagnosticArgument($0)) }
public func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void) {
_withBridgedStringRef { fn(BridgedDiagnosticArgument($0)) }
}
}
extension Int: DiagnosticArgument {
public func _withBridgedDiagnosticArgument(_ fn: (swift.DiagnosticArgument) -> Void) {
fn(swift.DiagnosticArgument(Int32(self)))
public func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void) {
fn(BridgedDiagnosticArgument(self))
}
}

Expand All @@ -41,12 +41,11 @@ public struct DiagnosticFixIt {
self.text = text
}

func withBridgedDiagnosticFixIt(_ fn: (swift.DiagnosticInfo.FixIt) -> Void) {
text._withStringRef { bridgedTextRef in
let bridgedDiagnosticFixIt = swift.DiagnosticInfo.FixIt(
swift.CharSourceRange(start.bridged, UInt32(byteLength)),
bridgedTextRef,
ArrayRefOfDiagnosticArgument())
func withBridgedDiagnosticFixIt(_ fn: (BridgedDiagnosticFixIt) -> Void) {
text._withBridgedStringRef { bridgedTextRef in
let bridgedDiagnosticFixIt = BridgedDiagnosticFixIt(
start.bridged, UInt32(byteLength),
bridgedTextRef)
fn(bridgedDiagnosticFixIt)
}
}
Expand All @@ -71,10 +70,18 @@ public struct DiagnosticEngine {
highlight: CharSourceRange? = nil,
fixIts: [DiagnosticFixIt] = []) {

let bridgedSourceLoc: swift.SourceLoc = position.bridged
let bridgedHighlightRange: swift.CharSourceRange = highlight.bridged
var bridgedArgs: [swift.DiagnosticArgument] = []
var bridgedFixIts: [swift.DiagnosticInfo.FixIt] = []
let bridgedSourceLoc: BridgedSourceLoc = position.bridged
let highlightStart: BridgedSourceLoc
let highlightLength: UInt32
if let highlight = highlight {
highlightStart = highlight.start.bridged
highlightLength = highlight.byteLength
} else {
highlightStart = BridgedSourceLoc()
highlightLength = 0
}
var bridgedArgs: [BridgedDiagnosticArgument] = []
var bridgedFixIts: [BridgedDiagnosticFixIt] = []

// Build a higher-order function to wrap every 'withBridgedXXX { ... }'
// calls, so we don't escape anything from the closure. 'bridgedArgs' and
Expand All @@ -86,7 +93,8 @@ public struct DiagnosticEngine {
bridgedFixIts.withBridgedArrayRef { bridgedFixItsRef in
DiagnosticEngine_diagnose(bridged, bridgedSourceLoc,
id, bridgedArgsRef,
bridgedHighlightRange, bridgedFixItsRef)
highlightStart, highlightLength,
bridgedFixItsRef)
}
}
}
Expand Down
40 changes: 10 additions & 30 deletions SwiftCompilerSources/Sources/Basic/SourceLoc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,15 @@ public struct SourceLoc {
self.locationInFile = locationInFile
}

public init?(bridged: swift.SourceLoc) {
public init?(bridged: BridgedSourceLoc) {
guard bridged.isValid() else {
return nil
}
#if $NewCxxMethodSafetyHeuristics
self.locationInFile = bridged.getOpaquePointerValue().assumingMemoryBound(to: UInt8.self)
#else
self.locationInFile = bridged.__getOpaquePointerValueUnsafe().assumingMemoryBound(to: UInt8.self)
#endif
self.locationInFile = bridged.opaquePointer!
}

public var bridged: swift.SourceLoc {
.init(llvm.SMLoc.getFromPointer(locationInFile))
public var bridged: BridgedSourceLoc {
.init(opaquePointer: locationInFile)
}
}

Expand All @@ -46,40 +42,24 @@ extension SourceLoc {
}

extension Optional where Wrapped == SourceLoc {
public var bridged: swift.SourceLoc {
public var bridged: BridgedSourceLoc {
self?.bridged ?? .init()
}
}

public struct CharSourceRange {
private let start: SourceLoc
private let byteLength: UInt32
public let start: SourceLoc
public let byteLength: UInt32

public init(start: SourceLoc, byteLength: UInt32) {
self.start = start
self.byteLength = byteLength
}

public init?(bridged: swift.CharSourceRange) {
#if $NewCxxMethodSafetyHeuristics
guard let start = SourceLoc(bridged: bridged.getStart()) else {
public init?(bridgedStart: BridgedSourceLoc, byteLength: UInt32) {
guard let start = SourceLoc(bridged: bridgedStart) else {
return nil
}
#else
guard let start = SourceLoc(bridged: bridged.__getStartUnsafe()) else {
return nil
}
#endif
self.init(start: start, byteLength: bridged.getByteLength())
}

public var bridged: swift.CharSourceRange {
.init(start.bridged, byteLength)
}
}

extension Optional where Wrapped == CharSourceRange {
public var bridged: swift.CharSourceRange {
self?.bridged ?? .init(.init(), 0)
self.init(start: start, byteLength: byteLength)
}
}
64 changes: 25 additions & 39 deletions SwiftCompilerSources/Sources/Basic/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,49 +58,39 @@ public extension NoReflectionChildren {
//===----------------------------------------------------------------------===//

public struct StringRef : CustomStringConvertible, NoReflectionChildren {
let _bridged: llvm.StringRef
let _bridged: BridgedStringRef

public init(bridged: llvm.StringRef) { self._bridged = bridged }
public init(bridged: BridgedStringRef) { self._bridged = bridged }

public var string: String { _bridged.string }
public var string: String { String(_bridged) }
public var description: String { string }

public var count: Int {
#if $NewCxxMethodSafetyHeuristics
Int(_bridged.bytes_end() - _bridged.bytes_begin())
#else
Int(_bridged.__bytes_endUnsafe() - _bridged.__bytes_beginUnsafe())
#endif
Int(_bridged.size())
}

public subscript(index: Int) -> UInt8 {
#if $NewCxxMethodSafetyHeuristics
let buffer = UnsafeBufferPointer<UInt8>(start: _bridged.bytes_begin(),
count: count)
#else
let buffer = UnsafeBufferPointer<UInt8>(start: _bridged.__bytes_beginUnsafe(),
count: count)
#endif
let buffer = UnsafeBufferPointer<UInt8>(start: _bridged.uintData(), count: count)
return buffer[index]
}

public static func ==(lhs: StringRef, rhs: StringRef) -> Bool {
let lhsBuffer = UnsafeBufferPointer<UInt8>(start: lhs._bridged.uintData(), count: lhs.count)
let rhsBuffer = UnsafeBufferPointer<UInt8>(start: rhs._bridged.uintData(), count: rhs.count)
if lhsBuffer.count != rhsBuffer.count { return false }
return lhsBuffer.elementsEqual(rhsBuffer, by: ==)
}

public static func ==(lhs: StringRef, rhs: StaticString) -> Bool {
#if $NewCxxMethodSafetyHeuristics
let lhsBuffer = UnsafeBufferPointer<UInt8>(
start: lhs._bridged.bytes_begin(),
count: lhs.count)
#else
let lhsBuffer = UnsafeBufferPointer<UInt8>(
start: lhs._bridged.__bytes_beginUnsafe(),
count: lhs.count)
#endif
let lhsBuffer = UnsafeBufferPointer<UInt8>(start: lhs._bridged.uintData(), count: lhs.count)
return rhs.withUTF8Buffer { (rhsBuffer: UnsafeBufferPointer<UInt8>) in
if lhsBuffer.count != rhsBuffer.count { return false }
return lhsBuffer.elementsEqual(rhsBuffer, by: ==)
}
}

public static func !=(lhs: StringRef, rhs: StaticString) -> Bool { !(lhs == rhs) }
public static func !=(lhs: StringRef, rhs: StringRef) -> Bool { !(lhs == rhs) }

public static func ~=(pattern: StaticString, value: StringRef) -> Bool { value == pattern }
}
Expand All @@ -109,27 +99,23 @@ public struct StringRef : CustomStringConvertible, NoReflectionChildren {
// Bridging Utilities
//===----------------------------------------------------------------------===//

extension llvm.StringRef {
public var string: String {
String(_cxxString: self.str())
}
}

extension String {
/// Underscored to avoid name collision with Swift LLVM Bindings.
/// To be replaced with a bindings call once bindings are a dependency.
public func _withStringRef<T>(_ c: (llvm.StringRef) -> T) -> T {
public func _withBridgedStringRef<T>(_ c: (BridgedStringRef) -> T) -> T {
var str = self
return str.withUTF8 { buffer in
return c(llvm.StringRef(buffer.baseAddress, buffer.count))
return c(BridgedStringRef(buffer.baseAddress, buffer.count))
}
}

/// Underscored to avoid name collision with the std overlay.
/// To be replaced with an overlay call once the CI uses SDKs built with Swift 5.8.
public init(_cxxString s: std.string) {
self.init(cString: s.__c_strUnsafe())
withExtendedLifetime(s) {}
public init(_ s: BridgedStringRef) {
let buffer = UnsafeBufferPointer<UInt8>(start: s.uintData(), count: Int(s.size()))
self.init(decoding: buffer, as: UTF8.self)
}

public init(taking s: BridgedOwnedString) {
let buffer = UnsafeBufferPointer<UInt8>(start: s.uintData(), count: s.size())
self.init(decoding: buffer, as: UTF8.self)
s.destroy()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct AliasAnalysis {
static func register() {
BridgedAliasAnalysis.registerAnalysis(
// getMemEffectsFn
{ (bridgedCtxt: BridgedPassContext, bridgedVal: BridgedValue, bridgedInst: BridgedInstruction, complexityBudget: Int) -> swift.MemoryBehavior in
{ (bridgedCtxt: BridgedPassContext, bridgedVal: BridgedValue, bridgedInst: BridgedInstruction, complexityBudget: Int) -> BridgedMemoryBehavior in
let context = FunctionPassContext(_bridged: bridgedCtxt)
let inst = bridgedInst.instruction
let val = bridgedVal.value
Expand Down Expand Up @@ -255,7 +255,7 @@ private struct IsIndirectResultWalker: AddressDefUseWalker {
}

private extension SideEffects.Memory {
var bridged: swift.MemoryBehavior {
var bridged: BridgedMemoryBehavior {
switch (read, write) {
case (false, false): return .None
case (true, false): return .MayRead
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public struct CalleeAnalysis {
return inst.instruction.isDeinitBarrier(bca.analysis)
},
// getMemBehaviorFn
{ (bridgedApply: BridgedInstruction, observeRetains: Bool, bca: BridgedCalleeAnalysis) -> swift.MemoryBehavior in
{ (bridgedApply: BridgedInstruction, observeRetains: Bool, bca: BridgedCalleeAnalysis) -> BridgedMemoryBehavior in
let apply = bridgedApply.instruction as! ApplySite
let e = bca.analysis.getSideEffects(ofApply: apply)
return e.getMemBehavior(observeRetains: observeRetains)
Expand Down Expand Up @@ -126,13 +126,13 @@ extension Instruction {
}

public struct FunctionArray : RandomAccessCollection, FormattedLikeArray {
fileprivate let bridged: swift.CalleeList
fileprivate let bridged: BridgedCalleeAnalysis.CalleeList

public var startIndex: Int { 0 }
public var endIndex: Int { Int(bridged.getCount()) }
public var endIndex: Int { bridged.getCount() }

public subscript(_ index: Int) -> Function {
return BridgedCalleeAnalysis.getCallee(bridged, index).function
return bridged.getCallee(index).function
}
}
// Bridging utilities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private func mergeCondFails(_ condFailToMerge: inout Stack<CondFailInst>,

// Create a new cond_fail using the merged condition.
_ = builder.createCondFail(condition: mergedCond!,
message: lastCFI.message)
message: lastCFI.message.string)

while let cfi = condFailToMerge.pop() {
context.erase(instruction: cfi)
Expand Down
Loading