/* * $Id$ */ /* * Harbour Project source code: * Compiler PCODE optimizer * * Copyright 2007 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). * * As a special exception, the Harbour Project gives permission for * additional uses of the text contained in its release of Harbour. * * The exception is that, if you link the Harbour libraries with other * files to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public License. * Your use of that executable is in no way restricted on account of * linking the Harbour library code into it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the GNU General Public License. * * This exception applies only to the code released by the Harbour * Project under the name Harbour. If you copy code from other * Harbour Project or Free Software Foundation releases into a copy of * Harbour, as the General Public License permits, the exception does * not apply to the code that you add in this way. To avoid misleading * anyone as to the status of such modified files, you must delete * this exception notice from them. * * If you write modifications of your own for Harbour, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. * */ #include "hbcomp.h" #include "hbassert.h" typedef struct HB_stru_opt_info { HB_COMP_DECL; } HB_OPT_INFO, * HB_OPT_INFO_PTR; #define HB_OPT_FUNC( func ) HB_PCODE_FUNC( func, HB_OPT_INFO_PTR ) typedef HB_OPT_FUNC( HB_OPT_FUNC_ ); typedef HB_OPT_FUNC_ * HB_OPT_FUNC_PTR; static HB_OPT_FUNC( hb_p_poplocal ) { BYTE * pVar = &pFunc->pCode[ lPCodePos + 1 ]; SHORT iVar = HB_PCODE_MKSHORT( pVar ); HB_SYMBOL_UNUSED( cargo ); if( HB_LIM_INT8( iVar ) ) { pFunc->pCode[ lPCodePos ] = HB_P_POPLOCALNEAR; hb_compNOOPfill( pFunc, lPCodePos + 2, 1, FALSE, FALSE ); } return 3; } static HB_OPT_FUNC( hb_p_pushlocal ) { BYTE * pVar = &pFunc->pCode[ lPCodePos + 1 ]; SHORT iVar = HB_PCODE_MKSHORT( pVar ); if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_POPLOCAL && HB_PCODE_MKSHORT( &pFunc->pCode[ lPCodePos + 4 ] ) == iVar && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 6, FALSE, FALSE ); } else if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_POPLOCALNEAR && ( SCHAR ) pFunc->pCode[ lPCodePos + 4 ] == iVar && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 5, FALSE, FALSE ); } else if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_POP && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 4, FALSE, FALSE ); } else if( HB_LIM_INT8( iVar ) ) { pFunc->pCode[ lPCodePos ] = HB_P_PUSHLOCALNEAR; hb_compNOOPfill( pFunc, lPCodePos + 2, 1, FALSE, FALSE ); } return 3; } static HB_OPT_FUNC( hb_p_pushlocalnear ) { if( pFunc->pCode[ lPCodePos + 2 ] == HB_P_POPLOCAL && ( SCHAR ) pFunc->pCode[ lPCodePos + 1 ] == HB_PCODE_MKSHORT( &pFunc->pCode[ lPCodePos + 3 ] ) && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 2 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 5, FALSE, FALSE ); } else if( pFunc->pCode[ lPCodePos + 2 ] == HB_P_POPLOCALNEAR && pFunc->pCode[ lPCodePos + 1 ] == pFunc->pCode[ lPCodePos + 3 ] && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 2 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 4, FALSE, FALSE ); } else if( pFunc->pCode[ lPCodePos + 2 ] == HB_P_POP && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 2 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 3, FALSE, FALSE ); } return 2; } static HB_OPT_FUNC( hb_p_localaddint ) { BYTE * pVar = &pFunc->pCode[ lPCodePos + 1 ]; SHORT iVar = HB_PCODE_MKSHORT( pVar ); HB_SYMBOL_UNUSED( cargo ); if( HB_LIM_INT8( iVar ) ) { pVar[ 0 ] = HB_P_LOCALNEARADDINT; pVar[ 1 ] = HB_LOBYTE( iVar ); hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); } return 5; } static HB_OPT_FUNC( hb_p_pushstatic ) { if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_POPSTATIC && HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ) == HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 4 ] ) && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 6, FALSE, FALSE ); } else if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_POP && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 4, FALSE, FALSE ); } return 3; } static HB_OPT_FUNC( hb_p_pushmemvar ) { if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_POPMEMVAR && HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ) == HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 4 ] ) && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 6, FALSE, FALSE ); } else if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_POP && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 4, FALSE, FALSE ); } return 3; } static HB_OPT_FUNC( hb_p_pushnil ) { if( pFunc->pCode[ lPCodePos + 1 ] == HB_P_POP && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 2, FALSE, FALSE ); } return 1; } static HB_OPT_FUNC( hb_p_false ) { switch( pFunc->pCode[ lPCodePos + 1 ] ) { case HB_P_POP: case HB_P_NOT: case HB_P_JUMPFALSENEAR: case HB_P_JUMPFALSE: case HB_P_JUMPFALSEFAR: case HB_P_JUMPTRUENEAR: case HB_P_JUMPTRUE: case HB_P_JUMPTRUEFAR: if( ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) ) { int iCount = 1; switch( pFunc->pCode[ lPCodePos + 1 ] ) { case HB_P_JUMPFALSENEAR: pFunc->pCode[ lPCodePos + 1 ] = HB_P_JUMPNEAR; break; case HB_P_JUMPFALSE: pFunc->pCode[ lPCodePos + 1 ] = HB_P_JUMP; break; case HB_P_JUMPFALSEFAR: pFunc->pCode[ lPCodePos + 1 ] = HB_P_JUMPFAR; break; case HB_P_NOT: pFunc->pCode[ lPCodePos + 1 ] = HB_P_TRUE; break; case HB_P_POP: iCount = 2; break; case HB_P_JUMPTRUENEAR: iCount = 3; break; case HB_P_JUMPTRUE: iCount = 4; break; case HB_P_JUMPTRUEFAR: iCount = 5; break; } hb_compNOOPfill( pFunc, lPCodePos, iCount, FALSE, FALSE ); } break; } return 1; } static HB_OPT_FUNC( hb_p_true ) { switch( pFunc->pCode[ lPCodePos + 1 ] ) { case HB_P_POP: case HB_P_NOT: case HB_P_JUMPTRUENEAR: case HB_P_JUMPTRUE: case HB_P_JUMPTRUEFAR: case HB_P_JUMPFALSENEAR: case HB_P_JUMPFALSE: case HB_P_JUMPFALSEFAR: if( ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) ) { int iCount = 1; switch( pFunc->pCode[ lPCodePos + 1 ] ) { case HB_P_JUMPTRUENEAR: pFunc->pCode[ lPCodePos + 1 ] = HB_P_JUMPNEAR; break; case HB_P_JUMPTRUE: pFunc->pCode[ lPCodePos + 1 ] = HB_P_JUMP; break; case HB_P_JUMPTRUEFAR: pFunc->pCode[ lPCodePos + 1 ] = HB_P_JUMPFAR; break; case HB_P_NOT: pFunc->pCode[ lPCodePos + 1 ] = HB_P_FALSE; break; case HB_P_POP: iCount = 2; break; case HB_P_JUMPFALSENEAR: iCount = 3; break; case HB_P_JUMPFALSE: iCount = 4; break; case HB_P_JUMPFALSEFAR: iCount = 5; break; } hb_compNOOPfill( pFunc, lPCodePos, iCount, FALSE, FALSE ); } break; } return 1; } static HB_OPT_FUNC( hb_p_duplicate ) { switch( pFunc->pCode[ lPCodePos + 1 ] ) { case HB_P_JUMPTRUEFAR: case HB_P_JUMPFALSEFAR: if( pFunc->pCode[ lPCodePos + 5 ] == HB_P_POP ) { BYTE * pAddr = &pFunc->pCode[ lPCodePos + 2 ]; LONG lOffset = HB_PCODE_MKINT24( pAddr ), lLastOffset = 0; ULONG ulNewPos = lPCodePos + 1 + lOffset; BOOL fNot = FALSE, fRepeat = TRUE; do { if( pFunc->pCode[ ulNewPos ] == HB_P_DUPLICATE ) { if( lOffset > 0 ) hb_p_duplicate( pFunc, ulNewPos, cargo ); } if( pFunc->pCode[ ulNewPos ] == HB_P_NOOP ) { ulNewPos++; lOffset++; } else if( pFunc->pCode[ ulNewPos ] == HB_P_NOT ) { ulNewPos++; lOffset++; fNot = !fNot; } else if( pFunc->pCode[ ulNewPos ] == HB_P_DUPLICATE && ( pFunc->pCode[ ulNewPos + 1 ] == HB_P_JUMPTRUEFAR || pFunc->pCode[ ulNewPos + 1 ] == HB_P_JUMPFALSEFAR ) ) { LONG lJump; if( pFunc->pCode[ ulNewPos + 1 ] != pFunc->pCode[ lPCodePos + 1 ] ) fNot = !fNot; lJump = fNot ? 4 : HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 2 ] ); lOffset += lJump + 1; ulNewPos = lPCodePos + 1 + lOffset; fRepeat = lJump > 0; } else fRepeat = FALSE; if( !fNot ) lLastOffset = lOffset; } while( fRepeat ); if( ( pFunc->pCode[ ulNewPos ] == HB_P_JUMPTRUEFAR || pFunc->pCode[ ulNewPos ] == HB_P_JUMPFALSEFAR ) && !hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) && !hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 5 ) ) { if( pFunc->pCode[ ulNewPos ] != pFunc->pCode[ lPCodePos + 1 ] ) fNot = !fNot; if( fNot ) lOffset += 4; else lOffset += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); HB_PUT_LE_UINT24( pAddr, lOffset ); hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); hb_compNOOPfill( pFunc, lPCodePos + 5, 1, FALSE, FALSE ); } else if( lLastOffset ) { HB_PUT_LE_UINT24( pAddr, lLastOffset ); } } break; } return 1; } static HB_OPT_FUNC( hb_p_not ) { BYTE opcode; switch( pFunc->pCode[ lPCodePos + 1 ] ) { case HB_P_NOT: opcode = HB_P_NOOP; break; case HB_P_JUMPTRUENEAR: opcode = HB_P_JUMPFALSENEAR; break; case HB_P_JUMPTRUE: opcode = HB_P_JUMPFALSE; break; case HB_P_JUMPTRUEFAR: opcode = HB_P_JUMPFALSEFAR; break; case HB_P_JUMPFALSENEAR: opcode = HB_P_JUMPTRUENEAR; break; case HB_P_JUMPFALSE: opcode = HB_P_JUMPTRUE; break; case HB_P_JUMPFALSEFAR: opcode = HB_P_JUMPTRUEFAR; break; /* This optimization will be enabled in the future in a little bit differ form */ #if 0 case HB_P_DUPLICATE: if( ( pFunc->pCode[ lPCodePos + 2 ] == HB_P_JUMPTRUEFAR || pFunc->pCode[ lPCodePos + 2 ] == HB_P_JUMPFALSEFAR ) && pFunc->pCode[ lPCodePos + 6 ] == HB_P_POP ) { BYTE * pAddr = &pFunc->pCode[ lPCodePos + 3 ]; LONG lOffset = HB_PCODE_MKINT24( pAddr ); if( lOffset > 0 ) { hb_p_duplicate( pFunc, lPCodePos + 1, cargo ); lOffset = HB_PCODE_MKINT24( pAddr ); } if( ( pFunc->pCode[ lPCodePos + 1 ] == HB_P_NOT || ( pFunc->pCode[ lPCodePos + 1 ] == HB_P_DUPLICATE && pFunc->pCode[ lPCodePos + lOffset + 2 ] == HB_P_NOT ) ) && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); if( pFunc->pCode[ lPCodePos + 2 ] == HB_P_JUMPTRUEFAR ) pFunc->pCode[ lPCodePos + 2 ] = HB_P_JUMPFALSEFAR; else pFunc->pCode[ lPCodePos + 2 ] = HB_P_JUMPTRUEFAR; if( pFunc->pCode[ lPCodePos + 1 ] == HB_P_DUPLICATE ) { ++lOffset; HB_PUT_LE_UINT24( pAddr, lOffset ); } } } /* no break; */ #endif default: opcode = HB_P_LAST_PCODE; break; } if( opcode < HB_P_LAST_PCODE && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); if( opcode == HB_P_NOOP ) hb_compNOOPfill( pFunc, lPCodePos + 1, 1, FALSE, FALSE ); else pFunc->pCode[ lPCodePos + 1 ] = opcode; } return 1; } static HB_OPT_FUNC( hb_p_jumpfar ) { BYTE * pAddr = &pFunc->pCode[ lPCodePos + 1 ]; LONG lOffset = HB_PCODE_MKINT24( pAddr ); ULONG ulNewPos = lPCodePos + lOffset; BOOL fLine = FALSE; HB_SYMBOL_UNUSED( cargo ); if( lOffset == 4 ) { hb_compNOOPfill( pFunc, lPCodePos, 4, FALSE, FALSE ); } else { if( pFunc->pCode[ ulNewPos ] == HB_P_LINE ) { fLine = TRUE; ulNewPos += 3; lOffset += 3; } switch( pFunc->pCode[ ulNewPos ] ) { case HB_P_JUMPFAR: lOffset += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); if( !fLine || pFunc->pCode[ lPCodePos + lOffset ] == HB_P_LINE ) HB_PUT_LE_UINT24( pAddr, lOffset ); break; case HB_P_JUMPFALSEFAR: ulNewPos += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); if( ulNewPos == lPCodePos + 4 && ( !fLine || ( pFunc->pCode[ ulNewPos ] == HB_P_LINE && pFunc->pCode[ lPCodePos + lOffset + 4 ] == HB_P_LINE ) ) ) { pFunc->pCode[ lPCodePos ] = HB_P_JUMPTRUEFAR; HB_PUT_LE_UINT24( pAddr, lOffset + 4 ); } break; case HB_P_JUMPTRUEFAR: ulNewPos += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); if( ulNewPos == lPCodePos + 4 && ( !fLine || ( pFunc->pCode[ ulNewPos ] == HB_P_LINE && pFunc->pCode[ lPCodePos + lOffset + 4 ] == HB_P_LINE ) ) ) { pFunc->pCode[ lPCodePos ] = HB_P_JUMPFALSEFAR; HB_PUT_LE_UINT24( pAddr, lOffset + 4 ); } break; } } return 4; } static HB_OPT_FUNC( hb_p_jumpfalsefar ) { BYTE * pAddr = &pFunc->pCode[ lPCodePos + 1 ]; LONG lOffset = HB_PCODE_MKINT24( pAddr ); ULONG ulNewPos = lPCodePos + lOffset; BOOL fLine = FALSE; HB_SYMBOL_UNUSED( cargo ); if( lOffset == 8 && pFunc->pCode[ lPCodePos + 4 ] == HB_P_JUMPFAR && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 4 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 4, FALSE, FALSE ); pFunc->pCode[ lPCodePos + 4 ] = HB_P_JUMPTRUEFAR; } else if( lOffset == 11 && pFunc->pCode[ lPCodePos + 4 ] == HB_P_LINE && pFunc->pCode[ lPCodePos + 11 ] == HB_P_LINE && pFunc->pCode[ lPCodePos + 7 ] == HB_P_JUMPFAR && pFunc->pCode[ lPCodePos + 7 + HB_PCODE_MKINT24( &pFunc->pCode[ lPCodePos + 8 ] ) ] == HB_P_LINE && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 4 ) && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 7 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 7, FALSE, FALSE ); pFunc->pCode[ lPCodePos + 7 ] = HB_P_JUMPTRUEFAR; } else { if( pFunc->pCode[ ulNewPos ] == HB_P_LINE ) { fLine = TRUE; ulNewPos += 3; lOffset += 3; } if( pFunc->pCode[ ulNewPos ] == HB_P_JUMPFAR ) { lOffset += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); if( !fLine || pFunc->pCode[ lPCodePos + lOffset ] == HB_P_LINE ) HB_PUT_LE_UINT24( pAddr, lOffset ); } } return 4; } static HB_OPT_FUNC( hb_p_jumptruefar ) { BYTE * pAddr = &pFunc->pCode[ lPCodePos + 1 ]; LONG lOffset = HB_PCODE_MKINT24( pAddr ); ULONG ulNewPos = lPCodePos + lOffset; BOOL fLine = FALSE; HB_SYMBOL_UNUSED( cargo ); if( lOffset == 8 && pFunc->pCode[ lPCodePos + 4 ] == HB_P_JUMPFAR && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 4 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 4, FALSE, FALSE ); pFunc->pCode[ lPCodePos + 4 ] = HB_P_JUMPFALSEFAR; } else if( lOffset == 11 && pFunc->pCode[ lPCodePos + 4 ] == HB_P_LINE && pFunc->pCode[ lPCodePos + 11 ] == HB_P_LINE && pFunc->pCode[ lPCodePos + 7 ] == HB_P_JUMPFAR && pFunc->pCode[ lPCodePos + 7 + HB_PCODE_MKINT24( &pFunc->pCode[ lPCodePos + 8 ] ) ] == HB_P_LINE && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 4 ) && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 7 ) ) { hb_compNOOPfill( pFunc, lPCodePos, 7, FALSE, FALSE ); pFunc->pCode[ lPCodePos + 7 ] = HB_P_JUMPFALSEFAR; } else { if( pFunc->pCode[ ulNewPos ] == HB_P_LINE ) { fLine = TRUE; ulNewPos += 3; lOffset += 3; } if( pFunc->pCode[ ulNewPos ] == HB_P_JUMPFAR ) { lOffset += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); if( !fLine || pFunc->pCode[ lPCodePos + lOffset ] == HB_P_LINE ) HB_PUT_LE_UINT24( pAddr, lOffset ); } } return 4; } static HB_OPT_FUNC( hb_p_switch ) { USHORT usCases = HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ), us; ULONG ulStart = lPCodePos; HB_SYMBOL_UNUSED( cargo ); lPCodePos += 3; for( us = 0; us < usCases; ++us ) { switch( pFunc->pCode[ lPCodePos ] ) { case HB_P_PUSHBYTE: lPCodePos += 2; break; case HB_P_PUSHINT: lPCodePos += 3; break; case HB_P_PUSHLONG: case HB_P_PUSHDATE: lPCodePos += 5; break; case HB_P_PUSHLONGLONG: lPCodePos += 9; break; case HB_P_PUSHSTRSHORT: lPCodePos += 2 + pFunc->pCode[ lPCodePos + 1 ]; break; case HB_P_PUSHSTR: lPCodePos += 3 + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ); break; case HB_P_PUSHSTRLARGE: lPCodePos += 4 + HB_PCODE_MKUINT24( &pFunc->pCode[ lPCodePos + 1 ] ); break; case HB_P_PUSHNIL: /* default clause */ us = usCases; lPCodePos++; break; } switch( pFunc->pCode[ lPCodePos ] ) { case HB_P_JUMPNEAR: lPCodePos += 2; break; case HB_P_JUMP: lPCodePos += 3; break; /*case HB_P_JUMPFAR:*/ default: lPCodePos += 4; break; } } return lPCodePos - ulStart; } static HB_OPT_FUNC( hb_p_function ) { if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_RETVALUE && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { pFunc->pCode[ lPCodePos ] = HB_P_DO; hb_compNOOPfill( pFunc, lPCodePos + 3, 1, FALSE, FALSE ); } return 3; } static HB_OPT_FUNC( hb_p_functionshort ) { if( pFunc->pCode[ lPCodePos + 2 ] == HB_P_RETVALUE && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 2 ) ) { pFunc->pCode[ lPCodePos ] = HB_P_DOSHORT; hb_compNOOPfill( pFunc, lPCodePos + 2, 1, FALSE, FALSE ); } return 2; } static HB_OPT_FUNC( hb_p_macrofunc ) { if( pFunc->pCode[ lPCodePos + 3 ] == HB_P_RETVALUE && ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 3 ) ) { pFunc->pCode[ lPCodePos ] = HB_P_MACRODO; hb_compNOOPfill( pFunc, lPCodePos + 3, 1, FALSE, FALSE ); } return 3; } static HB_OPT_FUNC( hb_p_endblock ) { HB_SYMBOL_UNUSED( cargo ); if( lPCodePos + 1 < pFunc->lPCodePos && pFunc->pCode[ lPCodePos + 1 ] == HB_P_ENDBLOCK ) { hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); } return 1; } static HB_OPT_FUNC( hb_p_endproc ) { HB_SYMBOL_UNUSED( cargo ); if( lPCodePos + 1 < pFunc->lPCodePos && pFunc->pCode[ lPCodePos + 1 ] == HB_P_ENDPROC ) { hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); } return 1; } /* NOTE: The order of functions have to match the order of opcodes mnemonics */ static const HB_OPT_FUNC_PTR s_opt_table[] = { NULL, /* HB_P_AND, */ NULL, /* HB_P_ARRAYPUSH, */ NULL, /* HB_P_ARRAYPOP, */ NULL, /* HB_P_ARRAYDIM, */ NULL, /* HB_P_ARRAYGEN, */ NULL, /* HB_P_EQUAL, */ hb_p_endblock, /* HB_P_ENDBLOCK, */ hb_p_endproc, /* HB_P_ENDPROC, */ NULL, /* HB_P_EXACTLYEQUAL, */ hb_p_false, /* HB_P_FALSE, */ NULL, /* HB_P_FORTEST, */ hb_p_function, /* HB_P_FUNCTION, */ hb_p_functionshort, /* HB_P_FUNCTIONSHORT, */ NULL, /* HB_P_FRAME, */ NULL, /* HB_P_FUNCPTR, */ NULL, /* HB_P_GREATER, */ NULL, /* HB_P_GREATEREQUAL, */ NULL, /* HB_P_DEC, */ NULL, /* HB_P_DIVIDE, */ NULL, /* HB_P_DO, */ NULL, /* HB_P_DOSHORT, */ hb_p_duplicate, /* HB_P_DUPLICATE, */ NULL, /* HB_P_DUPLTWO, */ NULL, /* HB_P_INC, */ NULL, /* HB_P_INSTRING, */ NULL, /* HB_P_JUMPNEAR, */ NULL, /* HB_P_JUMP, */ hb_p_jumpfar, /* HB_P_JUMPFAR, */ NULL, /* HB_P_JUMPFALSENEAR, */ NULL, /* HB_P_JUMPFALSE, */ hb_p_jumpfalsefar, /* HB_P_JUMPFALSEFAR, */ NULL, /* HB_P_JUMPTRUENEAR, */ NULL, /* HB_P_JUMPTRUE, */ hb_p_jumptruefar, /* HB_P_JUMPTRUEFAR, */ NULL, /* HB_P_LESSEQUAL, */ NULL, /* HB_P_LESS, */ NULL, /* HB_P_LINE, */ NULL, /* HB_P_LOCALNAME, */ NULL, /* HB_P_MACROPOP, */ NULL, /* HB_P_MACROPOPALIASED, */ NULL, /* HB_P_MACROPUSH, */ NULL, /* HB_P_MACROARRAYGEN, */ NULL, /* HB_P_MACROPUSHLIST, */ NULL, /* HB_P_MACROPUSHINDEX, */ NULL, /* HB_P_MACROPUSHPARE, */ NULL, /* HB_P_MACROPUSHALIASED, */ NULL, /* HB_P_MACROSYMBOL, */ NULL, /* HB_P_MACROTEXT, */ NULL, /* HB_P_MESSAGE, */ NULL, /* HB_P_MINUS, */ NULL, /* HB_P_MODULUS, */ NULL, /* HB_P_MODULENAME, */ /* start: pcodes generated by macro compiler */ NULL, /* HB_P_MMESSAGE, */ NULL, /* HB_P_MPOPALIASEDFIELD, */ NULL, /* HB_P_MPOPALIASEDVAR, */ NULL, /* HB_P_MPOPFIELD, */ NULL, /* HB_P_MPOPMEMVAR, */ NULL, /* HB_P_MPUSHALIASEDFIELD, */ NULL, /* HB_P_MPUSHALIASEDVAR, */ NULL, /* HB_P_MPUSHBLOCK, */ NULL, /* HB_P_MPUSHFIELD, */ NULL, /* HB_P_MPUSHMEMVAR, */ NULL, /* HB_P_MPUSHMEMVARREF, */ NULL, /* HB_P_MPUSHSYM, */ NULL, /* HB_P_MPUSHVARIABLE, */ /* end: */ NULL, /* HB_P_MULT, */ NULL, /* HB_P_NEGATE, */ NULL, /* HB_P_NOOP, */ hb_p_not, /* HB_P_NOT, */ NULL, /* HB_P_NOTEQUAL, */ NULL, /* HB_P_OR, */ NULL, /* HB_P_PARAMETER, */ NULL, /* HB_P_PLUS, */ NULL, /* HB_P_POP, */ NULL, /* HB_P_POPALIAS, */ NULL, /* HB_P_POPALIASEDFIELD, */ NULL, /* HB_P_POPALIASEDFIELDNEAR, */ NULL, /* HB_P_POPALIASEDVAR, */ NULL, /* HB_P_POPFIELD, */ hb_p_poplocal, /* HB_P_POPLOCAL, */ NULL, /* HB_P_POPLOCALNEAR, */ NULL, /* HB_P_POPMEMVAR, */ NULL, /* HB_P_POPSTATIC, */ NULL, /* HB_P_POPVARIABLE, */ NULL, /* HB_P_POWER, */ NULL, /* HB_P_PUSHALIAS, */ NULL, /* HB_P_PUSHALIASEDFIELD, */ NULL, /* HB_P_PUSHALIASEDFIELDNEAR, */ NULL, /* HB_P_PUSHALIASEDVAR, */ NULL, /* HB_P_PUSHBLOCK, */ NULL, /* HB_P_PUSHBLOCKSHORT, */ NULL, /* HB_P_PUSHFIELD, */ NULL, /* HB_P_PUSHBYTE, */ NULL, /* HB_P_PUSHINT, */ hb_p_pushlocal, /* HB_P_PUSHLOCAL, */ hb_p_pushlocalnear, /* HB_P_PUSHLOCALNEAR, */ NULL, /* HB_P_PUSHLOCALREF, */ NULL, /* HB_P_PUSHLONG, */ hb_p_pushmemvar, /* HB_P_PUSHMEMVAR, */ NULL, /* HB_P_PUSHMEMVARREF, */ hb_p_pushnil, /* HB_P_PUSHNIL, */ NULL, /* HB_P_PUSHDOUBLE, */ NULL, /* HB_P_PUSHSELF, */ hb_p_pushstatic, /* HB_P_PUSHSTATIC, */ NULL, /* HB_P_PUSHSTATICREF, */ NULL, /* HB_P_PUSHSTR, */ NULL, /* HB_P_PUSHSTRSHORT, */ NULL, /* HB_P_PUSHSYM, */ NULL, /* HB_P_PUSHSYMNEAR, */ NULL, /* HB_P_PUSHVARIABLE, */ NULL, /* HB_P_RETVALUE, */ NULL, /* HB_P_SEND, */ NULL, /* HB_P_SENDSHORT, */ NULL, /* HB_P_SEQBEGIN, */ NULL, /* HB_P_SEQEND, */ NULL, /* HB_P_SEQRECOVER, */ NULL, /* HB_P_SFRAME, */ NULL, /* HB_P_STATICS, */ NULL, /* HB_P_STATICNAME, */ NULL, /* HB_P_SWAPALIAS, */ hb_p_true, /* HB_P_TRUE, */ NULL, /* HB_P_ZERO, */ NULL, /* HB_P_ONE, */ hb_p_macrofunc, /* HB_P_MACROFUNC, */ NULL, /* HB_P_MACRODO, */ NULL, /* HB_P_MPUSHSTR, */ NULL, /* HB_P_LOCALNEARADDINT, */ NULL, /* HB_P_MACROPUSHREF */ NULL, /* HB_P_PUSHLONGLONG */ NULL, /* HB_P_ENUMSTART */ NULL, /* HB_P_ENUMNEXT */ NULL, /* HB_P_ENUMPREV */ NULL, /* HB_P_ENUMEND */ hb_p_switch, /* HB_P_SWITCH */ NULL, /* HB_P_PUSHDATE */ NULL, /* HB_P_PLUSEQPOP */ NULL, /* HB_P_MINUSEQPOP */ NULL, /* HB_P_MULTEQPOP */ NULL, /* HB_P_DIVEQPOP */ NULL, /* HB_P_PLUSEQ */ NULL, /* HB_P_MINUSEQ */ NULL, /* HB_P_MULTEQ */ NULL, /* HB_P_DIVEQ */ NULL, /* HB_P_WITHOBJECTSTART */ NULL, /* HB_P_WITHOBJECTMESSAGE */ NULL, /* HB_P_WITHOBJECTEND */ NULL, /* HB_P_MACROSEND */ NULL, /* HB_P_PUSHOVARREF */ NULL, /* HB_P_ARRAYPUSHREF */ NULL, /* HB_P_VFRAME */ NULL, /* HB_P_LARGEFRAME */ NULL, /* HB_P_LARGEVFRAME */ NULL, /* HB_P_PUSHSTRHIDDEN */ hb_p_localaddint, /* HB_P_LOCALADDINT */ NULL, /* HB_P_MODEQPOP */ NULL, /* HB_P_EXPEQPOP */ NULL, /* HB_P_MODEQ */ NULL, /* HB_P_EXPEQ */ NULL, /* HB_P_DUPLUNREF */ NULL, /* HB_P_MPUSHBLOCKLARGE */ NULL, /* HB_P_MPUSHSTRLARGE */ NULL, /* HB_P_PUSHBLOCKLARGE */ NULL, /* HB_P_PUSHSTRLARGE */ NULL, /* HB_P_SWAP */ NULL, /* HB_P_PUSHVPARAMS */ NULL, /* HB_P_PUSHUNREF */ NULL, /* HB_P_SEQALWAYS */ NULL, /* HB_P_ALWAYSBEGIN */ NULL, /* HB_P_ALWAYSEND */ NULL, /* HB_P_DECEQPOP */ NULL, /* HB_P_INCEQPOP */ NULL, /* HB_P_DECEQ */ NULL, /* HB_P_INCEQ */ NULL, /* HB_P_LOCALDEC */ NULL, /* HB_P_LOCALINC */ NULL, /* HB_P_LOCALINCPUSH */ NULL, /* HB_P_PUSHFUNCSYM */ NULL, /* HB_P_HASHGEN */ NULL /* HB_P_SEQBLOCK */ }; void hb_compOptimizePCode( HB_COMP_DECL, PFUNCTION pFunc ) { const HB_OPT_FUNC_PTR * pFuncTable = s_opt_table; HB_OPT_INFO opt_info; opt_info.HB_COMP_PARAM = HB_COMP_PARAM; assert( HB_P_LAST_PCODE == sizeof( s_opt_table ) / sizeof( HB_OPT_FUNC_PTR ) ); hb_compPCodeEval( pFunc, ( const HB_PCODE_FUNC_PTR * ) pFuncTable, ( void * ) &opt_info ); }