Beispiel #1
0
void BytecodeTranslatorVisitor::visitForNode(ForNode* node) {
    onVisitNode(node);

    const AstVar* i = node->var();
    if (i->type() != VT_INT)
        ERROR("Non-iterable type in for loop");

    const BinaryOpNode* expr = node->inExpr()->asBinaryOpNode();
    if (expr == NULL || expr->kind() != tRANGE)
        ERROR("Invalid range in for loop");

    CONTEXT(function(), locals(), node->body()->scope(), typeStack());

    beforeProcessBlock();

    bool needTempVar = !expr->right()->isIntLiteralNode();
    AstVar* temp = NULL;
    if (needTempVar) {
        if (!scope()->declareVariable("<tempForEnd>", VT_INT))
            ERROR("internal error: temp name is unavailable");
        temp = scope()->lookupVariable("<tempForEnd>", false);
    }

    Label L_Begin(bytecode());
    Label L_End(bytecode());

    VISIT(expr->left());
    EMIT_STORE(i);

    if (needTempVar) {
        VISIT(expr->right());
        EMIT_STORE(temp);
        popType(VT_INT);
    }

    popType(VT_INT);
    EMIT_BIND(L_Begin);
    if (needTempVar)
        EMIT_LOAD(temp);
    else
        VISIT(expr->right());
    EMIT_LOAD(i);
    EMIT_BRANCH(BC_IFICMPG, L_End);

    processBlockNode(node->body());
    afterProcessBlock();

    /* i += 1 */
    EMIT_LOAD(i);
    EMIT(BC_ILOAD1);
    EMIT(BC_IADD);
    EMIT_STORE(i);

    EMIT_BRANCH(BC_JA, L_Begin);
    EMIT_BIND(L_End);

    pushType(VT_VOID);
}
Beispiel #2
0
void BytecodeTranslatorVisitor::visitBinaryOpNode(BinaryOpNode * node) {
    onVisitNode(node);

    TokenKind op = node->kind();
    if (op == tOR || op == tAND) {
        processLazyLogic(node);
        return;
    }

    VISIT(node->right()); ensureTopIsNumeric();
    VISIT(node->left());  ensureTopIsNumeric();

    if (tEQ <= op && op <= tLE)
        processComparison(node->kind());
    else if (tADD <= op && op <= tDIV)
        processNumericOperation(node->kind());
    else if (op == tMOD || op == tAXOR || op == tAOR || op == tAAND) {
        popType(VT_INT);
        ensureTopType(VT_INT);
        EMIT(op == tAXOR ? BC_IAXOR :
             op == tMOD  ? BC_IMOD  :
             op == tAOR  ? BC_IAOR  :
                           BC_IAAND);

    } else ERROR("Unknown binary op");
}
Beispiel #3
0
void BytecodeTranslatorVisitor::castTopsToCommonType() {
    VarType hi = popType();
    VarType lo = popType();

    if (hi != lo) {
        if (hi == VT_DOUBLE) {
            EMIT(BC_SWAP);
            EMIT(BC_I2D);
            EMIT(BC_SWAP);
        } else {
            EMIT(BC_I2D);
        }
        hi = VT_DOUBLE;
    }

    pushType(hi);
    pushType(hi);
}
Beispiel #4
0
void BytecodeTranslatorVisitor::processNumericOperation(TokenKind op) {
    castTopsToCommonType();

    switch (op) {
    case tADD: EMIT(TYPED(ADD)); break;
    case tSUB: EMIT(TYPED(SUB)); break;
    case tMUL: EMIT(TYPED(MUL)); break;
    default  : EMIT(TYPED(DIV)); break;
    }

    popType();
    ensureTopIsNumeric();
}
Beispiel #5
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;
        }
    }
}
Beispiel #6
0
void BytecodeTranslatorVisitor::processBlockNode(BlockNode* node) {
    for (uint32_t i = 0; i < node->nodes(); i++) {
        AstNode* ith = node->nodeAt(i);

        warningIf(isUnused(ith), "unused result of statement");

        VISIT(ith);
        VarType result = popType();

        if (result != VT_VOID && !ith->isReturnNode())
            EMIT(BC_POP);
    }
}
Beispiel #7
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);
}
Beispiel #8
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);
}
Beispiel #9
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);
}
Beispiel #10
0
void BytecodeTranslatorVisitor::processLazyLogic(BinaryOpNode* node) {
    Label L_Lazy(bytecode());
    Label L_End(bytecode());

    bool isOr = node->kind() == tOR;

    VISIT(node->left());
    popType(VT_INT);

    EMIT(BC_ILOAD0);
    EMIT_BRANCH(isOr ? BC_IFICMPNE : BC_IFICMPE, L_Lazy);

    VISIT(node->right());
    ensureTopType(VT_INT);

    EMIT_BRANCH(BC_JA, L_End);
    EMIT_BIND(L_Lazy);
    EMIT(isOr ? BC_ILOAD1 : BC_ILOAD0);
    EMIT_BIND(L_End);
}
Beispiel #11
0
void BytecodeTranslatorVisitor::visitStoreNode(StoreNode* node) {
    onVisitNode(node);

    visitTyped(node->value(), node->var()->type());
    pushType(node->var()->type());

    if (node->op() == tINCRSET || node->op() == tDECRSET) {
        ensureTopIsNumeric();
        EMIT_LOAD(node->var());

        if (node->op() == tINCRSET)
            EMIT(TYPED(ADD));
        else
            EMIT(TYPED(SUB));

    } else if (node->op() != tASSIGN)
        ERROR("Invalid store operation");

    EMIT_STORE(node->var());
    popType();
    pushType(VT_VOID); /* a = b = c is forbidden */
}
Beispiel #12
0
 bool popInt64()
 {
     return popType(OperandType::Int64);
 }
Beispiel #13
0
 bool popPointer()
 {
     return popType(OperandType::Pointer);
 }
Beispiel #14
0
void BytecodeTranslatorVisitor::popType(VarType expected) {
    if (topType() != expected)
        ERROR(string("Expected: ") + typeToName(expected) +
              ", got: " + typeToName(topType()));
    popType();
}
Beispiel #15
0
 bool popInt32()
 {
     return popType(OperandType::Int32);
 }
Beispiel #16
0
 bool popFloat32()
 {
     return popType(OperandType::Float32);
 }
Beispiel #17
0
 bool popFloat64()
 {
     return popType(OperandType::Float64);
 }
Beispiel #18
0
void BytecodeTranslatorVisitor::visitTyped(AstNode* node, VarType type) {
    VISIT(node);
    tryCast(type);
    popType(type);
}
Beispiel #19
0
 bool popOop()
 {
     return popType(OperandType::Oop);
 }