Exemplo n.º 1
0
static void binary_op(struct context *context, enum Opcode op)
{
    if (!context->runtime)
        VM_DEBUGPRINT("%s\n", NUM_TO_STRING(opcodes, op));

    struct variable *u = variable_pop(context);
    struct variable *v = variable_pop(context);
    enum VarType ut = (enum VarType)u->type;
    enum VarType vt = (enum VarType)v->type;
    struct variable *w;

    if (ut == VAR_NIL || vt == VAR_NIL) {
        w = binary_op_nil(context, op, u, v);
    } else if ((op == VM_EQU) || (op == VM_NEQ)) {
        bool same = variable_compare(context, u, v) ^ (op == VM_NEQ);
        w = variable_new_bool(context, same);
    } else {
        bool floater  = (ut == VAR_FLT && is_num(vt)) || (vt == VAR_FLT && is_num(ut));
        bool inter = (ut==VAR_INT || ut==VAR_BOOL) && (vt==VAR_INT || vt==VAR_BOOL);

        if (floater)                                w = binary_op_float(context, op, u, v);
        else if (inter)                             w = binary_op_int(context, op, v, u);
        else if (vt == VAR_STR || ut == VAR_STR)    w = binary_op_str(context, op, u, v);
        else if (vt == VAR_LST)                     w = binary_op_lst(context, op, u, v);
        else
            vm_exit_message(context, "unknown binary op");
    }

    variable_push(context, w);

    DEBUGPRINT("%s(%s,%s) = %s\n",
               NUM_TO_STRING(opcodes, op),
               variable_value_str(context, v),
               variable_value_str(context, u),
               variable_value_str(context, w));
}
Exemplo n.º 2
0
SILK_API void dump_icode(std::ostream& os, ICode *code, size_t base_offset, bool use_basic_block)
{
    if (NULL == code)
        return;

    switch (code->op)
    {
    case IC_MODULE:
    {
        ModuleICode *mc = SILK_DYNAMIC_CAST<ModuleICode*>(code);
        assert(NULL != mc && NULL != mc->proc);

        dump_symtbl(os, mc->proc->symbol_table, base_offset);

        if (use_basic_block)
            dump_basic_blocks(os, mc->proc->blocks, base_offset);
        else
            dump_icodes(os, mc->proc->codes, base_offset, false);
        break;
    }

    case IC_LOAD:
    {
        LoadICode *lc = SILK_DYNAMIC_CAST<LoadICode*>(code);
        assert(NULL != lc);

        align_tab(os, base_offset);
        os << dump_dst(lc->dst) << "%load " << dump_value(lc->src) << std::endl;
        break;
    }

    case IC_POS:
    case IC_NEG:
    case IC_NOT:
    case IC_BIT_NOT:
    {
        UnaryOpICode *uc = SILK_DYNAMIC_CAST<UnaryOpICode*>(code);
        assert(NULL != uc);

        align_tab(os, base_offset);
        os << dump_dst(uc->dst) << unary_op_str(uc->op) << " " <<
               dump_value(uc->src) << std::endl;
        break;
    }

    case IC_GETG:
    {
        UnaryOpICode *uc = SILK_DYNAMIC_CAST<UnaryOpICode*>(code);
        assert(NULL != uc);

        align_tab(os, base_offset);
        os << dump_dst(uc->dst) << "%getg " << uc->src.get_var_name() << std::endl;
        break;
    }

    case IC_SETG:
    {
        UnaryOpICode *uc = SILK_DYNAMIC_CAST<UnaryOpICode*>(code);
        assert(NULL != uc);

        align_tab(os, base_offset);
        os << "%setg " << uc->dst.get_var_name() << " " <<
            dump_value(uc->src) << std::endl;
        break;
    }

    case IC_ADD:
    case IC_SUB:
    case IC_MUL:
    case IC_DIV:
    case IC_MOD:

    case IC_BIT_AND:
    case IC_BIT_OR:
    case IC_BIT_XOR:
    case IC_LSHIFT:
    case IC_RSHIFT:
    case IC_URSHIFT:

    case IC_EQ:
    case IC_REF_EQ:
    case IC_LESS_THAN:

    case IC_INDEX:
    {
        BinaryOpICode *bc = SILK_DYNAMIC_CAST<BinaryOpICode*>(code);
        assert(NULL != bc);

        align_tab(os, base_offset);
        os << dump_dst(bc->dst) << binary_op_str(bc->op) << " " <<
               dump_value(bc->left) << " " << dump_value(bc->right) << std::endl;
        break;
    }

    case IC_SET_INDEX:
    {
        SetIndexICode *sic = SILK_DYNAMIC_CAST<SetIndexICode*>(code);
        assert(NULL != sic);

        align_tab(os, base_offset);
        os << "%setidx " << dump_value(sic->left) << " " <<
            dump_value(sic->index) << " " << dump_value(sic->value) << std::endl;
        break;
    }

    case IC_MEMBER:
    {
        MemberICode *mc = SILK_DYNAMIC_CAST<MemberICode*>(code);
        assert(NULL != mc);

        align_tab(os, base_offset);
        os << dump_dst(mc->dst) << "%mbr " << dump_value(mc->left) <<
               " " << mc->member << std::endl;
        break;
    }

    case IC_SET_MEMBER:
    {
        SetMemberICode *smc = SILK_DYNAMIC_CAST<SetMemberICode*>(code);
        assert(NULL != smc);

        align_tab(os, base_offset);
        os << "%setmbr " << dump_value(smc->left) << " " <<
            smc->member << " " << dump_value(smc->value) << std::endl;
        break;
    }

    case IC_BS:
    {
        BinSwitchICode *bsc = SILK_DYNAMIC_CAST<BinSwitchICode*>(code);
        assert(NULL != bsc);

        align_tab(os, base_offset);
        os << dump_dst(bsc->dst) << "%bs " << dump_value(bsc->condition) <<
               " " << dump_value(bsc->true_value) << " " <<
               dump_value(bsc->false_value) << std::endl;
        break;
    }

    case IC_PUSH:
    {
        PushICode *pc = SILK_DYNAMIC_CAST<PushICode*>(code);
        assert(NULL != pc);

        align_tab(os, base_offset);
        os << "%push " << dump_value(pc->value) << std::endl;
        break;
    }

    case IC_MAKE_ARRAY:
    {
        MakeArrayICode *mac = SILK_DYNAMIC_CAST<MakeArrayICode*>(code);
        assert(NULL != mac);

        align_tab(os, base_offset);
        os << dump_dst(mac->dst) << "%mkarr " << mac->array_size << std::endl;
        break;
    }

    case IC_MAKE_MAP:
    {
        MakeMapICode *mmc = SILK_DYNAMIC_CAST<MakeMapICode*>(code);
        assert(NULL != mmc);

        align_tab(os, base_offset);
        os << dump_dst(mmc->dst) << "%mkmap " << mmc->map_size << std::endl;
        break;
    }

    case IC_MAKE_SET:
    {
        MakeSetICode *smc = SILK_DYNAMIC_CAST<MakeSetICode*>(code);
        assert(NULL != smc);

        align_tab(os, base_offset);
        os << dump_dst(smc->dst) << "%mkset " << smc->set_size << std::endl;
        break;
    }

    case IC_MAKE_LAMBDA:
    {
        MakeLambdaICode *mlc = SILK_DYNAMIC_CAST<MakeLambdaICode*>(code);
        assert(NULL != mlc && NULL != mlc->proc);

        align_tab(os, base_offset);
        os << dump_dst(mlc->dst) << "%lambda " << mlc->name <<
               dump_params(mlc->params) << " {" << std::endl;

        dump_symtbl(os, mlc->proc->symbol_table, base_offset + 1);

        if (use_basic_block)
            dump_basic_blocks(os, mlc->proc->blocks, base_offset + 1);
        else
            dump_icodes(os, mlc->proc->codes, base_offset + 1, false);

        align_tab(os, base_offset);
        os << "}" << std::endl;
        break;
    }

    case IC_MAKE_CLASS:
    {
        MakeClassICode *mcc = SILK_DYNAMIC_CAST<MakeClassICode*>(code);
        assert(NULL != mcc);
        align_tab(os, base_offset);
        os << dump_dst(mcc->dst) << "%class " << mcc->class_name << " {" << std::endl;

        // Static fields
        for (size_t i = 0, sz = mcc->static_fields.size(); i < sz; ++i)
        {
            MakeClassICode::Field &f = mcc->static_fields.at(i);
            align_tab(os, base_offset + 1);
            os << "%sfield " << Variable::get_var_type_name(f.type) << " " <<
                   f.name << std::endl;
        }

        // Instance fields
        for (size_t i = 0, sz = mcc->instance_fields.size(); i < sz; ++i)
        {
            MakeClassICode::Field &f = mcc->instance_fields.at(i);
            align_tab(os, base_offset + 1);
            os << "%field " << Variable::get_var_type_name(f.type) << " " <<
                   f.name << std::endl;
        }

        // Static init
        align_tab(os, base_offset + 1);
        os << "%cinit {" << std::endl;
        assert(NULL != mcc->static_init_code.proc);
        if (use_basic_block)
            dump_basic_blocks(os, mcc->static_init_code.proc->blocks, base_offset + 2);
        else
            dump_icodes(os, mcc->static_init_code.proc->codes, base_offset + 2, false);
        align_tab(os, base_offset + 1);
        os << "}" << std::endl;

        // Instance init
        align_tab(os, base_offset + 1);
        os << "%init {" << std::endl;
        assert(NULL != mcc->instance_init_code.proc);
        if (use_basic_block)
            dump_basic_blocks(os, mcc->instance_init_code.proc->blocks, base_offset + 2);
        else
            dump_icodes(os, mcc->instance_init_code.proc->codes, base_offset + 2, false);
        align_tab(os, base_offset + 1);
        os << "}" << std::endl;

        // Constructor
        align_tab(os, base_offset + 1);
        os << "%constructor " << dump_params(mcc->constructor.params) << " {" << std::endl;
        assert(NULL != mcc->constructor.proc);
        if (use_basic_block)
            dump_basic_blocks(os, mcc->constructor.proc->blocks, base_offset + 2);
        else
            dump_icodes(os, mcc->constructor.proc->codes, base_offset + 2, false);
        align_tab(os, base_offset + 1);
        os << "}" << std::endl;

        // Static methods
        for (size_t i = 0, sz = mcc->static_methods.size(); i < sz; ++i)
        {
            MakeClassICode::Method &m = mcc->static_methods.at(i);
            align_tab(os, base_offset + 1);
            os << "%smethod " << m.name << dump_params(m.params) << " {" << std::endl;
            assert(NULL != m.proc);
            if (use_basic_block)
                dump_basic_blocks(os, m.proc->blocks, base_offset + 2);
            else
                dump_icodes(os, m.proc->codes, base_offset + 2, false);
            align_tab(os, base_offset + 1);
            os << "}" << std::endl;
        }

        // Instance methods
        for (size_t i = 0, sz = mcc->instance_methods.size(); i < sz; ++i)
        {
            MakeClassICode::Method &m = mcc->instance_methods.at(i);
            align_tab(os, base_offset + 1);
            os << "%method " << m.name << dump_params(m.params) << " {" << std::endl;
            assert(NULL != m.proc);
            if (use_basic_block)
                dump_basic_blocks(os, m.proc->blocks, base_offset + 2);
            else
                dump_icodes(os, m.proc->codes, base_offset + 2, false);
            align_tab(os, base_offset + 1);
            os << "}" << std::endl;
        }

        align_tab(os, base_offset);
        os << "}" << std::endl;
        break;
    }

    case IC_JMP:
    {
        JumpICode *jc = SILK_DYNAMIC_CAST<JumpICode*>(code);
        assert(NULL != jc);

        align_tab(os, base_offset);
        os << "%jmp " << jc->label << std::endl;
        break;
    }

    case IC_JMP_IF:
    {
        JumpIfICode *jic = SILK_DYNAMIC_CAST<JumpIfICode*>(code);
        assert(NULL != jic);
        align_tab(os, base_offset);
        os << "%jmpif " << dump_value(jic->condition) << " " << jic->label
            << std::endl;
        break;
    }

    case IC_SWITCH:
    {
        SwitchICode *sc = SILK_DYNAMIC_CAST<SwitchICode*>(code);
        assert(NULL != sc);
        align_tab(os, base_offset);
        os << "%switch " << dump_value(sc->switch_value) << " {" << std::endl;

        for (size_t i = 0, sz = sc->cases.size(); i < sz; ++i)
        {
            SwitchICode::Case *c = sc->cases.at(i);
            assert(NULL != c);
            align_tab(os, base_offset);
            if (c->value.is_void())
                os << "default: ";
            else
                os << "case " << dump_value(c->value) << ":";
            os << c->label << std::endl;
        }
        align_tab(os, base_offset);
        os << "}" << std::endl;;
        break;
    }

    case IC_LABEL:
    {
        LabelICode *lc = SILK_DYNAMIC_CAST<LabelICode*>(code);
        assert(NULL != lc);
        align_tab(os, base_offset);
        os << lc->label << ":" << std::endl;
        break;
    }

    case IC_INVOKE:
    {
        InvokeICode *ic = SILK_DYNAMIC_CAST<InvokeICode*>(code);
        assert(NULL != ic);
        align_tab(os, base_offset);
        os << dump_dst(ic->dst) << "%invoke " << dump_value(ic->func) <<
               " " << ic->argc << std::endl;
        break;
    }

    case IC_NEW:
    {
        NewICode *nc = SILK_DYNAMIC_CAST<NewICode*>(code);
        assert(NULL != nc);
        align_tab(os, base_offset);
        os << dump_dst(nc->dst) << "%new " << dump_value(nc->clazz) <<
               " " << nc->argc << std::endl;
        break;
    }

    case IC_RETURN:
    {
        ReturnICode *rc = SILK_DYNAMIC_CAST<ReturnICode*>(code);
        assert(NULL != rc);
        align_tab(os, base_offset);
        os << "%return ";
        if (rc->retval.is_void())
            os << "void";
        else
            os << dump_value(rc->retval);
        os << std::endl;
        break;
    }

    case IC_DEF_VAR:
    {
        DefVarICode *dvc = SILK_DYNAMIC_CAST<DefVarICode*>(code);
        assert(NULL != dvc);
        align_tab(os, base_offset);
        os << "%defvar " << Variable::get_var_type_name(dvc->type) << " " <<
               dvc->name << std::endl;
        break;
    }

    case IC_CLOSE_CLOSURE:
    {
        CloseClosureICode *ccc = SILK_DYNAMIC_CAST<CloseClosureICode*>(code);
        assert(NULL != ccc);
        align_tab(os, base_offset);
        os << "%closure " << ccc->register_pos << std::endl;
        break;
    }

    case IC_CONVERT:
    {
        ConvertTypeICode *ctc = SILK_DYNAMIC_CAST<ConvertTypeICode*>(code);
        assert(NULL != ctc);
        align_tab(os, base_offset);
        os << dump_dst(ctc->dst) << "%cvt " <<
              Variable::get_var_type_name(ctc->var_type) <<
              " " << dump_value(ctc->src) << std::endl;
        break;
    }

    case IC_IMPORT:
    {
        ImportICode *mc = SILK_DYNAMIC_CAST<ImportICode*>(code);
        assert(NULL != mc);
        align_tab(os, base_offset);
        os << dump_dst(mc->dst) << "%import \"" << mc->module << "\"" << std::endl;
        break;
    }

    default:
        align_tab(os, base_offset);
        os << "!!!!unknown icode " << code->op << std::endl;
        break;
    }
}