jitcraft/Opcodes.cpp
author David Anderson <dvander@alliedmods.net>
Sat Jun 30 19:38:53 2012 -0700 (2012-06-30)
changeset 12 75e385f68b7e
parent 8 069d207a8f2a
child 13 627b6b94e774
permissions -rw-r--r--
Refactored Array, Code to be Objects. Removed Object tagging.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     6  * JITCraft is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * JITCraft. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #include "Opcodes.h"
    19 #include "Utility.h"
    20 #include "Code.h"
    21 #include "Zone.h"
    22 #include "Array.h"
    23 #include "Heap-inl.h"
    24 
    25 using namespace jc;
    26 
    27 OpInfo jc::OpcodeInfo[] =
    28 {
    29 #define OPDEF(name, number, text, length, uses, defs) \
    30     {text, length, uses, defs},
    31 #include "Opcodes.tbl"
    32 #undef OPDEF
    33 };
    34 
    35 void
    36 Code::init(ByteArray *bytecode, FixedArray *locals, FixedArray *args,
    37            FixedArray *maps, unsigned maxStackDepth, Module *module)
    38 {
    39     WRITE_FIELD_OBJ_NO_BARRIER(bytecode, bytecode);
    40     WRITE_FIELD_OBJ_NO_BARRIER(locals, locals);
    41     WRITE_FIELD_OBJ_NO_BARRIER(args, args);
    42     WRITE_FIELD_OBJ_NO_BARRIER(maps, maps);
    43     WRITE_FIELD(maxStackDepth, maxStackDepth);
    44     WRITE_FIELD(module, VoidPtr(module));
    45 }
    46 
    47 Code *
    48 Code::New(Zone *zone, ByteArray *bytecode, FixedArray *locals, FixedArray *args,
    49           FixedArray *maps, unsigned maxStackDepth, Module *module)
    50 {
    51     Object *obj = zone->allocate(MapKind_Code, sizeof(Code), Heap::Tenure_Old);
    52     if (!obj)
    53         return NULL;
    54 
    55     Code *code = Code::cast(obj);
    56     code->init(bytecode, locals, args, maps, maxStackDepth, module);
    57     return code;
    58 }
    59 
    60 // All jumps must be the same length.
    61 STATIC_ASSERT(OP_JL_LENGTH == OP_JUMP_LENGTH);
    62 STATIC_ASSERT(OP_JLE_LENGTH == OP_JUMP_LENGTH);
    63 STATIC_ASSERT(OP_JG_LENGTH == OP_JUMP_LENGTH);
    64 STATIC_ASSERT(OP_JGE_LENGTH == OP_JUMP_LENGTH);
    65 STATIC_ASSERT(OP_JEQ_LENGTH == OP_JUMP_LENGTH);
    66 STATIC_ASSERT(OP_JNE_LENGTH == OP_JUMP_LENGTH);
    67 STATIC_ASSERT(OP_JT_LENGTH == OP_JUMP_LENGTH);
    68 STATIC_ASSERT(OP_JF_LENGTH == OP_JUMP_LENGTH);
    69 
    70 void
    71 jc::Disassemble(Code *code, FILE *fp)
    72 {
    73     bytecode *pc = code->start();
    74     for (;;) {
    75         Opcode op = Opcode(*pc);
    76 
    77         fprintf(fp, "%-4d %s ", int(pc - code->start()), OpcodeInfo[op].name);
    78 
    79         switch (op) {
    80           case OP_NOP:
    81           case OP_RETURN:
    82           case OP_ADD:
    83           case OP_SUB:
    84           case OP_MUL:
    85           case OP_DIV:
    86           case OP_ADD_F:
    87           case OP_SUB_F:
    88           case OP_MUL_F:
    89           case OP_DIV_F:
    90           case OP_CVT_I2F:
    91           case OP_POP:
    92           case OP_GETARRAY_I:
    93           case OP_SETARRAY_I:
    94           case OP_GETARRAY_F:
    95           case OP_SETARRAY_F:
    96           case OP_GETARRAY_P:
    97           case OP_BOUNDS_STA:
    98           case OP_SHL:
    99           case OP_SHR:
   100           case OP_USHR:
   101           case OP_BITAND:
   102           case OP_BITOR:
   103           case OP_BITXOR:
   104             break;
   105 
   106           case OP_STOP:
   107             fprintf(fp, "\n");
   108             return;
   109 
   110           case OP_INT:
   111             fprintf(fp, "%d", READ_INT32(pc));
   112             break;
   113 
   114           case OP_FLOAT:
   115             fprintf(fp, "%f", READ_FLOAT(pc));
   116             break;
   117 
   118           case OP_JL:
   119           case OP_JLE:
   120           case OP_JG:
   121           case OP_JGE:
   122           case OP_JEQ:
   123           case OP_JNE:
   124           case OP_JT:
   125           case OP_JF:
   126           case OP_JUMP:
   127             fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
   128             break;
   129 
   130           case OP_LIFOARRAY:
   131           {
   132             // :TODO: use Local
   133             ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc)));
   134             fprintf(fp, "%s:", map->type()->innermost()->tag()
   135                                ? map->type()->innermost()->tag()
   136                                : "_");
   137             for (; map; map = map->contained()) {
   138                 Type *type = map->type();
   139                 fprintf(fp, "[%d]", type->elements());
   140             }
   141             break;
   142           }
   143 
   144           case OP_GETLOCAL:
   145           case OP_SETLOCAL:
   146           case OP_GETARG:
   147           case OP_SETARG:
   148           case OP_SAVELIFO:
   149           case OP_UNWINDLIFO:
   150           case OP_CALLGLOBAL:
   151             fprintf(fp, "%u", READ_UINT32(pc));
   152             break;
   153 
   154           default:
   155             // Unknown opcode!
   156             assert(false);
   157             return;
   158         }
   159 
   160         fprintf(fp, "\n");
   161         pc += OpcodeInfo[op].length;
   162         assert(pc < code->start() + code->length());
   163     }
   164 }