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)); }
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; } }