Skip to content

Commit fe9c21f

Browse files
committed
[sil] Add a new instruction cast_implicit_actor_to_optional_actor.
This instruction converts Builtin.ImplicitActor to Optional<any Actor>. In the process of doing so, it masks out the bits we may have stolen from the witness table pointer of Builtin.ImplicitActor. The bits that we mask out are the bottom two bits of the top nibble of the TBI space on platforms that support TBI (that is bit 60,61 on arm64). On platforms that do not support TBI, we just use the bottom two tagged pointer bits (0,1). By using an instruction, we avoid having to represent the bitmasking that we are performing at the SIL level and can instead just make the emission of the bitmasking an IRGen detail. It also allows us to move detection if we are compiling for AArch64 to be an IRGen flag instead of a LangOpts flag. The instruction is a guaranteed forwarding instruction since we want to treat its result as a borrowed projection from the Builtin.ImplicitActor.
1 parent 81885a6 commit fe9c21f

32 files changed

+256
-11
lines changed

SwiftCompilerSources/Sources/SIL/ForwardingInstruction.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,12 @@ extension BorrowedFromInst: ForwardingInstruction {
467467
public var canForwardOwnedValues: Bool { false }
468468
}
469469

470+
extension ImplicitActorToOpaqueIsolationCastInst: ConversionInstruction {
471+
public var preservesRepresentation: Bool { true }
472+
public var canForwardGuaranteedValues: Bool { true }
473+
public var canForwardOwnedValues: Bool { false }
474+
}
475+
470476
// -----------------------------------------------------------------------------
471477
// ownership transition instructions
472478

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,3 +2060,6 @@ final public class MergeIsolationRegionInst : Instruction {
20602060

20612061
final public class IgnoredUseInst : Instruction, UnaryInstruction {
20622062
}
2063+
2064+
final public class ImplicitActorToOpaqueIsolationCastInst
2065+
: SingleValueInstruction, UnaryInstruction {}

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ private func registerSILClasses() {
265265
register(ThunkInst.self)
266266
register(MergeIsolationRegionInst.self)
267267
register(IgnoredUseInst.self)
268+
register(ImplicitActorToOpaqueIsolationCastInst.self)
268269
}
269270

270271
private func registerUtilities() {

docs/SIL/Instructions.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4555,6 +4555,9 @@ copy.
45554555
The resulting value must meet the usual ownership requirements; for
45564556
example, a trivial type must have '.none' ownership.
45574557

4558+
NOTE: A guaranteed result value is assumed to be a non-dependent guaranteed
4559+
value like a function argument.
4560+
45584561
### ref_to_raw_pointer
45594562

45604563
```
@@ -4871,6 +4874,27 @@ TODO
48714874

48724875
TODO
48734876

4877+
### cast_implicitactor_to_opaqueisolation
4878+
4879+
```
4880+
sil-instruction ::= 'cast_implicitactor_to_opaqueisolation' sil-operand
4881+
4882+
%1 = cast_implicitactor_to_opaqueisolation %0 : $Builtin.ImplicitActor
4883+
// %0 must have guaranteed ownership
4884+
// %1 must have guaranteed ownership
4885+
// %1 will have type $Optional<any Actor>
4886+
```
4887+
4888+
Convert a `$Builtin.ImplicitActor` to a `$Optional<any Actor>` masking out any
4889+
bits that we have stolen from the witness table pointer.
4890+
4891+
At IRGen time, we lower this to the relevant masking operations, allowing us to
4892+
avoid exposing these low level details to the SIL optimizer. On platforms where
4893+
we support TBI, IRGen uses a mask that is the bottom 2 bits of the top nibble of
4894+
the pointer. On 64 bit platforms this is bit 60,61. If the platform does not
4895+
support TBI, then IRGen uses the bottom two tagged pointer bits of the pointer
4896+
(bits 0,1).
4897+
48744898
## Checked Conversions
48754899

48764900
Some user-level cast operations can fail and thus require runtime

include/swift/AST/DiagnosticsParse.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,12 @@ ERROR(sil_operand_has_incorrect_moveonlywrapped,none,
621621
ERROR(sil_operand_not_ref_storage_address,none,
622622
"%0 operand of '%1' must have address of %2 type",
623623
(StringRef, StringRef, ReferenceOwnership))
624+
ERROR(sil_operand_has_wrong_ownership_kind,none,
625+
"operand has ownership kind %0 but ownership kind %1 was expected",
626+
(StringRef, StringRef))
627+
ERROR(sil_operand_has_incompatible_ownership_kind,none,
628+
"operand has ownership kind %0 but ownership kind compatible with %1 was expected",
629+
(StringRef, StringRef))
624630
ERROR(sil_integer_literal_not_integer_type,none,
625631
"integer_literal instruction requires a 'Builtin.Int<n>' type", ())
626632
ERROR(sil_integer_literal_not_well_formed,none,

include/swift/SIL/InstWrappers.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ class ForwardingOperation {
301301
return &forwardingInst->getOperandRef(TuplePackExtractInst::TupleOperand);
302302
case SILInstructionKind::BorrowedFromInst:
303303
return &forwardingInst->getOperandRef(0);
304+
case SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst:
305+
return &forwardingInst->getOperandRef(0);
304306
default:
305307
int numRealOperands = forwardingInst->getNumRealOperands();
306308
if (numRealOperands == 0) {
@@ -344,6 +346,7 @@ class ForwardingOperation {
344346
case SILInstructionKind::StructExtractInst:
345347
case SILInstructionKind::DifferentiableFunctionExtractInst:
346348
case SILInstructionKind::LinearFunctionExtractInst:
349+
case SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst:
347350
return true;
348351
default:
349352
return false;
@@ -352,6 +355,8 @@ class ForwardingOperation {
352355

353356
/// Return true if the forwarded value has the same representation. If true,
354357
/// then the result can be mapped to the same storage without a move or copy.
358+
///
359+
/// See ForwardingInstruction.swift preservesRepresentation().
355360
bool hasSameRepresentation() const;
356361

357362
/// Return true if the forwarded value is address-only either before or after

include/swift/SIL/SILBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,12 @@ class SILBuilder {
23412341
return createUncheckedOwnershipConversion(Loc, Operand, Kind);
23422342
}
23432343

2344+
ImplicitActorToOpaqueIsolationCastInst *
2345+
createImplicitActorToOpaqueIsolationCast(SILLocation Loc, SILValue Value) {
2346+
return insert(new (getModule()) ImplicitActorToOpaqueIsolationCastInst(
2347+
getSILDebugLocation(Loc), Value));
2348+
}
2349+
23442350
FixLifetimeInst *createFixLifetime(SILLocation Loc, SILValue Operand) {
23452351
return insert(new (getModule())
23462352
FixLifetimeInst(getSILDebugLocation(Loc), Operand));

include/swift/SIL/SILCloner.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3153,6 +3153,16 @@ void SILCloner<ImplClass>::visitUncheckedOwnershipConversionInst(
31533153
getOpValue(Inst->getOperand()), Kind));
31543154
}
31553155

3156+
template <typename ImplClass>
3157+
void SILCloner<ImplClass>::visitImplicitActorToOpaqueIsolationCastInst(
3158+
ImplicitActorToOpaqueIsolationCastInst *Inst) {
3159+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
3160+
3161+
recordClonedInstruction(
3162+
Inst, getBuilder().createImplicitActorToOpaqueIsolationCast(
3163+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getValue())));
3164+
}
3165+
31563166
template <typename ImplClass>
31573167
void SILCloner<ImplClass>::visitMarkDependenceInst(MarkDependenceInst *Inst) {
31583168
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));

include/swift/SIL/SILInstruction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8789,6 +8789,18 @@ class UncheckedOwnershipConversionInst
87898789
}
87908790
};
87918791

8792+
class ImplicitActorToOpaqueIsolationCastInst final
8793+
: public UnaryInstructionBase<
8794+
SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst,
8795+
OwnershipForwardingSingleValueInstruction> {
8796+
friend SILBuilder;
8797+
8798+
ImplicitActorToOpaqueIsolationCastInst(SILDebugLocation loc, SILValue value);
8799+
8800+
public:
8801+
SILValue getValue() const { return getOperand(); }
8802+
};
8803+
87928804
enum class MarkDependenceKind {
87938805
Unresolved, Escaping, NonEscaping
87948806
};
@@ -11653,6 +11665,7 @@ OwnershipForwardingSingleValueInstruction::classof(SILInstructionKind kind) {
1165311665
case SILInstructionKind::FunctionExtractIsolationInst:
1165411666
case SILInstructionKind::DropDeinitInst:
1165511667
case SILInstructionKind::BorrowedFromInst:
11668+
case SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst:
1165611669
return true;
1165711670
default:
1165811671
return false;

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
423423
SingleValueInstruction, None, DoesNotRelease)
424424
SINGLE_VALUE_INST(ObjCExistentialMetatypeToObjectInst, objc_existential_metatype_to_object,
425425
SingleValueInstruction, None, DoesNotRelease)
426+
SINGLE_VALUE_INST(ImplicitActorToOpaqueIsolationCastInst, implicitactor_to_opaqueisolation_cast,
427+
SingleValueInstruction, None, DoesNotRelease)
426428
// unconditional_checked_cast_inst is only MayRead to prevent a subsequent
427429
// release of the cast's source from being hoisted above the cast:
428430
// retain X

0 commit comments

Comments
 (0)