Swift Bridging: use C++ instead of C bridging for the optimizer

This commit is contained in:
Erik Eckstein
2023-03-21 13:50:22 +01:00
parent a092ecb5c2
commit 010efc1ca6
18 changed files with 554 additions and 671 deletions

View File

@@ -17,7 +17,7 @@ struct AliasAnalysis {
let bridged: BridgedAliasAnalysis let bridged: BridgedAliasAnalysis
func mayRead(_ inst: Instruction, fromAddress: Value) -> Bool { func mayRead(_ inst: Instruction, fromAddress: Value) -> Bool {
switch AliasAnalysis_getMemBehavior(bridged, inst.bridged, fromAddress.bridged) { switch bridged.getMemBehavior(inst.bridged, fromAddress.bridged) {
case .MayRead, .MayReadWrite, .MayHaveSideEffects: case .MayRead, .MayReadWrite, .MayHaveSideEffects:
return true return true
default: default:
@@ -26,7 +26,7 @@ struct AliasAnalysis {
} }
func mayWrite(_ inst: Instruction, toAddress: Value) -> Bool { func mayWrite(_ inst: Instruction, toAddress: Value) -> Bool {
switch AliasAnalysis_getMemBehavior(bridged, inst.bridged, toAddress.bridged) { switch bridged.getMemBehavior(inst.bridged, toAddress.bridged) {
case .MayWrite, .MayReadWrite, .MayHaveSideEffects: case .MayWrite, .MayReadWrite, .MayHaveSideEffects:
return true return true
default: default:
@@ -35,7 +35,7 @@ struct AliasAnalysis {
} }
func mayReadOrWrite(_ inst: Instruction, address: Value) -> Bool { func mayReadOrWrite(_ inst: Instruction, address: Value) -> Bool {
switch AliasAnalysis_getMemBehavior(bridged, inst.bridged, address.bridged) { switch bridged.getMemBehavior(inst.bridged, address.bridged) {
case .MayRead, .MayWrite, .MayReadWrite, .MayHaveSideEffects: case .MayRead, .MayWrite, .MayReadWrite, .MayHaveSideEffects:
return true return true
default: default:
@@ -61,7 +61,7 @@ struct AliasAnalysis {
} }
static func register() { static func register() {
AliasAnalysis_register( BridgedAliasAnalysis.registerAnalysis(
// getMemEffectsFn // getMemEffectsFn
{ (bridgedCtxt: BridgedPassContext, bridgedVal: BridgedValue, bridgedInst: BridgedInstruction) -> swift.MemoryBehavior in { (bridgedCtxt: BridgedPassContext, bridgedVal: BridgedValue, bridgedInst: BridgedInstruction) -> swift.MemoryBehavior in
let context = FunctionPassContext(_bridged: bridgedCtxt) let context = FunctionPassContext(_bridged: bridgedCtxt)

View File

@@ -17,7 +17,7 @@ public struct CalleeAnalysis {
let bridged: BridgedCalleeAnalysis let bridged: BridgedCalleeAnalysis
static func register() { static func register() {
CalleeAnalysis_register( BridgedCalleeAnalysis.registerAnalysis(
// isDeinitBarrierFn: // isDeinitBarrierFn:
{ (inst : BridgedInstruction, bca: BridgedCalleeAnalysis) -> Bool in { (inst : BridgedInstruction, bca: BridgedCalleeAnalysis) -> Bool in
return inst.instruction.isDeinitBarrier(bca.analysis) return inst.instruction.isDeinitBarrier(bca.analysis)
@@ -33,19 +33,19 @@ public struct CalleeAnalysis {
} }
public func getCallees(callee: Value) -> FunctionArray? { public func getCallees(callee: Value) -> FunctionArray? {
let bridgedFuncs = CalleeAnalysis_getCallees(bridged, callee.bridged) let bridgedFuncs = bridged.getCallees(callee.bridged)
if bridgedFuncs.incomplete != 0 { if bridgedFuncs.isIncomplete() {
return nil return nil
} }
return FunctionArray(bridged: bridgedFuncs) return FunctionArray(bridged: bridgedFuncs)
} }
public func getIncompleteCallees(callee: Value) -> FunctionArray { public func getIncompleteCallees(callee: Value) -> FunctionArray {
return FunctionArray(bridged: CalleeAnalysis_getCallees(bridged, callee.bridged)) return FunctionArray(bridged: bridged.getCallees(callee.bridged))
} }
public func getDestructor(ofExactType type: Type) -> Function? { public func getDestructor(ofExactType type: Type) -> Function? {
let destructors = FunctionArray(bridged: CalleeAnalysis_getDestructors(bridged, type.bridged, /*isExactType*/ 1)) let destructors = FunctionArray(bridged: bridged.getDestructors(type.bridged, /*isExactType*/ true))
if destructors.count == 1 { if destructors.count == 1 {
return destructors[0] return destructors[0]
} }
@@ -53,8 +53,8 @@ public struct CalleeAnalysis {
} }
public func getDestructors(of type: Type) -> FunctionArray? { public func getDestructors(of type: Type) -> FunctionArray? {
let bridgedDtors = CalleeAnalysis_getDestructors(bridged, type.bridged, /*isExactType*/ 0) let bridgedDtors = bridged.getDestructors(type.bridged, /*isExactType*/ false)
if bridgedDtors.incomplete != 0 { if bridgedDtors.isIncomplete() {
return nil return nil
} }
return FunctionArray(bridged: bridgedDtors) return FunctionArray(bridged: bridgedDtors)
@@ -123,13 +123,13 @@ extension Instruction {
} }
public struct FunctionArray : RandomAccessCollection, FormattedLikeArray { public struct FunctionArray : RandomAccessCollection, FormattedLikeArray {
fileprivate let bridged: BridgedCalleeList fileprivate let bridged: swift.CalleeList
public var startIndex: Int { 0 } public var startIndex: Int { 0 }
public var endIndex: Int { BridgedFunctionArray_size(bridged) } public var endIndex: Int { Int(bridged.getCount()) }
public subscript(_ index: Int) -> Function { public subscript(_ index: Int) -> Function {
return BridgedFunctionArray_get(bridged, index).function return BridgedCalleeAnalysis.getCallee(bridged, index).function
} }
} }
// Bridging utilities // Bridging utilities

View File

@@ -17,6 +17,6 @@ public struct DeadEndBlocksAnalysis {
let bridged: BridgedDeadEndBlocksAnalysis let bridged: BridgedDeadEndBlocksAnalysis
public func isDeadEnd(_ block: BasicBlock) -> Bool { public func isDeadEnd(_ block: BasicBlock) -> Bool {
return DeadEndBlocksAnalysis_isDeadEnd(bridged, block.bridged) != 0 return bridged.isDeadEnd(block.bridged)
} }
} }

View File

@@ -19,7 +19,7 @@ public struct DominatorTree {
extension BasicBlock { extension BasicBlock {
func dominates(_ other: BasicBlock, _ domTree: DominatorTree) -> Bool { func dominates(_ other: BasicBlock, _ domTree: DominatorTree) -> Bool {
DominatorTree_dominates(domTree.bridged, self.bridged, other.bridged) != 0 domTree.bridged.dominates(self.bridged, other.bridged)
} }
func strictlyDominates(_ other: BasicBlock, _ domTree: DominatorTree) -> Bool { func strictlyDominates(_ other: BasicBlock, _ domTree: DominatorTree) -> Bool {

View File

@@ -19,7 +19,7 @@ public struct PostDominatorTree {
extension BasicBlock { extension BasicBlock {
func postDominates(_ other: BasicBlock, _ pdomTree: PostDominatorTree) -> Bool { func postDominates(_ other: BasicBlock, _ pdomTree: PostDominatorTree) -> Bool {
PostDominatorTree_postDominates(pdomTree.bridged, self.bridged, other.bridged) != 0 pdomTree.bridged.postDominates(self.bridged, other.bridged)
} }
func strictlyPostDominates(_ other: BasicBlock, _ pdomTree: PostDominatorTree) -> Bool { func strictlyPostDominates(_ other: BasicBlock, _ pdomTree: PostDominatorTree) -> Bool {

View File

@@ -38,25 +38,25 @@ struct BasicBlockSet : IntrusiveSet {
init(_ context: some Context) { init(_ context: some Context) {
self.context = context._bridged self.context = context._bridged
self.bridged = PassContext_allocBasicBlockSet(self.context) self.bridged = self.context.allocBasicBlockSet()
} }
func contains(_ block: BasicBlock) -> Bool { func contains(_ block: BasicBlock) -> Bool {
BasicBlockSet_contains(bridged, block.bridged) != 0 bridged.contains(block.bridged)
} }
/// Returns true if `block` was not contained in the set before inserting. /// Returns true if `block` was not contained in the set before inserting.
@discardableResult @discardableResult
mutating func insert(_ block: BasicBlock) -> Bool { mutating func insert(_ block: BasicBlock) -> Bool {
BasicBlockSet_insert(bridged, block.bridged) != 0 bridged.insert(block.bridged)
} }
mutating func erase(_ block: BasicBlock) { mutating func erase(_ block: BasicBlock) {
BasicBlockSet_erase(bridged, block.bridged) bridged.erase(block.bridged)
} }
var description: String { var description: String {
let function = BasicBlockSet_getFunction(bridged).function let function = bridged.getFunction().function
let blockNames = function.blocks.enumerated().filter { contains($0.1) } let blockNames = function.blocks.enumerated().filter { contains($0.1) }
.map { "bb\($0.0)"} .map { "bb\($0.0)"}
return "{" + blockNames.joined(separator: ", ") + "}" return "{" + blockNames.joined(separator: ", ") + "}"
@@ -64,7 +64,7 @@ struct BasicBlockSet : IntrusiveSet {
/// TODO: once we have move-only types, make this a real deinit. /// TODO: once we have move-only types, make this a real deinit.
mutating func deinitialize() { mutating func deinitialize() {
PassContext_freeBasicBlockSet(context, bridged) context.freeBasicBlockSet(bridged)
} }
} }
@@ -83,25 +83,25 @@ struct ValueSet : IntrusiveSet {
init(_ context: some Context) { init(_ context: some Context) {
self.context = context._bridged self.context = context._bridged
self.bridged = PassContext_allocNodeSet(self.context) self.bridged = self.context.allocNodeSet()
} }
func contains(_ value: Value) -> Bool { func contains(_ value: Value) -> Bool {
NodeSet_containsValue(bridged, value.bridged) != 0 bridged.containsValue(value.bridged)
} }
/// Returns true if `value` was not contained in the set before inserting. /// Returns true if `value` was not contained in the set before inserting.
@discardableResult @discardableResult
mutating func insert(_ value: Value) -> Bool { mutating func insert(_ value: Value) -> Bool {
NodeSet_insertValue(bridged, value.bridged) != 0 bridged.insertValue(value.bridged)
} }
mutating func erase(_ value: Value) { mutating func erase(_ value: Value) {
NodeSet_eraseValue(bridged, value.bridged) bridged.eraseValue(value.bridged)
} }
var description: String { var description: String {
let function = NodeSet_getFunction(bridged).function let function = bridged.getFunction().function
var d = "{\n" var d = "{\n"
for block in function.blocks { for block in function.blocks {
for arg in block.arguments { for arg in block.arguments {
@@ -123,7 +123,7 @@ struct ValueSet : IntrusiveSet {
/// TODO: once we have move-only types, make this a real deinit. /// TODO: once we have move-only types, make this a real deinit.
mutating func deinitialize() { mutating func deinitialize() {
PassContext_freeNodeSet(context, bridged) context.freeNodeSet(bridged)
} }
} }
@@ -142,25 +142,25 @@ struct InstructionSet : IntrusiveSet {
init(_ context: some Context) { init(_ context: some Context) {
self.context = context._bridged self.context = context._bridged
self.bridged = PassContext_allocNodeSet(self.context) self.bridged = self.context.allocNodeSet()
} }
func contains(_ inst: Instruction) -> Bool { func contains(_ inst: Instruction) -> Bool {
NodeSet_containsInstruction(bridged, inst.bridged) != 0 bridged.containsInstruction(inst.bridged)
} }
/// Returns true if `inst` was not contained in the set before inserting. /// Returns true if `inst` was not contained in the set before inserting.
@discardableResult @discardableResult
mutating func insert(_ inst: Instruction) -> Bool { mutating func insert(_ inst: Instruction) -> Bool {
NodeSet_insertInstruction(bridged, inst.bridged) != 0 bridged.insertInstruction(inst.bridged)
} }
mutating func erase(_ inst: Instruction) { mutating func erase(_ inst: Instruction) {
NodeSet_eraseInstruction(bridged, inst.bridged) bridged.eraseInstruction(inst.bridged)
} }
var description: String { var description: String {
let function = NodeSet_getFunction(bridged).function let function = bridged.getFunction().function
var d = "{\n" var d = "{\n"
for inst in function.instructions { for inst in function.instructions {
if contains(inst) { if contains(inst) {
@@ -173,6 +173,6 @@ struct InstructionSet : IntrusiveSet {
/// TODO: once we have move-only types, make this a real deinit. /// TODO: once we have move-only types, make this a real deinit.
mutating func deinitialize() { mutating func deinitialize() {
PassContext_freeNodeSet(context, bridged) context.freeNodeSet(bridged)
} }
} }

View File

@@ -27,22 +27,22 @@ import SIL
struct Stack<Element> : CollectionLikeSequence { struct Stack<Element> : CollectionLikeSequence {
private let bridgedContext: BridgedPassContext private let bridgedContext: BridgedPassContext
private var firstSlab = BridgedSlab(data: nil) private var firstSlab = BridgedPassContext.Slab(nil)
private var lastSlab = BridgedSlab(data: nil) private var lastSlab = BridgedPassContext.Slab(nil)
private var endIndex: Int = 0 private var endIndex: Int = 0
private static var slabCapacity: Int { private static var slabCapacity: Int {
BridgedSlabCapacity / MemoryLayout<Element>.stride BridgedPassContext.Slab.getCapacity() / MemoryLayout<Element>.stride
} }
private static func bind(_ slab: BridgedSlab) -> UnsafeMutablePointer<Element> { private static func bind(_ slab: BridgedPassContext.Slab) -> UnsafeMutablePointer<Element> {
return slab.data!.bindMemory(to: Element.self, capacity: Stack.slabCapacity) return UnsafeMutableRawPointer(slab.data!).bindMemory(to: Element.self, capacity: Stack.slabCapacity)
} }
struct Iterator : IteratorProtocol { struct Iterator : IteratorProtocol {
var slab: BridgedSlab var slab: BridgedPassContext.Slab
var index: Int var index: Int
let lastSlab: BridgedSlab let lastSlab: BridgedPassContext.Slab
let endIndex: Int let endIndex: Int
mutating func next() -> Element? { mutating func next() -> Element? {
@@ -52,7 +52,7 @@ struct Stack<Element> : CollectionLikeSequence {
index += 1 index += 1
if index >= end && slab.data != lastSlab.data { if index >= end && slab.data != lastSlab.data {
slab = PassContext_getNextSlab(slab) slab = slab.getNext()
index = 0 index = 0
} }
return elem return elem
@@ -77,11 +77,11 @@ struct Stack<Element> : CollectionLikeSequence {
mutating func push(_ element: Element) { mutating func push(_ element: Element) {
if endIndex >= Stack.slabCapacity { if endIndex >= Stack.slabCapacity {
lastSlab = PassContext_allocSlab(bridgedContext, lastSlab) lastSlab = bridgedContext.allocSlab(lastSlab)
endIndex = 0 endIndex = 0
} else if firstSlab.data == nil { } else if firstSlab.data == nil {
assert(endIndex == 0) assert(endIndex == 0)
firstSlab = PassContext_allocSlab(bridgedContext, lastSlab) firstSlab = bridgedContext.allocSlab(lastSlab)
lastSlab = firstSlab lastSlab = firstSlab
} }
(Stack.bind(lastSlab) + endIndex).initialize(to: element) (Stack.bind(lastSlab) + endIndex).initialize(to: element)
@@ -109,12 +109,12 @@ struct Stack<Element> : CollectionLikeSequence {
if endIndex == 0 { if endIndex == 0 {
if lastSlab.data == firstSlab.data { if lastSlab.data == firstSlab.data {
_ = PassContext_freeSlab(bridgedContext, lastSlab) _ = bridgedContext.freeSlab(lastSlab)
firstSlab.data = nil firstSlab.data = nil
lastSlab.data = nil lastSlab.data = nil
endIndex = 0 endIndex = 0
} else { } else {
lastSlab = PassContext_freeSlab(bridgedContext, lastSlab) lastSlab = bridgedContext.freeSlab(lastSlab)
endIndex = Stack.slabCapacity endIndex = Stack.slabCapacity
} }
} }

View File

@@ -24,7 +24,7 @@ extension Context {
// The calleeAnalysis is not specific to a function and therefore can be provided in // The calleeAnalysis is not specific to a function and therefore can be provided in
// all contexts. // all contexts.
var calleeAnalysis: CalleeAnalysis { var calleeAnalysis: CalleeAnalysis {
let bridgeCA = PassContext_getCalleeAnalysis(_bridged) let bridgeCA = _bridged.getCalleeAnalysis()
return CalleeAnalysis(bridged: bridgeCA) return CalleeAnalysis(bridged: bridgeCA)
} }
} }
@@ -36,8 +36,8 @@ protocol MutatingContext : Context {
} }
extension MutatingContext { extension MutatingContext {
func notifyInvalidatedStackNesting() { PassContext_notifyInvalidatedStackNesting(_bridged) } func notifyInvalidatedStackNesting() { _bridged.notifyInvalidatedStackNesting() }
var needFixStackNesting: Bool { PassContext_getNeedFixStackNesting(_bridged) } var needFixStackNesting: Bool { _bridged.getNeedFixStackNesting() }
/// Splits the basic block, which contains `inst`, before `inst` and returns the /// Splits the basic block, which contains `inst`, before `inst` and returns the
/// new block. /// new block.
@@ -46,7 +46,7 @@ extension MutatingContext {
/// instructions _before_ `inst` remain in the original block. /// instructions _before_ `inst` remain in the original block.
func splitBlock(at inst: Instruction) -> BasicBlock { func splitBlock(at inst: Instruction) -> BasicBlock {
notifyBranchesChanged() notifyBranchesChanged()
return PassContext_splitBlock(inst.bridged).block return _bridged.splitBlock(inst.bridged).block
} }
func erase(instruction: Instruction) { func erase(instruction: Instruction) {
@@ -58,7 +58,7 @@ extension MutatingContext {
} }
notifyInstructionsChanged() notifyInstructionsChanged()
PassContext_eraseInstruction(_bridged, instruction.bridged) _bridged.eraseInstruction(instruction.bridged)
} }
func erase(instructionIncludingDebugUses inst: Instruction) { func erase(instructionIncludingDebugUses inst: Instruction) {
@@ -72,25 +72,25 @@ extension MutatingContext {
} }
func tryDeleteDeadClosure(closure: SingleValueInstruction) -> Bool { func tryDeleteDeadClosure(closure: SingleValueInstruction) -> Bool {
PassContext_tryDeleteDeadClosure(_bridged, closure.bridged) _bridged.tryDeleteDeadClosure(closure.bridged)
} }
func getContextSubstitutionMap(for type: Type) -> SubstitutionMap { func getContextSubstitutionMap(for type: Type) -> SubstitutionMap {
SubstitutionMap(PassContext_getContextSubstitutionMap(_bridged, type.bridged)) SubstitutionMap(_bridged.getContextSubstitutionMap(type.bridged))
} }
// Private utilities // Private utilities
fileprivate func notifyInstructionsChanged() { fileprivate func notifyInstructionsChanged() {
PassContext_notifyChanges(_bridged, instructionsChanged) _bridged.asNotificationHandler().notifyChanges(.instructionsChanged)
} }
fileprivate func notifyCallsChanged() { fileprivate func notifyCallsChanged() {
PassContext_notifyChanges(_bridged, callsChanged) _bridged.asNotificationHandler().notifyChanges(.callsChanged)
} }
fileprivate func notifyBranchesChanged() { fileprivate func notifyBranchesChanged() {
PassContext_notifyChanges(_bridged, branchesChanged) _bridged.asNotificationHandler().notifyChanges(.branchesChanged)
} }
} }
@@ -103,7 +103,7 @@ struct FunctionPassContext : MutatingContext {
func continueWithNextSubpassRun(for inst: Instruction? = nil) -> Bool { func continueWithNextSubpassRun(for inst: Instruction? = nil) -> Bool {
let bridgedInst = OptionalBridgedInstruction(inst?.bridged.obj) let bridgedInst = OptionalBridgedInstruction(inst?.bridged.obj)
return PassContext_continueWithNextSubpassRun(_bridged, bridgedInst) != 0 return _bridged.continueWithNextSubpassRun(bridgedInst)
} }
func createSimplifyContext(preserveDebugInfo: Bool, notifyInstructionChanged: @escaping (Instruction) -> ()) -> SimplifyContext { func createSimplifyContext(preserveDebugInfo: Bool, notifyInstructionChanged: @escaping (Instruction) -> ()) -> SimplifyContext {
@@ -111,33 +111,33 @@ struct FunctionPassContext : MutatingContext {
} }
var aliasAnalysis: AliasAnalysis { var aliasAnalysis: AliasAnalysis {
let bridgedAA = PassContext_getAliasAnalysis(_bridged) let bridgedAA = _bridged.getAliasAnalysis()
return AliasAnalysis(bridged: bridgedAA) return AliasAnalysis(bridged: bridgedAA)
} }
var deadEndBlocks: DeadEndBlocksAnalysis { var deadEndBlocks: DeadEndBlocksAnalysis {
let bridgeDEA = PassContext_getDeadEndBlocksAnalysis(_bridged) let bridgeDEA = _bridged.getDeadEndBlocksAnalysis()
return DeadEndBlocksAnalysis(bridged: bridgeDEA) return DeadEndBlocksAnalysis(bridged: bridgeDEA)
} }
var dominatorTree: DominatorTree { var dominatorTree: DominatorTree {
let bridgedDT = PassContext_getDomTree(_bridged) let bridgedDT = _bridged.getDomTree()
return DominatorTree(bridged: bridgedDT) return DominatorTree(bridged: bridgedDT)
} }
var postDominatorTree: PostDominatorTree { var postDominatorTree: PostDominatorTree {
let bridgedPDT = PassContext_getPostDomTree(_bridged) let bridgedPDT = _bridged.getPostDomTree()
return PostDominatorTree(bridged: bridgedPDT) return PostDominatorTree(bridged: bridgedPDT)
} }
func loadFunction(name: StaticString) -> Function? { func loadFunction(name: StaticString) -> Function? {
return name.withUTF8Buffer { (nameBuffer: UnsafeBufferPointer<UInt8>) in return name.withUTF8Buffer { (nameBuffer: UnsafeBufferPointer<UInt8>) in
PassContext_loadFunction(_bridged, llvm.StringRef(nameBuffer.baseAddress, nameBuffer.count)).function _bridged.loadFunction(llvm.StringRef(nameBuffer.baseAddress, nameBuffer.count)).function
} }
} }
func erase(block: BasicBlock) { func erase(block: BasicBlock) {
PassContext_eraseBlock(_bridged, block.bridged) _bridged.eraseBlock(block.bridged)
} }
func modifyEffects(in function: Function, _ body: (inout FunctionEffects) -> ()) { func modifyEffects(in function: Function, _ body: (inout FunctionEffects) -> ()) {
@@ -146,7 +146,7 @@ struct FunctionPassContext : MutatingContext {
} }
fileprivate func notifyEffectsChanged() { fileprivate func notifyEffectsChanged() {
PassContext_notifyChanges(_bridged, effectsChanged) _bridged.asNotificationHandler().notifyChanges(.effectsChanged)
} }
} }
@@ -164,23 +164,23 @@ extension Builder {
/// Creates a builder which inserts _before_ `insPnt`, using a custom `location`. /// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
init(before insPnt: Instruction, location: Location, _ context: some MutatingContext) { init(before insPnt: Instruction, location: Location, _ context: some MutatingContext) {
self.init(insertAt: .before(insPnt), location: location, self.init(insertAt: .before(insPnt), location: location,
context.notifyInstructionChanged, context._bridged) context.notifyInstructionChanged, context._bridged.asNotificationHandler())
} }
/// Creates a builder which inserts _before_ `insPnt`, using the location of `insPnt`. /// Creates a builder which inserts _before_ `insPnt`, using the location of `insPnt`.
init(before insPnt: Instruction, _ context: some MutatingContext) { init(before insPnt: Instruction, _ context: some MutatingContext) {
self.init(insertAt: .before(insPnt), location: insPnt.location, self.init(insertAt: .before(insPnt), location: insPnt.location,
context.notifyInstructionChanged, context._bridged) context.notifyInstructionChanged, context._bridged.asNotificationHandler())
} }
/// Creates a builder which inserts _after_ `insPnt`, using a custom `location`. /// Creates a builder which inserts _after_ `insPnt`, using a custom `location`.
init(after insPnt: Instruction, location: Location, _ context: some MutatingContext) { init(after insPnt: Instruction, location: Location, _ context: some MutatingContext) {
if let nextInst = insPnt.next { if let nextInst = insPnt.next {
self.init(insertAt: .before(nextInst), location: location, self.init(insertAt: .before(nextInst), location: location,
context.notifyInstructionChanged, context._bridged) context.notifyInstructionChanged, context._bridged.asNotificationHandler())
} else { } else {
self.init(insertAt: .atEndOf(insPnt.parentBlock), location: location, self.init(insertAt: .atEndOf(insPnt.parentBlock), location: location,
context.notifyInstructionChanged, context._bridged) context.notifyInstructionChanged, context._bridged.asNotificationHandler())
} }
} }
@@ -192,14 +192,14 @@ extension Builder {
/// Creates a builder which inserts at the end of `block`, using a custom `location`. /// Creates a builder which inserts at the end of `block`, using a custom `location`.
init(atEndOf block: BasicBlock, location: Location, _ context: some MutatingContext) { init(atEndOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
self.init(insertAt: .atEndOf(block), location: location, self.init(insertAt: .atEndOf(block), location: location,
context.notifyInstructionChanged, context._bridged) context.notifyInstructionChanged, context._bridged.asNotificationHandler())
} }
/// Creates a builder which inserts at the begin of `block`, using a custom `location`. /// Creates a builder which inserts at the begin of `block`, using a custom `location`.
init(atBeginOf block: BasicBlock, location: Location, _ context: some MutatingContext) { init(atBeginOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
let firstInst = block.instructions.first! let firstInst = block.instructions.first!
self.init(insertAt: .before(firstInst), location: location, self.init(insertAt: .before(firstInst), location: location,
context.notifyInstructionChanged, context._bridged) context.notifyInstructionChanged, context._bridged.asNotificationHandler())
} }
/// Creates a builder which inserts at the begin of `block`, using the location of the first /// Creates a builder which inserts at the begin of `block`, using the location of the first
@@ -207,7 +207,7 @@ extension Builder {
init(atBeginOf block: BasicBlock, _ context: some MutatingContext) { init(atBeginOf block: BasicBlock, _ context: some MutatingContext) {
let firstInst = block.instructions.first! let firstInst = block.instructions.first!
self.init(insertAt: .before(firstInst), location: firstInst.location, self.init(insertAt: .before(firstInst), location: firstInst.location,
context.notifyInstructionChanged, context._bridged) context.notifyInstructionChanged, context._bridged.asNotificationHandler())
} }
} }
@@ -217,7 +217,7 @@ extension Builder {
extension Undef { extension Undef {
static func get(type: Type, _ context: some MutatingContext) -> Undef { static func get(type: Type, _ context: some MutatingContext) -> Undef {
SILUndef_get(type.bridged, context._bridged).value as! Undef context._bridged.getSILUndef(type.bridged).value as! Undef
} }
} }
@@ -259,7 +259,7 @@ extension BasicBlock {
extension AllocRefInstBase { extension AllocRefInstBase {
func setIsStackAllocatable(_ context: some MutatingContext) { func setIsStackAllocatable(_ context: some MutatingContext) {
context.notifyInstructionsChanged() context.notifyInstructionsChanged()
AllocRefInstBase_setIsStackAllocatable(bridged) bridged.AllocRefInstBase_setIsStackAllocatable()
context.notifyInstructionChanged(self) context.notifyInstructionChanged(self)
} }
} }
@@ -294,7 +294,7 @@ extension RefCountingInst {
extension TermInst { extension TermInst {
func replaceBranchTarget(from fromBlock: BasicBlock, to toBlock: BasicBlock, _ context: some MutatingContext) { func replaceBranchTarget(from fromBlock: BasicBlock, to toBlock: BasicBlock, _ context: some MutatingContext) {
context.notifyBranchesChanged() context.notifyBranchesChanged()
TermInst_replaceBranchTarget(bridged, fromBlock.bridged, toBlock.bridged) bridged.TermInst_replaceBranchTarget(fromBlock.bridged, toBlock.bridged)
} }
} }
@@ -305,7 +305,6 @@ extension Function {
} }
func fixStackNesting(_ context: FunctionPassContext) { func fixStackNesting(_ context: FunctionPassContext) {
PassContext_fixStackNesting(context._bridged, bridged) context._bridged.fixStackNesting(bridged)
} }
} }

View File

@@ -28,7 +28,7 @@ struct ModulePassContext : Context {
mutating func next() -> Function? { mutating func next() -> Function? {
if let f = currentFunction { if let f = currentFunction {
currentFunction = PassContext_nextFunctionInModule(f.bridged).function currentFunction = BridgedPassContext.getNextFunctionInModule(f.bridged).function
return f return f
} }
return nil return nil
@@ -36,14 +36,14 @@ struct ModulePassContext : Context {
} }
struct VTableArray : BridgedRandomAccessCollection { struct VTableArray : BridgedRandomAccessCollection {
fileprivate let bridged: BridgedVTableArray fileprivate let bridged: BridgedPassContext.VTableArray
var startIndex: Int { return 0 } var startIndex: Int { return 0 }
var endIndex: Int { return bridged.count } var endIndex: Int { return bridged.count }
subscript(_ index: Int) -> VTable { subscript(_ index: Int) -> VTable {
assert(index >= startIndex && index < endIndex) assert(index >= startIndex && index < endIndex)
return VTable(bridged: bridged.vTables![index]) return VTable(bridged: BridgedVTable(vTable: bridged.base![index]))
} }
} }
@@ -54,7 +54,7 @@ struct ModulePassContext : Context {
mutating func next() -> WitnessTable? { mutating func next() -> WitnessTable? {
if let t = currentTable { if let t = currentTable {
currentTable = PassContext_nextWitnessTableInModule(t.bridged).witnessTable currentTable = BridgedPassContext.getNextWitnessTableInModule(t.bridged).witnessTable
return t return t
} }
return nil return nil
@@ -68,7 +68,7 @@ struct ModulePassContext : Context {
mutating func next() -> DefaultWitnessTable? { mutating func next() -> DefaultWitnessTable? {
if let t = currentTable { if let t = currentTable {
currentTable = PassContext_nextDefaultWitnessTableInModule(t.bridged).defaultWitnessTable currentTable = BridgedPassContext.getNextDefaultWitnessTableInModule(t.bridged).defaultWitnessTable
return t return t
} }
return nil return nil
@@ -76,19 +76,19 @@ struct ModulePassContext : Context {
} }
var functions: FunctionList { var functions: FunctionList {
FunctionList(first: PassContext_firstFunctionInModule(_bridged).function) FunctionList(first: _bridged.getFirstFunctionInModule().function)
} }
var vTables: VTableArray { var vTables: VTableArray {
VTableArray(bridged: PassContext_getVTables(_bridged)) VTableArray(bridged: _bridged.getVTables())
} }
var witnessTables: WitnessTableList { var witnessTables: WitnessTableList {
WitnessTableList(first: PassContext_firstWitnessTableInModule(_bridged).witnessTable) WitnessTableList(first: _bridged.getFirstWitnessTableInModule().witnessTable)
} }
var defaultWitnessTables: DefaultWitnessTableList { var defaultWitnessTables: DefaultWitnessTableList {
DefaultWitnessTableList(first: PassContext_firstDefaultWitnessTableInModule(_bridged).defaultWitnessTable) DefaultWitnessTableList(first: _bridged.getFirstDefaultWitnessTableInModule().defaultWitnessTable)
} }
/// Run a closure with a `PassContext` for a function, which allows to modify that function. /// Run a closure with a `PassContext` for a function, which allows to modify that function.
@@ -96,8 +96,8 @@ struct ModulePassContext : Context {
/// Only a single `transform` can be alive at the same time, i.e. it's not allowed to nest /// Only a single `transform` can be alive at the same time, i.e. it's not allowed to nest
/// calls to `transform`. /// calls to `transform`.
func transform(function: Function, _ runOnFunction: (FunctionPassContext) -> ()) { func transform(function: Function, _ runOnFunction: (FunctionPassContext) -> ()) {
PassContext_beginTransformFunction(function.bridged, _bridged) _bridged.beginTransformFunction(function.bridged)
runOnFunction(FunctionPassContext(_bridged: _bridged)) runOnFunction(FunctionPassContext(_bridged: _bridged))
PassContext_endTransformFunction(_bridged); _bridged.endTransformFunction();
} }
} }

View File

@@ -17,14 +17,14 @@ struct Options {
let _bridged: BridgedPassContext let _bridged: BridgedPassContext
var enableStackProtection: Bool { var enableStackProtection: Bool {
SILOptions_enableStackProtection(_bridged) != 0 _bridged.enableStackProtection()
} }
var enableMoveInoutStackProtection: Bool { var enableMoveInoutStackProtection: Bool {
SILOptions_enableMoveInoutStackProtection(_bridged) != 0 _bridged.enableMoveInoutStackProtection()
} }
func enableSimplification(for inst: Instruction) -> Bool { func enableSimplification(for inst: Instruction) -> Bool {
SILOptions_enableSimplificationFor(inst.bridged) _bridged.enableSimplificationFor(inst.bridged)
} }
} }

View File

@@ -23,7 +23,7 @@ public struct Builder {
let insertAt: InsertionPoint let insertAt: InsertionPoint
let location: Location let location: Location
private let passContext: BridgedPassContext private let notificationHandler: BridgedChangeNotificationHandler
private let notifyNewInstruction: (Instruction) -> () private let notifyNewInstruction: (Instruction) -> ()
private var bridged: BridgedBuilder { private var bridged: BridgedBuilder {
@@ -40,12 +40,12 @@ public struct Builder {
} }
private func notifyNew<I: Instruction>(_ instruction: I) -> I { private func notifyNew<I: Instruction>(_ instruction: I) -> I {
PassContext_notifyChanges(passContext, instructionsChanged) notificationHandler.notifyChanges(.instructionsChanged)
if instruction is FullApplySite { if instruction is FullApplySite {
PassContext_notifyChanges(passContext, callsChanged) notificationHandler.notifyChanges(.callsChanged)
} }
if instruction is TermInst { if instruction is TermInst {
PassContext_notifyChanges(passContext, branchesChanged) notificationHandler.notifyChanges(.branchesChanged)
} }
notifyNewInstruction(instruction) notifyNewInstruction(instruction)
return instruction return instruction
@@ -53,11 +53,11 @@ public struct Builder {
public init(insertAt: InsertionPoint, location: Location, public init(insertAt: InsertionPoint, location: Location,
_ notifyNewInstruction: @escaping (Instruction) -> (), _ notifyNewInstruction: @escaping (Instruction) -> (),
_ passContext: BridgedPassContext) { _ notificationHandler: BridgedChangeNotificationHandler) {
self.insertAt = insertAt self.insertAt = insertAt
self.location = location; self.location = location;
self.notifyNewInstruction = notifyNewInstruction self.notifyNewInstruction = notifyNewInstruction
self.passContext = passContext self.notificationHandler = notificationHandler
} }
public func createBuiltinBinaryFunction(name: String, public func createBuiltinBinaryFunction(name: String,

View File

@@ -40,16 +40,7 @@ struct BridgedBasicBlock;
struct BridgedSuccessorArray; struct BridgedSuccessorArray;
struct OptionalBridgedBasicBlock; struct OptionalBridgedBasicBlock;
enum ChangeNotificationKind { void registerBridgedClass(llvm::StringRef className, SwiftMetatype metatype);
instructionsChanged,
callsChanged,
branchesChanged,
effectsChanged
};
typedef struct {
const void * _Nonnull opaqueCtxt;
} BridgedPassContext;
struct BridgedValue { struct BridgedValue {
SwiftObject obj; SwiftObject obj;
@@ -613,6 +604,12 @@ struct BridgedInstruction {
return getAs<swift::CondBranchInst>()->getNumTrueArgs(); return getAs<swift::CondBranchInst>()->getNumTrueArgs();
} }
void AllocRefInstBase_setIsStackAllocatable() const {
getAs<swift::AllocRefInstBase>()->setStackAllocatable();
}
inline void TermInst_replaceBranchTarget(BridgedBasicBlock from, BridgedBasicBlock to) const;
SwiftInt KeyPathInst_getNumComponents() const { SwiftInt KeyPathInst_getNumComponents() const {
if (swift::KeyPathPattern *pattern = getAs<swift::KeyPathInst>()->getPattern()) { if (swift::KeyPathPattern *pattern = getAs<swift::KeyPathInst>()->getPattern()) {
return (SwiftInt)pattern->getComponents().size(); return (SwiftInt)pattern->getComponents().size();
@@ -1052,17 +1049,24 @@ struct BridgedNominalTypeDecl {
swift::NominalTypeDecl * _Nonnull decl; swift::NominalTypeDecl * _Nonnull decl;
}; };
void registerBridgedClass(llvm::StringRef className, SwiftMetatype metatype); // Passmanager and Context
SwiftInt PassContext_continueWithNextSubpassRun(BridgedPassContext passContext, namespace swift {
OptionalBridgedInstruction inst); class SwiftPassInvocation;
void PassContext_notifyChanges(BridgedPassContext passContext, }
enum ChangeNotificationKind changeKind);
BridgedBasicBlock PassContext_splitBlock(BridgedInstruction bridgedInst); struct BridgedChangeNotificationHandler {
void PassContext_eraseInstruction(BridgedPassContext passContext, swift::SwiftPassInvocation * _Nonnull invocation;
BridgedInstruction inst);
void PassContext_eraseBlock(BridgedPassContext passContext, enum class Kind {
BridgedBasicBlock block); instructionsChanged,
callsChanged,
branchesChanged,
effectsChanged
};
void notifyChanges(Kind changeKind) const;
};
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Inline functions // Inline functions
@@ -1115,6 +1119,10 @@ BridgedBasicBlock BridgedInstruction::BranchInst_getTargetBlock() const {
return {getAs<swift::BranchInst>()->getDestBB()}; return {getAs<swift::BranchInst>()->getDestBB()};
} }
void BridgedInstruction::TermInst_replaceBranchTarget(BridgedBasicBlock from, BridgedBasicBlock to) const {
getAs<swift::TermInst>()->replaceBranchTarget(from.getBlock(), to.getBlock());
}
OptionalBridgedSuccessor BridgedBasicBlock::getFirstPred() const { OptionalBridgedSuccessor BridgedBasicBlock::getFirstPred() const {
return {getBlock()->pred_begin().getSuccessorRef()}; return {getBlock()->pred_begin().getSuccessorRef()};
} }

View File

@@ -104,6 +104,22 @@ public:
} }
} }
size_t getCount() const {
switch (kind) {
case Kind::empty: return 0;
case Kind::singleFunction: return 1;
case Kind::multipleCallees: return ((Callees *)functionOrCallees)->size();
}
}
SILFunction *get(unsigned index) const {
switch (kind) {
case Kind::empty: llvm_unreachable("empty callee list");
case Kind::singleFunction: return (SILFunction *)functionOrCallees;
case Kind::multipleCallees: return ((Callees *)functionOrCallees)->operator[](index);
}
}
bool isIncomplete() const { return incomplete; } bool isIncomplete() const { return incomplete; }
/// Returns true if all callees are known and not external. /// Returns true if all callees are known and not external.

View File

@@ -14,71 +14,400 @@
#define SWIFT_SILOPTIMIZER_OPTIMIZERBRIDGING_H #define SWIFT_SILOPTIMIZER_OPTIMIZERBRIDGING_H
#include "swift/SIL/SILBridging.h" #include "swift/SIL/SILBridging.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
#include "swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
typedef struct { struct BridgedPassContext;
struct BridgedAliasAnalysis {
swift::AliasAnalysis * _Nonnull aa;
swift::MemoryBehavior getMemBehavior(BridgedInstruction inst, BridgedValue addr) const {
return aa->computeMemoryBehavior(inst.getInst(), addr.getSILValue());
}
typedef swift::MemoryBehavior (* _Nonnull GetMemEffectFn)(
BridgedPassContext context, BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull Escaping2InstFn)(
BridgedPassContext context, BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull Escaping2ValFn)(
BridgedPassContext context, BridgedValue, BridgedValue);
typedef bool (* _Nonnull Escaping2ValIntFn)(
BridgedPassContext context, BridgedValue, BridgedValue, SwiftInt);
static void registerAnalysis(GetMemEffectFn getMemEffectsFn,
Escaping2InstFn isObjReleasedFn,
Escaping2ValIntFn isAddrVisibleFromObjFn,
Escaping2ValFn mayPointToSameAddrFn);
};
struct BridgedCalleeAnalysis {
swift::BasicCalleeAnalysis * _Nonnull ca;
SWIFT_IMPORT_UNSAFE
swift::CalleeList getCallees(BridgedValue callee) const {
return ca->getCalleeListOfValue(callee.getSILValue());
}
SWIFT_IMPORT_UNSAFE
swift::CalleeList getDestructors(swift::SILType type, bool isExactType) const {
return ca->getDestructors(type, isExactType);
}
SWIFT_IMPORT_UNSAFE
static BridgedFunction getCallee(swift::CalleeList cl, SwiftInt index) {
return {cl.get(index)};
}
typedef bool (* _Nonnull IsDeinitBarrierFn)(BridgedInstruction, BridgedCalleeAnalysis bca);
typedef swift::MemoryBehavior (* _Nonnull GetMemBehvaiorFn)(
BridgedPassContext context, BridgedInstruction apply, bool observeRetains);
static void registerAnalysis(IsDeinitBarrierFn isDeinitBarrierFn,
GetMemBehvaiorFn getEffectsFn);
};
struct BridgedDeadEndBlocksAnalysis {
swift::DeadEndBlocks * _Nonnull deb;
bool isDeadEnd(BridgedBasicBlock block) const {
return deb->isDeadEnd(block.getBlock());
}
};
struct BridgedDomTree {
swift::DominanceInfo * _Nonnull di;
bool dominates(BridgedBasicBlock dominating, BridgedBasicBlock dominated) const {
return di->dominates(dominating.getBlock(), dominated.getBlock());
}
};
struct BridgedBasicBlockSet {
swift::BasicBlockSet * _Nonnull set;
bool contains(BridgedBasicBlock block) const {
return set->contains(block.getBlock());
}
bool insert(BridgedBasicBlock block) const {
return set->insert(block.getBlock());
}
void erase(BridgedBasicBlock block) const {
set->erase(block.getBlock());
}
SWIFT_IMPORT_UNSAFE
BridgedFunction getFunction() const {
return {set->getFunction()};
}
};
struct BridgedNodeSet {
swift::NodeSet * _Nonnull set;
bool containsValue(BridgedValue value) const {
return set->contains(value.getSILValue());
}
bool insertValue(BridgedValue value) const {
return set->insert(value.getSILValue());
}
void eraseValue(BridgedValue value) const {
set->erase(value.getSILValue());
}
bool containsInstruction(BridgedInstruction inst) const {
return set->contains(inst.getInst()->asSILNode());
}
bool insertInstruction(BridgedInstruction inst) const {
return set->insert(inst.getInst()->asSILNode());
}
void eraseInstruction(BridgedInstruction inst) const {
set->erase(inst.getInst()->asSILNode());
}
SWIFT_IMPORT_UNSAFE
BridgedFunction getFunction() const {
return {set->getFunction()};
}
};
struct BridgedPostDomTree {
swift::PostDominanceInfo * _Nonnull pdi;
bool postDominates(BridgedBasicBlock dominating, BridgedBasicBlock dominated) const {
return pdi->dominates(dominating.getBlock(), dominated.getBlock());
}
};
struct BridgedPassContext {
swift::SwiftPassInvocation * _Nonnull invocation;
SWIFT_IMPORT_UNSAFE
BridgedChangeNotificationHandler asNotificationHandler() const {
return {invocation};
}
// Analysis
SWIFT_IMPORT_UNSAFE
BridgedAliasAnalysis getAliasAnalysis() const {
return {invocation->getPassManager()->getAnalysis<swift::AliasAnalysis>(invocation->getFunction())};
}
SWIFT_IMPORT_UNSAFE
BridgedCalleeAnalysis getCalleeAnalysis() const {
return {invocation->getPassManager()->getAnalysis<swift::BasicCalleeAnalysis>()};
}
SWIFT_IMPORT_UNSAFE
BridgedDeadEndBlocksAnalysis getDeadEndBlocksAnalysis() const {
auto *dba = invocation->getPassManager()->getAnalysis<swift::DeadEndBlocksAnalysis>();
return {dba->get(invocation->getFunction())};
}
SWIFT_IMPORT_UNSAFE
BridgedDomTree getDomTree() const {
auto *da = invocation->getPassManager()->getAnalysis<swift::DominanceAnalysis>();
return {da->get(invocation->getFunction())};
}
SWIFT_IMPORT_UNSAFE
BridgedPostDomTree getPostDomTree() const {
auto *pda = invocation->getPassManager()->getAnalysis<swift::PostDominanceAnalysis>();
return {pda->get(invocation->getFunction())};
}
// SIL modifications
SWIFT_IMPORT_UNSAFE
BridgedBasicBlock splitBlock(BridgedInstruction bridgedInst) const {
auto *inst = bridgedInst.getInst();
auto *block = inst->getParent();
return {block->split(inst->getIterator())};
}
void eraseInstruction(BridgedInstruction inst) const {
invocation->eraseInstruction(inst.getInst());
}
void eraseBlock(BridgedBasicBlock block) const {
block.getBlock()->eraseFromParent();
}
bool tryDeleteDeadClosure(BridgedInstruction closure) const;
SWIFT_IMPORT_UNSAFE
BridgedValue getSILUndef(swift::SILType type) const {
return {swift::SILUndef::get(type, *invocation->getFunction())};
}
// Sets
SWIFT_IMPORT_UNSAFE
BridgedBasicBlockSet allocBasicBlockSet() const {
return {invocation->allocBlockSet()};
}
void freeBasicBlockSet(BridgedBasicBlockSet set) const {
invocation->freeBlockSet(set.set);
}
SWIFT_IMPORT_UNSAFE
BridgedNodeSet allocNodeSet() const {
return {invocation->allocNodeSet()};
}
void freeNodeSet(BridgedNodeSet set) const {
invocation->freeNodeSet(set.set);
}
// Stack nesting
void notifyInvalidatedStackNesting() const {
invocation->setNeedFixStackNesting(true);
}
bool getNeedFixStackNesting() const {
return invocation->getNeedFixStackNesting();
}
void fixStackNesting(BridgedFunction function) const;
// Slabs
struct Slab {
swift::FixedSizeSlabPayload * _Nullable data = nullptr;
static SwiftInt getCapacity() {
return (SwiftInt)swift::FixedSizeSlabPayload::capacity;
}
Slab(swift::FixedSizeSlab * _Nullable slab) {
if (slab) {
data = slab;
assert((void *)data == slab->dataFor<void>());
}
}
swift::FixedSizeSlab * _Nullable getSlab() const {
if (data)
return static_cast<swift::FixedSizeSlab *>(data);
return nullptr;
}
SWIFT_IMPORT_UNSAFE
Slab getNext() const {
return &*std::next(getSlab()->getIterator());
}
SWIFT_IMPORT_UNSAFE
Slab getPrevious() const {
return &*std::prev(getSlab()->getIterator());
}
};
SWIFT_IMPORT_UNSAFE
Slab allocSlab(Slab afterSlab) const {
return invocation->allocSlab(afterSlab.getSlab());
}
SWIFT_IMPORT_UNSAFE
Slab freeSlab(Slab slab) const {
return invocation->freeSlab(slab.getSlab());
}
// Access SIL module data structures
SWIFT_IMPORT_UNSAFE
OptionalBridgedFunction getFirstFunctionInModule() const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
if (mod->getFunctions().empty())
return {nullptr};
return {&*mod->getFunctions().begin()};
}
SWIFT_IMPORT_UNSAFE
static OptionalBridgedFunction getNextFunctionInModule(BridgedFunction function) {
auto *f = function.getFunction();
auto nextIter = std::next(f->getIterator());
if (nextIter == f->getModule().getFunctions().end())
return {nullptr};
return {&*nextIter};
}
struct VTableArray {
swift::SILVTable * const _Nonnull * _Nullable base;
SwiftInt count;
};
SWIFT_IMPORT_UNSAFE
VTableArray getVTables() const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
auto vTables = mod->getVTables();
return {vTables.data(), (SwiftInt)vTables.size()};
}
SWIFT_IMPORT_UNSAFE
OptionalBridgedWitnessTable getFirstWitnessTableInModule() const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
if (mod->getWitnessTables().empty())
return {nullptr};
return {&*mod->getWitnessTables().begin()};
}
SWIFT_IMPORT_UNSAFE
static OptionalBridgedWitnessTable getNextWitnessTableInModule(BridgedWitnessTable table) {
auto *t = table.table;
auto nextIter = std::next(t->getIterator());
if (nextIter == t->getModule().getWitnessTables().end())
return {nullptr};
return {&*nextIter};
}
SWIFT_IMPORT_UNSAFE
OptionalBridgedDefaultWitnessTable getFirstDefaultWitnessTableInModule() const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
if (mod->getDefaultWitnessTables().empty())
return {nullptr};
return {&*mod->getDefaultWitnessTables().begin()};
}
SWIFT_IMPORT_UNSAFE
static OptionalBridgedDefaultWitnessTable getNextDefaultWitnessTableInModule(BridgedDefaultWitnessTable table) {
auto *t = table.table;
auto nextIter = std::next(t->getIterator());
if (nextIter == t->getModule().getDefaultWitnessTables().end())
return {nullptr};
return {&*nextIter};
}
SWIFT_IMPORT_UNSAFE
OptionalBridgedFunction loadFunction(llvm::StringRef name) const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
return {mod->loadFunction(name, swift::SILModule::LinkingMode::LinkNormal)};
}
SWIFT_IMPORT_UNSAFE
swift::SubstitutionMap getContextSubstitutionMap(swift::SILType type) const {
auto *ntd = type.getASTType()->getAnyNominal();
auto *mod = invocation->getPassManager()->getModule()->getSwiftModule();
return type.getASTType()->getContextSubstitutionMap(mod, ntd);
}
// Passmanager housekeeping
void beginTransformFunction(BridgedFunction function) const {
invocation->beginTransformFunction(function.getFunction());
}
void endTransformFunction() const {
invocation->endTransformFunction();
}
bool continueWithNextSubpassRun(OptionalBridgedInstruction inst) const {
swift::SILPassManager *pm = invocation->getPassManager();
return pm->continueWithNextSubpassRun(inst.getInst(),
invocation->getFunction(),
invocation->getTransform());
}
// Options
bool enableStackProtection() const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
return mod->getOptions().EnableStackProtection;
}
bool enableMoveInoutStackProtection() const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
return mod->getOptions().EnableMoveInoutStackProtection;
}
bool enableSimplificationFor(BridgedInstruction inst) const;
};
//===----------------------------------------------------------------------===//
// Pass registration
//===----------------------------------------------------------------------===//
struct BridgedFunctionPassCtxt {
BridgedFunction function; BridgedFunction function;
BridgedPassContext passContext; BridgedPassContext passContext;
} BridgedFunctionPassCtxt; } ;
typedef struct { struct BridgedInstructionPassCtxt {
BridgedInstruction instruction; BridgedInstruction instruction;
BridgedPassContext passContext; BridgedPassContext passContext;
} BridgedInstructionPassCtxt;
typedef struct {
const BridgedVTable * _Nullable vTables;
SwiftInt count;
} BridgedVTableArray;
typedef struct {
const void * _Nonnull aliasAnalysis;
} BridgedAliasAnalysis;
typedef struct {
void * _Nullable bca;
} BridgedCalleeAnalysis;
typedef bool (* _Nonnull InstructionIsDeinitBarrierFn)(BridgedInstruction, BridgedCalleeAnalysis bca);
typedef swift::MemoryBehavior (* _Nonnull CalleeAnalysisGetMemBehvaiorFn)(
BridgedPassContext context, BridgedInstruction apply, bool observeRetains);
void CalleeAnalysis_register(InstructionIsDeinitBarrierFn isDeinitBarrierFn,
CalleeAnalysisGetMemBehvaiorFn getEffectsFn);
typedef struct {
void * _Nullable dea;
} BridgedDeadEndBlocksAnalysis;
typedef struct {
void * _Nullable dt;
} BridgedDomTree;
typedef struct {
void * _Nullable pdt;
} BridgedPostDomTree;
typedef struct {
void * _Nonnull opaquePtr;
unsigned char kind;
unsigned char incomplete;
} BridgedCalleeList;
typedef struct {
void * _Nullable bbs;
} BridgedBasicBlockSet;
typedef struct {
void * _Nullable nds;
} BridgedNodeSet;
typedef struct {
void * _Nullable data;
} BridgedSlab;
enum {
BridgedSlabCapacity = 64 * sizeof(uintptr_t)
}; };
typedef void (* _Nonnull BridgedModulePassRunFn)(BridgedPassContext); typedef void (* _Nonnull BridgedModulePassRunFn)(BridgedPassContext);
@@ -92,124 +421,6 @@ void SILPassManager_registerFunctionPass(llvm::StringRef name,
void SILCombine_registerInstructionPass(llvm::StringRef instClassName, void SILCombine_registerInstructionPass(llvm::StringRef instClassName,
BridgedInstructionPassRunFn runFn); BridgedInstructionPassRunFn runFn);
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context);
swift::MemoryBehavior AliasAnalysis_getMemBehavior(BridgedAliasAnalysis aa,
BridgedInstruction inst,
BridgedValue addr);
BridgedCalleeAnalysis PassContext_getCalleeAnalysis(BridgedPassContext context);
BridgedCalleeList CalleeAnalysis_getCallees(BridgedCalleeAnalysis calleeAnalysis,
BridgedValue callee);
BridgedCalleeList CalleeAnalysis_getDestructors(BridgedCalleeAnalysis calleeAnalysis,
swift::SILType type,
SwiftInt isExactType);
SwiftInt BridgedFunctionArray_size(BridgedCalleeList callees);
BridgedFunction BridgedFunctionArray_get(BridgedCalleeList callees,
SwiftInt index);
BridgedDeadEndBlocksAnalysis
PassContext_getDeadEndBlocksAnalysis(BridgedPassContext context);
SwiftInt DeadEndBlocksAnalysis_isDeadEnd(BridgedDeadEndBlocksAnalysis debAnalysis,
BridgedBasicBlock);
BridgedDomTree PassContext_getDomTree(BridgedPassContext context);
SwiftInt DominatorTree_dominates(BridgedDomTree domTree,
BridgedBasicBlock dominating,
BridgedBasicBlock dominated);
BridgedPostDomTree PassContext_getPostDomTree(BridgedPassContext context);
SwiftInt PostDominatorTree_postDominates(BridgedPostDomTree pdomTree,
BridgedBasicBlock dominating,
BridgedBasicBlock dominated);
typedef swift::MemoryBehavior (* _Nonnull AliasAnalysisGetMemEffectFn)(
BridgedPassContext context, BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull AliasAnalysisEscaping2InstFn)(
BridgedPassContext context, BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull AliasAnalysisEscaping2ValFn)(
BridgedPassContext context, BridgedValue, BridgedValue);
typedef bool (* _Nonnull AliasAnalysisEscaping2ValIntFn)(
BridgedPassContext context, BridgedValue, BridgedValue, SwiftInt);
void AliasAnalysis_register(AliasAnalysisGetMemEffectFn getMemEffectsFn,
AliasAnalysisEscaping2InstFn isObjReleasedFn,
AliasAnalysisEscaping2ValIntFn isAddrVisibleFromObjFn,
AliasAnalysisEscaping2ValFn mayPointToSameAddrFn);
BridgedSlab PassContext_getNextSlab(BridgedSlab slab);
BridgedSlab PassContext_getPreviousSlab(BridgedSlab slab);
BridgedSlab PassContext_allocSlab(BridgedPassContext passContext,
BridgedSlab afterSlab);
BridgedSlab PassContext_freeSlab(BridgedPassContext passContext,
BridgedSlab slab);
bool PassContext_tryDeleteDeadClosure(BridgedPassContext context, BridgedInstruction closure);
void PassContext_notifyInvalidatedStackNesting(BridgedPassContext context);
bool PassContext_getNeedFixStackNesting(BridgedPassContext context);
void PassContext_fixStackNesting(BridgedPassContext context,
BridgedFunction function);
BridgedBasicBlockSet PassContext_allocBasicBlockSet(BridgedPassContext context);
void PassContext_freeBasicBlockSet(BridgedPassContext context,
BridgedBasicBlockSet set);
SwiftInt BasicBlockSet_contains(BridgedBasicBlockSet set, BridgedBasicBlock block);
SwiftInt BasicBlockSet_insert(BridgedBasicBlockSet set, BridgedBasicBlock block);
void BasicBlockSet_erase(BridgedBasicBlockSet set, BridgedBasicBlock block);
BridgedFunction BasicBlockSet_getFunction(BridgedBasicBlockSet set);
BridgedNodeSet PassContext_allocNodeSet(BridgedPassContext context);
void PassContext_freeNodeSet(BridgedPassContext context,
BridgedNodeSet set);
SwiftInt NodeSet_containsValue(BridgedNodeSet set, BridgedValue value);
SwiftInt NodeSet_insertValue(BridgedNodeSet set, BridgedValue value);
void NodeSet_eraseValue(BridgedNodeSet set, BridgedValue value);
SwiftInt NodeSet_containsInstruction(BridgedNodeSet set, BridgedInstruction inst);
SwiftInt NodeSet_insertInstruction(BridgedNodeSet set, BridgedInstruction inst);
void NodeSet_eraseInstruction(BridgedNodeSet set, BridgedInstruction inst);
BridgedFunction NodeSet_getFunction(BridgedNodeSet set);
void AllocRefInstBase_setIsStackAllocatable(BridgedInstruction arb);
void TermInst_replaceBranchTarget(BridgedInstruction term, BridgedBasicBlock from,
BridgedBasicBlock to);
swift::SubstitutionMap
PassContext_getContextSubstitutionMap(BridgedPassContext context,
swift::SILType bridgedType);
void PassContext_beginTransformFunction(BridgedFunction function,
BridgedPassContext ctxt);
void PassContext_endTransformFunction(BridgedPassContext ctxt);
OptionalBridgedFunction
PassContext_firstFunctionInModule(BridgedPassContext context);
OptionalBridgedFunction
PassContext_nextFunctionInModule(BridgedFunction function);
BridgedVTableArray PassContext_getVTables(BridgedPassContext context);
OptionalBridgedWitnessTable
PassContext_firstWitnessTableInModule(BridgedPassContext context);
OptionalBridgedWitnessTable
PassContext_nextWitnessTableInModule(BridgedWitnessTable table);
OptionalBridgedDefaultWitnessTable
PassContext_firstDefaultWitnessTableInModule(BridgedPassContext context);
OptionalBridgedDefaultWitnessTable
PassContext_nextDefaultWitnessTableInModule(BridgedDefaultWitnessTable table);
OptionalBridgedFunction
PassContext_loadFunction(BridgedPassContext context, llvm::StringRef name);
SwiftInt SILOptions_enableStackProtection(BridgedPassContext context);
SwiftInt SILOptions_enableMoveInoutStackProtection(BridgedPassContext context);
bool SILOptions_enableSimplificationFor(BridgedInstruction inst);
BridgedValue SILUndef_get(swift::SILType type, BridgedPassContext context);
SWIFT_END_NULLABILITY_ANNOTATIONS SWIFT_END_NULLABILITY_ANNOTATIONS
#endif #endif

View File

@@ -521,10 +521,10 @@ bool AliasAnalysis::typesMayAlias(SILType T1, SILType T2,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Bridging functions. // Bridging functions.
static AliasAnalysisGetMemEffectFn getMemEffectsFunction = nullptr; static BridgedAliasAnalysis::GetMemEffectFn getMemEffectsFunction = nullptr;
static AliasAnalysisEscaping2InstFn isObjReleasedFunction = nullptr; static BridgedAliasAnalysis::Escaping2InstFn isObjReleasedFunction = nullptr;
static AliasAnalysisEscaping2ValIntFn isAddrVisibleFromObjFunction = nullptr; static BridgedAliasAnalysis::Escaping2ValIntFn isAddrVisibleFromObjFunction = nullptr;
static AliasAnalysisEscaping2ValFn canReferenceSameFieldFunction = nullptr; static BridgedAliasAnalysis::Escaping2ValFn canReferenceSameFieldFunction = nullptr;
/// The main AA entry point. Performs various analyses on V1, V2 in an attempt /// The main AA entry point. Performs various analyses on V1, V2 in an attempt
/// to disambiguate the two values. /// to disambiguate the two values.
@@ -701,21 +701,10 @@ SILAnalysis *swift::createAliasAnalysis(SILModule *M) {
// Swift Bridging // Swift Bridging
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
inline AliasAnalysis *castToAliasAnalysis(BridgedAliasAnalysis aa) { void BridgedAliasAnalysis::registerAnalysis(GetMemEffectFn getMemEffectsFn,
return const_cast<AliasAnalysis *>( Escaping2InstFn isObjReleasedFn,
static_cast<const AliasAnalysis *>(aa.aliasAnalysis)); Escaping2ValIntFn isAddrVisibleFromObjFn,
} Escaping2ValFn canReferenceSameFieldFn) {
MemoryBehavior AliasAnalysis_getMemBehavior(BridgedAliasAnalysis aa,
BridgedInstruction inst,
BridgedValue addr) {
return castToAliasAnalysis(aa)->computeMemoryBehavior(inst.getInst(), addr.getSILValue());
}
void AliasAnalysis_register(AliasAnalysisGetMemEffectFn getMemEffectsFn,
AliasAnalysisEscaping2InstFn isObjReleasedFn,
AliasAnalysisEscaping2ValIntFn isAddrVisibleFromObjFn,
AliasAnalysisEscaping2ValFn canReferenceSameFieldFn) {
getMemEffectsFunction = getMemEffectsFn; getMemEffectsFunction = getMemEffectsFn;
isObjReleasedFunction = isObjReleasedFn; isObjReleasedFunction = isObjReleasedFn;
isAddrVisibleFromObjFunction = isAddrVisibleFromObjFn; isAddrVisibleFromObjFunction = isAddrVisibleFromObjFn;

View File

@@ -336,42 +336,11 @@ void BasicCalleeAnalysis::print(llvm::raw_ostream &os) const {
// Swift Bridging // Swift Bridging
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
BridgedCalleeList CalleeAnalysis_getCallees(BridgedCalleeAnalysis calleeAnalysis, static BridgedCalleeAnalysis::IsDeinitBarrierFn instructionIsDeinitBarrierFunction;
BridgedValue callee) { static BridgedCalleeAnalysis::GetMemBehvaiorFn getMemBehvaiorFunction = nullptr;
BasicCalleeAnalysis *bca = static_cast<BasicCalleeAnalysis *>(calleeAnalysis.bca);
CalleeList cl = bca->getCalleeListOfValue(callee.getSILValue());
return {cl.getOpaquePtr(), cl.getOpaqueKind(), cl.isIncomplete()};
}
BridgedCalleeList CalleeAnalysis_getDestructors(BridgedCalleeAnalysis calleeAnalysis, void BridgedCalleeAnalysis::registerAnalysis(IsDeinitBarrierFn instructionIsDeinitBarrierFn,
SILType type, GetMemBehvaiorFn getMemBehvaiorFn) {
SwiftInt isExactType) {
BasicCalleeAnalysis *bca = static_cast<BasicCalleeAnalysis *>(calleeAnalysis.bca);
CalleeList cl = bca->getDestructors(type, isExactType != 0);
return {cl.getOpaquePtr(), cl.getOpaqueKind(), cl.isIncomplete()};
}
SwiftInt BridgedFunctionArray_size(BridgedCalleeList callees) {
CalleeList cl = CalleeList::fromOpaque(callees.opaquePtr, callees.kind,
callees.incomplete);
return cl.end() - cl.begin();
}
BridgedFunction BridgedFunctionArray_get(BridgedCalleeList callees,
SwiftInt index) {
CalleeList cl = CalleeList::fromOpaque(callees.opaquePtr, callees.kind,
callees.incomplete);
auto iter = cl.begin() + index;
assert(index >= 0 && iter < cl.end());
return {*iter};
}
static InstructionIsDeinitBarrierFn instructionIsDeinitBarrierFunction;
static CalleeAnalysisGetMemBehvaiorFn getMemBehvaiorFunction = nullptr;
void CalleeAnalysis_register(
InstructionIsDeinitBarrierFn instructionIsDeinitBarrierFn,
CalleeAnalysisGetMemBehvaiorFn getMemBehvaiorFn) {
instructionIsDeinitBarrierFunction = instructionIsDeinitBarrierFn; instructionIsDeinitBarrierFunction = instructionIsDeinitBarrierFn;
getMemBehvaiorFunction = getMemBehvaiorFn; getMemBehvaiorFunction = getMemBehvaiorFn;
} }

View File

@@ -56,13 +56,3 @@ void DeadEndBlocksAnalysis::verify(DeadEndBlocks *deBlocks) const {
SILAnalysis *swift::createDeadEndBlocksAnalysis(SILModule *) { SILAnalysis *swift::createDeadEndBlocksAnalysis(SILModule *) {
return new DeadEndBlocksAnalysis(); return new DeadEndBlocksAnalysis();
} }
//===----------------------------------------------------------------------===//
// Swift Bridging
//===----------------------------------------------------------------------===//
SwiftInt DeadEndBlocksAnalysis_isDeadEnd(BridgedDeadEndBlocksAnalysis debAnalysis,
BridgedBasicBlock block) {
auto *dea = static_cast<DeadEndBlocks *>(debAnalysis.dea);
return dea->isDeadEnd(block.getBlock());
}

View File

@@ -1256,9 +1256,6 @@ void SILPassManager::viewCallGraph() {
// SwiftPassInvocation // SwiftPassInvocation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static_assert(BridgedSlabCapacity == FixedSizeSlab::capacity,
"wrong bridged slab capacity");
FixedSizeSlab *SwiftPassInvocation::allocSlab(FixedSizeSlab *afterSlab) { FixedSizeSlab *SwiftPassInvocation::allocSlab(FixedSizeSlab *afterSlab) {
FixedSizeSlab *slab = passManager->getModule()->allocSlab(); FixedSizeSlab *slab = passManager->getModule()->allocSlab();
if (afterSlab) { if (afterSlab) {
@@ -1393,333 +1390,42 @@ void SwiftPassInvocation::endTransformFunction() {
// Swift Bridging // Swift Bridging
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
inline SwiftPassInvocation *castToPassInvocation(BridgedPassContext ctxt) { void BridgedChangeNotificationHandler::notifyChanges(Kind changeKind) const {
return const_cast<SwiftPassInvocation *>(
static_cast<const SwiftPassInvocation *>(ctxt.opaqueCtxt));
}
inline FixedSizeSlab *castToSlab(BridgedSlab slab) {
if (slab.data)
return static_cast<FixedSizeSlab *>((FixedSizeSlabPayload *)slab.data);
return nullptr;
}
inline BridgedSlab toBridgedSlab(FixedSizeSlab *slab) {
if (slab) {
FixedSizeSlabPayload *payload = slab;
assert((void *)payload == slab->dataFor<void>());
return {payload};
}
return {nullptr};
}
inline BasicBlockSet *castToBlockSet(BridgedBasicBlockSet blockSet) {
return static_cast<BasicBlockSet *>(blockSet.bbs);
}
inline NodeSet *castToNodeSet(BridgedNodeSet nodeSet) {
return static_cast<NodeSet *>(nodeSet.nds);
}
BridgedSlab PassContext_getNextSlab(BridgedSlab slab) {
return toBridgedSlab(&*std::next(castToSlab(slab)->getIterator()));
}
BridgedSlab PassContext_getPreviousSlab(BridgedSlab slab) {
return toBridgedSlab(&*std::prev(castToSlab(slab)->getIterator()));
}
BridgedSlab PassContext_allocSlab(BridgedPassContext passContext,
BridgedSlab afterSlab) {
auto *inv = castToPassInvocation(passContext);
return toBridgedSlab(inv->allocSlab(castToSlab(afterSlab)));
}
BridgedSlab PassContext_freeSlab(BridgedPassContext passContext,
BridgedSlab slab) {
auto *inv = castToPassInvocation(passContext);
return toBridgedSlab(inv->freeSlab(castToSlab(slab)));
}
SwiftInt PassContext_continueWithNextSubpassRun(BridgedPassContext passContext,
OptionalBridgedInstruction inst) {
SwiftPassInvocation *inv = castToPassInvocation(passContext);
SILInstruction *i = inst.getInst();
return inv->getPassManager()->continueWithNextSubpassRun(i,
inv->getFunction(), inv->getTransform()) ? 1: 0;
}
void PassContext_notifyChanges(BridgedPassContext passContext,
enum ChangeNotificationKind changeKind) {
SwiftPassInvocation *inv = castToPassInvocation(passContext);
switch (changeKind) { switch (changeKind) {
case instructionsChanged: case Kind::instructionsChanged:
inv->notifyChanges(SILAnalysis::InvalidationKind::Instructions); invocation->notifyChanges(SILAnalysis::InvalidationKind::Instructions);
break; break;
case callsChanged: case Kind::callsChanged:
inv->notifyChanges(SILAnalysis::InvalidationKind::CallsAndInstructions); invocation->notifyChanges(SILAnalysis::InvalidationKind::CallsAndInstructions);
break; break;
case branchesChanged: case Kind::branchesChanged:
inv->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions); invocation->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions);
break; break;
case effectsChanged: case Kind::effectsChanged:
inv->notifyChanges(SILAnalysis::InvalidationKind::Effects); invocation->notifyChanges(SILAnalysis::InvalidationKind::Effects);
break; break;
} }
} }
BridgedBasicBlock PassContext_splitBlock(BridgedInstruction bridgedInst) { bool BridgedPassContext::tryDeleteDeadClosure(BridgedInstruction closure) const {
SILInstruction *inst = bridgedInst.getInst(); return ::tryDeleteDeadClosure(closure.getAs<SingleValueInstruction>(), InstModCallbacks());
SILBasicBlock *block = inst->getParent();
return {block->split(inst->getIterator())};
} }
void PassContext_eraseInstruction(BridgedPassContext passContext, void BridgedPassContext::fixStackNesting(BridgedFunction function) const {
BridgedInstruction inst) {
castToPassInvocation(passContext)->eraseInstruction(inst.getInst());
}
void PassContext_eraseBlock(BridgedPassContext passContext,
BridgedBasicBlock block) {
block.getBlock()->eraseFromParent();
}
bool PassContext_tryDeleteDeadClosure(BridgedPassContext context, BridgedInstruction closure) {
return tryDeleteDeadClosure(closure.getAs<SingleValueInstruction>(), InstModCallbacks());
}
void PassContext_notifyInvalidatedStackNesting(BridgedPassContext context) {
castToPassInvocation(context)->setNeedFixStackNesting(true);
}
bool PassContext_getNeedFixStackNesting(BridgedPassContext context) {
return castToPassInvocation(context)->getNeedFixStackNesting();
}
void PassContext_fixStackNesting(BridgedPassContext passContext,
BridgedFunction function) {
switch (StackNesting::fixNesting(function.getFunction())) { switch (StackNesting::fixNesting(function.getFunction())) {
case StackNesting::Changes::None: case StackNesting::Changes::None:
break; break;
case StackNesting::Changes::Instructions: case StackNesting::Changes::Instructions:
PassContext_notifyChanges(passContext, instructionsChanged); invocation->notifyChanges(SILAnalysis::InvalidationKind::Instructions);
break; break;
case StackNesting::Changes::CFG: case StackNesting::Changes::CFG:
PassContext_notifyChanges(passContext, branchesChanged); invocation->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions);
break; break;
} }
castToPassInvocation(passContext)->setNeedFixStackNesting(false); invocation->setNeedFixStackNesting(false);
} }
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context) { bool BridgedPassContext::enableSimplificationFor(BridgedInstruction inst) const {
SwiftPassInvocation *invocation = castToPassInvocation(context);
SILPassManager *pm = invocation->getPassManager();
return {pm->getAnalysis<AliasAnalysis>(invocation->getFunction())};
}
BridgedCalleeAnalysis
PassContext_getCalleeAnalysis(BridgedPassContext context) {
SILPassManager *pm = castToPassInvocation(context)->getPassManager();
return {pm->getAnalysis<BasicCalleeAnalysis>()};
}
BridgedDeadEndBlocksAnalysis
PassContext_getDeadEndBlocksAnalysis(BridgedPassContext context) {
SwiftPassInvocation *invocation = castToPassInvocation(context);
SILPassManager *pm = invocation->getPassManager();
return {pm->getAnalysis<DeadEndBlocksAnalysis>(invocation->getFunction())};
}
BridgedDomTree PassContext_getDomTree(BridgedPassContext context) {
SwiftPassInvocation *invocation = castToPassInvocation(context);
SILPassManager *pm = invocation->getPassManager();
return {pm->getAnalysis<DominanceAnalysis>(invocation->getFunction())};
}
SwiftInt DominatorTree_dominates(BridgedDomTree domTree,
BridgedBasicBlock dominating,
BridgedBasicBlock dominated) {
DominanceInfo *di = static_cast<DominanceInfo *>(domTree.dt);
return di->dominates(dominating.getBlock(), dominated.getBlock()) ? 1 : 0;
}
BridgedPostDomTree PassContext_getPostDomTree(BridgedPassContext context) {
SwiftPassInvocation *invocation = castToPassInvocation(context);
SILPassManager *pm = invocation->getPassManager();
return {pm->getAnalysis<PostDominanceAnalysis>(invocation->getFunction())};
}
SwiftInt PostDominatorTree_postDominates(BridgedPostDomTree pdomTree,
BridgedBasicBlock dominating,
BridgedBasicBlock dominated) {
auto *pdi = static_cast<PostDominanceInfo *>(pdomTree.pdt);
return pdi->dominates(dominating.getBlock(), dominated.getBlock()) ? 1 : 0;
}
BridgedBasicBlockSet PassContext_allocBasicBlockSet(BridgedPassContext context) {
return {castToPassInvocation(context)->allocBlockSet()};
}
void PassContext_freeBasicBlockSet(BridgedPassContext context,
BridgedBasicBlockSet set) {
castToPassInvocation(context)->freeBlockSet(castToBlockSet(set));
}
SwiftInt BasicBlockSet_contains(BridgedBasicBlockSet set, BridgedBasicBlock block) {
return castToBlockSet(set)->contains(block.getBlock()) ? 1 : 0;
}
SwiftInt BasicBlockSet_insert(BridgedBasicBlockSet set, BridgedBasicBlock block) {
return castToBlockSet(set)->insert(block.getBlock()) ? 1 : 0;
}
void BasicBlockSet_erase(BridgedBasicBlockSet set, BridgedBasicBlock block) {
castToBlockSet(set)->erase(block.getBlock());
}
BridgedFunction BasicBlockSet_getFunction(BridgedBasicBlockSet set) {
return {castToBlockSet(set)->getFunction()};
}
BridgedNodeSet PassContext_allocNodeSet(BridgedPassContext context) {
return {castToPassInvocation(context)->allocNodeSet()};
}
void PassContext_freeNodeSet(BridgedPassContext context,
BridgedNodeSet set) {
castToPassInvocation(context)->freeNodeSet(castToNodeSet(set));
}
SwiftInt NodeSet_containsValue(BridgedNodeSet set, BridgedValue value) {
return castToNodeSet(set)->contains(value.getSILValue()) ? 1 : 0;
}
SwiftInt NodeSet_insertValue(BridgedNodeSet set, BridgedValue value) {
return castToNodeSet(set)->insert(value.getSILValue()) ? 1 : 0;
}
void NodeSet_eraseValue(BridgedNodeSet set, BridgedValue value) {
castToNodeSet(set)->erase(value.getSILValue());
}
SwiftInt NodeSet_containsInstruction(BridgedNodeSet set, BridgedInstruction inst) {
return castToNodeSet(set)->contains(inst.getInst()->asSILNode()) ? 1 : 0;
}
SwiftInt NodeSet_insertInstruction(BridgedNodeSet set, BridgedInstruction inst) {
return castToNodeSet(set)->insert(inst.getInst()->asSILNode()) ? 1 : 0;
}
void NodeSet_eraseInstruction(BridgedNodeSet set, BridgedInstruction inst) {
castToNodeSet(set)->erase(inst.getInst()->asSILNode());
}
BridgedFunction NodeSet_getFunction(BridgedNodeSet set) {
return {castToNodeSet(set)->getFunction()};
}
void AllocRefInstBase_setIsStackAllocatable(BridgedInstruction arb) {
arb.getAs<AllocRefInstBase>()->setStackAllocatable();
}
void TermInst_replaceBranchTarget(BridgedInstruction term, BridgedBasicBlock from,
BridgedBasicBlock to) {
term.getAs<TermInst>()->replaceBranchTarget(from.getBlock(), to.getBlock());
}
SubstitutionMap
PassContext_getContextSubstitutionMap(BridgedPassContext context,
SILType type) {
auto *ntd = type.getASTType()->getAnyNominal();
auto *pm = castToPassInvocation(context)->getPassManager();
auto *m = pm->getModule()->getSwiftModule();
return type.getASTType()->getContextSubstitutionMap(m, ntd);
}
void PassContext_beginTransformFunction(BridgedFunction function, BridgedPassContext ctxt) {
castToPassInvocation(ctxt)->beginTransformFunction(function.getFunction());
}
void PassContext_endTransformFunction(BridgedPassContext ctxt) {
castToPassInvocation(ctxt)->endTransformFunction();
}
OptionalBridgedFunction
PassContext_firstFunctionInModule(BridgedPassContext context) {
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
if (mod->getFunctions().empty())
return {nullptr};
return {&*mod->getFunctions().begin()};
}
OptionalBridgedFunction
PassContext_nextFunctionInModule(BridgedFunction function) {
auto *f = function.getFunction();
auto nextIter = std::next(f->getIterator());
if (nextIter == f->getModule().getFunctions().end())
return {nullptr};
return {&*nextIter};
}
BridgedVTableArray PassContext_getVTables(BridgedPassContext context) {
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
auto vTables = mod->getVTables();
return {(const BridgedVTable *)vTables.data(), (SwiftInt)vTables.size()};
}
OptionalBridgedWitnessTable
PassContext_firstWitnessTableInModule(BridgedPassContext context) {
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
if (mod->getWitnessTables().empty())
return {nullptr};
return {&*mod->getWitnessTables().begin()};
}
OptionalBridgedWitnessTable
PassContext_nextWitnessTableInModule(BridgedWitnessTable table) {
auto *t = table.table;
auto nextIter = std::next(t->getIterator());
if (nextIter == t->getModule().getWitnessTables().end())
return {nullptr};
return {&*nextIter};
}
OptionalBridgedDefaultWitnessTable
PassContext_firstDefaultWitnessTableInModule(BridgedPassContext context) {
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
if (mod->getDefaultWitnessTables().empty())
return {nullptr};
return {&*mod->getDefaultWitnessTables().begin()};
}
OptionalBridgedDefaultWitnessTable
PassContext_nextDefaultWitnessTableInModule(BridgedDefaultWitnessTable table) {
auto *t = table.table;
auto nextIter = std::next(t->getIterator());
if (nextIter == t->getModule().getDefaultWitnessTables().end())
return {nullptr};
return {&*nextIter};
}
OptionalBridgedFunction
PassContext_loadFunction(BridgedPassContext context, StringRef name) {
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
SILFunction *f = mod->loadFunction(name, SILModule::LinkingMode::LinkNormal);
return {f};
}
SwiftInt SILOptions_enableStackProtection(BridgedPassContext context) {
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
return mod->getOptions().EnableStackProtection;
}
SwiftInt SILOptions_enableMoveInoutStackProtection(BridgedPassContext context) {
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
return mod->getOptions().EnableMoveInoutStackProtection;
}
bool SILOptions_enableSimplificationFor(BridgedInstruction inst) {
// Fast-path check. // Fast-path check.
if (SimplifyInstructionTest.empty() && SILDisablePass.empty()) if (SimplifyInstructionTest.empty() && SILDisablePass.empty())
return true; return true;
@@ -1738,8 +1444,3 @@ bool SILOptions_enableSimplificationFor(BridgedInstruction inst) {
} }
return false; return false;
} }
BridgedValue SILUndef_get(SILType type, BridgedPassContext context) {
SILUndef *undef = SILUndef::get(type, *castToPassInvocation(context)->getFunction());
return {undef};
}