memorylayouts padding, jextract C_BOOL

Michael Zucchi notzed at gmail.com
Fri Jan 31 08:08:07 UTC 2020


Hi guys,

I just noticed jextract turns a 'char' into a C_BOOL.  I suppose it 
doesn't make a difference but it just looks wrong.  _Bool exists in C99+ 
but an 8 bit int is more likely to be a int8_t or char than _Bool 
(imo).  I think the whole idea of 'c named types' just isn't adding any 
value and they should all be basically the "stdint.h" types with the 
platform byte ordering, but it's no big deal.  The scoped allocator sort 
of muddies it further by using java types, but at least they have 
defined sizes which map to fixed stdint types.

Also, this:

struct foo {
     char x;
     int v __attribute__ ((aligned(8)));
};

generates:

     public static final MemoryLayout foo$LAYOUT = MemoryLayout.ofStruct(
         MemoryLayouts.SysV.C_BOOL.withName("x"),
         MemoryLayout.ofPaddingBits(56),
         MemoryLayouts.SysV.C_INT.withName("v"),
         MemoryLayout.ofPaddingBits(32)
     ).withName("foo");

which breaks at this:

     MemorySegment seg = MemorySegment.allocateNative(foo);

Exception in thread "main" java.lang.IllegalArgumentException: Invalid 
alignment constraint : 7
         at 
jdk.incubator.foreign/jdk.incubator.foreign.MemorySegment.allocateNative(MemorySegment.java:422)
         at 
jdk.incubator.foreign/jdk.incubator.foreign.MemorySegment.allocateNative(MemorySegment.java:360)
         at notzed...

This is because MemoryLayou8ts.ofPaddingBits(X) creates a padding of "X" 
bits with "X" bit alignment, which is just not likely to work in the 
general case.

I hit this trying to use padding to skip private/unimportant fields (by 
using large bit paddings) and then recreated the problem using jextract.

Given it's specifically padding which almost by definition isn't 
aligned, maybe padding alignment bits should always just be 8?  Or just 
provide the alignment argument in MemoryLayout.ofPaddingBits() so you 
don't have to call.withBitAligment(8) every time (this currently works).

 From .withBitAlignment() javadoc it seems the alignment has to be >=8 
and 2^n so that means the MemoryLayouts.ofPaddingBits() implementation 
is incorrect in passing X as the alignment to new PaddingLayout().

     /**
      * Creates a new layout which features the desired alignment 
constraint.
      *
      * @param bitAlignment the layout alignment constraint, expressed 
in bits.
      * @return a new layout which is the same as this layout, except 
for the alignment constraint associated to it.
      * @throws IllegalArgumentException if {@code bitAlignment} is not 
a power of two, or if it's less than than 8.
      */
     MemoryLayout withBitAlignment(long bitAlignment);

But other functions say it can be < 8 bits so it's a little messy here.  
If it's intended for describing bitfields well it doesn't really fit the 
api constraints, and for bitfields you'd want a bit alignment of 1 by 
definition.

Also note that this however /does/ work:

struct foo {
     char x;
     long v;
};

     public static final MemoryLayout foo$LAYOUT = MemoryLayout.ofStruct(
         MemoryLayouts.SysV.C_BOOL.withName("x"),
         MemoryLayout.ofPaddingBits(56),
         MemoryLayouts.SysV.C_LONG.withName("v"),
     ).withName("foo");

Which doesn't make any sense if the padding alignment really was 56??

Cheers,
  Z






More information about the panama-dev mailing list