I have a problem where my LLVM-generated code works on Linux but not on OS X, and the problem involves non_lazy_ptr.
I have an external symbol named “@gc_safepoint_map”, which is generated by the linker’s GCStrategy plugin. Since it is not generated until link time, I declared it as an external symbol so that the modules that use it can compile without error.
Here’s what the generated IR looks like:
@gc_safepoint_map = external global [0 x i32]
The runtime startup code gets the safepoint map and calls GC_init with the safepoint map. Here’s what the code looks like in IR:
%init = invoke {} @GC_init(i32* getelementptr inbounds ([0 x i32]* @gc_safepoint_map, i32 0, i32 0))
to label %nounwind unwind label %catch
When lowered to assembly, the code looks like this on OS X:
Ltmp426:
movl L_gc_safepoint_map$non_lazy_ptr, %eax
movl %eax, (%esp)
calll _GC_init
(and later on in the same file):
L_gc_safepoint_map$non_lazy_ptr:
.indirect_symbol _gc_safepoint_map
.long 0
This looks correct to me - it’s dereferencing the non_lazy_ptr version of the global.
The GC_init function, which is written in C, simply looks like this:
void GC_init(size_t * safepointMap) {
// … details omitted…
}
On Linux, everything works as expected, however in OS X, the ‘safepointMap’ pointer is completely wrong - I’m not sure where it’s getting the value from but it isn’t sensible.
Unfortunately, gdb won’t let me print out the value of of L_gc_safepoint_map$non_lazy_ptr (No symbol “L_gc_safepoint_map$non_lazy_ptr” in current context) so it’s hard to tell what’s actually going on.