Transfer

  • Follow


I find a frequent need to byte swap when I transfer from little endian 
to big endian destined output.  It would be nice if transfer 
automatically byte swapped (by selection).  Does it already support this 
byte swapping readily?
0
Reply garylscott (1357) 8/14/2012 2:03:56 AM

Gary Scott <garylscott@sbcglobal.net> wrote:

> I find a frequent need to byte swap when I transfer from little endian 
> to big endian destined output.  It would be nice if transfer 
> automatically byte swapped (by selection).  Does it already support this 
> byte swapping readily?

Some C systems have a swab() function, which will byte-swap
data while copying it.

Otherwise, with the appropriate ORDER it seems to me that 
TRANSFER would byte swap data in an array of a one-byte type.

That might take a TRANSFER to a one byte type, TRANSFER to
do the byte swap, and TRANSFER again to the destination type.

Or call swab() with C interoperability.

Now, I believe that some C compilers will inline swab(), especially
on processors that have a byte swap instruction. For a large
enough data structure, though, the function call overhead 
shouldn't be so big.

-- glen
0
Reply gah (12303) 8/14/2012 3:05:40 AM


On 8/13/12 9:03 PM, Gary Scott wrote:
> I find a frequent need to byte swap when I transfer from little endian
> to big endian destined output. It would be nice if transfer
> automatically byte swapped (by selection). Does it already support this
> byte swapping readily?
I'm sure TRANSFER doesn't do byte swapping; nothing else in Fortran goes 
this deep into the hardware.  But, how about something like

     char_array(whatever:1:-1) = transfer(thing, "x", whatever)
     backwards_thing = transfer(char_array(1:whatever), thing, whatever)

I'm not sure what you need for the size arguments.

With a little work you can convert this into a one line expression by 
nesting the transfers and then it's easy to convert it into either a 
statement function or external function.

Not particularly elegant, but if you're doing I/O a few memory moves 
aren't a real cost.

Dick Hendrickson

0
Reply dick.hendrickson (1286) 8/14/2012 3:09:45 AM

On Aug 14, 12:03=A0pm, Gary Scott <garylsc...@sbcglobal.net> wrote:
> I find a frequent need to byte swap when I transfer from little endian
> to big endian destined output. =A0It would be nice if transfer
> automatically byte swapped (by selection). =A0Does it already support thi=
s
> byte swapping readily?

If the objects are integers,
it's easy to do with a few shifts and logical ands.

If reals, EQUIVALENCE to integer(s) and do as above.
0
Reply louisa.hutch (142) 8/14/2012 3:48:17 AM

Gary Scott <garylscott@sbcglobal.net> wrote:

> I find a frequent need to byte swap when I transfer from little endian
> to big endian destined output.  It would be nice if transfer 
> automatically byte swapped (by selection).  Does it already support this
> byte swapping readily?

Trouble is that byte-swapping details depend on the size of the objects,
and in at least one case on their type. Transfer pretty much ignore type
- that's its whole point.

-- 
Richard Maine
email: last name at domain . net
domain: summer-triangle
0
Reply nospam47 (9742) 8/14/2012 6:18:36 AM

Gary Scott wrote:
> I find a frequent need to byte swap when I transfer from little endian
> to big endian destined output.  It would be nice if transfer
> automatically byte swapped (by selection).  Does it already support this
> byte swapping readily?

If it is only about I/O, many compilers support a way to specify the 
endianness of the I/O via environment variables, command-line arguments 
and via a call to an intrinsic or withing an extra argument in the OPEN 
or WRITE/READ statement.

Contrary to the transfer suggestions, it is compiler dependent, but it 
might be faster and easier � at least if you mostly use a single compiler.

Tobias
0
Reply burnus (564) 8/14/2012 6:19:26 AM

Tobias Burnus <burnus@net-b.de> wrote:

> Gary Scott wrote:
> > I find a frequent need to byte swap when I transfer from little endian
> > to big endian destined output.  It would be nice if transfer
> > automatically byte swapped (by selection).  Does it already support this
> > byte swapping readily?
> 
> If it is only about I/O, many compilers support a way to specify the 
> endianness of the I/O via environment variables, command-line arguments
> and via a call to an intrinsic or withing an extra argument in the OPEN
> or WRITE/READ statement.
> 
> Contrary to the transfer suggestions, it is compiler dependent, but it
> might be faster and easier – at least if you mostly use a single compiler.

But those options all inherently depend on knowing the type and kind of
the variable at the time of the I/O. Otherwise, they won't know what
particular byte swapping to apply. For example, if 4 bytes are to be
treated as a single 4-byte integer, the swapping required is different
from if it is two 2-byte integers; and, of course, if it is 4 1-byte
integers, there is no swapping at all.

In some apps, you essentially read a block full of bytes. The particular
data types are not known at the time you read the block, but are
determined dynamically by embedded data within the block. To trivially
illustrate, each data item could be preceded by a 1-byte field to
indicate the type and kind of the data that follows it. The actual data
formats I deal with aren't quite like that, but that's a simple way to
explain the basic problem. There just is no way for the compiler to
automatically deal with structures like that. You have to parse the data
in the block and do any needed swapping yourself. Not that such swapping
is particularly hard to do yourself, assuming that you write the app to
accomodate such things in the first place. Retrofitting to an app that
previously ignored the matter can certainly be harder.

-- 
Richard Maine
email: last name at domain . net
domain: summer-triangle
0
Reply nospam47 (9742) 8/14/2012 12:40:38 PM

On 8/13/2012 10:05 PM, glen herrmannsfeldt wrote:
> Gary Scott <garylscott@sbcglobal.net> wrote:
>
>> I find a frequent need to byte swap when I transfer from little endian
>> to big endian destined output.  It would be nice if transfer
>> automatically byte swapped (by selection).  Does it already support this
>> byte swapping readily?
>
> Some C systems have a swab() function, which will byte-swap
> data while copying it.
>
> Otherwise, with the appropriate ORDER it seems to me that
> TRANSFER would byte swap data in an array of a one-byte type.
>
> That might take a TRANSFER to a one byte type, TRANSFER to
> do the byte swap, and TRANSFER again to the destination type.
>
> Or call swab() with C interoperability.
>
> Now, I believe that some C compilers will inline swab(), especially
> on processors that have a byte swap instruction. For a large
> enough data structure, though, the function call overhead
> shouldn't be so big.
>
> -- glen
>
I have my own byteswap procedure for integers.  It isn't a difficult 
thing, was just thinking that the need for such a thing in system 
programming, and in many areas of data processing and sharing across 
systems, that adding an option to transfer might be useful.
0
Reply garylscott (1357) 8/14/2012 1:20:55 PM

On 8/14/2012 1:19 AM, Tobias Burnus wrote:
> Gary Scott wrote:
>> I find a frequent need to byte swap when I transfer from little endian
>> to big endian destined output.  It would be nice if transfer
>> automatically byte swapped (by selection).  Does it already support this
>> byte swapping readily?
>
> If it is only about I/O, many compilers support a way to specify the
> endianness of the I/O via environment variables, command-line arguments
> and via a call to an intrinsic or withing an extra argument in the OPEN
> or WRITE/READ statement.
>
> Contrary to the transfer suggestions, it is compiler dependent, but it
> might be faster and easier � at least if you mostly use a single compiler.
>
> Tobias
the immediate target is internal write to character.  It will eventually 
be stored on disk, but part of a structure.
0
Reply garylscott (1357) 8/14/2012 1:22:41 PM

On 08/14/2012 05:05 AM, glen herrmannsfeldt wrote:
> Some C systems have a swab() function, which will byte-swap
> data while copying it.

swab only handles 2 byte quantities. If you want to do this both fast and
portably, it's probably better to look at what some portability library like
libSDL does.

> Otherwise, with the appropriate ORDER it seems to me that 
> TRANSFER would byte swap data in an array of a one-byte type.
> 
> That might take a TRANSFER to a one byte type, TRANSFER to
> do the byte swap, and TRANSFER again to the destination type.

ORDER is an argument to RESHAPE, so this would already chain two intrinsics
that are likely to make a copy of their arguments. Let's hope the OP is
not sensitive to low performance.

> Or call swab() with C interoperability.
> 
> Now, I believe that some C compilers will inline swab(), especially
> on processors that have a byte swap instruction. For a large
> enough data structure, though, the function call overhead 
> shouldn't be so big.

It's probably faster to have one's own output conversion function than
to address the general case.

Regards, Thomas
0
Reply jahns (51) 8/14/2012 4:39:05 PM

On Tuesday, August 14, 2012 11:39:05 AM UTC-5, Thomas Jahns wrote:
> On 08/14/2012 05:05 AM, glen herrmannsfeldt wrote: > Some C systems have =
a swab() function, which will byte-swap > data while copying it. swab only =
handles 2 byte quantities. If you want to do this both fast and portably, i=
t's probably better to look at what some portability library like libSDL do=
es. > Otherwise, with the appropriate ORDER it seems to me that > TRANSFER =
would byte swap data in an array of a one-byte type. > > That might take a =
TRANSFER to a one byte type, TRANSFER to > do the byte swap, and TRANSFER a=
gain to the destination type. ORDER is an argument to RESHAPE, so this woul=
d already chain two intrinsics that are likely to make a copy of their argu=
ments. Let's hope the OP is not sensitive to low performance. > Or call swa=
b() with C interoperability. > > Now, I believe that some C compilers will =
inline swab(), especially > on processors that have a byte swap instruction=
.. For a large > enough data structure, though, the function call overhead >=
 shouldn't be so big. It's probably faster to have one's own output convers=
ion function than to address the general case. Regards, Thomas

I am indeed very sensitive to performance.  That's why I spent considerable=
 time getting the UUID conversion from binary to character down from 64us p=
