The target macros described in the "Addressing Modes" section of the
internals manual are rather badly in need of cleaning up.  I see three
primary reasons why this is so:

1) These are the macros subject to REG_OK_STRICT.  For those of you
   who have managed so far to avoid finding out about this particular
   detail: It is defined by reload.c (and only by reload.c) prior to
   including all headers.  This is required to cause tm.h to define
   GO_IF_LEGITIMATE_ADDRESS, REG_OK_FOR_BASE_P, and REG_OK_FOR_INDEX_P
   according to a different specification (this may or may not require
   actual code changes to all of these, depending on the
   architecture).  There's nothing stopping a tm.h file from mutating
   other macros in response to it.  I inventoried all of the
   occurrences of REG_OK_STRICT in existing target files and found
   direct effects on definitions of EXTRA_CONSTRAINT,
   LEGITIMATE_PIC_OPERAND_P, and a gaggle of macros which I *think*
   are not part of the formal tm.h interface (that is, they are
   defined for internal use by other macros or for use in CPU.c).
   Also, any macro which uses any of the above macros is perforce
   affected.

2) Several of these macros are specified to alter control flow.  They
   take a label as an argument, and should "goto" it under specified
   conditions.  These are: GO_IF_LEGITIMATE_ADDRESS,
   GO_IF_MODE_DEPENDENT_ADDRESS, LEGITIMIZE_ADDRESS, and
   LEGITIMIZE_RELOAD_ADDRESS.  Because of this, they are used in an
   obscure fashion (especially the latter two) and are difficult to
   define as function calls.  Which brings us to ...

3) The definitions of these macros are necessarily complicated on a
   lot of architectures, so that it is desirable to take them
   out-of-line into the CPU.c file, but this is difficult because of
   points 1 and 2.

I have worked out a tentative plan for replacing most of these macros
with ordinary target hooks, and eliminating REG_OK_STRICT.  I propose
to change GO_IF_LEGITIMATE_ADDRESS, GO_IF_MODE_DEPENDENT_ADDRESS,
LEGITIMIZE_ADDRESS, LEGITIMIZE_RELOAD_ADDRESS, REG_OK_FOR_BASE_P,
REG_MODE_OK_FOR_BASE_P, REG_MODE_OK_FOR_REG_BASE_P,
REG_OK_FOR_INDEX_P, CONSTANT_ADDRESS_P, FIND_BASE_TERM, and
LEGITIMATE_CONSTANT_P.  The other macros in this section are all
numeric constants and in at least one case are used to size static
arrays, so conversion to hooks doesn't make sense (yet).

The majority of the work will be dealing with the first four, and to a
lesser extent the first eight.  It's a lot of work, and I would like
to get both initial buy-in from people familiar with the details of
these macros (never having written a port, I am not the best-qualified
to assess what is and is not safe) and pledges of assistance from port
maintainers in cleaning up their own code.

In order to do this in a sensible manner, we need to decouple problems
1 and 2 above, and we need to deal with problem 1 from the caller's
side, by making it explicit which behavior is expected at which call
sites.  Conveniently, the introduction of a target hook in DJ's style
(that is, with a default that invokes the old macro) does exactly
this.  For macros that are expected to vary with REG_OK_STRICT, we
replace with two hooks; for macros that should not vary, we replace
with one.  (Even if a macro has been defined to vary, we don't need
two hooks unless it is used both inside and outside reload.c.)

Also conveniently, there are only a small number of call sites for the
really nasty macros.  GO_IF_LEGITIMATE_ADDRESS is called from
memory_address_p, strict_memory_address_p, and a handful of places in
target-specific code (m68hc11.h, m68k.h, pdp11.c, sh.c).
GO_IF_MODE_DEPENDENT_ADDRESS is used only in mode_dependent_address_p.
LEGITIMIZE_ADDRESS is used only in memory_address, and
LEGITIMIZE_RELOAD_ADDRESS only in find_reloads_address.  Furthermore,
memory_address_p, strict_memory_address_p, and
mode_dependent_address_p are tiny wrappers which turn macros with
inconvenient control flow properties into ordinary predicate
functions.

So, the plan: Step 1 introduces - one at a time - target hooks
corresponding to each of the above macros.  All callers are changed to
use the hooks.  The default definitions of the hooks invoke the
existing macros.  The hardest part of this is working out exactly what
their sole callers expect of LEGITIMIZE_ADDRESS and
LEGITIMIZE_RELOAD_ADDRESS.  The manual, unfortunately, is not very
clear.  I think that in both cases it amounts to "either replace X
with a new value and jump to WIN, or leave X unmodified and drop
through", which can be translated to "return a new value for X, or
NULL", but I'm not sure, particularly about LEGITIMIZE_RELOAD_ADDRESS
and its interaction with push_reload.

Step 2 is to convert each architecture, one at a time, to make
target-hook definitions.  I think it makes most sense to do each
architecture in one go, because the definitions of these macros tend
to be intertwined.  In particular, REG_OK_FOR_BASE_P etc are often
used in the definition of GO_IF_LEGITIMATE_ADDRESS.  It will require
some care to be sure that the hooks retain the same semantics wrt
REG_OK_STRICT.  Some of the macros have sensible defaults; for
instance, it is allowed to define a LEGITIMIZE_ADDRESS that does
nothing.  In this stage we should identify what those defaults are,
and add appropriate functions to hooks.c; but we cannot change the
default settings in target-def.h until all architectures are
converted.

Step 3 cleans up after step 2: we remove the default definitions,
poison the macros, change the settings in target-def.h, and remove any
now-redundant hook settings in cpu.c files.  This can safely be done
all at once.

Step 4 is to remove all remaining references to REG_OK_STRICT from
target headers, one architecture at a time.  In many cases there won't
be any left.  This is when we deal with variable definitions of
EXTRA_CONSTRAINT, for instance (where I think the appropriate thing is
to make a single definition containing a
(reload_in_progress||reload_completed) conditional).

Thoughts?

zw

Reply via email to