Skip to content

Commit 839c389

Browse files
committed
[ownership] Add a helper API on InteriorPointerOperand that lets you infer the InteriorPointerOperand from the interior pointer operand's user instruction's result.
Useful when needing to walk use->def and get this info.
1 parent d505686 commit 839c389

File tree

1 file changed

+61
-9
lines changed

1 file changed

+61
-9
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ Optional<BorrowedValue> getSingleBorrowIntroducingValue(SILValue inputValue);
507507
class InteriorPointerOperandKind {
508508
public:
509509
enum Kind : uint8_t {
510+
Invalid=0,
510511
RefElementAddr,
511512
RefTailAddr,
512513
OpenExistentialBox,
@@ -518,18 +519,39 @@ class InteriorPointerOperandKind {
518519
public:
519520
InteriorPointerOperandKind(Kind newValue) : value(newValue) {}
520521

521-
operator Kind() const { return value; }
522+
operator Kind() const {
523+
assert(isValid());
524+
return value;
525+
}
526+
527+
bool isValid() const { return value != Kind::Invalid; }
522528

523-
static Optional<InteriorPointerOperandKind> get(Operand *use) {
529+
static InteriorPointerOperandKind get(Operand *use) {
524530
switch (use->getUser()->getKind()) {
525531
default:
526-
return None;
532+
return Kind::Invalid;
527533
case SILInstructionKind::RefElementAddrInst:
528-
return InteriorPointerOperandKind(RefElementAddr);
534+
return Kind::RefElementAddr;
529535
case SILInstructionKind::RefTailAddrInst:
530-
return InteriorPointerOperandKind(RefTailAddr);
536+
return Kind::RefTailAddr;
531537
case SILInstructionKind::OpenExistentialBoxInst:
532-
return InteriorPointerOperandKind(OpenExistentialBox);
538+
return Kind::OpenExistentialBox;
539+
}
540+
}
541+
542+
/// Given a \p value that is a result of an instruction with an interior
543+
/// pointer operand, return the interior pointer operand kind that would be
544+
/// appropriate for that operand.
545+
static InteriorPointerOperandKind inferFromResult(SILValue value) {
546+
switch (value->getKind()) {
547+
default:
548+
return Kind::Invalid;
549+
case ValueKind::RefElementAddrInst:
550+
return Kind::RefElementAddr;
551+
case ValueKind::RefTailAddrInst:
552+
return Kind::RefTailAddr;
553+
case ValueKind::OpenExistentialBoxInst:
554+
return Kind::OpenExistentialBox;
533555
}
534556
}
535557

@@ -546,14 +568,42 @@ struct InteriorPointerOperand {
546568
InteriorPointerOperandKind kind;
547569

548570
InteriorPointerOperand(Operand *op)
549-
: operand(op), kind(*InteriorPointerOperandKind::get(op)) {}
571+
: operand(op), kind(InteriorPointerOperandKind::get(op)) {
572+
assert(kind.isValid());
573+
}
550574

551-
/// If value is a borrow introducer return it after doing some checks.
575+
/// If \p op has a user that is an interior pointer, return a valid
576+
/// value. Otherwise, return None.
552577
static Optional<InteriorPointerOperand> get(Operand *op) {
553578
auto kind = InteriorPointerOperandKind::get(op);
554579
if (!kind)
555580
return None;
556-
return InteriorPointerOperand(op, *kind);
581+
return InteriorPointerOperand(op, kind);
582+
}
583+
584+
/// If \p val is a result of an instruction that is an interior pointer,
585+
/// return an interor pointer operand based off of the base value operand of
586+
/// the instruction.
587+
static Optional<InteriorPointerOperand>
588+
inferFromResult(SILValue resultValue) {
589+
auto kind = InteriorPointerOperandKind::inferFromResult(resultValue);
590+
591+
// NOTE: We use an exhaustive switch here to allow for further interior
592+
// pointer operand having instructions to make the interior pointer
593+
// operand's argument index arbitrary.
594+
switch (kind) {
595+
case InteriorPointerOperandKind::Invalid:
596+
// We do not have a valid instruction, so return None.
597+
return None;
598+
case InteriorPointerOperandKind::RefElementAddr:
599+
case InteriorPointerOperandKind::RefTailAddr:
600+
case InteriorPointerOperandKind::OpenExistentialBox: {
601+
// Ok, we have a valid instruction. Return the relevant operand.
602+
auto *op =
603+
&cast<SingleValueInstruction>(resultValue)->getAllOperands()[0];
604+
return InteriorPointerOperand(op, kind);
605+
}
606+
}
557607
}
558608

559609
/// Return the end scope of all borrow introducers of the parent value of this
@@ -573,6 +623,8 @@ struct InteriorPointerOperand {
573623

574624
SILValue getProjectedAddress() const {
575625
switch (kind) {
626+
case InteriorPointerOperandKind::Invalid:
627+
llvm_unreachable("Calling method on invalid?!");
576628
case InteriorPointerOperandKind::RefElementAddr:
577629
return cast<RefElementAddrInst>(operand->getUser());
578630
case InteriorPointerOperandKind::RefTailAddr:

0 commit comments

Comments
 (0)