int main() { jit_context_t ctx; // Create a context to hold the JIT's primary stats ctx = jit_context_create(); // Lock the context while we build and compile the function jit_context_build_start(ctx); // Build the function signature jit_function_t function; jit_type_t params[3]; jit_type_t signature; params[0] = jit_type_int; params[1] = jit_type_int; params[2] = jit_type_int; signature = jit_type_create_signature(jit_abi_cdecl, jit_type_int, params, 3, 1); // Create the function object function = jit_function_create(ctx, signature); jit_type_free(signature); // Construct the function body jit_value_t x, y, z; x = jit_value_get_param(function, 0); y = jit_value_get_param(function, 1); z = jit_value_get_param(function, 2); jit_value_t temp1, temp2; temp1 = jit_insn_mul(function, x, y); temp2 = jit_insn_add(function, temp1, z); jit_insn_return(function, temp2); // Compile the function jit_function_compile(function); // Unlock the context jit_context_build_end(ctx); // Execute the function and print the result jit_int arg1, arg2, arg3; jit_int result; void *args[3]; arg1 = 3; arg2 = 5; arg3 = 2; args[0] = &arg1; args[1] = &arg2; args[2] = &arg3; jit_function_apply(function, args, &result); printf("mul_add(3,5,2) = %d\n", (int)result); // Clean up jit_context_destroy(ctx); return 0; }
int compile_mul_add(jit_function_t function) { jit_value_t x, y, z; jit_value_t temp1, temp2; printf("Compiling mul_add on demand\n"); x = jit_value_get_param(function, 0); y = jit_value_get_param(function, 1); z = jit_value_get_param(function, 2); temp1 = jit_insn_mul(function, x, y); temp2 = jit_insn_add(function, temp1, z); jit_insn_return(function, temp2); return 1; }
/* * Handle a binary opcode. */ static void JITCoder_Binary(ILCoder *coder, int opcode, ILEngineType type1, ILEngineType type2) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder); _ILJitStackItemNew(value2); _ILJitStackItemNew(value1); ILJitValue result = 0; _ILJitStackPop(jitCoder, value2); _ILJitStackPop(jitCoder, value1); switch(opcode) { case IL_OP_ADD: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_add(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_ADD_OVF: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_add_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_ADD_OVF_UN: { AdjustMixedBinary(jitCoder, 1, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_add_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_SUB: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_sub(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_SUB_OVF: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_sub_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_SUB_OVF_UN: { AdjustMixedBinary(jitCoder, 1, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_sub_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_MUL: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_mul(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_MUL_OVF: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_mul_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_MUL_OVF_UN: { AdjustMixedBinary(jitCoder, 1, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_mul_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_DIV: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_div(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_DIV_UN: { AdjustMixedBinary(jitCoder, 1, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_div(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_REM: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_rem(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_REM_UN: { AdjustMixedBinary(jitCoder, 1, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_rem(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_AND: { result = jit_insn_and(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_OR: { result = jit_insn_or(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_XOR: { result = jit_insn_xor(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; default: { return; } } _ILJitStackPushValue(jitCoder, result); }
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; }
static jit_value_t parse_recursive(jit_function_t func) { jit_value_t arg1, arg2, result; jit_function_t func1; double val; char *t = token(); // Somebody, do something with this! // It's awful monkeycoding, but I'm too lazy to rewrite it :3 if (STREQ(t, "F")) result = val_freq; else if (STREQ(t, "X")) result = jit_insn_convert(func, val_sample, jit_type_float64, 0); else if (STREQ(t, "LEN")) result = jit_insn_convert(func, val_length, jit_type_float64, 0); else if (STREQ(t, "RATE")) result = const_rate; else if (STREQ(t, "PI")) result = const_pi; else if (STREQ(t, "+")) result = jit_insn_add(func, parse_recursive(func), parse_recursive(func)); else if (STREQ(t, "-")) { arg1 = parse_recursive(func); arg2 = parse_recursive(func); result = jit_insn_sub(func, arg1, arg2); } else if (STREQ(t, "*")) result = jit_insn_mul(func, parse_recursive(func), parse_recursive(func)); else if (STREQ(t, "/")) { arg1 = parse_recursive(func); arg2 = parse_recursive(func); result = jit_insn_div(func, arg1, arg2); } else if (STREQ(t, "%")) { arg1 = parse_recursive(func); arg2 = parse_recursive(func); result = jit_insn_rem(func, arg1, arg2); } else if (STREQ(t, ">")) { arg1 = parse_recursive(func); arg2 = parse_recursive(func); result = jit_insn_gt(func, arg1, arg2); } else if (STREQ(t, "<")) { arg1 = parse_recursive(func); arg2 = parse_recursive(func); result = jit_insn_lt(func, arg1, arg2); } else if (STREQ(t, "if")) { jit_value_t tmpval = jit_value_create(func, jit_type_float64); jit_label_t lb_false = jit_label_undefined, lb_end = jit_label_undefined; jit_insn_branch_if_not(func, jit_insn_to_bool(func, parse_recursive(func)), &lb_false); jit_insn_store(func, tmpval, parse_recursive(func)); jit_insn_branch(func, &lb_end); jit_insn_label(func, &lb_false); jit_insn_store(func, tmpval, parse_recursive(func)); jit_insn_label(func, &lb_end); result = jit_insn_load(func, tmpval); } else if (STREQ(t, "sin")) result = jit_insn_sin(func, parse_recursive(func)); else if (sscanf(t, "%lf", &val) == 1) result = jit_value_create_float64_constant(func, jit_type_float64, val); else if ((func1 = get_function_by_name(t)) != NULL) { arg1 = parse_recursive(func); arg2 = parse_recursive(func); jit_value_t args[3] = {arg1, arg2, val_length}; result = jit_insn_call( func, t, func1, NULL, args, 3, 0); } else { LOGF("Unexpected token '%s'", t); result = NULL; } free(t); return result; }
jit_value jit_function::insn_mul (const jit_value& value1, const jit_value& value2) { value_wrap(jit_insn_mul(func, value1.raw(), value2.raw())); }
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 operator*(const jit_value& value1, const jit_value& value2) { return jit_value(jit_insn_mul(value_owner(value1, value2), value1.raw(), value2.raw())); }