Commit 5f08f50d authored by Kenton Varda's avatar Kenton Varda

Get rid of stupid hacks to allow single-bit structs.

parent dcfd0915
...@@ -294,7 +294,6 @@ TEST(Encoding, InlineStructUnionLayout) { ...@@ -294,7 +294,6 @@ TEST(Encoding, InlineStructUnionLayout) {
initUnion<TestInlineUnions>([](TestInlineUnions::Builder b) {b.setter;}) initUnion<TestInlineUnions>([](TestInlineUnions::Builder b) {b.setter;})
EXPECT_EQ(UnionState({ 0,0,0,0}, -1), INIT_UNION(getUnion0().initF0())); EXPECT_EQ(UnionState({ 0,0,0,0}, -1), INIT_UNION(getUnion0().initF0()));
EXPECT_EQ(UnionState({ 1,0,0,0}, 0), INIT_UNION(getUnion0().initF1().setF(1)));
EXPECT_EQ(UnionState({ 2,0,0,0}, 0), INIT_UNION(getUnion0().initF8().setF0(true))); EXPECT_EQ(UnionState({ 2,0,0,0}, 0), INIT_UNION(getUnion0().initF8().setF0(true)));
EXPECT_EQ(UnionState({ 3,0,0,0}, 0), INIT_UNION(getUnion0().initF16().setF0(1))); EXPECT_EQ(UnionState({ 3,0,0,0}, 0), INIT_UNION(getUnion0().initF16().setF0(1)));
EXPECT_EQ(UnionState({ 4,0,0,0}, 0), INIT_UNION(getUnion0().initF32().setF0(1))); EXPECT_EQ(UnionState({ 4,0,0,0}, 0), INIT_UNION(getUnion0().initF32().setF0(1)));
...@@ -303,7 +302,6 @@ TEST(Encoding, InlineStructUnionLayout) { ...@@ -303,7 +302,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({ 7,0,0,0}, 0), INIT_UNION(getUnion0().initF192().setF0(1))); EXPECT_EQ(UnionState({ 7,0,0,0}, 0), INIT_UNION(getUnion0().initF192().setF0(1)));
EXPECT_EQ(UnionState({ 8,0,0,0}, -1), INIT_UNION(getUnion0().initF0p().initF())); EXPECT_EQ(UnionState({ 8,0,0,0}, -1), INIT_UNION(getUnion0().initF0p().initF()));
EXPECT_EQ(UnionState({ 9,0,0,0}, 0), INIT_UNION(getUnion0().initF1p().initF().setF(1)));
EXPECT_EQ(UnionState({10,0,0,0}, 0), INIT_UNION(getUnion0().initF8p().initF().setF0(true))); EXPECT_EQ(UnionState({10,0,0,0}, 0), INIT_UNION(getUnion0().initF8p().initF().setF0(true)));
EXPECT_EQ(UnionState({11,0,0,0}, 0), INIT_UNION(getUnion0().initF16p().initF().setF0(1))); EXPECT_EQ(UnionState({11,0,0,0}, 0), INIT_UNION(getUnion0().initF16p().initF().setF0(1)));
EXPECT_EQ(UnionState({12,0,0,0}, 0), INIT_UNION(getUnion0().initF32p().initF().setF0(1))); EXPECT_EQ(UnionState({12,0,0,0}, 0), INIT_UNION(getUnion0().initF32p().initF().setF0(1)));
...@@ -312,7 +310,6 @@ TEST(Encoding, InlineStructUnionLayout) { ...@@ -312,7 +310,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({15,0,0,0}, 0), INIT_UNION(getUnion0().initF192p().initF().setF0(1))); EXPECT_EQ(UnionState({15,0,0,0}, 0), INIT_UNION(getUnion0().initF192p().initF().setF0(1)));
EXPECT_EQ(UnionState({ 8,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF0p().setP0("1"))); EXPECT_EQ(UnionState({ 8,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF0p().setP0("1")));
EXPECT_EQ(UnionState({ 9,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF1p().setP0("1")));
EXPECT_EQ(UnionState({10,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF8p().setP0("1"))); EXPECT_EQ(UnionState({10,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF8p().setP0("1")));
EXPECT_EQ(UnionState({11,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF16p().setP0("1"))); EXPECT_EQ(UnionState({11,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF16p().setP0("1")));
EXPECT_EQ(UnionState({12,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF32p().setP0("1"))); EXPECT_EQ(UnionState({12,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF32p().setP0("1")));
...@@ -321,7 +318,6 @@ TEST(Encoding, InlineStructUnionLayout) { ...@@ -321,7 +318,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({15,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF192p().setP0("1"))); EXPECT_EQ(UnionState({15,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF192p().setP0("1")));
EXPECT_EQ(UnionState({0, 0,0,0}, -1), INIT_UNION(getUnion1().initF0())); EXPECT_EQ(UnionState({0, 0,0,0}, -1), INIT_UNION(getUnion1().initF0()));
EXPECT_EQ(UnionState({0, 1,0,0}, 193), INIT_UNION(getUnion1().initF1().setF(1)));
EXPECT_EQ(UnionState({0, 2,0,0}, 200), INIT_UNION(getUnion1().initF8().setF0(true))); EXPECT_EQ(UnionState({0, 2,0,0}, 200), INIT_UNION(getUnion1().initF8().setF0(true)));
EXPECT_EQ(UnionState({0, 3,0,0}, 208), INIT_UNION(getUnion1().initF16().setF0(1))); EXPECT_EQ(UnionState({0, 3,0,0}, 208), INIT_UNION(getUnion1().initF16().setF0(1)));
EXPECT_EQ(UnionState({0, 4,0,0}, 224), INIT_UNION(getUnion1().initF32().setF0(1))); EXPECT_EQ(UnionState({0, 4,0,0}, 224), INIT_UNION(getUnion1().initF32().setF0(1)));
...@@ -329,8 +325,6 @@ TEST(Encoding, InlineStructUnionLayout) { ...@@ -329,8 +325,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({0, 6,0,0}, 256), INIT_UNION(getUnion1().initF128().setF0(1))); EXPECT_EQ(UnionState({0, 6,0,0}, 256), INIT_UNION(getUnion1().initF128().setF0(1)));
EXPECT_EQ(UnionState({0, 7,0,0}, 256), INIT_UNION(getUnion1().initF192().setF0(1))); EXPECT_EQ(UnionState({0, 7,0,0}, 256), INIT_UNION(getUnion1().initF192().setF0(1)));
EXPECT_EQ(UnionState({0,0, 0,0}, 448), INIT_UNION(getUnion2().initF1p().initF().setF(1)));
EXPECT_EQ(UnionState({0,0,0, 0}, 449), INIT_UNION(getUnion3().initF1p().initF().setF(1)));
EXPECT_EQ(UnionState({0,0, 1,0}, 456), INIT_UNION(getUnion2().initF8p().initF().setF0(true))); EXPECT_EQ(UnionState({0,0, 1,0}, 456), INIT_UNION(getUnion2().initF8p().initF().setF0(true)));
EXPECT_EQ(UnionState({0,0,0, 1}, 464), INIT_UNION(getUnion3().initF8p().initF().setF0(true))); EXPECT_EQ(UnionState({0,0,0, 1}, 464), INIT_UNION(getUnion3().initF8p().initF().setF0(true)));
EXPECT_EQ(UnionState({0,0, 2,0}, 480), INIT_UNION(getUnion2().initF16p().initF().setF0(1))); EXPECT_EQ(UnionState({0,0, 2,0}, 480), INIT_UNION(getUnion2().initF16p().initF().setF0(1)));
...@@ -344,8 +338,6 @@ TEST(Encoding, InlineStructUnionLayout) { ...@@ -344,8 +338,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({0,0, 6,0}, 960), INIT_UNION(getUnion2().initF192p().initF().setF0(1))); EXPECT_EQ(UnionState({0,0, 6,0}, 960), INIT_UNION(getUnion2().initF192p().initF().setF0(1)));
EXPECT_EQ(UnionState({0,0,0, 6},1152), INIT_UNION(getUnion3().initF192p().initF().setF0(1))); EXPECT_EQ(UnionState({0,0,0, 6},1152), INIT_UNION(getUnion3().initF192p().initF().setF0(1)));
EXPECT_EQ(UnionState({0,0, 0,0}, ptr( 3)), INIT_UNION(getUnion2().initF1p().setP0("1")));
EXPECT_EQ(UnionState({0,0,0, 0}, ptr( 4)), INIT_UNION(getUnion3().initF1p().setP0("1")));
EXPECT_EQ(UnionState({0,0, 1,0}, ptr( 3)), INIT_UNION(getUnion2().initF8p().setP0("1"))); EXPECT_EQ(UnionState({0,0, 1,0}, ptr( 3)), INIT_UNION(getUnion2().initF8p().setP0("1")));
EXPECT_EQ(UnionState({0,0,0, 1}, ptr( 4)), INIT_UNION(getUnion3().initF8p().setP0("1"))); EXPECT_EQ(UnionState({0,0,0, 1}, ptr( 4)), INIT_UNION(getUnion3().initF8p().setP0("1")));
EXPECT_EQ(UnionState({0,0, 2,0}, ptr( 5)), INIT_UNION(getUnion2().initF16p().setP0("1"))); EXPECT_EQ(UnionState({0,0, 2,0}, ptr( 5)), INIT_UNION(getUnion2().initF16p().setP0("1")));
...@@ -367,9 +359,7 @@ TEST(Encoding, InitInlineStruct) { ...@@ -367,9 +359,7 @@ TEST(Encoding, InitInlineStruct) {
auto root = builder.getRoot<TestInlineLayout>(); auto root = builder.getRoot<TestInlineLayout>();
// Set as many bits as we can. // Set as many bits as we can.
root.initF1().setF(true); root.setPad1(0xffu);
root.initF1Offset().setF(true);
root.setBit(true);
root.initF8().setF0(true); root.initF8().setF0(true);
root.getF8().setF1(true); root.getF8().setF1(true);
root.getF8().setF2(true); root.getF8().setF2(true);
...@@ -386,8 +376,8 @@ TEST(Encoding, InitInlineStruct) { ...@@ -386,8 +376,8 @@ TEST(Encoding, InitInlineStruct) {
root.getF192().setF2(0xffffffffffffffffull); root.getF192().setF2(0xffffffffffffffffull);
root.initF0p().setP0("foo"); root.initF0p().setP0("foo");
root.initF1p().setP0("foo"); root.setPad2(0xffu);
root.getF1p().initF().setF(true); root.setPadP("foo");
root.initF8p().setP0("foo"); root.initF8p().setP0("foo");
root.initF16p().setP0("foo"); root.initF16p().setP0("foo");
root.getF16p().setP1("foo"); root.getF16p().setP1("foo");
...@@ -403,21 +393,10 @@ TEST(Encoding, InitInlineStruct) { ...@@ -403,21 +393,10 @@ TEST(Encoding, InitInlineStruct) {
root.getF192p().setP2("foo"); root.getF192p().setP2("foo");
// Now try re-initializing each thing and making sure the surrounding things aren't modified. // Now try re-initializing each thing and making sure the surrounding things aren't modified.
EXPECT_FALSE(root.initF1().getF());
EXPECT_TRUE(root.getF1Offset().getF());
root.getF1().setF(true);
EXPECT_FALSE(root.initF1Offset().getF());
EXPECT_TRUE(root.getF1().getF());
EXPECT_TRUE(root.getBit());
EXPECT_TRUE(root.getF8().getF0());
root.getF1Offset().setF(true);
EXPECT_FALSE(root.initF8().getF0()); EXPECT_FALSE(root.initF8().getF0());
EXPECT_FALSE(root.getF8().getF1()); EXPECT_FALSE(root.getF8().getF1());
EXPECT_FALSE(root.getF8().getF2()); EXPECT_FALSE(root.getF8().getF2());
EXPECT_TRUE(root.getF1().getF()); EXPECT_EQ(0xffu, root.getPad1());
EXPECT_TRUE(root.getBit());
EXPECT_EQ(0xffu, root.getF16().getF0()); EXPECT_EQ(0xffu, root.getF16().getF0());
root.initF8().setF0(true); root.initF8().setF0(true);
root.getF8().setF1(true); root.getF8().setF1(true);
...@@ -461,22 +440,17 @@ TEST(Encoding, InitInlineStruct) { ...@@ -461,22 +440,17 @@ TEST(Encoding, InitInlineStruct) {
EXPECT_EQ(0u, root.getF192().getF2()); EXPECT_EQ(0u, root.getF192().getF2());
EXPECT_EQ(0xffffffffffffffffull, root.getF128().getF0()); EXPECT_EQ(0xffffffffffffffffull, root.getF128().getF0());
EXPECT_EQ(0xffffffffffffffffull, root.getF128().getF1()); EXPECT_EQ(0xffffffffffffffffull, root.getF128().getF1());
EXPECT_TRUE(root.getF1p().getF().getF()); EXPECT_EQ(0xffu, root.getPad2());
root.getF192().setF0(0xffffffffffffffffull); root.getF192().setF0(0xffffffffffffffffull);
root.getF192().setF1(0xffffffffffffffffull); root.getF192().setF1(0xffffffffffffffffull);
root.getF192().setF2(0xffffffffffffffffull); root.getF192().setF2(0xffffffffffffffffull);
EXPECT_EQ("", root.initF0p().getP0()); EXPECT_EQ("", root.initF0p().getP0());
EXPECT_EQ("foo", root.getF1p().getP0()); EXPECT_EQ("foo", root.getPadP());
root.getF0p().setP0("foo"); root.getF0p().setP0("foo");
EXPECT_EQ("", root.initF1p().getP0());
EXPECT_EQ("foo", root.getF0p().getP0());
EXPECT_EQ("foo", root.getF8p().getP0());
root.getF1p().setP0("foo");
EXPECT_EQ("", root.initF8p().getP0()); EXPECT_EQ("", root.initF8p().getP0());
EXPECT_EQ("foo", root.getF1p().getP0()); EXPECT_EQ("foo", root.getPadP());
EXPECT_EQ("foo", root.getF16p().getP0()); EXPECT_EQ("foo", root.getF16p().getP0());
root.initF8p().setP0("foo"); root.initF8p().setP0("foo");
...@@ -525,7 +499,6 @@ TEST(Encoding, InlineDefaults) { ...@@ -525,7 +499,6 @@ TEST(Encoding, InlineDefaults) {
{ {
auto normal = reader.getNormal(); auto normal = reader.getNormal();
EXPECT_TRUE(normal.getF1().getF());
EXPECT_TRUE(normal.getF8().getF0()); EXPECT_TRUE(normal.getF8().getF0());
EXPECT_FALSE(normal.getF8().getF1()); EXPECT_FALSE(normal.getF8().getF1());
EXPECT_TRUE(normal.getF8().getF2()); EXPECT_TRUE(normal.getF8().getF2());
...@@ -541,7 +514,6 @@ TEST(Encoding, InlineDefaults) { ...@@ -541,7 +514,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(2345678901234ull, normal.getF192().getF1()); EXPECT_EQ(2345678901234ull, normal.getF192().getF1());
EXPECT_EQ(5678901234567ull, normal.getF192().getF2()); EXPECT_EQ(5678901234567ull, normal.getF192().getF2());
EXPECT_FALSE(normal.getF1p().getF().getF());
EXPECT_TRUE(normal.getF8p().getF().getF0()); EXPECT_TRUE(normal.getF8p().getF().getF0());
EXPECT_TRUE(normal.getF8p().getF().getF1()); EXPECT_TRUE(normal.getF8p().getF().getF1());
EXPECT_FALSE(normal.getF8p().getF().getF2()); EXPECT_FALSE(normal.getF8p().getF().getF2());
...@@ -558,7 +530,6 @@ TEST(Encoding, InlineDefaults) { ...@@ -558,7 +530,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(5432109876543ull, normal.getF192p().getF().getF2()); EXPECT_EQ(5432109876543ull, normal.getF192p().getF().getF2());
EXPECT_EQ("foo", normal.getF0p().getP0()); EXPECT_EQ("foo", normal.getF0p().getP0());
EXPECT_EQ("bar", normal.getF1p().getP0());
EXPECT_EQ("baz", normal.getF8p().getP0()); EXPECT_EQ("baz", normal.getF8p().getP0());
EXPECT_EQ("qux", normal.getF16p().getP0()); EXPECT_EQ("qux", normal.getF16p().getP0());
EXPECT_EQ("quux", normal.getF16p().getP1()); EXPECT_EQ("quux", normal.getF16p().getP1());
...@@ -585,9 +556,6 @@ TEST(Encoding, InlineDefaults) { ...@@ -585,9 +556,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(1234567890123ull, unions.getUnion1().getF128().getF0()); EXPECT_EQ(1234567890123ull, unions.getUnion1().getF128().getF0());
EXPECT_EQ(4567890123456ull, unions.getUnion1().getF128().getF1()); EXPECT_EQ(4567890123456ull, unions.getUnion1().getF128().getF1());
ASSERT_EQ(TestInlineUnions::Union2::F1P, unions.getUnion2().which());
EXPECT_EQ("foo", unions.getUnion2().getF1p().getP0());
ASSERT_EQ(TestInlineUnions::Union3::F16P, unions.getUnion3().which()); ASSERT_EQ(TestInlineUnions::Union3::F16P, unions.getUnion3().which());
EXPECT_EQ(98u, unions.getUnion3().getF16p().getF().getF0()); EXPECT_EQ(98u, unions.getUnion3().getF16p().getF().getF0());
EXPECT_EQ(76u, unions.getUnion3().getF16p().getF().getF1()); EXPECT_EQ(76u, unions.getUnion3().getF16p().getF().getF1());
...@@ -659,10 +627,6 @@ TEST(Encoding, InlineDefaults) { ...@@ -659,10 +627,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(Void::VOID, lists.getStructList0()[0].getF()); EXPECT_EQ(Void::VOID, lists.getStructList0()[0].getF());
EXPECT_EQ(Void::VOID, lists.getStructList0()[1].getF()); EXPECT_EQ(Void::VOID, lists.getStructList0()[1].getF());
EXPECT_TRUE(lists.getStructList1()[0].getF());
EXPECT_FALSE(lists.getStructList1()[1].getF());
// EXPECT_TRUE(lists.getStructList1()[2].getF());
EXPECT_TRUE (lists.getStructList8()[0].getF0()); EXPECT_TRUE (lists.getStructList8()[0].getF0());
EXPECT_FALSE(lists.getStructList8()[0].getF1()); EXPECT_FALSE(lists.getStructList8()[0].getF1());
EXPECT_FALSE(lists.getStructList8()[0].getF2()); EXPECT_FALSE(lists.getStructList8()[0].getF2());
...@@ -717,10 +681,6 @@ TEST(Encoding, InlineDefaults) { ...@@ -717,10 +681,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ("baz", lists.getStructList0p()[2].getP0()); EXPECT_EQ("baz", lists.getStructList0p()[2].getP0());
EXPECT_EQ("qux", lists.getStructList0p()[3].getP0()); EXPECT_EQ("qux", lists.getStructList0p()[3].getP0());
EXPECT_TRUE(lists.getStructList1p()[0].getF().getF());
EXPECT_EQ("quux", lists.getStructList1p()[0].getP0());
EXPECT_EQ("corge", lists.getStructList1p()[1].getP0());
EXPECT_TRUE(lists.getStructList8p()[0].getF().getF0()); EXPECT_TRUE(lists.getStructList8p()[0].getF().getF0());
EXPECT_EQ("grault", lists.getStructList8p()[0].getP0()); EXPECT_EQ("grault", lists.getStructList8p()[0].getP0());
EXPECT_EQ("garply", lists.getStructList8p()[1].getP0()); EXPECT_EQ("garply", lists.getStructList8p()[1].getP0());
......
...@@ -102,7 +102,7 @@ static const AlignedData<2> SUBSTRUCT_DEFAULT = {{0,0,0,0,1,0,0,0, 0,0,0,0,0,0, ...@@ -102,7 +102,7 @@ static const AlignedData<2> SUBSTRUCT_DEFAULT = {{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,
static const AlignedData<2> STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT = static const AlignedData<2> STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT =
{{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0}}; {{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0}};
static constexpr StructSize STRUCTLIST_ELEMENT_SIZE(1 * WORDS, 1 * REFERENCES, 64 * BITS); static constexpr StructSize STRUCTLIST_ELEMENT_SIZE(1 * WORDS, 1 * REFERENCES, 8 * BYTES);
static void setupStruct(StructBuilder builder) { static void setupStruct(StructBuilder builder) {
builder.setDataField<uint64_t>(0 * ELEMENTS, 0x1011121314151617ull); builder.setDataField<uint64_t>(0 * ELEMENTS, 0x1011121314151617ull);
...@@ -120,7 +120,7 @@ static void setupStruct(StructBuilder builder) { ...@@ -120,7 +120,7 @@ static void setupStruct(StructBuilder builder) {
{ {
StructBuilder subStruct = builder.initStructField( StructBuilder subStruct = builder.initStructField(
0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS)); 0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES));
subStruct.setDataField<uint32_t>(0 * ELEMENTS, 123); subStruct.setDataField<uint32_t>(0 * ELEMENTS, 123);
} }
...@@ -139,7 +139,7 @@ static void setupStruct(StructBuilder builder) { ...@@ -139,7 +139,7 @@ static void setupStruct(StructBuilder builder) {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
StructBuilder element = list.getStructElement(i * ELEMENTS, STRUCTLIST_ELEMENT_SIZE); StructBuilder element = list.getStructElement(i * ELEMENTS, STRUCTLIST_ELEMENT_SIZE);
element.setDataField<int32_t>(0 * ELEMENTS, 300 + i); element.setDataField<int32_t>(0 * ELEMENTS, 300 + i);
element.initStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS)) element.initStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES))
.setDataField<int32_t>(0 * ELEMENTS, 400 + i); .setDataField<int32_t>(0 * ELEMENTS, 400 + i);
} }
} }
...@@ -174,7 +174,7 @@ static void checkStruct(StructBuilder builder) { ...@@ -174,7 +174,7 @@ static void checkStruct(StructBuilder builder) {
{ {
StructBuilder subStruct = builder.getStructField( StructBuilder subStruct = builder.getStructField(
0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS), SUBSTRUCT_DEFAULT.words); 0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES), SUBSTRUCT_DEFAULT.words);
EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS)); EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS));
} }
...@@ -193,7 +193,7 @@ static void checkStruct(StructBuilder builder) { ...@@ -193,7 +193,7 @@ static void checkStruct(StructBuilder builder) {
StructBuilder element = list.getStructElement(i * ELEMENTS, STRUCTLIST_ELEMENT_SIZE); StructBuilder element = list.getStructElement(i * ELEMENTS, STRUCTLIST_ELEMENT_SIZE);
EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS)); EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS));
EXPECT_EQ(400 + i, EXPECT_EQ(400 + i,
element.getStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS), element.getStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES),
STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words) STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
.getDataField<int32_t>(0 * ELEMENTS)); .getDataField<int32_t>(0 * ELEMENTS));
} }
...@@ -272,7 +272,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) { ...@@ -272,7 +272,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
word* rootLocation = segment->allocate(1 * WORDS); word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder = StructBuilder::initRoot( StructBuilder builder = StructBuilder::initRoot(
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 128 * BITS)); segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 16 * BYTES));
setupStruct(builder); setupStruct(builder);
// word count: // word count:
...@@ -308,7 +308,7 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) { ...@@ -308,7 +308,7 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
word* rootLocation = segment->allocate(1 * WORDS); word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder = StructBuilder::initRoot( StructBuilder builder = StructBuilder::initRoot(
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 128 * BITS)); segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 16 * BYTES));
setupStruct(builder); setupStruct(builder);
// Verify that we made 15 segments. // Verify that we made 15 segments.
...@@ -345,7 +345,7 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) { ...@@ -345,7 +345,7 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
word* rootLocation = segment->allocate(1 * WORDS); word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder = StructBuilder::initRoot( StructBuilder builder = StructBuilder::initRoot(
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 128 * BITS)); segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 16 * BYTES));
setupStruct(builder); setupStruct(builder);
// Verify that we made 6 segments. // Verify that we made 6 segments.
......
...@@ -415,7 +415,7 @@ struct WireHelpers { ...@@ -415,7 +415,7 @@ struct WireHelpers {
ref->structRef.set(size); ref->structRef.set(size);
// Build the StructBuilder. // Build the StructBuilder.
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data), 0 * BITS, return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data),
size.pointers); size.pointers);
} }
...@@ -443,7 +443,7 @@ struct WireHelpers { ...@@ -443,7 +443,7 @@ struct WireHelpers {
"Trying to update struct with incorrect reference count."); "Trying to update struct with incorrect reference count.");
} }
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data), 0 * BITS, return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data),
size.pointers); size.pointers);
} }
...@@ -466,7 +466,7 @@ struct WireHelpers { ...@@ -466,7 +466,7 @@ struct WireHelpers {
// Build the ListBuilder. // Build the ListBuilder.
return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr), return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr),
step, step / BITS_PER_REFERENCE, elementCount); step / BITS_PER_BYTE, step / BITS_PER_REFERENCE, elementCount);
} }
static CAPNPROTO_ALWAYS_INLINE(ListBuilder initStructListReference( static CAPNPROTO_ALWAYS_INLINE(ListBuilder initStructListReference(
...@@ -479,13 +479,12 @@ struct WireHelpers { ...@@ -479,13 +479,12 @@ struct WireHelpers {
if (elementSize.pointers == 1 * REFERENCES) { if (elementSize.pointers == 1 * REFERENCES) {
primitiveElementSize = FieldSize::REFERENCE; primitiveElementSize = FieldSize::REFERENCE;
} else { } else {
switch (elementSize.dataBits / BITS) { switch (elementSize.dataBytes / BYTES) {
case 0: primitiveElementSize = FieldSize::VOID; break; case 0: primitiveElementSize = FieldSize::VOID; break;
case 1: primitiveElementSize = FieldSize::BIT; break; case 1: primitiveElementSize = FieldSize::BYTE; break;
case 8: primitiveElementSize = FieldSize::BYTE; break; case 2: primitiveElementSize = FieldSize::TWO_BYTES; break;
case 16: primitiveElementSize = FieldSize::TWO_BYTES; break; case 4: primitiveElementSize = FieldSize::FOUR_BYTES; break;
case 32: primitiveElementSize = FieldSize::FOUR_BYTES; break; case 8: primitiveElementSize = FieldSize::EIGHT_BYTES; break;
case 64: primitiveElementSize = FieldSize::EIGHT_BYTES; break;
default: FAIL_PRECOND("Invalid struct size."); break; default: FAIL_PRECOND("Invalid struct size."); break;
} }
} }
...@@ -510,7 +509,7 @@ struct WireHelpers { ...@@ -510,7 +509,7 @@ struct WireHelpers {
// Build the ListBuilder. // Build the ListBuilder.
return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + elementSize.data), return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + elementSize.data),
wordsPerElement * BITS_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE, wordsPerElement * BYTES_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE,
elementCount); elementCount);
} }
...@@ -521,7 +520,7 @@ struct WireHelpers { ...@@ -521,7 +520,7 @@ struct WireHelpers {
if (ref->isNull()) { if (ref->isNull()) {
if (defaultValue == nullptr) { if (defaultValue == nullptr) {
return ListBuilder(segment, nullptr, nullptr, 0 * BITS / ELEMENTS, return ListBuilder(segment, nullptr, nullptr, 0 * BYTES / ELEMENTS,
0 * REFERENCES / ELEMENTS, 0 * ELEMENTS); 0 * REFERENCES / ELEMENTS, 0 * ELEMENTS);
} }
ptr = copyMessage(segment, ref, defaultRef); ptr = copyMessage(segment, ref, defaultRef);
...@@ -543,12 +542,12 @@ struct WireHelpers { ...@@ -543,12 +542,12 @@ struct WireHelpers {
WireReference* pointers = reinterpret_cast<WireReference*>( WireReference* pointers = reinterpret_cast<WireReference*>(
data + tag->structRef.dataSize.get()); data + tag->structRef.dataSize.get());
auto step = tag->structRef.wordSize() / ELEMENTS; auto step = tag->structRef.wordSize() / ELEMENTS;
return ListBuilder(segment, data, pointers, step * BITS_PER_WORD, step / WORDS_PER_REFERENCE, return ListBuilder(segment, data, pointers, step * BYTES_PER_WORD, step / WORDS_PER_REFERENCE,
tag->inlineCompositeListElementCount()); tag->inlineCompositeListElementCount());
} else { } else {
decltype(BITS/ELEMENTS) step = bitsPerElement(ref->listRef.elementSize()); auto step = bytesPerElement(ref->listRef.elementSize());
return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr), return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr),
step, step / BITS_PER_REFERENCE, step, step / BYTES_PER_REFERENCE,
ref->listRef.elementCount()); ref->listRef.elementCount());
} }
} }
...@@ -637,7 +636,7 @@ struct WireHelpers { ...@@ -637,7 +636,7 @@ struct WireHelpers {
if (ref == nullptr || ref->isNull()) { if (ref == nullptr || ref->isNull()) {
useDefault: useDefault:
if (defaultValue == nullptr) { if (defaultValue == nullptr) {
return StructReader(nullptr, nullptr, nullptr, 0 * BITS, 0 * REFERENCES, 0 * BITS, return StructReader(nullptr, nullptr, nullptr, 0 * BYTES, 0 * REFERENCES,
std::numeric_limits<int>::max()); std::numeric_limits<int>::max());
} }
segment = nullptr; segment = nullptr;
...@@ -671,9 +670,9 @@ struct WireHelpers { ...@@ -671,9 +670,9 @@ struct WireHelpers {
return StructReader( return StructReader(
segment, ptr, reinterpret_cast<const WireReference*>(ptr + ref->structRef.dataSize.get()), segment, ptr, reinterpret_cast<const WireReference*>(ptr + ref->structRef.dataSize.get()),
ref->structRef.dataSize.get() * BITS_PER_WORD, ref->structRef.dataSize.get() * BYTES_PER_WORD,
ref->structRef.refCount.get(), ref->structRef.refCount.get(),
0 * BITS, nestingLimit - 1); nestingLimit - 1);
} }
static CAPNPROTO_ALWAYS_INLINE(ListReader readListReference( static CAPNPROTO_ALWAYS_INLINE(ListReader readListReference(
...@@ -684,7 +683,7 @@ struct WireHelpers { ...@@ -684,7 +683,7 @@ struct WireHelpers {
useDefault: useDefault:
if (defaultValue == nullptr) { if (defaultValue == nullptr) {
return ListReader(nullptr, nullptr, nullptr, 0 * ELEMENTS, return ListReader(nullptr, nullptr, nullptr, 0 * ELEMENTS,
0 * BITS / ELEMENTS, 0 * REFERENCES / ELEMENTS, 0 * BYTES / ELEMENTS, 0 * REFERENCES / ELEMENTS,
nestingLimit - 1); nestingLimit - 1);
} }
segment = nullptr; segment = nullptr;
...@@ -751,6 +750,11 @@ struct WireHelpers { ...@@ -751,6 +750,11 @@ struct WireHelpers {
break; break;
case FieldSize::BIT: case FieldSize::BIT:
FAIL_VALIDATE_INPUT("Expected a bit list, but got a list of structs.") {
goto useDefault;
}
break;
case FieldSize::BYTE: case FieldSize::BYTE:
case FieldSize::TWO_BYTES: case FieldSize::TWO_BYTES:
case FieldSize::FOUR_BYTES: case FieldSize::FOUR_BYTES:
...@@ -790,13 +794,13 @@ struct WireHelpers { ...@@ -790,13 +794,13 @@ struct WireHelpers {
return ListReader( return ListReader(
segment, ptr, segment, ptr,
reinterpret_cast<const WireReference*>(ptr + tag->structRef.dataSize.get()), reinterpret_cast<const WireReference*>(ptr + tag->structRef.dataSize.get()),
size, wordsPerElement * BITS_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE, size, wordsPerElement * BYTES_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE,
tag->structRef.dataSize.get() * BITS_PER_WORD, tag->structRef.dataSize.get() * BYTES_PER_WORD,
tag->structRef.refCount.get(), nestingLimit - 1); tag->structRef.refCount.get(), nestingLimit - 1);
} else { } else {
// The elements of the list are NOT structs. // The elements of the list are NOT structs.
decltype(BITS/ELEMENTS) step = bitsPerElement(ref->listRef.elementSize()); auto step = bitsPerElement(ref->listRef.elementSize());
if (segment != nullptr) { if (segment != nullptr) {
VALIDATE_INPUT(segment->containsInterval(ptr, ptr + VALIDATE_INPUT(segment->containsInterval(ptr, ptr +
...@@ -808,34 +812,39 @@ struct WireHelpers { ...@@ -808,34 +812,39 @@ struct WireHelpers {
if (ref->listRef.elementSize() == expectedElementSize) { if (ref->listRef.elementSize() == expectedElementSize) {
return ListReader(segment, ptr, reinterpret_cast<const WireReference*>(ptr), return ListReader(segment, ptr, reinterpret_cast<const WireReference*>(ptr),
ref->listRef.elementCount(), step, step / BITS_PER_REFERENCE, ref->listRef.elementCount(), step / BITS_PER_BYTE,
nestingLimit - 1); step / BITS_PER_REFERENCE, nestingLimit - 1);
} else if (expectedElementSize == FieldSize::INLINE_COMPOSITE) { } else if (expectedElementSize == FieldSize::INLINE_COMPOSITE) {
// We were expecting a struct list, but we received a list of some other type. Perhaps a // We were expecting a struct list, but we received a list of some other type. Perhaps a
// non-struct list was recently upgraded to a struct list, but the sender is using the // non-struct list was recently upgraded to a struct list, but the sender is using the
// old version of the protocol. We need to verify that the struct's first field matches // old version of the protocol. We need to verify that the struct's first field matches
// what the sender sent us. // what the sender sent us.
BitCount dataSize = 0 * BITS; ByteCount dataSize = 0 * BYTES;
WireReferenceCount referenceCount = 0 * REFERENCES; WireReferenceCount referenceCount = 0 * REFERENCES;
switch (ref->listRef.elementSize()) { switch (ref->listRef.elementSize()) {
case FieldSize::VOID: break; case FieldSize::VOID: break;
case FieldSize::BIT: dataSize = 1 * BITS; break; case FieldSize::BYTE: dataSize = 1 * BYTES; break;
case FieldSize::BYTE: dataSize = 8 * BITS; break; case FieldSize::TWO_BYTES: dataSize = 2 * BYTES; break;
case FieldSize::TWO_BYTES: dataSize = 16 * BITS; break; case FieldSize::FOUR_BYTES: dataSize = 4 * BYTES; break;
case FieldSize::FOUR_BYTES: dataSize = 32 * BITS; break; case FieldSize::EIGHT_BYTES: dataSize = 8 * BYTES; break;
case FieldSize::EIGHT_BYTES: dataSize = 64 * BITS; break;
case FieldSize::REFERENCE: referenceCount = 1 * REFERENCES; break; case FieldSize::REFERENCE: referenceCount = 1 * REFERENCES; break;
case FieldSize::BIT:
FAIL_VALIDATE_INPUT("Message contained a bit list where a struct list was expected.") {
dataSize = 0 * BYTES;
}
break;
case FieldSize::INLINE_COMPOSITE: case FieldSize::INLINE_COMPOSITE:
FAIL_CHECK(); FAIL_CHECK();
break; break;
} }
return ListReader(segment, ptr, reinterpret_cast<const WireReference*>(ptr), return ListReader(segment, ptr, reinterpret_cast<const WireReference*>(ptr),
ref->listRef.elementCount(), step, step / BITS_PER_REFERENCE, ref->listRef.elementCount(), step / BITS_PER_BYTE,
dataSize, referenceCount, nestingLimit - 1); step / BITS_PER_REFERENCE, dataSize, referenceCount, nestingLimit - 1);
} else { } else {
PRECOND(segment != nullptr, "Trusted message had incompatible list element type."); PRECOND(segment != nullptr, "Trusted message had incompatible list element type.");
goto useDefault; goto useDefault;
...@@ -1010,7 +1019,7 @@ StructReader StructBuilder::asReader() const { ...@@ -1010,7 +1019,7 @@ StructReader StructBuilder::asReader() const {
static_assert(sizeof(WireReference::structRef.refCount) == 2, static_assert(sizeof(WireReference::structRef.refCount) == 2,
"Has the maximum reference count changed?"); "Has the maximum reference count changed?");
return StructReader(segment, data, references, return StructReader(segment, data, references,
0xffffffff * BITS, 0xffff * REFERENCES, 0 * BITS, std::numeric_limits<int>::max()); 0xffffffff * BYTES, 0xffff * REFERENCES, std::numeric_limits<int>::max());
} }
StructReader StructReader::readRootTrusted(const word* location) { StructReader StructReader::readRootTrusted(const word* location) {
...@@ -1030,7 +1039,7 @@ StructReader StructReader::readRoot( ...@@ -1030,7 +1039,7 @@ StructReader StructReader::readRoot(
} }
StructReader StructReader::readEmpty() { StructReader StructReader::readEmpty() {
return StructReader(nullptr, nullptr, nullptr, 0 * BITS, 0 * REFERENCES, 0 * BITS, return StructReader(nullptr, nullptr, nullptr, 0 * BYTES, 0 * REFERENCES,
std::numeric_limits<int>::max()); std::numeric_limits<int>::max());
} }
...@@ -1061,11 +1070,10 @@ Data::Reader StructReader::getDataField( ...@@ -1061,11 +1070,10 @@ Data::Reader StructReader::getDataField(
StructBuilder ListBuilder::getStructElement(ElementCount index, StructSize elementSize) const { StructBuilder ListBuilder::getStructElement(ElementCount index, StructSize elementSize) const {
// TODO: Inline this method? // TODO: Inline this method?
BitCount64 indexBit = ElementCount64(index) * stepBits; ByteCount indexByte = ElementCount64(index) * stepBytes;
byte* structData = reinterpret_cast<byte*>(data) + indexBit / BITS_PER_BYTE; byte* structData = reinterpret_cast<byte*>(data) + indexByte;
WireReference* structPointers = pointers + index * stepPointers; WireReference* structPointers = pointers + index * stepPointers;
return StructBuilder(segment, structData, structPointers, indexBit % BITS_PER_BYTE, return StructBuilder(segment, structData, structPointers, elementSize.pointers);
elementSize.pointers);
} }
ListBuilder ListBuilder::initListElement( ListBuilder ListBuilder::initListElement(
...@@ -1117,13 +1125,13 @@ ListReader ListBuilder::asReader(FieldSize elementSize) const { ...@@ -1117,13 +1125,13 @@ ListReader ListBuilder::asReader(FieldSize elementSize) const {
// TODO: For INLINE_COMPOSITE I suppose we could just check the tag? // TODO: For INLINE_COMPOSITE I suppose we could just check the tag?
PRECOND(elementSize != FieldSize::INLINE_COMPOSITE, PRECOND(elementSize != FieldSize::INLINE_COMPOSITE,
"Need to call the other asReader() overload for INLINE_COMPOSITE lists."); "Need to call the other asReader() overload for INLINE_COMPOSITE lists.");
return ListReader(segment, data, pointers, elementCount, stepBits, stepPointers, return ListReader(segment, data, pointers, elementCount, stepBytes, stepPointers,
std::numeric_limits<int>::max()); std::numeric_limits<int>::max());
} }
ListReader ListBuilder::asReader(StructSize elementSize) const { ListReader ListBuilder::asReader(StructSize elementSize) const {
return ListReader(segment, data, pointers, elementCount, stepBits, stepPointers, return ListReader(segment, data, pointers, elementCount, stepBytes, stepPointers,
elementSize.dataBits, elementSize.pointers, std::numeric_limits<int>::max()); elementSize.dataBytes, elementSize.pointers, std::numeric_limits<int>::max());
} }
StructReader ListReader::getStructElement(ElementCount index) const { StructReader ListReader::getStructElement(ElementCount index) const {
...@@ -1133,11 +1141,11 @@ StructReader ListReader::getStructElement(ElementCount index) const { ...@@ -1133,11 +1141,11 @@ StructReader ListReader::getStructElement(ElementCount index) const {
return StructReader::readEmpty(); return StructReader::readEmpty();
} }
BitCount64 indexBit = ElementCount64(index) * stepBits; ByteCount indexByte = index * stepBytes;
const byte* structData = reinterpret_cast<const byte*>(data) + indexBit / BITS_PER_BYTE; const byte* structData = reinterpret_cast<const byte*>(data) + indexByte;
return StructReader( return StructReader(
segment, structData, pointers + index * stepPointers, segment, structData, pointers + index * stepPointers,
structDataSize, structReferenceCount, indexBit % BITS_PER_BYTE, nestingLimit - 1); structDataSize, structReferenceCount, nestingLimit - 1);
} }
ListReader ListReader::getListElement( ListReader ListReader::getListElement(
......
...@@ -101,6 +101,7 @@ enum class FieldSize: uint8_t { ...@@ -101,6 +101,7 @@ enum class FieldSize: uint8_t {
}; };
typedef decltype(BITS / ELEMENTS) BitsPerElement; typedef decltype(BITS / ELEMENTS) BitsPerElement;
typedef decltype(BYTES / ELEMENTS) BytesPerElement;
namespace internal { namespace internal {
static constexpr BitsPerElement BITS_PER_ELEMENT_TABLE[8] = { static constexpr BitsPerElement BITS_PER_ELEMENT_TABLE[8] = {
...@@ -119,6 +120,13 @@ inline constexpr BitsPerElement bitsPerElement(FieldSize size) { ...@@ -119,6 +120,13 @@ inline constexpr BitsPerElement bitsPerElement(FieldSize size) {
return internal::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)]; return internal::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)];
} }
inline constexpr BytesPerElement bytesPerElement(FieldSize size) {
// BIT gets rounded down to zero bytes. This is OK because bytesPerElement() is only used in
// cases where this doesn't matter, e.g. for computing stepBytes which is ignored by bit ops
// anyway.
return bitsPerElement(size) / BITS_PER_BYTE;
}
template <int wordCount> template <int wordCount>
union AlignedData { union AlignedData {
// Useful for declaring static constant data blobs as an array of bytes, but forcing those // Useful for declaring static constant data blobs as an array of bytes, but forcing those
...@@ -132,15 +140,15 @@ struct StructSize { ...@@ -132,15 +140,15 @@ struct StructSize {
WordCount16 data; WordCount16 data;
WireReferenceCount16 pointers; WireReferenceCount16 pointers;
BitCount32 dataBits; ByteCount32 dataBytes;
// If data == 1 word, dataBits may be 1, 8, 16, 32, or 64. Otherwise, it is data * BITS_PER_WORD. // Number of bytes in the data section. Must be data * 8 except when data == 1 in which case
// This is used when packing inline structs. // this can be 1, 2, 4, or 8.
inline constexpr WordCount total() const { return data + pointers * WORDS_PER_REFERENCE; } inline constexpr WordCount total() const { return data + pointers * WORDS_PER_REFERENCE; }
StructSize() = default; StructSize() = default;
inline constexpr StructSize(WordCount data, WireReferenceCount pointers, BitCount dataBits) inline constexpr StructSize(WordCount data, WireReferenceCount pointers, ByteCount dataBytes)
: data(data), pointers(pointers), dataBits(dataBits) {} : data(data), pointers(pointers), dataBytes(dataBytes) {}
}; };
template <typename T> template <typename T>
...@@ -286,13 +294,13 @@ public: ...@@ -286,13 +294,13 @@ public:
// or to the empty state if defaultValue is nullptr. // or to the empty state if defaultValue is nullptr.
CAPNPROTO_ALWAYS_INLINE(StructBuilder initInlineStructField( CAPNPROTO_ALWAYS_INLINE(StructBuilder initInlineStructField(
BitCount dataOffset, BitCount inlineDataSize, ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const); WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const);
// Initialize an inlined struct field, given the position and size of the data and pointer // Initialize an inlined struct field, given the position and size of the data and pointer
// sections. // sections.
CAPNPROTO_ALWAYS_INLINE(StructBuilder getInlineStructField( CAPNPROTO_ALWAYS_INLINE(StructBuilder getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize, ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const); WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const);
// Gets an inlined struct field, given the position and size of the data and pointer sections. // Gets an inlined struct field, given the position and size of the data and pointer sections.
...@@ -312,7 +320,7 @@ public: ...@@ -312,7 +320,7 @@ public:
// message). If the default value is null, an empty list is used. // message). If the default value is null, an empty list is used.
CAPNPROTO_ALWAYS_INLINE(ListBuilder initInlineDataListField( CAPNPROTO_ALWAYS_INLINE(ListBuilder initInlineDataListField(
BitCount offset, BitCount inlineSize, ByteCount offset, ByteCount inlineSize,
ElementCount elementCount, FieldSize elementSize) const); ElementCount elementCount, FieldSize elementSize) const);
// Initialize an inline list field. // Initialize an inline list field.
...@@ -322,12 +330,12 @@ public: ...@@ -322,12 +330,12 @@ public:
// Initialize an inline list field. // Initialize an inline list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder initInlineStructListField( CAPNPROTO_ALWAYS_INLINE(ListBuilder initInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount, ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const); StructSize elementSize) const);
// Initialize an inline struct list field. // Initialize an inline struct list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlineDataListField( CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const); ByteCount offset, ElementCount elementCount, FieldSize elementSize) const);
// Get an already-initialized inline list field. // Get an already-initialized inline list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlinePointerListField( CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlinePointerListField(
...@@ -335,7 +343,7 @@ public: ...@@ -335,7 +343,7 @@ public:
// Get an already-initialized inline list field. // Get an already-initialized inline list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlineStructListField( CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount, ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const); StructSize elementSize) const);
// Get an already-initialized inline struct list field. // Get an already-initialized inline struct list field.
...@@ -366,16 +374,12 @@ private: ...@@ -366,16 +374,12 @@ private:
void* data; // Pointer to the encoded data. void* data; // Pointer to the encoded data.
WireReference* references; // Pointer to the encoded references. WireReference* references; // Pointer to the encoded references.
BitCount8 bit0Offset;
// A special hack: When accessing a boolean with field number zero, pretend its offset is this
// instead of the usual zero. This is needed to support 1-bit inline structs.
WireReferenceCount16 referenceCount; WireReferenceCount16 referenceCount;
// Size of the pointer segment, available only for the sake of computing size of List(Inline(T)). // Size of the pointer segment, available only for the sake of computing size of List(Inline(T)).
inline StructBuilder(SegmentBuilder* segment, void* data, WireReference* references, inline StructBuilder(SegmentBuilder* segment, void* data, WireReference* references,
BitCount8 bit0Offset, WireReferenceCount referenceCount) WireReferenceCount referenceCount)
: segment(segment), data(data), references(references), bit0Offset(bit0Offset), : segment(segment), data(data), references(references),
referenceCount(referenceCount) {} referenceCount(referenceCount) {}
friend class ListBuilder; friend class ListBuilder;
...@@ -386,7 +390,7 @@ class StructReader { ...@@ -386,7 +390,7 @@ class StructReader {
public: public:
inline StructReader() inline StructReader()
: segment(nullptr), data(nullptr), references(nullptr), dataSize(0), : segment(nullptr), data(nullptr), references(nullptr), dataSize(0),
referenceCount(0), bit0Offset(0 * BITS), nestingLimit(0) {} referenceCount(0), nestingLimit(0) {}
static StructReader readRootTrusted(const word* location); static StructReader readRootTrusted(const word* location);
static StructReader readRoot(const word* location, SegmentReader* segment, int nestingLimit); static StructReader readRoot(const word* location, SegmentReader* segment, int nestingLimit);
...@@ -411,7 +415,7 @@ public: ...@@ -411,7 +415,7 @@ public:
// be null, in which case an empty struct is used. // be null, in which case an empty struct is used.
CAPNPROTO_ALWAYS_INLINE(StructReader getInlineStructField( CAPNPROTO_ALWAYS_INLINE(StructReader getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize, ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const); WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const);
// Gets an inlined struct field, given the position and size of the data and pointer sections. // Gets an inlined struct field, given the position and size of the data and pointer sections.
...@@ -421,7 +425,7 @@ public: ...@@ -421,7 +425,7 @@ public:
// initialized. The default value is allowed to be null, in which case an empty list is used. // initialized. The default value is allowed to be null, in which case an empty list is used.
CAPNPROTO_ALWAYS_INLINE(ListReader getInlineDataListField( CAPNPROTO_ALWAYS_INLINE(ListReader getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const); ByteCount offset, ElementCount elementCount, FieldSize elementSize) const);
// Get an inline list field. // Get an inline list field.
CAPNPROTO_ALWAYS_INLINE(ListReader getInlinePointerListField( CAPNPROTO_ALWAYS_INLINE(ListReader getInlinePointerListField(
...@@ -429,7 +433,7 @@ public: ...@@ -429,7 +433,7 @@ public:
// Get an inline list field. // Get an inline list field.
CAPNPROTO_ALWAYS_INLINE(ListReader getInlineStructListField( CAPNPROTO_ALWAYS_INLINE(ListReader getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount, ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const); StructSize elementSize) const);
// Get an inline struct list field. // Get an inline struct list field.
...@@ -449,24 +453,18 @@ private: ...@@ -449,24 +453,18 @@ private:
const void* data; const void* data;
const WireReference* references; const WireReference* references;
BitCount32 dataSize; // Size of data segment. ByteCount32 dataSize; // Size of data segment.
WireReferenceCount16 referenceCount; // Size of the reference segment. WireReferenceCount16 referenceCount; // Size of the reference segment.
BitCount8 bit0Offset;
// A special hack: When accessing a boolean with field number zero, pretend its offset is this
// instead of the usual zero. This is needed to allow a boolean list to be upgraded to a list
// of structs, and to support 1-bit inline structs.
int nestingLimit; int nestingLimit;
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks. // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
// Once this reaches zero, further pointers will be pruned. // Once this reaches zero, further pointers will be pruned.
// TODO: Limit to 8 bits for better alignment? // TODO: Limit to 8 bits for better alignment?
inline StructReader(SegmentReader* segment, const void* data, const WireReference* references, inline StructReader(SegmentReader* segment, const void* data, const WireReference* references,
BitCount dataSize, WireReferenceCount referenceCount, ByteCount dataSize, WireReferenceCount referenceCount, int nestingLimit)
BitCount bit0Offset, int nestingLimit)
: segment(segment), data(data), references(references), : segment(segment), data(data), references(references),
dataSize(dataSize), referenceCount(referenceCount), bit0Offset(bit0Offset), dataSize(dataSize), referenceCount(referenceCount),
nestingLimit(nestingLimit) {} nestingLimit(nestingLimit) {}
friend class ListReader; friend class ListReader;
...@@ -480,7 +478,7 @@ class ListBuilder { ...@@ -480,7 +478,7 @@ class ListBuilder {
public: public:
inline ListBuilder() inline ListBuilder()
: segment(nullptr), data(nullptr), pointers(nullptr), elementCount(0 * ELEMENTS), : segment(nullptr), data(nullptr), pointers(nullptr), elementCount(0 * ELEMENTS),
stepBits(0 * BITS / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS) {} stepBytes(0 * BYTES / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS) {}
inline ElementCount size(); inline ElementCount size();
// The number of elements in the list. // The number of elements in the list.
...@@ -540,15 +538,16 @@ private: ...@@ -540,15 +538,16 @@ private:
ElementCount elementCount; // Number of elements in the list. ElementCount elementCount; // Number of elements in the list.
decltype(BITS / ELEMENTS) stepBits; decltype(BYTES / ELEMENTS) stepBytes;
decltype(REFERENCES / ELEMENTS) stepPointers; decltype(REFERENCES / ELEMENTS) stepPointers;
// The distance between elements. Can be tricky e.g. for inlined struct lists. // The distance between elements. Can be tricky e.g. for inlined struct lists.
// Bit lists ignore stepBytes -- they are always tightly-packed.
inline ListBuilder(SegmentBuilder* segment, void* data, WireReference* pointers, inline ListBuilder(SegmentBuilder* segment, void* data, WireReference* pointers,
decltype(BITS / ELEMENTS) stepBits, decltype(BYTES / ELEMENTS) stepBytes,
decltype(REFERENCES / ELEMENTS) stepPointers, ElementCount size) decltype(REFERENCES / ELEMENTS) stepPointers, ElementCount size)
: segment(segment), data(data), pointers(pointers), elementCount(size), : segment(segment), data(data), pointers(pointers), elementCount(size),
stepBits(stepBits), stepPointers(stepPointers) {} stepBytes(stepBytes), stepPointers(stepPointers) {}
friend class StructBuilder; friend class StructBuilder;
friend struct WireHelpers; friend struct WireHelpers;
...@@ -558,7 +557,7 @@ class ListReader { ...@@ -558,7 +557,7 @@ class ListReader {
public: public:
inline ListReader() inline ListReader()
: segment(nullptr), data(nullptr), pointers(nullptr), elementCount(0), : segment(nullptr), data(nullptr), pointers(nullptr), elementCount(0),
stepBits(0 * BITS / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS), stepBytes(0 * BYTES / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS),
structDataSize(0), structReferenceCount(0), nestingLimit(0) {} structDataSize(0), structReferenceCount(0), nestingLimit(0) {}
inline ElementCount size(); inline ElementCount size();
...@@ -589,11 +588,12 @@ private: ...@@ -589,11 +588,12 @@ private:
ElementCount elementCount; // Number of elements in the list. ElementCount elementCount; // Number of elements in the list.
decltype(BITS / ELEMENTS) stepBits; decltype(BYTES / ELEMENTS) stepBytes;
decltype(REFERENCES / ELEMENTS) stepPointers; decltype(REFERENCES / ELEMENTS) stepPointers;
// The distance between elements. Can be tricky e.g. for inlined struct lists. // The distance between elements. Can be tricky e.g. for inlined struct lists.
// Bit lists ignore stepBytes -- they are always tightly-packed.
BitCount structDataSize; ByteCount structDataSize;
WireReferenceCount structReferenceCount; WireReferenceCount structReferenceCount;
// If the elements are structs, the properties of the struct. // If the elements are structs, the properties of the struct.
...@@ -602,17 +602,17 @@ private: ...@@ -602,17 +602,17 @@ private:
// Once this reaches zero, further pointers will be pruned. // Once this reaches zero, further pointers will be pruned.
inline ListReader(SegmentReader* segment, const void* data, const WireReference* pointers, inline ListReader(SegmentReader* segment, const void* data, const WireReference* pointers,
ElementCount elementCount, decltype(BITS / ELEMENTS) stepBits, ElementCount elementCount, decltype(BYTES / ELEMENTS) stepBytes,
decltype(REFERENCES / ELEMENTS) stepPointers, int nestingLimit) decltype(REFERENCES / ELEMENTS) stepPointers, int nestingLimit)
: segment(segment), data(data), pointers(pointers), elementCount(elementCount), : segment(segment), data(data), pointers(pointers), elementCount(elementCount),
stepBits(stepBits), stepPointers(stepPointers), structDataSize(0), structReferenceCount(0), stepBytes(stepBytes), stepPointers(stepPointers), structDataSize(0),
nestingLimit(nestingLimit) {} structReferenceCount(0), nestingLimit(nestingLimit) {}
inline ListReader(SegmentReader* segment, const void* data, const WireReference* pointers, inline ListReader(SegmentReader* segment, const void* data, const WireReference* pointers,
ElementCount elementCount, decltype(BITS / ELEMENTS) stepBits, ElementCount elementCount, decltype(BYTES / ELEMENTS) stepBytes,
decltype(REFERENCES / ELEMENTS) stepPointers, BitCount structDataSize, decltype(REFERENCES / ELEMENTS) stepPointers, ByteCount structDataSize,
WireReferenceCount structReferenceCount, int nestingLimit) WireReferenceCount structReferenceCount, int nestingLimit)
: segment(segment), data(data), pointers(pointers), elementCount(elementCount), : segment(segment), data(data), pointers(pointers), elementCount(elementCount),
stepBits(stepBits), stepPointers(stepPointers), structDataSize(structDataSize), stepBytes(stepBytes), stepPointers(stepPointers), structDataSize(structDataSize),
structReferenceCount(structReferenceCount), nestingLimit(nestingLimit) {} structReferenceCount(structReferenceCount), nestingLimit(nestingLimit) {}
friend class StructReader; friend class StructReader;
...@@ -631,10 +631,6 @@ inline T StructBuilder::getDataField(ElementCount offset) const { ...@@ -631,10 +631,6 @@ inline T StructBuilder::getDataField(ElementCount offset) const {
template <> template <>
inline bool StructBuilder::getDataField<bool>(ElementCount offset) const { inline bool StructBuilder::getDataField<bool>(ElementCount offset) const {
BitCount boffset = offset * (1 * BITS / ELEMENTS); BitCount boffset = offset * (1 * BITS / ELEMENTS);
// This branch should always be optimized away when inlining.
if (boffset == 0 * BITS) boffset = bit0Offset;
byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0; return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
} }
...@@ -658,10 +654,6 @@ inline void StructBuilder::setDataField( ...@@ -658,10 +654,6 @@ inline void StructBuilder::setDataField(
template <> template <>
inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) const { inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) const {
BitCount boffset = offset * (1 * BITS / ELEMENTS); BitCount boffset = offset * (1 * BITS / ELEMENTS);
// This branch should always be optimized away when inlining.
if (boffset == 0 * BITS) boffset = bit0Offset;
byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
uint bitnum = boffset % BITS_PER_BYTE / BITS; uint bitnum = boffset % BITS_PER_BYTE / BITS;
*reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum)) *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
...@@ -678,37 +670,29 @@ inline void StructBuilder::setDataField( ...@@ -678,37 +670,29 @@ inline void StructBuilder::setDataField(
} }
inline StructBuilder StructBuilder::initInlineStructField( inline StructBuilder StructBuilder::initInlineStructField(
BitCount dataOffset, BitCount inlineDataSize, ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const { WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const {
// This branch should be optimized away. memset(reinterpret_cast<byte*>(data) + dataOffset, 0, inlineDataSize / BYTES);
if (inlineDataSize == 1 * BITS) {
setDataField<bool>(dataOffset / (1 * BITS / ELEMENTS), false);
} else {
memset(reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE / BYTES,
0, inlineDataSize / BITS_PER_BYTE / BYTES);
}
memset(reinterpret_cast<word*>(references) + refIndex * WORDS_PER_REFERENCE, memset(reinterpret_cast<word*>(references) + refIndex * WORDS_PER_REFERENCE,
0, inlineRefCount * WORDS_PER_REFERENCE * BYTES_PER_WORD / BYTES); 0, inlineRefCount * WORDS_PER_REFERENCE * BYTES_PER_WORD / BYTES);
return getInlineStructField(dataOffset, inlineDataSize, refIndex, inlineRefCount); return getInlineStructField(dataOffset, inlineDataSize, refIndex, inlineRefCount);
} }
inline StructBuilder StructBuilder::getInlineStructField( inline StructBuilder StructBuilder::getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize, ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const { WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const {
return StructBuilder( return StructBuilder(
segment, reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE, segment, reinterpret_cast<byte*>(data) + dataOffset,
// WireReference is incomplete here so we have to cast around... Bah. // WireReference is incomplete here so we have to cast around... Bah.
reinterpret_cast<WireReference*>( reinterpret_cast<WireReference*>(
reinterpret_cast<word*>(references) + refIndex * WORDS_PER_REFERENCE), reinterpret_cast<word*>(references) + refIndex * WORDS_PER_REFERENCE),
dataOffset == 0 * BITS ? BitCount(bit0Offset) : dataOffset % BITS_PER_BYTE,
inlineRefCount); inlineRefCount);
} }
inline ListBuilder StructBuilder::initInlineDataListField( inline ListBuilder StructBuilder::initInlineDataListField(
BitCount offset, BitCount inlineSize, ByteCount offset, ByteCount inlineSize,
ElementCount elementCount, FieldSize elementSize) const { ElementCount elementCount, FieldSize elementSize) const {
memset(reinterpret_cast<byte*>(data) + offset / BITS_PER_BYTE, 0, memset(reinterpret_cast<byte*>(data) + offset, 0, inlineSize / BYTES);
inlineSize / BITS_PER_BYTE / BYTES);
return getInlineDataListField(offset, elementCount, elementSize); return getInlineDataListField(offset, elementCount, elementSize);
} }
...@@ -721,20 +705,20 @@ inline ListBuilder StructBuilder::initInlinePointerListField( ...@@ -721,20 +705,20 @@ inline ListBuilder StructBuilder::initInlinePointerListField(
} }
inline ListBuilder StructBuilder::initInlineStructListField( inline ListBuilder StructBuilder::initInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount, ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const { StructSize elementSize) const {
memset(reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE, 0, memset(reinterpret_cast<byte*>(data) + dataOffset, 0,
elementSize.dataBits / BITS_PER_BYTE / BYTES); elementSize.dataBytes / BYTES);
memset(reinterpret_cast<word*>(references) + ptrOffset * WORDS_PER_REFERENCE, 0, memset(reinterpret_cast<word*>(references) + ptrOffset * WORDS_PER_REFERENCE, 0,
elementSize.pointers * BYTES_PER_REFERENCE / BYTES); elementSize.pointers * BYTES_PER_REFERENCE / BYTES);
return getInlineStructListField(dataOffset, ptrOffset, elementCount, elementSize); return getInlineStructListField(dataOffset, ptrOffset, elementCount, elementSize);
} }
inline ListBuilder StructBuilder::getInlineDataListField( inline ListBuilder StructBuilder::getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const { ByteCount offset, ElementCount elementCount, FieldSize elementSize) const {
return ListBuilder( return ListBuilder(
segment, reinterpret_cast<byte*>(data) + offset / BITS_PER_BYTE, nullptr, segment, reinterpret_cast<byte*>(data) + offset, nullptr,
bitsPerElement(elementSize), 0 * REFERENCES / ELEMENTS, elementCount); bytesPerElement(elementSize), 0 * REFERENCES / ELEMENTS, elementCount);
} }
inline ListBuilder StructBuilder::getInlinePointerListField( inline ListBuilder StructBuilder::getInlinePointerListField(
...@@ -743,17 +727,17 @@ inline ListBuilder StructBuilder::getInlinePointerListField( ...@@ -743,17 +727,17 @@ inline ListBuilder StructBuilder::getInlinePointerListField(
segment, nullptr, segment, nullptr,
reinterpret_cast<WireReference*>( reinterpret_cast<WireReference*>(
reinterpret_cast<word*>(references) + offset * WORDS_PER_REFERENCE), reinterpret_cast<word*>(references) + offset * WORDS_PER_REFERENCE),
0 * BITS / ELEMENTS, 1 * REFERENCES / ELEMENTS, elementCount); 0 * BYTES / ELEMENTS, 1 * REFERENCES / ELEMENTS, elementCount);
} }
inline ListBuilder StructBuilder::getInlineStructListField( inline ListBuilder StructBuilder::getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount, ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const { StructSize elementSize) const {
return ListBuilder( return ListBuilder(
segment, reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE, segment, reinterpret_cast<byte*>(data) + dataOffset,
reinterpret_cast<WireReference*>( reinterpret_cast<WireReference*>(
reinterpret_cast<word*>(references) + ptrOffset * WORDS_PER_REFERENCE), reinterpret_cast<word*>(references) + ptrOffset * WORDS_PER_REFERENCE),
elementSize.dataBits / ELEMENTS, elementSize.pointers / ELEMENTS, elementSize.dataBytes / ELEMENTS, elementSize.pointers / ELEMENTS,
elementCount); elementCount);
} }
...@@ -761,7 +745,7 @@ inline ListBuilder StructBuilder::getInlineStructListField( ...@@ -761,7 +745,7 @@ inline ListBuilder StructBuilder::getInlineStructListField(
template <typename T> template <typename T>
T StructReader::getDataField(ElementCount offset) const { T StructReader::getDataField(ElementCount offset) const {
if ((offset + 1 * ELEMENTS) * capnproto::bitsPerElement<T>() <= dataSize) { if ((offset + 1 * ELEMENTS) * capnproto::bytesPerElement<T>() <= dataSize) {
return reinterpret_cast<const WireValue<T>*>(data)[offset / ELEMENTS].get(); return reinterpret_cast<const WireValue<T>*>(data)[offset / ELEMENTS].get();
} else { } else {
return static_cast<T>(0); return static_cast<T>(0);
...@@ -771,11 +755,7 @@ T StructReader::getDataField(ElementCount offset) const { ...@@ -771,11 +755,7 @@ T StructReader::getDataField(ElementCount offset) const {
template <> template <>
inline bool StructReader::getDataField<bool>(ElementCount offset) const { inline bool StructReader::getDataField<bool>(ElementCount offset) const {
BitCount boffset = offset * (1 * BITS / ELEMENTS); BitCount boffset = offset * (1 * BITS / ELEMENTS);
if (boffset < dataSize * BITS_PER_BYTE) {
// This branch should always be optimized away when inlining.
if (boffset == 0 * BITS) boffset = bit0Offset;
if (boffset < dataSize) {
const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE; const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE;
return (*reinterpret_cast<const uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0; return (*reinterpret_cast<const uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
} else { } else {
...@@ -794,23 +774,22 @@ T StructReader::getDataField(ElementCount offset, typename MaskType<T>::Type mas ...@@ -794,23 +774,22 @@ T StructReader::getDataField(ElementCount offset, typename MaskType<T>::Type mas
} }
inline StructReader StructReader::getInlineStructField( inline StructReader StructReader::getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize, ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const { WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const {
return StructReader( return StructReader(
segment, reinterpret_cast<const byte*>(data) + dataOffset / BITS_PER_BYTE, segment, reinterpret_cast<const byte*>(data) + dataOffset,
// WireReference is incomplete here so we have to cast around... Bah. // WireReference is incomplete here so we have to cast around... Bah.
reinterpret_cast<const WireReference*>( reinterpret_cast<const WireReference*>(
reinterpret_cast<const word*>(references) + refIndex * WORDS_PER_REFERENCE), reinterpret_cast<const word*>(references) + refIndex * WORDS_PER_REFERENCE),
dataSize, inlineRefCount, dataSize, inlineRefCount,
dataOffset == 0 * BITS ? BitCount(bit0Offset) : dataOffset % BITS_PER_BYTE,
nestingLimit); nestingLimit);
} }
inline ListReader StructReader::getInlineDataListField( inline ListReader StructReader::getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const { ByteCount offset, ElementCount elementCount, FieldSize elementSize) const {
return ListReader( return ListReader(
segment, reinterpret_cast<const byte*>(data) + offset / BITS_PER_BYTE, nullptr, segment, reinterpret_cast<const byte*>(data) + offset, nullptr,
elementCount, bitsPerElement(elementSize), 0 * REFERENCES / ELEMENTS, elementCount, bytesPerElement(elementSize), 0 * REFERENCES / ELEMENTS,
nestingLimit); nestingLimit);
} }
...@@ -820,19 +799,19 @@ inline ListReader StructReader::getInlinePointerListField( ...@@ -820,19 +799,19 @@ inline ListReader StructReader::getInlinePointerListField(
segment, nullptr, segment, nullptr,
reinterpret_cast<const WireReference*>( reinterpret_cast<const WireReference*>(
reinterpret_cast<const word*>(references) + offset * WORDS_PER_REFERENCE), reinterpret_cast<const word*>(references) + offset * WORDS_PER_REFERENCE),
elementCount, 0 * BITS / ELEMENTS, 1 * REFERENCES / ELEMENTS, elementCount, 0 * BYTES / ELEMENTS, 1 * REFERENCES / ELEMENTS,
nestingLimit); nestingLimit);
} }
inline ListReader StructReader::getInlineStructListField( inline ListReader StructReader::getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount, ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const { StructSize elementSize) const {
return ListReader( return ListReader(
segment, reinterpret_cast<const byte*>(data) + dataOffset / BITS_PER_BYTE, segment, reinterpret_cast<const byte*>(data) + dataOffset,
reinterpret_cast<const WireReference*>( reinterpret_cast<const WireReference*>(
reinterpret_cast<const word*>(references) + ptrOffset * WORDS_PER_REFERENCE), reinterpret_cast<const word*>(references) + ptrOffset * WORDS_PER_REFERENCE),
elementCount, elementSize.dataBits / ELEMENTS, elementSize.pointers / ELEMENTS, elementCount, elementSize.dataBytes / ELEMENTS, elementSize.pointers / ELEMENTS,
elementSize.dataBits, elementSize.pointers, nestingLimit); elementSize.dataBytes, elementSize.pointers, nestingLimit);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
...@@ -842,12 +821,13 @@ inline ElementCount ListBuilder::size() { return elementCount; } ...@@ -842,12 +821,13 @@ inline ElementCount ListBuilder::size() { return elementCount; }
template <typename T> template <typename T>
inline T ListBuilder::getDataElement(ElementCount index) const { inline T ListBuilder::getDataElement(ElementCount index) const {
return reinterpret_cast<WireValue<T>*>( return reinterpret_cast<WireValue<T>*>(
reinterpret_cast<byte*>(data) + index * stepBits / BITS_PER_BYTE)->get(); reinterpret_cast<byte*>(data) + index * stepBytes)->get();
} }
template <> template <>
inline bool ListBuilder::getDataElement<bool>(ElementCount index) const { inline bool ListBuilder::getDataElement<bool>(ElementCount index) const {
BitCount bindex = index * stepBits; // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount bindex = index * (1 * BITS / ELEMENTS);
byte* b = reinterpret_cast<byte*>(data) + bindex / BITS_PER_BYTE; byte* b = reinterpret_cast<byte*>(data) + bindex / BITS_PER_BYTE;
return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
} }
...@@ -860,12 +840,13 @@ inline Void ListBuilder::getDataElement<Void>(ElementCount index) const { ...@@ -860,12 +840,13 @@ inline Void ListBuilder::getDataElement<Void>(ElementCount index) const {
template <typename T> template <typename T>
inline void ListBuilder::setDataElement(ElementCount index, typename NoInfer<T>::Type value) const { inline void ListBuilder::setDataElement(ElementCount index, typename NoInfer<T>::Type value) const {
reinterpret_cast<WireValue<T>*>( reinterpret_cast<WireValue<T>*>(
reinterpret_cast<byte*>(data) + index * stepBits / BITS_PER_BYTE)->set(value); reinterpret_cast<byte*>(data) + index * stepBytes)->set(value);
} }
template <> template <>
inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) const { inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) const {
BitCount bindex = index * stepBits; // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount bindex = index * (1 * BITS / ELEMENTS);
byte* b = reinterpret_cast<byte*>(data) + bindex / BITS_PER_BYTE; byte* b = reinterpret_cast<byte*>(data) + bindex / BITS_PER_BYTE;
uint bitnum = bindex % BITS_PER_BYTE / BITS; uint bitnum = bindex % BITS_PER_BYTE / BITS;
*reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum)) *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
...@@ -882,12 +863,13 @@ inline ElementCount ListReader::size() { return elementCount; } ...@@ -882,12 +863,13 @@ inline ElementCount ListReader::size() { return elementCount; }
template <typename T> template <typename T>
inline T ListReader::getDataElement(ElementCount index) const { inline T ListReader::getDataElement(ElementCount index) const {
return reinterpret_cast<const WireValue<T>*>( return reinterpret_cast<const WireValue<T>*>(
reinterpret_cast<const byte*>(data) + index * stepBits / BITS_PER_BYTE)->get(); reinterpret_cast<const byte*>(data) + index * stepBytes)->get();
} }
template <> template <>
inline bool ListReader::getDataElement<bool>(ElementCount index) const { inline bool ListReader::getDataElement<bool>(ElementCount index) const {
BitCount bindex = index * stepBits; // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount bindex = index * (1 * BITS / ELEMENTS);
const byte* b = reinterpret_cast<const byte*>(data) + bindex / BITS_PER_BYTE; const byte* b = reinterpret_cast<const byte*>(data) + bindex / BITS_PER_BYTE;
return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
} }
......
...@@ -276,27 +276,25 @@ struct TestUsing { ...@@ -276,27 +276,25 @@ struct TestUsing {
innerNestedEnum @0 :NestedEnum = quux; innerNestedEnum @0 :NestedEnum = quux;
} }
struct TestInline0 fixed(0 bits) { f @0: Void; } struct TestInline0 fixed() { f @0: Void; }
struct TestInline1 fixed(1 bits) { f @0: Bool; } struct TestInline8 fixed(1 bytes) { f0 @0: Bool; f1 @1: Bool; f2 @2: Bool; }
struct TestInline8 fixed(8 bits) { f0 @0: Bool; f1 @1: Bool; f2 @2: Bool; } struct TestInline16 fixed(2 bytes) { f0 @0: UInt8; f1 @1: UInt8; }
struct TestInline16 fixed(16 bits) { f0 @0: UInt8; f1 @1: UInt8; } struct TestInline32 fixed(4 bytes) { f0 @0: UInt8; f1 @1: UInt16; }
struct TestInline32 fixed(32 bits) { f0 @0: UInt8; f1 @1: UInt16; } struct TestInline64 fixed(8 bytes) { f0 @0: UInt8; f1 @1: UInt32; }
struct TestInline64 fixed(64 bits) { f0 @0: UInt8; f1 @1: UInt32; }
struct TestInline128 fixed(2 words) { f0 @0: UInt64; f1 @1: UInt64; } struct TestInline128 fixed(2 words) { f0 @0: UInt64; f1 @1: UInt64; }
struct TestInline192 fixed(3 words) { f0 @0: UInt64; f1 @1: UInt64; f2 @2: UInt64; } struct TestInline192 fixed(3 words) { f0 @0: UInt64; f1 @1: UInt64; f2 @2: UInt64; }
struct TestInline0p fixed(0 bits, 1 pointers) { f @0 :Inline(TestInline0); p0 @1 :Text; } struct TestInline0p fixed(1 pointers) { f @0 :Inline(TestInline0); p0 @1 :Text; }
struct TestInline1p fixed(1 bits, 1 pointers) { f @0 :Inline(TestInline1); p0 @1 :Text; } struct TestInline8p fixed(1 bytes, 1 pointers) { f @0 :Inline(TestInline8); p0 @1 :Text; }
struct TestInline8p fixed(8 bits, 1 pointers) { f @0 :Inline(TestInline8); p0 @1 :Text; } struct TestInline16p fixed(2 bytes, 2 pointers) { f @0 :Inline(TestInline16); p0 @1 :Text; p1 @2 :Text; }
struct TestInline16p fixed(16 bits, 2 pointers) { f @0 :Inline(TestInline16); p0 @1 :Text; p1 @2 :Text; } struct TestInline32p fixed(4 bytes, 2 pointers) { f @0 :Inline(TestInline32); p0 @1 :Text; p1 @2 :Text; }
struct TestInline32p fixed(32 bits, 2 pointers) { f @0 :Inline(TestInline32); p0 @1 :Text; p1 @2 :Text; } struct TestInline64p fixed(8 bytes, 2 pointers) { f @0 :Inline(TestInline64); p0 @1 :Text; p1 @2 :Text; }
struct TestInline64p fixed(64 bits, 2 pointers) { f @0 :Inline(TestInline64); p0 @1 :Text; p1 @2 :Text; }
struct TestInline128p fixed(2 words, 3 pointers) { f @0 :Inline(TestInline128); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; } struct TestInline128p fixed(2 words, 3 pointers) { f @0 :Inline(TestInline128); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; }
struct TestInline192p fixed(3 words, 3 pointers) { f @0 :Inline(TestInline192); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; } struct TestInline192p fixed(3 words, 3 pointers) { f @0 :Inline(TestInline192); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; }
struct TestInlineLayout { struct TestInlineLayout {
f0 @0 :Inline(TestInline0); f0 @0 :Inline(TestInline0);
f1 @1 :Inline(TestInline1); pad1 @1 :UInt8;
f8 @2 :Inline(TestInline8); f8 @2 :Inline(TestInline8);
f16 @3 :Inline(TestInline16); f16 @3 :Inline(TestInline16);
f32 @4 :Inline(TestInline32); f32 @4 :Inline(TestInline32);
...@@ -305,22 +303,20 @@ struct TestInlineLayout { ...@@ -305,22 +303,20 @@ struct TestInlineLayout {
f192 @7 :Inline(TestInline192); f192 @7 :Inline(TestInline192);
f0p @8 :Inline(TestInline0p); f0p @8 :Inline(TestInline0p);
f1p @9 :Inline(TestInline1p); pad2 @9 :UInt8;
f8p @10 :Inline(TestInline8p); padP @10 :Text;
f16p @11 :Inline(TestInline16p); f8p @11 :Inline(TestInline8p);
f32p @12 :Inline(TestInline32p); f16p @12 :Inline(TestInline16p);
f64p @13 :Inline(TestInline64p); f32p @13 :Inline(TestInline32p);
f128p @14 :Inline(TestInline128p); f64p @14 :Inline(TestInline64p);
f192p @15 :Inline(TestInline192p); f128p @15 :Inline(TestInline128p);
f192p @16 :Inline(TestInline192p);
f1Offset @16 :Inline(TestInline1);
bit @17 :Bool;
} }
struct TestInlineUnions { struct TestInlineUnions {
union0 @0 union { union0 @0 union {
f0 @4 :Inline(TestInline0); f0 @4 :Inline(TestInline0);
f1 @5 :Inline(TestInline1); f1 @5 :Bool; # There used to be a TestInline1 but it was decided to be a bad idea.
f8 @6 :Inline(TestInline8); f8 @6 :Inline(TestInline8);
f16 @7 :Inline(TestInline16); f16 @7 :Inline(TestInline16);
f32 @8 :Inline(TestInline32); f32 @8 :Inline(TestInline32);
...@@ -329,7 +325,7 @@ struct TestInlineUnions { ...@@ -329,7 +325,7 @@ struct TestInlineUnions {
f192 @11 :Inline(TestInline192); f192 @11 :Inline(TestInline192);
f0p @12 :Inline(TestInline0p); f0p @12 :Inline(TestInline0p);
f1p @13 :Inline(TestInline1p); f1p @13 :Bool;
f8p @14 :Inline(TestInline8p); f8p @14 :Inline(TestInline8p);
f16p @15 :Inline(TestInline16p); f16p @15 :Inline(TestInline16p);
f32p @16 :Inline(TestInline32p); f32p @16 :Inline(TestInline32p);
...@@ -343,7 +339,7 @@ struct TestInlineUnions { ...@@ -343,7 +339,7 @@ struct TestInlineUnions {
union1 @1 union { union1 @1 union {
f0 @21 :Inline(TestInline0); f0 @21 :Inline(TestInline0);
f1 @22 :Inline(TestInline1); f1 @22 :Bool;
f8 @23 :Inline(TestInline8); f8 @23 :Inline(TestInline8);
f16 @24 :Inline(TestInline16); f16 @24 :Inline(TestInline16);
f32 @25 :Inline(TestInline32); f32 @25 :Inline(TestInline32);
...@@ -362,7 +358,7 @@ struct TestInlineUnions { ...@@ -362,7 +358,7 @@ struct TestInlineUnions {
# Interleave two unions to be really annoying. # Interleave two unions to be really annoying.
union2 @2 union { union2 @2 union {
f1p @35 :Inline(TestInline1p); f1p @35 :Bool;
f8p @37 :Inline(TestInline8p); f8p @37 :Inline(TestInline8p);
f16p @40 :Inline(TestInline16p); f16p @40 :Inline(TestInline16p);
f32p @42 :Inline(TestInline32p); f32p @42 :Inline(TestInline32p);
...@@ -372,7 +368,7 @@ struct TestInlineUnions { ...@@ -372,7 +368,7 @@ struct TestInlineUnions {
} }
union3 @3 union { union3 @3 union {
f1p @36 :Inline(TestInline1p); f1p @36 :Bool;
f8p @38 :Inline(TestInline8p); f8p @38 :Inline(TestInline8p);
f16p @41 :Inline(TestInline16p); f16p @41 :Inline(TestInline16p);
f32p @43 :Inline(TestInline32p); f32p @43 :Inline(TestInline32p);
...@@ -394,7 +390,7 @@ struct TestInlineLists { ...@@ -394,7 +390,7 @@ struct TestInlineLists {
textList @ 6 : InlineList(Text, 8); textList @ 6 : InlineList(Text, 8);
structList0 @ 7 : InlineList(TestInline0, 2); structList0 @ 7 : InlineList(TestInline0, 2);
structList1 @ 8 : InlineList(TestInline1, 3); structList1 @ 8 : InlineList(Bool, 3);
structList8 @ 9 : InlineList(TestInline8, 4); structList8 @ 9 : InlineList(TestInline8, 4);
structList16 @10 : InlineList(TestInline16, 2); structList16 @10 : InlineList(TestInline16, 2);
structList32 @11 : InlineList(TestInline32, 3); structList32 @11 : InlineList(TestInline32, 3);
...@@ -403,7 +399,7 @@ struct TestInlineLists { ...@@ -403,7 +399,7 @@ struct TestInlineLists {
structList192 @14 : InlineList(TestInline192, 3); structList192 @14 : InlineList(TestInline192, 3);
structList0p @15 : InlineList(TestInline0p, 4); structList0p @15 : InlineList(TestInline0p, 4);
structList1p @16 : InlineList(TestInline1p, 2); structList1p @16 : InlineList(Bool, 2);
structList8p @17 : InlineList(TestInline8p, 3); structList8p @17 : InlineList(TestInline8p, 3);
structList16p @18 : InlineList(TestInline16p, 4); structList16p @18 : InlineList(TestInline16p, 4);
structList32p @19 : InlineList(TestInline32p, 2); structList32p @19 : InlineList(TestInline32p, 2);
...@@ -435,7 +431,6 @@ struct TestStructLists { ...@@ -435,7 +431,6 @@ struct TestStructLists {
struct TestInlineDefaults { struct TestInlineDefaults {
normal @0 :TestInlineLayout = ( normal @0 :TestInlineLayout = (
f0 = (f = void), f0 = (f = void),
f1 = (f = true),
f8 = (f0 = true, f1 = false, f2 = true), f8 = (f0 = true, f1 = false, f2 = true),
f16 = (f0 = 123, f1 = 45), f16 = (f0 = 123, f1 = 45),
f32 = (f0 = 67, f1 = 8901), f32 = (f0 = 67, f1 = 8901),
...@@ -444,7 +439,6 @@ struct TestInlineDefaults { ...@@ -444,7 +439,6 @@ struct TestInlineDefaults {
f192 = (f0 = 7890123456789, f1 = 2345678901234, f2 = 5678901234567), f192 = (f0 = 7890123456789, f1 = 2345678901234, f2 = 5678901234567),
f0p = (p0 = "foo"), f0p = (p0 = "foo"),
f1p = (f = (f = false), p0 = "bar"),
f8p = (f = (f0 = true, f1 = true, f2 = false), p0 = "baz"), f8p = (f = (f0 = true, f1 = true, f2 = false), p0 = "baz"),
f16p = (f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux"), f16p = (f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux"),
f32p = (f = (f0 = 54, f1 = 32109), p0 = "corge", p1 = "grault"), f32p = (f = (f0 = 54, f1 = 32109), p0 = "corge", p1 = "grault"),
...@@ -457,7 +451,7 @@ struct TestInlineDefaults { ...@@ -457,7 +451,7 @@ struct TestInlineDefaults {
unions @1 :TestInlineUnions = ( unions @1 :TestInlineUnions = (
union0 = f32(f0 = 67, f1 = 8901), union0 = f32(f0 = 67, f1 = 8901),
union1 = f128(f0 = 1234567890123, f1 = 4567890123456), union1 = f128(f0 = 1234567890123, f1 = 4567890123456),
union2 = f1p(p0 = "foo"), union2 = f8p(p0 = "foo"),
union3 = f16p(f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux")); union3 = f16p(f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux"));
lists @2 :TestInlineLists = ( lists @2 :TestInlineLists = (
...@@ -470,7 +464,6 @@ struct TestInlineDefaults { ...@@ -470,7 +464,6 @@ struct TestInlineDefaults {
textList = ["foo", "bar", "baz", "qux", "quux", "corge", "grault", "garply"], textList = ["foo", "bar", "baz", "qux", "quux", "corge", "grault", "garply"],
structList0 = [(f = void), ()], structList0 = [(f = void), ()],
structList1 = [(f = true), (f = false), (f = true)],
structList8 = [(f0 = true, f1 = false, f2 = false), structList8 = [(f0 = true, f1 = false, f2 = false),
(f0 = false, f1 = true, f2 = false), (f0 = false, f1 = true, f2 = false),
(f0 = true, f1 = true, f2 = false), (f0 = true, f1 = true, f2 = false),
...@@ -487,7 +480,6 @@ struct TestInlineDefaults { ...@@ -487,7 +480,6 @@ struct TestInlineDefaults {
structList0p = [(f = (f = void), p0 = "foo"), (p0 = "bar"), structList0p = [(f = (f = void), p0 = "foo"), (p0 = "bar"),
(f = (), p0 = "baz"), (p0 = "qux")], (f = (), p0 = "baz"), (p0 = "qux")],
structList1p = [(f = (f = true), p0 = "quux"), (p0 = "corge")],
structList8p = [(f = (f0 = true), p0 = "grault"), (p0 = "garply"), (p0 = "waldo")], structList8p = [(f = (f0 = true), p0 = "grault"), (p0 = "garply"), (p0 = "waldo")],
structList16p = [(f = (f0 = 123), p0 = "fred", p1 = "plugh"), structList16p = [(f = (f0 = 123), p0 = "fred", p1 = "plugh"),
(p0 = "xyzzy", p1 = "thud"), (p0 = "xyzzy", p1 = "thud"),
......
...@@ -682,7 +682,8 @@ packUnion :: UnionDesc -> PackingState -> Map.Map Integer UnionPackingState ...@@ -682,7 +682,8 @@ packUnion :: UnionDesc -> PackingState -> Map.Map Integer UnionPackingState
packUnion _ state unionState = (DataOffset Size16 offset, newState, unionState) where packUnion _ state unionState = (DataOffset Size16 offset, newState, unionState) where
(offset, newState) = packData Size16 state (offset, newState) = packData Size16 state
stripHolesFromFirstWord Size1 _ = Size1 -- Nothing left to strip. stripHolesFromFirstWord Size1 _ = error "can't get this far"
stripHolesFromFirstWord Size8 _ = Size8 -- Don't reduce to less than a byte.
stripHolesFromFirstWord size holes = let stripHolesFromFirstWord size holes = let
nextSize = pred size nextSize = pred size
in case Map.lookup nextSize holes of in case Map.lookup nextSize holes of
...@@ -717,13 +718,12 @@ enforceFixed Nothing sizes = return sizes ...@@ -717,13 +718,12 @@ enforceFixed Nothing sizes = return sizes
enforceFixed (Just (Located pos (requestedDataSize, requestedPointerCount))) enforceFixed (Just (Located pos (requestedDataSize, requestedPointerCount)))
(actualDataSize, actualPointerCount) = do (actualDataSize, actualPointerCount) = do
validatedRequestedDataSize <- case requestedDataSize of validatedRequestedDataSize <- case requestedDataSize of
1 -> return DataSection1
8 -> return DataSection8 8 -> return DataSection8
16 -> return DataSection16 16 -> return DataSection16
32 -> return DataSection32 32 -> return DataSection32
s | mod s 64 == 0 -> return $ DataSectionWords $ div s 64 s | mod s 64 == 0 -> return $ DataSectionWords $ div s 64
_ -> makeError pos $ printf "Struct data section size must be a whole number of words \ _ -> makeError pos $ printf "Struct data section size must be a whole number of words \
\or 0, 1, 8, 16, or 32 bits." \or 0, 1, 2, 4, or 8 bytes."
recover () $ when (dataSectionBits actualDataSize > dataSectionBits validatedRequestedDataSize) $ recover () $ when (dataSectionBits actualDataSize > dataSectionBits validatedRequestedDataSize) $
makeError pos $ printf "Struct data section size is %s which exceeds specified maximum of \ makeError pos $ printf "Struct data section size is %s which exceeds specified maximum of \
......
...@@ -161,12 +161,12 @@ fieldOffsetInteger VoidOffset = "0" ...@@ -161,12 +161,12 @@ fieldOffsetInteger VoidOffset = "0"
fieldOffsetInteger (DataOffset _ o) = show o fieldOffsetInteger (DataOffset _ o) = show o
fieldOffsetInteger (PointerOffset o) = show o fieldOffsetInteger (PointerOffset o) = show o
fieldOffsetInteger (InlineCompositeOffset d p ds ps) = let fieldOffsetInteger (InlineCompositeOffset d p ds ps) = let
bitSize = dataSectionBits ds byteSize = div (dataSectionBits ds) 8
bitOffset = case ds of byteOffset = case ds of
DataSectionWords _ -> d * 64 DataSectionWords _ -> d * 8
_ -> d * bitSize _ -> d * byteSize
in printf "%d * ::capnproto::BITS, %d * ::capnproto::BITS, \ in printf "%d * ::capnproto::BYTES, %d * ::capnproto::BYTES, \
\%d * ::capnproto::REFERENCES, %d * ::capnproto::REFERENCES" bitOffset bitSize p ps \%d * ::capnproto::REFERENCES, %d * ::capnproto::REFERENCES" byteOffset byteSize p ps
isDefaultZero VoidDesc = True isDefaultZero VoidDesc = True
isDefaultZero (BoolDesc b) = not b isDefaultZero (BoolDesc b) = not b
...@@ -266,11 +266,11 @@ fieldContext parent desc = mkStrContext context where ...@@ -266,11 +266,11 @@ fieldContext parent desc = mkStrContext context where
_ -> muNull _ -> muNull
context "fieldInlineDataOffset" = case fieldOffset desc of context "fieldInlineDataOffset" = case fieldOffset desc of
InlineCompositeOffset off _ size _ -> InlineCompositeOffset off _ size _ ->
MuVariable (off * dataSizeInBits (dataSectionAlignment size)) MuVariable (off * div (dataSizeInBits (dataSectionAlignment size)) 8)
_ -> muNull _ -> muNull
context "fieldInlineDataSize" = case fieldOffset desc of context "fieldInlineDataSize" = case fieldOffset desc of
InlineCompositeOffset _ _ size _ -> InlineCompositeOffset _ _ size _ ->
MuVariable $ dataSectionBits size MuVariable $ div (dataSectionBits size) 8
_ -> muNull _ -> muNull
context "fieldInlinePointerOffset" = case fieldOffset desc of context "fieldInlinePointerOffset" = case fieldOffset desc of
InlineCompositeOffset _ off _ _ -> MuVariable off InlineCompositeOffset _ off _ _ -> MuVariable off
...@@ -330,7 +330,7 @@ structContext parent desc = mkStrContext context where ...@@ -330,7 +330,7 @@ structContext parent desc = mkStrContext context where
context "structFields" = MuList $ map (fieldContext context) $ structFields desc context "structFields" = MuList $ map (fieldContext context) $ structFields desc
context "structUnions" = MuList $ map (unionContext context) $ structUnions desc context "structUnions" = MuList $ map (unionContext context) $ structUnions desc
context "structDataSize" = MuVariable $ dataSectionWordSize $ structDataSize desc context "structDataSize" = MuVariable $ dataSectionWordSize $ structDataSize desc
context "structDataBits" = MuVariable $ dataSectionBits $ structDataSize desc context "structDataBytes" = MuVariable (div (dataSectionBits (structDataSize desc)) 8)
context "structReferenceCount" = MuVariable $ structPointerCount desc context "structReferenceCount" = MuVariable $ structPointerCount desc
context "structNestedEnums" = context "structNestedEnums" =
MuList $ map (enumContext context) [m | DescEnum m <- structMembers desc] MuList $ map (enumContext context) [m | DescEnum m <- structMembers desc]
......
...@@ -254,15 +254,14 @@ combineFixedSizes (_, Just _) (FixedPointers _) = ...@@ -254,15 +254,14 @@ combineFixedSizes (_, Just _) (FixedPointers _) =
fixedSize = do fixedSize = do
size <- literalInt size <- literalInt
(exactIdentifier "bit" >> return (FixedData size)) -- We do not allow single-bit structs because most CPUs cannot address bits.
<|> (exactIdentifier "bits" >> return (FixedData size)) (exactIdentifier "byte" >> return (FixedData (8 * size)))
<|> (exactIdentifier "byte" >> return (FixedData (8 * size)))
<|> (exactIdentifier "bytes" >> return (FixedData (8 * size))) <|> (exactIdentifier "bytes" >> return (FixedData (8 * size)))
<|> (exactIdentifier "word" >> return (FixedData (64 * size))) <|> (exactIdentifier "word" >> return (FixedData (64 * size)))
<|> (exactIdentifier "words" >> return (FixedData (64 * size))) <|> (exactIdentifier "words" >> return (FixedData (64 * size)))
<|> (exactIdentifier "pointer" >> return (FixedPointers size)) <|> (exactIdentifier "pointer" >> return (FixedPointers size))
<|> (exactIdentifier "pointers" >> return (FixedPointers size)) <|> (exactIdentifier "pointers" >> return (FixedPointers size))
<?> "\"bits\", \"bytes\", \"words\", or \"pointers\"" <?> "\"bytes\", \"words\", or \"pointers\""
structLine :: Maybe [Located Statement] -> TokenParser Declaration structLine :: Maybe [Located Statement] -> TokenParser Declaration
structLine Nothing = usingDecl <|> constantDecl <|> fieldDecl <|> annotationDecl structLine Nothing = usingDecl <|> constantDecl <|> fieldDecl <|> annotationDecl
......
...@@ -263,9 +263,9 @@ dataSizeToSectionSize Size32 = DataSection32 ...@@ -263,9 +263,9 @@ dataSizeToSectionSize Size32 = DataSection32
dataSizeToSectionSize Size64 = DataSectionWords 1 dataSizeToSectionSize Size64 = DataSectionWords 1
dataSectionSizeString DataSection1 = "1 bits" dataSectionSizeString DataSection1 = "1 bits"
dataSectionSizeString DataSection8 = "8 bits" dataSectionSizeString DataSection8 = "1 bytes"
dataSectionSizeString DataSection16 = "16 bits" dataSectionSizeString DataSection16 = "2 bytes"
dataSectionSizeString DataSection32 = "32 bits" dataSectionSizeString DataSection32 = "4 bytes"
dataSectionSizeString (DataSectionWords n) = show n ++ " words" dataSectionSizeString (DataSectionWords n) = show n ++ " words"
data DataSize = Size1 | Size8 | Size16 | Size32 | Size64 deriving(Eq, Ord, Enum) data DataSize = Size1 | Size8 | Size16 | Size32 | Size64 deriving(Eq, Ord, Enum)
...@@ -319,9 +319,9 @@ fieldSize (InlineStructType StructDesc { structDataSize = ds, structPointerCount ...@@ -319,9 +319,9 @@ fieldSize (InlineStructType StructDesc { structDataSize = ds, structPointerCount
fieldSize (InterfaceType _) = SizeReference fieldSize (InterfaceType _) = SizeReference
fieldSize (ListType _) = SizeReference fieldSize (ListType _) = SizeReference
fieldSize (InlineListType element size) = let fieldSize (InlineListType element size) = let
-- We intentionally do not allow single-bit lists because most CPUs cannot address bits.
minDataSectionForBits bits minDataSectionForBits bits
| bits <= 0 = DataSectionWords 0 | bits <= 0 = DataSectionWords 0
| bits <= 1 = DataSection1
| bits <= 8 = DataSection8 | bits <= 8 = DataSection8
| bits <= 16 = DataSection16 | bits <= 16 = DataSection16
| bits <= 32 = DataSection32 | bits <= 32 = DataSection32
......
...@@ -70,7 +70,7 @@ struct {{typeFullName}} { ...@@ -70,7 +70,7 @@ struct {{typeFullName}} {
static constexpr ::capnproto::internal::StructSize STRUCT_SIZE = static constexpr ::capnproto::internal::StructSize STRUCT_SIZE =
::capnproto::internal::StructSize({{structDataSize}} * ::capnproto::WORDS, ::capnproto::internal::StructSize({{structDataSize}} * ::capnproto::WORDS,
{{structReferenceCount}} * ::capnproto::REFERENCES, {{structReferenceCount}} * ::capnproto::REFERENCES,
{{structDataBits}} * ::capnproto::BITS); {{structDataBytes}} * ::capnproto::BYTES);
{{/typeStruct}} {{/typeStruct}}
{{#typeUnion}} {{#typeUnion}}
...@@ -375,7 +375,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() { ...@@ -375,7 +375,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
"Must check which() before get()ing a union member."); "Must check which() before get()ing a union member.");
{{/fieldUnion}} {{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getInlineDataListField( return {{fieldType}}::Reader(_reader.getInlineDataListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS, {{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS, {{fieldInlineListSize}} * ::capnproto::ELEMENTS,
::capnproto::internal::FieldSize::{{fieldElementSize}})); ::capnproto::internal::FieldSize::{{fieldElementSize}}));
} }
...@@ -386,8 +386,8 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}( ...@@ -386,8 +386,8 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}}); {{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}} {{/fieldUnion}}
return {{fieldType}}::Builder(_builder.initInlineDataListField( return {{fieldType}}::Builder(_builder.initInlineDataListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS, {{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlineDataSize}} * ::capnproto::BITS, {{fieldInlineDataSize}} * ::capnproto::BYTES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS, {{fieldInlineListSize}} * ::capnproto::ELEMENTS,
::capnproto::internal::FieldSize::{{fieldElementSize}})); ::capnproto::internal::FieldSize::{{fieldElementSize}}));
} }
...@@ -397,7 +397,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() ...@@ -397,7 +397,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}()
"Must check which() before get()ing a union member."); "Must check which() before get()ing a union member.");
{{/fieldUnion}} {{/fieldUnion}}
return {{fieldType}}::Builder(_builder.getInlineDataListField( return {{fieldType}}::Builder(_builder.getInlineDataListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS, {{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS, {{fieldInlineListSize}} * ::capnproto::ELEMENTS,
::capnproto::internal::FieldSize::{{fieldElementSize}})); ::capnproto::internal::FieldSize::{{fieldElementSize}}));
} }
...@@ -509,7 +509,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() { ...@@ -509,7 +509,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
"Must check which() before get()ing a union member."); "Must check which() before get()ing a union member.");
{{/fieldUnion}} {{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getInlineStructListField( return {{fieldType}}::Reader(_reader.getInlineStructListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS, {{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlinePointerOffset}} * ::capnproto::REFERENCES, {{fieldInlinePointerOffset}} * ::capnproto::REFERENCES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS, {{fieldInlineListSize}} * ::capnproto::ELEMENTS,
{{fieldElementType}}::STRUCT_SIZE)); {{fieldElementType}}::STRUCT_SIZE));
...@@ -521,7 +521,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}( ...@@ -521,7 +521,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}}); {{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}} {{/fieldUnion}}
return {{fieldType}}::Builder(_builder.initInlineStructListField( return {{fieldType}}::Builder(_builder.initInlineStructListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS, {{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlinePointerOffset}} * ::capnproto::REFERENCES, {{fieldInlinePointerOffset}} * ::capnproto::REFERENCES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS, {{fieldInlineListSize}} * ::capnproto::ELEMENTS,
{{fieldElementType}}::STRUCT_SIZE)); {{fieldElementType}}::STRUCT_SIZE));
...@@ -532,7 +532,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() ...@@ -532,7 +532,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}()
"Must check which() before get()ing a union member."); "Must check which() before get()ing a union member.");
{{/fieldUnion}} {{/fieldUnion}}
return {{fieldType}}::Builder(_builder.getInlineStructListField( return {{fieldType}}::Builder(_builder.getInlineStructListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS, {{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlinePointerOffset}} * ::capnproto::REFERENCES, {{fieldInlinePointerOffset}} * ::capnproto::REFERENCES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS, {{fieldInlineListSize}} * ::capnproto::ELEMENTS,
{{fieldElementType}}::STRUCT_SIZE)); {{fieldElementType}}::STRUCT_SIZE));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment