"hard" chars or shorts are those contained in structures, or found
indirectly through pointers.  In these cases the number of bytes
that the value is stored in is fixed by the definition of C.
Such a value is stored in the nominal number of bytes for its type.

"soft" chars or shorts are scalar variables (including arguments
of functions, and static variables) and temporaries holding
intermediate results.  They are always really stored as ints
(or unsigned ints), occupying 4 bytes and pre-extended with
sign or zeros.

The code generator pass always knows whether a short is hard or a
soft.  Here is a discussion of what the code generator must do for
evaluating and assigning short values.  (We use "short" here to
include "char" as well; in general, anything shorter than the length
of a general register.)


Rtl operators needed:

There should be distinct rtl operators for reference to different size
memory units: one for bytes, one for shorts, one for longs, and one for
superlongs (used for doubles).

There should be a parallel set of rtl operators for reference to
possibly-registers.

There should not be distinct rtl memory or register operators for
floating contents versus integer contents.  Instead, there should be
different rtl operators for fixed and floating arithmetic operations.
These make the distinction between fixed and floating arithmetic, and
the operands used indicate only the size.


Extracting a soft short as hard:

If the value of a soft short variable is to be used without a cast, or
is to be cast to a longer type of the same signedness, it can be
extracted as if the variable were a hard value of the desired type,
since its low bytes will contain the correct data for that type.  I
believe this can be done simply by generating "short" instructions;
that should work on both registers and memory.


Evaluation of soft shorts:

Evaluation of a soft short variable must be considered together with
any cast that is to be done on the value.  Code is generated for the
two operations combined.

If the value is to be used without a cast, or is to be cast to a
longer type of the same signedness, just extract the variable as a
hard value of the desired type.  See above.

Evaluating a soft short variable and casting it to a shorter type
or a type of different signedness requires extracting the soft short
as a hard short value and then truncating or extending that hard value
as appropriate.


Conversion of hard shorts:

Converting to a longer type requires an explicit instruction for
sign-extension or zero-extension.

Converting to a shorter type requires an explicit instruction for
truncation, followed by another instruction for explicit
sign-extension TO INT if the desired type is signed (because the
shorter value that results from the cast is a soft short).  Some
machines such as the vax have single instructions to combine
truncation with sign-extension.  Perhaps the combiner will take care
of that.


Assignments:

Assignments cannot be processed optimally by computing the rhs,
including all type conversions, before doing the actual store.
It is necessary to consider the rhs value as it exists before
any final type conversion, and do the assignment based on that value
and the target variable (and type).  [unsigned ints mostly - Len]

This applies, however, only to integers.  For assignments that convert
between integer and floating, the straightforward strategy of converting
the rhs first and then considering the assignment is correct.


Assignments to hard shorts:

Assignments to hard short variables from values of the same size or
longer are straightforward, regardless of whether the values are hard
or short.  Just generate a size of instruction according to the
variable being stored in.  It is ok to extract the value as hard first
if it is short (which is what is normally done to evaluate the
variable and not change its type); the effects of this will be
overridden in any case by choosing the instruction size according to
the target.

Assignments from values shorter than the target require explicit
conversion (see "Conversion of hard shorts") before the actual
assignment.  The conversion and assignment might be combined.


Assignments to soft shorts:

Assignments to soft short variables from hard values of the same size
(or smaller) must generate extra instructions to sign extend or zero
extend TO AN INT, and then assign the result into the variable,
regarded as an int.

Assignments to soft shorts from soft values of the same (or shorter)
size and the same signedness can be done by treating both as ints.
No extra code is required.

Assignments to soft shorts from soft values of the same or shorter
size but different signedness must explicitly extract the soft value
as a hard value of the same size, and then extend as above.

Assignments to soft shorts from longer values must extract the longer
value as hard (if it is not a full int), use that in an instruction for
explicit truncation, followed by another instruction for explicit
sign-extension TO INT if the target soft short is signed.  Some machines
such as the vax have single instructions to combine truncation with
sign-extension.  Perhaps the combiner will take care of that.

When a soft unsigned short ends up in memory, not in a register,
zero-extension of values stored in it can be done by storing into a
smaller unit of memory.  Some machines can do this in a register also.
On those machines, the assignment can be generated using a short
reference.  On machines that can do this in memory but not in registers,
this is a problem case, because I don't think the combiner can optimize
the explicit code that will work ok on registers into the simple thing
that is better for memory.  I do not see what is best here.


Floating and double:

These can be handled using similar rules except that floats are always
hard.  A soft float would be a float really stored as a double; this
is not necessary because a float uses an entire machine register (a
double uses two of them), and it would be wasteful.

Because float temporary values are not soft, conversion of a double
to float requires just truncation, without reextension afterward.
