Skip to content

Commit 139c573

Browse files
committed
SwiftCompilerSources: add OperandOwnership enum.
1 parent 1f7bfd8 commit 139c573

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed

SwiftCompilerSources/Sources/SIL/Operand.swift

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ public struct Operand : CustomStringConvertible, NoReflectionChildren {
3737
public var isTypeDependent: Bool { bridged.isTypeDependent() }
3838

3939
public var endsLifetime: Bool { bridged.isLifetimeEnding() }
40-
40+
4141
public var description: String { "operand #\(index) of \(instruction)" }
4242
}
4343

44+
4445
public struct OperandArray : RandomAccessCollection, CustomReflectable {
4546
private let base: OptionalBridgedOperand
4647
public let count: Int
@@ -141,3 +142,105 @@ extension OptionalBridgedOperand {
141142
return nil
142143
}
143144
}
145+
146+
/// Categorize all uses in terms of their ownership effect. Implies ownership and lifetime constraints.
147+
public enum OperandOwnership {
148+
/// Operands that do not use the value. They only represent a dependence on a dominating definition and do not require liveness. (type-dependent operands)
149+
case nonUse
150+
151+
/// Uses that can only handle trivial values. The operand value must have None ownership. These uses require liveness but are otherwise unverified.
152+
case trivialUse
153+
154+
/// Use the value only for the duration of the operation, which may have side effects. (single-instruction apply with @guaranteed argument)
155+
case instantaneousUse
156+
157+
/// Use a value without requiring or propagating ownership. The operation may not have side-effects that could affect ownership. This is limited to a small number of operations that are allowed to take Unowned values. (copy_value, single-instruction apply with @unowned argument))
158+
case unownedInstantaneousUse
159+
160+
/// Forwarding instruction with an Unowned result. Its operands may have any ownership.
161+
case forwardingUnowned
162+
163+
/// Escape a pointer into a value which cannot be tracked or verified.
164+
///
165+
/// PointerEscape operands indicate a SIL deficiency to suffuciently model dependencies. They never arise from user-level escapes.
166+
case pointerEscape
167+
168+
/// Bitwise escape. Escapes the nontrivial contents of the value. OSSA does not enforce the lifetime of the escaping bits. The programmer must explicitly force lifetime extension. (ref_to_unowned, unchecked_trivial_bitcast)
169+
case bitwiseEscape
170+
171+
/// Borrow. Propagates the owned or guaranteed value within a scope, without ending its lifetime. (begin_borrow, begin_apply with @guaranteed argument)
172+
case borrow
173+
174+
/// Destroying Consume. Destroys the owned value immediately. (store, destroy, @owned destructure).
175+
case destroyingConsume
176+
177+
/// Forwarding Consume. Consumes the owned value indirectly via a move. (br, destructure, tuple, struct, cast, switch).
178+
case forwardingConsume
179+
180+
/// Interior Pointer. Propagates a trivial value (e.g. address, pointer, or no-escape closure) that depends on the guaranteed value within the base's borrow scope. The verifier checks that all uses of the trivial
181+
/// value are in scope. (ref_element_addr, open_existential_box)
182+
case interiorPointer
183+
184+
/// Forwarded Borrow. Propagates the guaranteed value within the base's borrow scope. (tuple_extract, struct_extract, cast, switch)
185+
case guaranteedForwarding
186+
187+
/// End Borrow. End the borrow scope opened directly by the operand. The operand must be a begin_borrow, begin_apply, or function argument. (end_borrow, end_apply)
188+
case endBorrow
189+
190+
/// Reborrow. Ends the borrow scope opened directly by the operand and begins one or multiple disjoint borrow scopes. If a forwarded value is reborrowed, then its base must also be reborrowed at the same point. (br, FIXME: should also include destructure, tuple, struct)
191+
case reborrow
192+
193+
public var _bridged: BridgedOperand.OperandOwnership {
194+
switch self {
195+
case .nonUse:
196+
return BridgedOperand.OperandOwnership.NonUse
197+
case .trivialUse:
198+
return BridgedOperand.OperandOwnership.TrivialUse
199+
case .instantaneousUse:
200+
return BridgedOperand.OperandOwnership.InstantaneousUse
201+
case .unownedInstantaneousUse:
202+
return BridgedOperand.OperandOwnership.UnownedInstantaneousUse
203+
case .forwardingUnowned:
204+
return BridgedOperand.OperandOwnership.ForwardingUnowned
205+
case .pointerEscape:
206+
return BridgedOperand.OperandOwnership.PointerEscape
207+
case .bitwiseEscape:
208+
return BridgedOperand.OperandOwnership.BitwiseEscape
209+
case .borrow:
210+
return BridgedOperand.OperandOwnership.Borrow
211+
case .destroyingConsume:
212+
return BridgedOperand.OperandOwnership.DestroyingConsume
213+
case .forwardingConsume:
214+
return BridgedOperand.OperandOwnership.ForwardingConsume
215+
case .interiorPointer:
216+
return BridgedOperand.OperandOwnership.InteriorPointer
217+
case .guaranteedForwarding:
218+
return BridgedOperand.OperandOwnership.GuaranteedForwarding
219+
case .endBorrow:
220+
return BridgedOperand.OperandOwnership.EndBorrow
221+
case .reborrow:
222+
return BridgedOperand.OperandOwnership.Reborrow
223+
}
224+
}
225+
}
226+
227+
extension Operand {
228+
public var ownership: OperandOwnership {
229+
switch bridged.getOperandOwnership() {
230+
case .NonUse: return .nonUse
231+
case .TrivialUse: return .trivialUse
232+
case .InstantaneousUse: return .instantaneousUse
233+
case .UnownedInstantaneousUse: return .unownedInstantaneousUse
234+
case .ForwardingUnowned: return .forwardingUnowned
235+
case .PointerEscape: return .pointerEscape
236+
case .BitwiseEscape: return .bitwiseEscape
237+
case .Borrow: return .borrow
238+
case .DestroyingConsume: return .destroyingConsume
239+
case .ForwardingConsume: return .forwardingConsume
240+
case .InteriorPointer: return .interiorPointer
241+
case .GuaranteedForwarding: return .guaranteedForwarding
242+
case .EndBorrow: return .endBorrow
243+
case .Reborrow: return .reborrow
244+
}
245+
}
246+
}

