Ejemplo n.º 1
0
void BytecodeTranslatorVisitor::visitPrintNode(PrintNode * node) {
    onVisitNode(node);

    for (uint32_t i = 0; i < node->operands(); ++i) {
        VISIT(node->operandAt(i));

        switch (topType()) {
        case VT_INT:    EMIT(BC_IPRINT); break;
        case VT_DOUBLE: EMIT(BC_DPRINT); break;
        case VT_STRING: EMIT(BC_SPRINT); break;
        default: ERROR("Unprintable parameter");
        }

        popType();
    }

    pushType(VT_VOID);
}
Ejemplo n.º 2
0
void BytecodeTranslatorVisitor::tryCast(VarType to) {
    static Instruction castTable[VAR_TYPES_NUMBER][VAR_TYPES_NUMBER] = {BC_INVALID};
    castTable[VT_INT][VT_DOUBLE] = BC_I2D;
    castTable[VT_DOUBLE][VT_INT] = BC_D2I;

    VarType from = topType();
    if (from == to) return;

    Instruction cast = castTable[from][to];
    if (!cast)
        ERROR(string("Cast error from ") + typeToName(from) +
              " to " + typeToName(to));

    warningIf(cast == BC_D2I, "Casting double to int. I warned you!");

    EMIT(cast);
    popType();
    pushType(to);
}
Ejemplo n.º 3
0
void BytecodeTranslatorVisitor::falseJump(AstNode* node, Label& label) {
    bool isComparison = false;
    if (node->isBinaryOpNode()) {
        TokenKind kind = node->asBinaryOpNode()->kind();
        if (tEQ <= kind && kind <= tLE)
            isComparison = true;
    }
    if (!isComparison) {
        visitTyped(node, VT_INT);
        EMIT(BC_ILOAD0);
        EMIT_BRANCH(BC_IFICMPE, label);
    } else {
        /* Premature optimization is the root of all evil */
        VISIT(node->asBinaryOpNode()->right()); ensureTopIsNumeric();
        VISIT(node->asBinaryOpNode()->left());  ensureTopIsNumeric();
        TokenKind kind = node->asBinaryOpNode()->kind();

        castTopsToCommonType();

        Instruction cmp = TYPED(CMP);
        bool hack = topType() == VT_INT;
        popType();
        popType();

        if (!hack) {
            EMIT(cmp);
            EMIT(BC_ILOAD0);
        }

        switch (kind) {
        case tEQ:  EMIT_BRANCH(BC_IFICMPNE, label); break;
        case tNEQ: EMIT_BRANCH(BC_IFICMPE,  label); break;
        case tGT:  EMIT_BRANCH(hack ? BC_IFICMPLE : BC_IFICMPGE, label); break;
        case tGE:  EMIT_BRANCH(hack ? BC_IFICMPL  : BC_IFICMPG,  label); break;
        case tLT:  EMIT_BRANCH(hack ? BC_IFICMPGE : BC_IFICMPLE, label); break;
        default:   EMIT_BRANCH(hack ? BC_IFICMPG  : BC_IFICMPL,  label); break;
        }
    }
}
Ejemplo n.º 4
0
// All accesses to the stack and locals in this function use DataTypeGeneric so
// this function should only be used for inspecting state; when the values are
// actually used they must be constrained further.
Type predictedTypeFromLocation(IRGS& env, const Location& loc) {
  switch (loc.space) {
    case Location::Stack: {
      auto i = loc.bcRelOffset;
      assertx(i >= 0);
      if (i < env.irb->evalStack().size()) {
        return topType(env, i, DataTypeGeneric);
      } else {
        auto stackTy = env.irb->stackType(
          offsetFromIRSP(env, i),
          DataTypeGeneric
        );
        if (stackTy <= Type::BoxedCell) {
          return env.irb->stackInnerTypePrediction(
            offsetFromIRSP(env, i)).box();
        }
        return stackTy;
      }
    } break;
    case Location::Local:
      return env.irb->predictedLocalType(loc.offset);
    case Location::Litstr:
      return Type::cns(curUnit(env)->lookupLitstrId(loc.offset));
    case Location::Litint:
      return Type::cns(loc.offset);
    case Location::This:
      // Don't specialize $this for cloned closures which may have been re-bound
      if (curFunc(env)->hasForeignThis()) return Type::Obj;
      if (auto const cls = curFunc(env)->cls()) {
        return Type::SubObj(cls);
      }
      return Type::Obj;

    case Location::Iter:
    case Location::Invalid:
      break;
  }
  not_reached();
}
Ejemplo n.º 5
0
void BytecodeTranslatorVisitor::processComparison(TokenKind kind) {
    castTopsToCommonType();

    Instruction cmp = TYPED(CMP);
    int hack = topType() == VT_INT ? 3 : 0;
    popType();
    popType();
    pushType(VT_INT);

    if (kind == tNEQ) {
        EMIT(cmp);
        return;
    }

    if (!hack) {
        EMIT(cmp);
        EMIT(BC_ILOAD0);
    }

    Label L_Fail(bytecode());
    Label L_End(bytecode());

    switch (kind) {
    case tEQ: EMIT_BRANCH(BC_IFICMPE,  L_Fail); break;
    case tGT: EMIT_BRANCH(BC_IFICMPG,  L_Fail); break;
    case tGE: EMIT_BRANCH(BC_IFICMPGE, L_Fail); break;
    case tLT: EMIT_BRANCH(BC_IFICMPL,  L_Fail); break;
    default : EMIT_BRANCH(BC_IFICMPLE, L_Fail); break;
    }

    EMIT(BC_ILOAD1 - hack);
    EMIT_BRANCH(BC_JA, L_End);
    EMIT_BIND(L_Fail);
    EMIT(BC_ILOAD0 + hack);
    EMIT_BIND(L_End);
}
Ejemplo n.º 6
0
void BytecodeTranslatorVisitor::ensureTopIsNumeric() const {
    if (topType() != VT_INT && topType() != VT_DOUBLE)
        ERROR("Expected numeric type");
}
Ejemplo n.º 7
0
void BytecodeTranslatorVisitor::ensureTopType(VarType expected) const {
    if (topType() != expected)
        ERROR(string("Expected ") + typeToName(expected));
}
Ejemplo n.º 8
0
VarType BytecodeTranslatorVisitor::popType() {
    VarType type = topType();
    typeStack()->pop();
    return type;
}
Ejemplo n.º 9
0
void BytecodeTranslatorVisitor::popType(VarType expected) {
    if (topType() != expected)
        ERROR(string("Expected: ") + typeToName(expected) +
              ", got: " + typeToName(topType()));
    popType();
}
Ejemplo n.º 10
0
Type publicTopType(const IRGS& env, BCSPOffset idx) {
  // It's logically const, because we're using DataTypeGeneric.
  return topType(const_cast<IRGS&>(env), idx, DataTypeGeneric);
}
Ejemplo n.º 11
0
Type publicTopType(const HTS& env, int32_t idx) {
  // It's logically const, because we're using DataTypeGeneric.
  return topType(const_cast<HTS&>(env), idx, DataTypeGeneric);
}