예제 #1
0
  /**
   * During the join process, there might be cycle. It means the ECR <code>
   * root</code> might be set to <code>freshType</code>. The type-union should take care of it --
   * union <code>freshType</code> to <code>unionType</code>. In particular, <code>freshType</code>
   * is an object type, while <code>
   * unionType</code> is a struct type, then <code>unionType</code> should be collapsed before union
   * with <code>freshType</code>.
   *
   * @param root
   * @param unionType
   * @param freshType
   * @return unified type
   */
  private ValueType resolveType(ECR root, ValueType unionType, ValueType freshType) {
    Preconditions.checkArgument(!unionType.isLambda());
    Preconditions.checkArgument(!freshType.isLambda());

    Pair<ValueType, ValueType> pair = swap(unionType, freshType);
    ValueType t1 = pair.fst(), t2 = pair.snd();

    if (t1.isSimple() && t2.isStruct()) {
      Collection<ECR> elems = t2.asStruct().getFieldMap().asMapOfRanges().values();
      ValueType resType = t1;
      for (ECR elem : elems) {
        ECR elemLoc = getLoc(elem);
        ValueType elemLocType = getType(elemLoc);
        Parent parent = elemLocType.getParent().removeECR(root);
        elemLocType.setParent(parent);
        if (elemLocType.isStruct()) {
          elemLocType = collapseStruct(elemLoc, elemLocType.asStruct());
        }

        union(root, elemLoc);
        resType = unify(resType, elemLocType);
      }
      return resType;
    }

    return unify(t1, t2);
  }
예제 #2
0
  void clearPointerArithmetic() {
    if (ptrAriJoins.isEmpty()) return;
    for (Entry<Pair<ECR, Long>, Pair<ECR, Long>> cell : ptrAriJoins.entrySet()) {
      ECR resECR = findRoot(cell.getKey().fst());
      final ECR origECR = findRoot(cell.getValue().fst());
      long shift = cell.getValue().snd();
      if (shift >= 0) {
        // TODO: could do more precise analysis here.
        collapse(origECR, resECR);
        continue;
      }

      ValueType origType = getType(origECR);
      Parent parent = origType.getParent();
      if (parent.getECRs().isEmpty()) {
        // TODO: could do more precise analysis here.
        collapse(origECR, resECR);
        continue;
      }

      for (ECR parentECR : parent.getECRs()) {
        ValueType parentType = getType(parentECR);
        if (!parentType.isStruct()) {
          IOUtils.errPrinter().pln("WARNING: non-struct parent");
          join(parentECR, origECR);
          continue;
        }

        Map<Range<Long>, ECR> fieldMap = parentType.asStruct().getFieldMap().asMapOfRanges();
        Entry<Range<Long>, ECR> fieldRange =
            Iterables.find(
                fieldMap.entrySet(),
                new Predicate<Entry<Range<Long>, ECR>>() {
                  @Override
                  public boolean apply(Entry<Range<Long>, ECR> input) {
                    return origECR.equals(getLoc(input.getValue()));
                  }
                });
        long low = fieldRange.getKey().lowerEndpoint() + shift;
        Size parentSize = parentType.getSize();
        long size = cell.getKey().snd();
        if (low == 0
            && (parentSize.isBottom() || parentSize.isNumber() && parentSize.getValue() == size)) {
          join(parentECR, resECR);
          continue;
        }

        collapse(origECR, resECR);
      }
    }
  }
예제 #3
0
  /**
   * Collapse <code>structECR</code> by merge it with all its element ECRs, and set its type as the
   * cell type (simple type might with top size)
   *
   * @param structECR
   * @param structT
   * @param ECRCache avoid structure cycle
   * @return
   */
  private ValueType collapseStruct(ECR structECR, StructType structT, Collection<ECR> ECRCache) {
    // Ensure collapsed type to be simple
    ValueType unionType = null;

    // join components
    Collection<ECR> elems = structT.getFieldMap().asMapOfRanges().values();
    Collection<ECR> cjoins = Sets.newHashSet();
    Collection<Pair<Size, ECR>> ccjoins = Sets.newHashSet();

    for (ECR elem : elems) {
      ECR elemLoc = getLoc(elem);
      ValueType elemLocType = getType(elemLoc);
      Parent parent = elemLocType.getParent().removeECR(structECR);
      elemLocType.setParent(parent);

      if (!ECRCache.add(elemLoc)) continue; // ECRCache has elemLoc

      cjoins.addAll(getCjoins(elemLoc));
      elemLoc.clearCCjoins(ccjoins);
      ccjoins.addAll(getCCjoins(elemLoc));
      elemLoc.clearCCjoins(ccjoins);

      if (elemLocType.isStruct()) {
        elemLocType = collapseStruct(elemLoc, elemLocType.asStruct(), ECRCache);
      }

      union(structECR, elemLoc);
      unionType = unionType == null ? elemLocType : unify(unionType, elemLocType);
    }
    unionType = unionType == null ? ValueType.bottom() : unionType;

    setType(structECR, unionType);
    ECR root = findRoot(structECR);

    for (Pair<Size, ECR> cjoinPair : ccjoins) ccjoin(cjoinPair.fst(), root, cjoinPair.snd());

    for (ECR joinECR : cjoins) cjoin(root, joinECR);

    return unionType;
  }
예제 #4
0
  /**
   * Unify value types <code>t1</code> and <code>t2</code>
   *
   * @param t1
   * @param t2
   * @return a unified value type
   */
  ValueType unify(ValueType t1, ValueType t2) {
    Pair<ValueType, ValueType> pair = swap(t1, t2);
    t1 = pair.fst();
    t2 = pair.snd();
    if (t1.equals(t2)) return t1;
    if (t1.isBottom()) {
      if (t1.hasOpTag()) t2.enableOpTag();
      return t2;
    }

    Parent parent = Parent.getLUB(t1.getParent(), t2.getParent());
    Size size = Size.getLUB(t1.getSize(), t2.getSize());
    boolean hasOpTag = t1.hasOpTag() || t2.hasOpTag();

    switch (t1.getKind()) {
      case BLANK:
        {
          switch (t2.getKind()) {
            case BLANK:
              return ValueType.blank(size, parent, hasOpTag);
            case SIMPLE:
              {
                return ValueType.simple(
                    t2.asSimple().getLoc(), t2.asSimple().getFunc(), size, parent, hasOpTag);
              }
            default:
              { // case STRUCT:
                return ValueType.struct(t2.asStruct().getFieldMap(), size, parent, hasOpTag);
              }
          }
        }
      case SIMPLE:
        {
          switch (t2.getKind()) {
            case SIMPLE:
              {
                ECR loc1 = t1.asSimple().getLoc();
                ECR loc2 = t2.asSimple().getLoc();
                ECR func1 = t1.asSimple().getFunc();
                ECR func2 = t2.asSimple().getFunc();

                ECR loc = join(loc1, loc2);
                ECR func = join(func1, func2);

                return ValueType.simple(loc, func, size, parent, hasOpTag);
              }
            default: // case STRUCT:
              throw new IllegalArgumentException();
          }
        }
      case STRUCT:
        {
          if (ValueTypeKind.STRUCT.equals(t2.getKind())) {
            RangeMap<Long, ECR> map = getCompatibleMap(t1.asStruct(), t2.asStruct());
            return ValueType.struct(map, size, parent, hasOpTag);
          } else {
            throw new IllegalArgumentException();
          }
        }
      default:
        { // Lambda
          assert (t2.isLambda());

          List<ECR> params = Lists.newArrayList();
          Iterator<ECR> paramItr1 = t1.asLambda().getParams().iterator();
          Iterator<ECR> paramItr2 = t2.asLambda().getParams().iterator();
          while (paramItr1.hasNext() && paramItr2.hasNext()) {
            ECR param1 = paramItr1.next();
            ECR param2 = paramItr2.next();
            ECR param = join(param1, param2);
            params.add(param);
          }

          while (paramItr1.hasNext()) params.add(paramItr1.next());
          while (paramItr2.hasNext()) params.add(paramItr2.next());

          ECR ret1 = t1.asLambda().getRet();
          ECR ret2 = t2.asLambda().getRet();
          ECR ret = join(ret1, ret2);

          return ValueType.lam(ret, params, parent);
        }
    }
  }