include/swift/SIL/SILBridging.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,23 @@ struct BridgedValueArray {
122122
struct BridgedOperand {
123123
swift::Operand * _Nonnull op;
124124

125+
enum class OperandOwnership {
126+
NonUse,
127+
TrivialUse,
128+
InstantaneousUse,
129+
UnownedInstantaneousUse,
130+
ForwardingUnowned,
131+
PointerEscape,
132+
BitwiseEscape,
133+
Borrow,
134+
DestroyingConsume,
135+
ForwardingConsume,
136+
InteriorPointer,
137+
GuaranteedForwarding,
138+
EndBorrow,
139+
Reborrow
140+
};
141+
125142
bool isTypeDependent() const { return op->isTypeDependent(); }
126143

127144
bool isLifetimeEnding() const { return op->isLifetimeEnding(); }
@@ -134,6 +151,39 @@ struct BridgedOperand {
134151

135152
SWIFT_IMPORT_UNSAFE
136153
inline BridgedInstruction getUser() const;
154+
155+
OperandOwnership getOperandOwnership() const {
156+
switch (op->getOperandOwnership()) {
157+
case swift::OperandOwnership::NonUse:
158+
return OperandOwnership::NonUse;
159+
case swift::OperandOwnership::TrivialUse:
160+
return OperandOwnership::TrivialUse;
161+
case swift::OperandOwnership::InstantaneousUse:
162+
return OperandOwnership::InstantaneousUse;
163+
case swift::OperandOwnership::UnownedInstantaneousUse:
164+
return OperandOwnership::UnownedInstantaneousUse;
165+
case swift::OperandOwnership::ForwardingUnowned:
166+
return OperandOwnership::ForwardingUnowned;
167+
case swift::OperandOwnership::PointerEscape:
168+
return OperandOwnership::PointerEscape;
169+
case swift::OperandOwnership::BitwiseEscape:
170+
return OperandOwnership::BitwiseEscape;
171+
case swift::OperandOwnership::Borrow:
172+
return OperandOwnership::Borrow;
173+
case swift::OperandOwnership::DestroyingConsume:
174+
return OperandOwnership::DestroyingConsume;
175+
case swift::OperandOwnership::ForwardingConsume:
176+
return OperandOwnership::ForwardingConsume;
177+
case swift::OperandOwnership::InteriorPointer:
178+
return OperandOwnership::InteriorPointer;
179+
case swift::OperandOwnership::GuaranteedForwarding:
180+
return OperandOwnership::GuaranteedForwarding;
181+
case swift::OperandOwnership::EndBorrow:
182+
return OperandOwnership::EndBorrow;
183+
case swift::OperandOwnership::Reborrow:
184+
return OperandOwnership::Reborrow;
185+
}
186+
}
137187
};
138188

139189
struct OptionalBridgedOperand {

0 commit comments

Comments
 (0)