[comp.sys.ibm.pc.programmer] TC++ bug

aviv@discus.technion.ac.il (Aviv Siegel) (07/20/90)

  Hello all NetLanders !

   After we got (finally) the TC++ package, we go through an evaluation
 period. After more than a year of extensive usage in TC 2.00, we want
 to be sure that the migration to TC++ 1.00 worth it ...
   Currently, we don't use any C++ extensions, just pure TC code.
   Well, first of all, the package is HUGE. If you want to work without
 a VERY fast disk, or vast amount of EMS (more than 1M) and a fast machine
 (at least 10MHz 286) - you'll have to wait ...
   Most of our code compiled without a problem (a few 10K of source lines).
 BUT ...

   2 major points which popped up during the first 2 days of usage (!) :

   * The names of the CODE segment in the LARGE, MEDIUM and HUGE libraries
 were changed (unnoticeably ??). The CODE segments were named <filename>_TEXT
 where the <filename> was the function name (as MALLOC_TEXT). Now all
 the names are _TEXT, regardless of model. This change caused different
 grouping on link phase, which means different behavior of programs.
 The problem was easily solved (once recognized) by changing the NAME of
 the program modules CODE segment to _TEXT (instead of *, as default).

   * The second problem is a clearly a bug :
   When the next small procedure was compiled with the -O option (Jump-
 optimization), the compiler produces a bug. It uses the dx register to
 calculate the pointer, CHANGES IT BY USING IMUL, and using the changed
 value as if it wasn't changed (it compiled WITHOUT any other optimization).
 The code was compiled with no other optimization (Size preference).
 As far as we know, jump optimization does not do register load optimization
 (which is off, by default).

   the code fragment :

char far *screen=(char far *)0xb0000000 ;

void func(char x,char y,char length,char far *buffer) {
  char far *from ;

  from=screen+x*2+y*160 ;
  memcpy(buffer,from,length*2) ;
}

 The code it produces (using tcc -S -O, debug & other info removed) :
   .
   .
   .
   ;
   ;    void func(char x,char y,char length,char far *buffer) {
   ;
        assume  cs:_TEXT
_func   proc    near
        push    bp
        mov     bp,sp
        sub     sp,4
   ;
   ;      char far *from ;
   ;
   ;      from=screen+x*2+y*160 ;
   ;
        mov     al,byte ptr [bp+4]
        cbw
        shl     ax,1
        mov dx,word ptr DGROUP:_screen+2      ; <<--- using dx
        mov     bx,word ptr DGROUP:_screen
        add     bx,ax
        mov     al,byte ptr [bp+6]
        cbw
        mov     cx,160
        push    dx                            ; <<-- pushing it
        imul    cx                            ; <<-- CHANGING IT !!!
        add     bx,ax
        mov     word ptr [bp-4],bx
        pop ax                                ; <<-- popping into ax
        mov     word ptr [bp-2],ax
   ;
   ;      memcpy(buffer,from,length*2) ;
   ;
        mov     al,byte ptr [bp+8]
        cbw
        shl     ax,1
        push    ax
        push    dx                            ; <<-- pushing the WRONG value !!
        push    word ptr [bp-4]
        push    word ptr [bp+12]
        push    word ptr [bp+10]
        call    near ptr _memcpy
        add     sp,10
   ;
   ;    }
   ;
        mov     sp,bp
        pop     bp
        ret
_func   endp

   After compiling again without the -O, the ONLY difference was the wrong
 line (push dx) which was changed to (the correct) :

   push word ptr [bp-2] ;

   Surprisingly, another way to fix the problem was to change the source line
 to :

   from=screen+160*y+2*x ;

   This change swapped the order of execution, so the imul was done BEFORE
 the loading of dx, and the problem did not appear. Again, the -O switch
 changed the behavior of the parameters pushing to the stack. Why ???
 This problem, did not appear in TC 2.00. The compiler behaved correctly
 on all occasions.

   The only conclusion for us was : DON'T USE JUMP OPTIMIZATION !
   (or may be any other optimization ??)
   It can INSERT BUGS into your code.

   Until now, we did not find other bugs.

   And you ???

=============================================================================
    .--.                                    aviv@techunix.BITNET
   /    \  |      | | |      |                      or
  +------+  \    /  |  \    /            aviv@tecunix.technion.ac.il
  |      |   \__/   |   \__/
--
=============================================================================
    .--.                                    aviv@techunix.BITNET
   /    \  |      | | |      |                      or
  +------+  \    /  |  \    /            aviv@tecunix.technion.ac.il

grimlok@hubcap.clemson.edu (Mike Percy) (07/20/90)

aviv@discus.technion.ac.il (Aviv Siegel) writes:
>   Well, first of all, the package is HUGE. If you want to work without
> a VERY fast disk, or vast amount of EMS (more than 1M) and a fast machine
> (at least 10MHz 286) - you'll have to wait ...
 
I disagree.  I am running on a very slow disk (20M), 8MHz 286 XT, and
only have the standard 640K.  While it's not the fastest thing in the
world, I think it's still as fast as TC2.0 (talking about command line
setup here, haven't done too much with the IDE, since the old IDE made
me throw up).  
 
I use some of the options which more than buy back any lost time due to
having to load a bigger tcc.exe  (458560 vs. 179917,  but TC++ _must_
use VROOMM, otherwise I don't think I could compile anything! To hazzard
a guess the .cpp and .c compilers overlay each other.)
For instance, I use the make -S option, which swaps make out allowing
more free space for compiling, which makes compiling faster.  I also use
the command batching facility of make -- this alone shaves 15sec from my
typical full re-make (loading and unload the compiler takes a lot of
time, load it once to compile a handful of programs instead of load,
compile, unload, load, compile, unload...).
The improved assembly listings are a boon.  Autodependency checking
looks useful too, but I haven't had time to mess with it yet.
I look forward to using the VROOMM overlay technology, as I have some
stuff that is pushing the limit as it is.
The documentation seems to be much cleaner and useful, even though I
have found some misprints (check out the v..printf functions).
 
All this and a [supposedly] ANSI conformant compiler with C++ to boot!
 
It's not perfect, as is made clear by a number of posts.  But for a 1.0
release, I'll take it.