diff --git a/harbour/ChangeLog b/harbour/ChangeLog index cf9d581c4b..0e4f992257 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,26 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-12-08 16:30 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/bin/hb-mkslib.sh + ! fixed last modification + + * harbour/doc/Makefile + + harbour/doc/cmpopt.txt + + added small description for Harbour compile time optimization + + * harbour/include/hbexpra.c + + allow to use hb_mutexCreate() as static variable initializer, f.e.: + static s_mtxarr := { "MTX1" => hb_mutexCreate(), ; + "MTX2" => hb_mutexCreate(), ; + "MTX3" => hb_mutexCreate() } + * harbour/include/hbexprb.c + % comment + + * harbour/source/common/expropt2.c + + added some missing optimizations for date constants + + added optimization for multiple negate expressions + 2008-12-07 22:22 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * harbour/contrib/gtwvg/makefile * harbour/contrib/gtwvg/common.mak diff --git a/harbour/bin/hb-mkslib.sh b/harbour/bin/hb-mkslib.sh index 6710610533..a11f80a99a 100755 --- a/harbour/bin/hb-mkslib.sh +++ b/harbour/bin/hb-mkslib.sh @@ -96,7 +96,7 @@ if [ "${SLIB_EXT}" != ".dylib" ]; then echo "cannot read file: ${f}" exit 1 fi - cp "${dir}/${f}" "${OTMPDIR}" || exit 1 + cp "${f}" "${OTMPDIR}" || exit 1 ;; *.a) if [ "${f#/}" == "${f}" ]; then @@ -110,7 +110,7 @@ if [ "${SLIB_EXT}" != ".dylib" ]; then d="${f##*/}" mkdir $d cd $d - ${CCPREFIX}ar -x "${dir}/${f}" || exit 1 + ${CCPREFIX}ar -x "${f}" || exit 1 cd .. ;; *) diff --git a/harbour/doc/Makefile b/harbour/doc/Makefile index 9dedf77d9e..6ad6cad994 100644 --- a/harbour/doc/Makefile +++ b/harbour/doc/Makefile @@ -6,6 +6,7 @@ ROOT = ../ DOC_FILES=\ c_std.txt \ + cmpopt.txt \ class_tp.txt \ cmdline.txt \ codebloc.txt \ diff --git a/harbour/doc/cmpopt.txt b/harbour/doc/cmpopt.txt new file mode 100644 index 0000000000..b36842275c --- /dev/null +++ b/harbour/doc/cmpopt.txt @@ -0,0 +1,165 @@ +/* + * $Id$ + */ + +Przemyslaw Czerpak (druzus/at/priv.onet.pl) +Harbour compile time optimizations. + +1. Function call optimization. + +Just like Clipper Harbour compiler can optimize few function calls if +parameters are well known constant values. Here is the list of functions +optimized at compile time: + + - Clipper compatible: + + AT( , ) // Clipper wrongly calculates + // "" $ as .T. + CHR( ) + UPPER( ) // cannot contain characters different then + [0-9A-Za-z] + + - Harbour extension: + + INT( ) + ASC( [ , ... ] ) + MIN( , ) // is N, D or L value + MAX( , ) // is N, D or L value + EMPTY( | | | | + | | | NIL ) + LEN( | | ) + CTOD( [ , ... } ) + DTOS( ] ) + STOD( [ ] ) + HB_STOD( [ ] ) + HB_BITNOT( [, ... ] ) + HB_BITAND( , [, ] ) + HB_BITOR( , [, ] ) + HB_BITXOR( , [, ] ) + HB_BITTEST( , [, ... ] ) + HB_BITSET( , [, ... ] ) + HB_BITRESET( , [, ... ] ) + HB_BITSHIFT( , [, ... ] ) + + - Harbour special functions: + + HB_I18N_GETTEXT_NOOP( [ , ] ) + HB_I18N_NGETTEXT_NOOP( | [ , ] ) + HB_MUTEXCREATE() + + +2. Expresion optimization: + +Just like Clipper Harbour compiler can optimize some expresions if +arguments are well known and can be callculated at compile time: + + - Clipper compatible: + + + => + + => + + => + + => + // In Clipper neither nor + // can contain '&' character. Harbour checks + // if concatenation can change existing valid + // macro expression + - => + - => + - => + - => + // In Clipper neither nor + // can contain '&' character. Harbour checks + // if concatenation can change existing valid + // macro expression + * => + / => // Clipper optimize only integers + % => + $ => // Clipper wrongly calculates + // "" $ as .T. + == => + == => + == => + == => + NIL == => + == NIL => + = => + = => + = => + NIL = => + = NIL => + "" = "" => .T. + != => + != => + != => + NIL != => + != NIL => + "" != "" => .F. + >= => + >= => + >= => + <= => + <= => + <= => + > => + > => + > => + < => + < => + < => + .NOT. .T. => .F. + .NOT. .F. => .T. + .AND. => + .OR. => + IIF( .T., , ) => + IIF( .F., , ) => + + - optimizations disabled by -z compiler switch + + .T. .AND. => + .AND. .T. => + .F. .OR. => + .OR. .F. => + .F. .AND. => .F. + .AND. .F. => .F. + .T. .OR. => .T. + .OR. .T. => .T. + + - Harbour extension: + + ^ => + [ ] => + ( ) => // it allows to optimize expresions like: 1+(2) + + - Harbour extension which may disable RT errors in wrong expressions: + .NOT. .NOT. => + - - => + + 0 => + 0 + => + + "" => + "" + => + + In cases when result is miningless Harbour compiler can skip code + for operation, f.e. such line of .prg code: + ( ) + where result of operation is ignored Harbour reduced the code + to: + ( , ) + +In Clipper in some places optiomization is not enabled, f.e. Clipper +does not optimize in expressions like: + : msg( ... ) +Unlike Clipper Harbour tries to optimize all expressions. + +If some code needs strict Clipper behavior then it can be forced by using +-kc Harbour compiler switch. It disabled Harbour extensions and enables +replicating some Clipper bugs like optimizing "" $ to .T. at +compile time when it runtime it's .F. + +Expressions fully optimized to constant values at compile time can be used +to intialize static variables, f.e.: + static s_var := ( 1 + 2 / 3 ) + +Harbour has additional optimization phase which operates on generated PCODE. +It can also reduce expressions, joins jumps, removes death or meaningless +code which can appear after all other optimizations and were not optimized +by expression optimizer. diff --git a/harbour/include/hbexpra.c b/harbour/include/hbexpra.c index 97c0d4573c..ab7f2ed432 100644 --- a/harbour/include/hbexpra.c +++ b/harbour/include/hbexpra.c @@ -547,10 +547,35 @@ HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex, HB_CO /* ************************************************************************* */ #ifndef HB_MACRO_SUPPORT + +/* List of functions which can be used as static initializers */ +static const char * s_szStaticFun[] = { + "HB_MUTEXCREATE" +}; + +#define STATIC_FUNCTIONS ( sizeof( s_szStaticFun ) / sizeof( char * ) ) + +static BOOL hb_compStaticFunction( const char * szName ) +{ + unsigned int ui; + for( ui = 0; ui < STATIC_FUNCTIONS; ++ui ) + { + if( strcmp( szName, s_szStaticFun[ ui ] ) == 0 ) + return TRUE; + } + return FALSE; +} + + static void hb_compExprCheckStaticInitializer( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr, HB_COMP_DECL ) { - if( pRightExpr->ExprType > HB_ET_FUNREF || - pRightExpr->ExprType == HB_ET_SELF ) + if( ( pRightExpr->ExprType > HB_ET_FUNREF || + pRightExpr->ExprType == HB_ET_SELF ) && + !( pRightExpr->ExprType == HB_ET_FUNCALL && + pRightExpr->value.asFunCall.pFunName->ExprType == HB_ET_FUNNAME && + hb_compStaticFunction( pRightExpr->value.asFunCall.pFunName-> + value.asSymbol ) && + hb_compExprParamListLen( pRightExpr->value.asFunCall.pParms ) == 0 ) ) { /* Illegal initializer for static variable (not a constant value) */ diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index bc8a3657e7..56b024f96b 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -3127,6 +3127,8 @@ static HB_EXPR_FUNC( hb_compExprUseNot ) return pSelf; } +/* handler for = operator + */ static HB_EXPR_FUNC( hb_compExprUseEqual ) { switch( iMessage ) diff --git a/harbour/source/common/expropt2.c b/harbour/source/common/expropt2.c index 9d1dc0c99f..aaa010744f 100644 --- a/harbour/source/common/expropt2.c +++ b/harbour/source/common/expropt2.c @@ -756,6 +756,16 @@ HB_EXPR_PTR hb_compExprReduceNegate( HB_EXPR_PTR pSelf, HB_COMP_DECL ) HB_COMP_EXPR_FREE( pSelf ); pSelf = pExpr; } + else if( pExpr->ExprType == HB_EO_NEGATE && HB_SUPPORT_HARBOUR ) + { + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + pExpr->ExprType = HB_ET_NONE; /* suppress deletion of operator components */ + pExpr = pExpr->value.asOperator.pLeft; + HB_COMP_EXPR_FREE( pSelf ); + pSelf = pExpr; + } return pSelf; } @@ -875,6 +885,17 @@ HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; + case HB_ET_DATE: + { + BOOL bResult = pLeft->value.asNum.val.l != pRight->value.asNum.val.l; + HB_COMP_EXPR_FREE( pLeft ); + HB_COMP_EXPR_FREE( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + case HB_ET_NIL: HB_COMP_EXPR_FREE( pLeft ); HB_COMP_EXPR_FREE( pRight ); @@ -972,6 +993,17 @@ HB_EXPR_PTR hb_compExprReduceGE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; + case HB_ET_DATE: + { + BOOL bResult = pLeft->value.asNum.val.l >= pRight->value.asNum.val.l; + HB_COMP_EXPR_FREE( pLeft ); + HB_COMP_EXPR_FREE( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + } /* TODO: add checking of incompatible types else @@ -1036,6 +1068,17 @@ HB_EXPR_PTR hb_compExprReduceLE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; + case HB_ET_DATE: + { + BOOL bResult = pLeft->value.asNum.val.l <= pRight->value.asNum.val.l; + HB_COMP_EXPR_FREE( pLeft ); + HB_COMP_EXPR_FREE( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + } /* TODO: add checking of incompatible types else @@ -1100,6 +1143,17 @@ HB_EXPR_PTR hb_compExprReduceGT( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; + case HB_ET_DATE: + { + BOOL bResult = pLeft->value.asNum.val.l > pRight->value.asNum.val.l; + HB_COMP_EXPR_FREE( pLeft ); + HB_COMP_EXPR_FREE( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + } /* TODO: add checking of incompatible types else @@ -1164,8 +1218,17 @@ HB_EXPR_PTR hb_compExprReduceLT( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; - default: + case HB_ET_DATE: + { + BOOL bResult = pLeft->value.asNum.val.l < pRight->value.asNum.val.l; + HB_COMP_EXPR_FREE( pLeft ); + HB_COMP_EXPR_FREE( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } break; + } /* TODO: add checking of incompatible types else @@ -1246,6 +1309,17 @@ HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; + case HB_ET_DATE: + { + BOOL bResult = pLeft->value.asNum.val.l == pRight->value.asNum.val.l; + HB_COMP_EXPR_FREE( pLeft ); + HB_COMP_EXPR_FREE( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + case HB_ET_NIL: HB_COMP_EXPR_FREE( pLeft ); HB_COMP_EXPR_FREE( pRight );