This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, fortran] PR 40539 Document internal representation of LOGICAL variables
- From: Janne Blomqvist <blomqvist dot janne at gmail dot com>
- To: Tobias Burnus <burnus at net-b dot de>
- Cc: Fortran List <fortran at gcc dot gnu dot org>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 7 Apr 2010 15:43:11 +0300
- Subject: Re: [Patch, fortran] PR 40539 Document internal representation of LOGICAL variables
- References: <t2p7b446c2e1004061424l4ff15edv4a92e02de7c229b9@mail.gmail.com> <4BBC41BA.7070401@net-b.de>
On Wed, Apr 7, 2010 at 11:26, Tobias Burnus <burnus@net-b.de> wrote:
> On 04/06/2010 11:24 PM, Janne Blomqvist wrote:
>> the attached documentation patch explains how gfortran represents
>> LOGICAL variables. Ok for trunk/4.5/4.4?
>>
>> +In general, knowledge of the internal representation of @code{LOGICAL}
>> +variables is not necessary, even for mixed language programming since
>> +the introduction of the @code{ISO_C_BINDING} feature in Fortran 2003.
>> +For those cases where knowledge of the internal representation is
>> +after all required, the GNU Fortran internal representation is as
>> +follows.
>>
>
> I would delete this paragraph - it does not contain much information
Fair enough, I agree it's not particularly informative in the end.
> and
> as experience shows (PR40539) using ISO_C_BINDING also does not
> magically solve all problems.
Well, as ISO_C_BINDING was not used in the PR, it's a bit unreasonable
to expect it to help that case.
> The standard also only talks about
> "companion C processor", which is GCC's C compiler, but the issue (cf.
> PR) was about implementation differences between two different (Fortran)
> "processors" - ifort and gfortran.
My implied point was that ISO_C_BINDING does in practice not only
provide a standardized binding to the "companion C processor", but
also a standardized binding to the target ABI, as most platforms(?)
have an ABI that the C compilers on said platform follow. Hence, if
one were to write a library using Fortran compiler X, expose the
interface in terms of the ISO_C_BINDING, that interface could, in
practice, be used not only by the Fortran compiler X itself, and the
"companion C processor", but also by Fortran compiler Y, and C
compiler Z.
But anyway, that is perhaps the kind of philosophical point that does
not belong in the compiler manual as it's not guaranteed to work since
the "companion C compiler" does in principle not need to follow the
platform ABI.
>> +A @code{LOGICAL(KIND=N)} variable is represented as an
>> +@code{INTEGER(KIND=N)} variable, however with only two permissible
>> +values: @code{1} for @code{.TRUE.} and @code{0} for
>> +@code{.FALSE.}. Any other integer value results in undefined behavior.
>
> Add a comma after the "however".
Ah, yes.
> (For the mailing list readers: The problem is that ifort as optimization
> checks the sign bit (thus: 0 and -1 for .false./.true.)
Not quite. Ifort checks the least significant bit (LSB). I.e. even
values are considered .false. and odd ones .true. . Although it should
be noted ifort has the -fpscomp logicals option that makes it behave
like C (0 is .false., anything else .true.).
> while
> GCC/gfortran uses the first bit on the other side (i.e. 0 and 1), which
> leads to problems.
Not quite correct, either. Really, the integer values 0 and 1 are the
only allowable values, anything else leads to undefined behavior.
> As in C one usually uses integer expressions in
> conditions, either choice is compatible with C [at least when not
> explicitly using _Bool]. And somehow, ifort seems also to accept 1 as
> .true. while gfortran regards -1 as .false. Thus, passing ifort's
> .false. (and also .false._c_bool) to gfortran leads to wrong code. -
>From my above description, as it happens, thus the integer values 0
and 1 are .false. and .true. both for gfortran and ifort. The problem
is when the integer value is anything else. Consider for example the
Fortran .NOT. operator (Or ! in C), on x86 this is compiled using the
following ASM instructions
Ifort: notl (bitwise NOT)
gfortran: xorl (bitwise XOR with 1)
gcc w/int: testl + sete (bitwise AND + set byte to one based on flag register)
gcc w/_Bool: xorl (bitwise XOR with 1, just like gfortran)
OTOH, for a simple branch based on a logical variable, e.g.
if (logical_var) then
do_something
end if
we have:
Ifort: testb 1, %al + jX (I.e. test for the LSB, jump on condition)
gfortran: testl var, var + jX (test for integer value 0, jump on condition)
gcc w/int: testl var, var + jX (same as gfortran)
gcc w/_Bool: testb var, var + jX (same as gfortran/gcc, except
sizeof(_Bool) = 1)
Now, from the above it should be easy to see that if one where to
somehow put an integer value that is neither 0 or 1 into a logical
value, gfortran would produce nonsense results. E.g. "logical_var" and
".NOT. logical_var" would both evaluate to .TRUE. when doing a
conditional branch. Thus, only 0 and 1 are valid values.
> OK with the modifications. Note: GCC 4.5 is currently frozen - please
> wait until unfrozen.
Thanks for the review (and to Jerry too). Richard G. said on irc that
documentation changes were ok at the moment, so I plan to commit to
4.5 as well later today.
--
Janne Blomqvist