Skip to content

Commit 2dbd6cc

Browse files
committed
SwiftCompilerSources: rework bridging
Introduce two modes of bridging: * inline mode: this is basically how it worked so far. Using full C++ interop which allows bridging functions to be inlined. * pure mode: bridging functions are not inlined but compiled in a cpp file. This allows to reduce the C++ interop requirements to a minimum. No std/llvm/swift headers are imported. This change requires a major refactoring of bridging sources. The implementation of bridging functions go to two separate files: SILBridgingImpl.h and OptimizerBridgingImpl.h. Depending on the mode, those files are either included in the corresponding header files (inline mode), or included in the c++ file (pure mode). The mode can be selected with the BRIDGING_MODE cmake variable. By default it is set to the inline mode (= existing behavior). The pure mode is only selected in certain configurations to work around C++ interop issues: * In debug builds, to workaround a problem with LLDB's `po` command (rdar://115770255). * On windows to workaround a build problem.
1 parent a86b7cc commit 2dbd6cc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+3396
-2357
lines changed

CMakeLists.txt

+18
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,13 @@ How to build the swift compiler modules. Possible values are
346346
compiler, provided in `SWIFT_NATIVE_SWIFT_TOOLS_PATH`
347347
]=] OFF)
348348

349+
option(BRIDGING_MODE [=[
350+
How swift-C++ bridging code is compiled:
351+
INLINE: uses full swift C++ interop and briding functions are inlined
352+
PURE: uses limited C++ interp an bridging functions are not inlined
353+
DEFAULT: based on the build configuration
354+
]=] DEFAULT)
355+
349356
# The following only works with the Ninja generator in CMake >= 3.0.
350357
set(SWIFT_PARALLEL_LINK_JOBS "" CACHE STRING
351358
"Define the maximum number of linker jobs for swift.")
@@ -390,6 +397,17 @@ set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY
390397
${SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default}
391398
CACHE STRING "MSVC Runtime Library for the standard library")
392399

400+
401+
if(BRIDGING_MODE STREQUAL "DEFAULT" OR NOT BRIDGING_MODE)
402+
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
403+
# In debug builds, to workaround a problem with LLDB's `po` command (rdar://115770255).
404+
# On windows to workaround a build problem.
405+
set(BRIDGING_MODE "PURE")
406+
else()
407+
set(BRIDGING_MODE "INLINE")
408+
endif()
409+
endif()
410+
393411
is_build_type_optimized("${SWIFT_STDLIB_BUILD_TYPE}" swift_optimized)
394412
if(swift_optimized)
395413
set(SWIFT_STDLIB_ASSERTIONS_default FALSE)

SwiftCompilerSources/CMakeLists.txt

+7-7
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ function(add_swift_compiler_modules_library name)
7676
"-Xfrontend" "-validate-tbd-against-ir=none"
7777
"-Xfrontend" "-enable-experimental-cxx-interop"
7878
"-Xcc" "-std=c++17"
79+
"-Xcc" "-DCOMPILED_WITH_SWIFT"
7980
"-Xcc" "-UIBOutlet" "-Xcc" "-UIBAction" "-Xcc" "-UIBInspectable")
8081
if (NOT BOOTSTRAPPING_MODE STREQUAL "HOSTTOOLS")
8182
list(APPEND swift_compile_options "-Xfrontend" "-disable-implicit-string-processing-module-import")
@@ -91,6 +92,10 @@ function(add_swift_compiler_modules_library name)
9192
list(APPEND swift_compile_options "-Xcc" "-DNDEBUG")
9293
endif()
9394

95+
if("${BRIDGING_MODE}" STREQUAL "PURE")
96+
list(APPEND swift_compile_options "-Xcc" "-DPURE_BRIDGING_MODE")
97+
endif()
98+
9499
if(NOT SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT)
95100
list(APPEND swift_compile_options "-Xfrontend" "-disable-legacy-type-info")
96101
endif()
@@ -237,16 +242,11 @@ else()
237242
# defined in include/swift/module.modulemap
238243
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/HeaderDependencies.cpp.tmp"
239244
"
240-
#include \"Basic/BridgedSwiftObject.h\"
241-
#include \"Basic/BasicBridging.h\"
242-
#include \"Basic/SourceLoc.h\"
245+
#define COMPILED_WITH_SWIFT
243246
247+
#include \"Basic/BasicBridging.h\"
244248
#include \"AST/ASTBridging.h\"
245-
#include \"AST/DiagnosticEngine.h\"
246-
#include \"AST/DiagnosticConsumer.h\"
247-
248249
#include \"SIL/SILBridging.h\"
249-
250250
#include \"SILOptimizer/OptimizerBridging.h\"
251251
252252
#include \"Parse/RegexParserBridging.h\"

SwiftCompilerSources/Sources/AST/DiagnosticEngine.swift

