/* * Output a comparision between the 2 top most values on the evaluation stack. * The result value is returned. */ static ILJitValue OutputCompare(ILJITCoder *coder, int opcode, ILJitValue *value1, ILJitValue *value2) { switch(opcode) { case IL_OP_PREFIX + IL_PREFIX_OP_CEQ: case IL_OP_BEQ: { /* Test two values for equality */ AdjustMixedBinary(coder, 0, value1, value2); return jit_insn_eq(coder->jitFunction, *value1, *value2); } break; case IL_OP_BNE_UN: { /* Test two unsigned values for inequality */ AdjustMixedBinary(coder, 1, value1, value2); return jit_insn_ne(coder->jitFunction, *value1, *value2); } break; case IL_OP_PREFIX + IL_PREFIX_OP_CGT: case IL_OP_BGT: { /* Test two signed values for greater than */ AdjustMixedBinary(coder, 0, value1, value2); return jit_insn_gt(coder->jitFunction, *value1, *value2); } break; case IL_OP_PREFIX + IL_PREFIX_OP_CGT_UN: case IL_OP_BGT_UN: { /* Test two unsigned values for greater than */ AdjustMixedBinary(coder, 1, value1, value2); return jit_insn_gt(coder->jitFunction, *value1, *value2); } break; case IL_OP_BGE: { /* Test two signed values for greater than or equal */ AdjustMixedBinary(coder, 0, value1, value2); return jit_insn_ge(coder->jitFunction, *value1, *value2); } break; case IL_OP_BGE_UN: { /* Test two unsigned values for greater than or equal */ AdjustMixedBinary(coder, 1, value1, value2); return jit_insn_ge(coder->jitFunction, *value1, *value2); } break; case IL_OP_PREFIX + IL_PREFIX_OP_CLT: case IL_OP_BLT: { /* Test two signed values for less than */ AdjustMixedBinary(coder, 0, value1, value2); return jit_insn_lt(coder->jitFunction, *value1, *value2); } break; case IL_OP_PREFIX + IL_PREFIX_OP_CLT_UN: case IL_OP_BLT_UN: { /* Test two unsigned values for less than */ AdjustMixedBinary(coder, 1, value1, value2); return jit_insn_lt(coder->jitFunction, *value1, *value2); } break; case IL_OP_BLE: { /* Test two signed values for less than or equal */ AdjustMixedBinary(coder, 0, value1, value2); return jit_insn_le(coder->jitFunction, *value1, *value2); } break; case IL_OP_BLE_UN: { /* Test two unsigned values for less than or equal */ AdjustMixedBinary(coder, 1, value1, value2); return jit_insn_le(coder->jitFunction, *value1, *value2); } break; } return 0; }
static jit_value_t pj_jit_internal_op(jit_function_t function, jit_value_t *var_values, int nvars, pj_op_t *op) { jit_value_t tmp1, tmp2, rv; tmp1 = pj_jit_internal(function, var_values, nvars, op->op1); if (op->op2 != NULL) tmp2 = pj_jit_internal(function, var_values, nvars, op->op2); switch (op->optype) { case pj_unop_negate: rv = jit_insn_neg(function, tmp1); break; case pj_unop_sin: rv = jit_insn_sin(function, tmp1); break; case pj_unop_cos: rv = jit_insn_cos(function, tmp1); break; case pj_unop_abs: rv = jit_insn_abs(function, tmp1); break; case pj_unop_sqrt: rv = jit_insn_sqrt(function, tmp1); break; case pj_unop_log: rv = jit_insn_log(function, tmp1); break; case pj_unop_exp: rv = jit_insn_exp(function, tmp1); break; case pj_unop_not: rv = jit_insn_not(function, tmp1); break; case pj_unop_not_bool: rv = jit_insn_to_not_bool(function, tmp1); break; case pj_binop_add: rv = jit_insn_add(function, tmp1, tmp2); break; case pj_binop_subtract: rv = jit_insn_sub(function, tmp1, tmp2); break; case pj_binop_multiply: rv = jit_insn_mul(function, tmp1, tmp2); break; case pj_binop_divide: rv = jit_insn_div(function, tmp1, tmp2); break; case pj_binop_modulo: rv = jit_insn_rem(function, tmp1, tmp2); /* FIXME should this use jit_insn_rem_ieee? */ break; case pj_binop_atan2: rv = jit_insn_atan2(function, tmp1, tmp2); break; case pj_binop_left_shift: rv = jit_insn_shl(function, tmp1, tmp2); break; case pj_binop_right_shift: rv = jit_insn_shr(function, tmp1, tmp2); break; case pj_binop_and: rv = jit_insn_and(function, tmp1, tmp2); break; case pj_binop_or: rv = jit_insn_or(function, tmp1, tmp2); break; case pj_binop_xor: rv = jit_insn_xor(function, tmp1, tmp2); break; case pj_binop_eq: rv = jit_insn_eq(function, tmp1, tmp2); break; case pj_binop_ne: rv = jit_insn_ne(function, tmp1, tmp2); break; case pj_binop_lt: rv = jit_insn_lt(function, tmp1, tmp2); break; case pj_binop_le: rv = jit_insn_le(function, tmp1, tmp2); break; case pj_binop_gt: rv = jit_insn_gt(function, tmp1, tmp2); break; case pj_binop_ge: rv = jit_insn_ge(function, tmp1, tmp2); break; default: abort(); } return rv; }
void *LibJITFormula::emit (BinaryExprAST *expr) { // Deal with assign separately, we don't want to compile the LHS if (expr->op == "=") { VariableExprAST *var = dynamic_cast<VariableExprAST *>(expr->LHS); if (!var) return NULL; jit_value_t val = (jit_value_t)expr->RHS->generate (this); if (!val) return NULL; // Get a pointer for this variable jit_value_t pointer = jit_value_create_nint_constant (function, jit_type_void_ptr, (jit_nint)var->pointer); // Emit a store instruction jit_insn_store_relative (function, pointer, 0, val); // Return value return val; } // Generate both sides jit_value_t L = (jit_value_t)expr->LHS->generate (this); jit_value_t R = (jit_value_t)expr->RHS->generate (this); if (L == NULL || R == NULL) return NULL; if (expr->op == "<=") return jit_insn_le (function, L, R); else if (expr->op == ">=") return jit_insn_ge (function, L, R); else if (expr->op == "!=") return jit_insn_ne (function, L, R); else if (expr->op == "==") return jit_insn_eq (function, L, R); else if (expr->op == "<") return jit_insn_lt (function, L, R); else if (expr->op == ">") return jit_insn_gt (function, L, R); else if (expr->op == "+") return jit_insn_add (function, L, R); else if (expr->op == "-") return jit_insn_sub (function, L, R); else if (expr->op == "*") return jit_insn_mul (function, L, R); else if (expr->op == "/") return jit_insn_div (function, L, R); else if (expr->op == "^") { // jit_insn_pow seems to give the wrong results? jit_type_t params[2]; params[0] = jit_type_float64; params[1] = jit_type_float64; jit_type_t signature; signature = jit_type_create_signature (jit_abi_cdecl, jit_type_float64, params, 2, 1); jit_value_t args[2]; args[0] = L; args[1] = R; return jit_insn_call_native (function, "pow", (void *)((double (*)(double, double))pow), signature, args, 2, 0); } else return NULL; }
jit_value jit_function::insn_le (const jit_value& value1, const jit_value& value2) { value_wrap(jit_insn_le(func, value1.raw(), value2.raw())); }
jit_function_t GPerlJITCompiler::compile(JITParam *param) { GPerlVirtualMachineCode *pc = param->mtd; jit_context_t ctx = jit_context_create(); jit_context_build_start(ctx); int argc = param->argc; jit_type_t _params[argc]; for (int i = 0; i < argc; i++) { _params[i] = getJitType(param->arg_types[i]); } jit_type_t rtype = getJitType(param->return_type); jit_value_t curstack[32] = {0}; jit_value_t argstack[MAX_ARGSTACK_SIZE] = {0}; jit_type_t signature = jit_type_create_signature(jit_abi_fastcall, rtype, _params, argc, 0); jit_function_t func = jit_function_create(ctx, signature); jit_value_t _v[MAX_REG_SIZE] = {0}; GPerlJmpStack *jmp_stack = new GPerlJmpStack(); argc = 0; for (; pc->op != UNDEF; pc++) { if (jmp_stack->isJmp()) { GPerlJmpInfo *inf = jmp_stack->pop(); jit_insn_label(func, &inf->label); } switch (pc->op) { case LET: DBG_PL("COMPILE LET"); curstack[pc->dst] = _v[pc->src]; break; case MOV: DBG_PL("COMPILE MOV"); _v[pc->dst] = compileMOV(pc, &func); break; case ARRAY_ARGAT: { DBG_PL("COMPILE ARGAT"); jit_value_t arg = jit_value_get_param(func, pc->src); jit_nint offset = 48; jit_value_t list = jit_insn_load_relative(func, arg, offset, object_ptr_type); jit_value_t idx = jit_value_create_nint_constant(func, jit_type_int, pc->idx); jit_value_t elem = jit_insn_load_elem(func, list, idx, value_type); _v[pc->dst] = elem; break; } case vMOV: DBG_PL("COMPILE vMOV"); _v[pc->dst] = curstack[pc->src]; break; case gMOV: break; case ARGMOV: DBG_PL("COMPILE ARGMOV"); _v[pc->dst] = jit_value_get_param(func, pc->src); break; case ADD: DBG_PL("COMPILE ADD"); _v[pc->dst] = jit_insn_add(func, _v[pc->dst], _v[pc->src]); break; case SUB: DBG_PL("COMPILE SUB"); _v[pc->dst] = jit_insn_sub(func, _v[pc->dst], _v[pc->src]); break; case iADDC: { DBG_PL("COMPILE iADDC"); jit_value_t c = jit_value_create_nint_constant(func, jit_type_int, pc->v.ivalue); _v[pc->dst] = jit_insn_add(func, _v[pc->dst], c); break; } case iSUBC: { DBG_PL("COMPILE iSUBC"); jit_value_t c = jit_value_create_nint_constant(func, jit_type_int, pc->v.ivalue); _v[pc->dst] = jit_insn_sub(func, _v[pc->dst], c); break; } case IS: { DBG_PL("COMPILE IS"); jit_value_t c = jit_value_create_nint_constant(func, jit_type_int, 1); jit_value_t tmp = jit_insn_eq(func, _v[pc->dst], c); GPerlJmpInfo *inf = new GPerlJmpInfo(pc->jmp); jmp_stack->push(inf); jit_insn_branch_if_not(func, tmp, &inf->label); break; } case iJLC: { DBG_PL("COMPILE iJLC"); jit_value_t c = jit_value_create_nint_constant(func, jit_type_int, pc->v.ivalue); jit_value_t tmp = jit_insn_lt(func, _v[pc->dst], c); GPerlJmpInfo *inf = new GPerlJmpInfo(pc->jmp); jmp_stack->push(inf); jit_insn_branch_if_not(func, tmp, &inf->label); break; } case iJLEC: { DBG_PL("COMPILE iJLEC"); jit_value_t c = jit_value_create_nint_constant(func, jit_type_int, pc->v.ivalue); jit_value_t tmp = jit_insn_le(func, _v[pc->dst], c); GPerlJmpInfo *inf = new GPerlJmpInfo(pc->jmp); jmp_stack->push(inf); jit_insn_branch_if_not(func, tmp, &inf->label); break; } case JE: { DBG_PL("COMPILE JE"); jit_value_t tmp = jit_insn_eq(func, _v[pc->dst], _v[pc->src]); GPerlJmpInfo *inf = new GPerlJmpInfo(pc->jmp); jmp_stack->push(inf); jit_insn_branch_if_not(func, tmp, &inf->label); break; } case JLE: { DBG_PL("COMPILE JLE"); jit_value_t tmp = jit_insn_le(func, _v[pc->dst], _v[pc->src]); GPerlJmpInfo *inf = new GPerlJmpInfo(pc->jmp); jmp_stack->push(inf); jit_insn_branch_if_not(func, tmp, &inf->label); break; } case PUSH: DBG_PL("COMPILE PUSH"); argstack[pc->src] = _v[pc->dst]; argc++; break; case SELFCALL: { DBG_PL("COMPILE SELFCALL"); _v[pc->dst] = jit_insn_call(func, "", func, NULL, argstack, argc, 0);//JIT_CALL_TAIL); argc = 0; break; } case SELF_FASTCALL0: { DBG_PL("COMPILE SELF_FASTCALL0"); argstack[0] = _v[pc->arg0]; _v[pc->dst] = jit_insn_call(func, "", func, NULL, argstack, 1, 0);//JIT_CALL_TAIL); break; } case SELF_FASTCALL1: { DBG_PL("COMPILE SELF_FASTCALL1"); argstack[0] = _v[pc->arg0]; argstack[1] = _v[pc->arg1]; _v[pc->dst] = jit_insn_call(func, "", func, NULL, argstack, 2, 0);//JIT_CALL_TAIL); break; } case SELF_FASTCALL2: { DBG_PL("COMPILE SELF_FASTCALL2"); argstack[0] = _v[pc->arg0]; argstack[1] = _v[pc->arg1]; argstack[2] = _v[pc->arg2]; _v[pc->dst] = jit_insn_call(func, "", func, NULL, argstack, 3, 0);//JIT_CALL_TAIL); break; } case SELF_FASTCALL3: { DBG_PL("COMPILE SELF_FASTCALL3"); argstack[0] = _v[pc->arg0]; argstack[1] = _v[pc->arg1]; argstack[2] = _v[pc->arg2]; argstack[3] = _v[pc->arg3]; _v[pc->dst] = jit_insn_call(func, "", func, NULL, argstack, 4, 0);//JIT_CALL_TAIL); break; } case REF: { //int ret = 0; //if (TYPE_CHECK(v) > 1) { //GPerlObject *o = (GPerlObject *)getObject(v); //if (o->h.type == ArrayRef) { //ret = 1; //} //} //INT_init(reg[0], ret); break; } case RET: case JIT_COUNTDOWN_RET: DBG_PL("COMPILE RET"); _v[0] = _v[pc->src]; jit_insn_return(func, _v[0]); break; default: DBG_PL("COMPILE DEFALUT"); break; } } jit_function_compile(func); jit_context_build_end(ctx); return func; }