[LLVMdev] Code Generation Problem llvm 1.9

Ben Mayne bmayne at 21technologies.com
Thu Dec 20 12:54:32 PST 2007


I sent a long message yesterday describing a problem I thought had to do with the JIT stubs.
After further investigating, the problem seems to be in the code generation.

The following basic block seems to have an error in it's code generation:

__exp.exit:             ; preds = %codeRepl258, %__exp_bb_bb.exit
        phi double [ 1.000000e+00, %codeRepl258 ], [ %.reload.reload.i, %__exp_bb_bb.exit ]             ; <double>:30 [#uses=2]
        %castPointerToLong10 = cast [10 x double]* %DataStore to long           ; <long> [#uses=1]
        %pointerArithmetic11 = add long %castPointerToLong10, 0         ; <long> [#uses=1]
        %castPointerToLong9 = cast [10 x double]* %DataStore to long            ; <long> [#uses=1]
        %pointerArithmetic10 = add long %castPointerToLong9, 40         ; <long> [#uses=1]
        %castLongToGV11 = cast long %pointerArithmetic10 to double*             ; <double*> [#uses=1]
        store double 7.000000e+00, double* %castLongToGV11
        %castPointerToLong12 = cast [10 x double]* %DataStore to long           ; <long> [#uses=1]
        %pointerArithmetic13 = add long %castPointerToLong12, 16                ; <long> [#uses=1]
        %tmp2.loc = alloca int          ; <int*> [#uses=2]
        %castLongToGV14 = cast long %pointerArithmetic13 to double*             ; <double*> [#uses=1]
        store double 2.000000e+00, double* %castLongToGV14
        cast int %x to double           ; <double>:31 [#uses=1]
        frem double %31, 1.000000e+02           ; <double>:32 [#uses=2]
        %castPointerToLong15 = cast [10 x double]* %DataStore to long           ; <long> [#uses=1]
        %pointerArithmetic16 = add long %castPointerToLong15, 24                ; <long> [#uses=1]
        %castLongToGV17 = cast long %pointerArithmetic16 to double*             ; <double*> [#uses=1]
        store double %32, double* %castLongToGV17
        %castPointerToLong18 = cast [10 x double]* %DataStore to long           ; <long> [#uses=1]
        %pointerArithmetic19 = add long %castPointerToLong18, 24                ; <long> [#uses=1]
        %castLongToGV20 = cast long %pointerArithmetic19 to double*             ; <double*> [#uses=1]
        load double* %castLongToGV20            ; <double>:33 [#uses=1]
        %castPointerToLong21 = cast [10 x double]* %DataStore to long           ; <long> [#uses=1]
        %pointerArithmetic22 = add long %castPointerToLong21, 16                ; <long> [#uses=1]
        %castLongToGV23 = cast long %pointerArithmetic22 to double*             ; <double*> [#uses=1]
        load double* %castLongToGV23            ; <double>:34 [#uses=1]
        cast double %34 to int          ; <int>:9 [#uses=2]
        seteq int %9, 0         ; <bool>:7 [#uses=1]
        br bool %7, label %entry.bb19_crit_edge.i270, label %bb.preheader.i271

It gets converted to the following MachineBasicBlock
__exp.exit (0x8c58628, LLVM BB @0x8c1c558, ID#21):
    Predecessors according to CFG: 0x8c53a90 0x8c55b50
        MOV32mi %EBP, 1, %NOREG, -224, <ga:DataStore>
        %EAX = MOV32rm %EBP, 1, %NOREG, -224
        %EAX = ADD32ri8 %EAX, 40
        MOV32mi %EAX, 1, %NOREG, 0, 0
        MOV32mi %EAX, 1, %NOREG, 4, 1075576832
        %ESP = SUB32ri %ESP, 16
        %XMM0 = CVTSI2SDrr %EDI
        MOVSDmr %ESP, 1, %NOREG, 0, %XMM0
        MOV32mr %EBP, 1, %NOREG, -268, %ESP
        ADD32mi8 %EBP, 1, %NOREG, -268, 4294967288
        %ESP = MOV32rm %EBP, 1, %NOREG, -268
        %ESI = MOV32rm %EBP, 1, %NOREG, -224
        %ESI = ADD32ri8 %ESI, 16
        MOV32mi %ESI, 1, %NOREG, 0, 0
        MOV32mi %ESI, 1, %NOREG, 4, 1073741824
        MOV32mi %ESP, 1, %NOREG, 12, 1079574528
        MOV32mi %ESP, 1, %NOREG, 8, 0
        CALLpcrel32 <es:fmod>
        %ESP = ADD32ri8 %ESP, 16
        FSTP64m %EBP, 1, %NOREG, -160
        %EAX = MOV32rm %EBP, 1, %NOREG, -224
        %EAX = ADD32ri8 %EAX, 24
        %XMM0 = MOVSDrm %EBP, 1, %NOREG, -160
        MOVSDmr %EBP, 1, %NOREG, -232, %XMM0
        MOVSDmr %EAX, 1, %NOREG, 0, %XMM0
        %EAX = CVTTSD2SIrm %ESI, 1, %NOREG, 0
        %ECX = MOV32r0
        TEST32rr %EAX, %EAX
        JNE mbb<bb.preheader.i271,0x8c55330>
    Successors according to CFG: 0x8c55330 0x8c573b0

The gdb disassembler gives me the following lines for that basic block

__exp.exit:
0xf5f6f317:     movl   $0xa542b70,0xffffff20(%ebp)
0xf5f6f321:     mov    0xffffff20(%ebp),%eax
0xf5f6f327:     add    $0x28,%eax
0xf5f6f32a:     movl   $0x0,(%eax)
0xf5f6f330:     movl   $0x401c0000,0x4(%eax)
0xf5f6f337:     sub    $0x10,%esp 
0xf5f6f33d:     cvtsi2sd %edi,%xmm0
0xf5f6f341:     movsd  %xmm0,(%esp)
0xf5f6f346:     mov    %esp,0xfffffef4(%ebp)
0xf5f6f34c:     addl   $0xfffffff8,0xfffffef4(%ebp)
0xf5f6f353:     mov    0xfffffef4(%ebp),%esp
0xf5f6f359:     mov    0xffffff20(%ebp),%esi
0xf5f6f35f:     add    $0x10,%esi
0xf5f6f362:     movl   $0x0,(%esi)
0xf5f6f368:     movl   $0x40000000,0x4(%esi)
0xf5f6f36f:     movl   $0x40590000,0xc(%esp)
0xf5f6f377:     movl   $0x0,0x8(%esp)
0xf5f6f37f:     call   0xf5f6effb
0xf5f6f384:     add    $0x10,%esp
0xf5f6f387:     fstpl  0xffffff60(%ebp)
0xf5f6f38d:     mov    0xffffff20(%ebp),%eax
0xf5f6f393:     add    $0x18,%eax
0xf5f6f396:     movsd  0xffffff60(%ebp),%xmm0
0xf5f6f39e:     movsd  %xmm0,0xffffff18(%ebp)
0xf5f6f3a6:     movsd  %xmm0,(%eax)
0xf5f6f3aa:     cvttsd2si (%esi),%eax
0xf5f6f3ae:     xor    %ecx,%ecx
0xf5f6f3b0:     test   %eax,%eax
0xf5f6f3b2:     jne    0xf5f6f3c5


The problem I'm seeing is that the generated code for the "%tmp2.loc = alloca int" instruction seems to get placed in the middle of
the generated code for the "frem double %31, 1.000000e+02" instruction.  The generated code for the frem call subtracts 16 from the stack to
prepare for the insertion of arguments onto the stack.  However, before it insert the arguments on the stack, it allocates space for tmp2.loc.
Therefore the stack essentially gets subtracted by 10 more.  Then the arguments are placed on, the call is made, and upon return, 16 is added to
the stack.  Basically, after the call, the stack doesn't go back to the state it was in before the call because the alloca snuck in between
the instructions.  Now, tmp2.loc is sitting in memory past the stack pointer which can potentially be overwritten by a future call and in the example
I sent yesterday, it does get overwritten.

Thanks,

Ben Mayne
x245

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20071220/a2102e29/attachment.html>


More information about the llvm-dev mailing list