Ejemplo n.º 1
0
// 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();
}
Ejemplo n.º 2
0
MemLocation MemLocation::createMemLocation(SILValue Base, ProjectionPath &P1,
                                           ProjectionPath &P2) {
  ProjectionPath T;
  T.append(P1);
  T.append(P2);
  return MemLocation(Base, T);
}
Ejemplo n.º 3
0
Optional<ProjectionPath>
ProjectionPath::subtractPaths(const ProjectionPath &LHS, const ProjectionPath &RHS) {
    // If RHS is greater than or equal to LHS in size, RHS can not be a prefix of
    // LHS. Return None.
    unsigned RHSSize = RHS.size();
    unsigned LHSSize = LHS.size();
    if (RHSSize >= LHSSize)
        return llvm::NoneType::None;

    // First make sure that the prefix matches.
    Optional<ProjectionPath> P = ProjectionPath();
    for (unsigned i = 0; i < RHSSize; i++) {
        if (LHS.Path[i] != RHS.Path[i]) {
            P.reset();
            return P;
        }
    }

    // Add the rest of LHS to P and return P.
    for (unsigned i = RHSSize, e = LHSSize; i != e; ++i) {
        P->Path.push_back(LHS.Path[i]);
    }

    return P;
}
Ejemplo n.º 4
0
void LSLocation::getFirstLevelLSLocations(LSLocationList &Locs,
                                          SILModule *Mod) {
  SILType Ty = getType();
  llvm::SmallVector<Projection, 8> Out;
  Projection::getFirstLevelAddrProjections(Ty, *Mod, Out);
  for (auto &X : Out) {
    ProjectionPath P;
    P.append(X);
    P.append(Path.getValue());
    Locs.push_back(LSLocation(Base, P));
  }
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
void
ProjectionPath::expandTypeIntoLeafProjectionPaths(SILType B, SILModule *Mod,
        ProjectionPathList &Paths,
        bool OnlyLeafNode) {
    // Perform a BFS to expand the given type into projectionpath each of
    // which contains 1 field from the type.
    ProjectionPathList Worklist;
    llvm::SmallVector<Projection, 8> Projections;

    // Push an empty projection path to get started.
    SILType Ty;
    ProjectionPath P;
    Worklist.push_back(std::move(P));
    do {
        // Get the next level projections based on current projection's type.
        Optional<ProjectionPath> PP = Worklist.pop_back_val();
        // Get the current type to process, the very first projection path will be
        // empty.
        Ty = PP.getValue().empty() ? B : PP.getValue().front().getType();

        // Get the first level projection of the current type.
        Projections.clear();
        Projection::getFirstLevelAddrProjections(Ty, *Mod, Projections);

        // Reached the end of the projection tree, this field can not be expanded
        // anymore.
        if (Projections.empty()) {
            Paths.push_back(std::move(PP.getValue()));
            continue;
        }

        // If this is a class type, we also have reached the end of the type
        // tree for this type.
        //
        // We do not push its next level projection into the worklist,
        // if we do that, we could run into an infinite loop, e.g.
        //
        //   class SelfLoop {
        //     var p : SelfLoop
        //   }
        //
        //   struct XYZ {
        //     var x : Int
        //     var y : SelfLoop
        //   }
        //
        // The worklist would never be empty in this case !.
        //
        if (Ty.getClassOrBoundGenericClass()) {
            Paths.push_back(std::move(PP.getValue()));
            continue;
        }

        // This is NOT a leaf node, keep the intermediate nodes as well.
        if (!OnlyLeafNode)
            Paths.push_back(std::move(PP.getValue()));

        // Keep expanding the location.
        for (auto &P : Projections) {
            ProjectionPath X;
            X.append(P);
            X.append(PP.getValue());
            Worklist.push_back(std::move(X));
        }
        // Keep iterating if the worklist is not empty.
    } while (!Worklist.empty());
}