non_lazy_ptr question

So, I’ve got a case where I am attempting to pass the address of a static symbol from a module written in Tart (the language I am working on), to a module written in C (which is part of Tart’s runtime library). This works fine on Linux, but fails on OS X because the address being passed is the “non_lazy_ptr” symbol, not the symbol itself.

In my .bc file, I’ve got code that looks like this:

@gc_safepoint_map = external global [0 x i32] ; <[0 x i32]*> [#uses=1]

%init = invoke {} @GC_init(i32* getelementptr inbounds ([0 x i32]* @gc_safepoint_map, i32 0, i32 0))
to label %nounwind unwind label %catch, !dbg !400 ; <{}> [#uses=0]

In other words, we have an external symbol that is being passed to an external function. (BTW, gc_safepoint_map is the map of all of the stack offsets containing pointers, indexed by the program counter address of the safe point. It’s generated by a custom linker pass.)

However, the code that is being generated looks like this:

movl L_gc_safepoint_map$non_lazy_ptr, %eax
movl %eax, (%esp)
call _GC_init

In other words, it’s passing the ‘non_lazy_ptr’ version of the symbol directly to GC_init, without dereferencing it. This makes the code go boom.

OK, so my question is:

  • Where exactly would this dereference normally occur?
  • Would it be in the calling module (written in bitcode)? If so, do I need to generate bitcode to dereference the symbol, or is there some means to do this automatically? If I need to generate the bitcode myself, how do I tell whether the current target is one that needs this?
  • Conversely, would I need to write code on the callee side (written in C). In this case, I don’t have access to target data, just cmake config variables. Again, I’d need to come up with some test I can write in cmake language that lets me know whether or not I need to do the special dereference.
  • Alternatively perhaps there is some linker flag I can set that makes this problem go away.
    Any suggestions?

That the above code does dereference the non-lazy pointer symbol. To load the symbol address itself in AT&T syntax, you'd have to prepend a $ to the symbol name:

movl $L_gc_safepoint_map$non_lazy_ptr, %eax