I have the following code
renderer_opengl *oldr = (renderer_opengl*)enabler->renderer;
renderer *newr = new renderer;
void **vtable_old = ((void ***)oldr)[0];
void **vtable_new = ((void ***)newr)[0];
...
void *draw_new = vtable_new[IDX_draw];
void *reshape_gl_new = vtable_new[IDX_reshape_gl];
void *update_tile_new = vtable_new[IDX_update_tile];
// out << draw_new << std::endl;
p.verifyAccess(vtable_new, sizeof(void*)*32, true);
memcpy(vtable_new, vtable_old, sizeof(void*)*32);
out << draw_new << std::endl;
vtable_new[IDX_draw] = draw_new;
...
Compiling with
Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)
Not important what I'm doing here, but the problem is that the compiler rearranges the code and places assignment to draw_new
after memcpy
, so that in out stream I see address from vtable_old
instead of vtable_new
! This happens with -O3 and even -O2. If I uncomment the first output, everything is back to normal.
What's this - expected behaviour, a bug in clang or am I missing something? How to fix it?
EDIT
Adding volatile
to vtable_new
declaration
void ** volatile vtable_new = ((void ***)newr)[0];
helped. -fno-strict-aliasing
and asm volatile ("" : : : "memory")
barrier didn't. I still don't understand what the compiler is doing here.