void BytecodeGenerator::visitCallNode(CallNode* node) { BytecodeFunction* funToCall = _state.bcFunByName(node->name()); assert(funToCall); Bytecode* bc = _state.currentBcToFill(); for(size_t i = node->parametersNumber(); i > 0; --i) { node->parameterAt(i - 1)->visit(this); VarType expectedArgType = funToCall->parameterType(i - 1); VarType actualArgType = nodeType(node->parameterAt(i - 1)); if(actualArgType != expectedArgType) { Instruction castInsn = actualArgType == VT_INT ? BC_I2D : BC_D2I; bc->addInsn(castInsn); } } bc->addInsn(BC_CALL); bc->addInt16(funToCall->id()); }
void BytecodeGenerator::secondRun(Scope * scope) { Scope::FunctionIterator it(scope); while (it.hasNext()) { AstFunction *func = it.next(); BytecodeFunction *bcf = (BytecodeFunction*) code->functionByName(func->name()); fBC = bcf->bytecode(); currentFun = bcf->id(); returnType = func->returnType(); func->node()->body()->visit(this); bcf->setLocalsNumber(localsCounter[currentFun]); } for (size_t i = 0; i < scope->childScopeNumber(); ++i) { secondRun(scope->childScopeAt(i)); } }
void BytecodeVisitor::visitCallNode(CallNode *node) { LOG_Visitor("visitCallNode"); BytecodeFunction *calledFunction = context->getFunction(node->name()); if (node->parametersNumber() != calledFunction->parametersNumber()) { throw TranslationError("Incorrect number of parameters at calling function " + calledFunction->name(), node->position()); } for (int32_t i = node->parametersNumber() - 1; i >= 0; --i) { uint32_t j = (uint32_t) i; node->parameterAt(j)->visit(this); cast(calledFunction->parameterType(j), node, "casting call-node parameters"); } uint16_t functionID = calledFunction->id(); bc()->addInsn(BC_CALL); bc()->addUInt16(functionID); topOfStackType = calledFunction->returnType(); }
void BytecodeVisitor::visitCallNode(CallNode *node) { BytecodeFunction* bf = (BytecodeFunction*) code_->functionByName(node->name()); if (!bf) { throw new runtime_error("Function does not exist"); } if (node->parametersNumber() != bf->parametersNumber()) { throw new runtime_error("Uncorrect parameters number"); } for (size_t i = node->parametersNumber(); node->parametersNumber() > 0 && i > 0; --i) { node->parameterAt(i-1)->visit(this); castTos(bf->parameterType(i-1)); } bc()->addInsn(BC_CALL); bc()->addUInt16(bf->id()); setTosType(bf->returnType()); }
Id id() { return fn->id(); }
Status* InterpreterCodeImpl::execute(std::vector<Var*>& vars) { ByteStack stack; typedef std::map<uint16_t, ByteStorage> VarMap; VarMap var_map; for (std::vector<Var*>::iterator it = vars.begin(); it != vars.end(); ++it) { if ((*it)->name() == "#__INTERPRETER_TRACING__#") { m_trace = true; } } BytecodeFunction* function = (BytecodeFunction*) functionById(0); Bytecode* bytecode = function->bytecode(); for (size_t bci = 0; bci < bytecode->length();) { Instruction insn = BC_INVALID; size_t length = 1; // size of the BC_INVALID decodeInsn(bytecode, bci, insn, length); switch (insn) { case BC_INVALID: return new Status("BC_INVALID", bci); break; case BC_DLOAD: stack.pushTyped(bytecode->getDouble(bci + 1)); break; case BC_ILOAD: stack.pushTyped(bytecode->getInt64(bci + 1)); break; case BC_SLOAD: stack.pushTyped(bytecode->getUInt16(bci + 1)); break; case BC_DLOAD0: stack.pushTyped(double(0)); break; case BC_ILOAD0: stack.pushTyped(int64_t(0)); break; case BC_SLOAD0: stack.pushTyped(uint16_t(0)); break; case BC_DLOAD1: stack.pushTyped(double(1)); break; case BC_ILOAD1: stack.pushTyped(int64_t(1)); break; case BC_DADD: stack.pushDouble(stack.popDouble() + stack.popDouble()); break; case BC_IADD: stack.pushInt64(stack.popInt64() + stack.popInt64()); break; case BC_DSUB: stack.pushDouble(stack.popDouble() - stack.popDouble()); break; case BC_ISUB: stack.pushInt64(stack.popInt64() - stack.popInt64()); break; case BC_DMUL: stack.pushDouble(stack.popDouble() * stack.popDouble()); break; case BC_IMUL: stack.pushInt64(stack.popInt64() * stack.popInt64()); break; case BC_DDIV: stack.pushDouble(stack.popDouble() / stack.popDouble()); break; case BC_IDIV: stack.pushInt64(stack.popInt64() / stack.popInt64()); break; case BC_IMOD: stack.pushInt64(stack.popInt64() % stack.popInt64()); break; case BC_DNEG: stack.pushDouble(-stack.popDouble()); break; case BC_INEG: stack.pushInt64(-stack.popInt64()); break; case BC_IPRINT: std::cout << stack.popInt64(); break; case BC_DPRINT: std::cout << stack.popDouble(); break; case BC_SPRINT: std::cout << constantById(stack.popUInt16()); break; case BC_POP: stack.pop(); break; case BC_LOADDVAR0: stack.pushDouble(var_map[0].getDouble()); break; case BC_LOADDVAR1: stack.pushDouble(var_map[1].getDouble()); break; case BC_LOADDVAR2: stack.pushDouble(var_map[2].getDouble()); break; case BC_LOADDVAR3: stack.pushDouble(var_map[3].getDouble()); break; case BC_LOADIVAR0: stack.pushInt64(var_map[0].getInt64()); break; case BC_LOADIVAR1: stack.pushInt64(var_map[1].getInt64()); break; case BC_LOADIVAR2: stack.pushInt64(var_map[2].getInt64()); break; case BC_LOADIVAR3: stack.pushInt64(var_map[3].getInt64()); break; case BC_LOADSVAR0: stack.pushUInt16(var_map[0].getUInt16()); break; case BC_LOADSVAR1: stack.pushUInt16(var_map[1].getUInt16()); break; case BC_LOADSVAR2: stack.pushUInt16(var_map[2].getUInt16()); break; case BC_LOADSVAR3: stack.pushUInt16(var_map[3].getUInt16()); break; case BC_STOREDVAR0: var_map[0].setDouble(stack.popDouble()); break; case BC_STOREIVAR0: var_map[0].setInt64(stack.popInt64()); break; case BC_STORESVAR0: var_map[0].setUInt16(stack.popUInt16()); break; case BC_LOADDVAR: stack.pushDouble(var_map[bytecode->getUInt16(bci + 1)].getDouble()); break; case BC_LOADIVAR: stack.pushInt64(var_map[bytecode->getUInt16(bci + 1)].getInt64()); break; case BC_LOADSVAR: stack.pushUInt16(var_map[bytecode->getUInt16(bci + 1)].getUInt16()); break; case BC_STOREDVAR: var_map[bytecode->getUInt16(bci + 1)].setDouble(stack.popDouble()); break; case BC_STOREIVAR: var_map[bytecode->getUInt16(bci + 1)].setInt64(stack.popInt64()); break; case BC_STORESVAR: // out << name << " @" << getUInt16(bci + 1); var_map[bytecode->getUInt16(bci + 1)].setUInt16(stack.popUInt16()); break; // case BC_LOADCTXDVAR: // case BC_STORECTXDVAR: // case BC_LOADCTXIVAR: // case BC_STORECTXIVAR: // case BC_LOADCTXSVAR: // case BC_STORECTXSVAR: //// out << name << " @" << getUInt16(bci + 1) //// << ":" << getUInt16(bci + 3); // break; case BC_IFICMPNE: if (stack.popInt64() != stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPE: if (stack.popInt64() == stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPG: if (stack.popInt64() > stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPGE: if (stack.popInt64() >= stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPL: if (stack.popInt64() < stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPLE: if (stack.popInt64() <= stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_JA: bci += bytecode->getInt16(bci + 1) + 1; continue; break; case BC_CALL://{ stack.pushTyped(bci + length); stack.pushTyped(function->id()); // std::clog << "saving return address: " << function->id() << ":" << bci + length << std::endl; // uint16_t f = stack.popUInt16(); // size_t b = stack.popTyped<size_t>(); // std::clog << "checking return address: " << f << ":" << b << std::endl; // stack.pushTyped(bci + length); // stack.pushTyped(function->id()); function = (BytecodeFunction*) functionById(bytecode->getUInt16(bci + 1)); if (!function) { return new Status("Unresolved function ID\n", bci); } bytecode = function->bytecode(); bci = 0; continue; break;//} case BC_CALLNATIVE: return new Status("Native functions are currently not supported\n", bci); break; case BC_RETURN: { uint16_t new_function_id = stack.popUInt16(); // std::clog << "new func id=" << new_function_id << std::endl; function = (BytecodeFunction*) functionById(new_function_id); if (!function) { return new Status("Unresolved function ID\n", bci); } bytecode = function->bytecode(); size_t new_bci = stack.popTyped<size_t>(); // std::clog << "new bci=" << new_bci << std::endl; bci = new_bci; continue; break; } case BC_BREAK: return new Status("Breakpoints are currently not supported\n", bci); break; default: return new Status("Unknown or unsupported instruction\n", bci); } bci += length; } #ifdef ENABLE_TRACING std::cout << "Result = " << var_map[0].getInt64() << std::endl; #endif return 0; }