Exemplo n.º 1
0
bool
LSLocation::reduce(LSLocation Base, SILModule *M, LSLocationSet &Locs) {
  // If this is a class reference type, we have reached end of the type tree.
  if (Base.getType(M).getClassOrBoundGenericClass())
    return Locs.find(Base) != Locs.end();

  // This is a leaf node.
  LSLocationList NextLevel;
  Base.getNextLevelLSLocations(NextLevel, M);
  if (NextLevel.empty())
    return Locs.find(Base) != Locs.end();

  // This is not a leaf node, try to find whether all its children are alive.
  bool Alive = true;
  for (auto &X : NextLevel) {
    Alive &= LSLocation::reduce(X, M, Locs);
  }

  // All next level locations are alive, create the new aggregated location.
  if (Alive) {
    for (auto &X : NextLevel)
      Locs.erase(X);
    Locs.insert(Base);
  }
  return Alive;
}
Exemplo n.º 2
0
void
LSValue::reduceInner(LSLocation &Base, SILModule *M, LSLocationValueMap &Values,
                     SILInstruction *InsertPt) {
  // If this is a class reference type, we have reached end of the type tree.
  if (Base.getType(M).getClassOrBoundGenericClass())
    return;

  // This is a leaf node, we must have a value for it.
  LSLocationList NextLevel;
  Base.getNextLevelLSLocations(NextLevel, M);
  if (NextLevel.empty())
    return;

  // This is not a leaf node, reduce the next level node one by one.
  for (auto &X : NextLevel) {
    LSValue::reduceInner(X, M, Values, InsertPt);
  }

  // This is NOT a leaf node, we need to construct a value for it.
  auto Iter = NextLevel.begin();
  LSValue &FirstVal = Values[*Iter];

  // There is only 1 children node and its value's projection path is not
  // empty, keep stripping it.
  if (NextLevel.size() == 1 && !FirstVal.hasEmptyProjectionPath()) {
    Values[Base] = FirstVal.stripLastLevelProjection();
    // We have a value for the parent, remove all the values for children.
    removeLSLocations(Values, NextLevel);
    return;
  }

  bool HasIdenticalBase = true;
  SILValue FirstBase = FirstVal.getBase();
  for (auto &X : NextLevel) {
    HasIdenticalBase &= (FirstBase == Values[X].getBase());
  }

  // This is NOT a leaf node and it has multiple children, but they have the
  // same value base.
  if (NextLevel.size() > 1 && HasIdenticalBase) {
    if (!FirstVal.hasEmptyProjectionPath()) {
      Values[Base] = FirstVal.stripLastLevelProjection();
      // We have a value for the parent, remove all the values for children.
      removeLSLocations(Values, NextLevel);
      return;
    }
  }

  // In 3 cases do we need aggregation.
  //
  // 1. If there is only 1 child and we cannot strip off any projections,
  //    that means we need to create an aggregation.
  // 
  // 2. There are multiple children and they have the same base, but empty
  //    projection paths.
  //
  // 3. Children have values from different bases, We need to create
  //    extractions and aggregation in this case.
  //
  llvm::SmallVector<SILValue, 8> Vals;
  for (auto &X : NextLevel) {
    Vals.push_back(Values[X].materialize(InsertPt));
  }
  SILBuilder Builder(InsertPt);
  Builder.setCurrentDebugScope(InsertPt->getFunction()->getDebugScope());
  
  // We use an auto-generated SILLocation for now.
  NullablePtr<swift::SILInstruction> AI =
      Projection::createAggFromFirstLevelProjections(
          Builder, RegularLocation::getAutoGeneratedLocation(),
          Base.getType(M).getObjectType(),
          Vals);

  // This is the Value for the current base.
  ProjectionPath P(Base.getType(M));
  Values[Base] = LSValue(SILValue(AI.get()), P);
  removeLSLocations(Values, NextLevel);
}