Exemplo n.º 1
0
Type native_function_return_type(const php::Func* f,
                                 bool include_coercion_failures) {
  assert(f->nativeInfo);

  // If the function returns by ref, we can't say much about it. It can be a ref
  // or null.
  if (f->attrs & AttrReference) {
    return union_of(TRef, TInitNull);
  }

  // Infer the type from the HNI declaration
  auto t = [&]{
    auto const hni = f->nativeInfo->returnType;
    return hni ? from_DataType(*hni) : TInitCell;
  }();
  if (t.subtypeOf(BArr)) {
    if (f->retTypeConstraint.isVArray()) {
      assertx(!RuntimeOption::EvalHackArrDVArrs);
      t = TVArr;
    } else if (f->retTypeConstraint.isDArray()) {
      assertx(!RuntimeOption::EvalHackArrDVArrs);
      t = TDArr;
    } else if (f->retTypeConstraint.isArray()) {
      t = TPArr;
    }
  }

  // Non-simple types (ones that are represented by pointers) can always
  // possibly be null.
  if (t.subtypeOfAny(TStr, TArr, TVec, TDict,
                     TKeyset, TObj, TRes)) {
    t |= TInitNull;
  } else {
    // Otherwise it should be a simple type or possibly everything.
    assert(t == TInitCell || t.subtypeOfAny(TBool, TInt, TDbl, TNull));
  }

  if (include_coercion_failures) {
    // If parameter coercion fails, we can also get null or false depending on
    // the function.
    if (f->attrs & AttrParamCoerceModeNull) {
      t |= TInitNull;
    }
    if (f->attrs & AttrParamCoerceModeFalse) {
      t |= TFalse;
    }
  }

  return remove_uninit(t);
}
Exemplo n.º 2
0
void emitPrint(HTS& env) {
  auto const type = topC(env)->type();
  if (!type.subtypeOfAny(Type::Int, Type::Bool, Type::Null, Type::Str)) {
    interpOne(env, Type::Int, 1);
    return;
  }

  auto const cell = popC(env);

  Opcode op;
  if (type <= Type::Str) {
    op = PrintStr;
  } else if (type <= Type::Int) {
    op = PrintInt;
  } else if (type <= Type::Bool) {
    op = PrintBool;
  } else {
    assert(type <= Type::Null);
    op = Nop;
  }
  // the print helpers decref their arg, so don't decref pop'ed value
  if (op != Nop) {
    gen(env, op, cell);
  }
  push(env, cns(env, 1));
}
Exemplo n.º 3
0
void
IRTranslator::translateLtGtOp(const NormalizedInstruction& i) {
  auto const op = i.op();
  assert(op == Op::Lt || op == Op::Lte || op == Op::Gt || op == Op::Gte);

  auto leftType = m_hhbcTrans.topType(1, DataTypeGeneric);
  auto rightType = m_hhbcTrans.topType(0, DataTypeGeneric);
  if (!leftType.isKnownDataType() || !rightType.isKnownDataType()) {
    HHIR_UNIMPLEMENTED(LtGtOp-UnknownInput);
  }
  bool ok =
    leftType.subtypeOfAny (Type::Null, Type::Bool, Type::Int, Type::Dbl) &&
    rightType.subtypeOfAny(Type::Null, Type::Bool, Type::Int, Type::Dbl);

  HHIR_UNIMPLEMENTED_WHEN(!ok, LtGtOp);
  switch (op) {
    case Op::Lt  : HHIR_EMIT(Lt);
    case Op::Lte : HHIR_EMIT(Lte);
    case Op::Gt  : HHIR_EMIT(Gt);
    case Op::Gte : HHIR_EMIT(Gte);
    default    : HHIR_UNIMPLEMENTED(LtGtOp);
  }
}
Exemplo n.º 4
0
Type native_function_return_type(borrowed_ptr<const php::Func> f,
                                 bool include_coercion_failures) {
  assert(f->nativeInfo);

  // If the function returns by ref, we can't say much about it. It can be a ref
  // or null.
  if (f->attrs & AttrReference) {
    return union_of(TRef, TInitNull);
  }

  // Infer the type from the HNI declaration
  auto const hni = f->nativeInfo->returnType;
  auto t = hni ? from_DataType(*hni) : TInitCell;
  // Non-simple types (ones that are represented by pointers) can always
  // possibly be null.
  if (t.subtypeOfAny(TStr, TArr, TVec, TDict,
                     TKeyset, TObj, TRes)) {
    t = union_of(t, TInitNull);
  } else {
    // Otherwise it should be a simple type or possibly everything.
    assert(t == TInitCell || t.subtypeOfAny(TBool, TInt, TDbl, TNull));
  }

  if (include_coercion_failures) {
    // If parameter coercion fails, we can also get null or false depending on
    // the function.
    if (f->attrs & AttrParamCoerceModeNull) {
      t = union_of(t, TInitNull);
    }
    if (f->attrs & AttrParamCoerceModeFalse) {
      t = union_of(t, TFalse);
    }
  }

  return remove_uninit(t);
}
Exemplo n.º 5
0
void emitDecodeCufIter(IRGS& env, int32_t iterId, Offset relOffset) {
  auto const src        = popC(env);
  auto const type       = src->type();
  if (type.subtypeOfAny(TArr, TStr, TObj)) {
    auto const res = gen(
      env,
      DecodeCufIter,
      TBool,
      IterId(iterId),
      src,
      fp(env)
    );
    decRef(env, src);
    implCondJmp(env, bcOff(env) + relOffset, true, res);
  } else {
    decRef(env, src);
    jmpImpl(env, bcOff(env) + relOffset);
  }
}
Exemplo n.º 6
0
void
IRTranslator::translateLtGtOp(const NormalizedInstruction& i) {
  auto const op = i.op();
  assert(op == Op::Lt || op == Op::Lte || op == Op::Gt || op == Op::Gte);

  auto leftType = m_hhbcTrans.topType(1, DataTypeGeneric);
  auto rightType = m_hhbcTrans.topType(0, DataTypeGeneric);
  bool ok = equivDataTypes(leftType.toDataType(), rightType.toDataType()) &&
    leftType.subtypeOfAny(Type::Null, Type::Bool, Type::Int);

  HHIR_UNIMPLEMENTED_WHEN(!ok, LtGtOp);
  switch (op) {
    case Op::Lt  : HHIR_EMIT(Lt);
    case Op::Lte : HHIR_EMIT(Lte);
    case Op::Gt  : HHIR_EMIT(Gt);
    case Op::Gte : HHIR_EMIT(Gte);
    default    : HHIR_UNIMPLEMENTED(LtGtOp);
  }
}
Exemplo n.º 7
0
void emitDecodeCufIter(IRGS& env, int32_t iterId, Offset relOffset) {
  auto const src        = popC(env);
  auto const type       = src->type();
  if (type.subtypeOfAny(Type::Arr, Type::Str, Type::Obj)) {
    auto const res = gen(
      env,
      DecodeCufIter,
      Type::Bool,
      IterId(iterId),
      src,
      fp(env)
    );
    gen(env, DecRef, src);
    implCondJmp(env, bcOff(env) + relOffset, true, res);
  } else {
    gen(env, DecRef, src);
    jmpImpl(env,
            bcOff(env) + relOffset,
            instrJmpFlags(*env.currentNormalizedInstruction));
  }
}