[LLVMbugs] [Bug 10597] New: When using -mrtd and -ffreestanding, generated memcpy calls get the wrong calling convention

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Sat Aug 6 10:18:53 PDT 2011


http://llvm.org/bugs/show_bug.cgi?id=10597

           Summary: When using -mrtd and -ffreestanding, generated memcpy
                    calls get the wrong calling convention
           Product: new-bugs
           Version: trunk
          Platform: PC
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: dimitry at andric.com
                CC: llvmbugs at cs.uiuc.edu


When using -mrtd in combination with -ffreestanding, memcpy calls (and
possibly some other builtin function calls) get generated with the wrong
calling convention.

For example, consider the following program (which is meant to get its
memcpy implementation from a separate compilation unit):

//////////////////////////////////////////////////////////////////////
struct foo {
    int i[100];
};

void bar(void);
void memcpy(void *dst, const void *src, unsigned len);

void baz(struct foo *x, struct foo *y)
{
    bar();
    memcpy(x, y, sizeof(struct foo));
    bar();
    *x = *y; // causes memcpy() to be called
    bar();
}
//////////////////////////////////////////////////////////////////////

When you compile this with "-ffreestanding -mrtd", the resulting
assembly for the baz() function becomes:

//////////////////////////////////////////////////////////////////////
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %edi
        pushl   %esi
        subl    $16, %esp
        calll   bar
        movl    12(%ebp), %esi
        movl    %esi, 4(%esp)
        movl    8(%ebp), %edi
        movl    %edi, (%esp)
        movl    $400, 8(%esp)           # imm = 0x190
        calll   memcpy                  # (1)
        subl    $12, %esp               # (2)
        calll   bar
        movl    %esi, 4(%esp)
        movl    %edi, (%esp)
        movl    $400, 8(%esp)           # imm = 0x190
        calll   memcpy                  # (3)
        calll   bar
        addl    $16, %esp
        popl    %esi
        popl    %edi
        popl    %ebp
        ret     $8
//////////////////////////////////////////////////////////////////////

The first call to memcpy (1) is generated correctly, subtracting 12
bytes from the stack (2) to compensate for the 12 bytes that will have
been popped by the body of the memcpy function.

However, the second call to memcpy (3) has been generated by clang
itself, and has been assumed to have cdecl calling convention, even if
-mrtd is on the command line.  E.g. "subl $12, %esp" is not inserted
here, and the program will crash more or less spectacularly.

When you look at the corresponding .ll file, you will see:

//////////////////////////////////////////////////////////////////////
  tail call x86_stdcallcc void @bar() nounwind optsize
  %0 = bitcast %struct.foo* %x to i8*
  %1 = bitcast %struct.foo* %y to i8*
  tail call x86_stdcallcc void @memcpy(i8* %0, i8* %1, i32 400) nounwind
optsize
  tail call x86_stdcallcc void @bar() nounwind optsize
  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 400, i32 4, i1
false)
  tail call x86_stdcallcc void @bar() nounwind optsize
//////////////////////////////////////////////////////////////////////

So @llvm.memcpy.p0i8.p0i8.i32 is *not* x86_stdcallcc, and it results in
a cdecl memcpy call in assembly.

(Obviously a workaround is be to explicitly declare memcpy() as cdecl,
but that was impossible until bug 10591 was fixed.)

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list