Files
swift-mirror/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift
Erik Eckstein 2dbd6cc56b 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.
2023-10-09 09:52:52 +02:00

136 lines
4.3 KiB
Swift

//===--- ModulePassContext.swift ------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import SIL
import OptimizerBridging
/// The context which is passed to a `ModulePass`'s run-function.
///
/// It provides access to all functions, v-tables and witness tables of a module,
/// but it doesn't provide any APIs to modify functions.
/// In order to modify a function, a module pass must use `transform(function:)`.
struct ModulePassContext : Context, CustomStringConvertible {
let _bridged: BridgedPassContext
public var description: String {
return String(taking: _bridged.getModuleDescription())
}
struct FunctionList : CollectionLikeSequence, IteratorProtocol {
private var currentFunction: Function?
fileprivate init(first: Function?) { currentFunction = first }
mutating func next() -> Function? {
if let f = currentFunction {
currentFunction = BridgedPassContext.getNextFunctionInModule(f.bridged).function
return f
}
return nil
}
}
struct GlobalVariableList : CollectionLikeSequence, IteratorProtocol {
private var currentGlobal: GlobalVariable?
fileprivate init(first: GlobalVariable?) { currentGlobal = first }
mutating func next() -> GlobalVariable? {
if let g = currentGlobal {
currentGlobal = BridgedPassContext.getNextGlobalInModule(g.bridged).globalVar
return g
}
return nil
}
}
struct VTableArray : BridgedRandomAccessCollection {
fileprivate let bridged: BridgedPassContext.VTableArray
var startIndex: Int { return 0 }
var endIndex: Int { return bridged.count }
subscript(_ index: Int) -> VTable {
assert(index >= startIndex && index < endIndex)
return VTable(bridged: BridgedVTable(vTable: bridged.base![index]))
}
}
struct WitnessTableList : CollectionLikeSequence, IteratorProtocol {
private var currentTable: WitnessTable?
fileprivate init(first: WitnessTable?) { currentTable = first }
mutating func next() -> WitnessTable? {
if let t = currentTable {
currentTable = BridgedPassContext.getNextWitnessTableInModule(t.bridged).witnessTable
return t
}
return nil
}
}
struct DefaultWitnessTableList : CollectionLikeSequence, IteratorProtocol {
private var currentTable: DefaultWitnessTable?
fileprivate init(first: DefaultWitnessTable?) { currentTable = first }
mutating func next() -> DefaultWitnessTable? {
if let t = currentTable {
currentTable = BridgedPassContext.getNextDefaultWitnessTableInModule(t.bridged).defaultWitnessTable
return t
}
return nil
}
}
var functions: FunctionList {
FunctionList(first: _bridged.getFirstFunctionInModule().function)
}
var globalVariables: GlobalVariableList {
GlobalVariableList(first: _bridged.getFirstGlobalInModule().globalVar)
}
var vTables: VTableArray {
VTableArray(bridged: _bridged.getVTables())
}
var witnessTables: WitnessTableList {
WitnessTableList(first: _bridged.getFirstWitnessTableInModule().witnessTable)
}
var defaultWitnessTables: DefaultWitnessTableList {
DefaultWitnessTableList(first: _bridged.getFirstDefaultWitnessTableInModule().defaultWitnessTable)
}
/// Run a closure with a `PassContext` for a function, which allows to modify that function.
///
/// Only a single `transform` can be alive at the same time, i.e. it's not allowed to nest
/// calls to `transform`.
func transform(function: Function, _ runOnFunction: (FunctionPassContext) -> ()) {
_bridged.beginTransformFunction(function.bridged)
runOnFunction(FunctionPassContext(_bridged: _bridged))
_bridged.endTransformFunction();
}
func mangleAsyncRemoved(from function: Function) -> String {
return String(taking: _bridged.mangleAsyncRemoved(function.bridged))
}
}
extension GlobalVariable {
func setIsLet(to value: Bool, _ context: ModulePassContext) {
bridged.setLet(value)
}
}