/*************************************************************************** * performPeepholeOptimizer ***************************************************************************/ bool CCilCodeGen::performPeepholeOptimize( ILFRAGMENTINFO* pILPool ) { //early termination if( pILPool->ILPool.size() == 0 ) return true; ILFRAGMENTINFO& info = *pILPool; ILFRAGMENT optimizedILPool; ILFRAGMENT* pSrc = &pILPool->ILPool; ILFRAGMENT* pDest = &optimizedILPool; int32_t iMax; uint8_t cByteCode; hash_map< OP_CODE, PEEPHOLEOPTIMIZERCALLBACK >::iterator itCallback; uint32_t i; bool bContinue = true; while( bContinue ) { pDest->clear(); uint32_t iSize = uint32_t(pSrc->size()); bContinue = false; for( i = 0; i < iSize; ) { OPCODE_TABLEENTRY* pInfo; cByteCode = (*pSrc)[ i++ ]; switch( cByteCode ) { case 0xfe: cByteCode = (*pSrc)[ i++ ]; //Invoke call back if available itCallback = m_mapPeepholeOptimizer.find( OP_CODE(cByteCode | 0xfe00) ); if( itCallback != m_mapPeepholeOptimizer.end() ) { if( int32_t iSkip = itCallback->second( pSrc->begin() + i - 2, *pDest ) ) { i += iSkip - 2; bContinue = true; break; } } switch( cByteCode ) { case CEE_CODE_LABEL & 0xff: { pDest->push_back( 0xfe ); pDest->push_back( cByteCode ); //Skip code label info for( int32_t ii = 0; ii < sizeof( int32_t ); ii++ ) { pDest->push_back( (*pSrc)[ i++ ] ); } break; } case CEE_EXT_LDARG & 0xff: case CEE_EXT_STARG & 0xff: case CEE_EXT_LDLOC & 0xff: case CEE_EXT_STLOC & 0xff: { pDest->push_back( 0xfe ); pDest->push_back( cByteCode ); for( int32_t ii = 0; ii < sizeof( int32_t ) * 3; ii++ ) { pDest->push_back( (*pSrc)[ i++ ] ); } break; } case CEE_LEAVE_TMP & 0xff: { pDest->push_back( 0xfe ); pDest->push_back( cByteCode ); for( int32_t ii = 0; ii < sizeof( int32_t ) * 2; ii++ ) { pDest->push_back( (*pSrc)[ i++ ] ); } break; } default: pDest->push_back( 0xfe ); pDest->push_back( cByteCode ); pInfo = m_OpcodeMapByOpcode[ (OP_CODE)(0xfe00 | cByteCode) ]; iMax = pInfo->OperandParams & OPERAND_PARAMS_SIZEMASK; for( int32_t ii = 0; ii < iMax; ii++ ) { pDest->push_back( (*pSrc)[ i++ ] ); } break; } break; default: { //Invoke call back if available hash_map< OP_CODE, PEEPHOLEOPTIMIZERCALLBACK >::iterator itCallback; itCallback = m_mapPeepholeOptimizer.find( OP_CODE(cByteCode) ); if( itCallback != m_mapPeepholeOptimizer.end() ) { if( int32_t iSkip = itCallback->second( pSrc->begin() + i - 1, *pDest ) ) { i += iSkip - 1; bContinue = true; break; } } pInfo = m_OpcodeMapByOpcode[ (OP_CODE)cByteCode ]; pDest->push_back( cByteCode ); iMax = pInfo->OperandParams & OPERAND_PARAMS_SIZEMASK; for( int32_t ii = 0; ii < iMax; ii++ ) { pDest->push_back( (*pSrc)[ i++ ] ); } } break; } } if( bContinue ) { ILFRAGMENT* pTmp = pSrc; pSrc = pDest; pDest = pTmp; } } if( pDest != &info.ILPool ) { info.ILPool.clear(); info.ILPool = optimizedILPool; } return true; }
double Evaluate( AM_PARAM_EVAL_STACK& aExp ) { class OP_CODE // A small class to store a operator and its priority { public: parm_item_type m_Optype; int m_Priority; OP_CODE( AM_PARAM_EVAL& aAmPrmEval ) : m_Optype( aAmPrmEval.GetOperator() ), m_Priority( aAmPrmEval.GetPriority() ) {} OP_CODE( parm_item_type aOptype ) : m_Optype( aOptype ), m_Priority( 0 ) {} }; double result = 0.0; std::vector<double> values; // the current list of values std::vector<OP_CODE> optype; // the list of arith operators double curr_value = 0.0; int extra_priority = 0; for( unsigned ii = 0; ii < aExp.size(); ii++ ) { AM_PARAM_EVAL& prm = aExp[ii]; if( prm.IsOperator() ) { if( prm.GetOperator() == OPEN_PAR ) { extra_priority += AM_PARAM_EVAL::GetPriority( OPEN_PAR ); } else if( prm.GetOperator() == CLOSE_PAR ) { extra_priority -= AM_PARAM_EVAL::GetPriority( CLOSE_PAR ); } else { optype.push_back( OP_CODE( prm ) ); optype.back().m_Priority += extra_priority; } } else // we have a value: { values.push_back( prm.GetValue() ); if( optype.size() < 2 ) continue; OP_CODE& previous_optype = optype[optype.size() - 2]; if( optype.back().m_Priority > previous_optype.m_Priority ) { double op1 = 0.0; double op2 = values.back(); values.pop_back(); if( values.size() ) { op1 = values.back(); values.pop_back(); } switch( optype.back().m_Optype ) { case ADD: values.push_back( op1+op2 ); break; case SUB: values.push_back( op1-op2 ); break; case MUL: values.push_back( op1*op2 ); break; case DIV: values.push_back( op1/op2 ); break; default: break; } optype.pop_back(); } } } // Now all operators have the same priority, or those having the higher priority // are before others, calculate the final result by combining initial values and/or // replaced values. if( values.size() > optype.size() ) // If there are n values, the number of operator is n-1 or n if the first // item of the expression to evaluate is + or - (like -$1/2) // If the number of operator is n-1 the first value is just copied to result optype.insert( optype.begin(), OP_CODE( POPVALUE ) ); wxASSERT( values.size() == optype.size() ); for( unsigned idx = 0; idx < values.size(); idx++ ) { curr_value = values[idx]; switch( optype[idx].m_Optype ) { case POPVALUE: result = curr_value; break; case ADD: result += curr_value; break; case SUB: result -= curr_value; break; case MUL: result *= curr_value; break; case DIV: result /= curr_value; break; default: break; } } return result; }