mstorsjo created this revision.
Herald added a subscriber: aprantl.

Clang doesn't currently support building for windows/x86_64 with dwarf by 
setting command line parameters, but if manually modified to use dwarf, we can 
make libunwind work in this configuration as well.

Even if support for this is deemed pointless, I guess one could omit the 
assembly changes, but the fixes for the generic code probably are worthwhile at 
least.


https://reviews.llvm.org/D38819

Files:
  docs/index.rst
  include/unwind.h
  src/AddressSpace.hpp
  src/UnwindLevel1.c
  src/UnwindRegistersRestore.S
  src/UnwindRegistersSave.S

Index: src/UnwindRegistersSave.S
===================================================================
--- src/UnwindRegistersSave.S
+++ src/UnwindRegistersSave.S
@@ -63,6 +63,27 @@
 #  thread_state pointer is in rdi
 #
 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+#if defined(_WIN32)
+  movq  %rax,   (%rcx)
+  movq  %rbx,  8(%rcx)
+  movq  %rcx, 16(%rcx)
+  movq  %rdx, 24(%rcx)
+  movq  %rdi, 32(%rcx)
+  movq  %rsi, 40(%rcx)
+  movq  %rbp, 48(%rcx)
+  movq  %rsp, 56(%rcx)
+  addq  $8,   56(%rcx)
+  movq  %r8,  64(%rcx)
+  movq  %r9,  72(%rcx)
+  movq  %r10, 80(%rcx)
+  movq  %r11, 88(%rcx)
+  movq  %r12, 96(%rcx)
+  movq  %r13,104(%rcx)
+  movq  %r14,112(%rcx)
+  movq  %r15,120(%rcx)
+  movq  (%rsp),%rdx
+  movq  %rdx,128(%rcx) # store return address as rip
+#else
   movq  %rax,   (%rdi)
   movq  %rbx,  8(%rdi)
   movq  %rcx, 16(%rdi)
@@ -82,6 +103,7 @@
   movq  %r15,120(%rdi)
   movq  (%rsp),%rsi
   movq  %rsi,128(%rdi) # store return address as rip
+#endif
   # skip rflags
   # skip cs
   # skip fs
Index: src/UnwindRegistersRestore.S
===================================================================
--- src/UnwindRegistersRestore.S
+++ src/UnwindRegistersRestore.S
@@ -65,6 +65,40 @@
 #
 # void libunwind::Registers_x86_64::jumpto()
 #
+#if defined(_WIN32)
+# On entry, thread_state pointer is in rcx
+
+  movq  56(%rcx), %rax # rax holds new stack pointer
+  subq  $16, %rax
+  movq  %rax, 56(%rcx)
+  movq  16(%rcx), %rdx  # store new rcx on new stack
+  movq  %rdx, 0(%rax)
+  movq  128(%rcx), %rdx # store new rip on new stack
+  movq  %rdx, 8(%rax)
+  # restore all registers
+  movq    0(%rcx), %rax
+  movq    8(%rcx), %rbx
+  # restore rcx later
+  movq   24(%rcx), %rdx
+  movq   32(%rcx), %rdi
+  movq   40(%rcx), %rsi
+  movq   48(%rcx), %rbp
+  # restore rsp later
+  movq   64(%rcx), %r8
+  movq   72(%rcx), %r9
+  movq   80(%rcx), %r10
+  movq   88(%rcx), %r11
+  movq   96(%rcx), %r12
+  movq  104(%rcx), %r13
+  movq  112(%rcx), %r14
+  movq  120(%rcx), %r15
+  # skip rflags
+  # skip cs
+  # skip fs
+  # skip gs
+  movq  56(%rcx), %rsp  # cut back rsp to new location
+  pop    %rcx      # rcx was saved here earlier
+#else
 # On entry, thread_state pointer is in rdi
 
   movq  56(%rdi), %rax # rax holds new stack pointer
@@ -97,6 +131,7 @@
   # skip gs
   movq  56(%rdi), %rsp  # cut back rsp to new location
   pop    %rdi      # rdi was saved here earlier
+#endif
   ret            # rip was saved here
 
 
Index: src/UnwindLevel1.c
===================================================================
--- src/UnwindLevel1.c
+++ src/UnwindLevel1.c
@@ -86,7 +86,7 @@
     // this frame.
     if (frameInfo.handler != 0) {
       __personality_routine p =
-          (__personality_routine)(long)(frameInfo.handler);
+          (__personality_routine)(uintptr_t)(frameInfo.handler);
       _LIBUNWIND_TRACE_UNWINDING(
           "unwind_phase1(ex_ojb=%p): calling personality function %p",
           (void *)exception_object, (void *)(uintptr_t)p);
@@ -181,7 +181,7 @@
     // If there is a personality routine, tell it we are unwinding.
     if (frameInfo.handler != 0) {
       __personality_routine p =
-          (__personality_routine)(long)(frameInfo.handler);
+          (__personality_routine)(uintptr_t)(frameInfo.handler);
       _Unwind_Action action = _UA_CLEANUP_PHASE;
       if (sp == exception_object->private_2) {
         // Tell personality this was the frame it marked in phase 1.
Index: src/AddressSpace.hpp
===================================================================
--- src/AddressSpace.hpp
+++ src/AddressSpace.hpp
@@ -142,7 +142,7 @@
 /// making local unwinds fast.
 class __attribute__((visibility("hidden"))) LocalAddressSpace {
 public:
-#ifdef __LP64__
+#if defined(__LP64__) || defined(_WIN64)
   typedef uint64_t pint_t;
   typedef int64_t  sint_t;
 #else
@@ -194,7 +194,7 @@
 };
 
 inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
-#ifdef __LP64__
+#if defined(__LP64__) || defined(_WIN64)
   return get64(addr);
 #else
   return get32(addr);
Index: include/unwind.h
===================================================================
--- include/unwind.h
+++ include/unwind.h
@@ -122,7 +122,7 @@
                             _Unwind_Exception *exc);
   uintptr_t private_1; // non-zero means forced unwind
   uintptr_t private_2; // holds sp that phase1 found for phase2 to use
-#ifndef __LP64__
+#if !defined(__LP64__) && !defined(_WIN64)
   // The implementation of _Unwind_Exception uses an attribute mode on the
   // above fields which has the side effect of causing this whole struct to
   // round up to 32 bytes in size. To be more explicit, we add pad fields
Index: docs/index.rst
===================================================================
--- docs/index.rst
+++ docs/index.rst
@@ -50,7 +50,7 @@
 Linux        ARM                  Clang, GCC   EHABI
 Bare Metal   ARM                  Clang, GCC   EHABI
 NetBSD       x86_64               Clang, GCC   DWARF CFI
-Windows      i386                 Clang        DWARF CFI
+Windows      i386, x86_64         Clang        DWARF CFI
 Any          i386, x86_64, ARM    Clang        SjLj
 ============ ==================== ============ ========================
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to