unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [PATCH] [WIP] Port feature/native-comp to Windows.
@ 2020-05-08 19:55 Nicolas Bertolo
  2020-05-08 22:00 ` Andrea Corallo
                   ` (2 more replies)
  0 siblings, 3 replies; 71+ messages in thread
From: Nicolas Bertolo @ 2020-05-08 19:55 UTC (permalink / raw)
  To:  emacs-devel@gnu.org

[-- Attachment #1: Type: text/html, Size: 3121 bytes --]

[-- Attachment #2: 0001-HACK-Ensure-the-emacs_root_dir-function-does-not-cra.patch --]
[-- Type: application/octet-stream, Size: 1042 bytes --]

From 0fd74d1cb4ef523dd21b98333766da7fb7843fa6 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 16:30:11 -0300
Subject: [PATCH 1/6] HACK: Ensure the `emacs_root_dir` function does not
 crash.

That function is called when calling `load_pdump`. The problem is that
that happens too early in the initialization process and the
`emacs_dir` environment variable will not have been initialized yet.

The proper fix would be to initialize `emacs_dir` early enough. I do
not know enough of the Emacs internals to do that safely.
---
 src/w32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/w32.c b/src/w32.c
index 0f69e652a5..a8c763f23e 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -3154,7 +3154,7 @@ emacs_root_dir (void)
 
   p = getenv ("emacs_dir");
   if (p == NULL)
-    emacs_abort ();
+    p = "C:/Users";
   filename_from_ansi (p, root_dir);
   root_dir[parse_root (root_dir, NULL)] = '\0';
   dostounix_filename (root_dir);
-- 
2.25.1.windows.1


[-- Attachment #3: 0002-Do-not-block-SIGIO-in-platforms-that-don-t-have-it.patch --]
[-- Type: application/octet-stream, Size: 909 bytes --]

From 1dea64f24b8e9ea8a8d4ec135bd01fdb264e1fd2 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 16:02:58 -0300
Subject: [PATCH 2/6] Do not block SIGIO in platforms that don't have it.

* src/comp.c (comp--compile-ctxt-to-file): Add a preprocessor check to
avoid blocking SIGIO in platforms that don't have it.
---
 src/comp.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/comp.c b/src/comp.c
index d021be479b..750fd4aaee 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -3345,7 +3345,9 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
       sigemptyset (&blocked);
       sigaddset (&blocked, SIGALRM);
       sigaddset (&blocked, SIGINT);
+#ifdef USABLE_SIGIO
       sigaddset (&blocked, SIGIO);
+#endif
       pthread_sigmask (SIG_BLOCK, &blocked, &oldset);
     }
   emit_ctxt_code ();
-- 
2.25.1.windows.1


[-- Attachment #4: 0003-Handle-setjmp-taking-two-arguments-in-Windows.patch --]
[-- Type: application/octet-stream, Size: 4674 bytes --]

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


[-- Attachment #5: 0004-Handle-LISP_WORDS_ARE_POINTERS-and-CHECK_LISP_OBJECT.patch --]
[-- Type: application/octet-stream, Size: 18568 bytes --]

From 8b34725a83296c413c19a89717b43a4aedf48278 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 14:30:14 -0300
Subject: [PATCH 4/6] Handle LISP_WORDS_ARE_POINTERS and
 CHECK_LISP_OBJECT_TYPE.

* src/comp.c: Introduce the Lisp_X, Lisp_Word, and Lisp_Word_tag
types. These types are used instead of long or long long. Use
emacs_int_type and emacs_uint_types where appropriate.
(emit_coerce): Add special logic that handles the case when
Lisp_Object is a struct. This is necessary for handling the
--enable-check-lisp-object-type configure option.

* src/lisp.h: Since libgccjit does not support opaque unions, change
Lisp_X to be struct. This is done to ensure that the same types are
used in the same binary. It is probably unnecessary since only a
pointer to it is used.
---
 src/comp.c | 330 ++++++++++++++++++++++++++++++++++++-----------------
 src/lisp.h |   5 +-
 2 files changed, 229 insertions(+), 106 deletions(-)

diff --git a/src/comp.c b/src/comp.c
index 8a543e069d..c37a88321b 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -116,6 +116,16 @@ #define F_RELOC_MAX_SIZE 1500
   gcc_jit_type *char_ptr_type;
   gcc_jit_type *ptrdiff_type;
   gcc_jit_type *uintptr_type;
+#if LISP_WORDS_ARE_POINTERS
+  gcc_jit_struct *lisp_X_s;
+  gcc_jit_type *lisp_X;
+#endif
+  gcc_jit_type *lisp_word_type;
+  gcc_jit_type *lisp_word_tag_type;
+#ifdef LISP_OBJECT_IS_STRUCT
+  gcc_jit_field *lisp_obj_i;
+  gcc_jit_struct *lisp_obj_s;
+#endif
   gcc_jit_type *lisp_obj_type;
   gcc_jit_type *lisp_obj_ptr_type;
   /* struct Lisp_Cons */
@@ -158,7 +168,8 @@ #define F_RELOC_MAX_SIZE 1500
   gcc_jit_field *cast_union_as_c_p;
   gcc_jit_field *cast_union_as_v_p;
   gcc_jit_field *cast_union_as_lisp_cons_ptr;
-  gcc_jit_field *cast_union_as_lisp_obj;
+  gcc_jit_field *cast_union_as_lisp_word;
+  gcc_jit_field *cast_union_as_lisp_word_tag;
   gcc_jit_field *cast_union_as_lisp_obj_ptr;
   gcc_jit_function *func; /* Current function being compiled.  */
   bool func_has_non_local; /* From comp-func has-non-local slot.  */
@@ -347,8 +358,10 @@ type_to_cast_field (gcc_jit_type *type)
     field = comp.cast_union_as_c_p;
   else if (type == comp.lisp_cons_ptr_type)
     field = comp.cast_union_as_lisp_cons_ptr;
-  else if (type == comp.lisp_obj_type)
-    field = comp.cast_union_as_lisp_obj;
+  else if (type == comp.lisp_word_type)
+    field = comp.cast_union_as_lisp_word;
+  else if (type == comp.lisp_word_tag_type)
+    field = comp.cast_union_as_lisp_word_tag;
   else if (type == comp.lisp_obj_ptr_type)
     field = comp.cast_union_as_lisp_obj_ptr;
   else
@@ -627,6 +640,31 @@ emit_coerce (gcc_jit_type *new_type, gcc_jit_rvalue *obj)
   if (new_type == old_type)
     return obj;
 
+#ifdef LISP_OBJECT_IS_STRUCT
+  if (old_type == comp.lisp_obj_type)
+    {
+      gcc_jit_rvalue *lwordobj =
+        gcc_jit_rvalue_access_field (obj, NULL, comp.lisp_obj_i);
+      return emit_coerce (new_type, lwordobj);
+    }
+
+  if (new_type == comp.lisp_obj_type)
+    {
+      gcc_jit_rvalue *lwordobj =
+        emit_coerce (comp.lisp_word_type, obj);
+
+      gcc_jit_lvalue *tmp_s
+        = gcc_jit_function_new_local (comp.func, NULL, comp.lisp_obj_type,
+                                      format_string ("lisp_obj_%td", i++));
+
+      gcc_jit_block_add_assignment (comp.block, NULL,
+                                    gcc_jit_lvalue_access_field (tmp_s, NULL,
+                                                                 comp.lisp_obj_i),
+                                    lwordobj);
+      return gcc_jit_lvalue_as_rvalue (tmp_s);
+    }
+#endif
+
   gcc_jit_field *orig_field =
     type_to_cast_field (old_type);
   gcc_jit_field *dest_field = type_to_cast_field (new_type);
@@ -664,14 +702,8 @@ emit_binary_op (enum gcc_jit_binary_op op,
 /* Should come with libgccjit.  */
 
 static gcc_jit_rvalue *
-emit_rvalue_from_long_long (long long n)
+emit_rvalue_from_long_long (gcc_jit_type *type, long long n)
 {
-#ifndef WIDE_EMACS_INT
-  xsignal1 (Qnative_ice,
-	    build_string ("emit_rvalue_from_long_long called in non wide int"
-			  " configuration"));
-#endif
-
   emit_comment (format_string ("emit long long: %lld", n));
 
   gcc_jit_rvalue *high =
@@ -697,7 +729,7 @@ emit_rvalue_from_long_long (long long n)
 		      32));
 
   return
-    emit_coerce (comp.long_long_type,
+    emit_coerce (type,
       emit_binary_op (
 	GCC_JIT_BINARY_OP_BITWISE_OR,
 	comp.unsigned_long_long_type,
@@ -712,29 +744,135 @@ emit_rvalue_from_long_long (long long n)
 }
 
 static gcc_jit_rvalue *
-emit_most_positive_fixnum (void)
+emit_rvalue_from_unsigned_long_long (gcc_jit_type *type, unsigned long long n)
+{
+  emit_comment (format_string ("emit unsigned long long: %llu", n));
+
+  gcc_jit_rvalue *high =
+    gcc_jit_context_new_rvalue_from_long (comp.ctxt,
+					  comp.unsigned_long_long_type,
+					  n >> 32);
+  gcc_jit_rvalue *low =
+    emit_binary_op (GCC_JIT_BINARY_OP_RSHIFT,
+		    comp.unsigned_long_long_type,
+		    emit_binary_op (GCC_JIT_BINARY_OP_LSHIFT,
+				    comp.unsigned_long_long_type,
+				    gcc_jit_context_new_rvalue_from_long (
+				      comp.ctxt,
+				      comp.unsigned_long_long_type,
+				      n),
+				    gcc_jit_context_new_rvalue_from_int (
+				      comp.ctxt,
+				      comp.unsigned_long_long_type,
+				      32)),
+		    gcc_jit_context_new_rvalue_from_int (
+		      comp.ctxt,
+		      comp.unsigned_long_long_type,
+		      32));
+
+  return emit_coerce (
+           type,
+           emit_binary_op (
+             GCC_JIT_BINARY_OP_BITWISE_OR,
+             comp.unsigned_long_long_type,
+             emit_binary_op (
+               GCC_JIT_BINARY_OP_LSHIFT,
+               comp.unsigned_long_long_type,
+               high,
+               gcc_jit_context_new_rvalue_from_int (comp.ctxt,
+                                                    comp.unsigned_long_long_type,
+                                                    32)),
+             low));
+}
+
+static gcc_jit_rvalue *
+emit_rvalue_from_emacs_uint (EMACS_UINT val)
+{
+  if (val != (long) val)
+    {
+      return gcc_jit_context_new_rvalue_from_long (comp.ctxt,
+                                                   comp.emacs_uint_type,
+                                                   val);
+    }
+  else
+    {
+      return emit_rvalue_from_unsigned_long_long (comp.emacs_uint_type, val);
+    }
+}
+
+static gcc_jit_rvalue *
+emit_rvalue_from_emacs_int (EMACS_INT val)
+{
+  if (val != (long) val)
+    {
+      return emit_rvalue_from_long_long (comp.emacs_int_type, val);
+    }
+  else
+    {
+      return gcc_jit_context_new_rvalue_from_long (comp.ctxt,
+                                                   comp.emacs_int_type, val);
+    }
+}
+
+static gcc_jit_rvalue *
+emit_rvalue_from_lisp_word_tag (Lisp_Word_tag val)
 {
-#if EMACS_INT_MAX > LONG_MAX
-  return emit_rvalue_from_long_long (MOST_POSITIVE_FIXNUM);
+  if (val != (long) val)
+    {
+      return emit_rvalue_from_unsigned_long_long (comp.lisp_word_tag_type, val);
+    }
+  else
+    {
+      return gcc_jit_context_new_rvalue_from_long (comp.ctxt,
+                                                   comp.lisp_word_tag_type,
+                                                   val);
+    }
+}
+
+static gcc_jit_rvalue *
+emit_rvalue_from_lisp_word (Lisp_Word val)
+{
+#if LISP_WORDS_ARE_POINTERS
+  return gcc_jit_context_new_rvalue_from_ptr (comp.ctxt,
+                                              comp.lisp_word_type,
+                                              val);
 #else
-  return gcc_jit_context_new_rvalue_from_long (comp.ctxt,
-					       comp.emacs_int_type,
-					       MOST_POSITIVE_FIXNUM);
+  if (val != (long) val)
+    {
+      return emit_rvalue_from_unsigned_long_long (comp.lisp_word_type, val);
+    }
+  else
+    {
+      return gcc_jit_context_new_rvalue_from_long (comp.ctxt,
+                                                   comp.lisp_word_type,
+                                                   val);
+    }
 #endif
 }
 
 static gcc_jit_rvalue *
-emit_most_negative_fixnum (void)
+emit_rvalue_from_lisp_obj (Lisp_Object obj)
 {
-#if EMACS_INT_MAX > LONG_MAX
-  return emit_rvalue_from_long_long (MOST_NEGATIVE_FIXNUM);
+#ifdef LISP_OBJECT_IS_STRUCT
+  return emit_coerce(comp.lisp_obj_type,
+                     emit_rvalue_from_lisp_word (obj.i));
 #else
-  return gcc_jit_context_new_rvalue_from_long (comp.ctxt,
-					       comp.emacs_int_type,
-					       MOST_NEGATIVE_FIXNUM);
+  return emit_rvalue_from_lisp_word (obj);
 #endif
 }
 
+static gcc_jit_rvalue *
+emit_most_positive_fixnum (void)
+{
+  return emit_rvalue_from_emacs_int(MOST_POSITIVE_FIXNUM);
+}
+
+static gcc_jit_rvalue *
+emit_most_negative_fixnum (void)
+{
+  return emit_rvalue_from_emacs_int (MOST_NEGATIVE_FIXNUM);
+}
+
 /*
    Emit the equivalent of:
    (typeof_ptr) ((uintptr) ptr + size_of_ptr_ref * i)
@@ -769,7 +907,7 @@ emit_ptr_arithmetic (gcc_jit_rvalue *ptr, gcc_jit_type *ptr_type,
 emit_XLI (gcc_jit_rvalue *obj)
 {
   emit_comment ("XLI");
-  return obj;
+  return emit_coerce (comp.emacs_int_type, obj);
 }
 
 static gcc_jit_lvalue *
@@ -779,54 +917,40 @@ emit_lval_XLI (gcc_jit_lvalue *obj)
   return obj;
 }
 
-/*
+
 static gcc_jit_rvalue *
 emit_XLP (gcc_jit_rvalue *obj)
 {
   emit_comment ("XLP");
 
-  return gcc_jit_rvalue_access_field (obj,
-				      NULL,
-				      comp.lisp_obj_as_ptr);
+  return emit_coerce(comp.void_ptr_type, obj);
 }
 
-static gcc_jit_lvalue *
-emit_lval_XLP (gcc_jit_lvalue *obj)
-{
-  emit_comment ("lval_XLP");
+/* TODO */
+/* static gcc_jit_lvalue * */
+/* emit_lval_XLP (gcc_jit_lvalue *obj) */
+/* { */
+/*   emit_comment ("lval_XLP"); */
+
+/*   return gcc_jit_lvalue_access_field (obj, */
+/* 				      NULL, */
+/* 				      comp.lisp_obj_as_ptr); */
+/* } */
 
-  return gcc_jit_lvalue_access_field (obj,
-				      NULL,
-				      comp.lisp_obj_as_ptr);
-} */
 static gcc_jit_rvalue *
-emit_XUNTAG (gcc_jit_rvalue *a, gcc_jit_type *type, long long lisp_word_tag)
+emit_XUNTAG (gcc_jit_rvalue *a, gcc_jit_type *type, Lisp_Word_tag lisp_word_tag)
 {
   /* #define XUNTAG(a, type, ctype) ((ctype *)
      ((char *) XLP (a) - LISP_WORD_TAG (type))) */
   emit_comment ("XUNTAG");
 
-#ifndef WIDE_EMACS_INT
   return emit_coerce (
 	   gcc_jit_type_get_pointer (type),
 	   emit_binary_op (
 	     GCC_JIT_BINARY_OP_MINUS,
-	     comp.emacs_int_type,
-	     emit_XLI (a),
-	     gcc_jit_context_new_rvalue_from_int (
-	       comp.ctxt,
-	       comp.emacs_int_type,
-	       lisp_word_tag)));
-#else
-  return emit_coerce (
-	   gcc_jit_type_get_pointer (type),
-	   emit_binary_op (
-	     GCC_JIT_BINARY_OP_MINUS,
-	     comp.unsigned_long_long_type,
-	     /* FIXME Should be XLP.  */
-	     emit_XLI (a),
-	     emit_rvalue_from_long_long (lisp_word_tag)));
-#endif
+	     comp.uintptr_type,
+	     emit_XLP (a),
+	     emit_rvalue_from_lisp_word_tag(lisp_word_tag)));
 }
 
 static gcc_jit_rvalue *
@@ -853,7 +977,7 @@ emit_EQ (gcc_jit_rvalue *x, gcc_jit_rvalue *y)
 }
 
 static gcc_jit_rvalue *
-emit_TAGGEDP (gcc_jit_rvalue *obj, ptrdiff_t tag)
+emit_TAGGEDP (gcc_jit_rvalue *obj, Lisp_Word_tag tag)
 {
    /* (! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \
 	- (unsigned) (tag)) \
@@ -1054,17 +1178,7 @@ emit_make_fixnum_LSB_TAG (gcc_jit_rvalue *n)
 			comp.emacs_int_type,
 			tmp, comp.lisp_int0);
 
-  gcc_jit_lvalue *res = gcc_jit_function_new_local (comp.func,
-						    NULL,
-						    comp.lisp_obj_type,
-						    "lisp_obj_fixnum");
-
-  gcc_jit_block_add_assignment (comp.block,
-				NULL,
-				emit_lval_XLI (res),
-				tmp);
-
-  return gcc_jit_lvalue_as_rvalue (res);
+  return emit_coerce (comp.lisp_obj_type, tmp);
 }
 
 static gcc_jit_rvalue *
@@ -1076,10 +1190,8 @@ emit_make_fixnum_MSB_TAG (gcc_jit_rvalue *n)
     return XIL (n);
   */
 
-  gcc_jit_rvalue *intmask =
-    emit_coerce (comp.emacs_uint_type,
-		 emit_rvalue_from_long_long ((EMACS_INT_MAX
-					      >> (INTTYPEBITS - 1))));
+  gcc_jit_rvalue *intmask = emit_rvalue_from_emacs_uint (INTMASK);
+
   n = emit_binary_op (GCC_JIT_BINARY_OP_BITWISE_AND,
 		      comp.emacs_uint_type,
 		      intmask, n);
@@ -1090,12 +1202,10 @@ emit_make_fixnum_MSB_TAG (gcc_jit_rvalue *n)
 		    emit_binary_op (GCC_JIT_BINARY_OP_LSHIFT,
 				    comp.emacs_uint_type,
 				    comp.lisp_int0,
-				    gcc_jit_context_new_rvalue_from_int (
-				      comp.ctxt,
-				      comp.emacs_uint_type,
-				      VALBITS)),
+                                    emit_rvalue_from_emacs_uint(VALBITS)),
 		    n);
-  return emit_XLI (emit_coerce (comp.emacs_int_type, n));
+
+  return emit_coerce (comp.lisp_obj_type, n);
 }
 
 
