Swift SIL: add some instruction classes and APIs

* add `UnownedRetainInst` and `UnownedReleaseInst`
* add `var value` to `RetainValueInst` and `ReleaseValueInst`
* make the protocol `UnaryInstruction` be an `Instruction`
* add `var Type.isValueTypeWithDeinit`
* add `var Type.isUnownedStorageType`
* add `var OperandArray.values`
This commit is contained in:
Erik Eckstein
2023-06-06 19:12:47 +02:00
parent ae9a0c1007
commit 5325a4fe21
9 changed files with 65 additions and 2 deletions

View File

@@ -80,7 +80,7 @@ extension ApplySite {
/// ///
/// This does not include the callee function operand. /// This does not include the callee function operand.
public var arguments: LazyMapSequence<OperandArray, Value> { public var arguments: LazyMapSequence<OperandArray, Value> {
argumentOperands.lazy.map { $0.value } argumentOperands.values
} }
public var substitutionMap: SubstitutionMap { public var substitutionMap: SubstitutionMap {

View File

@@ -136,6 +136,18 @@ public struct Builder {
return notifyNew(release.getAs(StrongReleaseInst.self)) return notifyNew(release.getAs(StrongReleaseInst.self))
} }
@discardableResult
public func createUnownedRetain(operand: Value) -> UnownedRetainInst {
let retain = bridged.createUnownedRetain(operand.bridged)
return notifyNew(retain.getAs(UnownedRetainInst.self))
}
@discardableResult
public func createUnownedRelease(operand: Value) -> UnownedReleaseInst {
let release = bridged.createUnownedRelease(operand.bridged)
return notifyNew(release.getAs(UnownedReleaseInst.self))
}
public func createFunctionRef(_ function: Function) -> FunctionRefInst { public func createFunctionRef(_ function: Function) -> FunctionRefInst {
let functionRef = bridged.createFunctionRef(function.bridged) let functionRef = bridged.createFunctionRef(function.bridged)
return notifyNew(functionRef.getAs(FunctionRefInst.self)) return notifyNew(functionRef.getAs(FunctionRefInst.self))

View File

@@ -197,7 +197,7 @@ public class MultipleValueInstruction : Instruction {
} }
/// Instructions, which have a single operand. /// Instructions, which have a single operand.
public protocol UnaryInstruction : AnyObject { public protocol UnaryInstruction : Instruction {
var operands: OperandArray { get } var operands: OperandArray { get }
var operand: Operand { get } var operand: Operand { get }
} }
@@ -306,14 +306,24 @@ final public class StrongRetainInst : RefCountingInst {
public var instance: Value { operand.value } public var instance: Value { operand.value }
} }
final public class UnownedRetainInst : RefCountingInst {
public var instance: Value { operand.value }
}
final public class RetainValueInst : RefCountingInst { final public class RetainValueInst : RefCountingInst {
public var value: Value { return operand.value }
} }
final public class StrongReleaseInst : RefCountingInst { final public class StrongReleaseInst : RefCountingInst {
public var instance: Value { operand.value } public var instance: Value { operand.value }
} }
final public class UnownedReleaseInst : RefCountingInst {
public var instance: Value { operand.value }
}
final public class ReleaseValueInst : RefCountingInst { final public class ReleaseValueInst : RefCountingInst {
public var value: Value { return operand.value }
} }
final public class DestroyValueInst : Instruction, UnaryInstruction { final public class DestroyValueInst : Instruction, UnaryInstruction {

View File

@@ -76,6 +76,10 @@ public struct OperandArray : RandomAccessCollection, CustomReflectable {
base: OptionalBridgedOperand(op: base.advancedBy(bounds.lowerBound).op), base: OptionalBridgedOperand(op: base.advancedBy(bounds.lowerBound).op),
count: bounds.upperBound - bounds.lowerBound) count: bounds.upperBound - bounds.lowerBound)
} }
public var values: LazyMapSequence<LazySequence<OperandArray>.Elements, Value> {
self.lazy.map { $0.value }
}
} }
public struct UseList : CollectionLikeSequence { public struct UseList : CollectionLikeSequence {

View File

@@ -54,8 +54,10 @@ public func registerSILClasses() {
register(EndApplyInst.self) register(EndApplyInst.self)
register(AbortApplyInst.self) register(AbortApplyInst.self)
register(StrongRetainInst.self) register(StrongRetainInst.self)
register(UnownedRetainInst.self)
register(RetainValueInst.self) register(RetainValueInst.self)
register(StrongReleaseInst.self) register(StrongReleaseInst.self)
register(UnownedReleaseInst.self)
register(ReleaseValueInst.self) register(ReleaseValueInst.self)
register(DestroyValueInst.self) register(DestroyValueInst.self)
register(DestroyAddrInst.self) register(DestroyAddrInst.self)

View File

@@ -31,6 +31,10 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
return !bridged.isNonTrivialOrContainsRawPointer(function.bridged.getFunction()) return !bridged.isNonTrivialOrContainsRawPointer(function.bridged.getFunction())
} }
/// True if this type is a value type (struct/enum) that requires deinitialization beyond
/// destruction of its members.
public var isValueTypeWithDeinit: Bool { bridged.isValueTypeWithDeinit() }
public func isLoadable(in function: Function) -> Bool { public func isLoadable(in function: Function) -> Bool {
return bridged.isLoadable(function.bridged.getFunction()) return bridged.isLoadable(function.bridged.getFunction())
} }
@@ -39,6 +43,10 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
return bridged.isReferenceCounted(function.bridged.getFunction()) return bridged.isReferenceCounted(function.bridged.getFunction())
} }
public var isUnownedStorageType: Bool {
return bridged.isUnownedStorageType()
}
public var hasArchetype: Bool { bridged.hasArchetype() } public var hasArchetype: Bool { bridged.hasArchetype() }
public var isNominal: Bool { bridged.getNominalOrBoundGenericNominal() != nil } public var isNominal: Bool { bridged.getNominalOrBoundGenericNominal() != nil }

