[llvm-bugs] [Bug 32507] New: [Win64] XMM registers saved in funclet prologues clobber register saves in parent function

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Apr 3 09:55:20 PDT 2017


https://bugs.llvm.org/show_bug.cgi?id=32507

            Bug ID: 32507
           Summary: [Win64] XMM registers saved in funclet prologues
                    clobber register saves in parent function
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Backend: X86
          Assignee: unassignedbugs at nondot.org
          Reporter: rnk at google.com
                CC: llvm-bugs at lists.llvm.org

This C++ program illustrates the bug:

$ cat a.cpp
double get_xmm(double);
void throw_internally();
void use_xmm(double d);
int main() {
  double xmm = get_xmm(1.0);
  use_xmm(xmm);
  throw_internally();
  use_xmm(xmm);
}

$ cat b.cpp
extern "C" int printf(const char *, ...);
void use_xmm(double d) { printf("%f\n", d); }
double __declspec(noinline) get_xmm(double d) {
  asm volatile("" : "=m"(d) : "0"(d));
  return d;
}
void throw_internally() {
  double r1 = get_xmm(2.0);
  use_xmm(r1);
  use_xmm(r1);
  try {
    throw 42;
  } catch (...) {
    double r2 = get_xmm(3.0);
    use_xmm(r2);
  }
  use_xmm(r1);
}

$ clang-cl -Z7 -EHsc -O0 a.cpp b.cpp -Fet.exe && ./t.exe
1.000000
2.000000
2.000000
3.000000
2.000000
1.000000

$ clang-cl -Z7 -EHsc -O2 a.cpp b.cpp -Fet.exe && ./t.exe
1.000000
2.000000
2.000000
3.000000
2.000000
2.000000  # BUG: should be 1.0

The buggy code is in the catch funclet prologue. It does this:

"?catch$2@?0??throw_internally@@YAXXZ at 4HA":
.seh_proc "?catch$2@?0??throw_internally@@YAXXZ at 4HA"
        .seh_handler __CxxFrameHandler3, @unwind, @except
        movq    %rdx, 16(%rsp)
        pushq   %rbp
        .seh_pushreg 5
        pushq   %rsi
        .seh_pushreg 6
        subq    $40, %rsp
        .seh_stackalloc 40
        leaq    80(%rdx), %rbp
        movdqa  %xmm6, -16(%rbp)        # 16-byte Spill
        .seh_savexmm 6, 64
        .seh_endprologue

We set up RBP to point back to the parent stack frame, and then do XMM spills
through RBP. This is no good, because when we eventually return from
throw_internally, we will now restore XMM6 to the value it contained before
running the catch handler (2.0 in the example), and not the value it contained
before calling throw_internally (1.0 in the example).

Funclets should allocate their own stack memory to spill XMM registers.

This bug could probably also be observed by re-throwing the exception out of
the catch handler, since the .seh_savexmm directives we emit for the catch
handler are definitely wrong.

-- 
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/20170403/30a5b8a5/attachment.html>


More information about the llvm-bugs mailing list