[M3devel] unaligned record fields?
Jay
jayk123 at hotmail.com
Tue Jun 3 11:34:46 CEST 2008
I have on my machine like:
m3core/src/win32
UINT8 = BITS 8 FOR ...
UINT16 = BITS 16 FOR ...
UINT32 = BITS 32 FOR ...(actually via an edited Cstdint).
This is turning up, as I understand, two sets of problems, one "invented" and easy to fix, one "preexisting" and I don't know how to solve.
"Problem" 1:
structs that require inserting padding to be aligned:
FOO = RECORD
a: UINT16;
b: UINT32;
END;
=> Could not find a legal alignment...
Fixed with:
FOO = RECORD
a: UINT16;
>> padding: UINT16;
b: UINT32;
END;
I think this a good thing, however it definitely might break some code out there -- that is, the problem where I make a breaking change, rebuild all of cm3, fix things up, but that isn't all the Modula-3 code in the world.
Really, this is a good thing. I TEND to think that quiet insertion of padding for alignment is a bad thing, but that it should also by default be an error to declare unaligned fields. Granted, if you are going to share binary files between architectures, you might be forced to quash the error and allow unaligned fields. Really, I'm not sure what the answer is, but I don't think the current way of doing things, in the broader C/C++ world, is correct. It causes too many headaches to be correct. I suspend judgement about Modula-3 out of ignorance. At least I found a way, accidentally, for it trigger errors for things I don't like, but I haven't found a way to let through things that while dubious, are meant to be asis (see problem #2).
Problem 1b:
One record was missing a field! Add that back and the warning goes away. Nice to catch that.
Problem 2:
types that are not "internally" naturally aligned
There are at least of these.
The ??? stuff is not my introducing.
(*??? #pragma pack(2) *) PBITMAPFILEHEADER = UNTRACED REF BITMAPFILEHEADER; LPBITMAPFILEHEADER = UNTRACED REF BITMAPFILEHEADER; BITMAPFILEHEADER = BITS (16_E * 8) FOR RECORD bfType : UINT16; bfSize : UINT32; (* this is not aligned *) bfReserved1: UINT16; bfReserved2: UINT16; bfOffBits : UINT32; (* nor is this *) END; (*??? #pragma pack() *)
(*??? #pragma pack(2) *) PMETAHEADER = UNTRACED REF METAHEADER; LPMETAHEADER = UNTRACED REF METAHEADER; METAHEADER = RECORD mtType : UINT16; mtHeaderSize : UINT16; mtVersion : UINT16; mtSize : UINT32; (* This is not aligned. *) mtNoObjects : UINT16; mtMaxRecord : UINT32; (This is ok. *) mtNoParameters: UINT16; END;
(*??? #pragma pack() *)
I assume/fear that Modula-3 was not previously laying these types out correctly.
NOTE that I don't see evidence of them being really used, so this isn't likely related to "bitmap problems".
How does one declare these?
I think the best I can do for now is change the unaligned fields to be arrays of bytes and hope nobody uses them.
These two programs confirm the bug:
UNSAFE MODULE A EXPORTS Main;
IMPORT WinGDI;IMPORT IO;
VARa: WinGDI.BITMAPFILEHEADER;b: WinGDI.METAHEADER;
PROCEDURE F1(a,b: ADDRESS) =BEGIN IO.PutInt(b - a); IO.Put("\n");END F1;
BEGIN F1(ADR(a), ADR(a.bfSize)); F1(ADR(b), ADR(b.mtSize));
END A.
This prints 4 and 8.
vs.
#include <windows.h>#include <winioctl.h>
ACCEL a;IMAGE_DOS_HEADER b;TOKEN_STATISTICS c;SE_IMPERSONATION_STATE d;COMSTAT e;BITMAPFILEHEADER f;METAHEADER g;FORMAT_PARAMETERS h;FORMAT_EX_PARAMETERS i;DISK_GEOMETRY j;
int main(){ return 0;}
look at it in a debugger, should be 2 and 6:
0:000> ?? fstruct tagBITMAPFILEHEADER +0x000 bfType : 0 +0x002 bfSize : 0 +0x006 bfReserved1 : 0 +0x008 bfReserved2 : 0 +0x00a bfOffBits : 00:000> ?? gstruct tagMETAHEADER +0x000 mtType : 0 +0x002 mtHeaderSize : 0 +0x004 mtVersion : 0 +0x006 mtSize : 0 +0x00a mtNoObjects : 0 +0x00c mtMaxRecord : 0 +0x010 mtNoParameters : 0
Btw, regarding struct stat, I did write Modula-3 code to form a string that represents all the sizes/offsets of the fields.
We could write little tests that does that, and similar C code, and then compares the strings for equality.
And/or invest a little more in C code that prints out correct Modula .i3 files, driven by a bunch of data with sizeof and offsetof, including sorting by offsetof, and checking for padding by adding offsetof+sizeof.
It kind of looks like "lazyalign" is the answer, but I know this was brought up as "broken" recently, but that "Darwin (MacOSX)" needs it. I didn't follow the discusion closely. Lazyalign maybe is exactly the thing, as long as it is applicable on a type-by-type or field-by-field basis.
There are some <* UNALIGNED *> and <* PRAGMA UNALIGNED *> but I see no implementation of these. I think they are being silently ignored.
??
- Jay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20080603/b8867d29/attachment-0001.html>
More information about the M3devel
mailing list