From 5c64ac4ae0433039bb91e6579614f2796ecd42cb Mon Sep 17 00:00:00 2001 From: Gabriel Ozouf Date: Wed, 10 Apr 2024 10:13:10 +0200 Subject: [PATCH] [poincare/preferences] Fix alignment for emscripten --- apps/global_preferences.h | 8 ++- ion/include/ion/exam_mode.h | 15 ++++-- ion/src/shared/exam_mode.cpp | 11 ++-- omg/include/omg/bit_helper.h | 72 +++++++++++-------------- poincare/include/poincare/exam_mode.h | 12 +++-- poincare/include/poincare/preferences.h | 12 ++++- poincare/src/preferences.cpp | 16 +++--- 7 files changed, 80 insertions(+), 66 deletions(-) diff --git a/apps/global_preferences.h b/apps/global_preferences.h index 0ac7abc61f..2cf18c7be7 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -20,7 +20,8 @@ class GlobalPreferences { static GlobalPreferences* SharedGlobalPreferences(); GlobalPreferences() - : m_brightnessLevel(Ion::Backlight::MaxBrightness), + : m_version(k_version), + m_brightnessLevel(Ion::Backlight::MaxBrightness), m_showPopUp(true), m_font(KDFont::Size::Large) { setLanguage(I18n::Language::EN); @@ -106,6 +107,8 @@ class GlobalPreferences { void setFont(KDFont::Size font) { m_font = font; } private: + constexpr static int k_version = 0x20240401; + const CountryPreferences& preferences() const { return I18n::CountryPreferencesArray[static_cast(m_country)]; } @@ -119,10 +122,11 @@ class GlobalPreferences { static_assert(I18n::NumberOfCountries > 0, "I18n::NumberOfCountries is not superior to 0"); - int m_version = 0x20240401; #if __EMSCRIPTEN__ + emscripten_align1_int m_version; emscripten_align1_int m_brightnessLevel; #else + int m_version; int m_brightnessLevel; #endif I18n::Language m_language; diff --git a/ion/include/ion/exam_mode.h b/ion/include/ion/exam_mode.h index 40b6a5b67f..9009d2da9f 100644 --- a/ion/include/ion/exam_mode.h +++ b/ion/include/ion/exam_mode.h @@ -54,7 +54,9 @@ class Configuration { Configuration() : Configuration(-1) {} Configuration(Int raw) : m_bits(raw) {} - bool operator==(const Configuration& other) const { return m_bits == m_bits; } + bool operator==(const Configuration& other) const { + return m_bits == other.m_bits; + } bool operator!=(const Configuration& other) const { return !(*this == other); } @@ -70,10 +72,15 @@ class Configuration { static_assert(static_cast(Bits::NumberOfBits) == OMG::BitHelper::numberOfBitsIn()); - bool configurable() const { return m_bits.get(Bits::Configurable); } - Int data() const { return m_bits.get(Bits::DataLast, Bits::DataFirst); } + bool configurable() const { + return OMG::BitHelper::bitAtIndex(m_bits, Bits::Configurable); + } + Int data() const { + return OMG::BitHelper::bitsBetweenIndexes(m_bits, Bits::DataLast, + Bits::DataFirst); + } - OMG::BitHelper::BitField m_bits; + Int m_bits; }; static_assert( diff --git a/ion/src/shared/exam_mode.cpp b/ion/src/shared/exam_mode.cpp index 6137d416f5..f0e2e1a06f 100644 --- a/ion/src/shared/exam_mode.cpp +++ b/ion/src/shared/exam_mode.cpp @@ -57,11 +57,12 @@ void set(Configuration config) { // Class Configuration -Configuration::Configuration(Ruleset rules, Int flags) { +Configuration::Configuration(Ruleset rules, Int flags) : m_bits(0) { bool configurable = rules == Ruleset::PressToTest; - m_bits.set(Bits::Configurable, Bits::Configurable, configurable) - .set(Bits::DataLast, Bits::DataFirst, - configurable ? flags : static_cast(rules)); + OMG::BitHelper::setBitAtIndex(m_bits, Bits::Configurable, configurable); + OMG::BitHelper::setBitsBetweenIndexes( + m_bits, Bits::DataLast, Bits::DataFirst, + configurable ? flags : static_cast(rules)); assert(!isUninitialized()); } @@ -77,7 +78,7 @@ Int Configuration::flags() const { } bool Configuration::isUninitialized() const { - bool clearBit = m_bits.get(Bits::Cleared); + bool clearBit = OMG::BitHelper::bitAtIndex(m_bits, Bits::Cleared); return clearBit || (!configurable() && data() >= static_cast(Ruleset::NumberOfRulesets)); } diff --git a/omg/include/omg/bit_helper.h b/omg/include/omg/bit_helper.h index 946ba65fd1..a50d196058 100644 --- a/omg/include/omg/bit_helper.h +++ b/omg/include/omg/bit_helper.h @@ -29,6 +29,10 @@ constexpr bool bitAtIndex(T mask, size_t i) { assert(i >= 0 && i < numberOfBitsIn()); return (mask >> i) & 1U; } +template +constexpr bool bitAtIndex(T mask, I i) { + return bitAtIndex(mask, static_cast(i)); +} template constexpr void setBitAtIndex(T& mask, size_t i, bool b) { @@ -40,6 +44,32 @@ constexpr void setBitAtIndex(T& mask, size_t i, bool b) { mask &= ~(one << i); } } +template +constexpr void setBitAtIndex(T& mask, I i, bool b) { + setBitAtIndex(mask, static_cast(i), b); +} + +template +constexpr T bitsBetweenIndexes(T bits, size_t high, size_t low) { + return (bits >> low) & ((static_cast(1) << (high - low + 1)) - 1); +} +template +constexpr T bitsBetweenIndexes(T bits, I high, I low) { + return bitsBetweenIndexes(bits, static_cast(high), + static_cast(low)); +} + +template +constexpr void setBitsBetweenIndexes(T& bits, size_t high, size_t low, + T value) { + T mask = ((static_cast(1) << (high - low + 1)) - static_cast(1)) << low; + bits = (bits & ~mask) | ((value << low) & mask); +} +template +constexpr void setBitsBetweenIndexes(T& bits, I high, I low, T value) { + setBitsBetweenIndexes(bits, static_cast(high), + static_cast(low), value); +} constexpr inline size_t countLeadingZeros(uint32_t i) { return __builtin_clz(i); @@ -76,48 +106,6 @@ uint8_t log2(T v) { return numberOfBitsIn(); } -/* FIXME This could be the base class for Ion::Device::Regs::Register, but - * Register gets a little more specific with inline and volatile. This should be - * factorised still. */ -template -class BitField { - public: - constexpr BitField(T bits) : m_bits(bits) {} - constexpr BitField() : BitField(0) {} - - operator T() const { return m_bits; } - - constexpr T get() const { return m_bits; } - - template - bool get(K bit) const { - return get(bit, bit); - } - - template - T get(K high, K low) const { - return get(static_cast(high), static_cast(low)); - } - constexpr T get(size_t high, size_t low) const { - return (m_bits >> low) & ((k_one << (high - low + 1)) - 1); - } - - template - constexpr BitField& set(K high, K low, T value) { - return set(static_cast(high), static_cast(low), value); - } - constexpr BitField& set(size_t high, size_t low, T value) { - T mask = ((k_one << (high - low + 1)) - 1) << low; - m_bits = (m_bits & ~mask) | ((value << low) & mask); - return *this; - } - - protected: - constexpr static T k_one = static_cast(1); - - T m_bits; -}; - } // namespace BitHelper } // namespace OMG diff --git a/poincare/include/poincare/exam_mode.h b/poincare/include/poincare/exam_mode.h index 486e79e9a9..f5827dbe0d 100644 --- a/poincare/include/poincare/exam_mode.h +++ b/poincare/include/poincare/exam_mode.h @@ -16,7 +16,7 @@ class ExamMode : public Ion::ExamMode::Configuration { public: using Ruleset = Ion::ExamMode::Ruleset; - struct PressToTestFlags : OMG::BitHelper::BitField { + struct PressToTestFlags { CODE_GUARD(press_to_test_flags, 2156906052, // enum class Flags : size_t{ @@ -35,17 +35,23 @@ class ExamMode : public Ion::ExamMode::Configuration { static_assert(static_cast(Flags::NumberOfFlags) <= Ion::ExamMode::Configuration::k_dataSize); + bool operator==(const PressToTestFlags& other) { + return m_bits == other.m_bits; + } + bool getFlag(Flags flag) const { assert(static_cast(flag) < static_cast(Flags::NumberOfFlags)); - return BitField::get(flag); + return OMG::BitHelper::bitAtIndex(m_bits, flag); } PressToTestFlags& setFlag(Flags flag, bool value = true) { assert(static_cast(flag) < static_cast(Flags::NumberOfFlags)); - BitField::set(flag, flag, 1); + OMG::BitHelper::setBitAtIndex(m_bits, flag, value); return *this; } + + Ion::ExamMode::Int m_bits; }; static_assert(sizeof(PressToTestFlags) == sizeof(Ion::ExamMode::Int)); diff --git a/poincare/include/poincare/preferences.h b/poincare/include/poincare/preferences.h index 5c2b0e22b6..ee26597843 100644 --- a/poincare/include/poincare/preferences.h +++ b/poincare/include/poincare/preferences.h @@ -165,8 +165,15 @@ class Preferences final { } private: - CODE_GUARD(poincare_preferences, 4011524516, // - int m_version = 0x20240401; + constexpr static int k_version = 0x20240401; + +#if __EMSCRIPTEN__ + emscripten_align1_int m_version; +#else + int m_version; +#endif + + CODE_GUARD(poincare_preferences, 4027384180, // CalculationPreferences m_calculationPreferences; mutable ExamMode m_examMode; /* This flag can only be asserted by writing it via DFU. When set, @@ -178,6 +185,7 @@ class Preferences final { mutable LogarithmBasePosition m_logarithmBasePosition; mutable LogarithmKeyEvent m_logarithmKeyEvent; mutable ParabolaParameter m_parabolaParameter;) + #if PLATFORM_DEVICE /* Explicitly declare padding to ensure the structure of the class * stays consistent across versions. */ diff --git a/poincare/src/preferences.cpp b/poincare/src/preferences.cpp index ff8bc545ae..e337944702 100644 --- a/poincare/src/preferences.cpp +++ b/poincare/src/preferences.cpp @@ -14,14 +14,14 @@ constexpr int Preferences::ShortNumberOfSignificantDigits; constexpr int Preferences::VeryShortNumberOfSignificantDigits; Preferences::Preferences() - : m_calculationPreferences{.angleUnit = AngleUnit::Radian, - .displayMode = - Preferences::PrintFloatMode::Decimal, - .editionMode = EditionMode::Edition2D, - .complexFormat = - Preferences::ComplexFormat::Real, - .numberOfSignificantDigits = Preferences:: - DefaultNumberOfPrintedSignificantDigits}, + : m_version(k_version), + m_calculationPreferences{ + .angleUnit = AngleUnit::Radian, + .displayMode = Preferences::PrintFloatMode::Decimal, + .editionMode = EditionMode::Edition2D, + .complexFormat = Preferences::ComplexFormat::Real, + .numberOfSignificantDigits = + Preferences::DefaultNumberOfPrintedSignificantDigits}, m_forceExamModeReload(false) {} Preferences::ComplexFormat Preferences::UpdatedComplexFormatWithExpressionInput(