Files
swift-mirror/lib/SIL/Utils/InstWrappers.cpp
Michael Gottesman fe9c21fd87 [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.
2025-10-16 10:52:04 -07:00

113 lines
4.1 KiB
C++

//===--- InstWrappers.cpp ------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/Assertions.h"
#include "swift/SIL/InstWrappers.h"
#include "swift/SIL/SILFunction.h"
using namespace swift;
ForwardingOperation::ForwardingOperation(SILInstruction *inst) {
if (ForwardingInstruction::isa(inst)) {
this->forwardingInst = inst;
return;
}
}
ValueOwnershipKind ForwardingOperation::getForwardingOwnershipKind() {
return ForwardingInstruction::get(forwardingInst)
->getForwardingOwnershipKind();
}
bool ForwardingOperation::preservesOwnership() {
return ForwardingInstruction::get(forwardingInst)->preservesOwnership();
}
// See ForwardingInstruction.swift preservesRepresentation().
bool ForwardingOperation::hasSameRepresentation() const {
switch (forwardingInst->getKind()) {
// Explicitly list instructions which definitely involve a representation
// change.
case SILInstructionKind::SwitchEnumInst:
default:
// Conservatively assume that a conversion changes representation.
// Operations can be added as needed to participate in SIL opaque values.
return false;
case SILInstructionKind::ConvertFunctionInst:
case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst:
case SILInstructionKind::DestructureTupleInst:
case SILInstructionKind::DestructureStructInst:
case SILInstructionKind::InitExistentialRefInst:
case SILInstructionKind::ObjectInst:
case SILInstructionKind::OpenExistentialBoxValueInst:
case SILInstructionKind::OpenExistentialRefInst:
case SILInstructionKind::OpenExistentialValueInst:
case SILInstructionKind::MarkUnresolvedNonCopyableValueInst:
case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst:
case SILInstructionKind::MarkUninitializedInst:
case SILInstructionKind::StructExtractInst:
case SILInstructionKind::TupleExtractInst:
case SILInstructionKind::TuplePackExtractInst:
case SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst:
return true;
}
}
bool ForwardingOperation::isAddressOnly() const {
if (auto *singleForwardingOp = getSingleForwardingOperand()) {
return singleForwardingOp->get()->getType().isAddressOnly(
*forwardingInst->getFunction());
}
// All ForwardingInstructions that forward all operands or no operands are
// currently a single value instruction.
auto *aggregate =
cast<OwnershipForwardingSingleValueInstruction>(forwardingInst);
// If any of the operands are address-only, then the aggregate must be.
return aggregate->getType().isAddressOnly(*forwardingInst->getFunction());
}
bool ForwardingOperation::visitForwardedValues(
function_ref<bool(SILValue)> visitor) {
if (auto *svi = dyn_cast<SingleValueInstruction>(forwardingInst)) {
return visitor(svi);
}
if (auto *mvri = dyn_cast<MultipleValueInstruction>(forwardingInst)) {
return llvm::all_of(mvri->getResults(), [&](SILValue value) {
if (value->getOwnershipKind() == OwnershipKind::None)
return true;
return visitor(value);
});
}
auto *ti = cast<TermInst>(forwardingInst);
assert(ti->mayHaveTerminatorResult());
return llvm::all_of(ti->getSuccessorBlocks(), [&](SILBasicBlock *succBlock) {
// If we do not have any arguments, then continue.
if (succBlock->args_empty())
return true;
auto args = succBlock->getSILPhiArguments();
assert(args.size() == 1 && "Transforming terminator with multiple args?!");
return visitor(args[0]);
});
}
bool swift::isFixedStorageSemanticsCallKind(SILFunction *function) {
for (auto &attr : function->getSemanticsAttrs()) {
if (attr == "fixed_storage.check_index" ||
attr == "fixed_storage.get_count") {
return true;
}
}
return false;
}