/* * Handle a unary opcode. */ static void JITCoder_Unary(ILCoder *coder, int opcode, ILEngineType type) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder); _ILJitStackItemNew(value); ILJitValue result = 0; _ILJitStackPop(jitCoder, value); switch(opcode) { case IL_OP_NEG: { result = jit_insn_neg(jitCoder->jitFunction, _ILJitStackItemValue(value)); } break; case IL_OP_NOT: { result = jit_insn_not(jitCoder->jitFunction, _ILJitStackItemValue(value)); } break; case IL_OP_CKFINITE: { /* Check the stack Top-most F value to see if it is finite */ result = jit_insn_is_finite(jitCoder->jitFunction, _ILJitStackItemValue(value)); } break; } _ILJitStackPushValue(jitCoder, result); }
/* * Inline function to get the character at the specified indexe in a * string. */ static int _ILJitSystemStringChars(ILJITCoder *jitCoder, ILMethod *method, ILCoderMethodInfo *methodInfo, ILJitStackItem *args, ILInt32 numArgs) { ILJitFunction jitFunction = ILJitFunctionFromILMethod(method); ILClass *stringClass = ILMethod_Owner(method); ILJitValue length; ILJitValue stringBase; ILJitValue returnValue; 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::get_Chars\n"); ILMutexUnlock(globalTraceMutex); } #endif _ILJitStackItemCheckNull(jitCoder, args[0]); length = _ILJitStringGetLength(jitCoder->jitFunction, _ILJitStackItemValue(args[0])); JITC_START_CHECK_STRING_INDEX(jitCoder, length, _ILJitStackItemValue(args[1])) stringBase = _ILJitStringGetStart(jitCoder->jitFunction, _ILJitStackItemValue(args[0])); returnValue = jit_insn_load_elem(jitCoder->jitFunction, stringBase, _ILJitStackItemValue(args[1]), _IL_JIT_TYPE_CHAR); JITC_END_CHECK_STRING_INDEX(jitCoder) _ILJitStackPushValue(jitCoder, returnValue); return 1; }
/* * Merge the current jitStack status with the one saved in the label. */ static int _ILJitLabelMergeStack(ILJITCoder *coder, ILJITLabel *label) { int coderStackHeight = _ILJitStackHeight(coder); #ifdef _IL_JIT_ENABLE_INLINE int coderStackBase; if(coder->currentInlineContext) { coderStackBase = coder->currentInlineContext->stackBase; coderStackHeight -= coderStackBase; } else { coderStackBase = 0; } #else /* !_IL_JIT_ENABLE_INLINE */ int coderStackBase = 0; #endif /* !_IL_JIT_ENABLE_INLINE */ if(label->labelType & (_IL_JIT_LABEL_NORMAL | _IL_JIT_LABEL_STARTCATCH)) { /* Verify that the stack sizes match. */ if(coderStackHeight != label->stackSize) { fprintf(stdout, "Stack sizes don't match!\n"); /* return 0; */ } if(coderStackHeight > 0) { int current = 0; /* Now save the current stack state. */ for(current = 0; current < coderStackHeight; current++) { ILJitStackItem *stackItem = _ILJitStackItemGet(coder, coderStackBase + current); if(_ILJitStackItemValue(*stackItem) != label->jitStack[current]) { /* store the changed value to the saved stack. */ jit_insn_store(coder->jitFunction, label->jitStack[current], _ILJitStackItemValue(*stackItem)); } } } } return 1; }
/* * Output the start of a table-based switch statement. */ static void JITCoder_SwitchStart(ILCoder *coder, ILUInt32 numEntries) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder); _ILJitStackItemNew(value); _ILJitStackPop(jitCoder, value); jitCoder->numSwitch = 0; jitCoder->maxSwitch = numEntries; jitCoder->switchValue = _ILJitStackItemValue(value); }
/* * Output a comparison instruction. */ static void JITCoder_Compare(ILCoder *coder, int opcode, ILEngineType type1, ILEngineType type2, int invertTest) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder); _ILJitStackItemNew(value2); _ILJitStackItemNew(value1); ILJitValue temp; _ILJitStackPop(jitCoder, value2); _ILJitStackPop(jitCoder, value1); temp = OutputCompare(jitCoder, opcode, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); if(invertTest) { temp = jit_insn_to_not_bool(jitCoder->jitFunction, temp); } else { temp = jit_insn_to_bool(jitCoder->jitFunction, temp); } _ILJitStackPushValue(jitCoder, temp); }
/* * Save the current jitStack status to the label. * This is done when the label is referenced the first time. */ static int _ILJitLabelSaveStack(ILJITCoder *coder, ILJITLabel *label) { int coderStackHeight = _ILJitStackHeight(coder); #ifdef _IL_JIT_ENABLE_INLINE int coderStackBase; if(coder->currentInlineContext) { coderStackBase = coder->currentInlineContext->stackBase; coderStackHeight -= coderStackBase; } else { coderStackBase = 0; } #else /* !_IL_JIT_ENABLE_INLINE */ int coderStackBase = 0; #endif /* !_IL_JIT_ENABLE_INLINE */ if(((label->labelType & (_IL_JIT_LABEL_NORMAL | _IL_JIT_LABEL_STARTCATCH)) != 0) && (coderStackHeight > 0)) { int current = 0; ILJitValue *stack = ILMemStackAllocItem(&(coder->stackStates), coderStackHeight * sizeof(ILJitValue)); if(!stack) { return 0; } /* Now save the current stack state. */ for(current = 0; current < coderStackHeight; current++) { ILJitStackItem *stackItem = _ILJitStackItemGet(coder, coderStackBase + current); stack[current] = _ILJitStackItemValue(*stackItem); if(jit_value_is_constant(_ILJitStackItemValue(*stackItem))) { /* We have to handle this case different. */ /* Create a local value of the type of the constant. */ ILJitValue temp = jit_value_create(coder->jitFunction, jit_value_get_type(_ILJitStackItemValue(*stackItem))); /* and store the value of the constant in the new temporary. */ jit_insn_store(coder->jitFunction, temp, _ILJitStackItemValue(*stackItem)); /* Now replace the constant with the new temporary. */ stack[current] = temp; _ILJitStackItemSetValue(*stackItem, temp); } else if(_ILJitStackItemNeedsDupOnLabel(*stackItem)) { ILJitValue temp = jit_insn_dup(coder->jitFunction, _ILJitStackItemValue(*stackItem)); stack[current] = temp; _ILJitStackItemSetValue(*stackItem, temp); } } label->jitStack = stack; label->stackSize = coderStackHeight; } 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); }
/* * Handle a shift opcode. */ static void JITCoder_Shift(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); /* Determine how to perform the operation */ switch(opcode) { case IL_OP_SHL: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_shl(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_SHR: { AdjustMixedBinary(jitCoder, 0, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result= jit_insn_shr(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_SHR_UN: { AdjustMixedBinary(jitCoder, 1, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); result = jit_insn_shr(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; } _ILJitStackPushValue(jitCoder, result); }
/* * Handle a binary opcode when pointer arithmetic is involved. */ static void JITCoder_BinaryPtr(ILCoder *coder, int opcode, ILEngineType type1, ILEngineType type2) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder); int value1IsPointer = _IL_JIT_ENGINE_TYPE_IS_POINTER(type1); int value2IsPointer = _IL_JIT_ENGINE_TYPE_IS_POINTER(type2); _ILJitStackItemNew(value2); _ILJitStackItemNew(value1); ILJitValue result = 0; _ILJitStackPop(jitCoder, value2); _ILJitStackPop(jitCoder, value1); switch(opcode) { case IL_OP_ADD: { result = jit_insn_add(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } case IL_OP_ADD_OVF_UN: { result = jit_insn_add_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; case IL_OP_SUB: { result = jit_insn_sub(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } case IL_OP_SUB_OVF_UN: { result = jit_insn_sub_ovf(jitCoder->jitFunction, _ILJitStackItemValue(value1), _ILJitStackItemValue(value2)); } break; } if(value1IsPointer && value2IsPointer) { /* We can't keep the reference information for this case. */ _ILJitStackPushValue(jitCoder, result); } else if(value1IsPointer) { /* Keep the reference information for value1. */ _ILJitStackItemSetValue(value1, result); _ILJitStackPush(jitCoder, value1); } else if(value2IsPointer) { /* Keep the reference information for value2. */ _ILJitStackItemSetValue(value2, result); _ILJitStackPush(jitCoder, value2); } else { /* There is no pointer involved in this operation. */ _ILJitStackPushValue(jitCoder, result); } }
/* * Output a branch instruction using a JIT coder. */ static void JITCoder_Branch(ILCoder *coder, int opcode, ILUInt32 dest, ILEngineType type1, ILEngineType type2) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder); ILJITLabel *label = 0; ILJitValue temp = 0; _ILJitStackItemNew(value2); _ILJitStackItemNew(value1); #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) if (jitCoder->flags & IL_CODER_FLAG_STATS) { ILMutexLock(globalTraceMutex); fprintf(stdout, "Branch: %i\n", dest); ILMutexUnlock(globalTraceMutex); } #endif /* Determine what form of branch to use */ switch(opcode) { case IL_OP_BR: case IL_OP_BR_S: case IL_OP_LEAVE: case IL_OP_LEAVE_S: { /* Unconditional branch */ label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); jit_insn_branch(jitCoder->jitFunction, &(label->label)); } break; case IL_OP_BRTRUE_S: case IL_OP_BRTRUE: { /* Branch if the top-most stack item is true */ _ILJitStackPop(jitCoder, value1); label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); jit_insn_branch_if(jitCoder->jitFunction, _ILJitStackItemValue(value1), &(label->label)); } break; case IL_OP_BRFALSE_S: case IL_OP_BRFALSE: { /* Branch if the top-most stack item is false */ _ILJitStackPop(jitCoder, value1); label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); jit_insn_branch_if_not(jitCoder->jitFunction, _ILJitStackItemValue(value1), &(label->label)); } break; default: { _ILJitStackPop(jitCoder, value2); _ILJitStackPop(jitCoder, value1); label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); switch(opcode) { case IL_OP_BEQ: case IL_OP_BEQ_S: { /* Equality testing branch */ temp = OutputCompare(jitCoder, IL_OP_BEQ, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BNE_UN: case IL_OP_BNE_UN_S: { /* Unsigned inequality testing branch */ temp = OutputCompare(jitCoder, IL_OP_BNE_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGT: case IL_OP_BGT_S: { /* Signed greater than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGT, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGT_UN: case IL_OP_BGT_UN_S: { /* Unsigned greater than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGT_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGE: case IL_OP_BGE_S: { /* Signed greater than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGE, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGE_UN: case IL_OP_BGE_UN_S: { /* Unsigned greater than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGE_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLT: case IL_OP_BLT_S: { /* Signed less than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLT, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLT_UN: case IL_OP_BLT_UN_S: { /* Unsigned less than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLT_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLE: case IL_OP_BLE_S: { /* Signed less than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLE, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLE_UN: case IL_OP_BLE_UN_S: { /* Unsigned less than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLE_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; } } break; } }
/* * 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; }