2 |
7u83 |
1 |
<!-- Crown Copyright (c) 1998 -->
|
|
|
2 |
<HTML>
|
|
|
3 |
<HEAD>
|
|
|
4 |
<TITLE>SHAPEs, ALIGNMENTs and OFFSETs.</TITLE>
|
|
|
5 |
</HEAD>
|
|
|
6 |
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#400080" ALINK="#FF0000">
|
|
|
7 |
<A NAME=S18>
|
|
|
8 |
<H1>TDF Guide, Issue 4.0 </H1>
|
|
|
9 |
<H3>January 1998</H3>
|
|
|
10 |
<A HREF="guide7.html"><IMG SRC="../images/next.gif" ALT="next section">
|
|
|
11 |
</A> <A HREF="guide5.html">
|
|
|
12 |
<IMG SRC="../images/prev.gif" ALT="previous section"></A>
|
|
|
13 |
<A HREF="guide1.html"><IMG SRC="../images/top.gif" ALT="current document"></A>
|
|
|
14 |
<A HREF="../index.html"><IMG SRC="../images/home.gif" ALT="TenDRA home page">
|
|
|
15 |
</A>
|
|
|
16 |
<IMG SRC="../images/no_index.gif" ALT="document index"><P>
|
|
|
17 |
<HR>
|
|
|
18 |
<DL>
|
|
|
19 |
<DT><A HREF="#S19"><B>4.1 </B> - Shapes</A><DD>
|
|
|
20 |
<DT><A HREF="#S20"><B>4.1.1 </B> - TOP, BOTTOM, LUB</A><DD>
|
|
|
21 |
<DT><A HREF="#S21"><B>4.1.2 </B> - INTEGER</A><DD>
|
|
|
22 |
<DT><A HREF="#S22"><B>4.1.3 </B> - FLOATING and complex</A><DD>
|
|
|
23 |
<DT><A HREF="#S23"><B>4.1.4 </B> - BITFIELD</A><DD>
|
|
|
24 |
<DT><A HREF="#S24"><B>4.1.5 </B> - PROC</A><DD>
|
|
|
25 |
<DT><A HREF="#S25"><B>4.1.6 </B> - Non-primitive SHAPEs</A><DD>
|
|
|
26 |
<DT><A HREF="#S26"><B>4.2 </B> - Alignments</A><DD>
|
|
|
27 |
<DT><A HREF="#S27"><B>4.2.1 </B> - ALIGNMENT constructors</A>
|
|
|
28 |
<DD>
|
|
|
29 |
<DT><A HREF="#S28"><B>4.2.2 </B> - Special alignments</A><DD>
|
|
|
30 |
<DT><A HREF="#S29"><B>4.2.3 </B> - AL_TAG, make_al_tagdef</A>
|
|
|
31 |
<DD>
|
|
|
32 |
<DT><A HREF="#S30"><B>4.3 </B> - Pointer and offset SHAPEs</A><DD>
|
|
|
33 |
<DT><A HREF="#S31"><B>4.3.1 </B> - OFFSET</A><DD>
|
|
|
34 |
<DT><A HREF="#S32"><B>4.4 </B> - Compound SHAPEs</A><DD>
|
|
|
35 |
<DT><A HREF="#S33"><B>4.4.1 </B> - Offset arithmetic with compound
|
|
|
36 |
shapes</A><DD>
|
|
|
37 |
<DT><A HREF="#S34"><B>4.4.2 </B> - offset_mult</A><DD>
|
|
|
38 |
<DT><A HREF="#S35"><B>4.4.3 </B> - OFFSET ordering and representation</A><DD>
|
|
|
39 |
<DT><A HREF="#S36"><B>4.5 </B> - BITFIELD alignments</A><DD>
|
|
|
40 |
</DL>
|
|
|
41 |
<HR>
|
|
|
42 |
<H1>4 SHAPEs, ALIGNMENTs and OFFSETs.</H1>
|
|
|
43 |
In most languages there is some notion of the type of a value. This
|
|
|
44 |
is often an uncomfortable mix of a definition of a representation
|
|
|
45 |
for the value and a means of choosing which operators are applicable
|
|
|
46 |
to the value. The TDF analogue of the type of value is its SHAPE (S3.20).
|
|
|
47 |
A SHAPE is only concerned with the representation of a value, being
|
|
|
48 |
an abstraction of its size and alignment properties. Clearly an architecture-independent
|
|
|
49 |
representation of a program cannot say, for example, that a pointer
|
|
|
50 |
is 32 bits long; the size of pointers has to be abstracted so that
|
|
|
51 |
translations to particular architectures can choose the size that
|
|
|
52 |
is apposite for the platform.<P>
|
|
|
53 |
<A NAME=S19>
|
|
|
54 |
<HR><H2>4.1. Shapes</H2>
|
|
|
55 |
There are ten different basic constructors for the SORT SHAPE from
|
|
|
56 |
bitfield to top as shown in table 3. SHAPEs arising from those constructors
|
|
|
57 |
are used as qualifiers (just using an upper case version of the constructor
|
|
|
58 |
name) to various SORTs in the definition; for example, EXP TOP is
|
|
|
59 |
an expression with top SHAPE. This is just used for definitional purposes
|
|
|
60 |
only; there is no SORT SHAPENAME as one has SORTNAME.<P>
|
|
|
61 |
In the TDF specification of EXPs, you will observe that all EXPs in
|
|
|
62 |
constructor signatures are all qualified by the SHAPE name; for example,
|
|
|
63 |
a parameter might be EXP INTEGER(v). This merely means that for the
|
|
|
64 |
construct to be meaningful the parameter must be derived from a constructor
|
|
|
65 |
defined to be an EXP INTEGER(v). You might be forgiven for assuming
|
|
|
66 |
that TDF is hence strongly-typed by its SHAPEs. This is not true;
|
|
|
67 |
the producer must get it right. There are some checks in translators,
|
|
|
68 |
but these are not exhaustive and are more for the benefit of translator
|
|
|
69 |
writers than for the user. A tool for testing the SHAPE correctness
|
|
|
70 |
of a TDF program would be useful but has yet to be written.<P>
|
|
|
71 |
<A NAME=S20>
|
|
|
72 |
<H3>4.1.1. TOP, BOTTOM, LUB</H3>
|
|
|
73 |
Two of the SHAPE constructions are rather specialised; these are
|
|
|
74 |
TOP and BOTTOM. The result of any expression with a TOP shape will
|
|
|
75 |
always be discarded; examples are those produced by assign and integer_test
|
|
|
76 |
. A BOTTOM SHAPE is produced by an expression which will leave the
|
|
|
77 |
current flow of control e.g. goto . The significance of these SHAPEs
|
|
|
78 |
only really impinges on the computation of the shapes of constructs
|
|
|
79 |
which have alternative expressions as results. For example, the result
|
|
|
80 |
of conditional is the result of one of its component expressions.
|
|
|
81 |
In this case, the SHAPE of the result is described as the LUB of the
|
|
|
82 |
SHAPEs of the components. This simply means that if one of the component
|
|
|
83 |
SHAPEs is TOP then the resulting SHAPE is TOP; if one is BOTTOM then
|
|
|
84 |
the resulting SHAPE is the SHAPE of the other; otherwise both component
|
|
|
85 |
SHAPEs must be equal and is the resulting SHAPE. Since this operation
|
|
|
86 |
is associative, commutative and idempotent, we can speak quite unambiguously
|
|
|
87 |
of the LUB of several SHAPEs.<P>
|
|
|
88 |
<A NAME=S21>
|
|
|
89 |
<H3>4.1.2. INTEGER</H3>
|
|
|
90 |
Integer values in TDF have shape INTEGER(v) where v is of SORT VARIETY.
|
|
|
91 |
The constructor for this SHAPE is integer with a VARIETY parameter.
|
|
|
92 |
The basic constructor for VARIETY is var_limits which has a pair of
|
|
|
93 |
signed natural numbers as parameters giving the limits of possible
|
|
|
94 |
values that the integer can attain. The SHAPE required for a 32 bit
|
|
|
95 |
signed integer would be:<P>
|
|
|
96 |
<PRE>
|
|
|
97 |
integer(var_limits(-2<I>31</I>, 2<I>31</I>-1))
|
|
|
98 |
</PRE>
|
|
|
99 |
while an unsigned char is:<P>
|
|
|
100 |
<PRE>
|
|
|
101 |
integer(var_limits(0, 255))
|
|
|
102 |
</PRE>
|
|
|
103 |
A translator should represent each integer variety by an object big
|
|
|
104 |
enough (or bigger) to contain all the possible values with limits
|
|
|
105 |
of the VARIETY. That being said, I must confess that most current
|
|
|
106 |
translators do not handle integers of more than the maximum given
|
|
|
107 |
naturally by the target architecture, but this will be rectified in
|
|
|
108 |
due course.<P>
|
|
|
109 |
The other way of constructing a VARIETY is to specify the number of
|
|
|
110 |
bits required for its 2s-complemennt representation using var_width:
|
|
|
111 |
<P>
|
|
|
112 |
<PRE>
|
|
|
113 |
signed_width: BOOL
|
|
|
114 |
width: NAT
|
|
|
115 |
-> VARIETY
|
|
|
116 |
</PRE>
|
|
|
117 |
<P>
|
|
|
118 |
<A NAME=S22>
|
|
|
119 |
<H3>4.1.3. FLOATING and complex</H3>
|
|
|
120 |
Similarly, floating point and complex numbers have shape FLOATING
|
|
|
121 |
qualified by a FLOATING_VARIETY. <P>
|
|
|
122 |
A FLOATING_VARIETY for a real number is constructed using fvar_parms:<P>
|
|
|
123 |
<PRE>
|
|
|
124 |
base: NAT
|
|
|
125 |
mantissa_digits: NAT
|
|
|
126 |
minimum_exponent: NAT
|
|
|
127 |
maximum_exponent:: NAT
|
|
|
128 |
-> FLOATING_VARIETY
|
|
|
129 |
</PRE>
|
|
|
130 |
A FLOATING_VARIETY specifies the base, number of mantissa digits,
|
|
|
131 |
and maximum and minimum exponent. Once again, it is intended that
|
|
|
132 |
the translator will choose a representation which will contain all
|
|
|
133 |
possible values, but in practice only those which are included in
|
|
|
134 |
IEEE float, double and extended are actually implemented.<P>
|
|
|
135 |
Complex numbers have a floating variety constructed by complex_parms
|
|
|
136 |
which has the the same signature as fvar_parms. The representation
|
|
|
137 |
of these numbers is likely to be a pair of real numbers each defined
|
|
|
138 |
as if by fvar_parms with the same arguments. The real and imaginary
|
|
|
139 |
parts of of a complex number can be extracted using real_part and
|
|
|
140 |
imaginary_part; these could have been injected ito the complex number
|
|
|
141 |
using make_complex or any of the complex operations. Many translators
|
|
|
142 |
will simply transform complex numbers into COMPOUNDs consisting of
|
|
|
143 |
two floating point numbers, transforming the complex operations into
|
|
|
144 |
floating point operations on the fields.<P>
|
|
|
145 |
<A NAME=S23>
|
|
|
146 |
<H3>4.1.4. BITFIELD</H3>
|
|
|
147 |
A number of contiguous bits have shape BITFIELD, qualified by a BITFIELD_VARIETY
|
|
|
148 |
(S3.4) which gives the number of bits involved and whether these bits
|
|
|
149 |
are to be treated as signed or unsigned integers. Current translators
|
|
|
150 |
put a maximum of 32 or 64 on the number of bits.<P>
|
|
|
151 |
<A NAME=S24>
|
|
|
152 |
<H3>4.1.5. PROC</H3>
|
|
|
153 |
The representational SHAPEs of procedure values is given by PROC with
|
|
|
154 |
constructor proc . I shall return to this in the description of the
|
|
|
155 |
operations which use it.<P>
|
|
|
156 |
<A NAME=S25>
|
|
|
157 |
<H3>4.1.6. Non-primitive SHAPEs</H3>
|
|
|
158 |
The construction of the other four SHAPEs involves either existing
|
|
|
159 |
SHAPEs or the alignments of existing SHAPEs. These are constructed
|
|
|
160 |
by compound, nof , offset and pointer. Before describing these, we
|
|
|
161 |
require a digression into what is meant by alignments and offsets.<P>
|
|
|
162 |
<P>
|
|
|
163 |
<A NAME=S26>
|
|
|
164 |
<HR><H2>4.2. Alignments</H2>
|
|
|
165 |
In most processor architectures there are limitations on how one can
|
|
|
166 |
address particular kinds of objects in convenient ways. These limitations
|
|
|
167 |
are usually defined as part of the ABI for the processor. For example,
|
|
|
168 |
in the MIPs processor the fastest way to access a 32-bit integer is
|
|
|
169 |
to ensure that the address of the integer is aligned on a 4-byte boundary
|
|
|
170 |
in the address space; obviously one can extract a mis-aligned integer
|
|
|
171 |
but not in one machine instruction. Similarly, 16-bit integers should
|
|
|
172 |
be aligned on a 2-byte boundary. In principle, each primitive object
|
|
|
173 |
could have similar restrictions for efficient access and these restrictions
|
|
|
174 |
could vary from platform to platform. Hence, the notion of alignment
|
|
|
175 |
has to be abstracted to form part of the architecture independent
|
|
|
176 |
TDF - we cannot assume that any particular alignment regime will hold
|
|
|
177 |
universally.<P>
|
|
|
178 |
The abstraction of alignments clearly has to cover compound objects
|
|
|
179 |
as well as primitive ones like integers. For example, if a field of
|
|
|
180 |
structure in C is to be accessed efficiently, then the alignment of
|
|
|
181 |
the field will influence the alignment of the structure as whole;
|
|
|
182 |
the structure itself could be a component of a larger object whose
|
|
|
183 |
alignment must then depend on the alignment of the structure and so
|
|
|
184 |
on. In general, we find that a compound alignment is given by the
|
|
|
185 |
maximum alignment of its components, regardless of the form of the
|
|
|
186 |
compound object e.g. whether it is a structure, union, array or whatever.
|
|
|
187 |
<P>
|
|
|
188 |
This gives an immediate handle on the abstraction of the alignment
|
|
|
189 |
of a compound object - it is just the set of abstractions of the alignments
|
|
|
190 |
of its components. Since "maximum" is associative, commutative
|
|
|
191 |
and idempotent, the component sets can be combined using normal set-union
|
|
|
192 |
rules. In other words, a compound alignment is abstracted as the set
|
|
|
193 |
of alignments of the primitive objects which make up the compound
|
|
|
194 |
object. Thus the alignment abstraction of a C structure with only
|
|
|
195 |
float fields is the singleton set containing the alignment of a float
|
|
|
196 |
while that of a C union of an int and this structure is a pair of
|
|
|
197 |
the alignments of an int and a float.<P>
|
|
|
198 |
<A NAME=S27>
|
|
|
199 |
<H3>4.2.1. ALIGNMENT constructors</H3>
|
|
|
200 |
The TDF abstraction of an alignment has SORT ALIGNMENT. The constructor,
|
|
|
201 |
unite_alignments, gives the set-union of its ALIGNMENT parameters;
|
|
|
202 |
this would correspond to taking a maximum of two real alignments in
|
|
|
203 |
the translator. <P>
|
|
|
204 |
The constructor , alignment, gives the ALIGNMENT of a given SHAPE
|
|
|
205 |
according to the rules given in the definition. These rules effectively
|
|
|
206 |
<I>define</I> the primitive ALIGNMENTs as in the ALIGNMENT column
|
|
|
207 |
of table 3. Those for PROC, all OFFSETs and all POINTERs are constants
|
|
|
208 |
regardless of any SHAPE qualifiers. Each of the INTERGER VARIETYs,
|
|
|
209 |
each of the FLOATING VARIETYs and each of the BITFIELD VARIETYs have
|
|
|
210 |
their own ALIGNMENTs. These ALIGNMENTs will be bound to values apposite
|
|
|
211 |
to the particular platform at translate-time. The ALIGNMENT of TOP
|
|
|
212 |
is conventionally taken to be the empty set of ALIGNMENTs (corresponding
|
|
|
213 |
to the minimum alignment on the platform). <P>
|
|
|
214 |
The alignment of a procedure parameter clearly has to include the
|
|
|
215 |
alignment of its SHAPE; however, most ABIs will mandate a greater
|
|
|
216 |
alignment for some SHAPEs e.g. the alignment of a byte parameter is
|
|
|
217 |
usually defined to be on a 32-bit rather than an 8-bit boundary. The
|
|
|
218 |
constructor, parameter_alignment, gives the ALIGNMENT of a parameter
|
|
|
219 |
of given SHAPE.<P>
|
|
|
220 |
<A NAME=S28>
|
|
|
221 |
<H3>4.2.2. Special alignments</H3>
|
|
|
222 |
There are several other special ALIGNMENTs.<P>
|
|
|
223 |
The alignment of a code address is {<I>code</I>} given by code_alignment;
|
|
|
224 |
this will be the alignment of a pointer given by make_local_lv giving
|
|
|
225 |
the value of a label. <P>
|
|
|
226 |
The other special ALIGNMENTs are considered to include all of the
|
|
|
227 |
others, but remain distinct. They are all concerned with offsets and
|
|
|
228 |
pointers relevant to procedure frames, procedure parameters and local
|
|
|
229 |
allocations and are collectively known as frame alignments. These
|
|
|
230 |
frame alignments differ from the normal alignments in that their mapping
|
|
|
231 |
to a given architecture is rather more than just saying that it describes
|
|
|
232 |
some n-bit boundary. For example, alloca_alignment describes the alignment
|
|
|
233 |
of dynamic space produced by local_alloc (roughly the C alloca). Now,
|
|
|
234 |
an ABI could specify that the alloca space is a stack disjoint from
|
|
|
235 |
the normal procedure stack; thus manipulations of space at alloca_alignment
|
|
|
236 |
may involve different code to space generated in other ways.<P>
|
|
|
237 |
Similar considerations apply to the other special alignments, callees_alignment(b),
|
|
|
238 |
callers_alignment(b) and locals_alignment. The first two give the
|
|
|
239 |
alignments of the bases of the two different parameter spaces in procedures
|
|
|
240 |
(q.v.) and locals_alignment gives the alignment of the base of locally
|
|
|
241 |
declared tags within a procedure. The exact interpretation of these
|
|
|
242 |
depends on how the frame stack is defined in the target ABI, e.g.
|
|
|
243 |
does the stack grow downwards or upwards? <P>
|
|
|
244 |
The final special alignment is var_param_alignment. This describes
|
|
|
245 |
the alignment of a special kind of parameter to a procedure which
|
|
|
246 |
can be of arbitrary length (see <A HREF="guide7.html#12">section 5.1.1
|
|
|
247 |
on page 27</A>).<P>
|
|
|
248 |
<A NAME=S29>
|
|
|
249 |
<H3>4.2.3. AL_TAG, make_al_tagdef</H3>
|
|
|
250 |
Alignments can also be named as AL_TAGs using make_al_tagdef. There
|
|
|
251 |
is no corresponding make_al_tagdec since AL_TAGs are implicitly declared
|
|
|
252 |
by their constructor, make_al_tag. The main reason for having names
|
|
|
253 |
for alignments is to allow one to resolve the ALIGNMENTs of recursive
|
|
|
254 |
data structures. If, for example, we have mutually recursive structures,
|
|
|
255 |
their ALIGNMENTs are best named and given as a set of equations formed
|
|
|
256 |
by AL_TAGDEFs. A translator can then solve these equations trivially
|
|
|
257 |
by substitution; this is easy because the only significant operation
|
|
|
258 |
is set-union.<P>
|
|
|
259 |
<A NAME=S30>
|
|
|
260 |
<HR><H2>4.3. Pointer and offset SHAPEs</H2>
|
|
|
261 |
A pointer value must have a form which reflects the alignment of the
|
|
|
262 |
object that it points to; for example, in the MIPs processor, the
|
|
|
263 |
bottom two bits of a pointer to an integer must be zero. The TDF SHAPE
|
|
|
264 |
for a pointer is POINTER qualified by the ALIGNMENT of the object
|
|
|
265 |
pointed to. The constructor pointer uses this alignment to make a
|
|
|
266 |
POINTER SHAPE.<P>
|
|
|
267 |
<A NAME=S31>
|
|
|
268 |
<H3>4.3.1. OFFSET</H3>
|
|
|
269 |
Expressions which give sizes or offsets in TDF have an OFFSET SHAPE.
|
|
|
270 |
These are always described as the difference between two pointers.
|
|
|
271 |
Since the alignments of the objects pointed to could be different,
|
|
|
272 |
an OFFSET is qualified by these two ALIGNMENTs. Thus an EXP OFFSET(X,Y)
|
|
|
273 |
is the difference between an EXP POINTER(X) and an EXP POINTER(Y).
|
|
|
274 |
In order for the alignment rules to apply, the set X of alignments
|
|
|
275 |
must include Y. The constructor offset uses two such alignments to
|
|
|
276 |
make an OFFSET SHAPE. However, many instances of offsets will be produced
|
|
|
277 |
implicitly by the offset arithmetic, e.g., offset_pad:<P>
|
|
|
278 |
<PRE>
|
|
|
279 |
<I> a</I>: ALIGNMENT
|
|
|
280 |
<I> arg</I>1: EXP OFFSET(<I>z, t</I>)
|
|
|
281 |
-> EXP OFFSET(<I>z</I> xc8 <I> a, a</I>)
|
|
|
282 |
</PRE>
|
|
|
283 |
This gives the next OFFSET greater or equal to <I>arg1</I> at which
|
|
|
284 |
an object of ALIGNMENT <I>a</I> can be placed. It should be noted
|
|
|
285 |
that the calculation of shapes and alignments are all translate-time
|
|
|
286 |
activities; only EXPs should produce runnable code. This code, of
|
|
|
287 |
course, may depend on the shapes and alignments involved; for example,
|
|
|
288 |
offset_pad might round up <I>arg1</I> to be a multiple of four bytes
|
|
|
289 |
if<I> a</I> was an integer ALIGNMENT and <I>z</I> was a character
|
|
|
290 |
ALIGNMENT. Translators also do extensive constant analysis, so if
|
|
|
291 |
<I>arg1</I> was a constant offset, then the round-off would be done
|
|
|
292 |
at translate-time to produce another constant.<P>
|
|
|
293 |
.<P>
|
|
|
294 |
<A NAME=S32>
|
|
|
295 |
<HR><H2>4.4. Compound SHAPEs</H2>
|
|
|
296 |
The alignments of compound SHAPEs (i.e. those arising from the constructors
|
|
|
297 |
compound and nof) are derived from the constructions which produced
|
|
|
298 |
the SHAPE. To take the easy one first, the constructor nof has signature:<P>
|
|
|
299 |
<PRE>
|
|
|
300 |
<I> n</I>: NAT
|
|
|
301 |
<I> s</I>: SHAPE
|
|
|
302 |
-> SHAPE
|
|
|
303 |
</PRE>
|
|
|
304 |
This SHAPE describes an array of <I>n</I> values all of SHAPE <I>s</I>;
|
|
|
305 |
note that <I>n</I> is a natural number and hence is a constant known
|
|
|
306 |
to the producer. Throughout the definition this is referred to as
|
|
|
307 |
the SHAPE NOF(n, s). The ALIGNMENT of such a value is alignment(s);
|
|
|
308 |
i.e. the alignment of an array is just the alignment of its elements.<P>
|
|
|
309 |
The other compound SHAPEs are produced using compound:<P>
|
|
|
310 |
<PRE>
|
|
|
311 |
<I> sz</I>: EXP OFFSET(<I>x, y</I>)
|
|
|
312 |
-> S HAPE
|
|
|
313 |
</PRE>
|
|
|
314 |
The <I>sz</I> parameter gives the minimum size which can accommodate
|
|
|
315 |
the SHAPE. <P>
|
|
|
316 |
<A NAME=S33>
|
|
|
317 |
<H3>4.4.1. Offset arithmetic with compound shapes</H3>
|
|
|
318 |
The constructors offset_add , offset_zero and shape_offset are used
|
|
|
319 |
together with offset_pad to implement (<I>inter alia</I>) selection
|
|
|
320 |
from structures represented by COMPOUND SHAPEs. Starting from the
|
|
|
321 |
zero OFFSET given by offset_zero, one can construct an EXP which is
|
|
|
322 |
the offset of a field by padding and adding offsets until the required
|
|
|
323 |
field is reached. The value of the field required could then be extracted
|
|
|
324 |
using component or add_to_ptr. Most producers would define a TOKEN
|
|
|
325 |
for the EXP OFFSET of each field of a structure or union used in the
|
|
|
326 |
program simply to reduce the size of the TDF<P>
|
|
|
327 |
The SHAPE of a C structure consisting of an char followed by an int
|
|
|
328 |
would require <I>x</I> to be the set consisting of two INTEGER VARIETYs,
|
|
|
329 |
one for int and one for char, and <I>sz</I> would probably have been
|
|
|
330 |
constructed like:<P>
|
|
|
331 |
<PRE>
|
|
|
332 |
<I>sz </I>= offset_add(offset_pad(int_al, shape_offset(char)), shape_offset(int))
|
|
|
333 |
</PRE>
|
|
|
334 |
The various rules for the ALIGNMENT qualifiers of the OFFSETs give
|
|
|
335 |
the required SHAPE; these rules also ensure that offset arithmetic
|
|
|
336 |
can be implemented simply using integer arithmetic for standard architectures
|
|
|
337 |
(see <A HREF="guide15.html#2">section 13.1 on page 56</A>). Note that
|
|
|
338 |
the OFFSET computed here is the minimum size for the SHAPE. This would
|
|
|
339 |
not in general be the same as the difference between successive elements
|
|
|
340 |
of an array of these structures which would have SHAPE OFFSET(<I>x</I>,
|
|
|
341 |
<I>x</I>) as produced by offset_pad(<I>x</I>, <I>sz</I>). For examples
|
|
|
342 |
of the use of OFFSETs to access and create structures, see
|
|
|
343 |
<A HREF="guide14.html#0">section 12 on page 53</A>.<P>
|
|
|
344 |
<A NAME=S34>
|
|
|
345 |
<H3>4.4.2. offset_mult</H3>
|
|
|
346 |
In C, all structures have size known at translate-time. This means
|
|
|
347 |
that OFFSETs for all field selections of structures and unions are
|
|
|
348 |
translate-time constants; there is never any need to produce code
|
|
|
349 |
to compute these sizes and offsets. Other languages (notably Ada)
|
|
|
350 |
do have variable size structures and so sizes and offsets within these
|
|
|
351 |
structures may have to be computed dynamically. Indexing in C will
|
|
|
352 |
require the computation of dynamic OFFSETs; this would usually be
|
|
|
353 |
done by using offset_mult to multiply an offset expression representing
|
|
|
354 |
the stride by an integer expression giving the index:<P>
|
|
|
355 |
<PRE>
|
|
|
356 |
<I> arg1</I>: EXP OFFSET(<I>x, x</I>)
|
|
|
357 |
<I> arg2</I>: EXP INTEGER(<I>v</I>)
|
|
|
358 |
-> EXP OFFSET(<I>x, x</I>)
|
|
|
359 |
</PRE>
|
|
|
360 |
and using add_to_ptr with a pointer expression giving the base of
|
|
|
361 |
the array with the resulting OFFSET.<P>
|
|
|
362 |
<A NAME=S35>
|
|
|
363 |
<H3>4.4.3. OFFSET ordering and representation</H3>
|
|
|
364 |
There is an ordering defined on OFFSETs with the same alignment qualifiers,
|
|
|
365 |
as given by offset_test and offset_max having properties like:<P>
|
|
|
366 |
<PRE>
|
|
|
367 |
shape_offset(S) xb3 offset_zero(alignment(S))
|
|
|
368 |
A xb3 B iff offset_max(A,B) = A
|
|
|
369 |
offset_add(A, B) xb3 A where B xb3 offset_zero(some compatible alignment)
|
|
|
370 |
</PRE>
|
|
|
371 |
In most machines, OFFSETs would be represented as single integer values
|
|
|
372 |
with the OFFSET ordering corresponding to simple integer ordering.
|
|
|
373 |
The offset_add constructor just translates to simple addition with
|
|
|
374 |
offset_zero as 0 with similar correspondences for the other offset
|
|
|
375 |
constructors. You might well ask why TDF does not simply use integers
|
|
|
376 |
for offsets, instead of introducing the rather complex OFFSET SHAPE.
|
|
|
377 |
The reasons are two-fold. First, following the OFFSET arithmetic rules
|
|
|
378 |
concerned with the ALIGNMENT qualifiers will ensure that one never
|
|
|
379 |
extracts a value from a pointer with the wrong alignment by, for example,
|
|
|
380 |
applying contents to an add_to_pointer. This frees TDF from having
|
|
|
381 |
to define the effect of strange operations like forming a float by
|
|
|
382 |
taking the contents of a pointer to a character which may be mis-aligned
|
|
|
383 |
with respect to floats - a heavy operation on most processors. The
|
|
|
384 |
second reason is quite simple; there are machines which cannot represent
|
|
|
385 |
OFFSETs by a single integer value.<P>
|
|
|
386 |
The iAPX-432 is a fairly extreme example of such a machine; it is
|
|
|
387 |
a "capability" machine which must segregate pointer values
|
|
|
388 |
and non-pointer values into different spaces. On this machine a value
|
|
|
389 |
of SHAPE POINTER({<I>pointer</I>, int}) (e.g. a pointer to a structure
|
|
|
390 |
containing both integers and pointers) could have two components;
|
|
|
391 |
one referring to the pointers and another to the integers. In general,
|
|
|
392 |
offsets from this pointer would also have two components, one to pick
|
|
|
393 |
out any pointer values and the other the integer values. This would
|
|
|
394 |
obviously be the case if the original POINTER referred to an array
|
|
|
395 |
of structures containing both pointers and integers; an offset to
|
|
|
396 |
an element of the array would have SHAPE OFFSET({<I>pointer</I>, int},{<I>pointer
|
|
|
397 |
</I>, int}); both elements of the offset would have to be used as
|
|
|
398 |
displacements to the corresponding elements of the pointer to extract
|
|
|
399 |
the structure element. The OFFSET ordering is now given by the comparison
|
|
|
400 |
of both displacements. Using this method, one finds that pointers
|
|
|
401 |
in store to non-pointer alignments are two words in different blocks
|
|
|
402 |
and pointers to pointer-alignments are four words, two in one block
|
|
|
403 |
and two in another. This sounds a very unwieldy machine compared to
|
|
|
404 |
normal machines with linear addressing. However, who knows what similar
|
|
|
405 |
strange machines will appear in future; the basic conflicts between
|
|
|
406 |
security, integrity and flexibility that the iAPX-432 sought to resolve
|
|
|
407 |
are still with us. For more on the modelling of pointers and offsets
|
|
|
408 |
see <A HREF="guide15.html#0">section 13 on page 56</A>.<P>
|
|
|
409 |
<A NAME=S36>
|
|
|
410 |
<HR><H2>4.5. BITFIELD alignments</H2>
|
|
|
411 |
Even in standard machines, one finds that the size of a pointer may
|
|
|
412 |
depend on the alignment of the data pointed at. Most machines do not
|
|
|
413 |
allow one to construct pointers to bits with the same facility as
|
|
|
414 |
other alignments. This usually means that pointers in memory to BITFIELD
|
|
|
415 |
VARIETYs must be implemented as two words with an address and bit
|
|
|
416 |
displacement. One might imagine that a translator could implement
|
|
|
417 |
BITFIELD alignments so that they are the same as the smallest natural
|
|
|
418 |
alignment of the machine and avoid the bit displacement, but this
|
|
|
419 |
is not the intention of the definition. On any machine for which it
|
|
|
420 |
is meaningful, the alignment of a BITFIELD must be one bit; in other
|
|
|
421 |
words successive BITFIELDs are butted together with no padding bits
|
|
|
422 |
<A NAME=footnote73 HREF="footnote.html#73">*</A>. Within the limits
|
|
|
423 |
of what one can extract from BITFIELDs, namely INTEGER VARIETYs, this
|
|
|
424 |
is how one should implement non-standard alignments, perhaps in constructing
|
|
|
425 |
data, such as protocols, for exchange between machines. One could
|
|
|
426 |
implement some Ada representational statements in this way; certainly
|
|
|
427 |
the most commonly used ones.<P>
|
|
|
428 |
TDF Version 3.0 does not allow one to construct a pointer of SHAPE
|
|
|
429 |
POINTER(b) where b consists entirely of bitfield alignments; this
|
|
|
430 |
relieves the translators of the burden of doing general bit-addressing.
|
|
|
431 |
Of course, this simply shifts the burden to the producer. If the high
|
|
|
432 |
level language requires to construct a pointer to an arbitrary bit
|
|
|
433 |
position, then the producer is required to represent such a pointer
|
|
|
434 |
as a pair consisting of pointer to some alignment including the required
|
|
|
435 |
bitfield and an offset from this alignment to the bitfield. For example,
|
|
|
436 |
Ada may require the construction of a pointer to a boolean for use
|
|
|
437 |
as the parameter to a procedure; the SHAPE of the rep resentation
|
|
|
438 |
of this Ada pointer could be a COMPOUND formed from a POINTER({x,b})
|
|
|
439 |
and an OFFSET({x, b}, b) where b is the alignment given by a 1 bit
|
|
|
440 |
alignment. To access the boolean, the producer would use the elements
|
|
|
441 |
of this pair as arguements to bitfield_assign and bitfield_contents
|
|
|
442 |
(<A HREF="guide9.html#16">Assigning and extracting bitfields on page
|
|
|
443 |
39</A>.).<P>
|
|
|
444 |
<HR>
|
|
|
445 |
<P><I>Part of the <A HREF="../index.html">TenDRA Web</A>.<BR>Crown
|
|
|
446 |
Copyright © 1998.</I></P>
|
|
|
447 |
</BODY>
|
|
|
448 |
</HTML>
|