er to 7us per conversion (16 bytes to formatted 38 bytes).  And the convers=
ion from MS GUIDStruct to big endian 16 bytes from 650ns to 328ns.  Mostly =
i eliminated use of transfer and fell back to equivalence :(.  It just was =
taking too long for the conversion.  A major improvement also was gained by=
 a more sophisticated internal write (with implied do) and eliminating exte=
rnal looping.
0
Reply garylscott (1357) 8/14/2012 4:55:51 PM

Gary Scott <garylscott@sbcglobal.net> wrote:

> I have my own byteswap procedure for integers.  It isn't a difficult 
> thing, was just thinking that the need for such a thing in system 
> programming, and in many areas of data processing and sharing across 
> systems, that adding an option to transfer might be useful.

While I could see having some kind of intrinsic for the purpose,
TRANSFER is just the wrong place to start. The whole concept of TRANSFER
is to move bits without regard to type or kind. As I noted elsewhere,
byte swapping is closely tied to type and kind. Doesn't fit well.

-- 
Richard Maine
email: last name at domain . net
domain: summer-triangle
0
Reply nospam47 (9742) 8/15/2012 6:47:43 AM

I use something like this. Do you recommend something other?

     Vladimir


     elemental function BigEnd32(x) result(res)
       real(real32) :: res
       real(real32),intent(in)::x
       integer(selected_int_kind(1)),dimension(4):: bytes !may not work =
on  =

some processors

       if (.not.littleendian) then
         res =3D x
       else
         bytes =3D transfer(x,bytes,4)
         res =3D transfer(bytes(4:1:-1),x)
       endif
     end function BigEnd32

Dne Wed, 15 Aug 2012 08:47:43 +0200 Richard Maine <nospam@see.signature>=
  =

napsal(a):

> Gary Scott <garylscott@sbcglobal.net> wrote:
>
>> I have my own byteswap procedure for integers.  It isn't a difficult
>> thing, was just thinking that the need for such a thing in system
>> programming, and in many areas of data processing and sharing across
>> systems, that adding an option to transfer might be useful.
>
> While I could see having some kind of intrinsic for the purpose,
> TRANSFER is just the wrong place to start. The whole concept of TRANSF=
ER
> is to move bits without regard to type or kind. As I noted elsewhere,
> byte swapping is closely tied to type and kind. Doesn't fit well.
>


-- =

Tato zpr=C3=A1va byla vytvo=C5=99ena p=C5=99evratn=C3=BDm po=C5=A1tovn=C3=
=ADm klientem Opery:  =

http://www.opera.com/mail/
0
Reply utf 8/15/2012 9:07:52 AM

[Confusing (to me) top-posting reordered]

> Dne Wed, 15 Aug 2012 08:47:43 +0200 Richard Maine <nospam@see.signature>
> napsal(a):
> 
> > While I could see having some kind of intrinsic for the purpose,
> > TRANSFER is just the wrong place to start. The whole concept of TRANSFER
> > is to move bits without regard to type or kind. As I noted elsewhere,
> > byte swapping is closely tied to type and kind. Doesn't fit well.

\"Vladim�r Fuka <\"name.surname at <mffDOTcuniDOTcz"> wrote:

> I use something like this. Do you recommend something other?

[user subroutine using TRANSFER elided]

That's ok. (I didn't carefully check it - just skimmed for the idea,
which seems fine). You are using TRANSFER, but you aren't asking
TRANSFER to be aware of the byte swapping needed for the type. You are
providing that information in your own code. I see nothing obviously
wrong in your code. I might suspect that its performance would be less
than could be obtained by other coding, but the only way to know that
for sure is to test. You also might not particularly care about the
performance.

I had some apps where performance of the byte swapping was important
enough to be worth some attention, so I spent a bit of time fiddling
with it. But that was quite a while ago - about 2 decades now. Compilers
might have done a lot since then.

-- 
Richard Maine
email: last name at domain . net
domain: summer-triangle
0
Reply nospam47 (9742) 8/15/2012 3:01:57 PM

On Aug 15, 7:07=A0pm, \"Vladim=EDr Fuka <\"name.surname at
<mffDOTcuniDOTcz">> wrote:
> I use something like this. Do you recommend something other?
>
> =A0 =A0 =A0Vladimir
>
> =A0 =A0 =A0elemental function BigEnd32(x) result(res)
> =A0 =A0 =A0 =A0real(real32) :: res
> =A0 =A0 =A0 =A0real(real32),intent(in)::x
> =A0 =A0 =A0 =A0integer(selected_int_kind(1)),dimension(4):: bytes !may no=
t work on
> some processors
>
> =A0 =A0 =A0 =A0if (.not.littleendian) then
> =A0 =A0 =A0 =A0 =A0res =3D x
> =A0 =A0 =A0 =A0else
> =A0 =A0 =A0 =A0 =A0bytes =3D transfer(x,bytes,4)
> =A0 =A0 =A0 =A0 =A0res =3D transfer(bytes(4:1:-1),x)
> =A0 =A0 =A0 =A0endif
> =A0 =A0 =A0end function BigEnd32

