Recent

Author Topic: enumeration size in bitpacked records  (Read 5310 times)

440bx

  • Hero Member
  • *****
  • Posts: 3921
enumeration size in bitpacked records
« on: October 23, 2021, 06:27:24 am »
Hello,

I am getting a different size than expected in bitpacked records that contain enumerated types.  Consider the following sample program:
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2.  
  3.  
  4. {$ifdef FPC}
  5.   {$MODESWITCH NESTEDCOMMENTS OFF}
  6. {$endif}
  7.  
  8.  
  9. {$MINENUMSIZE     4}
  10.  
  11. {$TYPEDADDRESS   ON}
  12.  
  13. {$LONGSTRINGS    OFF}
  14.  
  15.  
  16. program _BitpEnumeration;
  17.  
  18. type
  19.    _1bit     = 0 ..        $1;
  20.  
  21.   _30bits    = 0 .. $3FFFFFFF;
  22.   _31bits    = 0 .. $7FFFFFFF;
  23.  
  24.  
  25. type
  26.   { _THREAD_UMS_INFORMATION_COMMAND                                           }
  27.  
  28.   PTHREAD_UMS_INFORMATION_COMMAND = ^TTHREAD_UMS_INFORMATION_COMMAND;
  29.   TTHREAD_UMS_INFORMATION_COMMAND =
  30.   (
  31.    {   0    0 } UmsInformationCommandInvalid,
  32.    {   1    1 } UmsInformationCommandAttach,
  33.    {   2    2 } UmsInformationCommandDetach,
  34.    {   3    3 } UmsInformationCommandQuery
  35.   );
  36.  
  37.  
  38. type
  39.   PTHREAD_UMS_INFORMATION = ^TTHREAD_UMS_INFORMATION;
  40.   TTHREAD_UMS_INFORMATION = {$ifdef FPC} bitpacked {$endif} record
  41.     Command                   : TTHREAD_UMS_INFORMATION_COMMAND;    { 4 }
  42.     CompletionList            : pointer;                            { 4 }
  43.     UmsContext                : pointer;                            { 4 }
  44.  
  45.     case integer of
  46.       1 : (
  47.            Flags                : DWORD;                            { 4 }
  48.           );
  49.  
  50.       {$ifdef FPC}
  51.       2 : (
  52.            IsUmsSchedulerThread :  _1bit;
  53.            IsUmsWorkerThread    :  _1bit;
  54.            SpareBits            : _30bits;
  55.           );
  56.       {$endif}
  57.   end;
  58.  
  59.  
  60. type
  61.   PTHREAD_UMS_INFORMATION2 = ^TTHREAD_UMS_INFORMATION2;
  62.   TTHREAD_UMS_INFORMATION2 = record
  63.     Command                   : TTHREAD_UMS_INFORMATION_COMMAND;    { 4 }
  64.     CompletionList            : pointer;                            { 4 }
  65.     UmsContext                : pointer;                            { 4 }
  66.  
  67.     case integer of
  68.       1 : (
  69.            Flags              : DWORD;                              { 4 }
  70.           );
  71.  
  72.       {$ifdef FPC}
  73.       2 : (
  74.            BitFlags           : bitpacked record
  75.              IsUmsSchedulerThread :  _1bit;
  76.              IsUmsWorkerThread    :  _1bit;
  77.              SpareBits            : _30bits;
  78.            end;
  79.           );
  80.       {$endif}
  81.   end;
  82.  
  83.  
  84. begin
  85.   writeln;
  86.   writeln;
  87.  
  88.  
  89.   writeln(' sizeof TTHREAD_UMS_INFORMATION  : ', sizeof(TTHREAD_UMS_INFORMATION));
  90.   writeln(' sizeof TTHREAD_UMS_INFORMATION2 : ', sizeof(TTHREAD_UMS_INFORMATION2));
  91.  
  92.   writeln;
  93.   writeln;
  94.   writeln('press ENTER/RETURN to end this program');
  95.   readln;
  96. end.
The output size of the first structure is 13 instead of the expected size of 16. 

Changing the structure definition to exclude the enumeration from the bitpacked scope results in the expected size but this requires naming the group of bits, doing that makes it different than the original C definition.

Is there a way to have the "Command" enumerated field occupy 4 bytes without having to change the scope of the bitpacked modifier ? (hopefully leaving it defined as an enumeration and not have to resort to define it as a DWORD)

It seems to me that the incorrect size of the first structure is a bug but, since I am using an older version of the compiler and, I don't know if it happens in the current version, I haven't reported it.

Thank you for your help.


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: enumeration size in bitpacked records
« Reply #1 on: October 24, 2021, 09:23:30 pm »
Is there a way to have the "Command" enumerated field occupy 4 bytes without having to change the scope of the bitpacked modifier ?
Code: Pascal  [Select][+][-]
  1.   TTHREAD_UMS_INFORMATION3 = bitpacked record
  2.   case Byte of
  3.     1:
  4.       (
  5.         DontUseThisFieldToAccessDataInRecordItIsOnlyByteFiller: DWORD;
  6.         CompletionList: Pointer;
  7.         UmsContext: Pointer;
  8.         case Byte of
  9.           1: (Flags: DWORD);
  10.           2:
  11.             (
  12.               IsUmsSchedulerThread: _1bit;
  13.               IsUmsWorkerThread: _1bit;
  14.               SpareBits: _30bits
  15.             );
  16.       );
  17.     2: (Command: TTHREAD_UMS_INFORMATION_COMMAND);
  18.   end;

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: enumeration size in bitpacked records
« Reply #2 on: October 24, 2021, 10:13:23 pm »


Thank you Serge.  That's a good solution.



@Jamie,

I still think this is a bug in the compiler because the compiler is being explicitly told to use 4 bytes (DWORD) _minimum_ for the enumeration.  Enumerated types are not supposed to be bitpacked and I haven't seen the documentation stating anywhere they are susceptible to bitpacking.

That said, thank you for your input.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018