Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
8a19a44a
Commit
8a19a44a
authored
Apr 17, 1999
by
Craig Burley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
forgot to add ffe.texi, the actual g77 front-end internals docs
From-SVN: r26518
parent
0f4668ef
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
883 additions
and
0 deletions
+883
-0
gcc/f/ffe.texi
+883
-0
No files found.
gcc/f/ffe.texi
0 → 100644
View file @
8a19a44a
@node
Front
End
@chapter
Front
End
@cindex
GNU
Fortran
Front
End
(
FFE
)
@cindex
FFE
@cindex
@code
{
g77
},
front
end
@cindex
front
end
,
@code
{
g77
}
This
chapter
describes
some
aspects
of
the
design
and
implementation
of
the
@code
{
g77
}
front
end
.
@menu
*
Philosophy
of
Code
Generation
::
*
Two
-
pass
Design
::
*
Challenges
Posed
::
*
Transforming
Statements
::
*
Transforming
Expressions
::
@end
menu
@node
Philosophy
of
Code
Generation
@section
Philosophy
of
Code
Generation
Don
'
t
poke
the
bear
.
The
@code
{
g77
}
front
end
generates
code
via
the
@code
{
gcc
}
back
end
.
@cindex
GNU
Back
End
(
GBE
)
@cindex
GBE
@cindex
@code
{
gcc
},
back
end
@cindex
back
end
,
gcc
@cindex
code
generator
The
@code
{
gcc
}
back
end
(
GBE
)
is
a
large
,
complex
labyrinth
of
intricate
code
written
in
a
combination
of
the
C
language
and
specialized
languages
internal
to
@code
{
gcc
}.
While
the
@emph
{
code
}
that
implements
the
GBE
is
written
in
a
combination
of
languages
,
the
GBE
itself
is
,
to
the
front
end
for
a
language
like
Fortran
,
best
viewed
as
a
@emph
{
compiler
}
that
compiles
its
own
,
unique
,
language
.
The
GBE
'
s
``
source
''
,
then
,
is
written
in
this
language
,
which
consists
primarily
of
a
combination
of
calls
to
GBE
functions
and
@dfn
{
tree
}
nodes
(
which
are
,
themselves
,
created
by
calling
GBE
functions
).
So
,
the
@code
{
g77
}
generates
code
by
,
in
effect
,
translating
the
Fortran
code
it
reads
into
a
form
``
written
''
in
the
``
language
''
of
the
@code
{
gcc
}
back
end
.
@cindex
GBEL
@cindex
GNU
Back
End
Language
(
GBEL
)
This
language
will
heretofore
be
referred
to
as
@dfn
{
GBEL
},
for
GNU
Back
End
Language
.
GBEL
is
an
evolving
language
,
not
fully
specified
in
any
published
form
as
of
this
writing
.
It
offers
many
facilities
,
but
its
``
core
''
facilities
are
those
that
corresponding
most
directly
to
those
needed
to
support
@code
{
gcc
}
(
compiling
code
written
in
GNU
C
).
The
@code
{
g77
}
Fortran
Front
End
(
FFE
)
is
designed
and
implemented
to
navigate
the
currents
and
eddies
of
ongoing
GBEL
and
@code
{
gcc
}
development
while
also
delivering
on
the
potential
of
an
integrated
FFE
(
as
compared
to
using
a
converter
like
@code
{
f2c
}
and
feeding
the
output
into
@code
{
gcc
}).
Goals
of
the
FFE
'
s
code
-
generation
strategy
include
:
@itemize
@bullet
@item
High
likelihood
of
generation
of
correct
code
,
or
,
failing
that
,
producing
a
fatal
diagnostic
or
crashing
.
@item
Generation
of
highly
optimized
code
,
as
directed
by
the
user
via
GBE
-
specific
(
versus
@code
{
g77
}
-
specific
)
constructs
,
such
as
command
-
line
options
.
@item
Fast
overall
(
FFE
plus
GBE
)
compilation
.
@item
Preservation
of
source
-
level
debugging
information
.
@end
itemize
The
strategies
historically
,
and
currently
,
used
by
the
FFE
to
achieve
these
goals
include
:
@itemize
@bullet
@item
Use
of
GBEL
constructs
that
most
faithfully
encapsulate
the
semantics
of
Fortran
.
@item
Avoidance
of
GBEL
constructs
that
are
so
rarely
used
,
or
limited
to
use
in
specialized
situations
not
related
to
Fortran
,
that
their
reliability
and
performance
has
not
yet
been
established
as
sufficient
for
use
by
the
FFE
.
@item
Flexible
design
,
to
readily
accommodate
changes
to
specific
code
-
generation
strategies
,
perhaps
governed
by
command
-
line
options
.
@end
itemize
@cindex
Bear
-
poking
@cindex
Poking
the
bear
``
Don
'
t
poke
the
bear
''
somewhat
summarizes
the
above
strategies
.
The
GBE
is
the
bear
.
The
FFE
is
designed
and
implemented
to
avoid
poking
it
in
ways
that
are
likely
to
just
annoy
it
.
The
FFE
usually
either
tackles
it
head
-
on
,
or
avoids
treating
it
in
ways
dissimilar
to
how
the
@code
{
gcc
}
front
end
treats
it
.
For
example
,
the
FFE
uses
the
native
array
facility
in
the
back
end
instead
of
the
lower
-
level
pointer
-
arithmetic
facility
used
by
@code
{
gcc
}
when
compiling
@code
{
f2c
}
output
).
Theoretically
,
this
presents
more
opportunities
for
optimization
,
faster
compile
times
,
and
the
production
of
more
faithful
debugging
information
.
These
benefits
were
not
,
however
,
immediately
realized
,
mainly
because
@code
{
gcc
}
itself
makes
little
or
no
use
of
the
native
array
facility
.
Complex
arithmetic
is
a
case
study
of
the
evolution
of
this
strategy
.
When
originally
implemented
,
the
GBEL
had
just
evolved
its
own
native
complex
-
arithmetic
facility
,
so
the
FFE
took
advantage
of
that
.
When
porting
@code{
g77
}
to
64
-
bit
systems
,
it
was
discovered
that
the
GBE
didn
'
t
really
implement
its
native
complex
-
arithmetic
facility
properly
.
The
short
-
term
solution
was
to
rewrite
the
FFE
to
instead
use
the
lower
-
level
facilities
that
'
d
be
used
by
@code{
gcc
}
-
compiled
code
(
assuming
that
code
,
itself
,
didn
'
t
use
the
native
complex
type
provided
,
as
an
extension
,
by
@code{
gcc
}
),
since
these
were
known
to
work
,
and
,
in
any
case
,
if
shown
to
not
work
,
would
likely
be
rapidly
fixed
(
since
they
'
d
likely
not
work
for
vanilla
C
code
in
similar
circumstances
).
However
,
the
rewrite
accommodated
the
original
,
native
approach
as
well
by
offering
a
command
-
line
option
to
select
it
over
the
emulated
approach
.
This
allowed
users
,
and
especially
GBE
maintainers
,
to
try
out
fixes
to
complex
-
arithmetic
support
in
the
GBE
while
@code{
g77
}
continued
to
default
to
compiling
more
code
correctly
,
albeit
producing
(
typically
)
slower
executables
.
As
of
April
1999
,
it
appeared
that
the
last
few
bugs
in
the
GBE
'
s
support
of
its
native
complex
-
arithmetic
facility
were
worked
out
.
The
FFE
was
changed
back
to
default
to
using
that
native
facility
,
leaving
emulation
as
an
option
.
Other
Fortran
constructs
---
arrays
,
character
strings
,
complex
division
,
@code{
COMMON
}
and
@code{
EQUIVALENCE
}
aggregates
,
and
so
on
---
involve
issues
similar
to
those
pertaining
to
complex
arithmetic
.
So
,
it
is
possible
that
the
history
of
how
the
FFE
handled
complex
arithmetic
will
be
repeated
,
probably
in
modified
form
(
and
hopefully
over
shorter
timeframes
),
for
some
of
these
other
facilities
.
@node
Two
-
pass
Design
@section
Two
-
pass
Design
The
FFE
does
not
tell
the
GBE
anything
about
a
program
unit
until
after
the
last
statement
in
that
unit
has
been
parsed
.
(
A
program
unit
is
a
Fortran
concept
that
corresponds
,
in
the
C
world
,
mostly
closely
to
functions
definitions
in
ISO
C
.
That
is
,
a
program
unit
in
Fortran
is
like
a
top
-
level
function
in
C
.
Nested
functions
,
found
among
the
extensions
offered
by
GNU
C
,
correspond
roughly
to
Fortran
'
s
statement
functions
.)
So
,
while
parsing
the
code
in
a
program
unit
,
the
FFE
saves
up
all
the
information
on
statements
,
expressions
,
names
,
and
so
on
,
until
it
has
seen
the
last
statement
.
At
that
point
,
the
FFE
revisits
the
saved
information
(
in
what
amounts
to
a
second
@dfn{
pass
}
over
the
program
unit
)
to
perform
the
actual
translation
of
the
program
unit
into
GBEL
,
ultimating
in
the
generation
of
assembly
code
for
it
.
Some
lookahead
is
performed
during
this
second
pass
,
so
the
FFE
could
be
viewed
as
a
``
two
-
plus
-
pass
''
design
.
@menu
*
Two
-
pass
Code
::
*
Why
Two
Passes
::
@end
menu
@node
Two
-
pass
Code
@subsection
Two
-
pass
Code
Most
of
the
code
that
turns
the
first
pass
(
parsing
)
into
a
second
pass
for
code
generation
is
in
@file
{
@value
{
path
-
g77
}
/
std
.
c
}.
It
has
external
functions
,
called
mainly
by
siblings
in
@file
{
@value
{
path
-
g77
}
/
stc
.
c
},
that
record
the
information
on
statements
and
expressions
in
the
order
they
are
seen
in
the
source
code
.
These
functions
save
that
information
.
It
also
has
an
external
function
that
revisits
that
information
,
calling
the
siblings
in
@file
{
@value
{
path
-
g77
}
/
ste
.
c
},
which
handles
the
actual
code
generation
(
by
generating
GBEL
code
,
that
is
,
by
calling
GBE
routines
to
represent
and
specify
expressions
,
statements
,
and
so
on
).
@node
Why
Two
Passes
@subsection
Why
Two
Passes
The
need
for
two
passes
was
not
immediately
evident
during
the
design
and
implementation
of
the
code
in
the
FFE
that
was
to
produce
GBEL
.
Only
after
a
few
kludges
,
to
handle
things
like
incorrectly
-
guessed
@code
{
ASSIGN
}
label
nature
,
had
been
implemented
,
did
enough
evidence
pile
up
to
make
it
clear
that
@file
{
std
.
c
}
had
to
be
introduced
to
intercept
,
save
,
then
revisit
as
part
of
a
second
pass
,
the
digested
contents
of
a
program
unit
.
Other
such
missteps
have
occurred
during
the
evolution
of
the
FFE
,
because
of
the
different
goals
of
the
FFE
and
the
GBE
.
Because
the
GBE
'
s
original
,
and
still
primary
,
goal
was
to
directly
support
the
GNU
C
language
,
the
GBEL
,
and
the
GBE
itself
,
requires
more
complexity
on
the
part
of
most
front
ends
than
it
requires
of
@code
{
gcc
}
'
s
.
For
example
,
the
GBEL
offers
an
interface
that
permits
the
@code
{
gcc
}
front
end
to
implement
most
,
or
all
,
of
the
language
features
it
supports
,
without
the
front
end
having
to
make
use
of
non
-
user
-
defined
variables
.
(
It
'
s
almost
certainly
the
case
that
all
of
K
&
R
C
,
and
probably
ANSI
C
as
well
,
is
handled
by
the
@code{
gcc
}
front
end
without
declaring
such
variables
.)
The
FFE
,
on
the
other
hand
,
must
resort
to
a
variety
of
``
tricks
''
to
achieve
its
goals
.
Consider
the
following
C
code
:
@smallexample
int
foo
(
int
a
,
int
b
)
@{
int
c
=
0
;
if
((
c
=
bar
(
c
))
==
0
)
goto
done
;
quux
(
c
<<
1
)
;
done:
return
c
;
@
}
@end
smallexample
Note
what
kinds
of
objects
are
declared
,
or
defined
,
before
their
use
,
and
before
any
actual
code
generation
involving
them
would
normally
take
place
:
@itemize
@bullet
@item
Return
type
of
function
@item
Entry
point
(
s
)
of
function
@item
Dummy
arguments
@item
Variables
@item
Initial
values
for
variables
@end
itemize
Whereas
,
the
following
items
can
,
and
do
,
suddenly
appear
``
out
of
the
blue
''
in
C
:
@itemize
@bullet
@item
Label
references
@item
Function
references
@end
itemize
Not
surprisingly
,
the
GBE
faithfully
permits
the
latter
set
of
items
to
be
``
discovered
''
partway
through
GBEL
``
programs
''
,
just
as
they
are
permitted
to
in
C
.
Yet
,
the
GBE
has
tended
,
at
least
in
the
past
,
to
be
reticent
to
fully
support
similar
``
late
''
discovery
of
items
in
the
former
set
.
This
makes
Fortran
a
poor
fit
for
the
``
safe
''
subset
of
GBEL
.
Consider
:
@smallexample
FUNCTION
X
(
A
,
ARRAY
,
ID1
)
CHARACTER
*
(
*
)
A
DOUBLE
PRECISION
X
,
Y
,
Z
,
TMP
,
EE
,
PI
REAL
ARRAY
(
ID1
*
ID2
)
COMMON
ID2
EXTERNAL
FRED
ASSIGN
100
TO
J
CALL
FOO
(
I
)
IF
(
I
.
EQ
.
0
)
PRINT
*
,
A
(
0
)
GOTO
200
ENTRY
Y
(
Z
)
ASSIGN
101
TO
J
200
PRINT
*
,
A
(
1
)
READ
*
,
TMP
GOTO
J
100
X
=
TMP
*
EE
RETURN
101
Y
=
TMP
*
PI
CALL
FRED
DATA
EE
,
PI
/
2
.
71
D0
,
3
.
14
D0
/
END
@end
smallexample
Here
are
some
observations
about
the
above
code
,
which
,
while
somewhat
contrived
,
conforms
to
the
FORTRAN
77
and
Fortran
90
standards
:
@itemize
@bullet
@item
The
return
type
of
function
@samp
{
X
}
is
not
known
until
the
@samp
{
DOUBLE
PRECISION
}
line
has
been
parsed
.
@item
Whether
@samp
{
A
}
is
a
function
or
a
variable
is
not
known
until
the
@samp
{
PRINT
*
,
A
(
0
)}
statement
has
been
parsed
.
@item
The
bounds
of
the
array
of
argument
@samp
{
ARRAY
}
depend
on
a
computation
involving
the
subsequent
argument
@samp
{
ID1
}
and
the
blank
-
common
member
@samp
{
ID2
}.
@item
Whether
@samp
{
Y
}
and
@samp
{
Z
}
are
local
variables
,
additional
function
entry
points
,
or
dummy
arguments
to
additional
entry
points
is
not
known
until
the
@samp
{
ENTRY
}
statement
is
parsed
.
@item
Similarly
,
whether
@samp
{
TMP
}
is
a
local
variable
is
not
known
until
the
@samp
{
READ
*
,
TMP
}
statement
is
parsed
.
@item
The
initial
values
for
@samp
{
EE
}
and
@samp
{
PI
}
are
not
known
until
after
the
@samp
{
DATA
}
statement
is
parsed
.
@item
Whether
@samp
{
FRED
}
is
a
function
returning
type
@code
{
REAL
}
or
a
subroutine
(
which
can
be
thought
of
as
returning
type
@code
{
void
}
@emph
{
or
},
to
support
alternate
returns
in
a
simple
way
,
type
@code
{
int
})
is
not
known
until
the
@samp
{
CALL
FRED
}
statement
is
parsed
.
@item
Whether
@samp
{
100
}
is
a
@code
{
FORMAT
}
label
or
the
label
of
an
executable
statement
is
not
known
until
the
@samp
{
X
=
}
statement
is
parsed
.
(
These
two
types
of
labels
get
@emph
{
very
}
different
treatment
,
especially
when
@code
{
ASSIGN
}
'
ed
.)
@item
That
@samp
{
J
}
is
a
local
variable
is
not
known
until
the
first
@samp
{
ASSIGN
}
statement
is
parsed
.
(
This
happens
@emph
{
after
}
executable
code
has
been
seen
.)
@end
itemize
Very
few
of
these
``
discoveries
''
can
be
accommodated
by
the
GBE
as
it
has
evolved
over
the
years
.
The
GBEL
doesn
'
t
support
several
of
them
,
and
those
it
might
appear
to
support
don
'
t
always
work
properly
,
especially
in
combination
with
other
GBEL
and
GBE
features
,
as
implemented
in
the
GBE
.
(
Had
the
GBE
and
its
GBEL
originally
evolved
to
support
@code
{
g77
},
the
shoe
would
be
on
the
other
foot
,
so
to
speak
---
most
,
if
not
all
,
of
the
above
would
be
directly
supported
by
the
GBEL
,
and
a
few
C
constructs
would
probably
not
,
as
they
are
in
reality
,
be
supported
.
Both
this
mythical
,
and
today
'
s
real
,
GBE
caters
to
its
GBEL
by
,
sometimes
,
scrambling
around
,
cleaning
up
after
itself
---
after
discovering
that
assumptions
it
made
earlier
during
code
generation
are
incorrect
.)
So
,
the
FFE
handles
these
discrepancies
---
between
the
order
in
which
it
discovers
facts
about
the
code
it
is
compiling
,
and
the
order
in
which
the
GBEL
and
GBE
support
such
discoveries
---
by
performing
what
amounts
to
two
passes
over
each
program
unit
.
(
A
few
ambiguities
can
remain
at
that
point
,
such
as
whether
,
given
@samp
{
EXTERNAL
BAZ
}
and
no
other
reference
to
@samp
{
BAZ
}
in
the
program
unit
,
it
is
a
subroutine
,
a
function
,
or
a
block
-
data
---
which
,
in
C
-
speak
,
governs
its
declared
return
type
.
Fortunately
,
these
distinctions
are
easily
finessed
for
the
procedure
,
library
,
and
object
-
file
interfaces
supported
by
@code
{
g77
}.)
@node
Challenges
Posed
@section
Challenges
Posed
Consider
the
following
Fortran
code
,
which
uses
various
extensions
(
including
some
to
Fortran
90
)
:
@smallexample
SUBROUTINE
X
(
A
)
CHARACTER
*
(
*
)
A
COMPLEX
CFUNC
INTEGER
*
2
CLOCKS
(
200
)
INTEGER
IFUNC
CALL
SYSTEM_CLOCK
(
CLOCKS
(
IFUNC
(
CFUNC
(
'('
//A//')'))))
@end
smallexample
The
above
poses
the
following
challenges
to
any
Fortran
compiler
that
uses
run
-
time
interfaces
,
and
a
run
-
time
library
,
roughly
similar
to
those
used
by
@code
{
g77
}
:
@itemize
@bullet
@item
Assuming
the
library
routine
that
supports
@code
{
SYSTEM_CLOCK
}
expects
to
set
an
@code
{
INTEGER
*
4
}
variable
via
its
@code
{
COUNT
}
argument
,
the
compiler
must
make
available
to
it
a
temporary
variable
of
that
type
.
@item
Further
,
after
the
@code
{
SYSTEM_CLOCK
}
library
routine
returns
,
the
compiler
must
ensure
that
the
temporary
variable
it
wrote
is
copied
into
the
appropriate
element
of
the
@samp
{
CLOCKS
}
array
.
(
This
assumes
the
compiler
doesn
'
t
just
reject
the
code
,
which
it
should
if
it
is
compiling
under
some
kind
of
a
"strict"
option
.)
@item
To
determine
the
correct
index
into
the
@samp
{
CLOCKS
}
array
,
(
putting
aside
the
fact
that
the
index
,
in
this
particular
case
,
need
not
be
computed
until
after
the
@code{
SYSTEM_CLOCK
}
library
routine
returns
),
the
compiler
must
ensure
that
the
@code{
IFUNC
}
function
is
called
.
That
requires
evaluating
its
argument
,
which
requires
,
for
@code{
g77
}
(
assuming
@code{
-
ff2c
}
is
in
force
),
reserving
a
temporary
variable
of
type
@code{
COMPLEX
}
for
use
as
a
repository
for
the
return
value
being
computed
by
@samp{
CFUNC
}
.
@item
Before
invoking
@samp{
CFUNC
}
,
is
argument
must
be
evaluated
,
which
requires
allocating
,
at
run
time
,
a
temporary
large
enough
to
hold
the
result
of
the
concatenation
,
as
well
as
actually
performing
the
concatenation
.
@item
The
large
temporary
needed
during
invocation
of
@code{
CFUNC
}
should
,
ideally
,
be
deallocated
(
or
,
at
least
,
left
to
the
GBE
to
dispose
of
,
as
it
sees
fit
)
as
soon
as
@code{
CFUNC
}
returns
,
which
means
before
@code{
IFUNC
}
is
called
(
as
it
might
need
a
lot
of
dynamically
allocated
memory
).
@end
itemize
@code{
g77
}
currently
doesn
'
t
support
all
of
the
above
,
but
,
so
that
it
might
someday
,
it
has
evolved
to
handle
at
least
some
of
the
above
requirements
.
Meeting
the
above
requirements
is
made
more
challenging
by
conforming
to
the
requirements
of
the
GBEL
/
GBE
combination
.
@node
Transforming
Statements
@section
Transforming
Statements
Most
Fortran
statements
are
given
their
own
block
,
and
,
for
temporary
variables
they
might
need
,
their
own
scope
.
(
A
block
is
what
distinguishes
@samp{
@{
foo
()
;
@
}
}
from
just
@samp{
foo
()
;}
in
C
.
A
scope
is
included
with
every
such
block
,
providing
a
distinct
name
space
for
local
variables
.)
Label
definitions
for
the
statement
precede
this
block
,
so
@samp{
10
PRINT
*
,
I
}
is
handled
more
like
@samp{
fl10
:
@{
@dots{
}
@
}}
than
@samp
{@{
fl10
:
@dots{
}
@
}}
(
where
@samp
{
fl10
}
is
just
a
notation
meaning
``
Fortran
Label
10
''
for
the
purposes
of
this
document
).
@menu
*
Statements
Needing
Temporaries
::
*
Transforming
DO
WHILE
::
*
Transforming
Iterative
DO
::
*
Transforming
Block
IF
::
*
Transforming
SELECT
CASE
::
@end
menu
@node
Statements
Needing
Temporaries
@subsection
Statements
Needing
Temporaries
Any
temporaries
needed
during
,
but
not
beyond
,
execution
of
a
Fortran
statement
,
are
made
local
to
the
scope
of
that
statement
'
s
block
.
This
allows
the
GBE
to
share
storage
for
these
temporaries
among
the
various
statements
without
the
FFE
having
to
manage
that
itself
.
(
The
GBE
could
,
of
course
,
decide
to
optimize
management
of
these
temporaries
.
For
example
,
it
could
,
theoretically
,
schedule
some
of
the
computations
involving
these
temporaries
to
occur
in
parallel
.
More
practically
,
it
might
leave
the
storage
for
some
temporaries
``
live
''
beyond
their
scopes
,
to
reduce
the
number
of
manipulations
of
the
stack
pointer
at
run
time
.)
Temporaries
needed
across
distinct
statement
boundaries
usually
are
associated
with
Fortran
blocks
(
such
as
@code
{
DO
}
/
@code
{
END
DO
}).
(
Also
,
there
might
be
temporaries
not
associated
with
blocks
at
all
---
these
would
be
in
the
scope
of
the
entire
program
unit
.)
Each
Fortran
block
@emph
{
should
}
get
its
own
block
/
scope
in
the
GBE
.
This
is
best
,
because
it
allows
temporaries
to
be
more
naturally
handled
.
However
,
it
might
pose
problems
when
handling
labels
(
in
particular
,
when
they
'
re
the
targets
of
@code
{
GOTO
}
s
outside
the
Fortran
block
),
and
generally
just
hassling
with
replicating
parts
of
the
@code
{
gcc
}
front
end
(
because
the
FFE
needs
to
support
an
arbitrary
number
of
nested
back
-
end
blocks
if
each
Fortran
block
gets
one
).
So
,
there
might
still
be
a
need
for
top
-
level
temporaries
,
whose
``
owning
''
scope
is
that
of
the
containing
procedure
.
Also
,
there
seems
to
be
problems
declaring
new
variables
after
generating
code
(
within
a
block
)
in
the
back
end
,
leading
to
,
e
.
g
.,
@samp
{
label
not
defined
before
binding
contour
}
or
similar
messages
,
when
compiling
with
@samp
{
-
fstack
-
check
}
or
when
compiling
for
certain
targets
.
Because
of
that
,
and
because
sometimes
these
temporaries
are
not
discovered
until
in
the
middle
of
of
generating
code
for
an
expression
statement
(
as
in
the
case
of
the
optimization
for
@samp{
X
**
I
}
),
it
seems
best
to
always
pre
-
scan
all
the
expressions
that
'
ll
be
expanded
for
a
block
before
generating
any
of
the
code
for
that
block
.
This
pre
-
scan
then
handles
discovering
and
declaring
,
to
the
back
end
,
the
temporaries
needed
for
that
block
.
It
'
s
also
important
to
treat
distinct
items
in
an
I
/
O
list
as
distinct
statements
deserving
their
own
blocks
.
That
'
s
because
there
'
s
a
requirement
that
each
I
/
O
item
be
fully
processed
before
the
next
one
,
which
matters
in
cases
like
@samp{
READ
(
*
,
*
),
I
,
A
(
I
)
}
---
the
element
of
@samp{
A
}
read
in
the
second
item
@emph{
must
}
be
determined
from
the
value
of
@samp{
I
}
read
in
the
first
item
.
@node
Transforming
DO
WHILE
@subsection
Transforming
DO
WHILE
@samp{
DO
WHILE
(
expr
)
}
@emph{
must
}
be
implemented
so
that
temporaries
needed
to
evaluate
@samp{
expr
}
are
generated
just
for
the
test
,
each
time
.
Consider
how
@samp{
DO
WHILE
(
A
//B .NE. 'END'); @dots{}; END DO} is transformed:
@smallexample
for
(
;;
)
@{
int
temp0
;
@{
char
temp1
[
large
]
;
libg77_catenate
(
temp1
,
a
,
b
)
;
temp0
=
libg77_ne
(
temp1
,
'
END
'
)
;
@
}
if
(
!
temp0
)
break
;
@dots{
}
@}
@end
smallexample
In
this
case
,
it
seems
like
a
time
/
space
tradeoff
between
allocating
and
deallocating
@samp{
temp1
}
for
each
iteration
and
allocating
it
just
once
for
the
entire
loop
.
However
,
if
@samp{
temp1
}
is
allocated
just
once
for
the
entire
loop
,
it
could
be
the
wrong
size
for
subsequent
iterations
of
that
loop
in
cases
like
@samp{
DO
WHILE
(
A
(
I
:
J
)
//B .NE. 'END')},
because
the
body
of
the
loop
might
modify
@samp{
I
}
or
@samp{
J
}
.
So
,
the
above
implementation
is
used
,
though
a
more
optimal
one
can
be
used
in
specific
circumstances
.
@node
Transforming
Iterative
DO
@subsection
Transforming
Iterative
DO
An
iterative
@code{
DO
}
loop
(
one
that
specifies
an
iteration
variable
)
is
required
by
the
Fortran
standards
to
be
implemented
as
though
an
iteration
count
is
computed
before
entering
the
loop
body
,
and
that
iteration
count
used
to
determine
the
number
of
times
the
loop
body
is
to
be
performed
(
assuming
the
loop
isn
'
t
cut
short
via
@code{
GOTO
}
or
@code{
EXIT
}
).
The
FFE
handles
this
by
allocating
a
temporary
variable
to
contain
the
computed
number
of
iterations
.
Since
this
variable
must
be
in
a
scope
that
includes
the
entire
loop
,
a
GBEL
block
is
created
for
that
loop
,
and
the
variable
declared
as
belonging
to
the
scope
of
that
block
.
@node
Transforming
Block
IF
@subsection
Transforming
Block
IF
Consider:
@smallexample
SUBROUTINE
X
(
A
,
B
,
C
)
CHARACTER
*
(
*
)
A
,
B
,
C
LOGICAL
LFUNC
IF
(
LFUNC
(
A
//B)) THEN
CALL
SUBR1
ELSE
IF
(
LFUNC
(
A
//C)) THEN
CALL
SUBR2
ELSE
CALL
SUBR3
END
@end
smallexample
The
arguments
to
the
two
calls
to
@samp{
LFUNC
}
require
dynamic
allocation
(
at
run
time
),
but
are
not
required
during
execution
of
the
@samp{
CALL
}
statements
.
So
,
the
scopes
of
those
temporaries
must
be
within
blocks
inside
the
block
corresponding
to
the
Fortran
@code{
IF
}
block
.
This
cannot
be
represented
``
naturally
''
in
vanilla
C
,
nor
in
GBEL
.
The
@samp{
if
}
,
@samp{
elseif
}
,
@samp{
else
}
,
and
@samp{
endif
}
constructs
provided
by
both
languages
must
,
for
a
given
@samp{
if
}
block
,
share
the
same
C
/
GBE
block
.
Therefore
,
any
temporaries
needed
during
evaluation
of
@samp{
expr
}
while
executing
@samp{
ELSE
IF
(
expr
)
}
must
either
have
been
predeclared
at
the
top
of
the
corresponding
@code{
IF
}
block
,
or
declared
within
a
new
block
for
that
@code{
ELSE
IF
}
---
a
block
that
,
since
it
cannot
contain
the
@code{
else
}
or
@code{
else
if
}
itself
(
due
to
the
above
requirement
),
actually
implements
the
rest
of
the
@code{
IF
}
block
'
s
@code{
ELSE
IF
}
and
@code{
ELSE
}
statements
within
an
inner
block
.
The
FFE
takes
the
latter
approach
.
@node
Transforming
SELECT
CASE
@subsection
Transforming
SELECT
CASE
@code{
SELECT
CASE
}
poses
a
few
interesting
problems
for
code
generation
,
if
efficiency
and
frugal
stack
management
are
important
.
Consider
@samp{
SELECT
CASE
(
I
(
'
PREFIX
'
//A))},
where
@samp{
A
}
is
@code{
CHARACTER
*
(
*
)
}
.
In
a
case
like
this
---
basically
,
in
any
case
where
largish
temporaries
are
needed
to
evaluate
the
expression
---
those
temporaries
should
not
be
``
live
''
during
execution
of
any
of
the
@code{
CASE
}
blocks
.
So
,
evaluation
of
the
expression
is
best
done
within
its
own
block
,
which
in
turn
is
within
the
@code{
SELECT
CASE
}
block
itself
(
which
contains
the
code
for
the
CASE
blocks
as
well
,
though
each
within
their
own
block
).
Otherwise
,
we
'
d
have
the
rough
equivalent
of
this
pseudo
-
code
:
@smallexample
@{
char
temp
[
large
]
;
libg77_catenate
(
temp
,
'
prefix
'
,
a
)
;
switch
(
i
(
temp
))
@{
case
0
:
@dots{
}
@
}
@}
@end
smallexample
And
that
would
leave
temp
[
large
]
in
scope
during
the
CASE
blocks
(
although
a
clever
back
end
*
could
*
see
that
it
isn
'
t
referenced
in
them
,
and
thus
free
that
temp
before
executing
the
blocks
).
So
this
approach
is
used
instead
:
@smallexample
@{
int
temp0
;
@{
char
temp1
[
large
]
;
libg77_catenate
(
temp1
,
'
prefix
'
,
a
)
;
temp0
=
i
(
temp1
)
;
@
}
switch
(
temp0
)
@{
case
0
:
@dots{
}
@
}
@}
@end
smallexample
Note
how
@samp{
temp1
}
goes
out
of
scope
before
starting
the
switch
,
thus
making
it
easy
for
a
back
end
to
free
it
.
The
problem
@emph{
that
}
solution
has
,
however
,
is
with
@samp{
SELECT
CASE
(
'
prefix
'
//A)}
(
which
is
currently
not
supported
).
Unless
the
GBEL
is
extended
to
support
arbitrarily
long
character
strings
in
its
@code{
case
}
facility
,
the
FFE
has
to
implement
@code{
SELECT
CASE
}
on
@code{
CHARACTER
}
(
probably
excepting
@code{
CHARACTER
*
1
}
)
using
a
cascade
of
@code{
if
}
,
@code{
elseif
}
,
@code{
else
}
,
and
@code{
endif
}
constructs
in
GBEL
.
To
prevent
the
(
potentially
large
)
temporary
,
needed
to
hold
the
selected
expression
itself
(
@samp{'
prefix
'
//A}),
from
being
in
scope
during
execution
of
the
@code{
CASE
}
blocks
,
two
approaches
are
available
:
@itemize
@bullet
@item
Pre
-
evaluate
all
the
@code{
CASE
}
tests
,
producing
an
integer
ordinal
that
is
used
,
a
la
@samp{
temp0
}
in
the
earlier
example
,
as
if
@samp{
SELECT
CASE
(
temp0
)
}
had
been
written
.
Each
corresponding
@code{
CASE
}
is
replaced
with
@samp{
CASE
(
@var{
i
}
)
}
,
where
@var{
i
}
is
the
ordinal
for
that
case
,
determined
while
,
or
before
,
generating
the
cascade
of
@samp{
if
}
-
related
constructs
to
cope
with
@code{
CHARACTER
}
selection
.
@item
Make
@samp{
temp0
}
above
just
large
enough
to
hold
the
longest
@code{
CASE
}
string
that
'
ll
actually
be
compared
against
the
expression
(
in
this
case
,
@samp{'
prefix
'
//A}).
Since
that
length
must
be
constant
(
because
@code{
CASE
}
expressions
are
all
constant
),
it
won
'
t
be
so
large
,
and
,
further
,
@samp{
temp1
}
need
not
be
dynamically
allocated
,
since
normal
@code{
CHARACTER
}
assignment
can
be
used
into
the
fixed
-
length
@samp{
temp0
}
.
@end
itemize
Both
of
these
solutions
require
@code{
SELECT
CASE
}
implementation
to
be
changed
so
all
the
corresponding
@code{
CASE
}
statements
are
seen
during
the
actual
code
generation
for
@code{
SELECT
CASE
}
.
@node
Transforming
Expressions
@section
Transforming
Expressions
The
interactions
between
statements
,
expressions
,
and
subexpressions
at
program
run
time
can
be
viewed
as
:
@smallexample
@var{
action
}
(
@var{
expr
}
)
@end
smallexample
Here
,
@var{
action
}
is
the
series
of
steps
performed
to
effect
the
statement
,
and
@var{
expr
}
is
the
expression
whose
value
is
used
by
@var{
action
}
.
Expanding
the
above
shows
a
typical
order
of
events
at
run
time
:
@smallexample
Evaluate
@var{
expr
}
Perform
@var{
action
}
,
using
result
of
evaluation
of
@var{
expr
}
Clean
up
after
evaluating
@var{
expr
}
@end
smallexample
So
,
if
evaluating
@var{
expr
}
requires
allocating
memory
,
that
memory
can
be
freed
before
performing
@var{
action
}
only
if
it
is
not
needed
to
hold
the
result
of
evaluating
@var{
expr
}
.
Otherwise
,
it
must
be
freed
no
sooner
than
after
@var{
action
}
has
been
performed
.
The
above
are
recursive
definitions
,
in
the
sense
that
they
apply
to
subexpressions
of
@var{
expr
}
.
That
is
,
evaluating
@var{
expr
}
involves
evaluating
all
of
its
subexpressions
,
performing
the
@var{
action
}
that
computes
the
result
value
of
@var{
expr
}
,
then
cleaning
up
after
evaluating
those
subexpressions
.
The
recursive
nature
of
this
evaluation
is
implemented
via
recursive
-
descent
transformation
of
the
top
-
level
statements
,
their
expressions
,
@emph{
their
}
subexpressions
,
and
so
on
.
However
,
that
recursive
-
descent
transformation
is
,
due
to
the
nature
of
the
GBEL
,
focused
primarily
on
generating
a
@emph{
single
}
stream
of
code
to
be
executed
at
run
time
.
Yet
,
from
the
above
,
it
'
s
clear
that
multiple
streams
of
code
must
effectively
be
simultaneously
generated
during
the
recursive
-
descent
analysis
of
statements
.
The
primary
stream
implements
the
primary
@var{
action
}
items
,
while
at
least
two
other
streams
implement
the
evaluation
and
clean
-
up
items
.
Requirements
imposed
by
expressions
include
:
@itemize
@bullet
@item
Whether
the
caller
needs
to
have
a
temporary
ready
to
hold
the
value
of
the
expression
.
@item
Other
stuff
???
@end
itemize
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment