SIL: add var Instruction.mayCallFunction

It checks if arbitrary functions may be called by an instruction.
This can be either directly, e.g. by an `apply` instruction, or indirectly by destroying a value which might have a deinitializer which can call functions.
This commit is contained in:
Erik Eckstein
2025-11-21 18:57:04 +01:00
parent dbc50633b9
commit 2c5d8237bc

View File

@@ -143,6 +143,11 @@ public class Instruction : CustomStringConvertible, Hashable {
return bridged.mayAccessPointer()
}
/// True if arbitrary functions may be called by this instruction.
/// This can be either directly, e.g. by an `apply` instruction, or indirectly by destroying a value which
/// might have a deinitializer which can call functions.
public var mayCallFunction: Bool { false }
public final var mayLoadWeakOrUnowned: Bool {
return bridged.mayLoadWeakOrUnowned()
}
@@ -331,6 +336,8 @@ final public class StoreInst : Instruction, StoringInstruction {
public var storeOwnership: StoreOwnership {
StoreOwnership(rawValue: bridged.StoreInst_getStoreOwnership())!
}
public override var mayCallFunction: Bool { storeOwnership == .assign }
}
final public class StoreWeakInst : Instruction, StoringInstruction { }
@@ -345,6 +352,15 @@ final public class AssignInst : Instruction, StoringInstruction {
public var assignOwnership: AssignOwnership {
AssignOwnership(rawValue: bridged.AssignInst_getAssignOwnership())!
}
public override var mayCallFunction: Bool {
switch assignOwnership {
case .unknown, .reassign, .reinitialize:
true
case .initialize:
false
}
}
}
final public class AssignOrInitInst : Instruction, StoringInstruction {}
@@ -382,6 +398,7 @@ final public class CopyAddrInst : Instruction, SourceDestAddrInstruction {
bridged.CopyAddrInst_setIsInitializationOfDest(isInitializationOfDestination)
context.notifyInstructionChanged(self)
}
public override var mayCallFunction: Bool { !isInitializationOfDestination }
}
final public class ExplicitCopyAddrInst : Instruction, SourceDestAddrInstruction {
@@ -394,6 +411,7 @@ final public class ExplicitCopyAddrInst : Instruction, SourceDestAddrInstruction
public var isInitializationOfDestination: Bool {
bridged.ExplicitCopyAddrInst_isInitializationOfDest()
}
public override var mayCallFunction: Bool { !isInitializationOfDestination }
}
final public class MarkUninitializedInst : SingleValueInstruction, UnaryInstruction {
@@ -639,10 +657,12 @@ final public class RetainValueAddrInst : RefCountingInst {
}
final public class ReleaseValueAddrInst : RefCountingInst {
public override var mayCallFunction: Bool { true }
}
final public class StrongReleaseInst : RefCountingInst {
public var instance: Value { operand.value }
public override var mayCallFunction: Bool { true }
}
final public class UnownedReleaseInst : RefCountingInst {
@@ -651,10 +671,12 @@ final public class UnownedReleaseInst : RefCountingInst {
final public class ReleaseValueInst : RefCountingInst {
public var value: Value { return operand.value }
public override var mayCallFunction: Bool { true }
}
final public class UnmanagedReleaseValueInst : RefCountingInst {
public var value: Value { return operand.value }
public override var mayCallFunction: Bool { true }
}
final public class AutoreleaseValueInst : RefCountingInst {}
@@ -667,10 +689,14 @@ final public class DestroyValueInst : Instruction, UnaryInstruction {
/// end the lifetime of its operand.
/// Such `destroy_value` instructions are lowered to no-ops.
public var isDeadEnd: Bool { bridged.DestroyValueInst_isDeadEnd() }
public override var mayCallFunction: Bool { true }
}
final public class DestroyAddrInst : Instruction, UnaryInstruction {
public var destroyedAddress: Value { operand.value }
public override var mayCallFunction: Bool { true }
}
final public class EndLifetimeInst : Instruction, UnaryInstruction {}
@@ -762,6 +788,15 @@ final public class BuiltinInst : SingleValueInstruction {
public var arguments: LazyMapSequence<OperandArray, Value> {
operands.values
}
public override var mayCallFunction: Bool {
switch id {
case .Once, .OnFastPath, .Destroy, .DestroyArray, .DestroyTaskGroup, .DestroyDefaultActor, .Release:
true
default:
false
}
}
}
final public class UpcastInst : SingleValueInstruction, UnaryInstruction {
@@ -1371,6 +1406,8 @@ final public class ApplyInst : SingleValueInstruction, FullApplySite {
public typealias SpecializationInfo = BridgedGenericSpecializationInformation
public var specializationInfo: SpecializationInfo { bridged.ApplyInst_getSpecializationInfo() }
public override var mayCallFunction: Bool { true }
}
final public class FunctionExtractIsolationInst : SingleValueInstruction {}
@@ -1648,7 +1685,12 @@ final public class BeginAccessInst : SingleValueInstruction, UnaryInstruction {
case read = 1
case modify = 2
case `deinit` = 3
public func conflicts(with other: AccessKind) -> Bool {
return self != .read || other != .read
}
}
public var accessKind: AccessKind {
AccessKind(rawValue: bridged.BeginAccessInst_getAccessKind())!
}
@@ -1730,11 +1772,15 @@ final public class BeginApplyInst : MultipleValueInstruction, FullApplySite {
public var isNonThrowing: Bool { bridged.BeginApplyInst_getNonThrowing() }
public var isNonAsync: Bool { bridged.BeginApplyInst_getNonAsync() }
public override var mayCallFunction: Bool { true }
}
final public class EndApplyInst : SingleValueInstruction, UnaryInstruction {
public var token: MultipleValueInstructionResult { operand.value as! MultipleValueInstructionResult }
public var beginApply: BeginApplyInst { token.parentInstruction as! BeginApplyInst }
public override var mayCallFunction: Bool { true }
}
final public class AbortApplyInst : Instruction, UnaryInstruction {
@@ -1931,6 +1977,8 @@ final public class TryApplyInst : TermInst, FullApplySite {
public var isNonAsync: Bool { bridged.TryApplyInst_getNonAsync() }
public var specializationInfo: ApplyInst.SpecializationInfo { bridged.TryApplyInst_getSpecializationInfo() }
public override var mayCallFunction: Bool { true }
}
final public class BranchInst : TermInst {