static jit_value_t pj_jit_internal(jit_function_t function, jit_value_t *var_values, int nvars, pj_term_t *term) { if (term->type == pj_ttype_variable) { pj_variable_t *v = (pj_variable_t *)term; return var_values[v->ivar]; } else if (term->type == pj_ttype_constant) { pj_constant_t *c = (pj_constant_t *)term; if (c->const_type == pj_int_type) return jit_value_create_nint_constant(function, jit_type_sys_int, c->value_u.int_value); else if (c->const_type == pj_uint_type) /* FIXME no jit_value_create_nuint_constant defined? */ return jit_value_create_nint_constant(function, jit_type_sys_int, c->value_u.uint_value); else if (c->const_type == pj_double_type) return jit_value_create_float64_constant(function, jit_type_sys_double, c->value_u.dbl_value); else abort(); } else if (term->type == pj_ttype_op) { return pj_jit_internal_op(function, var_values, nvars, (pj_op_t *)term); } else { abort(); } }
void emitDecrement(jit_function_t function, jit_value_t ptr, ops *unit) { jit_value_t tmp = jit_insn_load_relative(function, ptr, 0, jit_type_ubyte); jit_value_t numbyte = jit_value_create_nint_constant(function, jit_type_ubyte, unit->count); tmp = jit_insn_sub(function, tmp, numbyte); tmp = jit_insn_convert(function, tmp, jit_type_ubyte, 0); jit_insn_store_relative(function, ptr, 0, tmp); }
void JitInstanceMemberFunction::compileThisAdjustementThunk( size_t a_uiThisOffset ) const { o_assert(m_ThisAdjustmentThunks.find(a_uiThisOffset) == m_ThisAdjustmentThunks.end()); size_t argCount = getSignature()->getParameterCount()+1; // parameters+this jit_value_t* args = o_allocate_n(argCount, jit_value_t); // The fixing function has the same signature as the indirected one jit_function_t func = jit_function_create((jit_context_t)m_jit_context.context, jit_function_get_signature((jit_function_t)m_jit_function.function)); jit_value_t new_this = jit_insn_add(func, jit_value_get_param(func, 0), jit_value_create_nint_constant(func, jit_type_nint, -((int)a_uiThisOffset))); args[0] = new_this; size_t i = 1; for(;i<argCount;++i) { args[i] = jit_value_get_param(func, i); } string name = "[thunk]:"+m_pSubroutine->getQualifiedDecoratedName()+":adjustor{"+boost::lexical_cast<string>(a_uiThisOffset)+"}"; jit_insn_call(func , name.c_str() , (jit_function_t)m_jit_function.function , jit_function_get_signature((jit_function_t)m_jit_function.function) , args , argCount , 0); int result = jit_function_compile(func); o_assert(result != 0); o_deallocate_n(args, argCount, jit_value_t); m_ThisAdjustmentThunks[a_uiThisOffset] = func; }
void JitInstanceMemberFunction::compileVTableIndirectionFunction() { m_jit_virtual_indirection_function = jit_function_create((jit_context_t)m_jit_context.context, toJitSignature(m_eAbi, getSignature())); o_assert(m_jit_virtual_indirection_function.function); jit_context_build_start((jit_context_t)m_jit_context.context); size_t argCount = getSignature()->getParameterCount()+1; // parameters+this jit_value_t* args = o_allocate_n(argCount, jit_value_t); // The indirection has the same signature as the indirected one jit_value_t this_pointer = jit_value_get_param((jit_function_t)m_jit_virtual_indirection_function.function, 0); jit_value_t vtable_index = jit_value_create_nint_constant((jit_function_t)m_jit_virtual_indirection_function.function, jit_type_nuint, getInstanceMemberFunction()->getVirtualTableIndex()); jit_value_t vtable_array = jit_insn_load_relative ((jit_function_t)m_jit_virtual_indirection_function.function, this_pointer, 0, jit_type_void_ptr); jit_value_t vtable_pointer = jit_insn_load_elem((jit_function_t)m_jit_virtual_indirection_function.function, vtable_array, vtable_index, jit_type_void_ptr); size_t i = 0; for(;i<argCount;++i) { args[i] = jit_value_get_param((jit_function_t)m_jit_virtual_indirection_function.function, i); } jit_insn_call_indirect_vtable ((jit_function_t)m_jit_virtual_indirection_function.function, vtable_pointer, jit_function_get_signature((jit_function_t)m_jit_function.function), args, argCount, 0); int result = jit_function_compile((jit_function_t)m_jit_virtual_indirection_function.function); o_assert(result != 0); jit_context_build_end((jit_context_t)m_jit_context.context); o_deallocate_n(args, argCount, jit_value_t); }
jit_value jit_function::new_constant(jit_uint value, jit_type_t type) { if(!type) { type = jit_type_uint; } value_wrap(jit_value_create_nint_constant(func, type, (jit_nint)value)); }
jit_value jit_function::new_constant(void *value, jit_type_t type) { if(!type) { type = jit_type_void_ptr; } value_wrap(jit_value_create_nint_constant(func, type, (jit_nint)value)); }
/*@ * @deftypefun jit_value_t jit_value_create_constant (jit_function_t @var{func}, const jit_constant_t *@var{const_value}) * Create a new constant from a generic constant structure in the specified * function. Returns NULL if out of memory or if the type in * @var{const_value} is not suitable for a constant. * @end deftypefun @*/ jit_value_t jit_value_create_constant(jit_function_t func, const jit_constant_t *const_value) { jit_type_t stripped = jit_type_remove_tags(const_value->type); if(!stripped) { return 0; } switch(stripped->kind) { case JIT_TYPE_SBYTE: case JIT_TYPE_UBYTE: case JIT_TYPE_SHORT: case JIT_TYPE_USHORT: case JIT_TYPE_INT: case JIT_TYPE_UINT: return jit_value_create_nint_constant(func, const_value->type, const_value->un.int_value); case JIT_TYPE_NINT: case JIT_TYPE_NUINT: case JIT_TYPE_PTR: case JIT_TYPE_SIGNATURE: return jit_value_create_nint_constant(func, const_value->type, const_value->un.nint_value); case JIT_TYPE_LONG: case JIT_TYPE_ULONG: return jit_value_create_long_constant(func, const_value->type, const_value->un.long_value); case JIT_TYPE_FLOAT32: return jit_value_create_float32_constant(func, const_value->type, const_value->un.float32_value); case JIT_TYPE_FLOAT64: return jit_value_create_float64_constant(func, const_value->type, const_value->un.float64_value); case JIT_TYPE_NFLOAT: return jit_value_create_nfloat_constant(func, const_value->type, const_value->un.nfloat_value); } return 0; }
void *LibJITFormula::emit (VariableExprAST *expr) { // Create a pointer temporary with the address stored in it jit_value_t pointer = jit_value_create_nint_constant (function, jit_type_void_ptr, (jit_nint)expr->pointer); // Create a load instruction for this address return jit_insn_load_relative (function, pointer, 0, jit_type_float64); }
/* * Initialize the local value to 0. */ static int _ILJitLocalInit(ILJITCoder *coder, ILJitLocalSlot *slot) { if((slot->flags & _IL_JIT_VALUE_INITIALIZED) == 0) { ILJitType type = jit_value_get_type(slot->value); if(!jit_type_is_struct(type)) { int typeKind = jit_type_get_kind(type); ILJitValue constant = 0; if(_JIT_TYPEKIND_IS_FLOAT(typeKind)) { if(!(constant = jit_value_create_nfloat_constant(coder->jitFunction, type, (jit_nfloat)0))) { return 0; } jit_insn_store(coder->jitFunction, slot->value, constant); } else { if(_JIT_TYPEKIND_IS_LONG(typeKind)) { if(!(constant = jit_value_create_long_constant(coder->jitFunction, type, (jit_long)0))) { return 0; } jit_insn_store(coder->jitFunction, slot->value, constant); } else { if(!(constant = jit_value_create_nint_constant(coder->jitFunction, type, (jit_nint)0))) { return 0; } jit_insn_store(coder->jitFunction, slot->value, constant); } } } slot->flags |= _IL_JIT_VALUE_INITIALIZED; } return 1; }
/* * Output an entry for a table-based switch statement. */ static void JITCoder_SwitchEntry(ILCoder *_coder, ILUInt32 dest) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(_coder); ILJITLabel *label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); ILJitValue constant = jit_value_create_nint_constant(jitCoder->jitFunction, jit_type_nint, jitCoder->numSwitch); ILJitValue temp = jit_insn_eq(jitCoder->jitFunction, jitCoder->switchValue, constant); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); ++jitCoder->numSwitch; }
/* * Create the slots for the declared local variables. * Returns zero if out of memory. */ static int _ILJitLocalsCreate(ILJITCoder *coder, ILStandAloneSig *localVarSig) { if(!_ILJitLocalSlotsCreateLocals(coder, &(coder->jitLocals), localVarSig)) { return 0; } #ifdef IL_CONFIG_DEBUGGER if(coder->markBreakpoints) { ILUInt32 current; jit_value_t data1; jit_value_t data2; /* Set the offsets for each of the local variables */ for(current = 0; current < coder->jitLocals.numSlots; ++current) { ILJitLocalSlot *local = &_ILJitLocalSlotFromSlots(coder->jitLocals, current); /* Notify debugger about address of local variable */ /* Make the variable accessible for debugger */ jit_value_set_volatile(local->value); jit_value_set_addressable(local->value); /* Report address of the variable to debugger */ data1 = jit_value_create_nint_constant(coder->jitFunction, jit_type_nint, JIT_DEBUGGER_DATA1_LOCAL_VAR_ADDR); data2 = jit_insn_address_of(coder->jitFunction, local->value); jit_insn_mark_breakpoint_variable(coder->jitFunction, data1, data2); } } #endif #ifndef _IL_JIT_OPTIMIZE_INIT_LOCALS /* Initialize the locals. */ if(!_ILJitLocalsInit(coder)) { return 0; } #endif return 1; }
jit_value_t GPerlJITCompiler::compileMOV(GPerlVirtualMachineCode *pc, jit_function_t *func) { jit_value_t ret = NULL; switch (TYPE_CHECK(pc->v)) { case 0: break; case 1: ret = jit_value_create_nint_constant(*func, jit_type_int, pc->v.ivalue); break; case 2: break; case 3: break; default: break; } return ret; }
jit_value_t _make_ptr(jit_function_t func, void *val) { return jit_value_create_nint_constant(func, jit_type_void_ptr, (jit_nint) val); }
int __cdecl main(int argc, char **argv) { jit_context_t context; jit_type_t params[5]; jit_type_t signature; jit_function_t function; void* _this; bool a = true; bool b = true; bool c = true; bool d = true; void *args[5]; //jit_int result;` MyClass* pMyClass = new MyClass; void*** pMyClassCasted = (void***)pMyClass; void ** vtable_ptr = *pMyClassCasted; std::cout<<vtable_ptr[0]<<std::endl; typedef void (*void_method)(); void** new_vtable = (void**)malloc(sizeof(void*)*2); *pMyClassCasted = new_vtable; memcpy(new_vtable, vtable_ptr, NativeVTableIndexInspector::getVirtualMethodCount<MySubClass>()*sizeof(void*)); auto method_ptr = &MyClass::doSmth; auto method_ptr2 = &MyClass::doSmthElse; //std::cout<< "index of MyClass::doSmth"<< NativeVTableIndexInspector::getIndexOf(&MyClass::doSmth) <<std::endl; /* Create a context to hold the JIT's primary state */ context = jit_context_create(); // DEBUGGER debugger = jit_debugger_create(context); jit_debugger_set_hook(context, debugger_hook); /* // Create threads pthread_t thread0; pthread_t thread1; pthread_create(&thread0, NULL, thread0_func, NULL); pthread_create(&thread1, NULL, thread1_func, NULL);*/ /* Lock the context while we construct the function */ jit_context_build_start(context); /* Build the function signature */ params[0] = jit_type_void_ptr; // this params[1] = jit_type_sys_bool; // a params[2] = jit_type_sys_bool; // b params[3] = jit_type_sys_bool; // c params[4] = jit_type_sys_bool; // d signature = jit_type_create_signature(jit_abi_thiscall, jit_type_void_ptr, params, 1, 1); /* Create the function object */ function = jit_function_create(context, signature); //Expression* expression = new Or(new And(new ArgumentAccess(0), new ArgumentAccess(1)) // , new And(new ArgumentAccess(2), new NativeMethodCall(native_method))); void* hacked_ptr = *reinterpret_cast<void**>(&method_ptr); signature = jit_type_create_signature(jit_abi_thiscall, jit_type_void, params, 1, 1); jit_value_t args_this = jit_value_create_nint_constant(function, jit_type_void_ptr, 0); jit_insn_call_native(function, "doSmth", hacked_ptr, signature, &args_this, 1, 0); jit_insn_mark_breakpoint (function, JIT_DEBUGGER_DATA1_LINE, 0); jit_insn_return(function, jit_value_get_param(function, 0)); jit_insn_mark_breakpoint (function, JIT_DEBUGGER_DATA1_LINE, 1); /* Unlock the context. It will be automatically locked for us when the on-demand compiler is called */ jit_context_build_end(context); /* Execute the function and print the result. This will arrange to call the on-demand compiler to build the function's body */ jit_function_compile(function); _this = (void*)10; void* result; args[0] = &pMyClass; args[1] = &a; args[2] = &b; args[3] = &c; args[4] = &d; /*__asm { mov ecx, pMyClass };*/ jit_function_apply(function, args, &result); printf("(a && b) || (c && call) = %d\n", result); new_vtable[1] = jit_function_to_vtable_pointer(function); result = pMyClass->doSmthElse(); printf("(a && b) || (c && call) = %d\n", result); /* Execute the function again, to demonstrate that the on-demand compiler is not invoked a second time */ /*arg1 = 13; arg2 = 5; arg3 = 7; args[0] = &arg1; args[1] = &arg2; args[2] = &arg3; jit_function_apply(function, args, &result); printf("mul_add(13, 5, 7) = %d\n", (int)result);*/ /* Execute the function a third time, after it is recompiled */ /*arg1 = 2; arg2 = 18; arg3 = -3; args[0] = &arg1; args[1] = &arg2; args[2] = &arg3; jit_function_apply(function, args, &result); printf("mul_add(2, 18, -3) = %d\n", (int)result);*/ /* Clean up */ jit_context_destroy(context); system("pause"); /* Finished */ return 0; }
jit_function_t bf_compile(jit_context_t cx, FILE *fp) { jit_type_t params[1], putchar_params[1], signature, putchar_sig, getchar_sig; jit_value_t ptr, uptr, ubyte, tmp; bf_loop_t loop = NULL; ubyte_ptr = jit_type_create_pointer(jit_type_ubyte, 1); params[0] = ubyte_ptr; putchar_params[0] = jit_type_ubyte; signature = jit_type_create_signature(jit_abi_cdecl, jit_type_void, params, 1, 1); putchar_sig = jit_type_create_signature(jit_abi_cdecl, jit_type_ubyte, putchar_params, 1, 1); getchar_sig = jit_type_create_signature(jit_abi_cdecl, jit_type_ubyte, NULL, 0, 1); jit_function_t function = jit_function_create(cx, signature); ptr = jit_value_get_param(function, 0); uptr = jit_value_create_nint_constant(function, ubyte_ptr, 1); ubyte = jit_value_create_nint_constant(function, jit_type_ubyte, 1); ops *unit = (ops*)malloc(sizeof(ops)); unit->count = 0; int first = 1; while(!feof(fp)) { char c = fgetc(fp); if (first) { unit->token = c; first = 0; } switch(c) { case '>': OPTIMIZE_TOKEN('>') case '<': OPTIMIZE_TOKEN('<') case '+': OPTIMIZE_TOKEN('+') case '-': OPTIMIZE_TOKEN('-') case '.': emitOpcodes(function, ptr, unit); unit->token = '.'; tmp = jit_insn_load_relative(function, ptr, 0, jit_type_ubyte); jit_insn_call_native(function, "putchar", putchar, putchar_sig, &tmp, 1, JIT_CALL_NOTHROW); break; case ',': emitOpcodes(function, ptr, unit); unit->token = ','; jit_insn_call_native(function, "getchar", getchar, getchar_sig, NULL, 0, JIT_CALL_NOTHROW); jit_insn_store_relative(function, ptr, 0, tmp); break; case '[': emitOpcodes(function, ptr, unit); unit->token = '['; loop_start(function, &loop); tmp = jit_insn_load_relative(function, ptr, 0, jit_type_ubyte); jit_insn_branch_if_not(function, tmp, &loop->stop); break; case ']': emitOpcodes(function, ptr, unit); unit->token = ']'; loop_stop(function, &loop); break; } } jit_insn_return(function, NULL); jit_function_compile(function); return function; }
/*@ * @deftypefun int _jit_create_call_setup_insns (jit_function_t @var{func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{is_nested}, int @var{nested_level}, jit_value_t *@var{struct_return}, int @var{flags}) * Create instructions within @var{func} necessary to set up for a * function call to a function with the specified @var{signature}. * Use @code{jit_insn_push} to push values onto the system stack, * or @code{jit_insn_outgoing_reg} to copy values into call registers. * * If @var{is_nested} is non-zero, then it indicates that we are calling a * nested function within the current function's nested relationship tree. * The @var{nested_level} value will be -1 to call a child, zero to call a * sibling of @var{func}, 1 to call a sibling of the parent, 2 to call * a sibling of the grandparent, etc. The @code{jit_insn_setup_for_nested} * instruction should be used to create the nested function setup code. * * If the function returns a structure by pointer, then @var{struct_return} * must be set to a new local variable that will contain the returned * structure. Otherwise it should be set to NULL. * @end deftypefun @*/ int _jit_create_call_setup_insns (jit_function_t func, jit_type_t signature, jit_value_t *args, unsigned int num_args, int is_nested, int nested_level, jit_value_t *struct_return, int flags) { jit_type_t type; jit_type_t vtype; jit_value_t value; unsigned int arg_num; jit_nint offset; jit_nuint size; /* Regular or tail call? */ if((flags & JIT_CALL_TAIL) == 0) { /* Push all of the arguments in reverse order */ while(num_args > 0) { --num_args; type = jit_type_get_param(signature, num_args); type = jit_type_remove_tags(type); if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION) { /* If the value is a pointer, then we are pushing a structure argument by pointer rather than by local variable */ vtype = jit_type_normalize(jit_value_get_type(args[num_args])); if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE) { if(!jit_insn_push_ptr(func, args[num_args], type)) { return 0; } continue; } } if(!jit_insn_push(func, args[num_args])) { return 0; } } /* Do we need to add a structure return pointer argument? */ type = jit_type_get_return(signature); if(jit_type_return_via_pointer(type)) { value = jit_value_create(func, type); if(!value) { return 0; } *struct_return = value; value = jit_insn_address_of(func, value); if(!value) { return 0; } if(!jit_insn_push(func, value)) { return 0; } } else if((flags & JIT_CALL_NATIVE) != 0) { /* Native calls always return a return area pointer */ if(!jit_insn_push_return_area_ptr(func)) { return 0; } *struct_return = 0; } else { *struct_return = 0; } /* Do we need to add nested function scope information? */ if(is_nested) { if(!jit_insn_setup_for_nested(func, nested_level, -1)) { return 0; } } } else { /* Copy the arguments into our own parameter slots */ offset = -1; if(func->nested_parent) { offset -= 2; } type = jit_type_get_return(signature); if(jit_type_return_via_pointer(type)) { --offset; } for(arg_num = 0; arg_num < num_args; ++arg_num) { type = jit_type_get_param(signature, arg_num); value = jit_value_create(func, type); if(!value) { return 0; } if(!jit_insn_outgoing_frame_posn(func, value, offset)) { return 0; } type = jit_type_remove_tags(type); size = jit_type_get_size(type); offset -= (jit_nint)(JIT_NUM_ITEMS_IN_STRUCT(size)); if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION) { /* If the value is a pointer, then we are pushing a structure argument by pointer rather than by local variable */ vtype = jit_type_normalize(jit_value_get_type(args[arg_num])); if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE) { value = jit_insn_address_of(func, value); if(!value) { return 0; } if(!jit_insn_memcpy (func, value, args[arg_num], jit_value_create_nint_constant (func, jit_type_nint, (jit_nint)size))) { return 0; } continue; } } if(!jit_insn_store(func, value, args[arg_num])) { return 0; } } *struct_return = 0; } /* The call is ready to proceed */ return 1; }
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_t _make_ubyte(jit_function_t func, uint32_t val) { return jit_value_create_nint_constant(func, jit_type_ubyte, val); }
/* * Inline function to create a new string with the given length */ static int _ILJitSystemStringNew(ILJITCoder *jitCoder, ILMethod *method, ILCoderMethodInfo *methodInfo, ILJitStackItem *args, ILInt32 numArgs) { ILJitFunction jitFunction = ILJitFunctionFromILMethod(method); ILClass *stringClass = ILMethod_Owner(method); ILJitValue newString; ILJitValue callArgs[2]; if(!jitFunction) { /* We need to layout the class first. */ if(!_LayoutClass(ILExecThreadCurrent(), stringClass)) { return 0; } if(!(jitFunction = ILJitFunctionFromILMethod(method))) { return 0; } } #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) && defined(_IL_JIT_ENABLE_DEBUG) if(jitCoder->flags & IL_CODER_FLAG_STATS) { ILMutexLock(globalTraceMutex); fprintf(stdout, "Inline System.String::NewString\n"); ILMutexUnlock(globalTraceMutex); } #endif /* We call the alloc functions. */ /* They thow an out of memory exception so we don't need to care. */ callArgs[0] = jit_value_create_nint_constant(jitCoder->jitFunction, _IL_JIT_TYPE_VPTR, (jit_nint)stringClass); if(!callArgs[0]) { return 0; } callArgs[1] = _ILJitValueConvertImplicit(jitCoder->jitFunction, _ILJitStackItemValue(args[0]), _IL_JIT_TYPE_UINT32); if(!callArgs[1]) { return 0; } newString = jit_insn_call_native(jitCoder->jitFunction, "_ILJitStringAlloc", _ILJitStringAlloc, _ILJitSignature_ILJitStringAlloc, callArgs, 2, 0); if(!newString) { return 0; } _ILJitStackPushValue(jitCoder, newString); return 1; }
void emitDecrementPtr(jit_function_t function, jit_value_t ptr, ops *unit) { jit_value_t numbyte = jit_value_create_nint_constant(function, ubyte_ptr, unit->count); jit_value_t tmp = jit_insn_sub(function, ptr, numbyte); jit_insn_store(function, ptr, tmp); }
// LIBJIT void vm_cpu_4(uint32_t newPC,int opt, int size) { int i; PC = newPC; nPC = 4; RF[0] = 0; //Register $zero must always be zero RF[31] = 1; //Return default (if the program does not set to zero, should put error) uint32_t HI = 0, LO = 0; uint32_t offset = 4; uint8_t halted = 0; uint32_t instr; uint8_t op; uint8_t rs; uint8_t rt; uint8_t rd; int16_t immediate; uint32_t address; uint8_t shamt; uint8_t funct; uint64_t mult; /*lib jit variables */ jit_context_t context; jit_type_t signature; jit_function_t function; jit_type_t params[VM_MEMORY_SZ+2]; jit_int result; jit_value_t constant_sum; jit_value_t constant_while; jit_value_t v_it; jit_value_t constant_update; jit_value_t compare; jit_value_t reg[32]; /* Reg */ jit_value_t mem[VM_MEMORY_SZ]; /* Memory */ jit_label_t labels[10]; /* Labs for jumping :D */ jit_value_t sum, t_sum; void *args[VM_MEMORY_SZ+2]; /* Args */ jit_int arg_uint[VM_MEMORY_SZ+2]; /* Create a context to hold the JIT's primary state */ context = jit_context_create(); /* Lock the context while we build and compile the function */ jit_context_build_start(context); for(i=0; i<(VM_MEMORY_SZ+2); i++) { params[i] = jit_type_int; } signature = jit_type_create_signature(jit_abi_cdecl, jit_type_int, params, VM_MEMORY_SZ+2, 1); /* Create the function object */ function = jit_function_create(context, signature); jit_type_free(signature); // Read memory and start registers for(i=0; i<VM_MEMORY_SZ; i++) { //printf("%d\n",i); mem[i] = jit_value_get_param(function, i); } reg[0] = jit_value_get_param(function, VM_MEMORY_SZ); reg[31] = jit_value_get_param(function, VM_MEMORY_SZ+1); /*int verify = 0 - 1; for (i=1; i<VM_MEMORY_SZ; i++) { if((i%2)==0) { verify = verify + (i); } else { verify = verify - i; } } printf("verify %d\n", verify); */ int l_index; // Only doing the micro benchmark, for analysis // Addiu #define loopSize 10000 #define smallerLoopSize 1000 #define opPerLoop 100 // v_it = 0 ; constant_while = loopSize ; constant_update = 1 v_it = jit_value_create(function, jit_type_uint); constant_update = jit_value_create_nint_constant(function, jit_type_int, (int)0); jit_insn_store(function, v_it, constant_update); reg[2] = jit_value_create(function, jit_type_uint); constant_while = jit_value_create_nint_constant(function, jit_type_int, 0); jit_insn_store(function, reg[2], constant_while); reg[3] = jit_value_create(function, jit_type_uint); constant_while = jit_value_create_nint_constant(function, jit_type_int, 1); jit_insn_store(function, reg[3], constant_while); // do while (v_it < constant_while) { jit_insn_label(function, &labels[0]); if (opt == 0) { constant_update = jit_insn_add(function, reg[2], reg[3]); } else if(opt == 1) { constant_update = jit_insn_xor(function, reg[2], reg[3]); } else if(opt == 2) { constant_update = jit_insn_load(function, mem[0]); } for (l_index = 1; l_index < opPerLoop; l_index++) { if (opt == 0) { constant_update = jit_insn_add(function, constant_update, reg[3]); } else if(opt == 1) { constant_update = jit_insn_xor(function, constant_update, reg[3]); } else if(opt == 2) { constant_update = jit_insn_load(function, mem[l_index % 5]); } } jit_insn_store(function, reg[2], constant_update); // do while constant_update = jit_value_create_nint_constant(function, jit_type_uint, 1); constant_sum = jit_insn_add(function, v_it, constant_update); jit_insn_store(function, v_it, constant_sum); if(size > 0) { constant_while = jit_value_create_nint_constant(function, jit_type_uint, loopSize); } else { constant_while = jit_value_create_nint_constant(function, jit_type_uint, smallerLoopSize); } compare = jit_insn_gt(function, constant_while, v_it); jit_insn_branch_if(function, compare, &labels[0]); // Return //jit_insn_return(function, reg[2]); jit_insn_return(function, reg[2]); // START OF FINAL PART /* Compile the function */ jit_function_compile(function); /* Unlock the context */ jit_context_build_end(context); // Put memory and first registers for (i=0; i<VM_MEMORY_SZ; i++) { arg_uint[i] = (int) VM_memory[i]; //arg_uint[i] = (int)i; args[i] = &(arg_uint[i]); } arg_uint[VM_MEMORY_SZ] = 0; args[VM_MEMORY_SZ] = &(arg_uint[VM_MEMORY_SZ]); arg_uint[VM_MEMORY_SZ+1] = 1; args[VM_MEMORY_SZ+1] = &(arg_uint[VM_MEMORY_SZ+1]); jit_function_apply(function, args, &result); //printf("%d\n", result); return; /* end lib jit variables */ }
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; }