--- old/src/jdk.jextract/share/classes/com/sun/tools/jextract/tree/LayoutUtils.java 2019-01-22 18:27:12.000000000 +0530 +++ new/src/jdk.jextract/share/classes/com/sun/tools/jextract/tree/LayoutUtils.java 2019-01-22 18:27:11.000000000 +0530 @@ -218,7 +218,7 @@ Stream fieldTypes = cu.children() .filter(cx -> cx.isAnonymousStruct() || cx.kind() == CursorKind.FieldDecl); List fieldLayouts = new ArrayList<>(); - int pendingBitfieldStart = -1; + List bitfieldLayouts = null; long actualSize = 0L; for (Cursor c : fieldTypes.collect(Collectors.toList())) { boolean isBitfield = c.isBitField(); @@ -228,22 +228,31 @@ if (isUnion) { throw new IllegalStateException("No padding in union elements!"); } - fieldLayouts.add(Padding.of(expectedOffset - offset)); + Layout padding = Padding.of(expectedOffset - offset); + if (bitfieldLayouts != null) { + bitfieldLayouts.add(padding); + } else { + fieldLayouts.add(padding); + } actualSize += (expectedOffset - offset); offset = expectedOffset; } - if (isBitfield && !isUnion && pendingBitfieldStart == -1) { - pendingBitfieldStart = fieldLayouts.size(); + if (isBitfield && !isUnion && bitfieldLayouts == null) { + bitfieldLayouts = new ArrayList<>(); } - if (!isBitfield && pendingBitfieldStart >= 0) { + if (!isBitfield && bitfieldLayouts != null) { //emit/replace bitfields - replaceBitfields(fieldLayouts, pendingBitfieldStart); - pendingBitfieldStart = -1; + fieldLayouts.addAll(convertBitfields(bitfieldLayouts)); + bitfieldLayouts = null; } Layout fieldLayout = (c.isAnonymousStruct()) ? getRecordLayoutInternal(offset, parent, c.type(), fieldMapper) : fieldLayout(isUnion, c, fieldMapper); - fieldLayouts.add(fieldLayout); + if (bitfieldLayouts != null) { + bitfieldLayouts.add(fieldLayout); + } else { + fieldLayouts.add(fieldLayout); + } long size = fieldSize(isUnion, c); if (isUnion) { actualSize = Math.max(actualSize, size); @@ -254,11 +263,17 @@ } long expectedSize = t.size() * 8; if (actualSize < expectedSize) { - fieldLayouts.add(Padding.of(expectedSize - actualSize)); + Layout padding = Padding.of(expectedSize - actualSize); + if (bitfieldLayouts != null) { + bitfieldLayouts.add(padding); + } else { + fieldLayouts.add(padding); + } } - if (pendingBitfieldStart >= 0) { + if (bitfieldLayouts != null) { //emit/replace bitfields - replaceBitfields(fieldLayouts, pendingBitfieldStart); + fieldLayouts.addAll(convertBitfields(bitfieldLayouts)); + bitfieldLayouts = null; } Layout[] fields = fieldLayouts.toArray(new Layout[0]); Group g = isUnion ? @@ -290,17 +305,15 @@ } } - private static void replaceBitfields(List layouts, int pendingBitfieldsStart) { + private static List convertBitfields(List layouts) { long storageSize = storageSize(layouts); long offset = 0L; List newFields = new ArrayList<>(); List pendingFields = new ArrayList<>(); - while (layouts.size() > pendingBitfieldsStart) { - Layout l = layouts.remove(pendingBitfieldsStart); + for (Layout l : layouts) { offset += l.bitsSize(); pendingFields.add(l); - if (!pendingFields.isEmpty() && - offset == storageSize) { + if (!pendingFields.isEmpty() && offset == storageSize) { //emit new newFields.add(bitfield(Value.ofUnsignedInt(storageSize), pendingFields)); pendingFields.clear(); @@ -313,7 +326,7 @@ throw new IllegalStateException("Partially used storage unit"); } //add back new fields - newFields.forEach(layouts::add); + return newFields; } private static long storageSize(List layouts) { --- old/test/jdk/com/sun/tools/jextract/bitfields.h 2019-01-22 18:27:14.000000000 +0530 +++ new/test/jdk/com/sun/tools/jextract/bitfields.h 2019-01-22 18:27:14.000000000 +0530 @@ -60,3 +60,19 @@ char c1 : 4; int i : 20; }; + +struct bitfields7 { + unsigned int x; + unsigned int a:15, pad:17; +}; + +struct Point { + int i; + int j; +}; + +struct bitfields8 { + struct Point p; + int x:12; + int y:2; +}; --- old/test/jdk/com/sun/tools/jextract/compare/bitfields.java 2019-01-22 18:27:16.000000000 +0530 +++ new/test/jdk/com/sun/tools/jextract/compare/bitfields.java 2019-01-22 18:27:16.000000000 +0530 @@ -194,4 +194,64 @@ @NativeSetter("i") void i$set(int value); } + + @NativeStruct("[" + + "u32(x)" + + "u32=[u15(a)u17(pad)]" + + "](bitfields7)") + public interface bitfields7 extends Struct { + @NativeGetter("x") + int x$get(); + @NativeSetter("x") + void x$set(int value); + @NativeAddressof("x") + Pointer x$ptr(); + @NativeGetter("a") + int a$get(); + @NativeSetter("a") + void a$set(int value); + @NativeGetter("pad") + int pad$get(); + @NativeSetter("pad") + void pad$set(int value); + } + + @NativeStruct("[" + + "i32(i)" + + "i32(j)" + + "](Point)") + public interface Point extends Struct { + @NativeGetter("i") + int i$get(); + @NativeSetter("i") + void i$set(int value); + @NativeAddressof("i") + Pointer i$ptr(); + @NativeGetter("j") + int j$get(); + @NativeSetter("j") + void j$set(int value); + @NativeAddressof("j") + Pointer j$ptr(); + } + + @NativeStruct("[" + + "${Point}(p)" + + "u32=[i12(x)i2(y)x18]" + + "](bitfields8)") + public interface bitfields8 extends Struct { + @NativeGetter("p") + Point p$get(); + @NativeSetter("p") + void p$set(Point value); + Pointer p$ptr(); + @NativeGetter("x") + int x$get(); + @NativeSetter("x") + void x$set(int value); + @NativeGetter("y") + int y$get(); + @NativeSetter("y") + void y$set(int value); + } } --- old/test/jdk/com/sun/tools/jextract/compare/windows/bitfields.java 2019-01-22 18:27:18.000000000 +0530 +++ new/test/jdk/com/sun/tools/jextract/compare/windows/bitfields.java 2019-01-22 18:27:18.000000000 +0530 @@ -238,4 +238,64 @@ @NativeSetter("i") void i$set(int value); } + + @NativeStruct("[" + + "u32(x)" + + "u32=[u15(a)u17(pad)]" + + "](bitfields7)") + public interface bitfields7 extends Struct { + @NativeGetter("x") + int x$get(); + @NativeSetter("x") + void x$set(int value); + @NativeAddressof("x") + Pointer x$ptr(); + @NativeGetter("a") + int a$get(); + @NativeSetter("a") + void a$set(int value); + @NativeGetter("pad") + int pad$get(); + @NativeSetter("pad") + void pad$set(int value); + } + + @NativeStruct("[" + + "i32(i)" + + "i32(j)" + + "](Point)") + public interface Point extends Struct { + @NativeGetter("i") + int i$get(); + @NativeSetter("i") + void i$set(int value); + @NativeAddressof("i") + Pointer i$ptr(); + @NativeGetter("j") + int j$get(); + @NativeSetter("j") + void j$set(int value); + @NativeAddressof("j") + Pointer j$ptr(); + } + + @NativeStruct("[" + + "${Point}(p)" + + "u32=[i12(x)i2(y)x18]" + + "](bitfields8)") + public interface bitfields8 extends Struct { + @NativeGetter("p") + Point p$get(); + @NativeSetter("p") + void p$set(Point value); + Pointer p$ptr(); + @NativeGetter("x") + int x$get(); + @NativeSetter("x") + void x$set(int value); + @NativeGetter("y") + int y$get(); + @NativeSetter("y") + void y$set(int value); + } } --- old/test/jdk/java/foreign/OutOfBoundsTest.java 2019-01-22 18:27:21.000000000 +0530 +++ new/test/jdk/java/foreign/OutOfBoundsTest.java 2019-01-22 18:27:20.000000000 +0530 @@ -41,7 +41,7 @@ import java.foreign.memory.Struct; import java.lang.invoke.MethodHandles; -public class OutOfBoundsTest {xtract +public class OutOfBoundsTest { @NativeHeader public interface OutOfBounds { @@ -79,4 +79,4 @@ s.ptr$set(p); // should throw } } -} \ No newline at end of file +}