[LLVMbugs] [Bug 16368] New: ARM struct byval size > 64 triggers failure

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Tue Jun 18 21:40:00 PDT 2013


            Bug ID: 16368
           Summary: ARM struct byval size > 64 triggers failure
           Product: libraries
           Version: trunk
          Hardware: Other
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Backend: ARM
          Assignee: unassignedbugs at nondot.org
          Reporter: viswabramana.rajesh at gmail.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

Handling of pass byval of struct size >64 bytes case is going wrong for arm

Test Code:
#include <stdio.h>
struct S114 {
  char a[67];

struct S114 check114 (struct S114 arg0, struct S114* arg1) { 
  if(&a114[0] != arg1)                         // arg1 value is wrong
    printf( "values %p, %p\n", &a114[0], arg1);

int main () {
  int i= 0, j = 0;
  for (;j<2; j++)             //filling a114 with some values for mark
    for(i=0; i<sizeof(struct S114); i++)
      memset(&a114[j].a[i],(0x11+i+j*30), sizeof(int)); 

  check114 (a114[1], &a114[0]);         

# ./check114.exe 
values 0x10861, 0x4071706f    --> which is wrong.

Assembly for check114 
        sub     sp, sp, #16
        push    {r11, lr}
        mov     r11, sp
        sub     sp, sp, #8
        str     r3, [r11, #20]
        str     r2, [r11, #16]
        str     r1, [r11, #12]
        ldr     r1, [r11, #76]
        str     r1, [sp, #4]
        .loc    1 7 0 prologue_end
        ldr     r2, .LCPI0_0
        cmp     r2, r1
        beq     .LBB0_2
        b       .LBB0_1

>From reg, stack dump:
@entry of check114:

=> 0x8398 <check114>: sub sp, sp, #16
     sp             0xbefff808 0xbefff808

@if condition :

   0x83b4 <check114+28>: ldr r1, [r11, #76] ; 0x4c  <- wrong value copied
offset #76 should be #80
   0x83b8 <check114+32>: str r1, [sp, #4]
   0x83bc <check114+36>: ldr r2, [pc, #44] ; 0x83f0 <check114+88>
=> 0x83c0 <check114+40>: cmp r2, r1

  r11            0xbefff7f0 -1090521104
  sp             0xbefff7e8 0xbefff7e8

  Stack dump:

  0xbefff7e4: 0x4001ed08 0x40024f90 0x4071706f 0xbefff8a0
  0xbefff7f4: 0x0000869c 0x00000000 0x3231302f 0x36353433
  0xbefff804: 0x3a393837 0x3e3d3c3b 0x4241403f 0x46454443
  0xbefff814: 0x4a494847 0x4e4d4c4b 0x5251504f 0x56555453
  0xbefff824: 0x5a595857 0x5e5d5c5b 0x6261605f 0x66656463
  0xbefff834: 0x6a696867 0x6e6d6c6b 0x4071706f 0x00010861 //[R11+4c] ---->
[0xbefff7f0+4c] ---> [0xbefff83c] ----> 0x4071706f

>From ARM Lowering part

ARMTargetLowering::computeRegArea(..) {
  VARegSize = NumGPRs * 4;
  VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1);//-> 8 byte alignment
done here

For above test code case,
NumGPRs = 3 registers (used to hold struct byval) = 3*4
VARegSaveSize  = 16 (after considering 8 byte alignment )
So, 4 bytes offset added due to alignment.

Which results,
     sub sp, sp, #16

- Offset(#76) for the instruction, "ldr r1, [r11, #76] ; 0x4c"  when
calculated, 4 bytes alignment is considered.
- Prologue stackpointer calculation 8 byte alignment is considered.

Due to this alignment mismatch, when try to access second or rest of arguments
after struct byval goes wrong.

- Issue occurs for only if odd number of registers used for struct byval.
- If even number of registers used for byval, issue doesnt occur(since it will
be naturally aligned by 8 byte boundary when copied to stack).

Ex: Update of above test case with int,
struct S114 check114 (int a, struct S114 arg0, struct S114* arg1) { //
accessing arg1 is fine in this case
} //works fine.

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20130619/c7954813/attachment.html>

More information about the llvm-bugs mailing list