Skip to content

Commit c8f3bec

Browse files
committed
cxx-qt-lib: ensure correct sizes for wasm 32bit
Related to #414
1 parent b560c29 commit c8f3bec

File tree

7 files changed

+62
-22
lines changed

7 files changed

+62
-22
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3333

3434
- Support for generating correct C++ code for `Pin<T>` Rust types
3535
- Support namespace attribute on shared types, QObject struct, and extern blocks
36+
- Asserts for 32bit platforms such as Wasm
3637

3738
## [0.4.1](https://github.com/KDAB/cxx-qt/compare/v0.4.0...v0.4.1) - 2022-11-18
3839

crates/cxx-qt-lib/src/core/qmodelindex.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@
88

99
#include "../assertion_utils.h"
1010

11-
// QModelIndex has two ints, a uint pointer, and a pointer.
12-
// This results in 4 + 4 + 4 + 8 = 20, then due to compiler padding this results
13-
// in size of 24 or three pointers.
11+
// QModelIndex has two ints, a quint pointer (same as size_t), and a pointer.
1412
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/itemmodels/qabstractitemmodel.h?h=v5.15.6-lts-lgpl#n93
1513
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/itemmodels/qabstractitemmodel.h?h=v6.2.4#n195
1614
assert_alignment_and_size(QModelIndex,
1715
alignof(::std::size_t),
18-
sizeof(::std::size_t[3]));
16+
(sizeof(::std::int32_t) * 2) + sizeof(::std::size_t) +
17+
sizeof(::std::size_t));
1918

2019
static_assert(::std::is_trivially_copyable<QModelIndex>::value);

crates/cxx-qt-lib/src/core/qmodelindex.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ mod ffi {
5656
#[derive(Clone)]
5757
#[repr(C)]
5858
pub struct QModelIndex {
59-
_space: MaybeUninit<[usize; 3]>,
59+
_r: MaybeUninit<i32>,
60+
_c: MaybeUninit<i32>,
61+
_i: MaybeUninit<usize>,
62+
_m: MaybeUninit<usize>,
6063
}
6164

6265
impl Default for QModelIndex {

crates/cxx-qt-lib/src/core/qvariant/mod.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,22 @@ pub struct QVariant {
5151
///
5252
/// Qt5 QVariant has one member, which contains three uints (but they are optimised to a size of 8) and a union
5353
/// Qt6 QVariant has one member, which contains three pointers and a union (pointer largest)
54+
_data: MaybeUninit<f64>,
55+
56+
// Compiler optimisations reduce the size of the uint to a ushort
57+
#[cfg(qt_version_major = "5")]
58+
_type: MaybeUninit<u16>,
59+
#[cfg(qt_version_major = "5")]
60+
_is_shared: MaybeUninit<u16>,
5461
#[cfg(qt_version_major = "5")]
55-
_space: MaybeUninit<[usize; 2]>,
62+
_is_null: MaybeUninit<u16>,
63+
64+
#[cfg(qt_version_major = "6")]
65+
_is_shared: MaybeUninit<usize>,
66+
#[cfg(qt_version_major = "6")]
67+
_is_null: MaybeUninit<usize>,
5668
#[cfg(qt_version_major = "6")]
57-
_space: MaybeUninit<[usize; 4]>,
69+
_packed_type: MaybeUninit<usize>,
5870
}
5971

6072
impl Clone for QVariant {

crates/cxx-qt-lib/src/core/qvariant/qvariant.cpp

+32-11
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,45 @@
1313

1414
// The layout has changed between Qt 5 and Qt 6
1515
//
16-
// Qt5 QVariant has one member, which contains three uints and a union.
17-
// The three uints are optimised to a reduced size, resulting in a combined size
18-
// of two pointers.
19-
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qvariant.h?h=v5.15.6-lts-lgpl#n491
20-
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qvariant.h?h=v5.15.6-lts-lgpl#n411
21-
//
2216
// Qt6 QVariant has one member, which contains three pointers and a union
23-
// (with a pointer as the largest member)
17+
// (with a pointer / double as the largest member)
2418
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qvariant.h?h=v6.2.4#n540
2519
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qvariant.h?h=v6.2.4#n474
20+
//
21+
// Qt5 QVariant has one member, which contains three uints and a union
22+
// (with a pointer / double as the largest member)
23+
// The three uints are optimised to a reduced size of ushorts
24+
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qvariant.h?h=v5.15.6-lts-lgpl#n491
25+
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qvariant.h?h=v5.15.6-lts-lgpl#n411
2626
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
27+
28+
#if (QT_POINTER_SIZE == 4)
29+
// 32bit is 3 * 32bit ptr (12) + union with double (8) + 4 bytes padding
30+
// alignment is 8 byte on 32bit systems as well due to the double
2731
assert_alignment_and_size(QVariant,
28-
alignof(::std::size_t),
29-
sizeof(::std::size_t[4]));
32+
alignof(double),
33+
(sizeof(::std::size_t) * 3) + sizeof(double) +
34+
4 /* compiler padding */);
3035
#else
36+
// 64bit is 3 * 64ptr ptr (16) + union with double (8)
37+
// alignment is 8 bytes from the double or the pointer on 64bit systems
3138
assert_alignment_and_size(QVariant,
32-
alignof(::std::size_t),
33-
sizeof(::std::size_t[2]));
39+
alignof(double),
40+
(sizeof(::std::size_t) * 3) + sizeof(double));
41+
#endif
42+
43+
#else
44+
45+
// 3 * uint (12) + union with double (8)
46+
// but due to compiler optimisation it ends up as
47+
// 3 * ushort (6) + union with double (8) + 2 bytes padding
48+
// alignment is 8 byte on 32bit systems as well due to the double
49+
assert_alignment_and_size(
50+
QVariant,
51+
alignof(double),
52+
(sizeof(::std::uint16_t /* compiler optimised from ::std::uint32_t */) * 3) +
53+
sizeof(double) + 2 /* compiler padding */);
54+
3455
#endif
3556

3657
static_assert(!::std::is_trivially_copy_assignable<QVariant>::value);

crates/cxx-qt-lib/src/gui/qcolor.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
#include "../assertion_utils.h"
1313

1414
// QColor has an enum with six values and a union with the largest being five
15-
// ushorts. This results in (5 * std::uint16) + std::uint32_t = 14, then due to
16-
// compiler padding this results in a sizeof 16 or two pointers.
15+
// ushorts. This results in std::int32_t + (5 * std::uint16) = 14, then due to
16+
// compiler padding this results in a sizeof 16.
1717
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/painting/qcolor.h?h=v5.15.6-lts-lgpl#n262
1818
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/painting/qcolor.h?h=v6.2.4#n237
1919
assert_alignment_and_size(QColor,
2020
alignof(::std::size_t),
21-
sizeof(::std::size_t[2]));
21+
sizeof(::std::int32_t) +
22+
(sizeof(::std::uint16_t) * 5) +
23+
2 /* compiler padding */);
2224

2325
// QColor still had copy & move constructors in Qt 5 but they were basically
2426
// trivial.

crates/cxx-qt-lib/src/gui/qcolor.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ mod ffi {
5858
#[derive(Clone)]
5959
#[repr(C)]
6060
pub struct QColor {
61-
_space: MaybeUninit<[usize; 2]>,
61+
_cspec: MaybeUninit<i32>,
62+
_ct: MaybeUninit<[u16; 5]>,
63+
_padding: MaybeUninit<u16>,
6264
}
6365

6466
impl QColor {

0 commit comments

Comments
 (0)