예제 #5
0
  void ccjoin(Size rangeSize, ECR e1, ECR e2) {
    ValueType type1 = getType(e1);
    if (type1.isBottom()) {
      addCCjoin(rangeSize, e1, e2);
      return;
    }

    Size size1 = type1.getSize();
    if (!Size.isLessThan(rangeSize, size1)) {
      addCCjoin(rangeSize, e1, e2);
      expand(e1, rangeSize); // expand(e1) would call setType(e1, ...) and thus ccjoin(e1, e2)
      return;
    }

    if (e1.equals(e2)) return;

    switch (type1.getKind()) {
      case BLANK:
        {
          addCCjoin(rangeSize, e1, e2);
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              setType(e2, ValueType.blank(rangeSize, Parent.getBottom()));
              return;
            default:
              Size size2 = type2.getSize();
              if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
              return;
          }
        }
      case SIMPLE:
        {
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              setType(
                  e2,
                  ValueType.simple(
                      type1.asSimple().getLoc(),
                      type1.asSimple().getFunc(),
                      rangeSize,
                      Parent.getBottom(),
                      type2.hasOpTag()));
              return;
            case BLANK:
              {
                setType(
                    e2,
                    ValueType.simple(
                        type1.asSimple().getLoc(),
                        type1.asSimple().getFunc(),
                        type2.getSize(),
                        type2.getParent(),
                        type2.hasOpTag()));
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case SIMPLE:
              {
                cjoin(type1.asSimple().getLoc(), type2.asSimple().getLoc());
                cjoin(type1.asSimple().getFunc(), type2.asSimple().getFunc());
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case STRUCT:
              {
                addCCjoin(rangeSize, e1, e2);
                collapseStruct(e2, type2.asStruct());
                return;
              }
            default: // lambda
              return;
          }
        }
      case STRUCT:
        {
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              {
                RangeMap<Long, ECR> fieldMapCopy = FieldRangeMap.create();
                fieldMapCopy.putAll(type1.asStruct().getFieldMap());
                setType(
                    e2,
                    ValueType.struct(
                        fieldMapCopy, rangeSize, Parent.getBottom(), type2.hasOpTag()));
                return;
              }
            case BLANK:
              {
                RangeMap<Long, ECR> fieldMapCopy = FieldRangeMap.create();
                fieldMapCopy.putAll(type1.asStruct().getFieldMap());
                Size size2 = type2.getSize();
                setType(
                    e2, ValueType.struct(fieldMapCopy, size2, type2.getParent(), type2.hasOpTag()));
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case SIMPLE:
              {
                addCCjoin(rangeSize, e1, e2);
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                for (ECR elemECR : type1.asStruct().getFieldMap().asMapOfRanges().values()) {
                  ValueType elemType = getType(elemECR);
                  Size elemSize = elemType.getSize();
                  ccjoin(elemSize, elemECR, e2);
                }
                return;
              }
            case STRUCT:
              {
                throw new IllegalArgumentException();
                //				Size size2 = type2.getSize();
                //				if(!Size.isLessThan(rangeSize, size2)) {
                //					addCCjoin(rangeSize, e1, e2);
                //					expand(e2, rangeSize); return;
                //				}
                //
                //				ValueType unifyStructType = unify(type1, type2); // unify structure type
                // eagerly
                //				setType(e1, unifyStructType);
                //				setType(e2, unifyStructType);
                //				return;
              }
            default:
              return; // lambda
          }
        }
      default:
        return; // lambda
    }
  }