@@ -1114,17 +1224,10 @@ emit_const_lisp_obj (Lisp_Object obj)
   emit_comment (format_string ("const lisp obj: %s",
 			       SSDATA (Fprin1_to_string (obj, Qnil))));
 
-  if (NIL_IS_ZERO && EQ (obj, Qnil))
+  if (EQ (obj, Qnil))
     {
       gcc_jit_rvalue *n;
-#ifdef WIDE_EMACS_INT
-      eassert (NIL_IS_ZERO);
-      n = emit_rvalue_from_long_long (0);
-#else
-      n = gcc_jit_context_new_rvalue_from_ptr (comp.ctxt,
-					       comp.void_ptr_type,
-					       NULL);
-#endif
+      n = emit_rvalue_from_lisp_word ((Lisp_Word) iQnil);
       return emit_coerce (comp.lisp_obj_type, n);
     }
 
@@ -1345,16 +1448,7 @@ emit_mvar_val (Lisp_Object mvar)
 	  /* We can still emit directly objects that are self-contained in a
 	     word (read fixnums).  */
 	  emit_comment (SSDATA (Fprin1_to_string (constant, Qnil)));
-	  gcc_jit_rvalue *word;
-#ifdef WIDE_EMACS_INT
-	  word = emit_rvalue_from_long_long (constant);
-#else
-	  word =
-	    gcc_jit_context_new_rvalue_from_ptr (comp.ctxt,
-						 comp.void_ptr_type,
-						 constant);
-#endif
-	  return emit_coerce (comp.lisp_obj_type, word);
+          return emit_rvalue_from_lisp_obj(constant);
 	}
       /* Other const objects are fetched from the reloc array.  */
       return emit_const_lisp_obj (constant);
@@ -2518,11 +2612,16 @@ define_cast_union (void)
 			       NULL,
 			       comp.lisp_cons_ptr_type,
 			       "cons_ptr");
-  comp.cast_union_as_lisp_obj =
+  comp.cast_union_as_lisp_word =
     gcc_jit_context_new_field (comp.ctxt,
 			       NULL,
-			       comp.lisp_obj_type,
-			       "lisp_obj");
+			       comp.lisp_word_type,
+			       "lisp_word");
+  comp.cast_union_as_lisp_word_tag =
+    gcc_jit_context_new_field (comp.ctxt,
+                               NULL,
+                               comp.lisp_word_tag_type,
+                               "lisp_word_tag");
   comp.cast_union_as_lisp_obj_ptr =
     gcc_jit_context_new_field (comp.ctxt,
 			       NULL,
@@ -2543,7 +2642,8 @@ define_cast_union (void)
       comp.cast_union_as_c_p,
       comp.cast_union_as_v_p,
       comp.cast_union_as_lisp_cons_ptr,
-      comp.cast_union_as_lisp_obj,
+      comp.cast_union_as_lisp_word,
+      comp.cast_union_as_lisp_word_tag,
       comp.cast_union_as_lisp_obj_ptr };
   comp.cast_union_type =
     gcc_jit_context_new_union_type (comp.ctxt,
@@ -2810,8 +2910,8 @@ define_add1_sub1 (void)
 					  GCC_JIT_COMPARISON_NE,
 					  n_fixnum,
 					  i == 0
-					  ? emit_most_positive_fixnum ()
-					  : emit_most_negative_fixnum ())),
+					  ? emit_rvalue_from_emacs_int (MOST_POSITIVE_FIXNUM)
+					  : emit_rvalue_from_emacs_int (MOST_NEGATIVE_FIXNUM))),
 	inline_block,
 	fcall_block);
 