As I suggested before, using some bit functions will do it.
something like the following will be more portable than the above
code, for integer kinds.  Capable of extension to real.

! Swap order: bytes of k are the reverse of those of i
   k =3D 0
   do j =3D 1, bit_size(k)/8
      k =3D ishft(k, 8) + iand(i, 255)
      i =3D ishft(i, -8)
   end do

0
Reply louisa.hutch (142) 8/16/2012 12:42:10 AM

"Tobias Burnus" <burnus@net-b.de> wrote in message 
news:5029EDEE.6060608@net-b.de...

> Gary Scott wrote:

>> I find a frequent need to byte swap when I transfer from little endian
>> to big endian destined output.  It would be nice if transfer
>> automatically byte swapped (by selection).  Does it already support this
>> byte swapping readily?

> If it is only about I/O, many compilers support a way to specify the 
> endianness of the I/O via environment variables, command-line arguments 
> and via a call to an intrinsic or withing an extra argument in the OPEN or 
> WRITE/READ statement.

> Contrary to the transfer suggestions, it is compiler dependent, but it 
> might be faster and easier � at least if you mostly use a single compiler.

I was looking at

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40210

And it seemed to me that either

C:\gfortran\clf\bswap>type bswap.f90
module builtins
   use ISO_C_BINDING
   implicit none
   private
   public bswap, bswap16, bswap32, bswap64, bswap128
   interface bswap
      function bswap32(x) bind(C,name='__builtin_bswap32')
         import
         implicit none
         integer(C_INT32_T) bswap32
         integer(C_INT32_T), value :: x
      end function bswap32
      function bswap64(x) bind(C,name='__builtin_bswap64')
         import
         implicit none
         integer(C_INT64_T) bswap64
         integer(C_INT64_T), value :: x
      end function bswap64
      module procedure bswap16, bswap128
   end interface bswap
   contains
      function bswap16(x)
         integer(C_INT16_T) bswap16
         integer(C_INT16_T), value :: x
         bswap16 = ishftc(x,8)
      end function bswap16
      function bswap128(x)
         integer(C_INT128_T) bswap128
         integer(C_INT128_T), value :: x
         bswap128 = ior( &
            ishft(int(bswap64(int(x,C_INT64_T)),C_INT128_T),64), &
            int(bswap64(int(ishft(x,-64),C_INT64_T)),C_INT128_T))
      end function bswap128
end module builtins

module testmod
   contains
function test16(x)
   use builtins
   use ISO_C_BINDING
   implicit none
   integer(C_INT16_T) test16
   integer(C_INT16_T), value :: x
   test16 = bswap(x)
end function test16

function test32(x)
   use builtins
   use ISO_C_BINDING
   implicit none
   integer(C_INT32_T) test32
   integer(C_INT32_T), value :: x
   test32 = bswap(x)
end function test32

function test64(x)
   use builtins
   use ISO_C_BINDING
   implicit none
   integer(C_INT64_T) test64
   integer(C_INT64_T), value :: x
   test64 = bswap(x)
end function test64

function test128(x)
   use builtins
   use ISO_C_BINDING
   implicit none
   integer(C_INT128_T) test128
   integer(C_INT128_T), value :: x
   test128 = bswap(x)
end function test128
end module testmod

program test
   use ISO_C_BINDING
   use testmod
   implicit none
   integer(C_INT16_T) :: x16 = 1
   integer(C_INT32_T) :: x32 = 1
   integer(C_INT64_T) :: x64 = 1
   integer(C_INT128_T) :: x128 = 1
   write(*,*) test16(x16)+test32(x32)+test64(x64)+test128(x128)
end program test

C:\gfortran\clf\bswap>gfortran bswap.f90 -obswap
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccAbEXSA.o:bswap.f90:(.text+0x1d): 
undefined
reference to `__builtin_bswap64'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccAbEXSA.o:bswap.f90:(.text+0x44): 
undefined
reference to `__builtin_bswap64'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccAbEXSA.o:bswap.f90:(.text+0x105): 
undefined
 reference to `__builtin_bswap64'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccAbEXSA.o:bswap.f90:(.text+0x126): 
undefined
 reference to `__builtin_bswap32'
