Skip to content

WIP: Make reinterpreting from Variant safer

Kenneth Moreland requested to merge kmorel/vtk-m:variant-safe-punning into master

I ran into some bizarre behavior with code generated with GCC in optimized mode. I think the problem was that the optimizer was being aggressive in removing computation after reinterpreting pointers.

The C++ standard states that if two pointers or references point to different types of data, they can be considered to point to different memory locations. This often allows the compiler to make much faster code. But it also means that if you pun the data (make the data look like two different things at once) you get undefined behavior.

The commonly accepted solution to the problem is to use std::memcpy to move the data to a pointer of a new type. However, this only works for trivial types, and we need to support non-trivial types.

The solution used here is to allow the data to be punned, but to use std::memmove to alert the compiler that there is a dependence between the two types. The pointers to the memmove are the same, so the compiler should remove any actual work but still record the data dependence. It should also be safe for non-trivial types since you are not actually moving any data.

Technically, this solution still is classified as undefined behavior. However, the only issue you should run into is that changes to the punned data won't reflect each other. This should be addressed in CastAndCall, which does a second memmove after the functor is called in case the object is changed. For the same reason, writing to the value using Get has been disabled to prevent those writes from being out of order.

Edited by Kenneth Moreland

Merge request reports