@@ -3307,9 +3407,31 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
   comp.emacs_uint_type = gcc_jit_context_get_int_type (comp.ctxt,
 						       sizeof (EMACS_UINT),
 						       false);
-  /* No XLP is emitted for now so lets define this always as integer
-     disregarding LISP_WORDS_ARE_POINTERS value.  */
-  comp.lisp_obj_type = comp.emacs_int_type;
+#if LISP_WORDS_ARE_POINTERS
+  comp.lisp_X_s = gcc_jit_context_new_opaque_struct (comp.ctxt,
+                                                     NULL,
+                                                     "Lisp_X");
+  comp.lisp_X = gcc_jit_struct_as_type(comp.lisp_X_s);
+  comp.lisp_word_type = gcc_jit_type_get_pointer(comp.lisp_X);
+#else
+  comp.lisp_word_type = comp.emacs_int_type;
+#endif
+  comp.lisp_word_tag_type
+    = gcc_jit_context_get_int_type (comp.ctxt, sizeof (Lisp_Word_tag), false);
+#ifdef LISP_OBJECT_IS_STRUCT
+  comp.lisp_obj_i = gcc_jit_context_new_field (comp.ctxt,
+                                               NULL,
+                                               comp.lisp_word_type,
+                                               "i");
+  comp.lisp_obj_s = gcc_jit_context_new_struct_type (comp.ctxt,
+                                                     NULL,
+                                                     "Lisp_Object",
+                                                     1,
+                                                     &comp.lisp_obj_i);
+  comp.lisp_obj_type = gcc_jit_struct_as_type (comp.lisp_obj_s);
+#else
+  comp.lisp_obj_type = comp.lisp_word_type;
+#endif
   comp.lisp_obj_ptr_type = gcc_jit_type_get_pointer (comp.lisp_obj_type);
   comp.one =
     gcc_jit_context_new_rvalue_from_int (comp.ctxt,
@@ -3612,7 +3734,7 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
   Lisp_Object *saved_cu = dynlib_sym (handle, COMP_UNIT_SYM);
   if (!saved_cu)
     xsignal1 (Qnative_lisp_file_inconsistent, comp_u->file);
-  bool reloading_cu = *saved_cu ? true : false;
+  bool reloading_cu = !NILP(*saved_cu);
   Lisp_Object *data_eph_relocs =
     dynlib_sym (handle, DATA_RELOC_EPHEMERAL_SYM);
 
diff --git a/src/lisp.h b/src/lisp.h
index 3d082911f5..e3d196ef9b 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -299,12 +299,12 @@ #define GCALIGNED(type) (alignof (type) % GCALIGNMENT == 0)
 
 /* Lisp_Word is a scalar word suitable for holding a tagged pointer or
    integer.  Usually it is a pointer to a deliberately-incomplete type
-   'union Lisp_X'.  However, it is EMACS_INT when Lisp_Objects and
+   'struct Lisp_X'.  However, it is EMACS_INT when Lisp_Objects and
    pointers differ in width.  */
 
 #define LISP_WORDS_ARE_POINTERS (EMACS_INT_MAX == INTPTR_MAX)
 #if LISP_WORDS_ARE_POINTERS
-typedef union Lisp_X *Lisp_Word;
+typedef struct Lisp_X *Lisp_Word;
 #else
 typedef EMACS_INT Lisp_Word;
 #endif
@@ -573,6 +573,7 @@ #define ENUM_BF(TYPE) enum TYPE
 
 #ifdef CHECK_LISP_OBJECT_TYPE
 typedef struct Lisp_Object { Lisp_Word i; } Lisp_Object;
+# define LISP_OBJECT_IS_STRUCT
 # define LISP_INITIALLY(w) {w}
 # undef CHECK_LISP_OBJECT_TYPE
 enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true };
