The following does not work with bleeding edge FreeBSD: program streamtest implicit none character(1) :: lf = char(10) character(1) :: tchar integer :: i,j,k real(kind=4), dimension(100,100) :: anarray open(10, file="teststream", access="stream", form="unformatted") anarray = 3.14159 write(10) anarray anarray = 0.0 write(10, pos=1) ! This should position for the following read read(10) anarray anarray = abs(anarray - 3.14159) if (any(anarray.gt.0.00001)) call abort() close(10,status="delete") end program streamtest
Created attachment 12093 [details] assembly output for reduced case There is wrong code generated setting up the parameters for the second call to write. The pointers are off by 400. You can see this by comparing the instructions just before the first call too _gfortran_st_write vs the instructions leading up to the second _gfortran_st_write. -fdump-tree-original looks OK. Inserting a flush right after the first call to write in the test case and the problem goes away. Middle-end or backend problem?
Simplified test case used in discussion above. program streamtest implicit none real, dimension(2,3) :: anarray open(10, file="teststream", access="stream", form="unformatted") anarray = 3.14159 write(10) anarray !flush(10) write(10, pos=1) ! This is a way to position an unformatted file anarray = 0.0 read(10) anarray close(10,status="keep") end program streamtest Additional info: Using built-in specs. Target: x86_64-unknown-freebsd7.0 Configured with: ../gcc4x/configure --prefix=/home/sgk/work/4x --enable-languages=c,fortran Thread model: posix gcc version 4.2.0 20060816 (experimental)
(In reply to comment #1) > Middle-end or backend problem? Can you look at the dump that is produced by -fdump-tree-final_cleanup and see if it is correct?
Using -fdump-tree-final_cleanup all looks OK.
Here is a debug trace showing the steps leading up to the mutation of the dtp pointer. StevebB on IRC indicated that the assembly output on linux x86-64 natch the freebsd version I posted here and the problem does not occur on that platform. Notice the before an after values of the dtp pointer! (gdb) s *_gfortran_st_write_done (dtp=0x7fffffffe640) at ../../../gcc4x/libgfortran/io/transfer.c:2546 2546 if (dtp->u.p.scratch != NULL) (gdb) s 2548 if (dtp->u.p.current_unit != NULL) (gdb) s 2549 unlock_unit (dtp->u.p.current_unit); (gdb) s *_gfortrani_unlock_unit (u=0x2008103b0) at gthr-posix.h:566 566 if (__gthread_active_p ()) (gdb) p dtp No symbol "dtp" in current context. (gdb) p u $5 = (gfc_unit *) 0x2008103b0 (gdb) p *u $6 = {unit_number = 10, s = 0x200828000, left = 0x0, right = 0x0, priority = 14047, read_bad = 1, current_record = 1, endfile = NO_ENDFILE, mode = WRITING, flags = {access = ACCESS_STREAM, action = ACTION_READWRITE, blank = BLANK_NULL, delim = DELIM_NONE, form = FORM_UNFORMATTED, is_notpadded = 0, position = POSITION_ASIS, status = STATUS_UNKNOWN, pad = PAD_YES, convert = CONVERT_NATIVE}, recl = 1, last_record = 25, maxrec = 9223372036854775807, bytes_left = 0, lock = 0x0, waiting = 0, closed = 0, ls = 0x0, rank = 0, file_len = 10, file = 0x20082c140 "teststream"} (gdb) s 567 return __gthrw_(pthread_mutex_unlock) (mutex); (gdb) s Breakpoint 1, *_gfortran_st_write (dtp=0x7fffffffe7d0) at ../../../gcc4x/libgfortran/io/transfer.c:2506 2506 {
Here is a comparison of no optimization and with -O1. Does this code look the same on x86-64 that is not FreeBSD? Code with no optimization: This does not work. call _gfortran_st_write_done movq $.LC0, -424(%rbp) movl $8, -416(%rbp) movl $10, -428(%rbp) movq $1, -392(%rbp) movl $512, -432(%rbp) leaq -432(%rbp), %rdi call _gfortran_st_write Code with -O1: This works call _gfortran_st_write_done movq $.LC0, 8(%rsp) movl $8, 16(%rsp) movl $10, 4(%rsp) movq $1, 40(%rsp) movl $512, (%rsp) movq %rsp, %rdi call _gfortran_st_write
Jerry, On Fedora Core 5 x86_64 with the svn pull from a few days back and last stream patch I get the follow diff between the code generated with -O0 and -O1... call _gfortran_st_write_done - movq $.LC0, -600(%rbp) - movl $8, -592(%rbp) - movl $10, -604(%rbp) - movq $1, -568(%rbp) - movl $512, -608(%rbp) - leaq -608(%rbp), %rdi + movq $.LC0, 8(%rsp) + movl $8, 16(%rsp) + movl $10, 4(%rsp) + movq $1, 40(%rsp) + movl $512, (%rsp) + movq %rsp, %rdi call _gfortran_st_write In both cases the reduced test case runs fine.
I think this confirms the problem is in __gthrw_(pthread_mutex_unlock) (mutex) on FreeBSD.
Fixed on 4.2, will not go to 4.1 *** This bug has been marked as a duplicate of 29053 ***