This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch, fortran] PR 40539 Document internal representation of LOGICAL variables


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]