-- 
2.25.1.windows.1


[-- Attachment #6: 0005-Remove-a-layer-of-indirection-for-access-to-pure-sto.patch --]
[-- Type: application/octet-stream, Size: 3345 bytes --]

From 4edb3f11915a41c1a45273fe0e8cbc62818e9865 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 16:23:10 -0300
Subject: [PATCH 5/6] Remove a layer of indirection for access to pure storage.

* src/comp.c: Taking the address of an array is the same as casting it
to a pointer. Therefore, the C expression `(EMACS_INT **) &pure` is in
fact adding a layer of indirection that is not necessary. The fix is
to cast the `pure` array to a pointer and store that in a void pointer
that is part of the compiled shared library.
---
 src/comp.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/src/comp.c b/src/comp.c
index c37a88321b..57bbda2c4e 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -38,7 +38,7 @@
 
 /* C symbols emitted for the load relocation mechanism.  */
 #define CURRENT_THREAD_RELOC_SYM "current_thread_reloc"
-#define PURE_RELOC_SYM "pure_reloc"
+#define PURE_PTR_SYM "pure_ptr"
 #define DATA_RELOC_SYM "d_reloc"
 #define DATA_RELOC_IMPURE_SYM "d_reloc_imp"
 #define DATA_RELOC_EPHEMERAL_SYM "d_reloc_eph"
@@ -152,7 +152,7 @@ #define F_RELOC_MAX_SIZE 1500
   gcc_jit_type *thread_state_ptr_type;
   gcc_jit_rvalue *current_thread_ref;
   /* Other globals.  */
-  gcc_jit_rvalue *pure_ref;
+  gcc_jit_rvalue *pure_ptr;
   /* libgccjit has really limited support for casting therefore this union will
      be used for the scope.  */
   gcc_jit_type *cast_union_type;
@@ -1419,8 +1419,7 @@ emit_PURE_P (gcc_jit_rvalue *ptr)
 	GCC_JIT_BINARY_OP_MINUS,
 	comp.uintptr_type,
 	ptr,
-	gcc_jit_lvalue_as_rvalue (
-	  gcc_jit_rvalue_dereference (comp.pure_ref, NULL))),
+        comp.pure_ptr),
       gcc_jit_context_new_rvalue_from_int (comp.ctxt,
 					   comp.uintptr_type,
 					   PURESIZE));
