| //===--- SILArgument.cpp - Arguments for high-level SIL code --------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 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 "llvm/ADT/STLExtras.h" |
| #include "swift/SIL/SILBasicBlock.h" |
| #include "swift/SIL/SILArgument.h" |
| #include "swift/SIL/SILFunction.h" |
| #include "swift/SIL/SILInstruction.h" |
| #include "swift/SIL/SILModule.h" |
| |
| using namespace swift; |
| |
| //===----------------------------------------------------------------------===// |
| // SILArgument Implementation |
| //===----------------------------------------------------------------------===// |
| |
| SILArgument::SILArgument(ValueKind ChildKind, SILBasicBlock *ParentBB, |
| SILType Ty, ValueOwnershipKind OwnershipKind, |
| const ValueDecl *D) |
| : ValueBase(ChildKind, Ty, IsRepresentative::Yes), ParentBB(ParentBB), |
| Decl(D) { |
| Bits.SILArgument.VOKind = static_cast<unsigned>(OwnershipKind); |
| ParentBB->insertArgument(ParentBB->args_end(), this); |
| } |
| |
| SILArgument::SILArgument(ValueKind ChildKind, SILBasicBlock *ParentBB, |
| SILBasicBlock::arg_iterator Pos, SILType Ty, |
| ValueOwnershipKind OwnershipKind, const ValueDecl *D) |
| : ValueBase(ChildKind, Ty, IsRepresentative::Yes), ParentBB(ParentBB), |
| Decl(D) { |
| Bits.SILArgument.VOKind = static_cast<unsigned>(OwnershipKind); |
| // Function arguments need to have a decl. |
| assert( |
| !ParentBB->getParent()->isBare() && |
| ParentBB->getParent()->size() == 1 |
| ? D != nullptr |
| : true); |
| ParentBB->insertArgument(Pos, this); |
| } |
| |
| |
| SILFunction *SILArgument::getFunction() { |
| return getParent()->getParent(); |
| } |
| |
| const SILFunction *SILArgument::getFunction() const { |
| return getParent()->getParent(); |
| } |
| |
| SILModule &SILArgument::getModule() const { |
| return getFunction()->getModule(); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // SILBlockArgument |
| //===----------------------------------------------------------------------===// |
| |
| static SILValue getIncomingValueForPred(const SILBasicBlock *BB, |
| const SILBasicBlock *Pred, |
| unsigned Index) { |
| const TermInst *TI = Pred->getTerminator(); |
| |
| switch (TI->getTermKind()) { |
| // TODO: This list is conservative. I think we can probably handle more of |
| // these. |
| case TermKind::UnreachableInst: |
| case TermKind::ReturnInst: |
| case TermKind::ThrowInst: |
| case TermKind::UnwindInst: |
| llvm_unreachable("Have terminator that implies no successors?!"); |
| case TermKind::TryApplyInst: |
| case TermKind::SwitchValueInst: |
| case TermKind::SwitchEnumAddrInst: |
| case TermKind::CheckedCastAddrBranchInst: |
| case TermKind::DynamicMethodBranchInst: |
| case TermKind::YieldInst: |
| return SILValue(); |
| case TermKind::BranchInst: |
| return cast<const BranchInst>(TI)->getArg(Index); |
| case TermKind::CondBranchInst: |
| return cast<const CondBranchInst>(TI)->getArgForDestBB(BB, Index); |
| case TermKind::CheckedCastBranchInst: |
| return cast<const CheckedCastBranchInst>(TI)->getOperand(); |
| case TermKind::CheckedCastValueBranchInst: |
| return cast<const CheckedCastValueBranchInst>(TI)->getOperand(); |
| case TermKind::SwitchEnumInst: |
| return cast<const SwitchEnumInst>(TI)->getOperand(); |
| } |
| llvm_unreachable("Unhandled TermKind?!"); |
| } |
| |
| SILValue SILPHIArgument::getSingleIncomingValue() const { |
| const SILBasicBlock *Parent = getParent(); |
| const SILBasicBlock *PredBB = Parent->getSinglePredecessorBlock(); |
| if (!PredBB) |
| return SILValue(); |
| return getIncomingValueForPred(Parent, PredBB, getIndex()); |
| } |
| |
| bool SILPHIArgument::getIncomingValues( |
| llvm::SmallVectorImpl<SILValue> &OutArray) { |
| SILBasicBlock *Parent = getParent(); |
| |
| if (Parent->pred_empty()) |
| return false; |
| |
| unsigned Index = getIndex(); |
| for (SILBasicBlock *Pred : getParent()->getPredecessorBlocks()) { |
| SILValue Value = getIncomingValueForPred(Parent, Pred, Index); |
| if (!Value) |
| return false; |
| OutArray.push_back(Value); |
| } |
| |
| return true; |
| } |
| |
| bool SILPHIArgument::getIncomingValues( |
| llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>> &OutArray) { |
| SILBasicBlock *Parent = getParent(); |
| |
| if (Parent->pred_empty()) |
| return false; |
| |
| unsigned Index = getIndex(); |
| for (SILBasicBlock *Pred : getParent()->getPredecessorBlocks()) { |
| SILValue Value = getIncomingValueForPred(Parent, Pred, Index); |
| if (!Value) |
| return false; |
| OutArray.push_back({Pred, Value}); |
| } |
| |
| return true; |
| } |
| |
| SILValue SILPHIArgument::getIncomingValue(unsigned BBIndex) { |
| SILBasicBlock *Parent = getParent(); |
| |
| if (Parent->pred_empty()) |
| return SILValue(); |
| |
| unsigned Index = getIndex(); |
| |
| // We could do an early check if the size of the pred list is <= BBIndex, but |
| // that would involve walking the linked list anyways, so we just iterate once |
| // over the loop. |
| |
| // We use this funky loop since predecessors are stored in a linked list but |
| // we want array like semantics. |
| unsigned BBCount = 0; |
| for (SILBasicBlock *Pred : Parent->getPredecessorBlocks()) { |
| // If BBCount is not BBIndex, continue. |
| if (BBCount < BBIndex) { |
| BBCount++; |
| continue; |
| } |
| |
| // This will return an empty SILValue if we found something we do not |
| // understand. |
| return getIncomingValueForPred(Parent, Pred, Index); |
| } |
| |
| return SILValue(); |
| } |
| |
| SILValue SILPHIArgument::getIncomingValue(SILBasicBlock *BB) { |
| SILBasicBlock *Parent = getParent(); |
| |
| assert(!Parent->pred_empty() && "Passed in non-predecessor BB!"); |
| unsigned Index = getIndex(); |
| |
| // We could do an early check if the size of the pred list is <= BBIndex, but |
| // that would involve walking the linked list anyways, so we just iterate once |
| // over the loop. |
| |
| auto Target = std::find(Parent->pred_begin(), Parent->pred_end(), BB); |
| if (Target == Parent->pred_end()) |
| return SILValue(); |
| return getIncomingValueForPred(Parent, BB, Index); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // SILFunctionArgument |
| //===----------------------------------------------------------------------===// |
| |
| bool SILFunctionArgument::isSelf() const { |
| // Return true if we are the last argument of our BB and that our parent |
| // function has a call signature with self. |
| return getFunction()->hasSelfParam() && |
| getParent()->getArguments().back() == this; |
| } |