[M3devel] alignment in X.i3?

Rodney M. Bates rodney_bates at lcwb.coop
Thu Jun 24 23:44:58 CEST 2010



Jay K wrote:
> While I did this to myself by accident, there is a "real" question buried here.
> I forgot I was experimenting with:
> 
> Index: 32BITS/BasicCtypes.i3
> ===================================================================
> RCS file: /usr/cvs/cm3/m3-libs/m3core/src/C/32BITS/BasicCtypes.i3,v
> retrieving revision 1.13
> diff -u -r1.13 BasicCtypes.i3
> --- 32BITS/BasicCtypes.i3    11 Feb 2010 12:24:33 -0000    1.13
> +++ 32BITS/BasicCtypes.i3    24 Jun 2010 09:54:01 -0000
> @@ -11,15 +11,15 @@
>  
>  TYPE
>    (* the four signed integer types *)
> -  signed_char        = [-16_7f-1 .. 16_7f];
> -  short_int          = [-16_7fff-1 .. 16_7fff];
> -  int                = [-16_7fffffff-1 .. 16_7fffffff];
> -  long_int           = [-16_7fffffff-1 .. 16_7fffffff];
> -  long_long          = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL];
> +  signed_char        = BITS 8 FOR [-16_7f-1 .. 16_7f];
> +  short_int          = BITS 16 FOR [-16_7fff-1 .. 16_7fff];
> +  int                = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff];
> +  long_int           = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff];
> +  long_long          = BITS 64 FOR [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL];

This is a block I've been around before.  Packed (BITS) types are not what many
people seem to think.

1) They don't do anything at all for whole variables, parameters, etc. (Except
    create some non-assignabilities).  They *only* apply when used as the type of
    a record field, object field, or array element.

2) When they do apply, they require the compiler not only to use exactly the given
    number of bits, but also, to *add no padding* ahead of the field/element.

If 2) conflicts with normal alignment rules, or any other discretionary rules
the compiler uses (e.g., fields/elements cannot cross native word boundaries),
it may/must refuse.  And this means what you really need will vary from one
record/array to another.  This whole system  is really intended
only for explicit control of bit layouts of records and arrays.

I have finally gotten it that I never want to use BITS in a named type that
could be used in more than one place.  Instead, I always put the BITS in as
an anonymous part of the type of the field or element.  This avoids this
problem.  E.g.:

TYPE T = ...;
...
TYPE R = RECORD
            ...
            F: BITS 8 FOR T;
            ...
          END;

I really think this kind of explicit layout control is, for the most part,
incompatible with writing portable code.  Certainly, the original language
designers seem to have thought so.

It does raise another question.  To use LOOPHOLE, you have to know that the
BITSIZE values of the two types match up.  And what those are is implementation-
dependent.  So if, e.g., BITS 16 FOR [0..16_FF] must occupy 16 bits when a
field of a record, but the compiler might likely give it only 8 when an
autonomous variable (as it does now for [0..16_FF]), what is BITSIZE of
this type?  And I don't just mean what does the current implementation
do here.  I don't believe the language specifies this.

>  
>    (* the four unsigned integer types *)
> -  unsigned_char      = [16_0 .. 16_ff];
> -  unsigned_short_int = [16_0 .. 16_ffff];
> +  unsigned_char      = BITS 8 FOR [16_0 .. 16_ff];
> +  unsigned_short_int = BITS 16 FOR [16_0 .. 16_ffff];
>    unsigned_int       = Word.T;
>    unsigned_long_int  = Word.T;
>    unsigned_long_long = Long.T;
> @@ -33,5 +33,3 @@
>    char               = signed_char;
>  
>  END BasicCtypes.
> -
> -
> Index: 64BITS/BasicCtypes.i3
> ===================================================================
> RCS file: /usr/cvs/cm3/m3-libs/m3core/src/C/64BITS/BasicCtypes.i3,v
> retrieving revision 1.8
> diff -u -r1.8 BasicCtypes.i3
> --- 64BITS/BasicCtypes.i3    13 Apr 2008 19:44:02 -0000    1.8
> +++ 64BITS/BasicCtypes.i3    24 Jun 2010 09:54:01 -0000
> @@ -11,16 +11,16 @@
>  
>  TYPE
>    (* the four signed integer types *)
> -  signed_char        = [-16_7f-1 .. 16_7f];
> -  short_int          = [-16_7fff-1 .. 16_7fff];
> -  int                = [-16_7fffffff-1 .. 16_7fffffff];
> -  long_int           = [-16_7fffffffffffffff -1  .. 16_7fffffffffffffff ];
> -  long_long          = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL];
> +  signed_char        = BITS 8 FOR [-16_7f-1 .. 16_7f];
> +  short_int          = BITS 16 FOR [-16_7fff-1 .. 16_7fff];
> +  int                = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff];
> +  long_int           = BITS 64 FOR [-16_7fffffffffffffff -1  .. 16_7fffffffffffffff ];
> +  long_long          = BITS 64 FOR [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL];
>  
>    (* the four unsigned integer types *)
> -  unsigned_char      = [16_0 .. 16_ff];
> -  unsigned_short_int = [16_0 .. 16_ffff];
> -  unsigned_int       = [16_0 .. 16_ffffffff];
> +  unsigned_char      = BITS 8 FOR [16_0 .. 16_ff];
> +  unsigned_short_int = BITS 16 FOR [16_0 .. 16_ffff];
> +  unsigned_int       = BITS 32 FOR [16_0 .. 16_ffffffff];
>    unsigned_long_int  = Word.T;
>    unsigned_long_long = Long.T;
>  
> @@ -33,5 +33,3 @@
>    char               = signed_char;
>  
>  END BasicCtypes.
> 
> and then I think there is a "hole" here:
> 
>   Int = int; Short = short; Long = long; Char = char;
>   Bool      = Int;
> 
>   XMotionEvent = RECORD
>      type: Int;             (* of event *)
> 
> (* 32bits padding for alignment here likely *)
> 
>      serial: unsigned_long; (* # of last request processed by server *)
>      send_event: Bool;      (* true if this came from a SendEvent request *)
> 
> (* 32bits padding for alignment here likely also *)
> 
> 
>      display: DisplayStar;  (* Display the event was read from *)
>      window: Window;        (* "event" window reported relative to *)
>      root: Window;          (* root window that the event occured on *)
>      subwindow: Window;     (* child window *)
>      time: Time;            (* milliseconds *)
>      x, y: Int;             (* pointer x, y coordinates in event window *)
>      x_root, y_root: Int;   (* coordinates relative to root *)
>      state: unsigned_int;   (* key or button mask *)
>      is_hint: Char;         (* detail *)
>      same_screen: Bool      (* same screen flag *)
>   END;
> 
> 
> Am I write to be concerned with this cloning of header files?
> Modula-3 probably inserts the holes/padding just like the C compiler probably inserts the holes/padding,
> but it an area that deserves some extra close checking?
> 
> 
> Like by passing the size of the record to some C that compares it to the size of the C type?
> Or more aggressively the size/offset of each field?
> 
> 
> Or maybe introducing a "more portable" C layer, where the "smallest" fields is an INTEGER or a LONGINT?
> 
> 
> Or maybe soon someone else will apply some swig-like automation here, and generate the checks?
> 
> 
>  - Jay
> 
> 
> ----------------------------------------
>> From: jay.krell at cornell.edu
>> To: m3devel at elegosoft.com
>> Date: Thu, 24 Jun 2010 09:46:27 +0000
>> Subject: [M3devel] alignment in X.i3?
>>
>>
>> I don't suppose anyone else is seeing this?
>>
>> -- building in AMD64_DARWIN ---
>>
>> ignoring ../src/m3overrides
>>
>> new source -> compiling XMachine.i3
>> new source -> compiling X.i3
>> "../src/Common/X.i3", line 1376: Could not find a legal alignment for the packed type.
>> "../src/Common/X.i3", line 1010: Could not find a legal alignment for the packed type.
>> 2 errors encountered
>> new source -> compiling Xatom.i3
>> new source -> compiling Xmbuf.i3
>>
>> I'll keep digging..
>>  - Jay
>>
>>
>  		 	   		  



More information about the M3devel mailing list