[LLVMdev] nested function's static link gets clobbered

Török Edwin edwintorok at gmail.com
Fri Oct 31 15:12:35 PDT 2008


On 2008-10-31 23:57, Yale Zhang wrote:
> Fellow developers,
>
> I'm parallelizing loops to be called by pthread. The thread body that
> I pass to pthread_create looks like
>
> define i8* @loop1({ i32*, i32* }* nest  %parent_frame, i8*
> %arg)            parent_frame is pointer to shared variables in
> original function
>
> 0x00007f0de11c41f0:     mov    (%r10),%rax
> 0x00007f0de11c41f3:     cmpl   $0x63,(%rax)
> 0x00007f0de11c41f6:     jg     0x7f0de11c420c
> 0x00007f0de11c41fc:     mov    0x8(%r10),%rax
> 0x00007f0de11c4200:     incl   (%rax)
> 0x00007f0de11c4202:     mov    (%r10),%rax
> 0x00007f0de11c4205:     incl   (%rax)
> 0x00007f0de11c4207:     jmpq   0x7f0de11c41f0
> 0x00007f0de11c420c:     xor    %rax,%rax
> 0x00007f0de11c420f:     retq
>
> I use init_trampoline to generate code that sets up the static link:
>
> 0x00007fffee982316:     mov    $0x7f48e1a08fb0,%r11
> 0x00007fffee982320:     mov    $0x7fffee982330,%r10               the
> static link
> 0x00007fffee98232a:     rex.WB jmpq   *%r11
>
> The program crashes in loop1 on the 2nd instruction. r10, which
> contained the static link was different from the value set by the
> trampoline.
>
> Upon closer inspection, it looks like the trampoline first jumps to a
> stub that compiles loop1:
>
> 0x00007f48e1a08fb0:     mov    $0x5c61c0,%r10               
> 0x00007f48e1a08fba:     callq  *%r10                        
> 0x00007f48e1a08fbd:     int    $0x0
>
> But that clobbers r10 which loop1 needs. According to the x86-64 ABI,
> r10 isn't preserved across functions, but here it needs to be. Is
> there anyway
> to force LLVM to do that? I tried telling lli to compile the entire
> program (-no-lazy) so that the stub won't be generated, but gives the
> error:
>
> LLVM JIT requested to do lazy compilation of function
> '_Z41__static_initialization_and_destruction_0ii' when lazy compiles
> are disabled!
>
> Any ideas?

Hmm, lli.cpp does this:
if (NoLazyCompilation)
    EE->DisableLazyCompilation();
[....]
// Run static constructors.
  EE->runStaticConstructorsDestructors(false);

  if (NoLazyCompilation) {
    for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
      Function *Fn = &*I;
      if (Fn != MainFn && !Fn->isDeclaration())
        EE->getPointerToFunction(Fn);
    }
  }

If you actually have static constructors and destructors then nolazy may
not work. You could try moving the runStatic... below the NoLazy block,
but it could be that compiling the functions themselves could need those
constructors to be run already.

The easiest way out seems to move the DisableLazyCompilation just after
you've run the static constructors.

Best regards,
--Edwin



More information about the llvm-dev mailing list