Gnat and pragma pack() big surprise


Today I worked on a set of tables used to determine the category of all the Unicode characters as supported by Ada 2005. First I attempted to create that in software using two levels of case, but it quickly became obvious that it would be large and probably inefficient. The result was about 152Kb of nearly only code.

After some thought, it seemed that if I were to create full tables of 256 x 3 bits (768 bits or 96 bytes) as the category can be compressed in that way, then it would generate tables 94 tables of 96 bytes = 9,024 bytes (~8.8Kb). Really cool. So I decided to create a packed array:

type full is array(unsigned_8'range) of character_category;
pragma pack(full);

This looks good in Ada and when you print out the size of a packed array it comes out as 768. Perfect! Unfortunately, the truth is that it is not saved that way in the compiled source. Once I had my 9,024 bytes of tables, the compiled version was about 1.2Mb. Wow! What happened?

The answer is simple, but rather scary: The compiler did NOT compress the data (even though everything is marked as constant) before compiling everything. Instead, in software, it creates the table at run-time. Yes! It creates the 94 tables by hand, packing the bits in assembly language, each time testing to make sure the values are valid for the type...

Needless to say, I will be really careful now a day since the use of pragma pack() is simply terrible (useless) for constants.

Syndicate content