@@ -2244,14 +2243,14 @@ emit_ctxt_code (void)
 	gcc_jit_type_get_pointer (comp.thread_state_ptr_type),
 	CURRENT_THREAD_RELOC_SYM));
 
-  comp.pure_ref =
+  comp.pure_ptr =
     gcc_jit_lvalue_as_rvalue (
       gcc_jit_context_new_global (
 	comp.ctxt,
 	NULL,
 	GCC_JIT_GLOBAL_EXPORTED,
-	gcc_jit_type_get_pointer (comp.void_ptr_type),
-	PURE_RELOC_SYM));
+        comp.void_ptr_type,
+	PURE_PTR_SYM));
 
   gcc_jit_context_new_global (
 	comp.ctxt,
@@ -3767,13 +3766,13 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
     {
       struct thread_state ***current_thread_reloc =
 	dynlib_sym (handle, CURRENT_THREAD_RELOC_SYM);
-      EMACS_INT ***pure_reloc = dynlib_sym (handle, PURE_RELOC_SYM);
+      void **pure_ptr = dynlib_sym (handle, PURE_PTR_SYM);
       Lisp_Object *data_relocs = dynlib_sym (handle, DATA_RELOC_SYM);
       Lisp_Object *data_imp_relocs = dynlib_sym (handle, DATA_RELOC_IMPURE_SYM);
       void **freloc_link_table = dynlib_sym (handle, FUNC_LINK_TABLE_SYM);
 
       if (!(current_thread_reloc
-	    && pure_reloc
+	    && pure_ptr
 	    && data_relocs
 	    && data_imp_relocs
 	    && data_eph_relocs
@@ -3784,7 +3783,7 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
 	xsignal1 (Qnative_lisp_file_inconsistent, comp_u->file);
 
       *current_thread_reloc = &current_thread;
-      *pure_reloc = (EMACS_INT **)&pure;
+      *pure_ptr = pure;
 
       /* Imported functions.  */
       *freloc_link_table = freloc.link_table;
-- 
2.25.1.windows.1


[-- Attachment #7: 0006-Workaround-the-32768-chars-command-line-limit-in-Win.patch --]
[-- Type: application/octet-stream, Size: 2422 bytes --]

From 081fb2dca81b6232e775d6133e742f9d3916df55 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 14:04:06 -0300
Subject: [PATCH 6/6] Workaround the 32768 chars command line limit in Windows.

* lisp/emacs-lisp/comp.el (comp-run-async-workers): Pass the
compilation commands through a temporary file that is loaded by the
child process. This is also done all other operating systems, even
those that support long command lines. It should not be a problem
since libgccjit uses temporary files too.
---
 lisp/emacs-lisp/comp.el | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 05417fdc31..f2dd199536 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -2207,6 +2207,9 @@ comp-run-async-workers
                             (message "Compiling %s..." ,source-file)
                             (native-compile ,source-file ,(and load t))))
                    (source-file1 source-file) ;; Make the closure works :/
+                   (temp-file (make-temp-file
+                               (concat "emacs-async-comp-" (file-name-base source-file) "-")
+                               nil ".el" (prin1-to-string expr)))
                    (load1 load)
                    (process (make-process
                              :name (concat "Compiling: " source-file)
@@ -2214,13 +2217,14 @@ comp-run-async-workers
                              :command (list
                                        (expand-file-name invocation-name
                                                          invocation-directory)
-                                       "--batch" "--eval" (prin1-to-string expr))
+                                       "--batch" "-l" temp-file)
                              :sentinel
                              (lambda (process _event)
                                (run-hook-with-args
                                 'comp-async-cu-done-hook
                                 source-file)
                                (accept-process-output process)
+                               (ignore-errors (delete-file temp-file))
                                (when (and load1
                                           (zerop (process-exit-status process)))
                                  (native-elisp-load
-- 
2.25.1.windows.1


^ permalink raw reply related	[flat|nested] 71+ messages in thread

end of thread, other threads:[~2020-05-13 15:48 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-08 19:55 [PATCH] [WIP] Port feature/native-comp to Windows Nicolas Bertolo
2020-05-08 22:00 ` Andrea Corallo
2020-05-08 22:11   ` Nicolas Bértolo
2020-05-08 22:22     ` Andrea Corallo
2020-05-08 22:23       ` Nicolas Bértolo
2020-05-08 22:27         ` Andrea Corallo
2020-05-08 23:18           ` Stefan Monnier
2020-05-09  6:07 ` Eli Zaretskii
2020-05-09 15:28   ` Nicolas Bértolo
2020-05-09 15:48     ` Eli Zaretskii
2020-05-09 17:09       ` Andrea Corallo
2020-05-10 16:36       ` Nicolas Bértolo
2020-05-10 17:08         ` Eli Zaretskii
2020-05-10 17:50           ` Nicolas Bértolo
2020-05-10 18:22             ` Eli Zaretskii
2020-05-10 19:02               ` Nicolas Bértolo
2020-05-10 19:16                 ` Eli Zaretskii
2020-05-10 19:41                   ` Nicolas Bértolo
2020-05-10 19:50                     ` Andrea Corallo
2020-05-10 19:55                       ` Nicolas Bértolo
2020-05-10 20:01                         ` Andrea Corallo
2020-05-11 14:19                         ` Eli Zaretskii
2020-05-11 14:17                     ` Eli Zaretskii
2020-05-11 15:20                       ` Nicolas Bértolo
2020-05-11 16:19                         ` Eli Zaretskii
2020-05-11 16:43                           ` Andrea Corallo
2020-05-11 16:44                           ` Nicolas Bértolo
2020-05-11 17:05                             ` Eli Zaretskii
2020-05-11 18:19                           ` Fabrice Popineau
2020-05-11 18:37                             ` Andrea Corallo
2020-05-11 18:48                             ` Eli Zaretskii
2020-05-11 19:27                               ` Stefan Monnier
2020-05-11 19:42                               ` Fabrice Popineau
2020-05-12  2:46                       ` Nicolas Bértolo
2020-05-12 16:56                         ` Eli Zaretskii
2020-05-12 17:25                           ` Nicolas Bértolo
2020-05-12 18:21                             ` Andrea Corallo
2020-05-12 20:33                               ` Andrea Corallo
2020-05-13 14:09                                 ` Nicolas Bértolo
2020-05-13 14:31                                   ` Andrea Corallo
2020-05-13 15:00                                     ` Nicolas Bértolo
2020-05-13 15:17                                       ` Andrea Corallo
2020-05-13 15:48                                   ` Eli Zaretskii
2020-05-13  3:59                         ` Richard Stallman
2020-05-13 14:02                           ` Nicolas Bértolo
2020-05-13 15:23                             ` Eli Zaretskii
2020-05-13 14:52                           ` Eli Zaretskii
2020-05-10 19:47                   ` Andrea Corallo
2020-05-10 19:39                 ` Andrea Corallo
2020-05-10 17:13         ` Andrea Corallo
2020-05-10 17:15           ` Eli Zaretskii
2020-05-10 18:14             ` Andrea Corallo
2020-05-10 18:30               ` Eli Zaretskii
2020-05-10 18:54                 ` Andrea Corallo
2020-05-10 19:02                   ` Eli Zaretskii
2020-05-10 19:07                     ` Nicolas Bértolo
2020-05-10 19:14                     ` Andrea Corallo
2020-05-10 19:24                     ` Andrea Corallo
2020-05-10 19:30                       ` Eli Zaretskii
2020-05-10 18:05           ` Nicolas Bértolo
2020-05-10 18:23             ` Andrea Corallo
2020-05-10 17:20       ` Andrea Corallo
2020-05-09 13:42 ` Andrea Corallo
2020-05-09 15:40   ` Nicolas Bértolo
2020-05-09 15:55     ` Eli Zaretskii
2020-05-09 16:07       ` Nicolas Bértolo
2020-05-09 16:15         ` Eli Zaretskii
2020-05-09 16:27     ` Andrea Corallo
2020-05-09 16:33       ` Eli Zaretskii
2020-05-09 16:46         ` Andrea Corallo
2020-05-09 16:52     ` Andrea Corallo

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).