// Get the aggregate member based on the top of the projection stack.
static SILValue getMember(SILInstruction *inst, ProjectionPath &projStack) {
  if (!projStack.empty()) {
    const Projection &proj = projStack.back();
    return proj.getOperandForAggregate(inst);
  }
  return SILValue();
}
Beispiel #2
0
/// TODO: Integrate has empty non-symmetric difference into here.
SubSeqRelation_t
ProjectionPath::
computeSubSeqRelation(const ProjectionPath &RHS) const {
    // If either path is empty, we can not prove anything, return Unrelated.
    if (empty() || RHS.empty())
        return SubSeqRelation_t::Unrelated;

    // We reverse the projection path to scan from the common object.
    auto LHSReverseIter = rbegin();
    auto RHSReverseIter = RHS.rbegin();

    unsigned MinPathSize = std::min(size(), RHS.size());

    // For each index i until min path size...
    for (unsigned i = 0; i != MinPathSize; ++i) {
        // Grab the current projections.
        const Projection &LHSProj = *LHSReverseIter;
        const Projection &RHSProj = *RHSReverseIter;

        // If the two projections do not equal exactly, return Unrelated.
        //
        // TODO: If Index equals zero, then we know that the two lists have nothing
        // in common and should return unrelated. If Index is greater than zero,
        // then we know that the two projection paths have a common base but a
        // non-empty symmetric difference. For now we just return Unrelated since I
        // can not remember why I had the special check in the
        // hasNonEmptySymmetricDifference code.
        if (LHSProj != RHSProj)
            return SubSeqRelation_t::Unrelated;

        // Otherwise increment reverse iterators.
        LHSReverseIter++;
        RHSReverseIter++;
    }

    // Ok, we now know that one of the paths is a subsequence of the other. If
    // both size() and RHS.size() equal then we know that the entire sequences
    // equal.
    if (size() == RHS.size())
        return SubSeqRelation_t::Equal;

    // If MinPathSize == size(), then we know that LHS is a strict subsequence of
    // RHS.
    if (MinPathSize == size())
        return SubSeqRelation_t::LHSStrictSubSeqOfRHS;

    // Otherwise, we know that MinPathSize must be RHS.size() and RHS must be a
    // strict subsequence of LHS. Assert to check this and return.
    assert(MinPathSize == RHS.size() &&
           "Since LHS and RHS don't equal and size() != MinPathSize, RHS.size() "
           "must equal MinPathSize");
    return SubSeqRelation_t::RHSStrictSubSeqOfLHS;
}
Beispiel #3
0
Optional<ProjectionPath>
ProjectionPath::getAddrProjectionPath(SILValue Start, SILValue End,
                                      bool IgnoreCasts) {
    // Do not inspect the body of structs with unreferenced types such as
    // bitfields and unions.
    if (Start.getType().aggregateHasUnreferenceableStorage() ||
            End.getType().aggregateHasUnreferenceableStorage()) {
        return llvm::NoneType::None;
    }

    ProjectionPath P;

    // If Start == End, there is a "trivial" address projection in between the
    // two. This is represented by returning an empty ProjectionPath.
    if (Start == End)
        return std::move(P);

    // Otherwise see if End can be projection extracted from Start. First see if
    // End is a projection at all.
    auto Iter = End;
    if (IgnoreCasts)
        Iter = Iter.stripCasts();
    bool NextAddrIsIndex = false;
    while (Projection::isAddrProjection(Iter) && Start != Iter) {
        Projection AP = *Projection::addressProjectionForValue(Iter);
        P.Path.push_back(AP);
        NextAddrIsIndex = (AP.getKind() == ProjectionKind::Index);

        Iter = cast<SILInstruction>(*Iter).getOperand(0);
        if (IgnoreCasts)
            Iter = Iter.stripCasts();
    }

    // Return None if we have an empty projection list or if Start == Iter.
    // If the next project is index_addr, then Start and End actually point to
    // disjoint locations (the value at Start has an implicit index_addr #0).
    if (P.empty() || Start != Iter || NextAddrIsIndex)
        return llvm::NoneType::None;

    // Otherwise, return P.
    return std::move(P);
}
Beispiel #4
0
/// Returns true if the two paths have a non-empty symmetric difference.
///
/// This means that the two objects have the same base but access different
/// fields of the base object.
bool
ProjectionPath::
hasNonEmptySymmetricDifference(const ProjectionPath &RHS) const {
    // If either the LHS or RHS is empty, there is no common base class. Return
    // false.
    if (empty() || RHS.empty())
        return false;

    // We reverse the projection path to scan from the common object.
    auto LHSReverseIter = Path.rbegin();
    auto RHSReverseIter = RHS.Path.rbegin();

    // For each index i until min path size...
    for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) {
        // Grab the current projections.
        const Projection &LHSProj = *LHSReverseIter;
        const Projection &RHSProj = *RHSReverseIter;

        // If we are accessing different fields of a common object, return
        // true. The two projection paths must have a non-empty symmetric
        // difference.
        if (areProjectionsToDifferentFields(LHSProj, RHSProj)) {
            DEBUG(llvm::dbgs() << "        Path different at index: " << i << '\n');
            return true;
        }

        // Otherwise, if the two projections equal exactly, they have no symmetric
        // difference.
        if (LHSProj == RHSProj)
            return false;

        // Continue if we are accessing the same field.
        LHSReverseIter++;
        RHSReverseIter++;
    }

    // We checked
    return false;
}
SILValue ConstantTracker::getStoredValue(SILInstruction *loadInst,
                                         ProjectionPath &projStack) {
  SILInstruction *store = links[loadInst];
  if (!store && callerTracker)
    store = callerTracker->links[loadInst];
  if (!store) return SILValue();

  assert(isa<LoadInst>(loadInst) || isa<CopyAddrInst>(loadInst));

  // Push the address projections of the load onto the stack.
  SmallVector<Projection, 4> loadProjections;
  scanProjections(loadInst->getOperand(0), &loadProjections);
  for (const Projection &proj : loadProjections) {
    projStack.push_back(proj);
  }

  //  Pop the address projections of the store from the stack.
  SmallVector<Projection, 4> storeProjections;
  scanProjections(store->getOperand(1), &storeProjections);
  for (auto iter = storeProjections.rbegin(); iter != storeProjections.rend();
       ++iter) {
    const Projection &proj = *iter;
    // The corresponding load-projection must match the store-projection.
    if (projStack.empty() || projStack.back() != proj)
      return SILValue();
    projStack.pop_back();
  }

  if (isa<StoreInst>(store))
    return store->getOperand(0);

  // The copy_addr instruction is both a load and a store. So we follow the link
  // again.
  assert(isa<CopyAddrInst>(store));
  return getStoredValue(store, projStack);
}