c:/gcc_equation/bin/../lib/gcc/x86_64-w64-mingw32/4.8.0/../../../../x86_64-w64-m
ingw32/bin/ld.exe: C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccAbEXSA.o: bad reloc 
addr
ess 0x0 in section `.pdata'
c:/gcc_equation/bin/../lib/gcc/x86_64-w64-mingw32/4.8.0/../../../../x86_64-w64-m
ingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status

or

C:\gfortran\clf\bswap>type bswap2.f90
module test
   use ISO_C_BINDING
   implicit none
   contains
      function bswap32(x) bind(C,name='bswap32')
         integer(C_INT32_T) bswap32
         integer(C_INT32_T), value :: x
         bswap32 = ior(ior(ior( &
            ishft(iand(x,int(Z'000000FF',C_INT32_T)),24), &
            ishft(iand(x,int(Z'0000FF00',C_INT32_T)),8)), &
            ishft(iand(x,int(Z'00FF0000',C_INT32_T)),-8)), &
            ishft(iand(x,int(Z'FF000000',C_INT32_T)),-24))
      end function bswap32
      function bswap64(x) bind(C,name='bswap64')
         integer(C_INT64_T) bswap64
         integer(C_INT64_T), value :: x
         bswap64 = ior(ior(ior(ior(ior(ior(ior( &
            ishft(iand(x,int(Z'00000000000000FF',C_INT64_T)),56), &
            ishft(iand(x,int(Z'000000000000FF00',C_INT64_T)),40)), &
            ishft(iand(x,int(Z'0000000000FF0000',C_INT64_T)),24)), &
            ishft(iand(x,int(Z'00000000FF000000',C_INT64_T)),8)), &
            ishft(iand(x,int(Z'000000FF00000000',C_INT64_T)),-8)), &
            ishft(iand(x,int(Z'0000FF0000000000',C_INT64_T)),-24)), &
            ishft(iand(x,int(Z'00FF000000000000',C_INT64_T)),-40)), &
            ishft(iand(x,int(Z'FF00000000000000',C_INT64_T)),-56))
      end function bswap64
end module test

program main
   use test
   implicit none
   integer(C_INT32_T) :: x32 = 1
   integer(C_INT64_T) :: x64 = 1

   write(*,*) bswap32(x32)+bswap64(x64)
end program main

C:\gfortran\clf\bswap>gfortran -fno-range-check -O3 -mtune=native -march=native
-fomit-frame-pointer bswap2.f90 -S

C:\gfortran\clf\bswap>type bswap2.s
        .file   "bswap2.f90"
        .text
        .p2align 4,,15
        .globl  bswap64
        .def    bswap64;        .scl    2;      .type   32;     .endef
        .seh_proc       bswap64
bswap64:
        .seh_endprologue
        movq    %rcx, %rax
        movq    %rcx, %rdx
        andl    $65280, %eax
        salq    $56, %rdx
        salq    $40, %rax
        orq     %rdx, %rax
        movq    %rcx, %rdx
        andl    $16711680, %edx
        salq    $24, %rdx
        orq     %rdx, %rax
        movq    %rcx, %rdx
        andl    $4278190080, %edx
        salq    $8, %rdx
        orq     %rdx, %rax
        movq    %rcx, %rdx
        shrq    $8, %rdx
        andl    $4278190080, %edx
        orq     %rdx, %rax
        movq    %rcx, %rdx
        shrq    $24, %rdx
        andl    $16711680, %edx
        orq     %rdx, %rax
        movq    %rcx, %rdx
        shrq    $56, %rcx
        shrq    $40, %rdx
        andl    $65280, %edx
        orq     %rdx, %rax
        orq     %rcx, %rax
        ret
        .seh_endproc
        .section .rdata,"dr"
..LC0:
        .ascii "bswap2.f90\0"
        .text
        .p2align 4,,15
        .def    MAIN__; .scl    3;      .type   32;     .endef
        .seh_proc       MAIN__
MAIN__:
        subq    $536, %rsp
        .seh_stackalloc 536
        .seh_endprologue
        leaq    .LC0(%rip), %rax
        leaq    48(%rsp), %rcx
        movq    %rax, 56(%rsp)
        movl    $35, 64(%rsp)
        movl    $128, 48(%rsp)
        movl    $6, 52(%rsp)
        call    _gfortran_st_write
        movl    $1, %ecx
        call    bswap64
        leaq    40(%rsp), %rdx
        movl    $8, %r8d
        leaq    48(%rsp), %rcx
        addq    $16777216, %rax
        movq    %rax, 40(%rsp)
        call    _gfortran_transfer_integer_write
        leaq    48(%rsp), %rcx
        call    _gfortran_st_write_done
        nop
        addq    $536, %rsp
        ret
        .seh_endproc
        .p2align 4,,15
        .globl  bswap32
        .def    bswap32;        .scl    2;      .type   32;     .endef
        .seh_proc       bswap32
bswap32:
        .seh_endprologue
        movl    %ecx, %eax
        movl    %ecx, %edx
        andl    $65280, %eax
        sall    $24, %edx
        sall    $8, %eax
        orl     %edx, %eax
        movl    %ecx, %edx
        shrl    $24, %ecx
        andl    $16711680, %edx
        shrl    $8, %edx
        orl     %edx, %eax
        orl     %ecx, %eax
        ret
        .seh_endproc
        .def    __main; .scl    2;      .type   32;     .endef
        .section        .text.startup,"x"
        .p2align 4,,15
        .globl  main
        .def    main;   .scl    2;      .type   32;     .endef
        .seh_proc       main
main:
        pushq   %rsi
        .seh_pushreg    %rsi
        pushq   %rbx
        .seh_pushreg    %rbx
        subq    $40, %rsp
        .seh_stackalloc 40
        .seh_endprologue
        movl    %ecx, %ebx
        movq    %rdx, %rsi
        call    __main
        movq    %rsi, %rdx
        movl    %ebx, %ecx
        call    _gfortran_set_args
        leaq    options.1.1878(%rip), %rdx
        movl    $7, %ecx
        call    _gfortran_set_options
        call    MAIN__
        xorl    %eax, %eax
        addq    $40, %rsp
        popq    %rbx
        popq    %rsi
        ret
        .seh_endproc
        .section .rdata,"dr"
        .align 16
options.1.1878:
        .long   68
        .long   1023
        .long   0
        .long   0
        .long   1
        .long   1
        .long   0
        .def    _gfortran_st_write;     .scl    2;      .type   32; 
..endef
        .def    _gfortran_transfer_integer_write;       .scl    2; 
..type
32;     .endef
        .def    _gfortran_st_write_done;        .scl    2;      .type   32;
..endef
        .def    _gfortran_set_args;     .scl    2;      .type   32; 
..endef
        .def    _gfortran_set_options;  .scl    2;      .type   32; 
..endef

should work, but neither did, the first because gfortran couldn't
figure out __builtin_bswap* and the second because gfortran wasn't
as alert as gcc at determining when to use a bswap instruction.

Can you get either or both of these examples to work in gfortran?

-- 
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


0
Reply not_valid (1681) 8/16/2012 7:58:41 PM

On Thu, 16 Aug 2012 13:58:41 -0600, James Van Buskirk wrote:

> "Tobias Burnus" <burnus@net-b.de> wrote in message 
> news:5029EDEE.6060608@net-b.de...
> 
>> Gary Scott wrote:
> 
>>> I find a frequent need to byte swap when I transfer from little endian
>>> to big endian destined output.  It would be nice if transfer
>>> automatically byte swapped (by selection).  Does it already support this
>>> byte swapping readily?
> 
>> If it is only about I/O, many compilers support a way to specify the 
>> endianness of the I/O via environment variables, command-line arguments 
>> and via a call to an intrinsic or withing an extra argument in the OPEN or 
>> WRITE/READ statement.
> 
>> Contrary to the transfer suggestions, it is compiler dependent, but it 
>> might be faster and easier – at least if you mostly use a single compiler.
> 
> I was looking at
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40210
> 
> And it seemed to me that either
> 
> C:\gfortran\clf\bswap>type bswap.f90
> module builtins
>    use ISO_C_BINDING
>    implicit none
>    private
>    public bswap, bswap16, bswap32, bswap64, bswap128
>    interface bswap
>       function bswap32(x) bind(C,name='__builtin_bswap32')

It is not at all clear to me why you think __builtin_bswap32 can be 
used here.  This is a reserved identifier within the C implementation.
(See 7.1.3 in n1256.pdf).  It does not need to actually exist outside
of the C implementation. (See note 163, p 167 in n1256.pdf, which 
clearly states that a C implementation can generate in-line code
for such an identifier).

-- 
steve


0
Reply sgk (132) 8/16/2012 11:48:38 PM

"Steven G. Kargl" <sgk@REMOVEtroutmask.apl.washington.edu> wrote in message 
news:k0k0sm$stq$1@dont-email.me...

> On Thu, 16 Aug 2012 13:58:41 -0600, James Van Buskirk wrote:

>> I was looking at

>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40210

>> And it seemed to me that either

>> C:\gfortran\clf\bswap>type bswap.f90
>> module builtins
>>    use ISO_C_BINDING
>>    implicit none
>>    private
>>    public bswap, bswap16, bswap32, bswap64, bswap128
>>    interface bswap
>>       function bswap32(x) bind(C,name='__builtin_bswap32')

> It is not at all clear to me why you think __builtin_bswap32 can be
> used here.  This is a reserved identifier within the C implementation.
> (See 7.1.3 in n1256.pdf).  It does not need to actually exist outside
> of the C implementation. (See note 163, p 167 in n1256.pdf, which
> clearly states that a C implementation can generate in-line code
> for such an identifier).

Not infrequently equivalent gfortran and gcc code seem to produce
identical machine-language output.  I assumed that the C side of
things saw that function call and converted it into inline code
at some point.  If the conversion happened late enough in the
code generation process I figured it had a good chance to work
for gfortran since it shares the same back-end.  I have definitely
used some of these builtins in gfortran before to fill in for
intrinsics which were missing at the time, but these were
complicated enough functions that they weren't inlined by gcc.

Of course you can always use gfortran to force bswap, but the
result isn't inlined like the compiler could potentially do it
and the technique is OS-dependent:

C:\gfortran\clf\bswap>type bswap3.f90
module bswap_stuff
   use ISO_C_BINDING
   implicit none
   private
   public bswap_init, bswap32, bswap64
   integer(C_INT8_T) BAD_STUFF(40)
   data BAD_STUFF / &
      Z'89', Z'c8', Z'0f', Z'c8', Z'c3', Z'90', Z'90', Z'90', &
      Z'48', Z'89', Z'c8', Z'48', Z'0f', Z'c8', Z'c3', Z'90', &
      Z'8b', Z'44', Z'24', Z'04', Z'0f', Z'c8', Z'c3', Z'90', &
      Z'8b', Z'44', Z'24', Z'08', Z'0f', Z'c8', Z'8b', Z'54', &
      Z'24', Z'04', Z'0f', Z'ca', Z'c3', Z'90', Z'90', Z'90' /
   abstract interface
      function bswap32_template(x) bind(C)
         import
         implicit none
         integer(C_INT32_T) bswap32_template
         integer(C_INT32_T), value :: x
      end function bswap32_template
      function bswap64_template(x) bind(C)
         import
         implicit none
         integer(C_INT64_T) bswap64_template
         integer(C_INT64_T), value :: x
      end function bswap64_template
   end interface
   procedure(bswap32_template), pointer :: bswap32 => NULL()
   procedure(bswap64_template), pointer :: bswap64 => NULL()
   interface
      function VirtualAlloc(lpAddress, dwSize, flAllocationType, &
            flProtect) bind(C, name = 'VirtualAlloc')
         import
         implicit none
!GCC$ ATTRIBUTES STDCALL :: VirtualAlloc
         type(C_PTR) VirtualAlloc
         type(C_PTR), value :: lpAddress
         integer(C_SIZE_T), value :: dwSize
         integer(C_LONG), value :: flAllocationType
         integer(C_LONG), value :: flProtect
      end function VirtualAlloc
      function GetLastError() bind(C,name='GetLastError')
         use ISO_C_BINDING
         implicit none
!GCC$ ATTRIBUTES STDCALL :: GetLastError
         integer(C_LONG) GetLastError
      end function GetLastError
   end interface
   contains
      subroutine bswap_init
         type(C_PTR) address
         integer(C_INTPTR_T) temp
         integer(C_LONG) error
         integer(C_INT8_T), pointer :: temp_ptr(:)
         type(C_FUNPTR) fun_address
         logical :: first = .TRUE.

         if(.NOT.first) return
         first = .FALSE.
         address = VirtualAlloc(C_NULL_PTR, &
            size(BAD_STUFF,kind=C_SIZE_T),int(Z'1000',C_LONG), &
            int(Z'40',C_LONG))
         if(.NOT.C_ASSOCIATED(address)) then
            error = GetLastError()
            write(*,'(a,z0,a)') "Error Z'",error,"' allocating memory"
            stop
         end if
         call C_F_POINTER(address, temp_ptr, shape(BAD_STUFF))
         temp_ptr = BAD_STUFF
         temp = transfer(address, temp)
         if(C_INT32_T == C_INTPTR_T) then
            temp = temp+16
         end if
         fun_address = transfer(temp, fun_address)
         call C_F_PROCPOINTER(fun_address, bswap32)
         temp = temp+8
         fun_address = transfer(temp, fun_address)
         call C_F_PROCPOINTER(fun_address, bswap64)
      end subroutine bswap_init
end module bswap_stuff

program bswap_test
   use bswap_stuff
   use ISO_C_BINDING
   implicit none
   integer(C_INT32_T) :: x32 = int(Z'12345678', C_INT32_T)
   integer(C_INT64_T) :: x64 = int(Z'1234567890abcdef', C_INT64_T)

   call bswap_init
   write(*,'(a,i0,a)') 'This is a ',bit_size(0_C_INTPTR_T),'-bit system.'
   write(*,'(z8.8,1x,z8.8)') x32, bswap32(x32)
   write(*,'(z16.16,1x,z16.16)') x64, bswap64(x64)
end program bswap_test

C:\gfortran\clf\bswap>gfortran -fno-range-check bswap3.f90 -obswap3

C:\gfortran\clf\bswap>bswap3
This is a 64-bit system.
12345678 78563412
1234567890ABCDEF EFCDAB9078563412

C:\gfortran\clf\bswap>gfortran -fno-range-check bswap3.f90 -obswap3

C:\gfortran\clf\bswap>bswap3
This is a 32-bit system.
12345678 78563412
1234567890ABCDEF EFCDAB9078563412

-- 
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


0
Reply not_valid (1681) 8/17/2012 12:48:10 AM

On Thu, 16 Aug 2012 18:48:10 -0600, James Van Buskirk wrote:

> "Steven G. Kargl" <sgk@REMOVEtroutmask.apl.washington.edu> wrote in message 
> news:k0k0sm$stq$1@dont-email.me...
> 
>> On Thu, 16 Aug 2012 13:58:41 -0600, James Van Buskirk wrote:
> 
>>> I was looking at
> 
>>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40210
> 
>>> And it seemed to me that either
> 
>>> C:\gfortran\clf\bswap>type bswap.f90
>>> module builtins
>>>    use ISO_C_BINDING
>>>    implicit none
>>>    private
>>>    public bswap, bswap16, bswap32, bswap64, bswap128
>>>    interface bswap
>>>       function bswap32(x) bind(C,name='__builtin_bswap32')
> 
>> It is not at all clear to me why you think __builtin_bswap32 can be
>> used here.  This is a reserved identifier within the C implementation.
>> (See 7.1.3 in n1256.pdf).  It does not need to actually exist outside
>> of the C implementation. (See note 163, p 167 in n1256.pdf, which
>> clearly states that a C implementation can generate in-line code
>> for such an identifier).
> 
> Not infrequently equivalent gfortran and gcc code seem to produce
> identical machine-language output.  I assumed that the C side of
> things saw that function call and converted it into inline code
> at some point.  If the conversion happened late enough in the
> code generation process I figured it had a good chance to work
> for gfortran since it shares the same back-end.  I have definitely
> used some of these builtins in gfortran before to fill in for
> intrinsics which were missing at the time, but these were
> complicated enough functions that they weren't inlined by gcc.

I believe (and I could be wrong) that gfortran explicitly needs
to include __builtin_bswap32 into its internal list of available
intrinsics.  Otherwise, it will be marked as an external procedure.

-- 
steve 
0
Reply sgk (132) 8/17/2012 2:51:06 AM

On Aug 14, 12:03=A0pm, Gary Scott <garylsc...@sbcglobal.net> wrote:
> I find a frequent need to byte swap when I transfer from little endian
> to big endian destined output. =A0It would be nice if transfer
> automatically byte swapped (by selection). =A0Does it already support thi=
s
> byte swapping readily?

PL/I provides data types that describe big-endian and little-endian
data.

The attributes NONNATIVE and NATIVE are used in declarations
of variables to indicate one or the other (big- or little-endian).
0
Reply robin.vowels (428) 8/17/2012 2:51:49 AM

On Fri, 17 Aug 2012 02:51:06 +0000, Steven G. Kargl wrote:

> On Thu, 16 Aug 2012 18:48:10 -0600, James Van Buskirk wrote:
> 
>> "Steven G. Kargl" <sgk@REMOVEtroutmask.apl.washington.edu> wrote in message 
>> news:k0k0sm$stq$1@dont-email.me...
>> 
>>> On Thu, 16 Aug 2012 13:58:41 -0600, James Van Buskirk wrote:
>> 
>>>> I was looking at
>> 
>>>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40210
>> 
>>>> And it seemed to me that either
>> 
>>>> C:\gfortran\clf\bswap>type bswap.f90
>>>> module builtins
>>>>    use ISO_C_BINDING
>>>>    implicit none
>>>>    private
>>>>    public bswap, bswap16, bswap32, bswap64, bswap128
>>>>    interface bswap
>>>>       function bswap32(x) bind(C,name='__builtin_bswap32')
>> 
>>> It is not at all clear to me why you think __builtin_bswap32 can be
>>> used here.  This is a reserved identifier within the C implementation.
>>> (See 7.1.3 in n1256.pdf).  It does not need to actually exist outside
>>> of the C implementation. (See note 163, p 167 in n1256.pdf, which
>>> clearly states that a C implementation can generate in-line code
>>> for such an identifier).
>> 
>> Not infrequently equivalent gfortran and gcc code seem to produce
>> identical machine-language output.  I assumed that the C side of
>> things saw that function call and converted it into inline code
>> at some point.  If the conversion happened late enough in the
>> code generation process I figured it had a good chance to work
>> for gfortran since it shares the same back-end.  I have definitely
>> used some of these builtins in gfortran before to fill in for
>> intrinsics which were missing at the time, but these were
>> complicated enough functions that they weren't inlined by gcc.
> 
> I believe (and I could be wrong) that gfortran explicitly needs
> to include __builtin_bswap32 into its internal list of available
> intrinsics.  Otherwise, it will be marked as an external procedure.

Looking in the *.mod files provides support for what I suspected

4 'bswap32' 'builtins' '__builtin_bswap32' 1 ((PROCEDURE UNKNOWN-INTENT
MODULE-PROC BODY UNKNOWN 0 0 EXTERNAL FUNCTION IS_BIND_C IS_C_INTEROP) (
INTEGER 4 0 1 0 INTEGER ()) 8 0 (9) () 4 () () () 0 0)

3 'bswap64' 'builtins' '__builtin_bswap64' 1 ((PROCEDURE UNKNOWN-INTENT
MODULE-PROC BODY UNKNOWN 0 0 EXTERNAL FUNCTION IS_BIND_C IS_C_INTEROP) (
INTEGER 8 0 1 0 INTEGER ()) 10 0 (11) () 3 () () () 0 0)

Notice the 'EXTERNAL FUNCTION' tag, I suspect that this inhibits
the middle/back-end from using the in-line code.

-- 
steve

0
Reply sgk (132) 8/17/2012 4:36:01 AM

20 Replies
113 Views

(page loaded in 0.353 seconds)


Reply: