dvander@0: /* dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@0: * This file is part of JITCraft. dvander@0: * dvander@0: * JITCraft is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@0: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@0: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@0: */ dvander@0: #include "Opcodes.h" dvander@0: #include "Utility.h" dvander@0: #include "Code.h" dvander@12: #include "Zone.h" dvander@12: #include "Array.h" dvander@12: #include "Heap-inl.h" dvander@0: dvander@0: using namespace jc; dvander@0: dvander@0: OpInfo jc::OpcodeInfo[] = dvander@0: { dvander@0: #define OPDEF(name, number, text, length, uses, defs) \ dvander@0: {text, length, uses, defs}, dvander@0: #include "Opcodes.tbl" dvander@0: #undef OPDEF dvander@0: }; dvander@0: dvander@12: Code * dvander@12: Code::New(Zone *zone, ByteArray *bytecode, FixedArray *locals, FixedArray *args, dvander@12: FixedArray *maps, unsigned maxStackDepth, Module *module) dvander@12: { dvander@12: Object *obj = zone->allocate(MapKind_Code, sizeof(Code), Heap::Tenure_Old); dvander@12: if (!obj) dvander@12: return NULL; dvander@12: dvander@12: Code *code = Code::cast(obj); dvander@13: code->bytecode_ = bytecode; dvander@13: code->locals_ = locals; dvander@13: code->args_ = args; dvander@13: code->maps_ = maps; dvander@13: code->maxStackDepth_ = maxStackDepth; dvander@13: code->module_ = module; dvander@12: return code; dvander@12: } dvander@12: dvander@0: // All jumps must be the same length. dvander@0: STATIC_ASSERT(OP_JL_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JLE_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JG_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JGE_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JEQ_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JNE_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JT_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JF_LENGTH == OP_JUMP_LENGTH); dvander@0: dvander@0: void dvander@0: jc::Disassemble(Code *code, FILE *fp) dvander@0: { dvander@0: bytecode *pc = code->start(); dvander@0: for (;;) { dvander@0: Opcode op = Opcode(*pc); dvander@0: dvander@0: fprintf(fp, "%-4d %s ", int(pc - code->start()), OpcodeInfo[op].name); dvander@0: dvander@0: switch (op) { dvander@0: case OP_NOP: dvander@0: case OP_RETURN: dvander@0: case OP_ADD: dvander@0: case OP_SUB: dvander@0: case OP_MUL: dvander@0: case OP_DIV: dvander@4: case OP_ADD_F: dvander@4: case OP_SUB_F: dvander@4: case OP_MUL_F: dvander@4: case OP_DIV_F: dvander@4: case OP_CVT_I2F: dvander@0: case OP_POP: dvander@6: case OP_GETARRAY_I: dvander@7: case OP_SETARRAY_I: dvander@7: case OP_GETARRAY_F: dvander@7: case OP_SETARRAY_F: dvander@6: case OP_GETARRAY_P: dvander@0: case OP_BOUNDS_STA: dvander@8: case OP_SHL: dvander@8: case OP_SHR: dvander@8: case OP_USHR: dvander@8: case OP_BITAND: dvander@8: case OP_BITOR: dvander@8: case OP_BITXOR: dvander@14: case OP_GETREF_I: dvander@14: case OP_SETREF_I: dvander@14: case OP_GETREF_F: dvander@14: case OP_SETREF_F: dvander@0: break; dvander@0: dvander@0: case OP_STOP: dvander@0: fprintf(fp, "\n"); dvander@0: return; dvander@0: dvander@0: case OP_INT: dvander@0: fprintf(fp, "%d", READ_INT32(pc)); dvander@0: break; dvander@0: dvander@4: case OP_FLOAT: dvander@4: fprintf(fp, "%f", READ_FLOAT(pc)); dvander@4: break; dvander@4: dvander@0: case OP_JL: dvander@0: case OP_JLE: dvander@0: case OP_JG: dvander@0: case OP_JGE: dvander@0: case OP_JEQ: dvander@0: case OP_JNE: dvander@0: case OP_JT: dvander@0: case OP_JF: dvander@0: case OP_JUMP: dvander@5: fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc)); dvander@0: break; dvander@0: dvander@12: case OP_LIFOARRAY: dvander@0: { dvander@12: // :TODO: use Local dvander@12: ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc))); dvander@12: fprintf(fp, "%s:", map->type()->innermost()->tag() dvander@12: ? map->type()->innermost()->tag() dvander@12: : "_"); dvander@12: for (; map; map = map->contained()) { dvander@12: Type *type = map->type(); dvander@12: fprintf(fp, "[%d]", type->elements()); dvander@12: } dvander@12: break; dvander@0: } dvander@0: dvander@0: case OP_GETLOCAL: dvander@0: case OP_SETLOCAL: dvander@0: case OP_GETARG: dvander@0: case OP_SETARG: dvander@12: case OP_SAVELIFO: dvander@12: case OP_UNWINDLIFO: dvander@0: case OP_CALLGLOBAL: dvander@14: case OP_VARREF_LIFO: dvander@14: case OP_ARGREF_LIFO: dvander@0: fprintf(fp, "%u", READ_UINT32(pc)); dvander@0: break; dvander@0: dvander@0: default: dvander@0: // Unknown opcode! dvander@0: assert(false); dvander@0: return; dvander@0: } dvander@0: dvander@0: fprintf(fp, "\n"); dvander@0: pc += OpcodeInfo[op].length; dvander@12: assert(pc < code->start() + code->length()); dvander@0: } dvander@0: }