mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SwiftCompilerSources: move SIL-related Context APIs from Optimizer to the SIL module
This commit is contained in:
@@ -102,7 +102,7 @@ private func tryConvertBoxesToStack(in function: Function, _ context: FunctionPa
|
|||||||
hoistMarkUnresolvedInsts(stackAddress: stack, checkKind: .consumableAndAssignable, context)
|
hoistMarkUnresolvedInsts(stackAddress: stack, checkKind: .consumableAndAssignable, context)
|
||||||
}
|
}
|
||||||
if !promotableBoxes.isEmpty {
|
if !promotableBoxes.isEmpty {
|
||||||
function.fixStackNesting(context)
|
context.fixStackNesting(in: function)
|
||||||
}
|
}
|
||||||
|
|
||||||
return functionsToSpecialize
|
return functionsToSpecialize
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ let autodiffClosureSpecialization = FunctionPass(name: "autodiff-closure-special
|
|||||||
}
|
}
|
||||||
|
|
||||||
if context.needFixStackNesting {
|
if context.needFixStackNesting {
|
||||||
function.fixStackNesting(context)
|
context.fixStackNesting(in: function)
|
||||||
}
|
}
|
||||||
|
|
||||||
remainingSpecializationRounds -= 1
|
remainingSpecializationRounds -= 1
|
||||||
@@ -836,7 +836,7 @@ private extension SpecializationCloner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (self.context.needFixStackNesting) {
|
if (self.context.needFixStackNesting) {
|
||||||
self.cloned.fixStackNesting(self.context)
|
self.context.fixStackNesting(in: self.cloned)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ let computeEscapeEffects = FunctionPass(name: "compute-escape-effects") {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
context.modifyEffects(in: function) { (effects: inout FunctionEffects) in
|
function.modifyEffects(context) { (effects: inout FunctionEffects) in
|
||||||
effects.escapeEffects.arguments = newEffects
|
effects.escapeEffects.arguments = newEffects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ let computeSideEffects = FunctionPass(name: "compute-side-effects") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally replace the function's side effects.
|
// Finally replace the function's side effects.
|
||||||
context.modifyEffects(in: function) { (effects: inout FunctionEffects) in
|
function.modifyEffects(context) { (effects: inout FunctionEffects) in
|
||||||
let globalEffects = function.isProgramTerminationPoint ?
|
let globalEffects = function.isProgramTerminationPoint ?
|
||||||
collectedEffects.globalEffects.forProgramTerminationPoints
|
collectedEffects.globalEffects.forProgramTerminationPoints
|
||||||
: collectedEffects.globalEffects
|
: collectedEffects.globalEffects
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ func runSimplification(on function: Function, _ context: FunctionPassContext,
|
|||||||
} while !worklist.isEmpty
|
} while !worklist.isEmpty
|
||||||
|
|
||||||
if context.needFixStackNesting {
|
if context.needFixStackNesting {
|
||||||
function.fixStackNesting(context)
|
context.fixStackNesting(in: function)
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ let stackPromotion = FunctionPass(name: "stack-promotion") {
|
|||||||
}
|
}
|
||||||
if needFixStackNesting {
|
if needFixStackNesting {
|
||||||
// Make sure that all stack allocating instructions are nested correctly.
|
// Make sure that all stack allocating instructions are nested correctly.
|
||||||
function.fixStackNesting(context)
|
context.fixStackNesting(in: function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ extension BuiltinInst : OnoneSimplifiable, SILCombineSimplifiable {
|
|||||||
case .Xor:
|
case .Xor:
|
||||||
simplifyNegation(context)
|
simplifyNegation(context)
|
||||||
default:
|
default:
|
||||||
if let literal = constantFold(context) {
|
if let literal = context.constantFold(builtin: self) {
|
||||||
uses.replaceAll(with: literal, context)
|
uses.replaceAll(with: literal, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ private extension BuiltinInst {
|
|||||||
if constantFoldStringNullPointerCheck(isEqual: isEqual, context) {
|
if constantFoldStringNullPointerCheck(isEqual: isEqual, context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let literal = constantFold(context) {
|
if let literal = context.constantFold(builtin: self) {
|
||||||
uses.replaceAll(with: literal, context)
|
uses.replaceAll(with: literal, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ private struct StackProtectionOptimization {
|
|||||||
process(instruction: inst, in: function, mustFixStackNesting: &mustFixStackNesting, context)
|
process(instruction: inst, in: function, mustFixStackNesting: &mustFixStackNesting, context)
|
||||||
}
|
}
|
||||||
if mustFixStackNesting {
|
if mustFixStackNesting {
|
||||||
function.fixStackNesting(context)
|
context.fixStackNesting(in: function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -193,15 +193,6 @@ struct FunctionPassContext : MutatingContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyEffects(in function: Function, _ body: (inout FunctionEffects) -> ()) {
|
|
||||||
notifyEffectsChanged()
|
|
||||||
function._modifyEffects(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate func notifyEffectsChanged() {
|
|
||||||
_bridged.notifyChanges(.Effects)
|
|
||||||
}
|
|
||||||
|
|
||||||
func eliminateDeadAllocations(in function: Function) -> Bool {
|
func eliminateDeadAllocations(in function: Function) -> Bool {
|
||||||
if bridgedPassContext.eliminateDeadAllocations(function.bridged) {
|
if bridgedPassContext.eliminateDeadAllocations(function.bridged) {
|
||||||
notifyInstructionsChanged()
|
notifyInstructionsChanged()
|
||||||
@@ -289,14 +280,24 @@ struct FunctionPassContext : MutatingContext {
|
|||||||
notifyInstructionsChanged()
|
notifyInstructionsChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fixStackNesting(in function: Function) {
|
||||||
|
bridgedPassContext.fixStackNesting(function.bridged)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimplifyContext : MutatingContext {
|
struct SimplifyContext : MutatingContext {
|
||||||
let _bridged: BridgedContext
|
let _bridged: BridgedContext
|
||||||
let notifyInstructionChanged: (Instruction) -> ()
|
let notifyInstructionChanged: (Instruction) -> ()
|
||||||
let preserveDebugInfo: Bool
|
let preserveDebugInfo: Bool
|
||||||
|
|
||||||
|
func constantFold(builtin: BuiltinInst) -> Value? {
|
||||||
|
bridgedPassContext.constantFoldBuiltin(builtin.bridged).value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Those Type APIs get information from IRGenModule, so they are formally not part of SIL and
|
||||||
|
// therefore need to be defined here, in the Optimizer module.
|
||||||
extension Type {
|
extension Type {
|
||||||
func getStaticSize(context: SimplifyContext) -> Int? {
|
func getStaticSize(context: SimplifyContext) -> Int? {
|
||||||
let v = context.bridgedPassContext.getStaticSize(self.bridged)
|
let v = context.bridgedPassContext.getStaticSize(self.bridged)
|
||||||
@@ -313,372 +314,3 @@ extension Type {
|
|||||||
return v == -1 ? nil : v
|
return v == -1 ? nil : v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Builder initialization
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
private extension Instruction {
|
|
||||||
/// Returns self, unless self is a meta instruction, in which case the next
|
|
||||||
/// non-meta instruction is returned. Returns nil if there are no non-meta
|
|
||||||
/// instructions in the basic block.
|
|
||||||
var nextNonMetaInstruction: Instruction? {
|
|
||||||
for inst in InstructionList(first: self) where !(inst is MetaInstruction) {
|
|
||||||
return inst
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Builder {
|
|
||||||
/// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
|
|
||||||
init(before insPnt: Instruction, location: Location, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
||||||
self.init(insertAt: .before(insPnt), location: location, context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts before `insPnt`, using `insPnt`'s next
|
|
||||||
/// non-meta instruction's location.
|
|
||||||
/// This function should be used when moving code to an unknown insert point,
|
|
||||||
/// when we want to inherit the location of the closest non-meta instruction.
|
|
||||||
/// For replacing an existing meta instruction with another, use
|
|
||||||
/// ``Builder.init(replacing:_:)``.
|
|
||||||
init(before insPnt: Instruction, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
||||||
self.init(insertAt: .before(insPnt), location: insPnt.location,
|
|
||||||
context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts _before_ `insPnt`, using the exact location of `insPnt`,
|
|
||||||
/// for the purpose of replacing that meta instruction with an equivalent instruction.
|
|
||||||
/// This function does not delete `insPnt`.
|
|
||||||
init(replacing insPnt: MetaInstruction, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
||||||
self.init(insertAt: .before(insPnt), location: insPnt.location, context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts _after_ `insPnt`, using a custom `location`.
|
|
||||||
///
|
|
||||||
/// TODO: this is usually incorrect for terminator instructions. Instead use
|
|
||||||
/// `Builder.insert(after:location:_:insertFunc)` from OptUtils.swift. Rename this to afterNonTerminator.
|
|
||||||
init(after insPnt: Instruction, location: Location, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
||||||
guard let nextInst = insPnt.next else {
|
|
||||||
fatalError("cannot insert an instruction after a block terminator.")
|
|
||||||
}
|
|
||||||
self.init(insertAt: .before(nextInst), location: location, context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts _after_ `insPnt`, using `insPnt`'s next
|
|
||||||
/// non-meta instruction's location.
|
|
||||||
///
|
|
||||||
/// TODO: this is incorrect for terminator instructions. Instead use `Builder.insert(after:location:_:insertFunc)`
|
|
||||||
/// from OptUtils.swift. Rename this to afterNonTerminator.
|
|
||||||
init(after insPnt: Instruction, _ context: some MutatingContext) {
|
|
||||||
self.init(after: insPnt, location: insPnt.location, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts at the end of `block`, using a custom `location`.
|
|
||||||
init(atEndOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: block.parentFunction)
|
|
||||||
self.init(insertAt: .atEndOf(block), location: location, context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts at the begin of `block`, using a custom `location`.
|
|
||||||
init(atBeginOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: block.parentFunction)
|
|
||||||
let firstInst = block.instructions.first!
|
|
||||||
self.init(insertAt: .before(firstInst), location: location, context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts at the begin of `block`, using the location of the first
|
|
||||||
/// non-meta instruction of `block`.
|
|
||||||
init(atBeginOf block: BasicBlock, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: block.parentFunction)
|
|
||||||
let firstInst = block.instructions.first!
|
|
||||||
self.init(insertAt: .before(firstInst),
|
|
||||||
location: firstInst.location, context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a builder which inserts instructions into an empty function, using the location of the function itself.
|
|
||||||
init(atStartOf function: Function, _ context: some MutatingContext) {
|
|
||||||
context.verifyIsTransforming(function: function)
|
|
||||||
self.init(insertAt: .atStartOf(function), location: function.location,
|
|
||||||
context.notifyInstructionChanged, context._bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(staticInitializerOf global: GlobalVariable, _ context: some MutatingContext) {
|
|
||||||
self.init(insertAt: .staticInitializer(global),
|
|
||||||
location: Location.artificialUnreachableLocation, { _ in }, context._bridged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Modifying the SIL
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
extension Undef {
|
|
||||||
static func get(type: Type, _ context: some MutatingContext) -> Undef {
|
|
||||||
context._bridged.getSILUndef(type.bridged).value as! Undef
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BasicBlock {
|
|
||||||
func addArgument(type: Type, ownership: Ownership, _ context: some MutatingContext) -> Argument {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
return bridged.addBlockArgument(type.bridged, ownership._bridged).argument
|
|
||||||
}
|
|
||||||
|
|
||||||
func addFunctionArgument(type: Type, _ context: some MutatingContext) -> FunctionArgument {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
return bridged.addFunctionArgument(type.bridged).argument as! FunctionArgument
|
|
||||||
}
|
|
||||||
|
|
||||||
func insertFunctionArgument(atPosition: Int, type: Type, ownership: Ownership, decl: ValueDecl? = nil,
|
|
||||||
_ context: some MutatingContext) -> FunctionArgument
|
|
||||||
{
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
return bridged.insertFunctionArgument(atPosition, type.bridged, ownership._bridged,
|
|
||||||
(decl as Decl?).bridged).argument as! FunctionArgument
|
|
||||||
}
|
|
||||||
|
|
||||||
func eraseArgument(at index: Int, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.eraseArgument(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
func moveAllInstructions(toBeginOf otherBlock: BasicBlock, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
context.notifyBranchesChanged()
|
|
||||||
bridged.moveAllInstructionsToBegin(otherBlock.bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
func moveAllInstructions(toEndOf otherBlock: BasicBlock, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
context.notifyBranchesChanged()
|
|
||||||
bridged.moveAllInstructionsToEnd(otherBlock.bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
func eraseAllArguments(_ context: some MutatingContext) {
|
|
||||||
// Arguments are stored in an array. We need to erase in reverse order to avoid quadratic complexity.
|
|
||||||
for argIdx in (0 ..< arguments.count).reversed() {
|
|
||||||
eraseArgument(at: argIdx, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func moveAllArguments(to otherBlock: BasicBlock, _ context: some MutatingContext) {
|
|
||||||
bridged.moveArgumentsTo(otherBlock.bridged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Argument {
|
|
||||||
func set(reborrow: Bool, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.setReborrow(reborrow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension FunctionArgument {
|
|
||||||
/// Copies the following flags from `arg`:
|
|
||||||
/// 1. noImplicitCopy
|
|
||||||
/// 2. lifetimeAnnotation
|
|
||||||
/// 3. closureCapture
|
|
||||||
/// 4. parameterPack
|
|
||||||
func copyFlags(from arg: FunctionArgument, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.copyFlags(arg.bridged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AllocRefInstBase {
|
|
||||||
func setIsStackAllocatable(_ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.AllocRefInstBase_setIsStackAllocatable()
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Sequence where Element == Operand {
|
|
||||||
func replaceAll(with replacement: Value, _ context: some MutatingContext) {
|
|
||||||
for use in self {
|
|
||||||
use.set(to: replacement, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Operand {
|
|
||||||
func set(to value: Value, _ context: some MutatingContext) {
|
|
||||||
instruction.setOperand(at: index, to: value, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
func changeOwnership(from: Ownership, to: Ownership, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.changeOwnership(from._bridged, to._bridged)
|
|
||||||
context.notifyInstructionChanged(instruction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Instruction {
|
|
||||||
func setOperand(at index : Int, to value: Value, _ context: some MutatingContext) {
|
|
||||||
if let apply = self as? FullApplySite, apply.isCallee(operand: operands[index]) {
|
|
||||||
context.notifyCallsChanged()
|
|
||||||
}
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.setOperand(index, value.bridged)
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
func move(before otherInstruction: Instruction, _ context: some MutatingContext) {
|
|
||||||
BridgedContext.moveInstructionBefore(bridged, otherInstruction.bridged)
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BuiltinInst {
|
|
||||||
func constantFold(_ context: SimplifyContext) -> Value? {
|
|
||||||
context.bridgedPassContext.constantFoldBuiltin(bridged).value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RefCountingInst {
|
|
||||||
func setAtomicity(isAtomic: Bool, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.RefCountingInst_setIsAtomic(isAtomic)
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AllocRefInst {
|
|
||||||
func setIsBare(_ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.AllocRefInst_setIsBare()
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RefElementAddrInst {
|
|
||||||
func set(isImmutable: Bool, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.RefElementAddrInst_setImmutable(isImmutable)
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension GlobalAddrInst {
|
|
||||||
func clearToken(_ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.GlobalAddrInst_clearToken()
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension GlobalValueInst {
|
|
||||||
func setIsBare(_ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.GlobalValueInst_setIsBare()
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoadInst {
|
|
||||||
func set(ownership: LoadInst.LoadOwnership, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.LoadInst_setOwnership(ownership.rawValue)
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension PointerToAddressInst {
|
|
||||||
func set(alignment: Int?, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.PointerToAddressInst_setAlignment(UInt64(alignment ?? 0))
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CopyAddrInst {
|
|
||||||
func set(isTakeOfSource: Bool, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.CopyAddrInst_setIsTakeOfSrc(isTakeOfSource)
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
func set(isInitializationOfDestination: Bool, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.CopyAddrInst_setIsInitializationOfDest(isInitializationOfDestination)
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MarkDependenceInstruction {
|
|
||||||
func resolveToNonEscaping(_ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.MarkDependenceInstruction_resolveToNonEscaping()
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
func settleToEscaping(_ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.MarkDependenceInstruction_settleToEscaping()
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeginAccessInst {
|
|
||||||
func set(accessKind: BeginAccessInst.AccessKind, context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.BeginAccess_setAccessKind(accessKind.rawValue)
|
|
||||||
context.notifyInstructionChanged(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TermInst {
|
|
||||||
func replaceBranchTarget(from fromBlock: BasicBlock, to toBlock: BasicBlock, _ context: some MutatingContext) {
|
|
||||||
context.notifyBranchesChanged()
|
|
||||||
bridged.TermInst_replaceBranchTarget(fromBlock.bridged, toBlock.bridged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ForwardingInstruction {
|
|
||||||
func setForwardingOwnership(to ownership: Ownership, _ context: some MutatingContext) {
|
|
||||||
context.notifyInstructionsChanged()
|
|
||||||
bridged.ForwardingInst_setForwardingOwnership(ownership._bridged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Function {
|
|
||||||
func set(needStackProtection: Bool, _ context: FunctionPassContext) {
|
|
||||||
context.notifyEffectsChanged()
|
|
||||||
bridged.setNeedStackProtection(needStackProtection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func set(thunkKind: ThunkKind, _ context: FunctionPassContext) {
|
|
||||||
context.notifyEffectsChanged()
|
|
||||||
switch thunkKind {
|
|
||||||
case .noThunk: bridged.setThunk(.IsNotThunk)
|
|
||||||
case .thunk: bridged.setThunk(.IsThunk)
|
|
||||||
case .reabstractionThunk: bridged.setThunk(.IsReabstractionThunk)
|
|
||||||
case .signatureOptimizedThunk: bridged.setThunk(.IsSignatureOptimizedThunk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func set(isPerformanceConstraint: Bool, _ context: FunctionPassContext) {
|
|
||||||
context.notifyEffectsChanged()
|
|
||||||
bridged.setIsPerformanceConstraint(isPerformanceConstraint)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fixStackNesting(_ context: FunctionPassContext) {
|
|
||||||
context.bridgedPassContext.fixStackNesting(bridged)
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendNewBlock(_ context: FunctionPassContext) -> BasicBlock {
|
|
||||||
context.notifyBranchesChanged()
|
|
||||||
return context._bridged.appendBlock(bridged).block
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension DeclRef {
|
|
||||||
func calleesAreStaticallyKnowable(_ context: some Context) -> Bool {
|
|
||||||
context._bridged.calleesAreStaticallyKnowable(bridged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -341,24 +341,6 @@ extension Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SingleValueInstruction {
|
|
||||||
/// Replaces all uses with `replacement` and then erases the instruction.
|
|
||||||
func replace(with replacement: Value, _ context: some MutatingContext) {
|
|
||||||
uses.replaceAll(with: replacement, context)
|
|
||||||
context.erase(instruction: self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MultipleValueInstruction {
|
|
||||||
/// Replaces all uses with the result of `replacement` and then erases the instruction.
|
|
||||||
func replace(with replacement: MultipleValueInstruction, _ context: some MutatingContext) {
|
|
||||||
for (origResult, newResult) in zip(self.results, replacement.results) {
|
|
||||||
origResult.uses.replaceAll(with: newResult, context)
|
|
||||||
}
|
|
||||||
context.erase(instruction: self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Instruction {
|
extension Instruction {
|
||||||
var isTriviallyDead: Bool {
|
var isTriviallyDead: Bool {
|
||||||
if results.contains(where: { !$0.uses.isEmpty }) {
|
if results.contains(where: { !$0.uses.isEmpty }) {
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ public class Argument : Value, Hashable {
|
|||||||
|
|
||||||
public var isReborrow: Bool { bridged.isReborrow() }
|
public var isReborrow: Bool { bridged.isReborrow() }
|
||||||
|
|
||||||
|
public func set(reborrow: Bool, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.setReborrow(reborrow)
|
||||||
|
}
|
||||||
|
|
||||||
public var isLexical: Bool { false }
|
public var isLexical: Bool { false }
|
||||||
|
|
||||||
public var decl: ValueDecl? { bridged.getDecl().getAs(ValueDecl.self) }
|
public var decl: ValueDecl? { bridged.getDecl().getAs(ValueDecl.self) }
|
||||||
@@ -83,6 +88,16 @@ final public class FunctionArgument : Argument {
|
|||||||
public var resultDependence: LifetimeDependenceConvention? {
|
public var resultDependence: LifetimeDependenceConvention? {
|
||||||
parentFunction.argumentConventions[resultDependsOn: index]
|
parentFunction.argumentConventions[resultDependsOn: index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copies the following flags from `arg`:
|
||||||
|
/// 1. noImplicitCopy
|
||||||
|
/// 2. lifetimeAnnotation
|
||||||
|
/// 3. closureCapture
|
||||||
|
/// 4. parameterPack
|
||||||
|
public func copyFlags(from arg: FunctionArgument, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.copyFlags(arg.bridged)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Phi {
|
public struct Phi {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
import Basic
|
import AST
|
||||||
import SILBridging
|
import SILBridging
|
||||||
|
|
||||||
@_semantics("arc.immortal")
|
@_semantics("arc.immortal")
|
||||||
@@ -25,8 +25,69 @@ final public class BasicBlock : CustomStringConvertible, HasShortDescription, Ha
|
|||||||
}
|
}
|
||||||
public var shortDescription: String { name }
|
public var shortDescription: String { name }
|
||||||
|
|
||||||
|
/// The index of the basic block in its function.
|
||||||
|
/// This has O(n) complexity. Only use it for debugging
|
||||||
|
public var index: Int {
|
||||||
|
for (idx, block) in parentFunction.blocks.enumerated() {
|
||||||
|
if block == self { return idx }
|
||||||
|
}
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
public var name: String { "bb\(index)" }
|
||||||
|
|
||||||
|
public static func == (lhs: BasicBlock, rhs: BasicBlock) -> Bool { lhs === rhs }
|
||||||
|
|
||||||
|
public func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(ObjectIdentifier(self))
|
||||||
|
}
|
||||||
|
|
||||||
|
public var bridged: BridgedBasicBlock { BridgedBasicBlock(SwiftObject(self)) }
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Arguments
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
public var arguments: ArgumentArray { ArgumentArray(block: self) }
|
public var arguments: ArgumentArray { ArgumentArray(block: self) }
|
||||||
|
|
||||||
|
public func addArgument(type: Type, ownership: Ownership, _ context: some MutatingContext) -> Argument {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
return bridged.addBlockArgument(type.bridged, ownership._bridged).argument
|
||||||
|
}
|
||||||
|
|
||||||
|
public func addFunctionArgument(type: Type, _ context: some MutatingContext) -> FunctionArgument {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
return bridged.addFunctionArgument(type.bridged).argument as! FunctionArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
public func insertFunctionArgument(atPosition: Int, type: Type, ownership: Ownership, decl: ValueDecl? = nil,
|
||||||
|
_ context: some MutatingContext) -> FunctionArgument
|
||||||
|
{
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
return bridged.insertFunctionArgument(atPosition, type.bridged, ownership._bridged,
|
||||||
|
(decl as Decl?).bridged).argument as! FunctionArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
public func eraseArgument(at index: Int, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.eraseArgument(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func eraseAllArguments(_ context: some MutatingContext) {
|
||||||
|
// Arguments are stored in an array. We need to erase in reverse order to avoid quadratic complexity.
|
||||||
|
for argIdx in (0 ..< arguments.count).reversed() {
|
||||||
|
eraseArgument(at: argIdx, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func moveAllArguments(to otherBlock: BasicBlock, _ context: some MutatingContext) {
|
||||||
|
bridged.moveArgumentsTo(otherBlock.bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Instructions
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
public var instructions: InstructionList {
|
public var instructions: InstructionList {
|
||||||
InstructionList(first: bridged.getFirstInst().instruction)
|
InstructionList(first: bridged.getFirstInst().instruction)
|
||||||
}
|
}
|
||||||
@@ -35,6 +96,22 @@ final public class BasicBlock : CustomStringConvertible, HasShortDescription, Ha
|
|||||||
bridged.getLastInst().instruction as! TermInst
|
bridged.getLastInst().instruction as! TermInst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func moveAllInstructions(toBeginOf otherBlock: BasicBlock, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
context.notifyBranchesChanged()
|
||||||
|
bridged.moveAllInstructionsToBegin(otherBlock.bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func moveAllInstructions(toEndOf otherBlock: BasicBlock, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
context.notifyBranchesChanged()
|
||||||
|
bridged.moveAllInstructionsToEnd(otherBlock.bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// predecessors and successors
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
public var successors: SuccessorArray { terminator.successors }
|
public var successors: SuccessorArray { terminator.successors }
|
||||||
|
|
||||||
public var predecessors: PredecessorList {
|
public var predecessors: PredecessorList {
|
||||||
@@ -76,25 +153,6 @@ final public class BasicBlock : CustomStringConvertible, HasShortDescription, Ha
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The index of the basic block in its function.
|
|
||||||
/// This has O(n) complexity. Only use it for debugging
|
|
||||||
public var index: Int {
|
|
||||||
for (idx, block) in parentFunction.blocks.enumerated() {
|
|
||||||
if block == self { return idx }
|
|
||||||
}
|
|
||||||
fatalError()
|
|
||||||
}
|
|
||||||
|
|
||||||
public var name: String { "bb\(index)" }
|
|
||||||
|
|
||||||
public static func == (lhs: BasicBlock, rhs: BasicBlock) -> Bool { lhs === rhs }
|
|
||||||
|
|
||||||
public func hash(into hasher: inout Hasher) {
|
|
||||||
hasher.combine(ObjectIdentifier(self))
|
|
||||||
}
|
|
||||||
|
|
||||||
public var bridged: BridgedBasicBlock { BridgedBasicBlock(SwiftObject(self)) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The list of instructions in a BasicBlock.
|
/// The list of instructions in a BasicBlock.
|
||||||
|
|||||||
@@ -29,6 +29,87 @@ public struct Builder {
|
|||||||
private let notificationHandler: BridgedContext
|
private let notificationHandler: BridgedContext
|
||||||
private let notifyNewInstruction: (Instruction) -> ()
|
private let notifyNewInstruction: (Instruction) -> ()
|
||||||
|
|
||||||
|
/// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
|
||||||
|
public init(before insPnt: Instruction, location: Location, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
||||||
|
self.init(insertAt: .before(insPnt), location: location, context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts before `insPnt`, using `insPnt`'s next
|
||||||
|
/// non-meta instruction's location.
|
||||||
|
/// This function should be used when moving code to an unknown insert point,
|
||||||
|
/// when we want to inherit the location of the closest non-meta instruction.
|
||||||
|
/// For replacing an existing meta instruction with another, use
|
||||||
|
/// ``Builder.init(replacing:_:)``.
|
||||||
|
public init(before insPnt: Instruction, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
||||||
|
self.init(insertAt: .before(insPnt), location: insPnt.location,
|
||||||
|
context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts _before_ `insPnt`, using the exact location of `insPnt`,
|
||||||
|
/// for the purpose of replacing that meta instruction with an equivalent instruction.
|
||||||
|
/// This function does not delete `insPnt`.
|
||||||
|
public init(replacing insPnt: MetaInstruction, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
||||||
|
self.init(insertAt: .before(insPnt), location: insPnt.location, context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts _after_ `insPnt`, using a custom `location`.
|
||||||
|
///
|
||||||
|
/// TODO: this is usually incorrect for terminator instructions. Instead use
|
||||||
|
/// `Builder.insert(after:location:_:insertFunc)` from OptUtils.swift. Rename this to afterNonTerminator.
|
||||||
|
public init(after insPnt: Instruction, location: Location, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
||||||
|
guard let nextInst = insPnt.next else {
|
||||||
|
fatalError("cannot insert an instruction after a block terminator.")
|
||||||
|
}
|
||||||
|
self.init(insertAt: .before(nextInst), location: location, context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts _after_ `insPnt`, using `insPnt`'s next
|
||||||
|
/// non-meta instruction's location.
|
||||||
|
///
|
||||||
|
/// TODO: this is incorrect for terminator instructions. Instead use `Builder.insert(after:location:_:insertFunc)`
|
||||||
|
/// from OptUtils.swift. Rename this to afterNonTerminator.
|
||||||
|
public init(after insPnt: Instruction, _ context: some MutatingContext) {
|
||||||
|
self.init(after: insPnt, location: insPnt.location, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts at the end of `block`, using a custom `location`.
|
||||||
|
public init(atEndOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: block.parentFunction)
|
||||||
|
self.init(insertAt: .atEndOf(block), location: location, context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts at the begin of `block`, using a custom `location`.
|
||||||
|
public init(atBeginOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: block.parentFunction)
|
||||||
|
let firstInst = block.instructions.first!
|
||||||
|
self.init(insertAt: .before(firstInst), location: location, context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts at the begin of `block`, using the location of the first
|
||||||
|
/// non-meta instruction of `block`.
|
||||||
|
public init(atBeginOf block: BasicBlock, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: block.parentFunction)
|
||||||
|
let firstInst = block.instructions.first!
|
||||||
|
self.init(insertAt: .before(firstInst),
|
||||||
|
location: firstInst.location, context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a builder which inserts instructions into an empty function, using the location of the function itself.
|
||||||
|
public init(atStartOf function: Function, _ context: some MutatingContext) {
|
||||||
|
context.verifyIsTransforming(function: function)
|
||||||
|
self.init(insertAt: .atStartOf(function), location: function.location,
|
||||||
|
context.notifyInstructionChanged, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(staticInitializerOf global: GlobalVariable, _ context: some MutatingContext) {
|
||||||
|
self.init(insertAt: .staticInitializer(global),
|
||||||
|
location: Location.artificialUnreachableLocation, { _ in }, context._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
/// Return 'nil' when inserting at the start of a function or in a global initializer.
|
/// Return 'nil' when inserting at the start of a function or in a global initializer.
|
||||||
public var insertionBlock: BasicBlock? {
|
public var insertionBlock: BasicBlock? {
|
||||||
switch insertionPoint {
|
switch insertionPoint {
|
||||||
@@ -70,7 +151,7 @@ public struct Builder {
|
|||||||
return instruction
|
return instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(insertAt: InsertionPoint, location: Location,
|
private init(insertAt: InsertionPoint, location: Location,
|
||||||
_ notifyNewInstruction: @escaping (Instruction) -> (),
|
_ notifyNewInstruction: @escaping (Instruction) -> (),
|
||||||
_ notificationHandler: BridgedContext) {
|
_ notificationHandler: BridgedContext) {
|
||||||
self.insertionPoint = insertAt
|
self.insertionPoint = insertAt
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ extension MutatingContext {
|
|||||||
_bridged.notifyChanges(.Branches)
|
_bridged.notifyChanges(.Branches)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func notifyEffectsChanged() {
|
||||||
|
_bridged.notifyChanges(.Effects)
|
||||||
|
}
|
||||||
|
|
||||||
public func createGlobalVariable(name: String, type: Type, linkage: Linkage, isLet: Bool) -> GlobalVariable {
|
public func createGlobalVariable(name: String, type: Type, linkage: Linkage, isLet: Bool) -> GlobalVariable {
|
||||||
let gv = name._withBridgedStringRef {
|
let gv = name._withBridgedStringRef {
|
||||||
_bridged.createGlobalVariable($0, type.bridged, linkage.bridged, isLet)
|
_bridged.createGlobalVariable($0, type.bridged, linkage.bridged, isLet)
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ public struct DeclRef: CustomStringConvertible, NoReflectionChildren {
|
|||||||
public static func ==(lhs: DeclRef, rhs: DeclRef) -> Bool {
|
public static func ==(lhs: DeclRef, rhs: DeclRef) -> Bool {
|
||||||
lhs.bridged.isEqualTo(rhs.bridged)
|
lhs.bridged.isEqualTo(rhs.bridged)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do we have enough information to determine all callees that could
|
||||||
|
/// be reached by calling the function represented by Decl?
|
||||||
|
public func calleesAreStaticallyKnowable(_ context: some Context) -> Bool {
|
||||||
|
context._bridged.calleesAreStaticallyKnowable(bridged)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DeclRef: DiagnosticArgument {
|
extension DeclRef: DiagnosticArgument {
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ extension ForwardingInstruction {
|
|||||||
Ownership(bridged: bridged.ForwardingInst_forwardingOwnership())
|
Ownership(bridged: bridged.ForwardingInst_forwardingOwnership())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func setForwardingOwnership(to ownership: Ownership, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.ForwardingInst_setForwardingOwnership(ownership._bridged)
|
||||||
|
}
|
||||||
|
|
||||||
/// A forwarding instruction preserves reference counts if it has a dynamically non-trivial result in which all references are forwarded from the operand.
|
/// A forwarding instruction preserves reference counts if it has a dynamically non-trivial result in which all references are forwarded from the operand.
|
||||||
///
|
///
|
||||||
/// A cast can only forward guaranteed values if it preserves reference counts. Such casts cannot release any references within their operand's value and cannot retain any references owned by their result.
|
/// A cast can only forward guaranteed values if it preserves reference counts. Such casts cannot release any references within their operand's value and cannot retain any references owned by their result.
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
|
|||||||
|
|
||||||
public var entryBlock: BasicBlock { blocks.first! }
|
public var entryBlock: BasicBlock { blocks.first! }
|
||||||
|
|
||||||
|
public func appendNewBlock(_ context: some MutatingContext) -> BasicBlock {
|
||||||
|
context.notifyBranchesChanged()
|
||||||
|
return context._bridged.appendBlock(bridged).block
|
||||||
|
}
|
||||||
|
|
||||||
public var arguments: LazyMapSequence<ArgumentArray, FunctionArgument> {
|
public var arguments: LazyMapSequence<ArgumentArray, FunctionArgument> {
|
||||||
entryBlock.arguments.lazy.map { $0 as! FunctionArgument }
|
entryBlock.arguments.lazy.map { $0 as! FunctionArgument }
|
||||||
}
|
}
|
||||||
@@ -242,6 +247,15 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
|
|||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public func set(thunkKind: ThunkKind, _ context: some MutatingContext) {
|
||||||
|
context.notifyEffectsChanged()
|
||||||
|
switch thunkKind {
|
||||||
|
case .noThunk: bridged.setThunk(.IsNotThunk)
|
||||||
|
case .thunk: bridged.setThunk(.IsThunk)
|
||||||
|
case .reabstractionThunk: bridged.setThunk(.IsReabstractionThunk)
|
||||||
|
case .signatureOptimizedThunk: bridged.setThunk(.IsSignatureOptimizedThunk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var accessorKindName: String? {
|
public var accessorKindName: String? {
|
||||||
guard bridged.isAccessor() else {
|
guard bridged.isAccessor() else {
|
||||||
@@ -260,6 +274,10 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
|
|||||||
public var needsStackProtection: Bool {
|
public var needsStackProtection: Bool {
|
||||||
bridged.needsStackProtection()
|
bridged.needsStackProtection()
|
||||||
}
|
}
|
||||||
|
public func set(needStackProtection: Bool, _ context: some MutatingContext) {
|
||||||
|
context.notifyEffectsChanged()
|
||||||
|
bridged.setNeedStackProtection(needStackProtection)
|
||||||
|
}
|
||||||
|
|
||||||
public var isDeinitBarrier: Bool {
|
public var isDeinitBarrier: Bool {
|
||||||
effects.sideEffects?.global.isDeinitBarrier ?? true
|
effects.sideEffects?.global.isDeinitBarrier ?? true
|
||||||
@@ -285,6 +303,10 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
|
|||||||
default: fatalError("unknown performance constraint")
|
default: fatalError("unknown performance constraint")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public func set(isPerformanceConstraint: Bool, _ context: some MutatingContext) {
|
||||||
|
context.notifyEffectsChanged()
|
||||||
|
bridged.setIsPerformanceConstraint(isPerformanceConstraint)
|
||||||
|
}
|
||||||
|
|
||||||
public enum InlineStrategy {
|
public enum InlineStrategy {
|
||||||
case automatic
|
case automatic
|
||||||
@@ -460,8 +482,8 @@ extension Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only to be called by PassContext
|
public func modifyEffects(_ context: some MutatingContext, _ body: (inout FunctionEffects) -> ()) {
|
||||||
public func _modifyEffects(_ body: (inout FunctionEffects) -> ()) {
|
context.notifyEffectsChanged()
|
||||||
body(&effects)
|
body(&effects)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,15 @@ public class Instruction : CustomStringConvertible, Hashable {
|
|||||||
return allOperands[(allOperands.count - typeOperands.count) ..< allOperands.count]
|
return allOperands[(allOperands.count - typeOperands.count) ..< allOperands.count]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final func setOperand(at index : Int, to value: Value, _ context: some MutatingContext) {
|
||||||
|
if let apply = self as? FullApplySite, apply.isCallee(operand: operands[index]) {
|
||||||
|
context.notifyCallsChanged()
|
||||||
|
}
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.setOperand(index, value.bridged)
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate var resultCount: Int { 0 }
|
fileprivate var resultCount: Int { 0 }
|
||||||
fileprivate func getResult(index: Int) -> Value { fatalError() }
|
fileprivate func getResult(index: Int) -> Value { fatalError() }
|
||||||
|
|
||||||
@@ -83,6 +92,11 @@ public class Instruction : CustomStringConvertible, Hashable {
|
|||||||
return Location(bridged: bridged.getLocation())
|
return Location(bridged: bridged.getLocation())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final func move(before otherInstruction: Instruction, _ context: some MutatingContext) {
|
||||||
|
BridgedContext.moveInstructionBefore(bridged, otherInstruction.bridged)
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
}
|
||||||
|
|
||||||
public var mayTrap: Bool { false }
|
public var mayTrap: Bool { false }
|
||||||
|
|
||||||
final public var mayHaveSideEffects: Bool {
|
final public var mayHaveSideEffects: Bool {
|
||||||
@@ -206,6 +220,12 @@ public class SingleValueInstruction : Instruction, Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var isLexical: Bool { false }
|
public var isLexical: Bool { false }
|
||||||
|
|
||||||
|
/// Replaces all uses with `replacement` and then erases the instruction.
|
||||||
|
public final func replace(with replacement: Value, _ context: some MutatingContext) {
|
||||||
|
uses.replaceAll(with: replacement, context)
|
||||||
|
context.erase(instruction: self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class MultipleValueInstructionResult : Value, Hashable {
|
public final class MultipleValueInstructionResult : Value, Hashable {
|
||||||
@@ -247,6 +267,14 @@ public class MultipleValueInstruction : Instruction {
|
|||||||
fileprivate final override func getResult(index: Int) -> Value {
|
fileprivate final override func getResult(index: Int) -> Value {
|
||||||
bridged.MultipleValueInstruction_getResult(index).result
|
bridged.MultipleValueInstruction_getResult(index).result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces all uses with the result of `replacement` and then erases the instruction.
|
||||||
|
public final func replace(with replacement: MultipleValueInstruction, _ context: some MutatingContext) {
|
||||||
|
for (origResult, newResult) in zip(self.results, replacement.results) {
|
||||||
|
origResult.uses.replaceAll(with: newResult, context)
|
||||||
|
}
|
||||||
|
context.erase(instruction: self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instructions, which have a single operand (not including type-dependent operands).
|
/// Instructions, which have a single operand (not including type-dependent operands).
|
||||||
@@ -333,9 +361,20 @@ final public class CopyAddrInst : Instruction, SourceDestAddrInstruction {
|
|||||||
public var isTakeOfSource: Bool {
|
public var isTakeOfSource: Bool {
|
||||||
bridged.CopyAddrInst_isTakeOfSrc()
|
bridged.CopyAddrInst_isTakeOfSrc()
|
||||||
}
|
}
|
||||||
|
public func set(isTakeOfSource: Bool, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.CopyAddrInst_setIsTakeOfSrc(isTakeOfSource)
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
|
|
||||||
public var isInitializationOfDestination: Bool {
|
public var isInitializationOfDestination: Bool {
|
||||||
bridged.CopyAddrInst_isInitializationOfDest()
|
bridged.CopyAddrInst_isInitializationOfDest()
|
||||||
}
|
}
|
||||||
|
public func set(isInitializationOfDestination: Bool, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.CopyAddrInst_setIsInitializationOfDest(isInitializationOfDestination)
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class ExplicitCopyAddrInst : Instruction, SourceDestAddrInstruction {
|
final public class ExplicitCopyAddrInst : Instruction, SourceDestAddrInstruction {
|
||||||
@@ -563,6 +602,12 @@ final public class RebindMemoryInst : SingleValueInstruction {}
|
|||||||
|
|
||||||
public class RefCountingInst : Instruction, UnaryInstruction {
|
public class RefCountingInst : Instruction, UnaryInstruction {
|
||||||
public var isAtomic: Bool { bridged.RefCountingInst_getIsAtomic() }
|
public var isAtomic: Bool { bridged.RefCountingInst_getIsAtomic() }
|
||||||
|
|
||||||
|
public final func setAtomicity(isAtomic: Bool, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.RefCountingInst_setIsAtomic(isAtomic)
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class StrongRetainInst : RefCountingInst {
|
final public class StrongRetainInst : RefCountingInst {
|
||||||
@@ -675,6 +720,11 @@ final public class LoadInst : SingleValueInstruction, LoadInstruction {
|
|||||||
public var loadOwnership: LoadOwnership {
|
public var loadOwnership: LoadOwnership {
|
||||||
LoadOwnership(rawValue: bridged.LoadInst_getLoadOwnership())!
|
LoadOwnership(rawValue: bridged.LoadInst_getLoadOwnership())!
|
||||||
}
|
}
|
||||||
|
public func set(ownership: LoadInst.LoadOwnership, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.LoadInst_setOwnership(ownership.rawValue)
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class LoadWeakInst : SingleValueInstruction, LoadInstruction {}
|
final public class LoadWeakInst : SingleValueInstruction, LoadInstruction {}
|
||||||
@@ -763,6 +813,11 @@ class PointerToAddressInst : SingleValueInstruction, UnaryInstruction {
|
|||||||
}
|
}
|
||||||
return Int(exactly: maybeAlign)
|
return Int(exactly: maybeAlign)
|
||||||
}
|
}
|
||||||
|
public func set(alignment: Int?, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.PointerToAddressInst_setAlignment(UInt64(alignment ?? 0))
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol IndexingInstruction: SingleValueInstruction {
|
public protocol IndexingInstruction: SingleValueInstruction {
|
||||||
@@ -896,10 +951,22 @@ final public class GlobalAddrInst : GlobalAccessInstruction, VarDeclInstruction
|
|||||||
public var dependencyToken: Value? {
|
public var dependencyToken: Value? {
|
||||||
operands.count == 1 ? operands[0].value : nil
|
operands.count == 1 ? operands[0].value : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func clearToken(_ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.GlobalAddrInst_clearToken()
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class GlobalValueInst : GlobalAccessInstruction {
|
final public class GlobalValueInst : GlobalAccessInstruction {
|
||||||
public var isBare: Bool { bridged.GlobalValueInst_isBare() }
|
public var isBare: Bool { bridged.GlobalValueInst_isBare() }
|
||||||
|
|
||||||
|
public func setIsBare(_ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.GlobalValueInst_setIsBare()
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class BaseAddrForOffsetInst : SingleValueInstruction {}
|
final public class BaseAddrForOffsetInst : SingleValueInstruction {}
|
||||||
@@ -1016,6 +1083,12 @@ final public class RefElementAddrInst : SingleValueInstruction, UnaryInstruction
|
|||||||
|
|
||||||
public var isImmutable: Bool { bridged.RefElementAddrInst_isImmutable() }
|
public var isImmutable: Bool { bridged.RefElementAddrInst_isImmutable() }
|
||||||
|
|
||||||
|
public func set(isImmutable: Bool, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.RefElementAddrInst_setImmutable(isImmutable)
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
|
|
||||||
public var varDecl: VarDecl? {
|
public var varDecl: VarDecl? {
|
||||||
bridged.RefElementAddr_getDecl().getAs(VarDecl.self)
|
bridged.RefElementAddr_getDecl().getAs(VarDecl.self)
|
||||||
}
|
}
|
||||||
@@ -1127,6 +1200,17 @@ extension MarkDependenceInstruction {
|
|||||||
public var valueOrAddress: Value { valueOrAddressOperand.value }
|
public var valueOrAddress: Value { valueOrAddressOperand.value }
|
||||||
public var baseOperand: Operand { operands[1] }
|
public var baseOperand: Operand { operands[1] }
|
||||||
public var base: Value { baseOperand.value }
|
public var base: Value { baseOperand.value }
|
||||||
|
|
||||||
|
public func resolveToNonEscaping(_ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.MarkDependenceInstruction_resolveToNonEscaping()
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
|
public func settleToEscaping(_ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.MarkDependenceInstruction_settleToEscaping()
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class MarkDependenceInst : SingleValueInstruction, MarkDependenceInstruction {
|
final public class MarkDependenceInst : SingleValueInstruction, MarkDependenceInstruction {
|
||||||
@@ -1404,6 +1488,12 @@ public class AllocRefInstBase : SingleValueInstruction, Allocation {
|
|||||||
bridged.AllocRefInstBase_canAllocOnStack()
|
bridged.AllocRefInstBase_canAllocOnStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final func setIsStackAllocatable(_ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.AllocRefInstBase_setIsStackAllocatable()
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
|
|
||||||
final public var tailAllocatedCounts: OperandArray {
|
final public var tailAllocatedCounts: OperandArray {
|
||||||
let numTailTypes = bridged.AllocRefInstBase_getNumTailTypes()
|
let numTailTypes = bridged.AllocRefInstBase_getNumTailTypes()
|
||||||
return operands[0..<numTailTypes]
|
return operands[0..<numTailTypes]
|
||||||
@@ -1416,6 +1506,12 @@ public class AllocRefInstBase : SingleValueInstruction, Allocation {
|
|||||||
|
|
||||||
final public class AllocRefInst : AllocRefInstBase {
|
final public class AllocRefInst : AllocRefInstBase {
|
||||||
public var isBare: Bool { bridged.AllocRefInst_isBare() }
|
public var isBare: Bool { bridged.AllocRefInst_isBare() }
|
||||||
|
|
||||||
|
public func setIsBare(_ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.AllocRefInst_setIsBare()
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class AllocRefDynamicInst : AllocRefInstBase {
|
final public class AllocRefDynamicInst : AllocRefInstBase {
|
||||||
@@ -1530,6 +1626,11 @@ final public class BeginAccessInst : SingleValueInstruction, UnaryInstruction {
|
|||||||
public var accessKind: AccessKind {
|
public var accessKind: AccessKind {
|
||||||
AccessKind(rawValue: bridged.BeginAccessInst_getAccessKind())!
|
AccessKind(rawValue: bridged.BeginAccessInst_getAccessKind())!
|
||||||
}
|
}
|
||||||
|
public func set(accessKind: BeginAccessInst.AccessKind, context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.BeginAccess_setAccessKind(accessKind.rawValue)
|
||||||
|
context.notifyInstructionChanged(self)
|
||||||
|
}
|
||||||
|
|
||||||
public var isStatic: Bool { bridged.BeginAccessInst_isStatic() }
|
public var isStatic: Bool { bridged.BeginAccessInst_isStatic() }
|
||||||
public var isUnsafe: Bool { bridged.BeginAccessInst_isUnsafe() }
|
public var isUnsafe: Bool { bridged.BeginAccessInst_isUnsafe() }
|
||||||
@@ -1691,6 +1792,11 @@ public class TermInst : Instruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var isFunctionExiting: Bool { false }
|
public var isFunctionExiting: Bool { false }
|
||||||
|
|
||||||
|
public final func replaceBranchTarget(from fromBlock: BasicBlock, to toBlock: BasicBlock, _ context: some MutatingContext) {
|
||||||
|
context.notifyBranchesChanged()
|
||||||
|
bridged.TermInst_replaceBranchTarget(fromBlock.bridged, toBlock.bridged)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final public class UnreachableInst : TermInst {
|
final public class UnreachableInst : TermInst {
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ public struct Operand : CustomStringConvertible, NoReflectionChildren, Equatable
|
|||||||
|
|
||||||
public var value: Value { bridged.getValue().value }
|
public var value: Value { bridged.getValue().value }
|
||||||
|
|
||||||
|
public func set(to value: Value, _ context: some MutatingContext) {
|
||||||
|
instruction.setOperand(at: index, to: value, context)
|
||||||
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Operand, rhs: Operand) -> Bool {
|
public static func ==(lhs: Operand, rhs: Operand) -> Bool {
|
||||||
return lhs.bridged.op == rhs.bridged.op
|
return lhs.bridged.op == rhs.bridged.op
|
||||||
}
|
}
|
||||||
@@ -45,6 +49,12 @@ public struct Operand : CustomStringConvertible, NoReflectionChildren, Equatable
|
|||||||
|
|
||||||
public func canAccept(ownership: Ownership) -> Bool { bridged.canAcceptOwnership(ownership._bridged) }
|
public func canAccept(ownership: Ownership) -> Bool { bridged.canAcceptOwnership(ownership._bridged) }
|
||||||
|
|
||||||
|
public func changeOwnership(from: Ownership, to: Ownership, _ context: some MutatingContext) {
|
||||||
|
context.notifyInstructionsChanged()
|
||||||
|
bridged.changeOwnership(from._bridged, to._bridged)
|
||||||
|
context.notifyInstructionChanged(instruction)
|
||||||
|
}
|
||||||
|
|
||||||
public var description: String { "operand #\(index) of \(instruction)" }
|
public var description: String { "operand #\(index) of \(instruction)" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +195,12 @@ extension Sequence where Element == Operand {
|
|||||||
public func users<I: Instruction>(ofType: I.Type) -> LazyMapSequence<LazyFilterSequence<Self>, I> {
|
public func users<I: Instruction>(ofType: I.Type) -> LazyMapSequence<LazyFilterSequence<Self>, I> {
|
||||||
self.lazy.filter{ $0.instruction is I }.lazy.map { $0.instruction as! I }
|
self.lazy.filter{ $0.instruction is I }.lazy.map { $0.instruction as! I }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func replaceAll(with replacement: Value, _ context: some MutatingContext) {
|
||||||
|
for use in self {
|
||||||
|
use.set(to: replacement, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Value {
|
extension Value {
|
||||||
|
|||||||
@@ -298,6 +298,10 @@ public final class Undef : Value {
|
|||||||
public var hasTrivialNonPointerType: Bool { false }
|
public var hasTrivialNonPointerType: Bool { false }
|
||||||
|
|
||||||
public var isLexical: Bool { false }
|
public var isLexical: Bool { false }
|
||||||
|
|
||||||
|
public static func get(type: Type, _ context: some MutatingContext) -> Undef {
|
||||||
|
context._bridged.getSILUndef(type.bridged).value as! Undef
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class PlaceholderValue : Value {
|
final class PlaceholderValue : Value {
|
||||||
|
|||||||
Reference in New Issue
Block a user