From a7718b4889773a8d8842f407a5d791a2b08e2309 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Fri, 8 May 2020 15:56:09 -0300
Subject: [PATCH 3/6] Handle setjmp() taking two arguments in Windows.

* src/comp.c: Add `define_setjmp_deps()` and `emit_setjmp()` which
abstract over this difference in behavior between operating systems.

WARNING: Not all cases are handled by this patch. The Mingw-64
setjmp.h header deals with many other combinations. I don't think it
is a good idea to replicate the logic of that header inside
emacs. (Maybe a few lines in the configure script could be added to
handle this problem?)
---
 src/comp.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/src/comp.c b/src/comp.c
index 750fd4aaee..8a543e069d 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -22,6 +22,7 @@
 
 #ifdef HAVE_NATIVE_COMP
 
+#include <setjmp.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <signal.h>
@@ -74,10 +75,15 @@ #define DECL_BLOCK(name, func)				\
   gcc_jit_block *(name) =				\
     gcc_jit_function_new_block ((func), STR (name))
 
-#ifdef HAVE__SETJMP
-#define SETJMP _setjmp
+#ifndef _WIN32
+# ifdef HAVE__SETJMP
+#  define SETJMP _setjmp
+# else
+#  define SETJMP setjmp
+# endif
 #else
-#define SETJMP setjmp
+/* snippet from MINGW-64 setjmp.h */
+# define SETJMP _setjmp
 #endif
 #define SETJMP_NAME SETJMP
 
@@ -174,6 +180,9 @@ #define F_RELOC_MAX_SIZE 1500
   gcc_jit_function *setcdr;
   gcc_jit_function *check_type;
   gcc_jit_function *check_impure;
+#ifdef _WIN32
+  gcc_jit_function *setjmp_ctx_func;
+#endif
   Lisp_Object func_blocks_h; /* blk_name -> gcc_block.  */
   Lisp_Object exported_funcs_h; /* c-func-name -> gcc_jit_function *.  */
   Lisp_Object imported_funcs_h; /* subr_name -> gcc_jit_field *reloc_field.  */
@@ -1474,6 +1483,29 @@ emit_limple_call_ref (Lisp_Object insn, bool direct)
 			direct);
 }
 
+static gcc_jit_rvalue *
+emit_setjmp (gcc_jit_rvalue *buf)
+{
+#ifndef _WIN32
+  gcc_jit_rvalue *args[] = {buf};
+  return emit_call (intern_c_string (STR (SETJMP_NAME)), comp.int_type, 1, args,
+                   false);
+#else
+  /* _setjmp (buf, __builtin_frame_address (0)) */
+  gcc_jit_rvalue *args[2];
+
+  args[0] = gcc_jit_context_new_rvalue_from_int (comp.ctxt, comp.unsigned_type, 0);
+
+  args[1] = gcc_jit_context_new_call(comp.ctxt,
+                                     NULL,
+                                     comp.setjmp_ctx_func,
+                                     1, args);
+  args[0] = buf;
+  return emit_call (intern_c_string (STR (SETJMP_NAME)), comp.int_type, 2, args,
+                    false);
+#endif
+}
+
 /* Register an handler for a non local exit.  */
 
 static void
@@ -1500,8 +1532,7 @@ emit_limple_push_handler (gcc_jit_rvalue *handler, gcc_jit_rvalue *handler_type,
 	NULL);
 
   gcc_jit_rvalue *res;
-  res =
-    emit_call (intern_c_string (STR (SETJMP_NAME)), comp.int_type, 1, args, false);
+  res = emit_setjmp(args[0]);
   emit_cond_jump (res, handler_bb, guarded_bb);
 }
 
@@ -2060,8 +2091,14 @@ #define ADD_IMPORTED(f_name, ret_type, nargs, args)			       \
   args[1] = comp.int_type;
   ADD_IMPORTED (push_handler, comp.handler_ptr_type, 2, args);
 
+#ifndef _WIN32
   args[0] = gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.jmp_buf_s));
   ADD_IMPORTED (SETJMP_NAME, comp.int_type, 1, args);
+#else
+  args[0] = gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.jmp_buf_s));
+  args[1] = comp.void_ptr_type;
+  ADD_IMPORTED (SETJMP_NAME, comp.int_type, 2, args);
+#endif
 
   ADD_IMPORTED (record_unwind_protect_excursion, comp.void_type, 0, NULL);
 
@@ -2301,7 +2338,7 @@ define_jmp_buf (void)
       gcc_jit_context_new_array_type (comp.ctxt,
 				      NULL,
 				      comp.char_type,
-				      sizeof (jmp_buf)),
+				      sizeof (sys_jmp_buf)),
       "stuff");
   comp.jmp_buf_s =
     gcc_jit_context_new_struct_type (comp.ctxt,
@@ -2969,6 +3006,14 @@ define_CHECK_IMPURE (void)
     gcc_jit_block_end_with_void_return (err_block, NULL);
 }
 
+static void
+define_setjmp_deps (void)
+{
+  comp.setjmp_ctx_func
+    = gcc_jit_context_get_builtin_function (comp.ctxt,
+                                            "__builtin_frame_address");
+}
+
 /* Define a function to convert boolean into t or nil */
 
 static void
@@ -3357,6 +3402,7 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
   define_PSEUDOVECTORP ();
   define_CHECK_TYPE ();
   define_CHECK_IMPURE ();
+  define_setjmp_deps ();
   define_bool_to_lisp_obj ();
   define_setcar_setcdr ();
   define_add1_sub1 ();
-- 
2.25.1.windows.1