+24-16
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ import Basic
1717
public typealias DiagID = BridgedDiagID
1818

1919
public protocol DiagnosticArgument {
20-
func _withBridgedDiagnosticArgument(_ fn: (swift.DiagnosticArgument) -> Void)
20+
func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void)
2121
}
2222
extension String: DiagnosticArgument {
23-
public func _withBridgedDiagnosticArgument(_ fn: (swift.DiagnosticArgument) -> Void) {
24-
_withStringRef { fn(swift.DiagnosticArgument($0)) }
23+
public func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void) {
24+
_withBridgedStringRef { fn(BridgedDiagnosticArgument($0)) }
2525
}
2626
}
2727
extension Int: DiagnosticArgument {
28-
public func _withBridgedDiagnosticArgument(_ fn: (swift.DiagnosticArgument) -> Void) {
29-
fn(swift.DiagnosticArgument(Int32(self)))
28+
public func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void) {
29+
fn(BridgedDiagnosticArgument(self))
3030
}
3131
}
3232

@@ -41,12 +41,11 @@ public struct DiagnosticFixIt {
4141
self.text = text
4242
}
4343

44-
func withBridgedDiagnosticFixIt(_ fn: (swift.DiagnosticInfo.FixIt) -> Void) {
45-
text._withStringRef { bridgedTextRef in
46-
let bridgedDiagnosticFixIt = swift.DiagnosticInfo.FixIt(
47-
swift.CharSourceRange(start.bridged, UInt32(byteLength)),
48-
bridgedTextRef,
49-
ArrayRefOfDiagnosticArgument())
44+
func withBridgedDiagnosticFixIt(_ fn: (BridgedDiagnosticFixIt) -> Void) {
45+
text._withBridgedStringRef { bridgedTextRef in
46+
let bridgedDiagnosticFixIt = BridgedDiagnosticFixIt(
47+
start.bridged, UInt32(byteLength),
48+
bridgedTextRef)
5049
fn(bridgedDiagnosticFixIt)
5150
}
5251
}
@@ -71,10 +70,18 @@ public struct DiagnosticEngine {
7170
highlight: CharSourceRange? = nil,
7271
fixIts: [DiagnosticFixIt] = []) {
7372

74-
let bridgedSourceLoc: swift.SourceLoc = position.bridged
75-
let bridgedHighlightRange: swift.CharSourceRange = highlight.bridged
76-
var bridgedArgs: [swift.DiagnosticArgument] = []
77-
var bridgedFixIts: [swift.DiagnosticInfo.FixIt] = []
73+
let bridgedSourceLoc: BridgedSourceLoc = position.bridged
74+
let highlightStart: BridgedSourceLoc
75+
let highlightLength: UInt32
76+
if let highlight = highlight {
77+
highlightStart = highlight.start.bridged
78+
highlightLength = highlight.byteLength
79+
} else {
80+
highlightStart = BridgedSourceLoc()
81+
highlightLength = 0
82+
}
83+
var bridgedArgs: [BridgedDiagnosticArgument] = []
84+
var bridgedFixIts: [BridgedDiagnosticFixIt] = []
7885

7986
// Build a higher-order function to wrap every 'withBridgedXXX { ... }'
8087
// calls, so we don't escape anything from the closure. 'bridgedArgs' and
@@ -86,7 +93,8 @@ public struct DiagnosticEngine {
8693
bridgedFixIts.withBridgedArrayRef { bridgedFixItsRef in
8794
DiagnosticEngine_diagnose(bridged, bridgedSourceLoc,
8895
id, bridgedArgsRef,
89-
bridgedHighlightRange, bridgedFixItsRef)
96+
highlightStart, highlightLength,
97+
bridgedFixItsRef)
9098
}
9199
}
92100
}

SwiftCompilerSources/Sources/Basic/SourceLoc.swift

+10-30
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,15 @@ public struct SourceLoc {
2323
self.locationInFile = locationInFile
2424
}
2525

26-
public init?(bridged: swift.SourceLoc) {
26+
public init?(bridged: BridgedSourceLoc) {
2727
guard bridged.isValid() else {
2828
return nil
2929
}
30-
#if $NewCxxMethodSafetyHeuristics
31-
self.locationInFile = bridged.getOpaquePointerValue().assumingMemoryBound(to: UInt8.self)
32-
#else
33-
self.locationInFile = bridged.__getOpaquePointerValueUnsafe().assumingMemoryBound(to: UInt8.self)
34-
#endif
30+
self.locationInFile = bridged.opaquePointer!
3531
}
3632

37-
public var bridged: swift.SourceLoc {
38-
.init(llvm.SMLoc.getFromPointer(locationInFile))
33+
public var bridged: BridgedSourceLoc {
34+
.init(opaquePointer: locationInFile)
3935
}
4036
}
4137

@@ -46,40 +42,24 @@ extension SourceLoc {
4642
}
4743

4844
extension Optional where Wrapped == SourceLoc {
49-
public var bridged: swift.SourceLoc {
45+
public var bridged: BridgedSourceLoc {
5046
self?.bridged ?? .init()
5147
}
5248
}
5349

5450
public struct CharSourceRange {
55-
private let start: SourceLoc
56-
private let byteLength: UInt32
51+
public let start: SourceLoc
52+
public let byteLength: UInt32
5753

5854
public init(start: SourceLoc, byteLength: UInt32) {
5955
self.start = start
6056
self.byteLength = byteLength
6157
}
6258

63-
public init?(bridged: swift.CharSourceRange) {
64-
#if $NewCxxMethodSafetyHeuristics
65-
guard let start = SourceLoc(bridged: bridged.getStart()) else {
59+
public init?(bridgedStart: BridgedSourceLoc, byteLength: UInt32) {
60+
guard let start = SourceLoc(bridged: bridgedStart) else {
6661
return nil
6762
}
68-
#else
69-
guard let start = SourceLoc(bridged: bridged.__getStartUnsafe()) else {
70-
return nil
71-
}
72-
#endif
73-
self.init(start: start, byteLength: bridged.getByteLength())
74-
}
75-
76-
public var bridged: swift.CharSourceRange {
77-
.init(start.bridged, byteLength)
78-
}
79-
}
80-
81-
extension Optional where Wrapped == CharSourceRange {
82-
public var bridged: swift.CharSourceRange {
83-
self?.bridged ?? .init(.init(), 0)
63+
self.init(start: start, byteLength: byteLength)
8464
}
8565
}

SwiftCompilerSources/Sources/Basic/Utils.swift

+25-39
Original file line numberDiff line numberDiff line change
@@ -58,49 +58,39 @@ public extension NoReflectionChildren {
5858
//===----------------------------------------------------------------------===//
5959

6060
public struct StringRef : CustomStringConvertible, NoReflectionChildren {
61-
let _bridged: llvm.StringRef
61+
let _bridged: BridgedStringRef
6262

63-
public init(bridged: llvm.StringRef) { self._bridged = bridged }
63+
public init(bridged: BridgedStringRef) { self._bridged = bridged }
6464

65-
public var string: String { _bridged.string }
65+
public var string: String { String(_bridged) }
6666
public var description: String { string }
6767

6868
public var count: Int {
69-
#if $NewCxxMethodSafetyHeuristics
70-
Int(_bridged.bytes_end() - _bridged.bytes_begin())
71-
#else
72-
Int(_bridged.__bytes_endUnsafe() - _bridged.__bytes_beginUnsafe())
73-
#endif
69+
Int(_bridged.size())
7470
}
7571

7672
public subscript(index: Int) -> UInt8 {
77-
#if $NewCxxMethodSafetyHeuristics
78-
let buffer = UnsafeBufferPointer<UInt8>(start: _bridged.bytes_begin(),
79-
count: count)
80-
#else
81-
let buffer = UnsafeBufferPointer<UInt8>(start: _bridged.__bytes_beginUnsafe(),
82-
count: count)
83-
#endif
73+
let buffer = UnsafeBufferPointer<UInt8>(start: _bridged.uintData(), count: count)
8474
return buffer[index]
8575
}
8676

77+
public static func ==(lhs: StringRef, rhs: StringRef) -> Bool {
78+
let lhsBuffer = UnsafeBufferPointer<UInt8>(start: lhs._bridged.uintData(), count: lhs.count)
79+
let rhsBuffer = UnsafeBufferPointer<UInt8>(start: rhs._bridged.uintData(), count: rhs.count)
80+
if lhsBuffer.count != rhsBuffer.count { return false }
81+
return lhsBuffer.elementsEqual(rhsBuffer, by: ==)
82+
}
83+
8784
public static func ==(lhs: StringRef, rhs: StaticString) -> Bool {
88-
#if $NewCxxMethodSafetyHeuristics
89-
let lhsBuffer = UnsafeBufferPointer<UInt8>(
90-
start: lhs._bridged.bytes_begin(),
91-
count: lhs.count)
92-
#else
93-
let lhsBuffer = UnsafeBufferPointer<UInt8>(
94-
start: lhs._bridged.__bytes_beginUnsafe(),
95-
count: lhs.count)
96-
#endif
85+
let lhsBuffer = UnsafeBufferPointer<UInt8>(start: lhs._bridged.uintData(), count: lhs.count)
9786
return rhs.withUTF8Buffer { (rhsBuffer: UnsafeBufferPointer<UInt8>) in
9887
if lhsBuffer.count != rhsBuffer.count { return false }
9988
return lhsBuffer.elementsEqual(rhsBuffer, by: ==)
10089
}
10190
}
10291

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

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

112-
extension llvm.StringRef {
113-
public var string: String {
114-
String(_cxxString: self.str())
115-
}
116-
}
117-
118102
extension String {
119-
/// Underscored to avoid name collision with Swift LLVM Bindings.
120-
/// To be replaced with a bindings call once bindings are a dependency.
121-
public func _withStringRef<T>(_ c: (llvm.StringRef) -> T) -> T {
103+
public func _withBridgedStringRef<T>(_ c: (BridgedStringRef) -> T) -> T {
122104
var str = self
123105
return str.withUTF8 { buffer in
124-
return c(llvm.StringRef(buffer.baseAddress, buffer.count))
106+
return c(BridgedStringRef(buffer.baseAddress, buffer.count))
125107
}
126108
}
127109

128-
/// Underscored to avoid name collision with the std overlay.
129-
/// To be replaced with an overlay call once the CI uses SDKs built with Swift 5.8.
130-
public init(_cxxString s: std.string) {
131-
self.init(cString: s.__c_strUnsafe())
132-
withExtendedLifetime(s) {}
110+
public init(_ s: BridgedStringRef) {
111+
let buffer = UnsafeBufferPointer<UInt8>(start: s.uintData(), count: Int(s.size()))
112+
self.init(decoding: buffer, as: UTF8.self)
113+
}
114+
115+
public init(taking s: BridgedOwnedString) {
116+
let buffer = UnsafeBufferPointer<UInt8>(start: s.uintData(), count: s.size())
117+
self.init(decoding: buffer, as: UTF8.self)
118+
s.destroy()
133119
}
134120
}
135121

SwiftCompilerSources/Sources/Optimizer/Analysis/AliasAnalysis.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct AliasAnalysis {
3636
static func register() {
3737
BridgedAliasAnalysis.registerAnalysis(
3838
// getMemEffectsFn
39-
{ (bridgedCtxt: BridgedPassContext, bridgedVal: BridgedValue, bridgedInst: BridgedInstruction, complexityBudget: Int) -> swift.MemoryBehavior in
39+
{ (bridgedCtxt: BridgedPassContext, bridgedVal: BridgedValue, bridgedInst: BridgedInstruction, complexityBudget: Int) -> BridgedMemoryBehavior in
4040
let context = FunctionPassContext(_bridged: bridgedCtxt)
4141
let inst = bridgedInst.instruction
4242
let val = bridgedVal.value
@@ -255,7 +255,7 @@ private struct IsIndirectResultWalker: AddressDefUseWalker {
255255
}
256256

257257
private extension SideEffects.Memory {
258-
var bridged: swift.MemoryBehavior {
258+
var bridged: BridgedMemoryBehavior {
259259
switch (read, write) {
260260
case (false, false): return .None
261261
case (true, false): return .MayRead

SwiftCompilerSources/Sources/Optimizer/Analysis/CalleeAnalysis.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public struct CalleeAnalysis {
2323
return inst.instruction.isDeinitBarrier(bca.analysis)
2424
},
2525
// getMemBehaviorFn
26-
{ (bridgedApply: BridgedInstruction, observeRetains: Bool, bca: BridgedCalleeAnalysis) -> swift.MemoryBehavior in
26+
{ (bridgedApply: BridgedInstruction, observeRetains: Bool, bca: BridgedCalleeAnalysis) -> BridgedMemoryBehavior in
2727
let apply = bridgedApply.instruction as! ApplySite
2828
let e = bca.analysis.getSideEffects(ofApply: apply)
2929
return e.getMemBehavior(observeRetains: observeRetains)
@@ -126,13 +126,13 @@ extension Instruction {
126126
}
127127

128128
public struct FunctionArray : RandomAccessCollection, FormattedLikeArray {
129-
fileprivate let bridged: swift.CalleeList
129+
fileprivate let bridged: BridgedCalleeAnalysis.CalleeList
130130

131131
public var startIndex: Int { 0 }
132-
public var endIndex: Int { Int(bridged.getCount()) }
132+
public var endIndex: Int { bridged.getCount() }
133133

134134
public subscript(_ index: Int) -> Function {
135-
return BridgedCalleeAnalysis.getCallee(bridged, index).function
135+
return bridged.getCallee(index).function
136136
}
137137
}
138138
// Bridging utilities

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/MergeCondFails.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ private func mergeCondFails(_ condFailToMerge: inout Stack<CondFailInst>,
8686

8787
// Create a new cond_fail using the merged condition.
8888
_ = builder.createCondFail(condition: mergedCond!,
89-
message: lastCFI.message)
89+
message: lastCFI.message.string)
9090

9191
while let cfi = condFailToMerge.pop() {
9292
context.erase(instruction: cfi)

0 commit comments

Comments
 (0)