[M3devel] what does it mean to read a UINT8?
Rodney M. Bates
rodney_bates at lcwb.coop
Sun Sep 22 19:04:30 CEST 2013
This touches on a mess I have been bothered by for a long time and was getting
ready to write about anyway, after spending some time inside pickles and
As I have noted several times on this list, BITS n FOR T, according to the language,
has an effect *only when used for an array element or record or object field*.
If used for a scalar, the BITS n FOR has no effect. So a compiler is free to
put scalars of packed type in anything with at least n bits, including, most
plausibly, a whole native word. This could well be an advantage on many targets.
But we have bit-twiddling code all over that makes assumptions about what the
compiler will do that are neither specified by the language nor documented by
our compiler. Presumably, most have at least been experimentally verified for
selected cases. But even for a single and unchanging compiler, that is not reliable.
People have, sometimes, wrapped a packed field inside a record to get around this,
then used an ADR on the field. But we have no rules about how the alignment of
a packed field nor of a whole record containing packed fields, so for
VAR V: RECORD f: BITS 16 FOR [0..16_FFFF] END
ADR(V.f) need not be 16-aligned. For bit counts other than 8, 16, 32, and 64,
it hardly makes sense for a field to have alignment other than 8, and for general
cases, ADR doesn't have any obvious or predictable definition. The best I can
think of would be a static error if the compiler couldn't guarantee it would be
at least a multiple of 8.
Or, for example, if UINT8 is BITS 8 FOR [0..16_FF], do we know that
BITSIZE(LOOPHOLE(x,UNTRACED REF UINT8)^)= 8?
What if x is ADR(AScalarVariable), and the scalar has been allocated 64 bits?
Or, x could be ADR(V.f)? The meaning of UNTRACED REF UINT16 can't depend on
this. Is there some kind of consistency here? Is it endian-dependent? What
about the alignment, assumed and/or ensured of these addresses?
We have lots of code that just assumes something the writer thought reasonable,
but it is far from consistently clear what the reasonable interpretation would
be. It would be tricky to get right in general, but we could use some rules,
either in the language itself or compiler supplementary documentation, spelling
this stuff out.
On 09/21/2013 10:58 PM, Jay K wrote:
> It appears that this code:
> b := LOOPHOLE(used + info.RegionSize - 1, UNTRACED REF UINT8)^;
> generates a read of a full INTEGER, in this case 8 bytes.
> Now, I know, I could change it to:
> b := LOOPHOLE(used + info.RegionSize - BYTESIZE(INTEGER), UNTRACED REF INTEGER)^;
> What were my expectations wrong in the first place?
> This code was part of getting stack bounds and it'd read
> the end of the stack to try to ensure it was correct.
> I removed it.
> 0:000> g
> (15bc.116c): Access violation - code c0000005 (first chance)
> First chance exceptions are reported before any exception handling.
> This exception may be expected and handled.
> *** WARNING: Unable to verify checksum for cm3.exe
> 00000001`3fdf1a78 488b48ff mov rcx,qword ptr [rax-1] ds:00000000`0028
> 0:000> r rax
> 0:000> r rsp
> 0:000> dv
> start_L_275 = 0x00000000`00338de0
> end_L_276 = 0x00000000`00338de8
> L_501_L_502 = 0n48
> used_L_272 = 0x00000000`0028f000
> available_L_273 = 0x00000000`00190000 "--- memory read error at address 0x000000
> 00`00190000 ---"
> b_L_274 = 0x30 '0'
> a_L_271 = 0n48
> info_L_270 = struct TA669C7A1
> _frame = struct ThreadWin32__GetStackBounds_Frame_t
> 0:000> ?? info_L_270
> struct TA669C7A1
> +0x000 BaseAddress : 0x00000000`0028f000 "0???"
> +0x008 AllocationBase : 0x00000000`00190000 "--- memory read error at addr
> ess 0x00000000`00190000 ---"
> +0x010 AllocationProtect : 4
> +0x014 L_7 :  ""
> +0x018 RegionSize : 0n4096
> +0x020 State : 0x1000
> +0x024 Protect : 4
> +0x028 Type : 0x20000
> +0x02c L_8 :  ""
> 0:000> q
> - Jay
More information about the M3devel