View File

@@ -1105,6 +1105,18 @@ struct BridgedBuilder{
return {b.createStrongRelease(regularLoc(), op.getSILValue(), b.getDefaultAtomicity())}; return {b.createStrongRelease(regularLoc(), op.getSILValue(), b.getDefaultAtomicity())};
} }
SWIFT_IMPORT_UNSAFE
BridgedInstruction createUnownedRetain(BridgedValue op) const {
auto b = builder();
return {b.createUnownedRetain(regularLoc(), op.getSILValue(), b.getDefaultAtomicity())};
}
SWIFT_IMPORT_UNSAFE
BridgedInstruction createUnownedRelease(BridgedValue op) const {
auto b = builder();
return {b.createUnownedRelease(regularLoc(), op.getSILValue(), b.getDefaultAtomicity())};
}
SWIFT_IMPORT_UNSAFE SWIFT_IMPORT_UNSAFE
BridgedInstruction createFunctionRef(BridgedFunction function) const { BridgedInstruction createFunctionRef(BridgedFunction function) const {
return {builder().createFunctionRef(regularLoc(), function.getFunction())}; return {builder().createFunctionRef(regularLoc(), function.getFunction())};

View File

@@ -394,6 +394,8 @@ public:
bool isReferenceCounted(SILFunction *f) const; bool isReferenceCounted(SILFunction *f) const;
bool isUnownedStorageType() const { return is<UnownedStorageType>(); }
/// Returns true if the referenced type is a function type that never /// Returns true if the referenced type is a function type that never
/// returns. /// returns.
bool isNoReturnFunction(SILModule &M, TypeExpansionContext context) const; bool isNoReturnFunction(SILModule &M, TypeExpansionContext context) const;
@@ -745,6 +747,10 @@ public:
/// for a move only wrapped type. /// for a move only wrapped type.
bool isPureMoveOnly() const; bool isPureMoveOnly() const;
/// Return true if this is a value type (struct/enum) that requires
/// deinitialization beyond destruction of its members.
bool isValueTypeWithDeinit() const;
/// Returns true if and only if this type is a first class move only /// Returns true if and only if this type is a first class move only
/// type. NOTE: Returns false if the type is a move only wrapped type. /// type. NOTE: Returns false if the type is a move only wrapped type.
bool isMoveOnlyNominalType() const; bool isMoveOnlyNominalType() const;

View File

@@ -1048,6 +1048,15 @@ bool SILType::isPureMoveOnly() const {
return false; return false;
} }
bool SILType::isValueTypeWithDeinit() const {
// Do not look inside an aggregate type that has a user-deinit, for which
// memberwise-destruction is not equivalent to aggregate destruction.
if (auto *nominal = getNominalOrBoundGenericNominal()) {
return nominal->getValueTypeDestructor() != nullptr;
}
return false;
}
SILType SILType::getInstanceTypeOfMetatype(SILFunction *function) const { SILType SILType::getInstanceTypeOfMetatype(SILFunction *function) const {
auto metaType = castTo<MetatypeType>(); auto metaType = castTo<MetatypeType>();
CanType instanceTy = metaType.getInstanceType(); CanType instanceTy = metaType.getInstanceType();