Implement utils::bless (pointer cast)

Tries to workaround strict aliasing troubles.
Don't confuse with std::bless which works differently.
This commit is contained in:
Nekotekina 2021-03-10 15:54:32 +03:00
parent 63ecb56b51
commit 03332c340d
3 changed files with 16 additions and 3 deletions

View File

@ -2161,7 +2161,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
auto& res = vm::reservation_acquire(eal);
// Lock each bit corresponding to a byte being written, using some free space in reservation memory
auto* bits = reinterpret_cast<atomic_t<u128>*>(vm::g_reservations + ((eal & 0xff80) / 2 + 16));
auto* bits = utils::bless<atomic_t<u128>>(vm::g_reservations + ((eal & 0xff80) / 2 + 16));
// Get writing mask
const u128 wmask = (~u128{} << (eal & 127)) & (~u128{} >> (127 - ((eal + size0 - 1) & 127)));

View File

@ -493,7 +493,7 @@ void GLGSRender::emit_geometry(u32 sub_index)
m_scratch_buffer.resize(draw_count * 24);
GLint* firsts = reinterpret_cast<GLint*>(m_scratch_buffer.data());
GLsizei* counts = (firsts + draw_count);
const GLvoid** offsets = reinterpret_cast<const GLvoid**>(counts + draw_count);
const GLvoid** offsets = utils::bless<const GLvoid*>(counts + draw_count);
u32 first = 0;
u32 dst_index = 0;
@ -560,7 +560,7 @@ void GLGSRender::emit_geometry(u32 sub_index)
m_scratch_buffer.resize(draw_count * 16);
GLsizei *counts = reinterpret_cast<GLsizei*>(m_scratch_buffer.data());
const GLvoid** offsets = reinterpret_cast<const GLvoid**>(counts + draw_count);
const GLvoid** offsets = utils::bless<const GLvoid*>(counts + draw_count);
int dst_index = 0;
for (const auto &range : subranges)

View File

@ -390,6 +390,19 @@ namespace utils
return static_cast<T>(value / align + (value > 0 ? T{(value % align) > (align / 2)} : 0 - T{(value % align) < (align / 2)}));
}
// Hack. Pointer cast util to workaround UB. Use with extreme care.
template <typename T, typename U>
[[nodiscard]] T* bless(U* ptr)
{
#ifdef _MSC_VER
return (T*)ptr;
#else
T* result;
__asm__("movq %1, %0;" : "=r" (result) : "r" (ptr) : "memory");
return result;
#endif
}
} // namespace utils
using utils::busy_wait;