🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

1 total messages Started by Jeremy Allison Tue, 13 Oct 1992 16:51
(none)
#1194
Author: Jeremy Allison
Date: Tue, 13 Oct 1992 16:51
341 lines
9703 bytes
Dear GCC maintainers,

	Firstly, thanks for such a great product. I really appreciate being
able to use ansi C and c++ on my obsolete machine (a Sun386i).

I believe I have found a bug in code generation using gcc2.2.2 with 
-fpic under a sun386i, but I believe this bug would also hit other 
architectures.I am generating pic code using the patch I submitted
earlier to change the format of the assembler generated output for
the sun386i - I don't think this is having an effect on the rtl
generated though. Please contact me if you wish a copy of this
patch.

Consider the following program, testcase.c

-------cut here---------------------
#ifdef WORKS
const double val = 0.3;
#else
#define val 0.3
#endif

int main()
{
        float newval = 5.0;
        float testval = newval/val;

        printf("should be 16.66666 etc. but is %f\n", testval);
}
-------------end testcase-----------

Compile using pic code :-

% gcc -fpic testcase.c

Then run

% a.out
should be 16.66666 etc. but is Inf

But compile with the -DWORKS flag set,

% gcc -fpic -DWORKS testcase.c

Then run

% a.out
should be 16.66666 etc. but is 16.666666


All is well. 


I have examined the code generated and have discovered 
the following.

---------Assembler generated with -fpic -DWORKS (correct code) -----------
        .file   "testcase.c"
        .version        "GNU C 2.2.2"
gcc2_compiled.:
.globl val
.text
        .align 4
val:
        .double 2.9999999999999998889777e-01
.LC0:
        .byte 0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x20
        .byte 0x31,0x36,0x2e,0x36,0x36,0x36,0x36,0x36,0x20,0x65
        .byte 0x74,0x63,0x2e,0x20,0x62,0x75,0x74,0x20,0x69,0x73
        .byte 0x20,0x25,0x66,0xa,0x0
        .align 4
.globl main
main:
        pushl %ebp
        movl %esp,%ebp
        subl $8,%esp
        pushl %ebx
        call .L2
.L2:
        popl %ebx
        addl $_globtb_offset,%ebx
        call __main, %eax
        movl $1084227584,-4(%ebp)
        flds -4(%ebp)
        movl val(%ebx),%eax
        fdivl (%eax)
        fstps -8(%ebp)
        flds -8(%ebp)
        subl $8,%esp
        fstpl (%esp)
        movl .LC0(%ebx),%edx
        movl %edx,%eax
        pushl %eax
        call printf, %eax
        addl $12,%esp
.L1:
        movl -12(%ebp),%ebx
        leave
        ret

-----------RTL GENERATED FOR ABOVE ASSEMBLER -----
-----(using gcc -fpic -c -dr -DWORKS testcase.c)--

;; Function main

(note 2 0 3 "" NOTE_INSN_DELETED)

(note 3 2 4 "" NOTE_INSN_FUNCTION_BEG)

(note 4 3 6 "" NOTE_INSN_DELETED)

(call_insn 6 4 8 (parallel[ 
           (call (mem:QI (symbol_ref:SI ("__main")))
               (const_int 0))
           (set (reg:SI 7)
               (plus:SI (reg:SI 7)
                   (const_int 0)))
       ] ) -1 (nil)
   (nil))

(note 8 6 9 "" NOTE_INSN_BLOCK_BEG)

(insn 9 8 11 (set (mem:SF (plus:SI (reg:SI 18)
               (const_int -4)))
       (const_double:SF (const_int 0) 0 1075052544)) -1 (nil)
   (nil))

(insn 11 9 13 (set (reg:DF 21)
       (float_extend:DF (mem:SF (plus:SI (reg:SI 18)
                   (const_int -4))))) -1 (nil)
   (nil))

(insn 13 11 14 (set (reg:SI 22)
       (mem:SI (plus:SI (reg:SI 3)
               (symbol_ref:SI ("val"))))) -1 (nil)
   (nil))

(insn 14 13 15 (set (reg:DF 23)
       (div:DF (reg:DF 21)
           (mem/u:DF (reg:SI 22)))) -1 (nil)
   (nil))

(insn 15 14 17 (set (mem:SF (plus:SI (reg:SI 18)
               (const_int -8)))
       (float_truncate:SF (reg:DF 23))) -1 (nil)
   (nil))

(insn 17 15 18 (set (reg:DF 24)
       (float_extend:DF (mem:SF (plus:SI (reg:SI 18)
                   (const_int -8))))) -1 (nil)
   (nil))

(insn 18 17 20 (set (mem:DF (pre_dec:SI (reg:SI 7)))
       (reg:DF 24)) -1 (nil)
   (nil))

(insn 20 18 21 (set (reg:SI 27)
       (mem:SI (plus:SI (reg:SI 3)
               (symbol_ref/v:SI ("*.LC0"))))) -1 (nil)
   (nil))

(insn 21 20 22 (set (reg:SI 26)
       (reg:SI 27)) -1 (nil)
   (expr_list:REG_EQUAL (symbol_ref/v:SI ("*.LC0"))
       (nil)))

(insn 22 21 24 (set (mem:SI (pre_dec:SI (reg:SI 7)))
       (reg:SI 26)) -1 (nil)
   (nil))

(call_insn 24 22 25 (set (reg:SI 0)
       (call (mem:QI (symbol_ref:SI ("printf")))
           (const_int 12))) -1 (nil)
   (nil))

(insn 25 24 27 (set (reg:SI 7)
       (plus:SI (reg:SI 7)
           (const_int 12))) -1 (nil)
   (nil))

