Skip to content

Commit 380e414

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. (cherry picked from commit fe9c21f)
1 parent 4039225 commit 380e414

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
@@ -462,6 +462,12 @@ extension BorrowedFromInst: ForwardingInstruction {
462462
public var canForwardOwnedValues: Bool { false }
463463
}
464464

465+
extension ImplicitActorToOpaqueIsolationCastInst: ConversionInstruction {
466+
public var preservesRepresentation: Bool { true }
467+
public var canForwardGuaranteedValues: Bool { true }
468+
public var canForwardOwnedValues: Bool { false }
469+
}
470+
465471
// -----------------------------------------------------------------------------
466472
// ownership transition instructions
467473

SwiftCompilerSources/Sources/SIL/Instruction.swift

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

18931893
final public class IgnoredUseInst : Instruction, UnaryInstruction {
18941894
}
1895+
1896+
final public class ImplicitActorToOpaqueIsolationCastInst
1897+
: SingleValueInstruction, UnaryInstruction {}

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,5 @@ public func registerSILClasses() {
260260
register(ThunkInst.self)
261261
register(MergeIsolationRegionInst.self)
262262
register(IgnoredUseInst.self)
263+
register(ImplicitActorToOpaqueIsolationCastInst.self)
263264
}

docs/SIL/Instructions.md

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

4538+
NOTE: A guaranteed result value is assumed to be a non-dependent guaranteed
4539+
value like a function argument.
4540+
45384541
### ref_to_raw_pointer
45394542

45404543
```
@@ -4851,6 +4854,27 @@ TODO
48514854

48524855
TODO
48534856

4857+
### cast_implicitactor_to_opaqueisolation
4858+
4859+
```
4860+
sil-instruction ::= 'cast_implicitactor_to_opaqueisolation' sil-operand
4861+
4862+
%1 = cast_implicitactor_to_opaqueisolation %0 : $Builtin.ImplicitActor
4863+
// %0 must have guaranteed ownership
4864+
// %1 must have guaranteed ownership
4865+
// %1 will have type $Optional<any Actor>
4866+
```
4867+
4868+
Convert a `$Builtin.ImplicitActor` to a `$Optional<any Actor>` masking out any
4869+
bits that we have stolen from the witness table pointer.
4870+
4871+
At IRGen time, we lower this to the relevant masking operations, allowing us to
4872+
avoid exposing these low level details to the SIL optimizer. On platforms where
4873+
we support TBI, IRGen uses a mask that is the bottom 2 bits of the top nibble of
4874+
the pointer. On 64 bit platforms this is bit 60,61. If the platform does not
4875+
support TBI, then IRGen uses the bottom two tagged pointer bits of the pointer
4876+
(bits 0,1).
4877+
48544878
## Checked Conversions
48554879

48564880
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
@@ -614,6 +614,12 @@ ERROR(sil_operand_has_incorrect_moveonlywrapped,none,
614614
ERROR(sil_operand_not_ref_storage_address,none,
615615
"%0 operand of '%1' must have address of %2 type",
616616
(StringRef, StringRef, ReferenceOwnership))
617+
ERROR(sil_operand_has_wrong_ownership_kind,none,
618+
"operand has ownership kind %0 but ownership kind %1 was expected",
619+
(StringRef, StringRef))
620+
ERROR(sil_operand_has_incompatible_ownership_kind,none,
621+
"operand has ownership kind %0 but ownership kind compatible with %1 was expected",
622+
(StringRef, StringRef))
617623
ERROR(sil_integer_literal_not_integer_type,none,
618624
"integer_literal instruction requires a 'Builtin.Int<n>' type", ())
619625
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
@@ -2338,6 +2338,12 @@ class SILBuilder {
23382338
return createUncheckedOwnershipConversion(Loc, Operand, Kind);
23392339
}
23402340

2341+
ImplicitActorToOpaqueIsolationCastInst *
2342+
createImplicitActorToOpaqueIsolationCast(SILLocation Loc, SILValue Value) {
2343+
return insert(new (getModule()) ImplicitActorToOpaqueIsolationCastInst(
2344+
getSILDebugLocation(Loc), Value));
2345+
}
2346+
23412347
FixLifetimeInst *createFixLifetime(SILLocation Loc, SILValue Operand) {
23422348
return insert(new (getModule())
23432349
FixLifetimeInst(getSILDebugLocation(Loc), Operand));

include/swift/SIL/SILCloner.h

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

3134+
template <typename ImplClass>
3135+
void SILCloner<ImplClass>::visitImplicitActorToOpaqueIsolationCastInst(
3136+
ImplicitActorToOpaqueIsolationCastInst *Inst) {
3137+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
3138+
3139+
recordClonedInstruction(
3140+
Inst, getBuilder().createImplicitActorToOpaqueIsolationCast(
3141+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getValue())));
3142+
}
3143+
31343144
template <typename ImplClass>
31353145
void SILCloner<ImplClass>::visitMarkDependenceInst(MarkDependenceInst *Inst) {
31363146
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));

include/swift/SIL/SILInstruction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8768,6 +8768,18 @@ class UncheckedOwnershipConversionInst
87688768
}
87698769
};
87708770

8771+
class ImplicitActorToOpaqueIsolationCastInst final
8772+
: public UnaryInstructionBase<
8773+
SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst,
8774+
OwnershipForwardingSingleValueInstruction> {
8775+
friend SILBuilder;
8776+
8777+
ImplicitActorToOpaqueIsolationCastInst(SILDebugLocation loc, SILValue value);
8778+
8779+
public:
8780+
SILValue getValue() const { return getOperand(); }
8781+
};
8782+
87718783
enum class MarkDependenceKind {
87728784
Unresolved, Escaping, NonEscaping
87738785
};
@@ -11637,6 +11649,7 @@ OwnershipForwardingSingleValueInstruction::classof(SILInstructionKind kind) {
1163711649
case SILInstructionKind::FunctionExtractIsolationInst:
1163811650
case SILInstructionKind::DropDeinitInst:
1163911651
case SILInstructionKind::BorrowedFromInst:
11652+
case SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst:
1164011653
return true;
1164111654
default:
1164211655
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)