void BytecodeGenerator::visitCallNode(CallNode * node) { size_t n = node->parametersNumber(); TranslatedFunction * fun = code->functionByName(node->name()); for (size_t i = 0; i < n; ++i) { node->parameterAt(n - i - 1)->visit(this); convert(TOSType, fun->parameterType(n - i - 1)); } fBC->addInsn(BC_CALL); fBC->addInt16(fun->id()); TOSType = fun->returnType(); }
void ByteCodeVisitor::initVars(Scope *scope) { if (!scope) return; Scope::VarIterator varIt(scope); while (varIt.hasNext()) { AstVar *var = varIt.next(); if (!var->info()) { var->setInfo(new AstVarInfo(currentBytecodeFunction->id(), currentBytecodeFunction->localsNumber())); currentBytecodeFunction->setLocalsNumber(currentBytecodeFunction->localsNumber() + 1); if (currentBytecodeFunction->localsNumber() >= UINT16_MAX) { error("vars overflow in function <%s,id>", currentBytecodeFunction->name().c_str(), currentBytecodeFunction->id()); } } else { AstVarInfo *varInfo = (AstVarInfo *) var->info(); TranslatedFunction *function = interpreterCode->functionById(varInfo->contextId); error("variable already declared var <%s,%d,%d> for function %s", var->name().c_str(), varInfo->contextId, varInfo->id, function->name().c_str()); } } }
void Code::disassemble(ostream& out, FunctionFilter* filter) { for (uint32_t i = 0; i < _functions.size(); i++) { TranslatedFunction* function = _functions[i]; bool match = filter ? filter->matches(function) : true; if (match) { out << "function [" << function->id() << "] " << typeToName(function->returnType()) << " " << function->name() << "("; for (uint32_t i = 0; i < function->parametersNumber(); i++) { out << typeToName(function->parameterType(i)); if (i + 1 < function->parametersNumber()) { out << ", "; } } out << ")" << endl; function->disassemble(out); } } }
void SimpleInterpreter::run(ostream &out) { stack.resize(50); bytecodes.clear(); indices.clear(); vars.clear(); bytecodes.push_back(bytecode); indices.push_back(0); contextID.push_back(0); callsCounter.push_back(0); SP = 0; while (!bytecodes.empty()) { indexType ¤tIndex = indices.back(); Bytecode &bytecode = *bytecodes.back(); Instruction instruction = bytecode.getInsn(currentIndex); size_t instructionLength = bytecodeLength(instruction); #ifdef LOG_INTERPRETER const char* bcName = bytecodeName(instruction, 0); cout << "index: " << currentIndex << ", instruction: " << bcName << endl; #endif switch (instruction) { case BC_DLOAD: pushVariable(bytecode.getDouble(currentIndex + 1)); break; case BC_ILOAD: pushVariable(bytecode.getInt64(currentIndex + 1)); break; case BC_SLOAD: pushVariable(constantById(bytecode.getUInt16(currentIndex + 1)).c_str()); break; case BC_DLOAD0: pushVariable(0.0); break; case BC_ILOAD0: pushVariable((signedIntType) 0); break; case BC_SLOAD0: pushVariable(""); break; case BC_DLOAD1: pushVariable(1.0); break; case BC_ILOAD1: pushVariable((signedIntType) 1); break; case BC_DLOADM1: pushVariable(-1.0); break; case BC_ILOADM1: pushVariable((signedIntType) - 1); break; case BC_DADD: binary_operation(VT_DOUBLE, add<double>); break; case BC_IADD: binary_operation(VT_INT, add < signedIntType > ); break; case BC_DSUB: binary_operation(VT_DOUBLE, sub<double>); break; case BC_ISUB: binary_operation(VT_INT, sub < signedIntType > ); break; case BC_DMUL: binary_operation(VT_DOUBLE, mul<double>); break; case BC_IMUL: binary_operation(VT_INT, mul < signedIntType > ); break; case BC_DDIV: binary_operation(VT_DOUBLE, _div<double>); break; case BC_IDIV: binary_operation(VT_INT, _div < signedIntType > ); break; case BC_IMOD: binary_operation(VT_INT, mod < signedIntType > ); break; case BC_DNEG: unary_operation(VT_DOUBLE, neg<double>); break; case BC_INEG: unary_operation(VT_INT, neg < signedIntType > ); break; case BC_IAOR: binary_operation(VT_INT, _or < signedIntType > ); break; case BC_IAAND: binary_operation(VT_INT, _and < signedIntType > ); break; case BC_IAXOR: binary_operation(VT_INT, _xor < signedIntType > ); break; case BC_IPRINT: out << popVariable().getIntValue(); out.flush(); break; case BC_DPRINT: out << popVariable().getDoubleValue(); out.flush(); break; case BC_SPRINT: out << popVariable().getStringValue(); out.flush(); break; case BC_SWAP: { auto v1 = popVariable(); auto v2 = popVariable(); pushVariable(v1); pushVariable(v2); break; } case BC_STOREDVAR0: case BC_STOREIVAR0: case BC_STORESVAR0: storeVariable(0); break; case BC_STOREDVAR1: case BC_STOREIVAR1: case BC_STORESVAR1: storeVariable(1); break; case BC_STOREDVAR2: case BC_STOREIVAR2: case BC_STORESVAR2: storeVariable(2); break; case BC_STOREDVAR3: case BC_STOREIVAR3: case BC_STORESVAR3: storeVariable(3); break; case BC_LOADDVAR: case BC_LOADIVAR: case BC_LOADSVAR: pushVariable(loadVariable(bytecode.getUInt16(currentIndex + 1))); break; case BC_LOADDVAR0: case BC_LOADIVAR0: case BC_LOADSVAR0: pushVariable(loadVariable(0)); break; case BC_LOADDVAR1: case BC_LOADIVAR1: case BC_LOADSVAR1: pushVariable(loadVariable(1)); break; case BC_LOADIVAR2: case BC_LOADSVAR2: case BC_LOADDVAR2: pushVariable(loadVariable(2)); break; case BC_LOADDVAR3: case BC_LOADIVAR3: case BC_LOADSVAR3: pushVariable(loadVariable(3)); break; case BC_STOREDVAR: case BC_STOREIVAR: case BC_STORESVAR: storeVariable(bytecode.getUInt16(currentIndex + 1)); break; case BC_LOADCTXDVAR: case BC_LOADCTXIVAR: case BC_LOADCTXSVAR: pushVariable(loadVariable(bytecode.getUInt16(currentIndex + 1), bytecode.getUInt16(currentIndex + 3))); break; case BC_STORECTXDVAR: case BC_STORECTXIVAR: case BC_STORECTXSVAR: storeVariable(bytecode.getUInt16(currentIndex + 1), bytecode.getUInt16(currentIndex + 3)); break; case BC_DCMP: binary_operation<double, signedIntType>(VT_DOUBLE, _cmp<double>); break; case BC_ICMP: binary_operation(VT_INT, _cmp < signedIntType > ); break; case BC_JA: { currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPNE: { if (!check_condition(_neq<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPE: { if (!check_condition(_eq<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPG: { if (!check_condition(_g<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPGE: { if (!check_condition(_ge<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPL: { if (!check_condition(_l<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPLE: { if (!check_condition(_le<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_STOP: { indices.clear(); bytecodes.clear(); continue; } case BC_CALLNATIVE: { callNative(bytecode.getUInt16(currentIndex + 1)); break; } case BC_CALL: { TranslatedFunction *f = functionById(bytecode.getUInt16(currentIndex + 1)); bytecodes.push_back(static_cast<BytecodeFunction *>(f)->bytecode()); indices.push_back(0); contextID.push_back(f->id()); detectCallWithFunctionID(contextID.back()); continue; } case BC_RETURN: { indices.pop_back(); bytecodes.pop_back(); if (!indices.empty()) { indices.back() += bytecodeLength(BC_CALL); } if (callsCounter[contextID.back()] > 0) { callsCounter[contextID.back()]--; } contextID.pop_back(); continue; } case BC_I2D: pushVariable((double) popVariable().getIntValue()); break; case BC_D2I: pushVariable((signedIntType) popVariable().getDoubleValue()); break; case BC_S2I: pushVariable((signedIntType) popVariable().getStringValue()); break; case BC_BREAK: break; case BC_INVALID: throw InterpretationError("BC_Invalid instruction"); default: throw InterpretationError(string("Unknown interpreting instruction: ") + bytecodeName(instruction, 0)); } currentIndex += instructionLength; } }