(note 27 25 28 "" NOTE_INSN_BLOCK_END)

(note 28 27 30 "" NOTE_INSN_FUNCTION_END)

(code_label 30 28 0 1 "")

-------------------end code-------------------------------

-------Assembler generated with -fpic (incorrect code)----
        .file   "testcase.c"
        .version        "GNU C 2.2.2"
gcc2_compiled.:
.text
.LC0:
        .byte 0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x20
        .byte 0x31,0x36,0x2e,0x36,0x36,0x36,0x36,0x36,0x20,0x65
        .byte 0x74,0x63,0x2e,0x20,0x62,0x75,0x74,0x20,0x69,0x73
        .byte 0x20,0x25,0x66,0xa,0x0
        .align 4
.LC1:
        .double 2.9999999999999998889777e-01
        .align 4
.globl main
main:
        pushl %ebp
        movl %esp,%ebp
        subl $8,%esp
        pushl %ebx
        call .L2
.L2:
        popl %ebx
        addl $_globtb_offset,%ebx
        call __main, %eax
        movl $1084227584,-4(%ebp)
        flds -4(%ebp) 
        fldl .LC1(%ebx)          <======= NOTE INCORRECT PIC REFERENCE
        fdivrp %st,%st(1)        Should be : movl .LC1(%ebx),%eax
        fstps -8(%ebp)			     fdivl (%eax)
        flds -8(%ebp)
        subl $8,%esp
        fstpl (%esp)
        movl .LC0(%ebx),%edx
        movl %edx,%eax
        pushl %eax
        call printf, %eax
        addl $12,%esp
.L1:
        movl -12(%ebp),%ebx
        leave
        ret

-------RTL GENERATED FOR ABOVE ASSEMBLER ---
-----(using gcc -c -fpic -dr testcase.c)----

;; Function main

(note 2 0 3 "" NOTE_INSN_DELETED)

(note 3 2 4 "" NOTE_INSN_FUNCTION_BEG)

(note 4 3 6 "" NOTE_INSN_DELETED)

(call_insn 6 4 8 (parallel[ 
           (call (mem:QI (symbol_ref:SI ("__main")))
               (const_int 0))
           (set (reg:SI 7)
               (plus:SI (reg:SI 7)
                   (const_int 0)))
       ] ) -1 (nil)
   (nil))

(note 8 6 9 "" NOTE_INSN_BLOCK_BEG)

(insn 9 8 11 (set (mem:SF (plus:SI (reg:SI 18)
               (const_int -4)))
       (const_double:SF (const_int 0) 0 1075052544)) -1 (nil)
   (nil))

(insn 11 9 12 (set (reg:DF 21)
       (float_extend:DF (mem:SF (plus:SI (reg:SI 18)
                   (const_int -4))))) -1 (nil)
   (nil))

(insn 12 11 13 (set (reg:DF 23)
       (const_double:DF (const_int 0) 858993459 1070805811)) -1 (nil)
   (nil))

(insn 13 12 14 (set (reg:DF 22)
       (div:DF (reg:DF 21)
           (reg:DF 23))) -1 (nil)
   (nil))

(insn 14 13 16 (set (mem:SF (plus:SI (reg:SI 18)
               (const_int -8)))
       (float_truncate:SF (reg:DF 22))) -1 (nil)
   (nil))

(insn 16 14 17 (set (reg:DF 24)
       (float_extend:DF (mem:SF (plus:SI (reg:SI 18)
                   (const_int -8))))) -1 (nil)
   (nil))

(insn 17 16 19 (set (mem:DF (pre_dec:SI (reg:SI 7)))
       (reg:DF 24)) -1 (nil)
   (nil))

(insn 19 17 20 (set (reg:SI 27)
       (mem:SI (plus:SI (reg:SI 3)
               (symbol_ref/v:SI ("*.LC0"))))) -1 (nil)
   (nil))

(insn 20 19 21 (set (reg:SI 26)
       (reg:SI 27)) -1 (nil)
   (expr_list:REG_EQUAL (symbol_ref/v:SI ("*.LC0"))
       (nil)))

(insn 21 20 23 (set (mem:SI (pre_dec:SI (reg:SI 7)))
       (reg:SI 26)) -1 (nil)
   (nil))

(call_insn 23 21 24 (set (reg:SI 0)
       (call (mem:QI (symbol_ref:SI ("printf")))
           (const_int 12))) -1 (nil)
   (nil))

(insn 24 23 26 (set (reg:SI 7)
       (plus:SI (reg:SI 7)
           (const_int 12))) -1 (nil)
   (nil))

(note 26 24 27 "" NOTE_INSN_BLOCK_END)

(note 27 26 29 "" NOTE_INSN_FUNCTION_END)

(code_label 29 27 0 1 "")

---------------end code-----------------------------

I have examined the GCC 2.2.2 code and believe I know what
is going wrong, but not yet how to fix it ! 
All numeric constants in a program are put onto a linked list
within each function and then just before the function is
generated are allocated real addresses and output. This is done
in the immed_double_const routines in varasm.c. The problem seems
to be that when pic references are made to these constants *and the
constant is too big to fix into a register* (ie. double float) then
an incorrect pic reference is generated. When the constant is turned
into an symbolic constant (-DWORKS) then a symbol is generated for 
this value and correct pic is generated. The outputting of the pool
constants doesn't seem to be going through the "legitimize_pic_address"
function, which I would have thought should fix the problem.
I have been investigating adding code to generate more rtx expressions
into the immed_double_const routine to return an rtx expression containing
the correct pic code. Please let me know if you think this is the correct
solution (as I haven't been able to get it to work yet, and also would like
to fix this one !).

	Regards,


		Jeremy Allison.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads