From 68f8243cbee815af0d98ed351f37d2144b353f45 Mon Sep 17 00:00:00 2001 From: Ron Pinkas Date: Tue, 18 Apr 2000 12:41:08 +0000 Subject: [PATCH] 20000419-05:30 GMT-8 Ron Pinkas * source/compiler/hvm.c + Added PCodes HB_P_JAMPSHORT, HB_P_JAMPSHORTFALSE and HB_P_JAMPSHORTTRUE * source/compiler/harbour.c + Added hb_compOptimizeJumps() - Jumps Optimizer. + Added hb_compSort_ULONG() Call back function for qsort - used in the Jump Optimizer. + Added support for new elements of _FUNC. * Modified hb_compGen*Jump*() to support Short Normal and Far Jumps. * source/include/hbexprb.c * Reverted handling of .OR. .AND. and IIF() to use default (FAR) JUMPs - note the use of (0) when calling hb_compGenJump*(). * source/compiler/genc.c + Added support for HB_P_JAMPSHORT, HB_P_JAMPSHORTFALSE and HB_P_JAMPSHORTTRUE * source/compiler/cmdcheck.c + Added support for new switch -J[0|1] default is J1 which enables the Jump Optimizer - Use -J0 to disable. * source/compiler/hbgenerr.c - Removed following errors: "Jump offset too long for HB_P_JUMP needed HB_P_JUMPFAR", "Jump offset too long for HB_P_JUMPTRUE needed HB_P_JUMPFARTRUE", "Jump offset too long for HB_P_JUMPFALSE needed HB_P_JUMPFARFALSE", * Changed "HB_P_JUMPx not found when fixing offset" to "Jump PCode not found" * source/include/hberrors.h - Removed following defines: #define HB_COMP_ERR_INVALID_JUMPTRUE 46 #define HB_COMP_ERR_INVALID_JUMPFALSE 47 #define HB_COMP_ERR_JUMP_NOT_FOUND 48 * source/include/hberrors.h + Added following to __FUNC ULONG * pNOOPs; /* pointer to the NOOP array */ ULONG * pJumps; /* pointer to the Jumps array */ int iNOOPs; /* NOOPs Counter */ int iJumps; /* Jumps Counter */ * source/include/hbpcode.h + Added HB_P_JAMPSHORT, HB_P_JAMPSHORTFALSE and HB_P_JAMPSHORTTRUE --- harbour/ChangeLog | 54 ++- harbour/bin/bld.bat | 2 + harbour/include/hbcomp.h | 35 +- harbour/include/hberrors.h | 5 +- harbour/include/hbexprb.c | 8 +- harbour/include/hbpcode.h | 7 +- harbour/makefile.bc | 2 +- harbour/source/compiler/cmdcheck.c | 32 +- harbour/source/compiler/genc.c | 126 ++++-- harbour/source/compiler/harbour.c | 660 +++++++++++++++++++++++++---- harbour/source/compiler/hbgenerr.c | 5 +- harbour/source/vm/hvm.c | 113 ++++- harbour/tests/test.prg | 31 +- 13 files changed, 886 insertions(+), 194 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 6f2c8d36c1..bbb44965c8 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,47 @@ +20000419-05:30 GMT-8 Ron Pinkas + + * source/compiler/hvm.c + + Added PCodes HB_P_JAMPSHORT, HB_P_JAMPSHORTFALSE and HB_P_JAMPSHORTTRUE + + * source/compiler/harbour.c + + Added hb_compOptimizeJumps() - Jumps Optimizer. + + Added hb_compSort_ULONG() Call back function for qsort - used in the Jump Optimizer. + + Added support for new elements of _FUNC. + * Modified hb_compGen*Jump*() to support Short Normal and Far Jumps. + + * source/include/hbexprb.c + * Reverted handling of .OR. .AND. and IIF() to use default (FAR) JUMPs - note the use of (0) when calling hb_compGenJump*(). + + * source/compiler/genc.c + + Added support for HB_P_JAMPSHORT, HB_P_JAMPSHORTFALSE and HB_P_JAMPSHORTTRUE + + * source/compiler/cmdcheck.c + + Added support for new switch -J[0|1] default is J1 which enables the Jump Optimizer - Use -J0 to disable. + + * source/compiler/hbgenerr.c + - Removed following errors: + "Jump offset too long for HB_P_JUMP needed HB_P_JUMPFAR", + "Jump offset too long for HB_P_JUMPTRUE needed HB_P_JUMPFARTRUE", + "Jump offset too long for HB_P_JUMPFALSE needed HB_P_JUMPFARFALSE", + + * Changed "HB_P_JUMPx not found when fixing offset" to "Jump PCode not found" + + * source/include/hberrors.h + - Removed following defines: + #define HB_COMP_ERR_INVALID_JUMPTRUE 46 + #define HB_COMP_ERR_INVALID_JUMPFALSE 47 + #define HB_COMP_ERR_JUMP_NOT_FOUND 48 + + * source/include/hberrors.h + + Added following to __FUNC + ULONG * pNOOPs; /* pointer to the NOOP array */ + ULONG * pJumps; /* pointer to the Jumps array */ + int iNOOPs; /* NOOPs Counter */ + int iJumps; /* Jumps Counter */ + + * source/include/hbpcode.h + + Added HB_P_JAMPSHORT, HB_P_JAMPSHORTFALSE and HB_P_JAMPSHORTTRUE + 20000418-13:30 GMT+1 Ryszard Glab *include/hbapigt.h @@ -14,8 +58,8 @@ modules - this will allow to use native (optimized) method of box drawing (xterm!) *full implementation of low level hb_gt_Replicate() - *added hb_gt_HorizLine() and hb_gt_VertLine() - this can be - extended by definition of HB_LINE() or + *added hb_gt_HorizLine() and hb_gt_VertLine() - this can be + extended by definition of HB_LINE() or @ row,left,right LINE command (this will get line drawing support on platforms where @ ... BOX command is not suitable) @@ -24,7 +68,7 @@ *source/rtl/gtcrs/gtcrs.c *support for box drawing added for xterm - NOTE: Only + NOTE: Only @ y1,x1 TO y2,x2 and @ y1,x1 TO y2,x2 DOUBLE @@ -33,10 +77,10 @@ used in current font (Well I am not so familiar with it then this needs some more work - I can be wrong here :) - + If you want a single method of box drawing for all platforms use @ y1,x1 TO y2,x2 - + 20000418-00:42 DST Paul Tucker * makefile.vc diff --git a/harbour/bin/bld.bat b/harbour/bin/bld.bat index b089f24840..ccd0a07c36 100644 --- a/harbour/bin/bld.bat +++ b/harbour/bin/bld.bat @@ -165,6 +165,8 @@ rem if "%HB_GT_LIB%" == "" set HB_GT_LIB= if "%HB_COMPILER%" == "rsxnt" gcc %1.c -Zwin32 %CFLAGS% -I..\include -L..\lib -ltools -ldebug -lvm -lrtl -l%HB_GT_LIB% -llang -lrdd -lrtl -lvm -lmacro -lpp -ldbfntx -ldbfcdx -lcommon if "%HB_COMPILER%" == "msvc" cl -Fd..\bin\harbour -w -Zi -TP -GZ -GA %CFLAGS% -I..\include %1.c /link /subsystem:CONSOLE ..\lib\tools.lib ..\lib\debug.lib ..\lib\vm.lib ..\lib\rtl.lib ..\lib\%HB_GT_LIB%.lib ..\lib\lang.lib ..\lib\rdd.lib ..\lib\macro.lib ..\lib\pp.lib ..\lib\dbfntx.lib ..\lib\dbfcdx.lib ..\lib\common.lib user32.lib if "%HB_COMPILER%" == "msvc" echo Ignore LNK4033 warning + + if "%HB_GT_LIB%" == "gtwin" set HB_GT_LIB= goto END :A_OS2 diff --git a/harbour/include/hbcomp.h b/harbour/include/hbcomp.h index 2b4bb948d4..1c1436e12a 100644 --- a/harbour/include/hbcomp.h +++ b/harbour/include/hbcomp.h @@ -102,21 +102,25 @@ typedef struct _VAR /* structure to hold a Clipper defined function */ typedef struct __FUNC { - char * szName; /* name of a defined Clipper function */ - char cScope; /* scope of a defined Clipper function */ - BYTE bFlags; /* some flags we may need */ - USHORT wParamCount; /* number of declared parameters */ - USHORT wParamNum; /* current parameter number */ - PVAR pLocals; /* pointer to local variables list */ - PVAR pStatics; /* pointer to static variables list */ - PVAR pFields; /* pointer to fields variables list */ - PVAR pMemvars; /* pointer to memvar variables list */ - BYTE * pCode; /* pointer to a memory block where pcode is stored */ - ULONG lPCodeSize; /* total memory size for pcode */ - ULONG lPCodePos; /* actual pcode offset */ - int iStaticsBase; /* base for this function statics */ - struct __FUNC * pOwner; /* pointer to the function/procedure that owns the codeblock */ - struct __FUNC * pNext; /* pointer to the next defined function */ + char * szName; /* name of a defined Clipper function */ + char cScope; /* scope of a defined Clipper function */ + BYTE bFlags; /* some flags we may need */ + USHORT wParamCount; /* number of declared parameters */ + USHORT wParamNum; /* current parameter number */ + PVAR pLocals; /* pointer to local variables list */ + PVAR pStatics; /* pointer to static variables list */ + PVAR pFields; /* pointer to fields variables list */ + PVAR pMemvars; /* pointer to memvar variables list */ + BYTE * pCode; /* pointer to a memory block where pcode is stored */ + ULONG lPCodeSize; /* total memory size for pcode */ + ULONG lPCodePos; /* actual pcode offset */ + int iStaticsBase; /* base for this function statics */ + ULONG * pNOOPs; /* pointer to the NOOP array */ + ULONG * pJumps; /* pointer to the Jumps array */ + int iNOOPs; /* NOOPs Counter */ + int iJumps; /* Jumps Counter */ + struct __FUNC * pOwner; /* pointer to the function/procedure that owns the codeblock */ + struct __FUNC * pNext; /* pointer to the next defined function */ } _FUNC, * PFUNCTION; /* structure to control all Clipper defined functions */ @@ -357,6 +361,7 @@ extern BOOL hb_comp_bCredits; extern BOOL hb_comp_bLogo; extern BOOL hb_comp_bSyntaxCheckOnly; extern int hb_comp_iLanguage; +extern int hb_comp_iJumpOptimize; extern USHORT hb_comp_wSeqCounter; extern USHORT hb_comp_wForCounter; diff --git a/harbour/include/hberrors.h b/harbour/include/hberrors.h index 8b84009b49..cdffb18fe4 100644 --- a/harbour/include/hberrors.h +++ b/harbour/include/hberrors.h @@ -89,10 +89,7 @@ extern "C" { #define HB_COMP_ERR_BAD_MACRO 42 #define HB_COMP_ERR_INVALID_SEND 43 #define HB_COMP_ERR_FUNC_ANNOUNCE 44 -#define HB_COMP_ERR_INVALID_JUMP 45 -#define HB_COMP_ERR_INVALID_JUMPTRUE 46 -#define HB_COMP_ERR_INVALID_JUMPFALSE 47 -#define HB_COMP_ERR_JUMP_NOT_FOUND 48 +#define HB_COMP_ERR_JUMP_NOT_FOUND 45 #define HB_COMP_WARN_AMBIGUOUS_VAR 1 #define HB_COMP_WARN_MEMVAR_ASSUMED 2 diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index affc2f65b3..1021c33250 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -648,11 +648,11 @@ static HB_EXPR_FUNC( hb_compExprUseIIF ) HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList; HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); - lPosFalse = HB_EXPR_PCODE1( hb_compGenJumpFalse, -1 ); + lPosFalse = HB_EXPR_PCODE1( hb_compGenJumpFalse, 0 ); pExpr =pExpr->pNext; HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); - lPosEnd = HB_EXPR_PCODE1( hb_compGenJump, -1 ); + lPosEnd = HB_EXPR_PCODE1( hb_compGenJump, 0 ); pExpr =pExpr->pNext; HB_EXPR_PCODE1( hb_compGenJumpHere, lPosFalse ); @@ -1993,7 +1993,7 @@ static HB_EXPR_FUNC( hb_compExprUseOr ) HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); - lEndPos = HB_EXPR_PCODE1( hb_compGenJumpTrue, -1 ); + lEndPos = HB_EXPR_PCODE1( hb_compGenJumpTrue, 0 ); HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_OR ); HB_EXPR_PCODE1( hb_compGenJumpHere, lEndPos ); @@ -2063,7 +2063,7 @@ static HB_EXPR_FUNC( hb_compExprUseAnd ) HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); - lEndPos = HB_EXPR_PCODE1( hb_compGenJumpFalse, -1 ); + lEndPos = HB_EXPR_PCODE1( hb_compGenJumpFalse, 0 ); HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_AND ); HB_EXPR_PCODE1( hb_compGenJumpHere, lEndPos ); diff --git a/harbour/include/hbpcode.h b/harbour/include/hbpcode.h index 062cff8289..3542bf3123 100644 --- a/harbour/include/hbpcode.h +++ b/harbour/include/hbpcode.h @@ -61,10 +61,13 @@ typedef enum HB_P_DUPLTWO, /* places a copy of the latest two virtual machine stack value on to the stack */ HB_P_INC, /* increments the latest value on the virtual machine stack */ HB_P_INSTRING, /* checks if the second latest value on the stack is a substring of the latest one */ - HB_P_JUMP, /* jumps to a relative offset */ - HB_P_JUMPFAR, /* jumps to a relative offset */ + HB_P_JUMPSHORT, /* jumps to a relative offset 1 Byte */ + HB_P_JUMP, /* jumps to a relative offset 2 Bytes */ + HB_P_JUMPFAR, /* jumps to a relative offset 3 Bytes */ + HB_P_JUMPSHORTFALSE, /* checks a logic expression of the stack and jumps to a relative offset */ HB_P_JUMPFALSE, /* checks a logic expression of the stack and jumps to a relative offset */ HB_P_JUMPFARFALSE, /* checks a logic expression of the stack and jumps to a relative offset */ + HB_P_JUMPSHORTTRUE, /* checks a logic expression of the stack and jumps to a relative offset */ HB_P_JUMPTRUE, /* checks a logic expression of the stack and jumps to a relative offset */ HB_P_JUMPFARTRUE, /* checks a logic expression of the stack and jumps to a relative offset */ HB_P_LESSEQUAL, /* checks if the second latest value on the stack is less equal that the latest one, leaves the result only */ diff --git a/harbour/makefile.bc b/harbour/makefile.bc index 1bc6da9fd8..4705dbf9b2 100644 --- a/harbour/makefile.bc +++ b/harbour/makefile.bc @@ -141,7 +141,7 @@ HB_GT_LIBS = \ !if !$d(HB_GT_LIB) HB_GT_LIB = $(GTWIN_LIB) -!endif +!endif !endif diff --git a/harbour/source/compiler/cmdcheck.c b/harbour/source/compiler/cmdcheck.c index dcfaefd488..621478667a 100644 --- a/harbour/source/compiler/cmdcheck.c +++ b/harbour/source/compiler/cmdcheck.c @@ -85,7 +85,7 @@ static void AddSearchPath( char * szPath, PATHNAMES * * pSearchList ) the exact date/time info from the resulting ULONG. Since the year is only stored in 6 bits, 1980 will result in the same bit pattern as 2044. The purpose of this value is only used to *differenciate* - between the dates ( the exact dates are not significant ), so this + between the dates ( the exact dates are not significant ), so this can be used here without problems. [vszakats] */ /* 76543210765432107654321076543210 @@ -143,7 +143,7 @@ void hb_compChkCompilerSwitch( int iArg, char * Args[] ) if( HB_ISOPTSEP( * Args[ i ] ) ) hb_compChkEnvironVar( Args[ i ] ); } - } + } else /* Chech the environment variables */ { @@ -247,7 +247,7 @@ void hb_compChkEnvironVar( char * szSwitch ) default: hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_BADOPTION, s, NULL ); - } + } } else hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_BADOPTION, s, NULL ); @@ -268,11 +268,11 @@ void hb_compChkEnvironVar( char * szSwitch ) case '1': hb_comp_bGenCVerbose = TRUE; break; - + case '0': hb_comp_bGenCVerbose = FALSE; break; - + default: hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_BADOPTION, s, NULL ); } @@ -331,6 +331,20 @@ void hb_compChkEnvironVar( char * szSwitch ) } break; + case 'j': + case 'J': + switch( *( s + 1 ) ) + { + case '0': + hb_comp_iJumpOptimize = 0; + break; + + case '1': + hb_comp_iJumpOptimize = 1; + break; + } + break; + case 'l': case 'L': hb_comp_bLineNumbers = FALSE; @@ -476,7 +490,7 @@ void hb_compChkPaths( void ) static void hb_compChkDefineSwitch( char * pszSwitch ) { - if( pszSwitch && HB_ISOPTSEP( pszSwitch[ 0 ] ) && + if( pszSwitch && HB_ISOPTSEP( pszSwitch[ 0 ] ) && ( pszSwitch[ 1 ] == 'd' || pszSwitch[ 1 ] == 'D' ) ) { char * szDefText = hb_strdup( pszSwitch + 2 ); @@ -497,7 +511,7 @@ void hb_compChkDefines( int iArg, char * Args[] ) { /* Chech the environment variables */ { - /* NOTE: CLIPPERCMD enviroment variable is overriden + /* NOTE: CLIPPERCMD enviroment variable is overriden if HARBOURCMD exists */ char * szStrEnv = getenv( "HARBOURCMD" ); @@ -521,9 +535,9 @@ void hb_compChkDefines( int iArg, char * Args[] ) { int i; - /* Check all switches in command line They start with an OS_OPT_DELIMITER + /* Check all switches in command line They start with an OS_OPT_DELIMITER char */ for( i = 0; i < iArg; i++ ) hb_compChkDefineSwitch( Args[ i ] ); - } + } } diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index 52e63f42d5..f50fce3616 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -45,6 +45,7 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou ULONG lPCodePos; char chr; BOOL bEndProcRequired; + LONG lOffset; FILE * yyc; /* file handle for C output */ @@ -355,74 +356,135 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou lPCodePos++; break; + case HB_P_JUMPSHORT: + /* if( 1 ) ( lPCodePos + 3 ) < pFunc->lPCodePos ) */ + { + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] ); + + if ( lOffset > 127 ) + lOffset -= 256; + + fprintf( yyc, "\tHB_P_JUMPSHORT, %i,", + pFunc->pCode[ lPCodePos + 1 ] ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); + fprintf( yyc, "\n" ); + } + lPCodePos += 2; + break; + case HB_P_JUMP: /* if( 1 ) ( lPCodePos + 3 ) < pFunc->lPCodePos ) */ { - w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 ); + + if ( lOffset > SHRT_MAX ) + lOffset -= 65536; + fprintf( yyc, "\tHB_P_JUMP, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); fprintf( yyc, "\n" ); } lPCodePos += 3; break; - case HB_P_JUMPFALSE: - w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; - fprintf( yyc, "\tHB_P_JUMPFALSE, %i, %i,", - pFunc->pCode[ lPCodePos + 1 ], - pFunc->pCode[ lPCodePos + 2 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); - fprintf( yyc, "\n" ); - lPCodePos += 3; - break; - - case HB_P_JUMPTRUE: - w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; - fprintf( yyc, "\tHB_P_JUMPTRUE, %i, %i,", - pFunc->pCode[ lPCodePos + 1 ], - pFunc->pCode[ lPCodePos + 2 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); - fprintf( yyc, "\n" ); - lPCodePos += 3; - break; - case HB_P_JUMPFAR: /* if( 1 ) ( lPCodePos + 3 ) < pFunc->lPCodePos ) */ { - LONG lPos = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536; + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset -= 16777216; + fprintf( yyc, "\tHB_P_JUMPFAR, %i, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ], pFunc->pCode[ lPCodePos + 3 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lPos, lPCodePos + ( lPos ? lPos : 4 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); fprintf( yyc, "\n" ); } lPCodePos += 4; break; + case HB_P_JUMPSHORTFALSE: + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] ); + + if ( lOffset > 127 ) + lOffset -= 256; + + fprintf( yyc, "\tHB_P_JUMPSHORTFALSE, %i,", + pFunc->pCode[ lPCodePos + 1 ] ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); + fprintf( yyc, "\n" ); + lPCodePos += 2; + break; + + case HB_P_JUMPFALSE: + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 ); + + if ( lOffset > SHRT_MAX ) + lOffset -= 65536; + + fprintf( yyc, "\tHB_P_JUMPFALSE, %i, %i,", + pFunc->pCode[ lPCodePos + 1 ], + pFunc->pCode[ lPCodePos + 2 ] ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); + fprintf( yyc, "\n" ); + lPCodePos += 3; + break; + case HB_P_JUMPFARFALSE: { - LONG lPos = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536; + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset -= 16777216; + fprintf( yyc, "\tHB_P_JUMPFARFALSE, %i, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ], pFunc->pCode[ lPCodePos + 3 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lPos, lPCodePos + ( lPos ? lPos : 4 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); fprintf( yyc, "\n" ); } lPCodePos += 4; break; + case HB_P_JUMPSHORTTRUE: + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] ); + if ( lOffset > 127 ) + lOffset -= 256; + + fprintf( yyc, "\tHB_P_JUMPSHORTTRUE, %i,", + pFunc->pCode[ lPCodePos + 1 ] ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); + fprintf( yyc, "\n" ); + lPCodePos += 2; + break; + + case HB_P_JUMPTRUE: + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 ); + if ( lOffset > SHRT_MAX ) + lOffset -= 65536; + + fprintf( yyc, "\tHB_P_JUMPTRUE, %i, %i,", + pFunc->pCode[ lPCodePos + 1 ], + pFunc->pCode[ lPCodePos + 2 ] ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); + fprintf( yyc, "\n" ); + lPCodePos += 3; + break; + case HB_P_JUMPFARTRUE: { - LONG lPos = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536; + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset -= 16777216; + fprintf( yyc, "\tHB_P_JUMPFARTRUE, %i, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ], pFunc->pCode[ lPCodePos + 3 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lPos, lPCodePos + ( lPos ? lPos : 4 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, ( LONG ) ( lPCodePos + lOffset ) ); fprintf( yyc, "\n" ); } lPCodePos += 4; @@ -1099,12 +1161,12 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou break; case HB_P_SEQBEGIN: - w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536; + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536 ); fprintf( yyc, "\tHB_P_SEQBEGIN, %i, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ], pFunc->pCode[ lPCodePos + 3 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 4 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, lPCodePos + lOffset ); fprintf( yyc, "\n" ); lPCodePos += 4; break; @@ -1112,12 +1174,12 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou case HB_P_SEQEND: if( hb_comp_bGenCVerbose ) fprintf( yyc, "/* %05li */ ", lPCodePos ); else fprintf( yyc, "\t" ); - w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536; + lOffset = ( LONG ) ( pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 + pFunc->pCode[ lPCodePos + 3 ] * 65536 ); fprintf( yyc, "HB_P_SEQEND, %i, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ], pFunc->pCode[ lPCodePos + 3 ] ); - if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 4 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li (abs: %05li) */", lOffset, lPCodePos + lOffset ); fprintf( yyc, "\n" ); lPCodePos += 4; break; diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 85b250a486..f7926392d2 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -60,6 +60,9 @@ void hb_compFixReturns( void ); /* fixes all last defined function returns jumps static PFUNCTION hb_compFunctionNew( char *, char ); /* creates and initialises the _FUNC structure */ static void hb_compCheckDuplVars( PVAR pVars, char * szVarName, int iVarScope ); /*checks for duplicate variables definitions */ +//int hb_compSort_ULONG( ULONG * ulLeft, ULONG * ulRight ); +static void hb_compOptimizeJumps( void ); +static void hb_compPrepareOptimize( void ); /* global variables */ FILES hb_comp_files; @@ -99,6 +102,7 @@ BOOL hb_comp_bCredits = FALSE; /* print credits */ BOOL hb_comp_bLogo = TRUE; /* print logo */ BOOL hb_comp_bSyntaxCheckOnly = FALSE; /* syntax check only */ int hb_comp_iLanguage = LANG_C; /* default Harbour generated output language */ +int hb_comp_iJumpOptimize = 1; typedef struct __EXTERN { @@ -671,6 +675,10 @@ static PFUNCTION hb_compFunctionNew( char * szName, HB_SYMBOLSCOPE cScope ) pFunc->iStaticsBase = hb_comp_iStaticCnt; pFunc->pOwner = NULL; pFunc->bFlags = 0; + pFunc->iNOOPs = 0; + pFunc->iJumps = 0; + pFunc->pNOOPs = NULL; + pFunc->pJumps = NULL; return pFunc; } @@ -841,6 +849,14 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) hb_xfree( ( void * ) pVar ); } + /* Release the NOOP array. */ + if ( pFunc->pNOOPs ) + hb_xfree( ( void * ) pFunc->pNOOPs ); + + /* Release the Jumps array. */ + if ( pFunc->pJumps ) + hb_xfree( ( void * ) pFunc->pJumps ); + hb_xfree( ( void * ) pFunc->pCode ); /* hb_xfree( ( void * ) pFunc->szName ); The name will be released in hb_compSymbolKill() */ hb_xfree( ( void * ) pFunc ); @@ -848,7 +864,6 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) return pNext; } - PCOMSYMBOL hb_compSymbolKill( PCOMSYMBOL pSym ) { PCOMSYMBOL pNext = pSym->pNext; @@ -1242,20 +1257,86 @@ USHORT hb_compFunctionGetPos( char * szFunctionName ) /* return 0 if not found o return 0; } +void hb_compPrepareOptimize() +{ + if ( ! hb_comp_iJumpOptimize ) + return; + + hb_comp_functions.pLast->iJumps++; + + //printf( "Preparing for Jump #%i in: %li 3rd Byte=%i", hb_comp_functions.pLast->iJumps, ( ULONG ) ( hb_comp_functions.pLast->lPCodePos - 4 ), hb_comp_functions.pLast->pCode[ hb_comp_functions.pLast->lPCodePos ] ); + //getchar(); + + if ( hb_comp_functions.pLast->pJumps ) + { + + hb_comp_functions.pLast->pJumps = hb_xrealloc( hb_comp_functions.pLast->pJumps, sizeof( ULONG ) * hb_comp_functions.pLast->iJumps ); + hb_comp_functions.pLast->pJumps[ hb_comp_functions.pLast->iJumps - 1 ] = ( ULONG ) ( hb_comp_functions.pLast->lPCodePos - 4 ); + } + else + { + hb_comp_functions.pLast->pJumps = hb_xgrab( sizeof( ULONG ) ); + hb_comp_functions.pLast->pJumps[ hb_comp_functions.pLast->iJumps - 1 ] = ( LONG ) ( hb_comp_functions.pLast->lPCodePos - 4 ); + } + + /* Only Reserve Request - Don't know if NOOPs will remain yet. */ + if ( hb_comp_functions.pLast->pCode[ hb_comp_functions.pLast->lPCodePos - 3 ] == 0 && + hb_comp_functions.pLast->pCode[ hb_comp_functions.pLast->lPCodePos - 2 ] == 0 && + hb_comp_functions.pLast->pCode[ hb_comp_functions.pLast->lPCodePos - 1 ] == 0 ) + return; + + /* 3rd. Byte might be not used */ + if( hb_comp_functions.pLast->pCode[ hb_comp_functions.pLast->lPCodePos - 1 ] == HB_P_NOOP ) + { + hb_comp_functions.pLast->iNOOPs++; + + if ( hb_comp_functions.pLast->pNOOPs ) + { + hb_comp_functions.pLast->pNOOPs = hb_xrealloc( hb_comp_functions.pLast->pNOOPs, sizeof( ULONG ) * hb_comp_functions.pLast->iNOOPs ); + hb_comp_functions.pLast->pNOOPs[ hb_comp_functions.pLast->iNOOPs - 1 ] = hb_comp_functions.pLast->lPCodePos - 1; + } + else + { + hb_comp_functions.pLast->pNOOPs = hb_xgrab( sizeof( ULONG ) ); + hb_comp_functions.pLast->pNOOPs[ hb_comp_functions.pLast->iNOOPs - 1 ] = hb_comp_functions.pLast->lPCodePos - 1; + } + + /* 2nd. Byte might be not used */ + if( hb_comp_functions.pLast->pCode[ hb_comp_functions.pLast->lPCodePos - 2 ] == HB_P_NOOP ) + { + hb_comp_functions.pLast->iNOOPs++; + + if ( hb_comp_functions.pLast->pNOOPs ) + { + hb_comp_functions.pLast->pNOOPs = hb_xrealloc( hb_comp_functions.pLast->pNOOPs, sizeof( ULONG ) * hb_comp_functions.pLast->iNOOPs ); + hb_comp_functions.pLast->pNOOPs[ hb_comp_functions.pLast->iNOOPs - 1 ] = hb_comp_functions.pLast->lPCodePos - 2; + } + else + { + hb_comp_functions.pLast->pNOOPs = hb_xgrab( sizeof( ULONG ) ); + hb_comp_functions.pLast->pNOOPs[ hb_comp_functions.pLast->iNOOPs - 1 ] = hb_comp_functions.pLast->lPCodePos - 2; + } + } + } +} + ULONG hb_compGenJump( LONG lOffset ) { - int iBytes = 3; - /* Just a place holder, it might be a far jump...*/ if ( lOffset == 0 ) { hb_compGenPCode3( HB_P_JUMPFAR, 0, 0 ); hb_compGenPCode1( 0 ); } + else if ( lOffset >= -128 && lOffset <= 127 ) + { + hb_compGenPCode3( HB_P_JUMPSHORT, HB_LOBYTE( lOffset ), HB_P_NOOP ); + hb_compGenPCode1( HB_P_NOOP ); + } else if ( lOffset >= SHRT_MIN && lOffset <= SHRT_MAX ) { hb_compGenPCode3( HB_P_JUMP, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); - iBytes = 2; + hb_compGenPCode1( HB_P_NOOP ); } else if ( lOffset >= (-8388608L) && lOffset <= 8388607L ) { @@ -1267,23 +1348,28 @@ ULONG hb_compGenJump( LONG lOffset ) hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); } - return hb_comp_functions.pLast->lPCodePos - iBytes; + hb_compPrepareOptimize(); + + return hb_comp_functions.pLast->lPCodePos - 3; } ULONG hb_compGenJumpFalse( LONG lOffset ) { - int iBytes = 3; - /* Just a place holder, it might be a far jump...*/ if ( lOffset == 0 ) { hb_compGenPCode3( HB_P_JUMPFARFALSE, 0, 0 ); hb_compGenPCode1( 0 ); } + else if ( lOffset >= -128 && lOffset <= 127 ) + { + hb_compGenPCode3( HB_P_JUMPSHORTFALSE, HB_LOBYTE( lOffset ), HB_P_NOOP ); + hb_compGenPCode1( HB_P_NOOP ); + } else if ( lOffset >= SHRT_MIN && lOffset <= SHRT_MAX ) { hb_compGenPCode3( HB_P_JUMPFALSE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); - iBytes = 2; + hb_compGenPCode1( HB_P_NOOP ); } else if ( lOffset >= (-8388608L) && lOffset <= 8388607L ) { @@ -1295,102 +1381,28 @@ ULONG hb_compGenJumpFalse( LONG lOffset ) hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); } - return hb_comp_functions.pLast->lPCodePos - iBytes; -} + hb_compPrepareOptimize(); -void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo ) -{ - BYTE * pCode = hb_comp_functions.pLast->pCode; - LONG lOffset = ulTo - ulFrom + 1; - - if ( lOffset >= SHRT_MIN && lOffset <= SHRT_MAX ) - { - switch ( pCode[ ( ULONG ) ulFrom - 1 ] ) - { - case HB_P_JUMP : - break; - - case HB_P_JUMPTRUE : - break; - - case HB_P_JUMPFALSE : - break; - case HB_P_JUMPFAR : - pCode[ ( ULONG ) ulFrom - 1 ] = HB_P_JUMP; - pCode[ ( ULONG ) ulFrom + 2 ] = HB_P_NOOP; - break; - - case HB_P_JUMPFARTRUE : - pCode[ ( ULONG ) ulFrom - 1 ] = HB_P_JUMPTRUE; - pCode[ ( ULONG ) ulFrom + 2 ] = HB_P_NOOP; - break; - - case HB_P_JUMPFARFALSE : - pCode[ ( ULONG ) ulFrom - 1 ] = HB_P_JUMPFALSE; - pCode[ ( ULONG ) ulFrom + 2 ] = HB_P_NOOP; - break; - - case HB_P_SEQBEGIN : - break; - - case HB_P_SEQEND : - break; - - default: - printf( "\rPCode: %i", pCode[ ( ULONG ) ulFrom - 1 ] ); - hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_NOT_FOUND, NULL, NULL ); - break; - } - - pCode[ ( ULONG ) ulFrom ] = HB_LOBYTE( lOffset ); - pCode[ ( ULONG ) ulFrom + 1 ] = HB_HIBYTE( lOffset ); - } - else if ( lOffset >= (-8388608L) && lOffset <= 8388607L ) - { - switch ( pCode[ ( ULONG ) ulFrom - 1 ] ) - { - case HB_P_JUMP : - hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_INVALID_JUMP, NULL, NULL ); - break; - - case HB_P_JUMPTRUE : - hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_INVALID_JUMPTRUE, NULL, NULL ); - break; - - case HB_P_JUMPFALSE : - hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_INVALID_JUMPFALSE, NULL, NULL ); - break; - } - - pCode[ ( ULONG ) ulFrom ] = HB_LOBYTE( lOffset ); - pCode[ ( ULONG ) ulFrom + 1 ] = HB_HIBYTE( lOffset ); - pCode[ ( ULONG ) ulFrom + 2 ] = ( BYTE ) ( ( ( USHORT ) ( lOffset ) >> 16 ) & 0xFF ); - } - else - { - hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); - } -} - -void hb_compGenJumpHere( ULONG ulOffset ) -{ - hb_compGenJumpThere( ulOffset, hb_comp_functions.pLast->lPCodePos ); + return hb_comp_functions.pLast->lPCodePos - 3; } ULONG hb_compGenJumpTrue( LONG lOffset ) { - int iBytes = 3; - /* Just a place holder, it might be a far jump...*/ if ( lOffset == 0 ) { hb_compGenPCode3( HB_P_JUMPFARTRUE, 0, 0 ); hb_compGenPCode1( 0 ); } - if ( lOffset >= SHRT_MIN && lOffset <= SHRT_MAX ) + else if ( lOffset >= -128 && lOffset <= 127 ) + { + hb_compGenPCode3( HB_P_JUMPSHORTTRUE, HB_LOBYTE( lOffset ), HB_P_NOOP ); + hb_compGenPCode1( HB_P_NOOP ); + } + else if ( lOffset >= SHRT_MIN && lOffset <= SHRT_MAX ) { hb_compGenPCode3( HB_P_JUMPTRUE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); - iBytes = 2; + hb_compGenPCode1( HB_P_NOOP ); } else if ( lOffset >= (-8388608L) && lOffset <= 8388607L ) { @@ -1402,7 +1414,218 @@ ULONG hb_compGenJumpTrue( LONG lOffset ) hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); } - return hb_comp_functions.pLast->lPCodePos - iBytes; + hb_compPrepareOptimize(); + + return hb_comp_functions.pLast->lPCodePos - 3; +} + +void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo ) +{ + BYTE * pCode = hb_comp_functions.pLast->pCode; + LONG lOffset = ulTo - ulFrom + 1; + int iOptimize = 1 && hb_comp_iJumpOptimize ; + + if ( lOffset >= -128 && lOffset <= 127 ) + { + switch ( pCode[ ( ULONG ) ( ulFrom - 1 ) ] ) + { + /* + case HB_P_JUMPSHORT : + break; + + case HB_P_JUMPSHORTTRUE : + break; + + case HB_P_JUMPSHORTFALSE : + break; + + case HB_P_JUMP : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPSHORT; + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPTRUE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPSHORTTRUE; + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPFALSE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPSHORTFALSE; + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + */ + + case HB_P_JUMPFAR : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPSHORT; + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPFARTRUE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPSHORTTRUE; + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPFARFALSE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPSHORTFALSE; + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_SEQBEGIN : + iOptimize = 0; + break; + + case HB_P_SEQEND : + iOptimize = 0; + break; + + default: + printf( "\rPCode: %i", pCode[ ( ULONG ) ulFrom - 1 ] ); + hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_NOT_FOUND, NULL, NULL ); + break; + } + + pCode[ ( ULONG ) ulFrom ] = HB_LOBYTE( lOffset ); + + if ( ! iOptimize ) + return; + + /* Check if 3rd. Byte not used. */ + if ( pCode[ ( ULONG ) ( ulFrom + 2 ) ] == HB_P_NOOP ) + { + hb_comp_functions.pLast->iNOOPs++; + + if ( hb_comp_functions.pLast->pNOOPs ) + { + hb_comp_functions.pLast->pNOOPs = hb_xrealloc( hb_comp_functions.pLast->pNOOPs, sizeof( ULONG ) * hb_comp_functions.pLast->iNOOPs ); + hb_comp_functions.pLast->pNOOPs[ hb_comp_functions.pLast->iNOOPs - 1 ] = ( ULONG ) ulFrom + 2; + } + else + { + hb_comp_functions.pLast->pNOOPs = hb_xgrab( sizeof( ULONG ) ); + hb_comp_functions.pLast->pNOOPs[ 0 ] = ( ULONG ) ulFrom + 2; + } + + /* Check if 2nd. Byte not used. */ + if ( pCode[ ( ULONG ) ulFrom + 1 ] == HB_P_NOOP ) + { + hb_comp_functions.pLast->iNOOPs++; + + if ( hb_comp_functions.pLast->pNOOPs ) + { + hb_comp_functions.pLast->pNOOPs = hb_xrealloc( hb_comp_functions.pLast->pNOOPs, sizeof( ULONG ) * hb_comp_functions.pLast->iNOOPs ); + hb_comp_functions.pLast->pNOOPs[ hb_comp_functions.pLast->iNOOPs - 1 ] = ( ULONG ) ulFrom + 1; + } + else + { + hb_comp_functions.pLast->pNOOPs = hb_xgrab( sizeof( ULONG ) ); + hb_comp_functions.pLast->pNOOPs[ 0 ] = ( ULONG ) ulFrom + 1; + } + } + } + } + else if ( lOffset >= SHRT_MIN && lOffset <= SHRT_MAX ) + { + switch ( pCode[ ( ULONG ) ( ulFrom - 1 ) ] ) + { + /* + case HB_P_JUMPSHORT : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPSHORTTRUE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPTRUE; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPSHORTFALSE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPFALSE; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMP : + break; + + case HB_P_JUMPTRUE : + break; + + case HB_P_JUMPFALSE : + break; + */ + + case HB_P_JUMPFAR : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMP; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPFARTRUE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPTRUE; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_JUMPFARFALSE : + pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPFALSE; + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP; + break; + + case HB_P_SEQBEGIN : + iOptimize = 0; + break; + + case HB_P_SEQEND : + iOptimize = 0; + break; + + default: + printf( "\rPCode: %i", pCode[ ( ULONG ) ulFrom - 1 ] ); + hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_NOT_FOUND, NULL, NULL ); + break; + } + + pCode[ ulFrom ] = HB_LOBYTE( lOffset ); + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_HIBYTE( lOffset ); + + if ( ! iOptimize ) + return; + + /* Check if 3rd. Byte not used. */ + if ( pCode[ ( ULONG ) ulFrom + 2 ] == HB_P_NOOP ) + { + hb_comp_functions.pLast->iNOOPs++; + + if ( hb_comp_functions.pLast->pNOOPs ) + { + hb_comp_functions.pLast->pNOOPs = hb_xrealloc( hb_comp_functions.pLast->pNOOPs, sizeof( ULONG ) * hb_comp_functions.pLast->iNOOPs ); + hb_comp_functions.pLast->pNOOPs[ hb_comp_functions.pLast->iNOOPs - 1 ] = ( ULONG ) ulFrom + 2; + } + else + { + hb_comp_functions.pLast->pNOOPs = hb_xgrab( sizeof( ULONG ) ); + hb_comp_functions.pLast->pNOOPs[ 0 ] = ( ULONG ) ulFrom + 2; + } + } + } + else if ( lOffset >= (-8388608L) && lOffset <= 8388607L ) + { + pCode[ ulFrom ] = HB_LOBYTE( lOffset ); + pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_HIBYTE( lOffset ); + pCode[ ( ULONG ) ( ulFrom + 2 ) ] = ( BYTE ) ( ( ( USHORT ) ( lOffset ) >> 16 ) & 0xFF ); + } + else + { + hb_compGenError( hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); + } +} + +void hb_compGenJumpHere( ULONG ulOffset ) +{ + hb_compGenJumpThere( ulOffset, hb_comp_functions.pLast->lPCodePos ); } void hb_compLinePush( void ) /* generates the pcode with the currently compiled source code line */ @@ -1446,7 +1669,6 @@ void hb_compLinePushIfDebugger( void ) } hb_comp_functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE ); /* clear RETURN flag */ } - } void hb_compLinePushIfInside( void ) /* generates the pcode with the currently compiled source code line */ @@ -2062,6 +2284,10 @@ static void hb_compCheckDuplVars( PVAR pVar, char * szVarName, int iVarScope ) void hb_compFixReturns( void ) /* fixes all last defined function returns jumps offsets */ { + if ( hb_comp_iJumpOptimize ) + if ( hb_comp_functions.pLast && hb_comp_functions.pLast->iNOOPs ) + hb_compOptimizeJumps(); + if( hb_comp_iWarnings && hb_comp_functions.pLast ) { PVAR pVar; @@ -2093,6 +2319,250 @@ void hb_compFixReturns( void ) /* fixes all last defined function returns jumps } } +int hb_compSort_ULONG( const void * pLeft, const void * pRight ) +{ + ULONG ulLeft = *( (ULONG *) (pLeft) ); + ULONG ulRight = *( (ULONG *) (pRight) ); + + if ( ulLeft == ulRight ) + return 0 ; + else if ( ulLeft < ulRight ) + return -1; + else + return 1; +} + +void hb_compOptimizeJumps( void ) +{ + /* Jump Optimizer */ + BYTE * pCode = hb_comp_functions.pLast->pCode; + BYTE * pOptimized = hb_xgrab( hb_comp_functions.pLast->lPCodePos - hb_comp_functions.pLast->iNOOPs ); + ULONG * pNOOPs = hb_comp_functions.pLast->pNOOPs; + ULONG * pJumps = hb_comp_functions.pLast->pJumps; + int * piShifts = hb_xgrab( sizeof( int ) * hb_comp_functions.pLast->iJumps ); + ULONG ulOptimized = 0; + ULONG ulNextByte = 0; + int iNOOP; + ULONG ulOffset; + ULONG ulBytes2Copy; + int iJump; + int iForward; + + //printf( "\rOptimize ON" ); + //getchar(); + + /* Needed so the pasting of PCODE pieces below will work correctly */ + qsort( (void *) pNOOPs, hb_comp_functions.pLast->iNOOPs, sizeof( ULONG ), hb_compSort_ULONG ); + + /* + for( iNOOP = 0; iNOOP < hb_comp_functions.pLast->iNOOPs; iNOOP++ ) + { + printf( "\rNOOP #%i at:%li", iNOOP, pNOOPs[ iNOOP ] ); + getchar(); + + if ( pNOOPs[ iNOOP ] == 0 ) + { + printf( "\r*** 0 *** NOOP # %i at:%li", iNOOP, pNOOPs[ iNOOP ] ); + getchar(); + } + } + + for( iJump = 0; iJump < hb_comp_functions.pLast->iJumps; iJump++ ) + { + switch ( pCode[ pJumps[ iJump ] ] ) + { + case HB_P_JUMPSHORT : + case HB_P_JUMPSHORTFALSE : + case HB_P_JUMPSHORTTRUE : + { + ulOffset = pCode[ pJumps[ iJump ] + 1 ]; + + if ( ulOffset > 127 ) + { + ulOffset -= 256; + iForward = 0; + } + else + iForward = 1; + } + break; + + case HB_P_JUMP : + case HB_P_JUMPFALSE : + case HB_P_JUMPTRUE : + { + ulOffset = ( ULONG ) ( pCode[ pJumps[ iJump ] + 1 ] + ( pCode[ pJumps[ iJump ] + 2 ] * 256 ) ); + if ( ulOffset > SHRT_MAX ) + { + ulOffset -= 65536; + iForward = 0; + } + else + iForward = 1; + } + break; + + default: + { + ulOffset = ( ULONG )( pCode[ pJumps[ iJump ] + 1 ] + ( pCode[ pJumps[ iJump ] + 2 ] * 256 ) + ( pCode[ pJumps[ iJump ] + 3 ] * 65536 ) ); + if ( ulOffset > 8388607L ) + { + ulOffset -= 16777216L; + iForward = 0; + } + } + break; + } + + printf( "\rJump=%li, Base=%li, Offset=%li, Target=%li", iJump, pJumps[ iJump ], ulOffset, pJumps[ iJump ] + ulOffset ); + getchar(); + + if ( pJumps[ iJump ] == 0 || ulOffset == 0 ) + { + printf( "\r*** 0 *** Jump=%li, Base=%li, Offset=%li, Target=%li", iJump, pJumps[ iJump ], ulOffset, pJumps[ iJump ] + ulOffset ); + getchar(); + } + } + */ + + for( iJump = 0; iJump < hb_comp_functions.pLast->iJumps; iJump++ ) + piShifts[ iJump ] = 0; + + /* First Scan NOOPS - Adjust Jump addresses. */ + for( iNOOP = 0; iNOOP < hb_comp_functions.pLast->iNOOPs; iNOOP++ ) + { + /* Adjusting preceding jumps that pooint to code beyond the current NOOP or trailing backward jumps pointing to lower address. */ + for ( iJump = 0; iJump < hb_comp_functions.pLast->iJumps ; iJump++ ) + { + switch ( pCode[ pJumps[ iJump ] ] ) + { + case HB_P_JUMPSHORT : + case HB_P_JUMPSHORTFALSE : + case HB_P_JUMPSHORTTRUE : + { + ulOffset = pCode[ pJumps[ iJump ] + 1 ]; + + if ( ulOffset > 127 ) + { + ulOffset -= 256; + iForward = 0; + } + else + iForward = 1; + } + break; + + case HB_P_JUMP : + case HB_P_JUMPFALSE : + case HB_P_JUMPTRUE : + { + ulOffset = ( ULONG ) ( pCode[ pJumps[ iJump ] + 1 ] + ( pCode[ pJumps[ iJump ] + 2 ] * 256 ) ); + if ( ulOffset > SHRT_MAX ) + { + ulOffset -= 65536; + iForward = 0; + } + else + iForward = 1; + } + break; + + default: + { + ulOffset = ( ULONG )( pCode[ pJumps[ iJump ] + 1 ] + ( pCode[ pJumps[ iJump ] + 2 ] * 256 ) + ( pCode[ pJumps[ iJump ] + 3 ] * 65536 ) ); + if ( ulOffset > 8388607L ) + { + ulOffset -= 16777216L; + iForward = 0; + } + } + break; + } + + /* Only intrested in forward (positive) jumps. */ + if ( iForward ) + { + //printf( "\rCurrent NOOP=%li, Address=%li, Jump=%i, Base=%li, Offset=%li, Target=%li", iNOOP, pNOOPs[ iNOOP ], iJump, pJumps[ iJump ], ulOffset, pJumps[ iJump ] + ulOffset ); + //getchar(); + + /* Only if points to code beyond the current fix. */ + if ( pJumps[ iJump ] < pNOOPs[ iNOOP ] && pJumps[ iJump ] + piShifts[ iJump ] + ulOffset > pNOOPs[ iNOOP ] ) + { + /* Increasing Shift Counter for this Jump. */ + piShifts[ iJump ]++; + + if ( pCode[ pJumps[ iJump ] + 1 ] ) + pCode[ pJumps[ iJump ] + 1 ]--; + else + { + pCode[ pJumps[ iJump ] + 1 ] = 255; + pCode[ pJumps[ iJump ] + 2 ]--; + } + + //printf( "\rAdjusted Jump=%li To: %li", iJump, ( pCode[ pJumps[ iJump ] + 1 ] + pCode[ pJumps[ iJump ] + 2 ] * 256 ) ); + //getchar(); + } + } + else + { + /* Adjusting all later jumps (if negative) and target prior the current NOOP. */ + + //printf( "\rCurrent NOOP=%li, Address=%li, Jump=%i, Base=%li, Offset=%li, Target=%li", iNOOP, pNOOPs[ iNOOP ], iJump, pJumps[ iJump ], ulOffset, pJumps[ iJump ] + ulOffset ); + //getchar(); + + // Only if points to code beyond the current fix. + if ( pJumps[ iJump ] > pNOOPs[ iNOOP ] && pJumps[ iJump ] + piShifts[ iJump ] + ulOffset < pNOOPs[ iNOOP ] ) + { + /* Decreasing Shift Counter for this Jump. */ + piShifts[ iJump ]--; + + if ( pCode[ pJumps[ iJump ] + 1 ] < 255 ) + pCode[ pJumps[ iJump ] + 1 ]++; + else + { + pCode[ pJumps[ iJump ] + 1 ] = 0; + pCode[ pJumps[ iJump ] + 2 ]++; + } + + //printf( "\rAdjusted Jump=%li To: %li", iJump, ( pCode[ pJumps[ iJump ] + 1 ] + pCode[ pJumps[ iJump ] + 2 ] * 256 - 65536 ) ); + //getchar(); + } + } + } + } + + //printf( "\rPasting" ); + //getchar(); + + /* Second Scan, after all adjustements been made, we can copy the optimized code. */ + for( iNOOP = 0; iNOOP < hb_comp_functions.pLast->iNOOPs; iNOOP++ ) + { + ulBytes2Copy = ( pNOOPs[ iNOOP ] - ulNextByte ) ; + + while ( ulBytes2Copy-- > 0 ) + pOptimized[ ulOptimized++ ] = pCode[ ulNextByte++ ]; + + /* Skip the NOOP and point to next valid byte */ + ulNextByte++; + } + + //printf( "\rCopying Remainder" ); + //getchar(); + + /* Copy remainder beyond the last NOOP. */ + while ( ulNextByte < hb_comp_functions.pLast->lPCodePos ) + pOptimized[ ulOptimized++ ] = pCode[ ulNextByte++ ]; + + //printf( "\rCopied" ); + //getchar(); + + hb_xfree( (void *) pCode ); + + hb_comp_functions.pLast->pCode = pOptimized; + hb_comp_functions.pLast->lPCodePos = ulOptimized; + hb_comp_functions.pLast->lPCodeSize = ulOptimized; +} + /* Generate the opcode to open BEGIN/END sequence * This code is simmilar to JUMP opcode - the offset will be filled with * - either the address of HB_P_SEQEND opcode if there is no RECOVER clause @@ -2103,6 +2573,8 @@ ULONG hb_compSequenceBegin( void ) hb_compGenPCode3( HB_P_SEQBEGIN, 0, 0 ); hb_compGenPCode1( 0 ); + hb_compPrepareOptimize(); + return hb_comp_functions.pLast->lPCodePos - 3; } @@ -2118,6 +2590,8 @@ ULONG hb_compSequenceEnd( void ) hb_compGenPCode3( HB_P_SEQEND, 0, 0 ); hb_compGenPCode1( 0 ); + hb_compPrepareOptimize(); + return hb_comp_functions.pLast->lPCodePos - 3; } diff --git a/harbour/source/compiler/hbgenerr.c b/harbour/source/compiler/hbgenerr.c index ca20cc4783..65894fbd17 100644 --- a/harbour/source/compiler/hbgenerr.c +++ b/harbour/source/compiler/hbgenerr.c @@ -82,10 +82,7 @@ char * hb_comp_szErrors[] = "Macro of declared symbol: \'%s\'", "Invalid selector in send: \'%s\'", "ANNOUNCEd procedure \'%s\' must be a public symbol", - "Jump offset too long for HB_P_JUMP needed HB_P_JUMPFAR", - "Jump offset too long for HB_P_JUMPTRUE needed HB_P_JUMPFARTRUE", - "Jump offset too long for HB_P_JUMPFALSE needed HB_P_JUMPFARFALSE", - "HB_P_JUMPx not found when fixing offset" + "Jump PCode not found", }; /* Table with parse warnings */ diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 5209688b2d..453ff7d201 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -362,10 +362,11 @@ void hb_vmQuit( void ) void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) { BYTE bCode; - USHORT w = 0; + LONG w = 0; USHORT uiParams; BOOL bCanRecover = FALSE; ULONG ulPrivateBase; + LONG lOffset; HB_TRACE(HB_TR_DEBUG, ("hb_vmExecute(%p, %p)", pCode, pSymbols)); @@ -623,7 +624,12 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) * 2) store the address of RECOVER or END opcode */ hb_stack.pPos->type = HB_IT_LONG; - hb_stack.pPos->item.asLong.value = w + pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset = ( lOffset - 16777216 ); + + hb_stack.pPos->item.asLong.value = w + lOffset; hb_stackPush(); /* * 3) store current RECOVER base @@ -679,7 +685,11 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) /* * skip outside of SEQUENCE structure */ - w += pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset = ( lOffset - 16777216 ); + + w += lOffset; break; case HB_P_SEQRECOVER: @@ -712,46 +722,123 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) /* Jumps */ + case HB_P_JUMPSHORT: + + lOffset = pCode[ w + 1 ]; + if ( lOffset > 127 ) + lOffset -= 256 ; + /* + if( lOffset ) + w += lOffset; + else + w += 2; + */ + w += lOffset; + break; + case HB_P_JUMP: - uiParams = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); - if( uiParams ) - w += uiParams; + + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); + if ( lOffset > SHRT_MAX ) + lOffset -= 65536; + /* + if( lOffset ) + w += lOffset; else w += 3; + */ + w += lOffset; break; case HB_P_JUMPFAR: - uiParams = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); - if( uiParams ) - w += uiParams; + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset -= 16777216L; + + /* + if( lOffset ) + w += lOffset; else w += 4; + */ + + w += lOffset; + break; + + case HB_P_JUMPSHORTFALSE: + if( ! hb_vmPopLogical() ) + { + lOffset = pCode[ w + 1 ]; + if ( lOffset > 127 ) + lOffset -= 256; + + w += lOffset; + } + else + w += 2; break; case HB_P_JUMPFALSE: if( ! hb_vmPopLogical() ) - w += pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); + { + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); + if ( lOffset > SHRT_MAX ) + lOffset -= 65536; + + w += lOffset; + } else w += 3; break; case HB_P_JUMPFARFALSE: if( ! hb_vmPopLogical() ) - w += pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + { + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset -= 16777216L; + + w += lOffset; + } else w += 4; break; + case HB_P_JUMPSHORTTRUE: + if( hb_vmPopLogical() ) + { + lOffset = pCode[ w + 1 ]; + if ( lOffset > 127 ) + lOffset -= 256; + + w += lOffset; + } + else + w += 2; + break; + case HB_P_JUMPTRUE: if( hb_vmPopLogical() ) - w += pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); + { + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); + if ( lOffset > SHRT_MAX ) + lOffset -= 65536; + + w += lOffset; + } else w += 3; break; case HB_P_JUMPFARTRUE: if( hb_vmPopLogical() ) - w += pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + { + lOffset = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) + ( pCode[ w + 3 ] * 65536 ); + if ( lOffset > 8388607L ) + lOffset -= 16777216L; + + w += lOffset; + } else w += 4; break; diff --git a/harbour/tests/test.prg b/harbour/tests/test.prg index 19dacf4745..4b39cfc820 100644 --- a/harbour/tests/test.prg +++ b/harbour/tests/test.prg @@ -1,19 +1,26 @@ -// -// $Id$ -// +#include "setcurs.ch" -// +#define ALTD_DISABLE 0 +#define ALTD_ENABLE 1 -procedure main() +static s_oDebugger +static s_lExit := .F. - local s := " " + chr(0) + " mab " + chr(0) + " " +function AltD( nAction ) + static s_lEnabled := .t. - StrDump( s ) - QOut( s ) + do case + case nAction == nil + if s_lEnabled + s_lExit := .f. + __dbgEntry( ProcLine( 2 ) ) + endif - qout( '"' + ltrim(s) + '"' ) - qout( '"' + rtrim(s) + '"' ) - qout( '"' + alltrim(s) + '"' ) + case nAction == ALTD_DISABLE + s_lEnabled := .f. -return + case nAction == ALTD_ENABLE + s_lEnabled := .t. + endcase +return nil