[comp.os.minix] PC Minix 1.3 compiler bugs

nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (07/24/89)

I have just spent about two hours trying to make Terrence Holm's
integer calculator (ic(1), from 412@ubc-bdcvax.uucp) work on my system.
What a frustrating experience!  And it's not because the calculator
is wrong, either.  The compiler shipped with v1.3 is BROKEN (but you
knew that already, didn't you?).

Here is a description of the bugs that I found while trying to make ic
work. Both involve long signed integers.

#1.  Generating -2147483648 (the largest negative long integer)

The compiler generates incorrect code for this, IF it is a static or
external variable.  Automatics and constants seem fine.  Here's an example:

  static long int x = 0x80000000;
  long int y = 020000000000;

  void func()
  {
    long int a = 0x80000000;
    long int b = 020000000000;
    long int c;

    c = 0x80000000;
    func2(c, 0x80000000);
  }

Here is the generated code:

  .data
  _x:
  .word 0,-32767
  .globl _y
  _y:
  .word 0,-32767
  .globl _func
  .text
  _func:
  push bp
  mov bp,sp
  sub sp,#12
  mov -4(bp),#0
  mov -2(bp),#-32768
  mov -8(bp),#0
  mov -6(bp),#-32768
  mov -12(bp),#0
  mov -10(bp),#-32768
  mov ax,#-32768
  push ax
  xor ax,ax
  push ax
  push -10(bp)
  push -12(bp)
  call _func2
  add sp,#8
  jmp .cret

Note that the automatic variables a,b, and c are all fine.  The
constant passed to func2() is fine too.  But x and y are both
initialized to bogus values.


#2.  Wrong code is generated for negation of long signed integers

Consider the code:
 
  main()
  {
    long int x = 65536;

    x = -x;
    x++;
    x = -x;
    printf("%ld\n", x);
  }

The corresponding assembler is:

  .globl _main
  .text
  _main:
  push bp
  mov bp,sp
  push ax
  push ax
  mov -4(bp),#0
  mov -2(bp),#1
  neg -4(bp)
  neg -2(bp)
  sbb -2(bp),#0
  add -4(bp),#1
  adc -2(bp),#0
  neg -4(bp)
  neg -2(bp)
  sbb -2(bp),#0
  push -2(bp)
  push -4(bp)
  mov ax,#_1
  push ax
  call _printf
  add sp,#6
  jmp .cret
  .data
  _1:
  .word 27685
  .word 2660
  .word 0
  .text

The output is:

  131071

which is quite clearly wrong.  It should be 65535.

The problem is with the generated code for the negation of a long
integer.  The Minix C compiler generates the instruction sequence:

  neg loword
  neg hiword
  sbb hiword,#0

which gives the spurious answer above.  It should generate:

  neg loword
  adc hiword,#0
  neg hiword


#3.  _doprintf is broken for long integers

This isn't a compiler problem - it's just the truth.  The fact that the
compiler is broken makes it that much harder to write a working version.
(The fact that _doprintf doesn't work makes it hard to find compiler bugs!)
No version that I have seen (even one fixed as in 396@uvicctr.uucp) will
correctly handle the case of -2147483648.  And the second bug described
above sure makes a lot of other cases fail too (just try -65536 and -655360
in %ld format for fun).

Does anyone have a working _doprintf?  Do I need to hack one myself?

Norbert


P.S.  (to ast)  Do I get a fixed compiler for free? :-)