<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW " title="NEW --- - llvm generates wrong offset for stack objects" href="https://urldefense.proofpoint.com/v2/url?u=https-3A__llvm.org_bugs_show-5Fbug.cgi-3Fid-3D24142&d=AwMBaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=pF93YEPyB-J_PERP4DUZOJDzFVX5ZQ57vQk33wu0vio&m=xJVo-1m5I-FY_NG5kACl4sOdeDY_aMSEYsP2OcEFpGg&s=6QWMz5dLEdRDpRoIiUIwNYhOdCwurGnY1I6OsgQaD10&e=">24142</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>llvm generates wrong offset for stack objects
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Common Code Generator Code
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>carrot@google.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Compile following source code to armv7 thumb2 code

typedef struct {
    int f1;
    int f2;
    int f3;
} struct_1;

typedef struct {
    struct_1 array[172];
} struct_2;

void bar1(int id, struct_2 params);
int bar2(int* obj, const char *name);
int* bar3(int, int, const char*, const char*, int);

void foo(int p1, int p2, int p3, int p4, int p5) {
    struct_2 params;

    for (int i = 0; i < 4; i++) {
        int* bb = bar3(p1, p5, "a", "b", i);
        if (bb == nullptr) {
            return;
        }
        params.array[i].f1 = bar2(bb, "c");
        params.array[i].f2 = bar2(bb, "d");
    }

    bar1(p4, params);
}

llvm generates:

_Z3fooiiiii:
.Lfunc_begin0:
        .loc    1 15 0                  @ t1.ii:15:0
        .fnstart
        .cfi_startproc
@ BB#0:                                 @ %entry
        .loc    1 15 14 is_stmt 0       @ t1.ii:15:14
        .save   {r4, r5, r6, r7, r8, r9, r10, r11, lr} 
        push.w  {r4, r5, r6, r7, r8, r9, r10, r11, lr} 
.Ltmp0:
        .cfi_def_cfa_offset 36
.Ltmp1:
        .cfi_offset lr, -4
.Ltmp2:
        .cfi_offset r11, -8
.Ltmp3:
        .cfi_offset r10, -12 
.Ltmp4:
        .cfi_offset r9, -16 
.Ltmp5:
        .cfi_offset r8, -20 
.Ltmp6:
        .cfi_offset r7, -24 
.Ltmp7:
        .cfi_offset r6, -28 
.Ltmp8:
        .cfi_offset r5, -32 
.Ltmp9:
        .cfi_offset r4, -36 
        .pad    #2064
        sub.w   sp, sp, #2064
        .pad    #12
        sub     sp, #12 
.Ltmp10:
        .cfi_def_cfa_offset 2112

        ...

        sub     sp, #8                     // A
.Ltmp18:
        ldr.w   r1, [sp, #2116]            // B
.Ltmp19:
        mov     r0, r10
        mov     r2, r11
.Ltmp20:
        mov     r3, r4
        str.w   r9, [sp]
        bl      _Z4bar3iiPKcS0_i(PLT)
        add     sp, #8

At the prolog of the function, llvm generates a stack frame of 2112 bytes. The
fifth parameter of function foo, p5, is on stack, its address should be sp+2112
after function prolog.

Instruction A allocates more stack space for outgoing parameters, after it the
address of p5 should be sp+2120, but instruction B uses sp+2116 for it.


The problem is in function PEI::replaceFrameIndices:

    if (I->getOpcode() == FrameSetupOpcode ||
        I->getOpcode() == FrameDestroyOpcode) {
      InsideCallSequence = (I->getOpcode() == FrameSetupOpcode);
      SPAdj += TII.getSPAdjust(I);

      MachineBasicBlock::iterator PrevI = BB->end();
      if (I != BB->begin()) PrevI = std::prev(I);
      TFI->eliminateCallFramePseudoInstr(Fn, *BB, I);

      // Visit the instructions created by eliminateCallFramePseudoInstr().
      if (PrevI == BB->end())
        I = BB->begin();     // The replaced instr was the first in the block.
      else
        I = std::next(PrevI);
      continue;
    }


The SP adjustment should consider the stack alignment, arm backend
implementation of eliminateCallFramePseudoInstr correctly generates sp
adjustment instructions with proper alignment. But TII.getSPAdjust doesn't take
into account the stack alignment, and causes wrong offset is used for other
stack objects.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>