Пример #1
0
Type typeIncDec(IncDecOp op, Type t) {
  auto const overflowToDbl = isIncDecO(op);
  auto const val = tv(t);

  if (!val) {
    // Doubles always stay doubles
    if (t.subtypeOf(TDbl)) return TDbl;

    // Ints stay ints unless they can overflow to doubles
    if (t.subtypeOf(TInt)) {
      return overflowToDbl ? TNum : TInt;
    }

    // Null goes to 1 on ++, stays null on --. Uninit is folded to init.
    if (t.subtypeOf(TNull)) {
      return isInc(op) ? ival(1) : TInitNull;
    }

    // No-op on bool, array, resource, object.
    if (t.subtypeOfAny(TBool, TArr, TRes, TObj, TVec, TDict, TKeyset)) return t;

    // Last unhandled case: strings. These result in Int|Str because of the
    // behavior on strictly-numeric strings, and we can't express that yet.
    return TInitCell;
  }

  auto const inc = isInc(op);

  // We can't constprop with this eval_cell, because of the effects
  // on locals.
  auto resultTy = eval_cell([inc,overflowToDbl,val] {
    auto c = *val;
    if (inc) {
      (overflowToDbl ? cellIncO : cellInc)(c);
    } else {
      (overflowToDbl ? cellDecO : cellDec)(c);
    }
    return c;
  });
  if (!resultTy) resultTy = TInitCell;

  // We may have inferred a TSStr or TSArr with a value here, but at
  // runtime it will not be static.
  resultTy = loosen_staticness(*resultTy);
  return *resultTy;
}
Пример #2
0
void
IRTranslator::translateIncDecL(const NormalizedInstruction& i) {
  auto const op = static_cast<IncDecOp>(i.imm[1].u_OA);
  HHIR_EMIT(IncDecL, isPre(op), isInc(op), isIncDecO(op), i.imm[0].u_LA);
}