FIX INLINING OF WRITE CALLS WITH Os ENABLED

The inlining issue was due to a bad template design in the access policies
implementations: the MMIO_t type from the field was used (which is a volatile
type) for all arguments in the write implementation.
The new implementation relies on two template types (one for the register memory
device and another one for the value to be written). This fixes inlining and was
checked on godbolt.
This commit is contained in:
Nicolas Clauvelin 2018-02-22 10:22:51 -05:00
parent d7404ab946
commit 5cf8a851d8
3 changed files with 65 additions and 66 deletions

View File

@ -25,14 +25,15 @@ namespace cppreg {
//! Read access implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
* @param offset Field offset.
* @return The value at the field location.
*/
template <typename T>
inline static T read(const T* const mmio_device,
template <typename MMIO_t, typename T>
inline static T read(const MMIO_t* const mmio_device,
const T mask,
const Offset_t offset) noexcept {
return static_cast<T>((*mmio_device & mask) >> offset);
@ -46,14 +47,15 @@ namespace cppreg {
//! Write access implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
* @param offset Field offset.
* @param value Value to be written at the field location.
*/
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {
@ -67,31 +69,36 @@ namespace cppreg {
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
*/
template <typename T>
inline static void set(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void set(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) | mask);
};
//! Clear field implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
*/
template <typename T>
inline static void clear(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void clear(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) & ~mask);
};
//! Toggle field implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
*/
template <typename T>
inline static void toggle(T* const mmio_device, const T mask) noexcept {
*mmio_device ^= mask;
template <typename MMIO_t, typename T>
inline static void toggle(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) ^ mask);
};
};
@ -102,14 +109,15 @@ namespace cppreg {
//! Write access implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
* @param offset Field offset
* @param value Value to be written at the field location.
*/
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {

View File

@ -90,10 +90,9 @@ namespace cppreg {
*/
inline static type read() noexcept {
return
AccessPolicy
::template read<MMIO_t>(parent_register::ro_mem_pointer(),
mask,
offset);
AccessPolicy::read(parent_register::ro_mem_pointer(),
mask,
offset);
};
//! Field write method (shadow value disabled).
@ -113,11 +112,10 @@ namespace cppreg {
write(const typename std::enable_if<
!parent_register::shadow::use_shadow, T
>::type value) noexcept {
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
mask,
offset,
value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
mask,
offset,
value);
};
//! Field write method (shadow value enabled).
@ -147,11 +145,10 @@ namespace cppreg {
// Write as a block to the register, that is, we do not use the
// mask and offset.
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);
};
@ -205,8 +202,7 @@ namespace cppreg {
* This method will set all bits in the field.
*/
inline static void set() noexcept {
AccessPolicy
::template set<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::set(parent_register::rw_mem_pointer(), mask);
};
//! Field clear method.
@ -214,8 +210,7 @@ namespace cppreg {
* This method will clear all bits in the field.
*/
inline static void clear() noexcept {
AccessPolicy
::template clear<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::clear(parent_register::rw_mem_pointer(), mask);
};
//! Field toggle method.
@ -223,8 +218,7 @@ namespace cppreg {
* This method will toggle all bits in the field.
*/
inline static void toggle() noexcept {
AccessPolicy
::template toggle<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::toggle(parent_register::rw_mem_pointer(), mask);
};
//! Is field set bool method.

View File

@ -24,38 +24,41 @@ namespace cppreg {
#define CPPREG_ACCESSPOLICY_H
namespace cppreg {
struct read_only {
template <typename T>
inline static T read(const T* const mmio_device,
template <typename MMIO_t, typename T>
inline static T read(const MMIO_t* const mmio_device,
const T mask,
const Offset_t offset) noexcept {
return static_cast<T>((*mmio_device & mask) >> offset);
};
};
struct read_write : read_only {
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {
*mmio_device = static_cast<T>((*mmio_device & ~mask) |
((value << offset) & mask));
};
template <typename T>
inline static void set(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void set(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) | mask);
};
template <typename T>
inline static void clear(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void clear(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) & ~mask);
};
template <typename T>
inline static void toggle(T* const mmio_device, const T mask) noexcept {
*mmio_device ^= mask;
template <typename MMIO_t, typename T>
inline static void toggle(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) ^ mask);
};
};
struct write_only {
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {
@ -287,21 +290,19 @@ namespace cppreg {
};
inline static type read() noexcept {
return
AccessPolicy
::template read<MMIO_t>(parent_register::ro_mem_pointer(),
mask,
offset);
AccessPolicy::read(parent_register::ro_mem_pointer(),
mask,
offset);
};
template <typename T = type>
inline static void
write(const typename std::enable_if<
!parent_register::shadow::use_shadow, T
>::type value) noexcept {
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
mask,
offset,
value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
mask,
offset,
value);
};
template <typename T = type>
inline static void
@ -311,11 +312,10 @@ namespace cppreg {
parent_register::shadow::value =
(parent_register::shadow::value & ~mask) |
((value << offset) & mask);
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);
};
template <type value, typename T = void>
inline static
@ -340,16 +340,13 @@ namespace cppreg {
write(value);
};
inline static void set() noexcept {
AccessPolicy
::template set<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::set(parent_register::rw_mem_pointer(), mask);
};
inline static void clear() noexcept {
AccessPolicy
::template clear<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::clear(parent_register::rw_mem_pointer(), mask);
};
inline static void toggle() noexcept {
AccessPolicy
::template toggle<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::toggle(parent_register::rw_mem_pointer(), mask);
};
template <typename T = bool>
inline static typename std::enable_if<FieldWidth == 1, T>::type