Recent

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

440bx

  • Hero Member
  • *****
  • Posts: 2556
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 on Windows 7 64bit.

jamie

  • Hero Member
  • *****
  • Posts: 5020
Re: enumeration size in bitpacked records
« Reply #1 on: October 23, 2021, 09:06:10 pm »
I just put that in here and looked at it. After closer look it seems correct to me.

The first record define you are using a Localized Bitpacked clause that is overriding global settings, to me that is normal.

as for the second one, the bitpacked on the inner record makes no difference because it should fit there anyways.

Take it as you wish but I really don't see a problem, its just localizing the range.

I don't know how the compiler maintains the flags for each ENUM created so I would guess each ENUM does not have a flag to indicate size, it uses the last setting..

 I guess this could cause some upset but indicating a record to be Bitpack means just that, it packed it.

oh well.

EDIT

  I guess the inner record does need a Packing.. that's strange.. I'll test something. BRB.

EDIT2

 Yup, False alarm, I think the compiler is correctly doing it. its just not what you want I suppose.



« Last Edit: October 23, 2021, 09:37:20 pm by jamie »
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 5020
Re: enumeration size in bitpacked records
« Reply #2 on: October 24, 2021, 01:25:08 am »
I see that you were forced to use a Name Tag for your Bitpacked record within the variant record, that just leads to more unnecessary complexity coding.

 I ask or suggested several times for anonymous records within records or variant fields to fix that issue since this is prevalent in other languages.

 C for example have anonymous unions where you can reference an identifier without the additional TAG descriptor.



The only true wisdom is knowing you know nothing

ASerge

  • Hero Member
  • *****
  • Posts: 1887
Re: enumeration size in bitpacked records
« Reply #3 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: 2556
Re: enumeration size in bitpacked records
« Reply #4 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 on Windows 7 64bit.

 

TinyPortal © 2005-2018