Files
swift-mirror/lib/SIL/SILValue.cpp
Erik Eckstein c2702fbf8b Fix <rdar://problem/19069205> Stack overflow in SIL alias analysis
The problem was that SILValue::stripAddressProjections() was out of sync with Projection::isAddrProjection().



Swift SVN r23806
2014-12-09 11:16:16 +00:00

199 lines
4.8 KiB
C++

//===--- SILValue.cpp - Implementation for SILValue -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/SIL/SILValue.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBasicBlock.h"
using namespace swift;
void SILValue::replaceAllUsesWith(SILValue V) {
assert(*this != V && "Cannot RAUW a value with itself");
assert(getType() == V.getType() && "Invalid type");
while (!use_empty())
(**use_begin()).set(V);
}
static bool isRCIdentityPreservingCast(ValueKind Kind) {
switch (Kind) {
case ValueKind::UpcastInst:
case ValueKind::UncheckedRefCastInst:
case ValueKind::UncheckedAddrCastInst:
case ValueKind::UnconditionalCheckedCastInst:
case ValueKind::UncheckedRefBitCastInst:
case ValueKind::RefToBridgeObjectInst:
case ValueKind::BridgeObjectToRefInst:
return true;
default:
return false;
}
}
// Similar to isRCIdentityPreservingCast, but does not
// allow for UnconditionalCheckedCastInst, which may
// perform downcasts.
static bool isUpcastPreservingCast(ValueKind Kind) {
switch (Kind) {
case ValueKind::UpcastInst:
case ValueKind::UncheckedRefCastInst:
case ValueKind::UncheckedAddrCastInst:
case ValueKind::UncheckedRefBitCastInst:
case ValueKind::RefToBridgeObjectInst:
case ValueKind::BridgeObjectToRefInst:
return true;
default:
return false;
}
}
/// Return the underlying SILValue after stripping off identity SILArguments if
/// we belong to a BB with one predecessor.
static SILValue stripSinglePredecessorArgs(SILValue V) {
while (true) {
auto *A = dyn_cast<SILArgument>(V);
if (!A)
return V;
SILBasicBlock *BB = A->getParent();
// First try and grab the single predecessor of our parent BB. If we don't
// have one, bail.
SILBasicBlock *Pred = BB->getSinglePredecessor();
if (!Pred)
return V;
// Then grab the terminator of Pred...
TermInst *PredTI = Pred->getTerminator();
// And attempt to find our matching argument.
if (auto *BI = dyn_cast<BranchInst>(PredTI)) {
V = BI->getArg(A->getIndex());
continue;
}
if (auto *CBI = dyn_cast<CondBranchInst>(PredTI)) {
if (SILValue Arg = CBI->getArgForDestBB(BB, A)) {
V = Arg;
continue;
}
}
return V;
}
}
SILValue SILValue::stripCasts() {
SILValue V = *this;
while (true) {
V = stripSinglePredecessorArgs(V);
auto K = V->getKind();
if (isRCIdentityPreservingCast(K) ||
K == ValueKind::UncheckedTrivialBitCastInst) {
V = cast<SILInstruction>(V.getDef())->getOperand(0);
continue;
}
return V;
}
}
SILValue SILValue::stripUpCasts() {
SILValue V = *this;
while (true) {
V = stripSinglePredecessorArgs(V);
auto K = V->getKind();
if (isUpcastPreservingCast(K) ||
K == ValueKind::UncheckedTrivialBitCastInst) {
V = cast<SILInstruction>(V.getDef())->getOperand(0);
continue;
}
return V;
}
}
SILValue SILValue::stripClassCasts() {
SILValue V = *this;
while (true) {
if (auto *UI = dyn_cast<UpcastInst>(V)) {
V = UI->getOperand();
continue;
}
if (auto *UCCI = dyn_cast<UnconditionalCheckedCastInst>(V)) {
V = UCCI->getOperand();
continue;
}
return V;
}
}
SILValue SILValue::stripAddressProjections() {
SILValue V = *this;
while (true) {
V = stripSinglePredecessorArgs(V);
switch (V->getKind()) {
case ValueKind::StructElementAddrInst:
case ValueKind::TupleElementAddrInst:
case ValueKind::RefElementAddrInst:
case ValueKind::UncheckedTakeEnumDataAddrInst:
V = cast<SILInstruction>(V.getDef())->getOperand(0);
continue;
default:
return V;
}
}
}
SILValue SILValue::stripAggregateProjections() {
SILValue V = *this;
while (true) {
V = stripSinglePredecessorArgs(V);
switch (V->getKind()) {
case ValueKind::StructExtractInst:
case ValueKind::TupleExtractInst:
V = cast<SILInstruction>(V.getDef())->getOperand(0);
continue;
default:
return V;
}
}
}
SILValue SILValue::stripIndexingInsts() {
SILValue V = *this;
while (true) {
if (!isa<IndexingInst>(V.getDef()))
return V;
V = cast<IndexingInst>(V)->getBase();
}
}
SILBasicBlock *ValueBase::getParentBB() {
if (auto Inst = dyn_cast<SILInstruction>(this))
return Inst->getParent();
if (auto Arg = dyn_cast<SILArgument>(this))
return Arg->getParent();
return nullptr;
}