///////////////////////////////////////////////////////////////////////////////
/// make the compiler think a particular variable may now be aliased somewhere.
///
/// useful for preventing optimisations eliding a variable.
///
/// stolen from Chandler Carruth's 2015 talk: "Tuning C++".
namespace cruft::debug {
    template <class T>
    inline T*
    escape (T *t)
    {
        asm volatile ("": : "g"(t): "memory");
        return t;
    }


    template <class T>
    inline const T*
    escape (const T *t)
    {
        asm volatile ("": : "g"(t): "memory");
        return t;
    }


    template <class T>
    inline const T&
    escape (const T &t)
    {
        return *escape (&t);
    }


    template <class T>
    inline T&
    escape (T &t)
    {
        return *escape (&t);
    }


    template <typename T, typename ...Args>
    inline void
    escape (T t, Args ...args)
    {
        escape (t);
        escape (args...);
    }
}


///////////////////////////////////////////////////////////////////////////////
/// force the compiler to conceptually dirty the global memory space.
///
/// stolen from Chandler Carruth's 2015 talk: "Tuning C++".
namespace cruft::debug {
    inline void
    clobber (void)
    {
        asm volatile ("": : : "memory");
    }
}