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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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-09  6:07 ` Eli Zaretskii
  2020-05-09 13:42 ` Andrea Corallo
  2 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-08 22:00 UTC (permalink / raw)
  To: Nicolas Bertolo; +Cc:  emacs-devel@gnu.org

Hi Nicolas,

this sounds just amazing thanks!  Tomorrow I'll look into these.

Have you the copyright paperwork done already?

Thanks

  Andrea
-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-08 22:00 ` Andrea Corallo
@ 2020-05-08 22:11   ` Nicolas Bértolo
  2020-05-08 22:22     ` Andrea Corallo
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-08 22:11 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: emacs-devel@gnu.org

Hi Andrea,

Thanks.
I haven't signed the paperwork.

Nicolas

El vie., 8 may. 2020 a las 19:01, Andrea Corallo (<akrl@sdf.org>) escribió:
>
> Hi Nicolas,
>
> this sounds just amazing thanks!  Tomorrow I'll look into these.
>
> Have you the copyright paperwork done already?
>
> Thanks
>
>   Andrea
> --
> akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-08 22:11   ` Nicolas Bértolo
@ 2020-05-08 22:22     ` Andrea Corallo
  2020-05-08 22:23       ` Nicolas Bértolo
  0 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-08 22:22 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel@gnu.org

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

> Hi Andrea,
>
> Thanks.
> I haven't signed the paperwork.
>
> Nicolas

Hi Nicolas,

I think it's a requirement if we want to have your patches merged in.
Would you be up for that?

Thanks

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-08 22:22     ` Andrea Corallo
@ 2020-05-08 22:23       ` Nicolas Bértolo
  2020-05-08 22:27         ` Andrea Corallo
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-08 22:23 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: emacs-devel@gnu.org

> I think it's a requirement if we want to have your patches merged in.
> Would you be up for that?

Sure!

Nicolas

El vie., 8 may. 2020 a las 19:22, Andrea Corallo (<akrl@sdf.org>) escribió:
>
> Nicolas Bértolo <nicolasbertolo@gmail.com> writes:
>
> > Hi Andrea,
> >
> > Thanks.
> > I haven't signed the paperwork.
> >
> > Nicolas
>
> Hi Nicolas,
>
> I think it's a requirement if we want to have your patches merged in.
> Would you be up for that?
>
> Thanks
>
>   Andrea
>
> --
> akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-08 22:23       ` Nicolas Bértolo
@ 2020-05-08 22:27         ` Andrea Corallo
  2020-05-08 23:18           ` Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-08 22:27 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel@gnu.org

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> I think it's a requirement if we want to have your patches merged in.
>> Would you be up for that?
>
> Sure!

This is great :)

I think Eli or someone else will send you very soon the stuff off-list
then.

Thanks

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-08 22:27         ` Andrea Corallo
@ 2020-05-08 23:18           ` Stefan Monnier
  0 siblings, 0 replies; 71+ messages in thread
From: Stefan Monnier @ 2020-05-08 23:18 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Nicolas Bértolo, emacs-devel@gnu.org

> I think Eli or someone else will send you very soon the stuff off-list
> then.

Sent off-list,


        Stefan




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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-08 19:55 [PATCH] [WIP] Port feature/native-comp to Windows Nicolas Bertolo
  2020-05-08 22:00 ` Andrea Corallo
@ 2020-05-09  6:07 ` Eli Zaretskii
  2020-05-09 15:28   ` Nicolas Bértolo
  2020-05-09 13:42 ` Andrea Corallo
  2 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-09  6:07 UTC (permalink / raw)
  To: Nicolas Bertolo; +Cc: emacs-devel

> Date: Fri, 8 May 2020 16:55:59 -0300
> From: Nicolas Bertolo <nicolasbertolo@gmail.com>
> 
> I have ported the feature/native-comp branch to Windows. I have tested my changes in Windows 10 x64 with
> Mingw64 GCC 10.0. Other architectures or compilers should work, but it may be necessary to adjust the
> code a little bit.

Great news, thank you for working on this.

> As I said above other architectures or compilers should work, but it may be necessary to change the code
> that generates calls to setjmp(), since there are many ways to do it. An option would be to copy what the
> setjmp.h header does, but I do not think it is a good idea. The proper fix would be to use autoconf to detect it
> somehow.

Could you elaborate why this is an issue, and what exactly are the
details that need to be adapted to a different setjmp implementation?

Also, did you try compiling the modified code with the 32-bit MinGW64
compiler?

> Another issue is that the “emacs_dir” environment variable needs to be set quite early in the initialization
> process. I do not know enough about the Emacs internals to make the proper changes for that, so I just
> added a dirty hack.

Why is this a problem for the native-compile version?

> There is a remaining issue involving the environment in which emacs runs. The libgccjit likes to run in a
> Mingw64 environment, so it can find the assembler, linker, etc.

What do you mean by Mingw64 environment?  Do you mean the MSYS
environment, i.e. the one that uses Bash and can run Unix shell
scripts?  If so, why is that needed?  Compiler passes are native
Windows programs, not MSYS programs.  Is this something special to how
libgccjit was ported to MinGW?

> This is means that Emacs needs to run in a pseudo-Unix
> environment. I don’t like this since this environment would be
> propagated to other processes launched by Emacs, and they may not
> like this.

This should be fixed, but I don't think I understand enough to propose
the way of fixing it.

> I have thought about a simple fix to this but I haven’t implemented it yet. The Emacs process that needs to
> run in a Mingw64 environment is actually the subprocess that performs the compilation, not the main
> process that runs the editor. So my idea is to run this subprocess through a small script that setups the
> environment that libgccjit expects without polluting the Emacs environment. 

I think describing the environment and the need for having it in this
case will be a significant first step towards resolving the problems.

> 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.

Is this specific to MS-Windows?  If so, what is the MS-Windows
specific aspects of native compilation that require this?

> 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.

Same questions here.

Thanks.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-08 19:55 [PATCH] [WIP] Port feature/native-comp to Windows Nicolas Bertolo
  2020-05-08 22:00 ` Andrea Corallo
  2020-05-09  6:07 ` Eli Zaretskii
@ 2020-05-09 13:42 ` Andrea Corallo
  2020-05-09 15:40   ` Nicolas Bértolo
  2 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-09 13:42 UTC (permalink / raw)
  To: Nicolas Bertolo; +Cc:  emacs-devel@gnu.org

Nicolas Bertolo <nicolasbertolo@gmail.com> writes:

> Hello emacs-devel
>
>  
>
> I have ported the feature/native-comp branch to Windows. I have
> tested my changes in Windows 10 x64 with Mingw64 GCC 10.0. Other
> architectures or compilers should work, but it may be necessary to
> adjust the code a little bit.

Yes, I guess we'll certanly have a run of tests on all configurations
that are now working.  These are parts of code quite sensitive and I
expect too some adjustment is likely to be required.

> I would like to thank the author of this blogpost which was very
> helpful for me: http://www.albertzhou.net/blog/2020/01/
> emacs-native-comp.html

I get a 404 now but IIRC he had to hack libgccjit too.  Did you had to
modify that too or just works OOTB in Mingw64?

> I have thought about a simple fix to this but I haven’t implemented
> it yet. The Emacs process that needs to run in a Mingw64 environment
> is actually the subprocess that performs the compilation, not the
> main process that runs the editor. So my idea is to run this
> subprocess through a small script that setups the environment that
> libgccjit expects without polluting the Emacs environment.

Mmmh the .eln do not link against any library so I guess if the shared
libraries produced from the Mingw64 env are usable outside it should
work (I'm totally ignorant on windows related subject).

Very cool

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09  6:07 ` Eli Zaretskii
@ 2020-05-09 15:28   ` Nicolas Bértolo
  2020-05-09 15:48     ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-09 15:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

>> As I said above other architectures or compilers should work, but it may be necessary to change the code
>> that generates calls to setjmp(), since there are many ways to do it. An option would be to copy what the
>> setjmp.h header does, but I do not think it is a good idea. The proper fix would be to use autoconf to detect it
>> somehow.

> Could you elaborate why this is an issue, and what exactly are the
> details that need to be adapted to a different setjmp implementation?

> Also, did you try compiling the modified code with the 32-bit MinGW64
> compiler?

I haven't tried to compile it with the 32-bit compiler.

There are many ways to call setjmp() in Windows. It depends on the architecture,
whether the Universal CRT is used, whether SEH is enabled, the compiler version,
etc.

#define setjmp(BUF) _setjmp3((BUF), NULL)
#define setjmp(BUF) __mingw_setjmp((BUF))
#define setjmp(BUF) _setjmp((BUF), __builtin_sponentry())
#define setjmp(BUF) _setjmp((BUF), mingw_getsp())
#define setjmp(BUF) _setjmp((BUF), __builtin_frame_address (0))
#define setjmp(BUF) _setjmp((BUF), NULL)

_setjmp may be a call to function or a macro:
#define _setjmp __intrinsic_setjmp
#define _setjmp __intrinsic_setjmpex
#define _setjmp _setjmpex

This is nicely abstracted through a macro in the setjmp.h header.
See https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-headers/crt/setjmp.h

In my machine (Windows 10, GCC 10.0 64 bits) the version that works is:
#define setjmp(BUF) _setjmp((BUF), __builtin_frame_address (0))
        where _setjmp is a call to the function.

libgccjit does not implement a preprocessor, so we need to create a
function call
to the proper function with the proper arguments for the system. To do this it
is necessary to know what function to call and what arguments to give it. An
option would be to copy the logic from the Mingw64 header. I don't like this for
two reasons:

- The header may change as Microsoft adds more stuff to its C runtime or
  something else is discovered through reverse engineering. This would lead to
  weird bugs when Emacs is compiled with a version of setjmp() but it generates
  calls to it in a different style.
- There may be licensing issues?

>> Another issue is that the “emacs_dir” environment variable needs to be set quite early in the initialization
>> process. I do not know enough about the Emacs internals to make the proper changes for that, so I just
>> added a dirty hack.

> Why is this a problem for the native-compile version?

The load_pdump() function calls it. I haven't found out why yet.

>> There is a remaining issue involving the environment in which emacs runs. The libgccjit likes to run in a
>> Mingw64 environment, so it can find the assembler, linker, etc.

> What do you mean by Mingw64 environment?  Do you mean the MSYS
> environment, i.e. the one that uses Bash and can run Unix shell
> scripts?  If so, why is that needed?  Compiler passes are native
> Windows programs, not MSYS programs.  Is this something special to how
> libgccjit was ported to MinGW?

> This should be fixed, but I don't think I understand enough to propose
> the way of fixing it.

> I think describing the environment and the need for having it in this
> case will be a significant first step towards resolving the problems.

I tried copying the assembler and linker (as.exe and ld.exe) into the folder
where emacs.exe lives. It is necessary to add that folder to PATH, that is the
first issue I found. Having done that was enough to make it work up to
the point where the
linker needs to find the Windows libraries.

If I remove the MSYS installation folder then it fails with these errors:

libgccjit.so: error: error invoking gcc driver

-or-

ld: cannot find dllcrt2.o: No such file or directory
ld: cannot find crtbegin.o: No such file or directory
ld: cannot find -lmingw32
ld: cannot find -lgcc_s
ld: cannot find -lgcc
ld: cannot find -lmoldname
ld: cannot find -lmingwex
ld: cannot find -lmsvcrt
ld: cannot find -lpthread
ld: cannot find -ladvapi32
ld: cannot find -lshell32
ld: cannot find -luser32
ld: cannot find -lkernel32
ld: cannot find -lmingw32
ld: cannot find -lgcc_s
ld: cannot find -lgcc
ld: cannot find -lmoldname
ld: cannot find -lmingwex
ld: cannot find -lmsvcrt
ld: cannot find crtend.o: No such file or directory

You are right when you say that they are native Windows programs. They don't
need a "pseudo-unix" environment like I said previously. But they need some
support files from the MSYS installation. I haven't figured out which ones yet.

>> Subject: [PATCH 4/6] Handle LISP_WORDS_ARE_POINTERS and
>>  CHECK_LISP_OBJECT_TYPE.

> Is this specific to MS-Windows?  If so, what is the MS-Windows
> specific aspects of native compilation that require this?

This is partially specific to Windows. I had trouble compiling it with the
`--enable-check-lisp-object-type` configure option, so I had to add support for
it.

One aspect that is specific to Windows is that sizeof(void*) != sizeof(long)
even if WIDE_EMACS_INT is not defined. The code assumed that sizeof(Lisp_Word)
== sizeof(long) if WIDE_EMACS_INT was not defined. I fixed this by adding many
types that represent the Lisp_* family and changing the code to use these
instead of long and long long.

>> Subject: [PATCH 5/6] Remove a layer of indirection for access to pure storage.

> Same questions here.

This one is definitely not Windows specific. There was a bug that caused
PURE_P() to be implemented incorrectly in the generated code.

It defined a variable `pure_reloc` of type `void**` that was supposed to store a
pointer to a pointer to pure storage. It was initialized to
`(EMACS_INT**)&pure`. This is expression does not take evaluates to a pointer of
type `EMACS_INT**` that points to the start of pure_storage. Since the generated
code derefereced this pointer, it was implementing PURE_P() as

bool PURE_P(void* ptr)
{
  return ((uintptr_t) ptr - (uintptr_t)pure[0]) <= PURESIZE;
}

In my tests `pure[0]` == 2.

This bug caused the native compiler to crash by calling pure_write_error(). It
is strange that this was not detected in GNU/Linux. I conjecture that all Lisp
objects are allocated in addresses higher than `pure` in GNU/Linux and that they
are higher than `pure[0]` too. I am not sure though.

This is not the case in Windows. It is possible to have Lisp objects that are
allocated below `pure`.

Nicolas

El sáb., 9 may. 2020 a las 3:08, Eli Zaretskii (<eliz@gnu.org>) escribió:
>
> > Date: Fri, 8 May 2020 16:55:59 -0300
> > From: Nicolas Bertolo <nicolasbertolo@gmail.com>
> >
> > I have ported the feature/native-comp branch to Windows. I have tested my changes in Windows 10 x64 with
> > Mingw64 GCC 10.0. Other architectures or compilers should work, but it may be necessary to adjust the
> > code a little bit.
>
> Great news, thank you for working on this.
>
> > As I said above other architectures or compilers should work, but it may be necessary to change the code
> > that generates calls to setjmp(), since there are many ways to do it. An option would be to copy what the
> > setjmp.h header does, but I do not think it is a good idea. The proper fix would be to use autoconf to detect it
> > somehow.
>
> Could you elaborate why this is an issue, and what exactly are the
> details that need to be adapted to a different setjmp implementation?
>
> Also, did you try compiling the modified code with the 32-bit MinGW64
> compiler?
>
> > Another issue is that the “emacs_dir” environment variable needs to be set quite early in the initialization
> > process. I do not know enough about the Emacs internals to make the proper changes for that, so I just
> > added a dirty hack.
>
> Why is this a problem for the native-compile version?
>
> > There is a remaining issue involving the environment in which emacs runs. The libgccjit likes to run in a
> > Mingw64 environment, so it can find the assembler, linker, etc.
>
> What do you mean by Mingw64 environment?  Do you mean the MSYS
> environment, i.e. the one that uses Bash and can run Unix shell
> scripts?  If so, why is that needed?  Compiler passes are native
> Windows programs, not MSYS programs.  Is this something special to how
> libgccjit was ported to MinGW?
>
> > This is means that Emacs needs to run in a pseudo-Unix
> > environment. I don’t like this since this environment would be
> > propagated to other processes launched by Emacs, and they may not
> > like this.
>
> This should be fixed, but I don't think I understand enough to propose
> the way of fixing it.
>
> > I have thought about a simple fix to this but I haven’t implemented it yet. The Emacs process that needs to
> > run in a Mingw64 environment is actually the subprocess that performs the compilation, not the main
> > process that runs the editor. So my idea is to run this subprocess through a small script that setups the
> > environment that libgccjit expects without polluting the Emacs environment.
>
> I think describing the environment and the need for having it in this
> case will be a significant first step towards resolving the problems.
>
> > 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.
>
> Is this specific to MS-Windows?  If so, what is the MS-Windows
> specific aspects of native compilation that require this?
>
> > 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.
>
> Same questions here.
>
> Thanks.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 13:42 ` Andrea Corallo
@ 2020-05-09 15:40   ` Nicolas Bértolo
  2020-05-09 15:55     ` Eli Zaretskii
                       ` (2 more replies)
  0 siblings, 3 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-09 15:40 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: emacs-devel@gnu.org

> I get a 404 now but IIRC he had to hack libgccjit too.  Did you had to
> modify that too or just works OOTB in Mingw64?

I did. I followed his procedures. I will write a document specifying what I had
to do in English.

> Mmmh the .eln do not link against any library so I guess if the shared
> libraries produced from the Mingw64 env are usable outside it should
> work (I'm totally ignorant on windows related subject).

They link against the crt (C runtime) and some core Windows libraries. As I
replied to Eli, the main issue is that the assembler and linker expect to find
some support files from the MSYS installation. The easiest way is to just run
Emacs from a MSYS shell. Another way would be to create a "stub installation" of
MSYS inside the emacs installation dir copying only the files that are
necessary.

The second way seems to be best, especially when you consider that shipping a
full MSYS installation alongside emacs is not a good idea.

PS: I don't understand why the freloc table is necessary. Is it impossible to
rely on the dynamic linker to solve that when calling dlopen()?

Nicolas



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 15:28   ` Nicolas Bértolo
@ 2020-05-09 15:48     ` Eli Zaretskii
  2020-05-09 17:09       ` Andrea Corallo
                         ` (2 more replies)
  0 siblings, 3 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-09 15:48 UTC (permalink / raw)
  To: Nicolas Bértolo, Andrea Corallo; +Cc: emacs-devel

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sat, 9 May 2020 12:28:29 -0300
> Cc: emacs-devel@gnu.org
> 
> > Also, did you try compiling the modified code with the 32-bit MinGW64
> > compiler?
> 
> I haven't tried to compile it with the 32-bit compiler.

This could have issues with setjmp, I think.

> There are many ways to call setjmp() in Windows. It depends on the architecture,
> whether the Universal CRT is used, whether SEH is enabled, the compiler version,
> etc.

Yes, I know.  But we need to support only the way we compile Emacs,
right?

> I tried copying the assembler and linker (as.exe and ld.exe) into the folder
> where emacs.exe lives. It is necessary to add that folder to PATH, that is the
> first issue I found.

Why do you need this?  The following command will show you the full
absolute file name of the assembler being used by GCC:

  gcc -print-prog-name=as

And similarly with ld.exe and any other program that GCC needs to
invoke as party of the compilation.  Can we use that instead of adding
directories to PATH?  In fact, I wonder how does the
native-compilation branch solve this for GNU/Linux systems, if not
like that?

> If I remove the MSYS installation folder then it fails with these errors:
> 
> libgccjit.so: error: error invoking gcc driver
> 
> -or-
> 
> ld: cannot find dllcrt2.o: No such file or directory
> ld: cannot find crtbegin.o: No such file or directory
> ld: cannot find -lmingw32
> ld: cannot find -lgcc_s
> ld: cannot find -lgcc
> ld: cannot find -lmoldname
> ld: cannot find -lmingwex
> ld: cannot find -lmsvcrt
> ld: cannot find -lpthread
> ld: cannot find -ladvapi32
> ld: cannot find -lshell32
> ld: cannot find -luser32
> ld: cannot find -lkernel32
> ld: cannot find -lmingw32
> ld: cannot find -lgcc_s
> ld: cannot find -lgcc
> ld: cannot find -lmoldname
> ld: cannot find -lmingwex
> ld: cannot find -lmsvcrt
> ld: cannot find crtend.o: No such file or directory

Sounds like something is broken in the MinGW libgccjit port?  It seems
not to pass the correct -L switch to the compiler, or something along
those lines?  Does libgccjit has the equivalent of the -v switch,
which would show the complete commands used to compile?

> You are right when you say that they are native Windows programs. They don't
> need a "pseudo-unix" environment like I said previously. But they need some
> support files from the MSYS installation. I haven't figured out which ones yet.

Well, please try to figure that out, and let us know if we can help
you in that task.  Once we understand the issues, we could think about
solving them.

> >> Subject: [PATCH 4/6] Handle LISP_WORDS_ARE_POINTERS and
> >>  CHECK_LISP_OBJECT_TYPE.
> 
> > Is this specific to MS-Windows?  If so, what is the MS-Windows
> > specific aspects of native compilation that require this?
> 
> This is partially specific to Windows. I had trouble compiling it with the
> `--enable-check-lisp-object-type` configure option, so I had to add support for
> it.

But --enable-check-lisp-object-type is not specific to Windows.
Andrea, is this configuration option supported by the branch on Posix
platforms?

> One aspect that is specific to Windows is that sizeof(void*) != sizeof(long)
> even if WIDE_EMACS_INT is not defined. The code assumed that sizeof(Lisp_Word)
> == sizeof(long) if WIDE_EMACS_INT was not defined. I fixed this by adding many
> types that represent the Lisp_* family and changing the code to use these
> instead of long and long long.

That's a general bug, and should be fixed on all platforms.
WIDE_EMACS_INT is supported on Posix platforms as well; I guess no one
has yet tried to make a 32-bit build of the branch --with-wide-int.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:27     ` Andrea Corallo
  2020-05-09 16:52     ` Andrea Corallo
  2 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-09 15:55 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sat, 9 May 2020 12:40:18 -0300
> Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
> 
> The easiest way is to just run Emacs from a MSYS shell.

IMO, we must not require this from Emacs users, most of them will not
have a full MSYS installation (and shouldn't be required to do that).
A MinGW GCC and Binutils installation should be enough.

> PS: I don't understand why the freloc table is necessary. Is it impossible to
> rely on the dynamic linker to solve that when calling dlopen()?

Can you tell the details?  Where does the freloc table come into play
in this context?



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 15:55     ` Eli Zaretskii
@ 2020-05-09 16:07       ` Nicolas Bértolo
  2020-05-09 16:15         ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-09 16:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

> IMO, we must not require this from Emacs users, most of them will not
> have a full MSYS installation (and shouldn't be required to do that).
> A MinGW GCC and Binutils installation should be enough.

Definitely. Ideally that would be shipped with Emacs just like 3rd party
libraries are.

> Can you tell the details?  Where does the freloc table come into play
> in this context?

It does not. It was a question to Andrea because I do not understand why we
can't use the OS dynamic linker. It is not related to the MSYS issue.
The freloc table stores a bunch of function pointers to internal Emacs
functions.
I think it would be cleaner to just declare each of those functions as an
"IMPORTED" function, which is equivalent to adding a line like this to
the generated code:

extern T a_function(T1, T2, ... Tn);

Then the dynamic linker will wire things together when loading the eln file.
Maybe I am missing something about how dynamic linking works.

Nicolas

El sáb., 9 may. 2020 a las 12:55, Eli Zaretskii (<eliz@gnu.org>) escribió:
>
> > From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> > Date: Sat, 9 May 2020 12:40:18 -0300
> > Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
> >
> > The easiest way is to just run Emacs from a MSYS shell.
>
> IMO, we must not require this from Emacs users, most of them will not
> have a full MSYS installation (and shouldn't be required to do that).
> A MinGW GCC and Binutils installation should be enough.
>
> > PS: I don't understand why the freloc table is necessary. Is it impossible to
> > rely on the dynamic linker to solve that when calling dlopen()?
>
> Can you tell the details?  Where does the freloc table come into play
> in this context?



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 16:07       ` Nicolas Bértolo
@ 2020-05-09 16:15         ` Eli Zaretskii
  0 siblings, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-09 16:15 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sat, 9 May 2020 13:07:44 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> > Can you tell the details?  Where does the freloc table come into play
> > in this context?
> 
> It does not. It was a question to Andrea because I do not understand why we
> can't use the OS dynamic linker. It is not related to the MSYS issue.
> The freloc table stores a bunch of function pointers to internal Emacs
> functions.
> I think it would be cleaner to just declare each of those functions as an
> "IMPORTED" function, which is equivalent to adding a line like this to
> the generated code:
> 
> extern T a_function(T1, T2, ... Tn);
> 
> Then the dynamic linker will wire things together when loading the eln file.
> Maybe I am missing something about how dynamic linking works.

There's an issue here due to the differences in how shared libraries
are loaded on Posix platforms and on MS-Windows.  Andrea probably
doesn't know how this is done on MS-Windows.

I'm sorry to ask questions about the native-comp branch, I don't
remember the details: how does it load the *.eln files?  Does it use
dlopen and dlsym?  If so, we should do the same on Windows, which
means functions from *.eln will be called via a function pointer and
not directly.

Calling functions from *.eln files directly is less desirable, as that
will require import libraries and other similar atrocities.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 15:40   ` Nicolas Bértolo
  2020-05-09 15:55     ` Eli Zaretskii
@ 2020-05-09 16:27     ` Andrea Corallo
  2020-05-09 16:33       ` Eli Zaretskii
  2020-05-09 16:52     ` Andrea Corallo
  2 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-09 16:27 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel@gnu.org

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

> PS: I don't understand why the freloc table is necessary. Is it impossible to
> rely on the dynamic linker to solve that when calling dlopen()?

The problem is that being Emacs an executable we do not export the
symbols to be used by the dynamic linker.

I think it should be possible (depending on the tool-chain) but I never
tried.  What I'm not sure of is how much is it portable given is not a
common scenario.  Because typically afterwards the answer comes up to be
"not enough" at the time I decided to handle it inside, the generated
code should be similar.

Also consider we need to have the list of all subr anyway for compiling.

Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 16:27     ` Andrea Corallo
@ 2020-05-09 16:33       ` Eli Zaretskii
  2020-05-09 16:46         ` Andrea Corallo
  0 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-09 16:33 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: nicolasbertolo, emacs-devel

> From: Andrea Corallo <akrl@sdf.org>
> Date: Sat, 09 May 2020 16:27:18 +0000
> Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
> 
> Nicolas Bértolo <nicolasbertolo@gmail.com> writes:
> 
> > PS: I don't understand why the freloc table is necessary. Is it impossible to
> > rely on the dynamic linker to solve that when calling dlopen()?
> 
> The problem is that being Emacs an executable we do not export the
> symbols to be used by the dynamic linker.

You mean, the symbols of primitives that compiled Elisp code calls?

> I think it should be possible (depending on the tool-chain) but I never
> tried.  What I'm not sure of is how much is it portable given is not a
> common scenario.  Because typically afterwards the answer comes up to be
> "not enough" at the time I decided to handle it inside, the generated
> code should be similar.

But that is even less portable, isn't it?  Or am I missing something?



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 16:33       ` Eli Zaretskii
@ 2020-05-09 16:46         ` Andrea Corallo
  0 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-09 16:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: nicolasbertolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrea Corallo <akrl@sdf.org>
>> Date: Sat, 09 May 2020 16:27:18 +0000
>> Cc: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
>> 
>> Nicolas Bértolo <nicolasbertolo@gmail.com> writes:
>> 
>> > PS: I don't understand why the freloc table is necessary. Is it impossible to
>> > rely on the dynamic linker to solve that when calling dlopen()?
>> 
>> The problem is that being Emacs an executable we do not export the
>> symbols to be used by the dynamic linker.
>
> You mean, the symbols of primitives that compiled Elisp code calls?

Yes

>> I think it should be possible (depending on the tool-chain) but I never
>> tried.  What I'm not sure of is how much is it portable given is not a
>> common scenario.  Because typically afterwards the answer comes up to be
>> "not enough" at the time I decided to handle it inside, the generated
>> code should be similar.
>
> But that is even less portable, isn't it?  Or am I missing something?

No should be portable, the mechanism is very simple, we have just some
memory in the .eln (static variables) that we fill with the right
pointers during load.

Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-09 15:40   ` Nicolas Bértolo
  2020-05-09 15:55     ` Eli Zaretskii
  2020-05-09 16:27     ` Andrea Corallo
@ 2020-05-09 16:52     ` Andrea Corallo
  2 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-09 16:52 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel@gnu.org

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> I get a 404 now but IIRC he had to hack libgccjit too.  Did you had to
>> modify that too or just works OOTB in Mingw64?
>
> I did. I followed his procedures. I will write a document specifying what I had
> to do in English.

Given you are assigning the copyright I think you should consider
assigning it for all projects including GCC, so you could upstream the
windows support for libgccjit too if you like.

Probably is the default but I don't remember.

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:20       ` Andrea Corallo
  2 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-09 17:09 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Nicolas Bértolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> But --enable-check-lisp-object-type is not specific to Windows.
> Andrea, is this configuration option supported by the branch on Posix
> platforms?

Yes, but I do not routinely build (especially all targets) with this
flag.  I see now GNU/Linux X86_64 is broken with that but is nothing
serious I'll fix it later.  I guess was a while since I verified it.

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:13         ` Andrea Corallo
  2020-05-10 17:20       ` Andrea Corallo
  2 siblings, 2 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-10 16:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

[-- Attachment #1: Type: text/plain, Size: 3358 bytes --]

> This could have issues with setjmp, I think.

Exactly.

>> There are many ways to call setjmp() in Windows. It depends on the architecture,
>> whether the Universal CRT is used, whether SEH is enabled, the compiler version,
>> etc.

> Yes, I know.  But we need to support only the way we compile Emacs,
> right?

Yes, but how do we get that information at build time? An automatic solution
would be to call `gcc -E` with something like this:

#include <setjmp.h>

jmp_buf buf;

void func()
{
  setjmp(buf);
}

And then parse the results to see what the setjmp() gets translated into by the
preprocessor. It is a lot of work, that why I suggested doing it with autoconf
somehow.

> And similarly with ld.exe and any other program that GCC needs to
> invoke as party of the compilation.  Can we use that instead of adding
> directories to PATH?  In fact, I wonder how does the
> native-compilation branch solve this for GNU/Linux systems, if not
> like that?

gccjit lets us add options to the command line it feeds its internal copy of
GCC. The option "-B path" can be used to define the path where a gcc
installation lives.

In GNU/Linux the branch relies on the gcc installation being in the standard
path. That is: libgccjit uses the same logic as gcc to find its binaries
and support libraries (this is why the "-B" switch works).

> Sounds like something is broken in the MinGW libgccjit port?  It seems
> not to pass the correct -L switch to the compiler, or something along
> those lines?  Does libgccjit has the equivalent of the -v switch,
> which would show the complete commands used to compile?

It can be fixed with the "-B" switch.

> You are right when you say that they are native Windows programs. They don't
> need a "pseudo-unix" environment like I said previously. But they need some
> support files from the MSYS installation. I haven't figured out which ones yet.

> Well, please try to figure that out, and let us know if we can help
> you in that task.  Once we understand the issues, we could think about
> solving them.

I think I found a solution. We can setup a "stub gcc installation" in the
directory where Emacs is installed. It should be like this:

configure --prefix:
- bin/
  - emacs.exe
  - etc
- lib/gcc/x86_64-w64-mingw32/10.0.0:
  - as.exe
  - collect2.exe
  - ld.exe
  - crtbegin.o
  - crtend.o
  - dllcrt2.o
  - libgcc.a
  - libkernel32.a
  - libmingw32.a
  - libmingwex.a
  - libmsvcrt.a

The actual name of the directories could be obtained through autoconf and the
files can be copied from the GCC used to build Emacs.

This is the minimal set of files required to build an eln file. They are
necessary to initialize the CRT in the DLL. Given that the generated code does
not use the CRT, I think we can further reduce the set of libraries used. This
would require adding a function called `DllMainCRTStartup` to the generated
code. It would do nothing, instead of setting up the CRT.

There is an issue with this approach: this function would need to be generated
with the __stdcall calling convention and there is no way in libgccjit to
specify that. It could be solved using a small object file compiled during the
Emacs build process and then put in the "stub GCC installation".

What do you think?

The attached patch sets up libgccjit to find libraries and binaries in the "stub
GCC installation".

Nicolas

[-- Attachment #2: 0007-Set-the-libraries-linked-against-native-lisp-modules.patch --]
[-- Type: application/octet-stream, Size: 1663 bytes --]

From 1b42b02287aecc9d966ca6579cd21c9e2940f284 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Sun, 10 May 2020 12:54:40 -0300
Subject: [PATCH] Set the libraries linked against native lisp modules in
 Windows.

* src/comp.c (comp--compile-ctxt-to-file): Add the following linker
options: -nodefaultlibs -lmingwex - lmingw32 -lkernel32 -lmsvcrt
-lgcc. Tell libgccjit to look for the GCC binaries and the previous
libraries in the directory invocation_directory/../lib/gcc. This is
does not affect to build process.
---
 src/comp.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/comp.c b/src/comp.c
index 57bbda2c4e..dce95ade5d 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -3545,6 +3545,20 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
   if (COMP_DEBUG > 2)
     gcc_jit_context_dump_reproducer_to_file (comp.ctxt, "comp_reproducer.c");
 
+#ifdef _WIN32
+  gcc_jit_context_add_driver_option (comp.ctxt, "-nodefaultlibs");
+
+  AUTO_STRING (format_str, "-B%s/../lib/gcc");
+  Lisp_Object arg = CALLN(Fformat, format_str, Vinvocation_directory);
+  gcc_jit_context_add_driver_option (comp.ctxt, SSDATA(arg));
+
+  gcc_jit_context_add_driver_option (comp.ctxt, "-lmingwex");
+  gcc_jit_context_add_driver_option (comp.ctxt, "-lmingw32");
+  gcc_jit_context_add_driver_option (comp.ctxt, "-lkernel32");
+  gcc_jit_context_add_driver_option (comp.ctxt, "-lmsvcrt");
+  gcc_jit_context_add_driver_option (comp.ctxt, "-lgcc");
+#endif
+
   AUTO_STRING (dot_so, NATIVE_ELISP_SUFFIX);
 
   Lisp_Object out_file = CALLN (Fconcat, base_name, dot_so);
-- 
2.25.1.windows.1


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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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 17:13         ` Andrea Corallo
  1 sibling, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-10 17:08 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sun, 10 May 2020 13:36:18 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> >> There are many ways to call setjmp() in Windows. It depends on the architecture,
> >> whether the Universal CRT is used, whether SEH is enabled, the compiler version,
> >> etc.
> 
> > Yes, I know.  But we need to support only the way we compile Emacs,
> > right?
> 
> Yes, but how do we get that information at build time?

What information do we need, exactly?

> And then parse the results to see what the setjmp() gets translated into by the
> preprocessor. It is a lot of work, that why I suggested doing it with autoconf
> somehow.

If you could explain in more detail what information is needed and how
it is used for compiling to native code, maybe I could think of a
reasonable solution.

> > And similarly with ld.exe and any other program that GCC needs to
> > invoke as party of the compilation.  Can we use that instead of adding
> > directories to PATH?  In fact, I wonder how does the
> > native-compilation branch solve this for GNU/Linux systems, if not
> > like that?
> 
> gccjit lets us add options to the command line it feeds its internal copy of
> GCC. The option "-B path" can be used to define the path where a gcc
> installation lives.

What is the definition of " where the gcc installation lives"?  What
files does libgccjit need from that place, and how does it look for
those files?

IIUC what is needed, it should be relatively easy to glean this
information from the output of "gcc -print-file-name=" and its ilk.

> In GNU/Linux the branch relies on the gcc installation being in the standard
> path. That is: libgccjit uses the same logic as gcc to find its binaries
> and support libraries (this is why the "-B" switch works).

Using the above-mentioned -print-* options to GCC should accomplish
the same tasks, because they ask GCC to reveal the places where it
finds its auxiliary binaries and support libraries.  Isn't it enough
to find out the absolute file names of each such file/program, and
tell libgccjit to use that absolute file name, instead of using -B?

We could also use -B, it is not much more complex, it just needs some
manipulation with file names returned by the various -print-* options
of GCC to find their common parent directory (which is what I presume
is meant by "where the GCC installation lives").

> I think I found a solution. We can setup a "stub gcc installation" in the
> directory where Emacs is installed. It should be like this:
> 
> configure --prefix:
> - bin/
>   - emacs.exe
>   - etc
> - lib/gcc/x86_64-w64-mingw32/10.0.0:
>   - as.exe
>   - collect2.exe
>   - ld.exe
>   - crtbegin.o
>   - crtend.o
>   - dllcrt2.o
>   - libgcc.a
>   - libkernel32.a
>   - libmingw32.a
>   - libmingwex.a
>   - libmsvcrt.a

I'd like to avoid that: it's a nuisance to have to copy files that
way, and users could legitimately have more than one GCC version
installed and available at the same time.

I think it is much better to figure out which directory to pass in the
"-B" option, or use absolute file names which we receive from GCC.
See the node "Developer Options" in the GCC manual, it describes the
various -print-* command-line options to GCC which can be used for
this purpose.  Can we use these to obtain the same information?  For
example, this command:

  gcc -print-file-name=libmingwex.a

will display the absolute file name of that library in each GCC
installation.

> The actual name of the directories could be obtained through autoconf and the
> files can be copied from the GCC used to build Emacs.

That assumes that Emacs is configured and built on the same system
where it is used.  That assumption is mostly false for Windows, where
many users simply download and install precompiled binaries, or build
on one system and then use on several different ones.  We should try
to find a way of getting this information at run time, not at
configure time.  And it shouldn't be hard: we can use at run time the
same GCC options as the configure script would do.  This should be
done once, and the result stored in some FOO-directory variable for
use when Lisp should be compiled.

> This is the minimal set of files required to build an eln file. They are
> necessary to initialize the CRT in the DLL. Given that the generated code does
> not use the CRT, I think we can further reduce the set of libraries used. This
> would require adding a function called `DllMainCRTStartup` to the generated
> code. It would do nothing, instead of setting up the CRT.
> 
> There is an issue with this approach: this function would need to be generated
> with the __stdcall calling convention and there is no way in libgccjit to
> specify that. It could be solved using a small object file compiled during the
> Emacs build process and then put in the "stub GCC installation".
> 
> What do you think?

The last bit sounds fine, but I'd like to avoid the stub GCC thingy.

I also think that making the *.eln files depend on fewer DLLs is an
optimization that can wait.  I suggest first to solve the problem with
discovering where GCC is installed so that the compilation could use
the correct file names, without requiring copying GCC files into a
stub installation.

> +#ifdef _WIN32

We use "#ifdef WINDOWSNT" in Emacs, not _WIN32.  But that's a minor
nit at this stage.

Thanks.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 16:36       ` Nicolas Bértolo
  2020-05-10 17:08         ` Eli Zaretskii
@ 2020-05-10 17:13         ` Andrea Corallo
  2020-05-10 17:15           ` Eli Zaretskii
  2020-05-10 18:05           ` Nicolas Bértolo
  1 sibling, 2 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 17:13 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

> What do you think?

If you use gcc_jit_context_add_driver_option you need to check for its
presence because I added it only for GCC9 and in not in all libgccjits.

You can do it with the macro
LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option or checking for
the ABI tag LIBGCCJIT_ABI_11.

We should do that at configure time tho.

That said I think a problem of this solution is that you limit the
compatibility to 1 year old GCCs that is quite strict.  I wrote all the
rest of the code trying not to use recent entry points on purpose.

It should be possible to use recent entry points but only with a
fallback.  This unless we see there's really no other option and we
accept the trade off.

For the rest I do not have Windows knowledge so to form an opinion I'd
need to understand a little more how it works.  In case you have some
reference to recommend please feel free to suggest.

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:05           ` Nicolas Bértolo
  1 sibling, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-10 17:15 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: nicolasbertolo, emacs-devel

> From: Andrea Corallo <akrl@sdf.org>
> Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org
> Date: Sun, 10 May 2020 10:13:08 -0700
> 
> For the rest I do not have Windows knowledge so to form an opinion I'd
> need to understand a little more how it works.

Can you describe how we find the GCC auxiliary programs and support
libraries needed for native compilation on GNU/Linux?



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:20       ` Andrea Corallo
  2 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 17:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Nicolas Bértolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:


> That's a general bug, and should be fixed on all platforms.
> WIDE_EMACS_INT is supported on Posix platforms as well; I guess no one
> has yet tried to make a 32-bit build of the branch --with-wide-int.

Uh I missed this sorry, I did it.  Should be working since a month
circa, I guess I'm a little behind schedule with the updates.

commit 49a3790e684213a6247f20e8029947f82fefdb5b
Author: Andrea Corallo <akrl@sdf.org>
Date:   Sat Apr 4 23:33:52 2020 +0100

    * src/comp.c: Add MSB TAG and wide int support.

commit 9bf9550836b526d1e72378b2a64385df8d47ac07
Author: Andrea Corallo <akrl@sdf.org>
Date:   Fri Apr 3 15:35:28 2020 +0100

    src/comp.c: Fix i386

    In i386 ABI parameter passing of structs (and unions) is done as
    pointer + size.  Surprisingly this is done *always* even if the
    structure is known to be word size.


--
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 17:08         ` Eli Zaretskii
@ 2020-05-10 17:50           ` Nicolas Bértolo
  2020-05-10 18:22             ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-10 17:50 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

> What information do we need, exactly?

We need:
- The name of the setjmp function.
- Whether it needs a second parameter, in that case:
   - It can be a gcc builtin, a function call or a NULL constant.
   - If it is a function call or a builtin it may need a parameter.
     This is a NULL constant in all cases I have seen.

> What is the definition of " where the gcc installation lives"?  What
> files does libgccjit need from that place, and how does it look for
> those files?

libgccjit implements generates an assembler file. This is done without any calls
to any external program. Then it calls a gcc entry point to finish the process.
This calls the same functions that the `gcc` program uses to identify where it
was installed. In particular, it uses constants defined at libgccjit build time
(the compiler version, the directories where it was installed, etc.). It uses
that information plus some environment variables: GCC_EXEC_PREFIX, LIBRARY_PATH,
maybe others, to find where the gcc support files are installed: the support
binaries, libgcc. This is what I meant by "where the gcc installation lives".

This logic runs inside the Emacs process that is performing the compilation
process, but it is the same code that would run in a `gcc -print-*` IIUC.

> IIUC what is needed, it should be relatively easy to glean this
> information from the output of "gcc -print-file-name=" and its ilk.

libgccjit runs the exact same code as gcc would. So this would not help.
Moreover, how would Emacs find gcc? We would need to add it to PATH.

> Using the above-mentioned -print-* options to GCC should accomplish
> the same tasks, because they ask GCC to reveal the places where it
> finds its auxiliary binaries and support libraries.  Isn't it enough
> to find out the absolute file names of each such file/program, and
> tell libgccjit to use that absolute file name, instead of using -B?

I do not think that is possible. libgccjit likes to find the files it needs as
if it was a gcc instance.

> I'd like to avoid that: it's a nuisance to have to copy files that
> way, and users could legitimately have more than one GCC version
> installed and available at the same time.

AFAIU, we need to use the same GCC version, that is what libgccjit looks for.
Also, the only things it needs are the assembler, linker and support libraries.

Using support libraries from different GCC versions may cause weird bugs. It is
not a good idea IMHO.

> That assumes that Emacs is configured and built on the same system
> where it is used.  That assumption is mostly false for Windows, where
> many users simply download and install precompiled binaries, or build
> on one system and then use on several different ones.  We should try
> to find a way of getting this information at run time, not at
> configure time.  And it shouldn't be hard: we can use at run time the
> same GCC options as the configure script would do.  This should be
> done once, and the result stored in some FOO-directory variable for
> use when Lisp should be compiled.

This would mean that users would have to download the appropriate GCC version if
they want to use native lisp compilation, ensure that Emacs finds it, etc. By
copying the support files into the installation dir we ensure that Emacs finds
the correct files and it works out of the box for users that download a ZIP
file.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 17:13         ` Andrea Corallo
  2020-05-10 17:15           ` Eli Zaretskii
@ 2020-05-10 18:05           ` Nicolas Bértolo
  2020-05-10 18:23             ` Andrea Corallo
  1 sibling, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-10 18:05 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Eli Zaretskii, emacs-devel

> It should be possible to use recent entry points but only with a
> fallback.  This unless we see there's really no other option and we
> accept the trade off.

We can fallback to the full set of default libs if we can not use the
"-nodefaultlibs" and "-l" options. But the key part of the patch is to set the
"-B" flag. It does not seem like we can use
gcc_jit_context_add_command_line_option instead of
gcc_jit_context_add_driver_option to pass "-B".

This means that we would need to use setenv() to define GCC_EXEC_PREFIX before
calling libgccjit, right?

> For the rest I do not have Windows knowledge so to form an opinion I'd
> need to understand a little more how it works.  In case you have some
> reference to recommend please feel free to suggest.

Regarding the CRT part this is what I read to understand why I needed to add so
many libraries:
https://support.microsoft.com/en-us/help/94248/how-to-use-the-c-run-time

Nicolas



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 17:15           ` Eli Zaretskii
@ 2020-05-10 18:14             ` Andrea Corallo
  2020-05-10 18:30               ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 18:14 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: nicolasbertolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrea Corallo <akrl@sdf.org>
>> Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org
>> Date: Sun, 10 May 2020 10:13:08 -0700
>> 
>> For the rest I do not have Windows knowledge so to form an opinion I'd
>> need to understand a little more how it works.
>
> Can you describe how we find the GCC auxiliary programs and support
> libraries needed for native compilation on GNU/Linux?

libgccjit when has produced the .s file has to invoke the "driver".
This is in GCC jargon the usual gcc executable that his the program that
is responsible for calling cc1 as and ld.

libgccjit can invoke the driver in two ways, one is using the embedded
one (default) or it can search for an external driver (the system gcc
executable).  AFAIU when the driver takes over the conventional logic to
identify support library is used by the linker.

Using gcc_jit_context_add_driver_option you can pass parameters to the
driver that will forward them to the linker.

Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 17:50           ` Nicolas Bértolo
@ 2020-05-10 18:22             ` Eli Zaretskii
  2020-05-10 19:02               ` Nicolas Bértolo
  0 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-10 18:22 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sun, 10 May 2020 14:50:52 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> > What information do we need, exactly?
> 
> We need:
> - The name of the setjmp function.
> - Whether it needs a second parameter, in that case:
>    - It can be a gcc builtin, a function call or a NULL constant.
>    - If it is a function call or a builtin it may need a parameter.
>      This is a NULL constant in all cases I have seen.

This is known in advance.  We already have that knowledge in Emacs,
see HAVE__SETJMP and HAVE_SIGSETJMP used in lisp.h.

I don't yet understand why we need the _name_ of the setjmp function.
How will this name be used?

> > What is the definition of " where the gcc installation lives"?  What
> > files does libgccjit need from that place, and how does it look for
> > those files?
> 
> libgccjit implements generates an assembler file. This is done without any calls
> to any external program. Then it calls a gcc entry point to finish the process.
> This calls the same functions that the `gcc` program uses to identify where it
> was installed. In particular, it uses constants defined at libgccjit build time
> (the compiler version, the directories where it was installed, etc.). It uses
> that information plus some environment variables: GCC_EXEC_PREFIX, LIBRARY_PATH,
> maybe others, to find where the gcc support files are installed: the support
> binaries, libgcc. This is what I meant by "where the gcc installation lives".
> 
> This logic runs inside the Emacs process that is performing the compilation
> process, but it is the same code that would run in a `gcc -print-*` IIUC.
> 
> > IIUC what is needed, it should be relatively easy to glean this
> > information from the output of "gcc -print-file-name=" and its ilk.
> 
> libgccjit runs the exact same code as gcc would. So this would not help.

Then why do we need to tell libgccjit where the GCC installation
lives?  AFAIU from what you are saying, libgccjit already knows that.
What am I missing?

> Moreover, how would Emacs find gcc? We would need to add it to PATH.

The gcc executable is always on PATH, only the auxiliary programs
(cc1.exe etc.) aren't.  Otherwise you couldn't compile programs in
arbitrary directories.

> > Using the above-mentioned -print-* options to GCC should accomplish
> > the same tasks, because they ask GCC to reveal the places where it
> > finds its auxiliary binaries and support libraries.  Isn't it enough
> > to find out the absolute file names of each such file/program, and
> > tell libgccjit to use that absolute file name, instead of using -B?
> 
> I do not think that is possible. libgccjit likes to find the files it needs as
> if it was a gcc instance.

Then I don't understand why it needs any help at all.  When I invoke
gcc to compile a program, I don't tell it anything about where the
installation lives, gcc finds that all by itself.  Why is libgccjit
different?

> > I'd like to avoid that: it's a nuisance to have to copy files that
> > way, and users could legitimately have more than one GCC version
> > installed and available at the same time.
> 
> AFAIU, we need to use the same GCC version, that is what libgccjit looks for.

Same GCC version as what other version? the one used to compile Emacs
itself, perhaps?

> Using support libraries from different GCC versions may cause weird bugs.

Then we are already in trouble, because libgcc comes with each GCC
version and is slightly different from other versions (although it's
supposed to be compatible), and libmingwex and libmingw32 come with
MinGW distribution which is independent of GCC -- users can upgrade
their MinGW installation at will.

I don't think using libraries from a different GCC version is going to
cause problems, assuming the newer library is binary-compatible to the
old one (if it isn't, the DLL will have a different name, like
libgcc_s_dw2-2.dll vs libgcc_s_dw2-1.dll).

> > That assumes that Emacs is configured and built on the same system
> > where it is used.  That assumption is mostly false for Windows, where
> > many users simply download and install precompiled binaries, or build
> > on one system and then use on several different ones.  We should try
> > to find a way of getting this information at run time, not at
> > configure time.  And it shouldn't be hard: we can use at run time the
> > same GCC options as the configure script would do.  This should be
> > done once, and the result stored in some FOO-directory variable for
> > use when Lisp should be compiled.
> 
> This would mean that users would have to download the appropriate GCC version if
> they want to use native lisp compilation

What is the definition of "the appropriate GCC version" in this
context?  E.g., does it have to be exactly the same version as the one
used to build Emacs itself?  Or does it mean something else?

> By copying the support files into the installation dir we ensure
> that Emacs finds the correct files and it works out of the box for
> users that download a ZIP file.

How will this work in practice?  Are you suggesting that we include
part of the GCC installation in the Emacs binary zip file?  If so, we
will have to provide also the humongous GCC source tarball on the same
site, to comply with the GPL.  That is doable, of course, but very
inconvenient.  We should try to find a better way.

But this is still too early, I think we first need to understand
exactly what files does libgccjit need to find during compilation and
how.  (Well, I guess _I_ need to understand that; apologies for not
being more familiar with these details of the native-comp branch, and
wasting your time on looking into this and describing the findings.
maybe someone else who knows more about this could chime in and make
the progress faster and less tedious.)



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 18:05           ` Nicolas Bértolo
@ 2020-05-10 18:23             ` Andrea Corallo
  0 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 18:23 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> It should be possible to use recent entry points but only with a
>> fallback.  This unless we see there's really no other option and we
>> accept the trade off.
>
> We can fallback to the full set of default libs if we can not use the
> "-nodefaultlibs" and "-l" options. But the key part of the patch is to set the
> "-B" flag. It does not seem like we can use
> gcc_jit_context_add_command_line_option instead of
> gcc_jit_context_add_driver_option to pass "-B".

Yep, AFAIR gcc_jit_context_add_command_line_option is for the compiler
only (that's the reason I added gcc_jit_context_add_driver_option).

> This means that we would need to use setenv() to define GCC_EXEC_PREFIX before
> calling libgccjit, right?

Sounds like an options for this specific problem but I still have to
understand the whole.

>> For the rest I do not have Windows knowledge so to form an opinion I'd
>> need to understand a little more how it works.  In case you have some
>> reference to recommend please feel free to suggest.
>
> Regarding the CRT part this is what I read to understand why I needed to add so
> many libraries:
> https://support.microsoft.com/en-us/help/94248/how-to-use-the-c-run-time

Thanks

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 18:14             ` Andrea Corallo
@ 2020-05-10 18:30               ` Eli Zaretskii
  2020-05-10 18:54                 ` Andrea Corallo
  0 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-10 18:30 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: nicolasbertolo, emacs-devel

> From: Andrea Corallo <akrl@sdf.org>
> Cc: nicolasbertolo@gmail.com, emacs-devel@gnu.org
> Date: Sun, 10 May 2020 11:14:11 -0700
> 
> libgccjit when has produced the .s file has to invoke the "driver".
> This is in GCC jargon the usual gcc executable that his the program that
> is responsible for calling cc1 as and ld.
> 
> libgccjit can invoke the driver in two ways, one is using the embedded
> one (default) or it can search for an external driver (the system gcc
> executable).  AFAIU when the driver takes over the conventional logic to
> identify support library is used by the linker.

And on GNU/Linux we use the default, i.e. the embedded driver?

Does the embedded driver know where GCC is installed on the system
where Emacs runs, and where to find the support libraries?  If not,
why not?  After all, I presume libgccjit is just one component of the
GCC installation, so it shares the environment and the search lists
with the locally installed gcc driver, no?

If for Windows we decide to use the external driver, i.e. the gcc.exe
installed on the end-user's system, does it solve all the problems
with finding the auxiliary programs and support libraries?  If so, I
think this way is better, at least on MS-Windows (if not on all
systems).

> Using gcc_jit_context_add_driver_option you can pass parameters to the
> driver that will forward them to the linker.

Sure, but it sounds like knowing what those parameters are is not a
simple job.  Although I still don't seem to understand why, silly me.

Thanks.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 18:30               ` Eli Zaretskii
@ 2020-05-10 18:54                 ` Andrea Corallo
  2020-05-10 19:02                   ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 18:54 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: nicolasbertolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrea Corallo <akrl@sdf.org>
>> Cc: nicolasbertolo@gmail.com, emacs-devel@gnu.org
>> Date: Sun, 10 May 2020 11:14:11 -0700
>> 
>> libgccjit when has produced the .s file has to invoke the "driver".
>> This is in GCC jargon the usual gcc executable that his the program that
>> is responsible for calling cc1 as and ld.
>> 
>> libgccjit can invoke the driver in two ways, one is using the embedded
>> one (default) or it can search for an external driver (the system gcc
>> executable).  AFAIU when the driver takes over the conventional logic to
>> identify support library is used by the linker.
>
> And on GNU/Linux we use the default, i.e. the embedded driver?

Yes.

> Does the embedded driver know where GCC is installed on the system
> where Emacs runs, and where to find the support libraries?

The embedde driver is just some code some code in libgccjit that act as
the original gcc executable so has not need to be located.  For the
support libraries is the linker that does that conventionally.

You can even log the ld invocation done by the embedded drive is nothing
magical.  Finally the linker is just the system one.

> If not,
> why not?  After all, I presume libgccjit is just one component of the
> GCC installation, so it shares the environment and the search lists
> with the locally installed gcc driver, no?

That is my understanding.

> If for Windows we decide to use the external driver, i.e. the gcc.exe
> installed on the end-user's system, does it solve all the problems
> with finding the auxiliary programs and support libraries?  If so, I
> think this way is better, at least on MS-Windows (if not on all
> systems).
>
>> Using gcc_jit_context_add_driver_option you can pass parameters to the
>> driver that will forward them to the linker.
>
> Sure, but it sounds like knowing what those parameters are is not a
> simple job.  Although I still don't seem to understand why, silly me.

Me too I do not understand why ld is not doing the expected job, I guess
I've to re-read the thread.

Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:39                 ` Andrea Corallo
  0 siblings, 2 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-10 19:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

> This is known in advance.  We already have that knowledge in Emacs,
> see HAVE__SETJMP and HAVE_SIGSETJMP used in lisp.h.

> I don't yet understand why we need the _name_ of the setjmp function.
> How will this name be used?

I think it is a good idea to show how the information is used:
This is the function that generates a function call to `setjmp`.

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
}

In Windows we issue a call to _setjmp with a jmp_buf as first parameter and the
result of calling __builtin_frame_address(0) as second argument.

This handles the case where setjmp.h defines setjmp like this:
#define setjmp(BUF) _setjmp((BUF), __builtin_frame_address (0))

The rest of the cases need to be added by hand to this function or we need to
find a way to get autoconf to generate this function.

We need the name of the setjmp function because it is used in two places:
- The freloc table needs to store a pointer to it, and to do it it needs the
name the macro is hiding.
- The emit_call function maps strings to fields in the freloc table.

> Then why do we need to tell libgccjit where the GCC installation
> lives?  AFAIU from what you are saying, libgccjit already knows that.
> What am I missing?

Because libgccjit tries to find the GCC installation in the path it was given
when `configure` was called. I thinking about redistributing a "stub GCC
installation" alongside Emacs.

> The gcc executable is always on PATH, only the auxiliary programs
> (cc1.exe etc.) aren't.  Otherwise you couldn't compile programs in
> arbitrary directories.

What about users that don't have `gcc` in PATH? We are back to the solution that
adds it to PATH before creating the compilation process.

> Then I don't understand why it needs any help at all.  When I invoke
> gcc to compile a program, I don't tell it anything about where the
> installation lives, gcc finds that all by itself.  Why is libgccjit
> different?

Because I was thinking about the case in which GCC is not in PATH because the
user does not have a Mingw installation. In that case we need to help libgccjit
find the stub GCC installtion.

> Same GCC version as what other version? the one used to compile Emacs
itself, perhaps?

> What is the definition of "the appropriate GCC version" in this
> context?  E.g., does it have to be exactly the same version as the one
> used to build Emacs itself?  Or does it mean something else?

The GCC that comes from the source tree that libgccjit was built from.

Lets say Emacs was built with libgccjit 9.2 and the user has GCC 10.0.0
installed: it would be a very bad idea to use the local installation, AFAIU.
In fact, libgccjit will not even try and it'll fail.
Andrea knows the internals of libgccjit way better than me: I am I right?

> How will this work in practice?  Are you suggesting that we include
> part of the GCC installation in the Emacs binary zip file?  If so, we
> will have to provide also the humongous GCC source tarball on the same
> site, to comply with the GPL.  That is doable, of course, but very
> inconvenient.  We should try to find a better way.

This is what I was proposing indeed. The strict version requirement seems to get
in the way of using the system GCC (If there is one. I hadn't thought about the
GPL requirement.

El dom., 10 may. 2020 a las 15:22, Eli Zaretskii (<eliz@gnu.org>) escribió:
>
> > From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> > Date: Sun, 10 May 2020 14:50:52 -0300
> > Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> >
> > > What information do we need, exactly?
> >
> > We need:
> > - The name of the setjmp function.
> > - Whether it needs a second parameter, in that case:
> >    - It can be a gcc builtin, a function call or a NULL constant.
> >    - If it is a function call or a builtin it may need a parameter.
> >      This is a NULL constant in all cases I have seen.
>
> This is known in advance.  We already have that knowledge in Emacs,
> see HAVE__SETJMP and HAVE_SIGSETJMP used in lisp.h.
>
> I don't yet understand why we need the _name_ of the setjmp function.
> How will this name be used?
>
> > > What is the definition of " where the gcc installation lives"?  What
> > > files does libgccjit need from that place, and how does it look for
> > > those files?
> >
> > libgccjit implements generates an assembler file. This is done without any calls
> > to any external program. Then it calls a gcc entry point to finish the process.
> > This calls the same functions that the `gcc` program uses to identify where it
> > was installed. In particular, it uses constants defined at libgccjit build time
> > (the compiler version, the directories where it was installed, etc.). It uses
> > that information plus some environment variables: GCC_EXEC_PREFIX, LIBRARY_PATH,
> > maybe others, to find where the gcc support files are installed: the support
> > binaries, libgcc. This is what I meant by "where the gcc installation lives".
> >
> > This logic runs inside the Emacs process that is performing the compilation
> > process, but it is the same code that would run in a `gcc -print-*` IIUC.
> >
> > > IIUC what is needed, it should be relatively easy to glean this
> > > information from the output of "gcc -print-file-name=" and its ilk.
> >
> > libgccjit runs the exact same code as gcc would. So this would not help.
>
> Then why do we need to tell libgccjit where the GCC installation
> lives?  AFAIU from what you are saying, libgccjit already knows that.
> What am I missing?
>
> > Moreover, how would Emacs find gcc? We would need to add it to PATH.
>
> The gcc executable is always on PATH, only the auxiliary programs
> (cc1.exe etc.) aren't.  Otherwise you couldn't compile programs in
> arbitrary directories.
>
> > > Using the above-mentioned -print-* options to GCC should accomplish
> > > the same tasks, because they ask GCC to reveal the places where it
> > > finds its auxiliary binaries and support libraries.  Isn't it enough
> > > to find out the absolute file names of each such file/program, and
> > > tell libgccjit to use that absolute file name, instead of using -B?
> >
> > I do not think that is possible. libgccjit likes to find the files it needs as
> > if it was a gcc instance.
>
> Then I don't understand why it needs any help at all.  When I invoke
> gcc to compile a program, I don't tell it anything about where the
> installation lives, gcc finds that all by itself.  Why is libgccjit
> different?
>
> > > I'd like to avoid that: it's a nuisance to have to copy files that
> > > way, and users could legitimately have more than one GCC version
> > > installed and available at the same time.
> >
> > AFAIU, we need to use the same GCC version, that is what libgccjit looks for.
>
> Same GCC version as what other version? the one used to compile Emacs
> itself, perhaps?
>
> > Using support libraries from different GCC versions may cause weird bugs.
>
> Then we are already in trouble, because libgcc comes with each GCC
> version and is slightly different from other versions (although it's
> supposed to be compatible), and libmingwex and libmingw32 come with
> MinGW distribution which is independent of GCC -- users can upgrade
> their MinGW installation at will.
>
> I don't think using libraries from a different GCC version is going to
> cause problems, assuming the newer library is binary-compatible to the
> old one (if it isn't, the DLL will have a different name, like
> libgcc_s_dw2-2.dll vs libgcc_s_dw2-1.dll).
>
> > > That assumes that Emacs is configured and built on the same system
> > > where it is used.  That assumption is mostly false for Windows, where
> > > many users simply download and install precompiled binaries, or build
> > > on one system and then use on several different ones.  We should try
> > > to find a way of getting this information at run time, not at
> > > configure time.  And it shouldn't be hard: we can use at run time the
> > > same GCC options as the configure script would do.  This should be
> > > done once, and the result stored in some FOO-directory variable for
> > > use when Lisp should be compiled.
> >
> > This would mean that users would have to download the appropriate GCC version if
> > they want to use native lisp compilation
>
> What is the definition of "the appropriate GCC version" in this
> context?  E.g., does it have to be exactly the same version as the one
> used to build Emacs itself?  Or does it mean something else?
>
> > By copying the support files into the installation dir we ensure
> > that Emacs finds the correct files and it works out of the box for
> > users that download a ZIP file.
>
> How will this work in practice?  Are you suggesting that we include
> part of the GCC installation in the Emacs binary zip file?  If so, we
> will have to provide also the humongous GCC source tarball on the same
> site, to comply with the GPL.  That is doable, of course, but very
> inconvenient.  We should try to find a better way.
>
> But this is still too early, I think we first need to understand
> exactly what files does libgccjit need to find during compilation and
> how.  (Well, I guess _I_ need to understand that; apologies for not
> being more familiar with these details of the native-comp branch, and
> wasting your time on looking into this and describing the findings.
> maybe someone else who knows more about this could chime in and make
> the progress faster and less tedious.)



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 18:54                 ` Andrea Corallo
@ 2020-05-10 19:02                   ` Eli Zaretskii
  2020-05-10 19:07                     ` Nicolas Bértolo
                                       ` (2 more replies)
  0 siblings, 3 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-10 19:02 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: nicolasbertolo, emacs-devel

> From: Andrea Corallo <akrl@sdf.org>
> Cc: nicolasbertolo@gmail.com, emacs-devel@gnu.org
> Date: Sun, 10 May 2020 11:54:05 -0700
> 
> The embedde driver is just some code some code in libgccjit that act as
> the original gcc executable so has not need to be located.  For the
> support libraries is the linker that does that conventionally.
> 
> You can even log the ld invocation done by the embedded drive is nothing
> magical.  Finally the linker is just the system one.

But the linker doesn't usually know where to find the libraries,
because the libraries are part of the GCC installation, not of the
Binutils installation.  That's why gcc always tells the linker where
to find the libraries, via the -L switch.  Try compiling a trivial
program with "gcc -v", and you will see how the linker is invoked: gcc
spoon-feeds it with all the directories on the library search path
(you can see those directories if you invoke "gcc -print-search-paths").

> > Sure, but it sounds like knowing what those parameters are is not a
> > simple job.  Although I still don't seem to understand why, silly me.
> 
> Me too I do not understand why ld is not doing the expected job

See above.  What _I_ don't understand is why cannot libgccjit feed the
linker with the same -L switches that gcc does.

Someone, perhaps you, mentioned -nostdlib option to gcc, which might
be the answer to this question, but then why use -nostdlib at all?



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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
  2 siblings, 0 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-10 19:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

> Someone, perhaps you, mentioned -nostdlib option to gcc, which might
> be the answer to this question, but then why use -nostdlib at all?

I tried this. It creates the libraries fine, but LoadLibrary() fails
to load the library
because the entry point is not defined. This is why we need to include the CRT,
and all its dependencies.

The issue is actually finding what as.exe collect2.exe and ld.exe to
call. See my other reply to Eli.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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
  2 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 19:14 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: nicolasbertolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrea Corallo <akrl@sdf.org>
>> Cc: nicolasbertolo@gmail.com, emacs-devel@gnu.org
>> Date: Sun, 10 May 2020 11:54:05 -0700
>>
>> The embedde driver is just some code some code in libgccjit that act as
>> the original gcc executable so has not need to be located.  For the
>> support libraries is the linker that does that conventionally.
>>
>> You can even log the ld invocation done by the embedded drive is nothing
>> magical.  Finally the linker is just the system one.
>
> But the linker doesn't usually know where to find the libraries,
> because the libraries are part of the GCC installation, not of the
> Binutils installation.  That's why gcc always tells the linker where
> to find the libraries, via the -L switch.  Try compiling a trivial
> program with "gcc -v", and you will see how the linker is invoked: gcc
> spoon-feeds it with all the directories on the library search path
> (you can see those directories if you invoke "gcc -print-search-paths").

Yeah sure, I clearly see your point now.

>> > Sure, but it sounds like knowing what those parameters are is not a
>> > simple job.  Although I still don't seem to understand why, silly me.
>>
>> Me too I do not understand why ld is not doing the expected job
>
> See above.  What _I_ don't understand is why cannot libgccjit feed the
> linker with the same -L switches that gcc does.

Is it really this the problem or is Nicolas who wants to use two
different setups for some reason?  I guess he will explain shortly.

BTW this is what I log with my libgccjit for the driver options:

 JIT:       argv[0]: x86_64-pc-linux-gnu-gcc-10.0.1
 JIT:       argv[1]: -m64
 JIT:       argv[2]: -shared
 JIT:       argv[3]: /tmp/libgccjit-TO70rk/fake.s
 JIT:       argv[4]: -o
 JIT:       argv[5]: /tmp/libgccjit-TO70rk/fake.so
 JIT:       argv[6]: -fno-use-linker-plugin

> Someone, perhaps you, mentioned -nostdlib option to gcc,

Wasn't me :)

Andrea

--
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:47                   ` Andrea Corallo
  2020-05-10 19:39                 ` Andrea Corallo
  1 sibling, 2 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-10 19:16 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sun, 10 May 2020 16:02:11 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> > This is known in advance.  We already have that knowledge in Emacs,
> > see HAVE__SETJMP and HAVE_SIGSETJMP used in lisp.h.
> 
> > I don't yet understand why we need the _name_ of the setjmp function.
> > How will this name be used?
> 
> I think it is a good idea to show how the information is used:
> This is the function that generates a function call to `setjmp`.

Thanks, I will think about this.  But up front, we can simply use the
apriori knowledge about the way the setjmp macro is expanded in the
version used for building Emacs.  We could build in some defenses
against changes in that expansion, if that is a real danger, but
that's not urgent.

> > The gcc executable is always on PATH, only the auxiliary programs
> > (cc1.exe etc.) aren't.  Otherwise you couldn't compile programs in
> > arbitrary directories.
> 
> What about users that don't have `gcc` in PATH?

That'd mean the user's GCC installation is not workable.  I don't
think we need to consider this case, at least not seriously and not as
our first goal.

> > What is the definition of "the appropriate GCC version" in this
> > context?  E.g., does it have to be exactly the same version as the one
> > used to build Emacs itself?  Or does it mean something else?
> 
> The GCC that comes from the source tree that libgccjit was built from.
> 
> Lets say Emacs was built with libgccjit 9.2 and the user has GCC 10.0.0
> installed: it would be a very bad idea to use the local installation, AFAIU.
> In fact, libgccjit will not even try and it'll fail.

But that's a problem on any platform, not just on Windows, isn't it?
It would mean that when you upgrade GCC, you need to rebuild Emacs in
order to be able to continue natively-compiling Lisp files, even if
your Emacs version stays the same.  Is this reasonable?  What will
GNU/Linux users do that install binary distributions of Emacs -- will
they have to install a very particular version of GCC to be able to
compile to native code, and never upgrade it, except together with
upgrading Emacs?  Sounds very inconvenient to me.

I thought that we expect to use libgccjit that's part of the GCC
installation on the system where Emacs is used, i.e. that libgccjit
would be a shared library into which Emacs will call.  You seem to be
saying that libgccjit will come with Emacs (or be statically linked
into Emacs), and the end-user will have to have a GCC installation of
the same version from which libgccjit came on the system where Emacs
was built.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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
  2 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 19:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: nicolasbertolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrea Corallo <akrl@sdf.org>
>> Cc: nicolasbertolo@gmail.com, emacs-devel@gnu.org
>> Date: Sun, 10 May 2020 11:54:05 -0700
>>
>> The embedde driver is just some code some code in libgccjit that act as
>> the original gcc executable so has not need to be located.  For the
>> support libraries is the linker that does that conventionally.
>>
>> You can even log the ld invocation done by the embedded drive is nothing
>> magical.  Finally the linker is just the system one.
>
> But the linker doesn't usually know where to find the libraries,
> because the libraries are part of the GCC installation, not of the
> Binutils installation.  That's why gcc always tells the linker where
> to find the libraries, via the -L switch.  Try compiling a trivial
> program with "gcc -v", and you will see how the linker is invoked: gcc
> spoon-feeds it with all the directories on the library search path
> (you can see those directories if you invoke "gcc -print-search-paths").
>
>> > Sure, but it sounds like knowing what those parameters are is not a
>> > simple job.  Although I still don't seem to understand why, silly me.
>>
>> Me too I do not understand why ld is not doing the expected job
>
> See above.  What _I_ don't understand is why cannot libgccjit feed the
> linker with the same -L switches that gcc does.

To complete, I think it does: here the ouput of the libgccjit driver
running -v (this is a local build).

=============================

COLLECT_GCC=x86_64-pc-linux-gnu-gcc-10.0.1
COLLECT_LTO_WRAPPER=/home/akrl/libexec/gcc/x86_64-pc-linux-gnu/10.0.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --disable-bootstrap --enable-checking=release --enable-host-shared --prefix=/home/akrl --enable-languages=c,c++,jit
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.0.1 20200331 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-m64' '-shared' '-o' '/tmp/libgccjit-nQRJfi/fake.so' '-fno-use-linker-plugin' '-v' '-mtune=generic' '-march=x86-64'
 as -v --64 -o /tmp/ccG1nTa8.o /tmp/libgccjit-nQRJfi/fake.s
GNU assembler version 2.30 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.30
COMPILER_PATH=/home/akrl/libexec/gcc/x86_64-pc-linux-gnu/10.0.1/:/home/akrl/libexec/gcc/x86_64-pc-linux-gnu/10.0.1/:/home/akrl/libexec/gcc/x86_64-pc-linux-gnu/:/home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/:/home/akrl/lib/gcc/x86_64-pc-linux-gnu/
LIBRARY_PATH=/home/akrl/lib/../lib64/:/home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/:/home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../../../lib64/:/lib/x86_64-linux-gnu/:/lib/../lib64/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib64/:/home/akrl/lib/:./:/home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-m64' '-shared' '-o' '/tmp/libgccjit-nQRJfi/fake.so' '-fno-use-linker-plugin' '-v' '-mtune=generic' '-march=x86-64'
 /home/akrl/libexec/gcc/x86_64-pc-linux-gnu/10.0.1/collect2 --eh-frame-hdr -m elf_x86_64 -shared -o /tmp/libgccjit-nQRJfi/fake.so /usr/lib/x86_64-linux-gnu/crti.o /home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/crtbeginS.o -L/home/akrl/lib/../lib64 -L/home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1 -L/home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/home/akrl/lib -L. -L/home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../.. /tmp/ccG1nTa8.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /home/akrl/lib/gcc/x86_64-pc-linux-gnu/10.0.1/crtendS.o /usr/lib/x86_64-linux-gnu/crtn.o
COLLECT_GCC_OPTIONS='-m64' '-shared' '-o' '/tmp/libgccjit-nQRJfi/fake.so' '-fno-use-linker-plugin' '-v' '-mtune=generic' '-march=x86-64'



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 19:24                     ` Andrea Corallo
@ 2020-05-10 19:30                       ` Eli Zaretskii
  0 siblings, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-10 19:30 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: nicolasbertolo, emacs-devel

> From: Andrea Corallo <akrl@sdf.org>
> Cc: nicolasbertolo@gmail.com, emacs-devel@gnu.org
> Date: Sun, 10 May 2020 12:24:32 -0700
> 
> > See above.  What _I_ don't understand is why cannot libgccjit feed the
> > linker with the same -L switches that gcc does.
> 
> To complete, I think it does: here the ouput of the libgccjit driver
> running -v (this is a local build).

Right, as expected.  So now I don't understand why Nicolas was worried
about this bit.  Is it only because he thought libgccjit was from a
different GCC version/installation?



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 19:02               ` Nicolas Bértolo
  2020-05-10 19:16                 ` Eli Zaretskii
@ 2020-05-10 19:39                 ` Andrea Corallo
  1 sibling, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 19:39 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

> Lets say Emacs was built with libgccjit 9.2 and the user has GCC 10.0.0
> installed: it would be a very bad idea to use the local installation, AFAIU.
> In fact, libgccjit will not even try and it'll fail.
> Andrea knows the internals of libgccjit way better than me: I am I right?

If you compile Emacs with libgccjit9 and the upgrade to libgccjit10 is
no problem, the entry point are always additive by design:

"The libgccjit developers strive for ABI and API backward-compatibility:
programs built against libgccjit.so stand a good chance of running
without recompilation against newer versions of libgccjit.so, and ought
to recompile without modification against newer versions of
libgccjit.h."

https://gcc.gnu.org/onlinedocs/jit/topics/compatibility.html

As long as the dynamic linker does not complain at startup (and it we'll
not give the above) Emacs will start and work.

If then we are trying to redistribute libgccjit bundled with Emacs
that's another issue, and I agree with Eli that should not be our next
goal.  But I go further saying that probably would be searching for
troubles, certanly not urgent.

Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 19:16                 ` Eli Zaretskii
@ 2020-05-10 19:41                   ` Nicolas Bértolo
  2020-05-10 19:50                     ` Andrea Corallo
  2020-05-11 14:17                     ` Eli Zaretskii
  2020-05-10 19:47                   ` Andrea Corallo
  1 sibling, 2 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-10 19:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

> But up front, we can simply use the apriori knowledge about the way the setjmp
> macro is expanded in the version used for building Emacs.

I do not understand this. Do you mean that we should just add the necessary
expansions to the emit_setjmp() function?

> But that's a problem on any platform, not just on Windows, isn't it?
> It would mean that when you upgrade GCC, you need to rebuild Emacs in
> order to be able to continue natively-compiling Lisp files, even if
> your Emacs version stays the same.  Is this reasonable?  What will
> GNU/Linux users do that install binary distributions of Emacs -- will
> they have to install a very particular version of GCC to be able to
> compile to native code, and never upgrade it, except together with
> upgrading Emacs?  Sounds very inconvenient to me.

Exactly. I suppose libgccjit has a stable ABI, so it should not be a problem to
update libgccjit. The user will need to ensure that the version of libgccjit
loaded by Emacs has its corresponding GCC installation present.

> I thought that we expect to use libgccjit that's part of the GCC
> installation on the system where Emacs is used, i.e. that libgccjit
> would be a shared library into which Emacs will call.  You seem to be
> saying that libgccjit will come with Emacs (or be statically linked
> into Emacs), and the end-user will have to have a GCC installation of
> the same version from which libgccjit came on the system where Emacs
> was built.

I thought that libgccjit was going to be shipped with Emacs, and therefore it
made most sense to just add a few support files to the Emacs ZIP file.

Right now libgccjit is a shared library that is linked at build time against
Emacs. That is: Emacs will not even start if it was built with native
compilation and the OS dynamic linker cannot find libgccjit.so.

If we intend to depend on the system libgccjit then we need to dlopen()
libgccjit. Just like what's done to libpng or libjansson.

Given that Emacs won't start without libgccjit I was worried about the case
where the user might not have the exact same GCC version installed as the
libgccjit version that was downloaded.

Nicolas



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 19:16                 ` Eli Zaretskii
  2020-05-10 19:41                   ` Nicolas Bértolo
@ 2020-05-10 19:47                   ` Andrea Corallo
  1 sibling, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 19:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Nicolas Bértolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
>> Date: Sun, 10 May 2020 16:02:11 -0300
>> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
>> 
>> > This is known in advance.  We already have that knowledge in Emacs,
>> > see HAVE__SETJMP and HAVE_SIGSETJMP used in lisp.h.
>> 
>> > I don't yet understand why we need the _name_ of the setjmp function.
>> > How will this name be used?
>> 
>> I think it is a good idea to show how the information is used:
>> This is the function that generates a function call to `setjmp`.
>
> Thanks, I will think about this.  But up front, we can simply use the
> apriori knowledge about the way the setjmp macro is expanded in the
> version used for building Emacs.  We could build in some defenses
> against changes in that expansion, if that is a real danger, but
> that's not urgent.

I think one easy way to find in the configure the function name would be
trying the compilation of few test programs till we succeed with the one
that uses the right function name.  This way is a little hacky but way
simpler than parsing the expansion.

Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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-11 14:17                     ` Eli Zaretskii
  1 sibling, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 19:50 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> But up front, we can simply use the apriori knowledge about the way the setjmp
>> macro is expanded in the version used for building Emacs.
>
> I do not understand this. Do you mean that we should just add the necessary
> expansions to the emit_setjmp() function?
>
>> But that's a problem on any platform, not just on Windows, isn't it?
>> It would mean that when you upgrade GCC, you need to rebuild Emacs in
>> order to be able to continue natively-compiling Lisp files, even if
>> your Emacs version stays the same.  Is this reasonable?  What will
>> GNU/Linux users do that install binary distributions of Emacs -- will
>> they have to install a very particular version of GCC to be able to
>> compile to native code, and never upgrade it, except together with
>> upgrading Emacs?  Sounds very inconvenient to me.
>
> Exactly. I suppose libgccjit has a stable ABI, so it should not be a problem to
> update libgccjit. The user will need to ensure that the version of libgccjit
> loaded by Emacs has its corresponding GCC installation present.

I think that's the misunderstanding: libgccjit *is* GCC.  No external
compiler is required.

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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
  0 siblings, 2 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-10 19:55 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Eli Zaretskii, emacs-devel

> I think that's the misunderstanding: libgccjit *is* GCC.  No external
> compiler is required.

I understand that. But we need some extra files, like libgcc.a and
some extra binaries: as, ld, and collect2.
If understood the libgccjit sources correctly it will try to find
them in a directory like: /usr/lib/gcc/x86_64-w64-mingw32/10.0.0

The contents of that directory are what I meant when said "GCC installation".

Nicolas.

El dom., 10 may. 2020 a las 16:50, Andrea Corallo (<akrl@sdf.org>) escribió:
>
> Nicolas Bértolo <nicolasbertolo@gmail.com> writes:
>
> >> But up front, we can simply use the apriori knowledge about the way the setjmp
> >> macro is expanded in the version used for building Emacs.
> >
> > I do not understand this. Do you mean that we should just add the necessary
> > expansions to the emit_setjmp() function?
> >
> >> But that's a problem on any platform, not just on Windows, isn't it?
> >> It would mean that when you upgrade GCC, you need to rebuild Emacs in
> >> order to be able to continue natively-compiling Lisp files, even if
> >> your Emacs version stays the same.  Is this reasonable?  What will
> >> GNU/Linux users do that install binary distributions of Emacs -- will
> >> they have to install a very particular version of GCC to be able to
> >> compile to native code, and never upgrade it, except together with
> >> upgrading Emacs?  Sounds very inconvenient to me.
> >
> > Exactly. I suppose libgccjit has a stable ABI, so it should not be a problem to
> > update libgccjit. The user will need to ensure that the version of libgccjit
> > loaded by Emacs has its corresponding GCC installation present.
>
> I think that's the misunderstanding: libgccjit *is* GCC.  No external
> compiler is required.
>
> --
> akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 19:55                       ` Nicolas Bértolo
@ 2020-05-10 20:01                         ` Andrea Corallo
  2020-05-11 14:19                         ` Eli Zaretskii
  1 sibling, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-10 20:01 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> I think that's the misunderstanding: libgccjit *is* GCC.  No external
>> compiler is required.
>
> I understand that. But we need some extra files, like libgcc.a and
> some extra binaries: as, ld, and collect2.
> If understood the libgccjit sources correctly it will try to find
> them in a directory like: /usr/lib/gcc/x86_64-w64-mingw32/10.0.0

Okay but binutils is just a dependency of libgccjit.  I don't know
Windows but is usually up to the user to admin his system, so yes when
you upgrade libgccjit maybe a new binutils could be needed, but still
Emacs is independent.

Unless we are discussing distributing a bundle, but that's another
subject I think no?

Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 19:41                   ` Nicolas Bértolo
  2020-05-10 19:50                     ` Andrea Corallo
@ 2020-05-11 14:17                     ` Eli Zaretskii
  2020-05-11 15:20                       ` Nicolas Bértolo
  2020-05-12  2:46                       ` Nicolas Bértolo
  1 sibling, 2 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-11 14:17 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sun, 10 May 2020 16:41:42 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> > I thought that we expect to use libgccjit that's part of the GCC
> > installation on the system where Emacs is used, i.e. that libgccjit
> > would be a shared library into which Emacs will call.  You seem to be
> > saying that libgccjit will come with Emacs (or be statically linked
> > into Emacs), and the end-user will have to have a GCC installation of
> > the same version from which libgccjit came on the system where Emacs
> > was built.
> 
> I thought that libgccjit was going to be shipped with Emacs, and therefore it
> made most sense to just add a few support files to the Emacs ZIP file.

I don't think it would be wise for us to distribute libgccjit, because
then we'd need to distribute the GCC sources, and the user will be
unable to reliably use the shipped libgccjit with their local GCC
installation (due to possible version mismatch).

> Right now libgccjit is a shared library that is linked at build time against
> Emacs. That is: Emacs will not even start if it was built with native
> compilation and the OS dynamic linker cannot find libgccjit.so.
> 
> If we intend to depend on the system libgccjit then we need to dlopen()
> libgccjit. Just like what's done to libpng or libjansson.

Right, I think at least on MS-Windows we need to do that.  On Posix
platforms, Emacs will be able to start if there's no libgccjit (and
will crash if it attempts to call any of its functions), so it might
be a good idea to use dlopen/dlsym there as well.  But on Windows it
is IMO critical.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-10 19:55                       ` Nicolas Bértolo
  2020-05-10 20:01                         ` Andrea Corallo
@ 2020-05-11 14:19                         ` Eli Zaretskii
  1 sibling, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-11 14:19 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Sun, 10 May 2020 16:55:18 -0300
> Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org
> 
> > I think that's the misunderstanding: libgccjit *is* GCC.  No external
> > compiler is required.
> 
> I understand that. But we need some extra files, like libgcc.a and
> some extra binaries: as, ld, and collect2.

Yes.  Users who want to compile to native code will have to install
GCC and Binutils.  That's the price of producing native code this way.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-11 14:17                     ` Eli Zaretskii
@ 2020-05-11 15:20                       ` Nicolas Bértolo
  2020-05-11 16:19                         ` Eli Zaretskii
  2020-05-12  2:46                       ` Nicolas Bértolo
  1 sibling, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-11 15:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

> I don't think it would be wise for us to distribute libgccjit, because
> then we'd need to distribute the GCC sources, and the user will be
> unable to reliably use the shipped libgccjit with their local GCC
> installation (due to possible version mismatch).

IMHO that is really inconvenient from the point of view of a user that just
wants to install Emacs and use all its features.

Installing Mingw is not a simple process (at least in my experience). And adding
it to PATH will also add many other unrelated utilities. This pollutes the PATH
variable and may cause trouble. I haven't done in my machine because I fear it
may interact with badly with the rest of the system.

I can think of two ways:

- The whole system will have the mingw libraries available in the LoadLibrary()
search path.

- The mingw distribution comes with many utilities that the user may not want in
  PATH. I haven't explicitly installed any of these, but they are in the same
  folder as `gcc`: ImageMagick, Python, sqlite, TCL.

Overall I don't think it is a good idea to make the user install a whole Mingw
distribution when they only need 10 files.

I can think of a middle-ground solution. Let's have a `comp-gcc-path` variable
that is prepended to PATH in `process-environment` when launching the
compilation subprocess. This will variable should point to the path
where `gcc` lives.
In my system it would be "C:/msys64/mingw64/bin".

This would set up the environment libgccjit expects (no "-B" flag necessary),
but it would not require adding that directory to PATH. It separates what is
necessary for Emacs to work, from the environment the user setup to work.

As an example: imagine the user prepends a "C:/myproject/custom-gcc/bin" to PATH
and then starts Emacs because they need a customized GCC to work on a certain
project. Let's say they need a custom libgccjit for that project too. Emacs
would load that version because it is first in PATH, and then what may happen is
unpredictable. It may have different function signatures and when Emacs calls
them through dlsym() we would get a hard-to-find crash.

> Right, I think at least on MS-Windows we need to do that.  On Posix
> platforms, Emacs will be able to start if there's no libgccjit (and
> will crash if it attempts to call any of its functions), so it might
> be a good idea to use dlopen/dlsym there as well.  But on Windows it
> is IMO critical.

I will do this.

Nicolas



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-11 15:20                       ` Nicolas Bértolo
@ 2020-05-11 16:19                         ` Eli Zaretskii
  2020-05-11 16:43                           ` Andrea Corallo
                                             ` (2 more replies)
  0 siblings, 3 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-11 16:19 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Mon, 11 May 2020 12:20:36 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> > I don't think it would be wise for us to distribute libgccjit, because
> > then we'd need to distribute the GCC sources, and the user will be
> > unable to reliably use the shipped libgccjit with their local GCC
> > installation (due to possible version mismatch).
> 
> IMHO that is really inconvenient from the point of view of a user that just
> wants to install Emacs and use all its features.

Not "all" of its features, just one.

And yes, this is an inconvenience, but it isn't specific to
MS-Windows.  AFAIK, Posix systems nowadays come without a compiler
preinstalled, and you need to install it if you want that.

This is a price to pay for compiling to native code using an external
compiler.  there's no way around this, I think.  People who cannot
afford installing a working compiler and Binutils will have to give up
compiling Lisp files to native code (the Lisp files that come with
Emacs can still be provided as *.eln, I would hope).

> Installing Mingw is not a simple process (at least in my experience). And adding
> it to PATH will also add many other unrelated utilities. This pollutes the PATH
> variable and may cause trouble. I haven't done in my machine because I fear it
> may interact with badly with the rest of the system.

I do have GCC and Binutils on PATH, and I have yet to see any problem.
But of course, someone else might feel uncomfortable with that.

> I can think of two ways:
> 
> - The whole system will have the mingw libraries available in the LoadLibrary()
> search path.

Why is that a problem?  The number of DLLs is quite small and their
names don't conflict with Windows system DLLs.

> - The mingw distribution comes with many utilities that the user may not want in
>   PATH.

I don't think I understand what utilities you have in mind.  Please
name them.

> I haven't explicitly installed any of these, but they are in the same
>   folder as `gcc`: ImageMagick, Python, sqlite, TCL.

I don't know why you have them or which package they came with, but
they are definitely not needed for running the compiler to produce
programs.

> Overall I don't think it is a good idea to make the user install a whole Mingw
> distribution when they only need 10 files.

I really don't see any way around this, sorry.

> I can think of a middle-ground solution. Let's have a `comp-gcc-path` variable
> that is prepended to PATH in `process-environment` when launching the
> compilation subprocess. This will variable should point to the path
> where `gcc` lives.
> In my system it would be "C:/msys64/mingw64/bin".
> 
> This would set up the environment libgccjit expects (no "-B" flag necessary),
> but it would not require adding that directory to PATH. It separates what is
> necessary for Emacs to work, from the environment the user setup to work.

This only solves the problem of having the stuff on PATH, it doesn't
solve the problem of installing it.  And it creates a new problem: the
DLLs will not be in a place where the system looks for them, so we
will need some extra code in the *.eln loader to find them.

> As an example: imagine the user prepends a "C:/myproject/custom-gcc/bin" to PATH
> and then starts Emacs because they need a customized GCC to work on a certain
> project. Let's say they need a custom libgccjit for that project too. Emacs
> would load that version because it is first in PATH, and then what may happen is
> unpredictable. It may have different function signatures and when Emacs calls
> them through dlsym() we would get a hard-to-find crash.

This can happen even without this.  Users who have more than one
compiler installation need to be very careful and need to know what
they are doing.

> > Right, I think at least on MS-Windows we need to do that.  On Posix
> > platforms, Emacs will be able to start if there's no libgccjit (and
> > will crash if it attempts to call any of its functions), so it might
> > be a good idea to use dlopen/dlsym there as well.  But on Windows it
> > is IMO critical.
> 
> I will do this.

Thanks.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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 18:19                           ` Fabrice Popineau
  2 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-11 16:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Nicolas Bértolo, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
>> Date: Mon, 11 May 2020 12:20:36 -0300
>> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
>> 
>> > I don't think it would be wise for us to distribute libgccjit, because
>> > then we'd need to distribute the GCC sources, and the user will be
>> > unable to reliably use the shipped libgccjit with their local GCC
>> > installation (due to possible version mismatch).
>> 
>> IMHO that is really inconvenient from the point of view of a user that just
>> wants to install Emacs and use all its features.
>
> Not "all" of its features, just one.
>
> And yes, this is an inconvenience, but it isn't specific to
> MS-Windows.  AFAIK, Posix systems nowadays come without a compiler
> preinstalled, and you need to install it if you want that.
>
> This is a price to pay for compiling to native code using an external
> compiler.  there's no way around this, I think.  People who cannot
> afford installing a working compiler and Binutils will have to give up
> compiling Lisp files to native code (the Lisp files that come with
> Emacs can still be provided as *.eln, I would hope).

Correct, we do not rely on libgccjit for the load machinery so it is
possible.  I imagine distros could compile and distribute .elns and
still do not hard require libgccjit installed.

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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
  2 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-11 16:44 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

> This only solves the problem of having the stuff on PATH, it doesn't
> solve the problem of installing it.  And it creates a new problem: the
> DLLs will not be in a place where the system looks for them, so we
> will need some extra code in the *.eln loader to find them.

The .eln files do not link against any dynamic libraries. They can be loaded
into Emacs even if GCC is not in the path. `ld` needs a few object files and
static libraries to create the file. I am typing this from an Emacs that does
not have gcc in PATH and it has many .eln files loaded.

>> I will do this.

> Thanks.

I have seen that the way to declare DLL functions to be used in Windows is to
use the DEF_DLL_FN macro. This only works in Windows though. Is there a library
that is loaded through dlopen() in Posix too? I would like to use it as an
example.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-11 16:44                           ` Nicolas Bértolo
@ 2020-05-11 17:05                             ` Eli Zaretskii
  0 siblings, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-11 17:05 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Mon, 11 May 2020 13:44:03 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> I have seen that the way to declare DLL functions to be used in Windows is to
> use the DEF_DLL_FN macro. This only works in Windows though. Is there a library
> that is loaded through dlopen() in Posix too? I would like to use it as an
> example.

We have some facilities in dynlib.c, but I think they stop short of
what DEF_DLL_FN etc. do.

My advice is not to try to solve too many problems at once.  Let's
solve the Windows specific parts, and worry about extending the Posix
platforms to dynamically load *.eln files later.  So I suggest to use
DEF_DLL_FN and LOAD_DLL_FN in Windows-specific code fragments, and
leave the rest to a later day.

(Please keep in mind that DEF_DLL_FN and LOAD_DLL_FN cannot be used
for functions that use stdcall calling convention, they can only be
used with cdecl functions.  Forgetting that cost me a few hours of
hair-pulling not so long time ago ;-)



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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 18:19                           ` Fabrice Popineau
  2020-05-11 18:37                             ` Andrea Corallo
  2020-05-11 18:48                             ` Eli Zaretskii
  2 siblings, 2 replies; 71+ messages in thread
From: Fabrice Popineau @ 2020-05-11 18:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Nicolas Bértolo, akrl, Emacs developers

[-- Attachment #1: Type: text/plain, Size: 1655 bytes --]

Le lun. 11 mai 2020 à 18:20, Eli Zaretskii <eliz@gnu.org> a écrit :

> > From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> > Date: Mon, 11 May 2020 12:20:36 -0300
> > Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> >
> > > I don't think it would be wise for us to distribute libgccjit, because
> > > then we'd need to distribute the GCC sources, and the user will be
> > > unable to reliably use the shipped libgccjit with their local GCC
> > > installation (due to possible version mismatch).
> >
> > IMHO that is really inconvenient from the point of view of a user that
> just
> > wants to install Emacs and use all its features.
>
>
> This is a price to pay for compiling to native code using an external
> compiler.  there's no way around this, I think.  People who cannot
> afford installing a working compiler and Binutils will have to give up
> compiling Lisp files to native code (the Lisp files that come with
> Emacs can still be provided as *.eln, I would hope).
>

<Out_of_Topic>
I guess I am not alone reading this and thinking:
well, Common Lisp provides an embedded compiler even at runtime for years.
(Sorry but could not resist)
</Out_of_Topic>

About the issue there. In the Windows context I would totally follow
Nicolas here.
If Emacs users have to install a working gcc toolchain to be able to
compile to native code,
it almost totally defeats the purpose.
IMHO, the right way to do it is to target a binary distribution that has
all of what is needed.
Else, you will end up in a situation where people must compile their own
binary.
Nobody will do it.

Best regards,

Fabrice

[-- Attachment #2: Type: text/html, Size: 2444 bytes --]

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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-11 18:19                           ` Fabrice Popineau
@ 2020-05-11 18:37                             ` Andrea Corallo
  2020-05-11 18:48                             ` Eli Zaretskii
  1 sibling, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-11 18:37 UTC (permalink / raw)
  To: Fabrice Popineau; +Cc: Nicolas Bértolo, Eli Zaretskii, Emacs developers

Fabrice Popineau <fabrice.popineau@gmail.com> writes:

> <Out_of_Topic>
> I guess I am not alone reading this and thinking: 
> well, Common Lisp provides an embedded compiler even at runtime for
> years.
> (Sorry but could not resist)
> </Out_of_Topic>

I'm not sure what you mean with "Common Lisp", but for instance ECL
(that is C toolchain based) AFAIK on Windows falls back to bytecode by
default (I guess this is similar to the Emacs one).  CLISP is even only
byte-compiled.

That said to be clear: with the native compiler we are in full bring-up
phase.  The fact that I try to maintain the branch always functional and
people are already using it does no mean is finished.

I don't think this is the moment to address this, especially given we
are not taking any design decision that goes against this option.

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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
  1 sibling, 2 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-11 18:48 UTC (permalink / raw)
  To: Fabrice Popineau; +Cc: nicolasbertolo, emacs-devel, akrl

> From: Fabrice Popineau <fabrice.popineau@gmail.com>
> Date: Mon, 11 May 2020 20:19:43 +0200
> Cc: Nicolas Bértolo <nicolasbertolo@gmail.com>, akrl@sdf.org,
>  Emacs developers <emacs-devel@gnu.org>
> 
> If Emacs users have to install a working gcc toolchain to be able to compile to native code,
> it almost totally defeats the purpose.

How is that different from users on Posix platforms?

> IMHO, the right way to do it is to target a binary distribution that has all of what is needed.

So you want Emacs to come with a subset of GCC, a subset of Binutils,
and a subset of MinGW?  Is that reasonable?



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-11 18:48                             ` Eli Zaretskii
@ 2020-05-11 19:27                               ` Stefan Monnier
  2020-05-11 19:42                               ` Fabrice Popineau
  1 sibling, 0 replies; 71+ messages in thread
From: Stefan Monnier @ 2020-05-11 19:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: nicolasbertolo, akrl, Fabrice Popineau, emacs-devel

> So you want Emacs to come with a subset of GCC, a subset of Binutils,
> and a subset of MinGW?  Is that reasonable?

I think we don't even need to choose this, it's not fundamentally
different from the issue of using diff/grep or libgnutls.

Emacs itself will not have libgccjit in the Git nor in the tarball.
Some precompiled versions will likely come "naked" while others can come
bundled with the kitchen sink (including GCC) while yet others come via
package managements that will mark `gcc` as a dependency, ...

The only serious consequence of the availability of this choice is that
we have to make sure Emacs still works well in the absence of libgccjit.

Maybe at some point, we will be in a position to decide that libgccjit
is a *necessary* dependency, but we're very far from that point, AFAIK,
so I'll leave the corresponding discussion for later (for my grand
children?).


        Stefan




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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-11 18:48                             ` Eli Zaretskii
  2020-05-11 19:27                               ` Stefan Monnier
@ 2020-05-11 19:42                               ` Fabrice Popineau
  1 sibling, 0 replies; 71+ messages in thread
From: Fabrice Popineau @ 2020-05-11 19:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: nicolasbertolo, Emacs developers, akrl

[-- Attachment #1: Type: text/plain, Size: 203 bytes --]

Le lun. 11 mai 2020 à 20:48, Eli Zaretskii <eliz@gnu.org> a écrit :

>
> How is that different from users on Posix platforms?
>

The difference may be in the users (or their habits).

Fabrice

[-- Attachment #2: Type: text/html, Size: 592 bytes --]

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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-11 14:17                     ` Eli Zaretskii
  2020-05-11 15:20                       ` Nicolas Bértolo
@ 2020-05-12  2:46                       ` Nicolas Bértolo
  2020-05-12 16:56                         ` Eli Zaretskii
  2020-05-13  3:59                         ` Richard Stallman
  1 sibling, 2 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-12  2:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

[-- Attachment #1: Type: text/plain, Size: 377 bytes --]

> Right, I think at least on MS-Windows we need to do that.  On Posix
> platforms, Emacs will be able to start if there's no libgccjit (and
> will crash if it attempts to call any of its functions), so it might
> be a good idea to use dlopen/dlsym there as well.  But on Windows it
> is IMO critical.

The attached patch does implement dynamic loading of libgccjit in Windows.

[-- Attachment #2: 0001-Load-libgccjit-dynamically-in-Windows.patch --]
[-- Type: application/octet-stream, Size: 19705 bytes --]

From edea454459bbf434241a9f2299cb5032d4412723 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Mon, 11 May 2020 20:43:06 -0300
Subject: [PATCH] Load libgccjit dynamically in Windows.

* configure.ac: don't add linker flags if compiling on Windows.
* lisp/term/w32-win.el: Map 'gccjit to "libgccjit.dll" in
`dynamic-library-alist`.
* src/comp.c: Add declarations of used libgccjit functions using
DEF_DLL_FN. Add calls to load_gccjit_if_necessary() where necessary.
* src/w32fns.c: Add Qgccjit symbol.
---
 configure.ac         |   5 +-
 lisp/term/w32-win.el |   3 +-
 src/comp.c           | 304 +++++++++++++++++++++++++++++++++++++++++++
 src/w32fns.c         |   1 +
 4 files changed, 311 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 23b94cf6ca..97639fdfba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3793,7 +3793,10 @@ AC_DEFUN
       [AC_LINK_IFELSE([libgccjit_smoke_test], [], [libgccjit_not_found])])
     LIBS=$emacs_save_LIBS
     HAVE_NATIVE_COMP=yes
-    LIBGCCJIT_LIB="-lgccjit -ldl"
+    # mingw32 loads the library dynamically.
+    if test "${opsys}" != "mingw32"; then
+      LIBGCCJIT_LIB="-lgccjit -ldl"
+    fi
     COMP_OBJ="comp.o"
     AC_DEFINE(HAVE_NATIVE_COMP, 1, [Define to 1 if you have the libgccjit library (-lgccjit).])
 fi
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index 5901e0295e..6b9716ca30 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -289,7 +289,8 @@ libgnutls-version
        '(libxml2 "libxml2-2.dll" "libxml2.dll")
        '(zlib "zlib1.dll" "libz-1.dll")
        '(lcms2 "liblcms2-2.dll")
-       '(json "libjansson-4.dll")))
+       '(json "libjansson-4.dll")
+       '(gccjit "libgccjit.dll")))
 
 ;;; multi-tty support
 (defvar w32-initialized nil
diff --git a/src/comp.c b/src/comp.c
index 69525acfc0..d7fd408366 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -36,6 +36,291 @@
 #include "blockinput.h"
 #include "sha512.h"
 
+\f
+/********************************/
+/* Dynamic loading of libgccjit */
+/********************************/
+
+#ifdef WINDOWSNT
+# include "w32common.h"
+bool gccjit_initialized;
+
+/* In alphabetical order */
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_int,
+            (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, int value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_lvalue_as_rvalue,
+            (gcc_jit_lvalue *lvalue));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_rvalue_access_field,
+            (gcc_jit_rvalue *struct_or_union, gcc_jit_location *loc,
+             gcc_jit_field *field));
+DEF_DLL_FN (void, gcc_jit_block_add_comment,
+            (gcc_jit_block *block, gcc_jit_location *loc, const char *text));
+DEF_DLL_FN (void, gcc_jit_context_release, (gcc_jit_context *ctxt));
+DEF_DLL_FN (const char *, gcc_jit_context_get_first_error,
+            (gcc_jit_context *ctxt));
+DEF_DLL_FN (gcc_jit_block *, gcc_jit_function_new_block,
+            (gcc_jit_function *func, const char *name));
+DEF_DLL_FN (gcc_jit_context *, gcc_jit_context_acquire, (void));
+DEF_DLL_FN (gcc_jit_field *, gcc_jit_context_new_field,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_function *, gcc_jit_context_get_builtin_function,
+            (gcc_jit_context *ctxt, const char *name));
+DEF_DLL_FN (gcc_jit_function *, gcc_jit_context_new_function,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_function_kind kind, gcc_jit_type *return_type,
+             const char *name, int num_params, gcc_jit_param **params,
+             int is_variadic));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_context_new_array_access,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *ptr,
+             gcc_jit_rvalue *index));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_context_new_global,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_global_kind kind, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_function_new_local,
+            (gcc_jit_function *func, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_lvalue_access_field,
+            (gcc_jit_lvalue *struct_or_union, gcc_jit_location *loc,
+             gcc_jit_field *field));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_param_as_lvalue, (gcc_jit_param *param));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_rvalue_dereference,
+            (gcc_jit_rvalue *rvalue, gcc_jit_location *loc));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_rvalue_dereference_field,
+            (gcc_jit_rvalue *ptr, gcc_jit_location *loc, gcc_jit_field *field));
+DEF_DLL_FN (gcc_jit_param *, gcc_jit_context_new_param,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_param *, gcc_jit_function_get_param,
+            (gcc_jit_function *func, int index));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_binary_op,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_binary_op op, gcc_jit_type *result_type,
+             gcc_jit_rvalue *a, gcc_jit_rvalue *b));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_function *func, int numargs , gcc_jit_rvalue **args));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call_through_ptr,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_rvalue *fn_ptr, int numargs, gcc_jit_rvalue **args));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_comparison,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_comparison op, gcc_jit_rvalue *a, gcc_jit_rvalue *b));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_long,
+            (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, long value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_ptr,
+            (gcc_jit_context *ctxt, gcc_jit_type *pointer_type, void *value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_unary_op,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_unary_op op, gcc_jit_type *result_type,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_lvalue_get_address,
+            (gcc_jit_lvalue *lvalue, gcc_jit_location *loc));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_param_as_rvalue, (gcc_jit_param *param));
+DEF_DLL_FN (gcc_jit_struct *, gcc_jit_context_new_opaque_struct,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name));
+DEF_DLL_FN (gcc_jit_struct *, gcc_jit_context_new_struct_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name,
+             int num_fields, gcc_jit_field **fields));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_get_int_type,
+            (gcc_jit_context *ctxt, int num_bytes, int is_signed));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_get_type,
+            (gcc_jit_context *ctxt, enum gcc_jit_types type_));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_array_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_type *element_type, int num_elements));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_function_ptr_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_type *return_type, int num_params,
+             gcc_jit_type **param_types, int is_variadic));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_union_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name,
+             int num_fields, gcc_jit_field **fields));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_rvalue_get_type, (gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_struct_as_type,
+            (gcc_jit_struct *struct_type));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_type_get_pointer, (gcc_jit_type *type));
+DEF_DLL_FN (void, gcc_jit_block_add_assignment,
+            (gcc_jit_block *block, gcc_jit_location *loc, gcc_jit_lvalue *lvalue,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_add_eval,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_end_with_conditional,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *boolval, gcc_jit_block *on_true,
+             gcc_jit_block *on_false));
+DEF_DLL_FN (void, gcc_jit_block_end_with_jump,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_block *target));
+DEF_DLL_FN (void, gcc_jit_block_end_with_return,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_end_with_void_return,
+            (gcc_jit_block *block, gcc_jit_location *loc));
+DEF_DLL_FN (void, gcc_jit_context_compile_to_file,
+            (gcc_jit_context *ctxt, enum gcc_jit_output_kind output_kind,
+             const char *output_path));
+DEF_DLL_FN (void, gcc_jit_context_dump_reproducer_to_file,
+            (gcc_jit_context *ctxt, const char *path));
+DEF_DLL_FN (void, gcc_jit_context_dump_to_file,
+            (gcc_jit_context *ctxt, const char *path, int update_locations));
+DEF_DLL_FN (void, gcc_jit_context_set_bool_option,
+            (gcc_jit_context *ctxt, enum gcc_jit_bool_option opt, int value));
+DEF_DLL_FN (void, gcc_jit_context_set_int_option,
+            (gcc_jit_context *ctxt, enum gcc_jit_int_option opt, int value));
+DEF_DLL_FN (void, gcc_jit_context_set_logfile,
+            (gcc_jit_context *ctxt, FILE *logfile, int flags, int verbosity));
+DEF_DLL_FN (void, gcc_jit_struct_set_fields,
+            (gcc_jit_struct *struct_type, gcc_jit_location *loc, int num_fields,
+             gcc_jit_field **fields));
+
+static bool
+init_gccjit_functions(void)
+{
+  HMODULE library;
+
+  if (!(library = w32_delayed_load (Qgccjit)))
+    {
+      return false;
+    }
+
+  /* In alphabetical order */
+  LOAD_DLL_FN(library, gcc_jit_block_add_assignment);
+  LOAD_DLL_FN(library, gcc_jit_block_add_comment);
+  LOAD_DLL_FN(library, gcc_jit_block_add_eval);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_conditional);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_jump);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_return);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_void_return);
+  LOAD_DLL_FN(library, gcc_jit_context_acquire);
+  LOAD_DLL_FN(library, gcc_jit_context_compile_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_dump_reproducer_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_dump_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_get_builtin_function);
+  LOAD_DLL_FN(library, gcc_jit_context_get_first_error);
+  LOAD_DLL_FN(library, gcc_jit_context_get_int_type);
+  LOAD_DLL_FN(library, gcc_jit_context_get_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_array_access);
+  LOAD_DLL_FN(library, gcc_jit_context_new_array_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_binary_op);
+  LOAD_DLL_FN(library, gcc_jit_context_new_call);
+  LOAD_DLL_FN(library, gcc_jit_context_new_call_through_ptr);
+  LOAD_DLL_FN(library, gcc_jit_context_new_comparison);
+  LOAD_DLL_FN(library, gcc_jit_context_new_field);
+  LOAD_DLL_FN(library, gcc_jit_context_new_function);
+  LOAD_DLL_FN(library, gcc_jit_context_new_function_ptr_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_global);
+  LOAD_DLL_FN(library, gcc_jit_context_new_opaque_struct);
+  LOAD_DLL_FN(library, gcc_jit_context_new_param);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_int);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_long);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_ptr);
+  LOAD_DLL_FN(library, gcc_jit_context_new_struct_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_unary_op);
+  LOAD_DLL_FN(library, gcc_jit_context_new_union_type);
+  LOAD_DLL_FN(library, gcc_jit_context_release);
+  LOAD_DLL_FN(library, gcc_jit_context_set_bool_option);
+  LOAD_DLL_FN(library, gcc_jit_context_set_int_option);
+  LOAD_DLL_FN(library, gcc_jit_context_set_logfile);
+  LOAD_DLL_FN(library, gcc_jit_function_get_param);
+  LOAD_DLL_FN(library, gcc_jit_function_new_block);
+  LOAD_DLL_FN(library, gcc_jit_function_new_local);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_access_field);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_as_rvalue);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_get_address);
+  LOAD_DLL_FN(library, gcc_jit_param_as_lvalue);
+  LOAD_DLL_FN(library, gcc_jit_param_as_rvalue);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_access_field);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_dereference);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_dereference_field);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_get_type);
+  LOAD_DLL_FN(library, gcc_jit_struct_as_type);
+  LOAD_DLL_FN(library, gcc_jit_struct_set_fields);
+  LOAD_DLL_FN(library, gcc_jit_type_get_pointer);
+
+  return true;
+}
+
+/* In alphabetical order */
+#define gcc_jit_block_add_assignment fn_gcc_jit_block_add_assignment
+#define gcc_jit_block_add_comment fn_gcc_jit_block_add_comment
+#define gcc_jit_block_add_eval fn_gcc_jit_block_add_eval
+#define gcc_jit_block_end_with_conditional fn_gcc_jit_block_end_with_conditional
+#define gcc_jit_block_end_with_jump fn_gcc_jit_block_end_with_jump
+#define gcc_jit_block_end_with_return fn_gcc_jit_block_end_with_return
+#define gcc_jit_block_end_with_void_return fn_gcc_jit_block_end_with_void_return
+#define gcc_jit_context_acquire fn_gcc_jit_context_acquire
+#define gcc_jit_context_compile_to_file fn_gcc_jit_context_compile_to_file
+#define gcc_jit_context_dump_reproducer_to_file fn_gcc_jit_context_dump_reproducer_to_file
+#define gcc_jit_context_dump_to_file fn_gcc_jit_context_dump_to_file
+#define gcc_jit_context_get_builtin_function fn_gcc_jit_context_get_builtin_function
+#define gcc_jit_context_get_first_error fn_gcc_jit_context_get_first_error
+#define gcc_jit_context_get_int_type fn_gcc_jit_context_get_int_type
+#define gcc_jit_context_get_type fn_gcc_jit_context_get_type
+#define gcc_jit_context_new_array_access fn_gcc_jit_context_new_array_access
+#define gcc_jit_context_new_array_type fn_gcc_jit_context_new_array_type
+#define gcc_jit_context_new_binary_op fn_gcc_jit_context_new_binary_op
+#define gcc_jit_context_new_call fn_gcc_jit_context_new_call
+#define gcc_jit_context_new_call_through_ptr fn_gcc_jit_context_new_call_through_ptr
+#define gcc_jit_context_new_comparison fn_gcc_jit_context_new_comparison
+#define gcc_jit_context_new_field fn_gcc_jit_context_new_field
+#define gcc_jit_context_new_function fn_gcc_jit_context_new_function
+#define gcc_jit_context_new_function_ptr_type fn_gcc_jit_context_new_function_ptr_type
+#define gcc_jit_context_new_global fn_gcc_jit_context_new_global
+#define gcc_jit_context_new_opaque_struct fn_gcc_jit_context_new_opaque_struct
+#define gcc_jit_context_new_param fn_gcc_jit_context_new_param
+#define gcc_jit_context_new_rvalue_from_int fn_gcc_jit_context_new_rvalue_from_int
+#define gcc_jit_context_new_rvalue_from_long fn_gcc_jit_context_new_rvalue_from_long
+#define gcc_jit_context_new_rvalue_from_ptr fn_gcc_jit_context_new_rvalue_from_ptr
+#define gcc_jit_context_new_struct_type fn_gcc_jit_context_new_struct_type
+#define gcc_jit_context_new_unary_op fn_gcc_jit_context_new_unary_op
+#define gcc_jit_context_new_union_type fn_gcc_jit_context_new_union_type
+#define gcc_jit_context_release fn_gcc_jit_context_release
+#define gcc_jit_context_set_bool_option fn_gcc_jit_context_set_bool_option
+#define gcc_jit_context_set_int_option fn_gcc_jit_context_set_int_option
+#define gcc_jit_context_set_logfile fn_gcc_jit_context_set_logfile
+#define gcc_jit_function_get_param fn_gcc_jit_function_get_param
+#define gcc_jit_function_new_block fn_gcc_jit_function_new_block
+#define gcc_jit_function_new_local fn_gcc_jit_function_new_local
+#define gcc_jit_lvalue_access_field fn_gcc_jit_lvalue_access_field
+#define gcc_jit_lvalue_as_rvalue fn_gcc_jit_lvalue_as_rvalue
+#define gcc_jit_lvalue_get_address fn_gcc_jit_lvalue_get_address
+#define gcc_jit_param_as_lvalue fn_gcc_jit_param_as_lvalue
+#define gcc_jit_param_as_rvalue fn_gcc_jit_param_as_rvalue
+#define gcc_jit_rvalue_access_field fn_gcc_jit_rvalue_access_field
+#define gcc_jit_rvalue_dereference fn_gcc_jit_rvalue_dereference
+#define gcc_jit_rvalue_dereference_field fn_gcc_jit_rvalue_dereference_field
+#define gcc_jit_rvalue_get_type fn_gcc_jit_rvalue_get_type
+#define gcc_jit_struct_as_type fn_gcc_jit_struct_as_type
+#define gcc_jit_struct_set_fields fn_gcc_jit_struct_set_fields
+#define gcc_jit_type_get_pointer fn_gcc_jit_type_get_pointer
+
+#endif
+
+static bool
+load_gccjit_if_necessary(bool mandatory)
+{
+#ifdef WINDOWSNT
+  if (!gccjit_initialized)
+    {
+      Lisp_Object status;
+      gccjit_initialized = init_gccjit_functions ();
+      status = gccjit_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
+    }
+
+  if (mandatory && !gccjit_initialized)
+    xsignal1(Qnative_compiler_error, build_string("libgccjit not found"));
+
+  return gccjit_initialized;
+#else
+  return true;
+#endif
+}
+
+\f
 /* C symbols emitted for the load relocation mechanism.  */
 #define CURRENT_THREAD_RELOC_SYM "current_thread_reloc"
 #define PURE_PTR_SYM "pure_ptr"
@@ -3328,6 +3613,8 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
        doc: /* Initialize the native compiler context. Return t on success.  */)
      (void)
 {
+  load_gccjit_if_necessary(true);
+
   if (comp.ctxt)
     {
       xsignal1 (Qnative_ice,
@@ -3474,6 +3761,8 @@ DEFUN ("comp--release-ctxt", Fcomp__release_ctxt, Scomp__release_ctxt,
        doc: /* Release the native compiler context.  */)
      (void)
 {
+  load_gccjit_if_necessary(true);
+
   if (comp.ctxt)
     gcc_jit_context_release (comp.ctxt);
 
@@ -3490,6 +3779,8 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
        doc: /* Compile as native code the current context to file.  */)
      (Lisp_Object base_name)
 {
+  load_gccjit_if_necessary(true);
+
   CHECK_STRING (base_name);
 
   gcc_jit_context_set_int_option (comp.ctxt,
@@ -3660,6 +3951,9 @@ maybe_defer_native_compilation (Lisp_Object function_name,
       fflush (f);
     }
 #endif
+  if (!load_gccjit_if_necessary(false))
+    return;
+
   if (!comp_deferred_compilation
       || noninteractive
       || !NILP (Vpurify_flag)
@@ -3928,6 +4222,15 @@ DEFUN ("native-elisp-load", Fnative_elisp_load, Snative_elisp_load, 1, 2, 0,
   return Qt;
 }
 
+DEFUN ("native-comp-available-p", Fnative_comp_available_p,
+       Snative_comp_available_p, 0, 0, 0,
+       doc: /* Returns t if native compilation of Lisp files is available in
+this instance of Emacs. */)
+  (void)
+{
+  return load_gccjit_if_necessary(false) ? Qt : Qnil;
+}
+
 \f
 void
 syms_of_comp (void)
@@ -4039,6 +4342,7 @@ syms_of_comp (void)
   defsubr (&Scomp__register_subr);
   defsubr (&Scomp__late_register_subr);
   defsubr (&Snative_elisp_load);
+  defsubr (&Snative_comp_available_p);
 
   staticpro (&comp.exported_funcs_h);
   comp.exported_funcs_h = Qnil;
diff --git a/src/w32fns.c b/src/w32fns.c
index e595b0285a..eeb73489dd 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10462,6 +10462,7 @@ syms_of_w32fns (void)
   DEFSYM (Qzlib, "zlib");
   DEFSYM (Qlcms2, "lcms2");
   DEFSYM (Qjson, "json");
+  DEFSYM (Qgccjit, "gccjit");
 
   Fput (Qundefined_color, Qerror_conditions,
 	pure_list (Qundefined_color, Qerror));
-- 
2.25.1.windows.1


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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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-13  3:59                         ` Richard Stallman
  1 sibling, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-12 16:56 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Mon, 11 May 2020 23:46:09 -0300
> Cc: Andrea Corallo <akrl@sdf.org>, emacs-devel@gnu.org
> 
> The attached patch does implement dynamic loading of libgccjit in Windows.

Thanks.

> -    LIBGCCJIT_LIB="-lgccjit -ldl"
> +    # mingw32 loads the library dynamically.
> +    if test "${opsys}" != "mingw32"; then
> +      LIBGCCJIT_LIB="-lgccjit -ldl"

libdl exists only in MinGW64, I think.

Why do you need it? is it because the code uses dlopen/dlsym
somewhere?

> +/* In alphabetical order */
> +#define gcc_jit_block_add_assignment fn_gcc_jit_block_add_assignment
> +#define gcc_jit_block_add_comment fn_gcc_jit_block_add_comment
> +#define gcc_jit_block_add_eval fn_gcc_jit_block_add_eval
> +#define gcc_jit_block_end_with_conditional fn_gcc_jit_block_end_with_conditional

I think it's good to #undef each symbol before defining it.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-12 16:56                         ` Eli Zaretskii
@ 2020-05-12 17:25                           ` Nicolas Bértolo
  2020-05-12 18:21                             ` Andrea Corallo
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-12 17:25 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel, Andrea Corallo

[-- Attachment #1: Type: text/plain, Size: 661 bytes --]

> libdl exists only in MinGW64, I think.

> Why do you need it? is it because the code uses dlopen/dlsym
> somewhere?

The code uses `dynlib_open` and `dynlib_sym` which are implemented using libdl
in Posix systems. The original libgccjit uses it to implement the
`compile_to_memory` function that we do not use. The version of libgccjit I am
using implements that feature using native Windows functions, so libdl is not
necessary.

I don't think we can remove it because that part of the code runs only when the
platform is not Mingw, and in that case libdl is necessary.

> I think it's good to #undef each symbol before defining it.

Fixed in the new patch.

[-- Attachment #2: Load-libgccjit-dynamically-in-Windows.patch --]
[-- Type: application/octet-stream, Size: 21655 bytes --]

From 3054c4464de78aecd93bf88862b4b266763ba5aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Mon, 11 May 2020 20:43:06 -0300
Subject: [PATCH] Load libgccjit dynamically in Windows.

* configure.ac: don't add linker flags if compiling on Windows.
* lisp/term/w32-win.el: Map 'gccjit to "libgccjit.dll" in
`dynamic-library-alist`.
* src/comp.c: Add declarations of used libgccjit functions using
DEF_DLL_FN. Add calls to load_gccjit_if_necessary() where necessary.
* src/w32fns.c: Add Qgccjit symbol.
---
 configure.ac         |   5 +-
 lisp/term/w32-win.el |   3 +-
 src/comp.c           | 357 +++++++++++++++++++++++++++++++++++++++++++
 src/w32fns.c         |   1 +
 4 files changed, 364 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 23b94cf6ca..97639fdfba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3793,7 +3793,10 @@ AC_DEFUN
       [AC_LINK_IFELSE([libgccjit_smoke_test], [], [libgccjit_not_found])])
     LIBS=$emacs_save_LIBS
     HAVE_NATIVE_COMP=yes
-    LIBGCCJIT_LIB="-lgccjit -ldl"
+    # mingw32 loads the library dynamically.
+    if test "${opsys}" != "mingw32"; then
+      LIBGCCJIT_LIB="-lgccjit -ldl"
+    fi
     COMP_OBJ="comp.o"
     AC_DEFINE(HAVE_NATIVE_COMP, 1, [Define to 1 if you have the libgccjit library (-lgccjit).])
 fi
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index 5901e0295e..6b9716ca30 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -289,7 +289,8 @@ libgnutls-version
        '(libxml2 "libxml2-2.dll" "libxml2.dll")
        '(zlib "zlib1.dll" "libz-1.dll")
        '(lcms2 "liblcms2-2.dll")
-       '(json "libjansson-4.dll")))
+       '(json "libjansson-4.dll")
+       '(gccjit "libgccjit.dll")))
 
 ;;; multi-tty support
 (defvar w32-initialized nil
diff --git a/src/comp.c b/src/comp.c
index 69525acfc0..9fb4e6f6af 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -36,6 +36,344 @@
 #include "blockinput.h"
 #include "sha512.h"
 
+\f
+/********************************/
+/* Dynamic loading of libgccjit */
+/********************************/
+
+#ifdef WINDOWSNT
+# include "w32common.h"
+bool gccjit_initialized;
+
+#undef gcc_jit_block_add_assignment
+#undef gcc_jit_block_add_comment
+#undef gcc_jit_block_add_eval
+#undef gcc_jit_block_end_with_conditional
+#undef gcc_jit_block_end_with_jump
+#undef gcc_jit_block_end_with_return
+#undef gcc_jit_block_end_with_void_return
+#undef gcc_jit_context_acquire
+#undef gcc_jit_context_compile_to_file
+#undef gcc_jit_context_dump_reproducer_to_file
+#undef gcc_jit_context_dump_to_file
+#undef gcc_jit_context_get_builtin_function
+#undef gcc_jit_context_get_first_error
+#undef gcc_jit_context_get_int_type
+#undef gcc_jit_context_get_type
+#undef gcc_jit_context_new_array_access
+#undef gcc_jit_context_new_array_type
+#undef gcc_jit_context_new_binary_op
+#undef gcc_jit_context_new_call
+#undef gcc_jit_context_new_call_through_ptr
+#undef gcc_jit_context_new_comparison
+#undef gcc_jit_context_new_field
+#undef gcc_jit_context_new_function
+#undef gcc_jit_context_new_function_ptr_type
+#undef gcc_jit_context_new_global
+#undef gcc_jit_context_new_opaque_struct
+#undef gcc_jit_context_new_param
+#undef gcc_jit_context_new_rvalue_from_int
+#undef gcc_jit_context_new_rvalue_from_long
+#undef gcc_jit_context_new_rvalue_from_ptr
+#undef gcc_jit_context_new_struct_type
+#undef gcc_jit_context_new_unary_op
+#undef gcc_jit_context_new_union_type
+#undef gcc_jit_context_release
+#undef gcc_jit_context_set_bool_option
+#undef gcc_jit_context_set_int_option
+#undef gcc_jit_context_set_logfile
+#undef gcc_jit_function_get_param
+#undef gcc_jit_function_new_block
+#undef gcc_jit_function_new_local
+#undef gcc_jit_lvalue_access_field
+#undef gcc_jit_lvalue_as_rvalue
+#undef gcc_jit_lvalue_get_address
+#undef gcc_jit_param_as_lvalue
+#undef gcc_jit_param_as_rvalue
+#undef gcc_jit_rvalue_access_field
+#undef gcc_jit_rvalue_dereference
+#undef gcc_jit_rvalue_dereference_field
+#undef gcc_jit_rvalue_get_type
+#undef gcc_jit_struct_as_type
+#undef gcc_jit_struct_set_fields
+#undef gcc_jit_type_get_pointer
+
+/* In alphabetical order */
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_int,
+            (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, int value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_lvalue_as_rvalue,
+            (gcc_jit_lvalue *lvalue));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_rvalue_access_field,
+            (gcc_jit_rvalue *struct_or_union, gcc_jit_location *loc,
+             gcc_jit_field *field));
+DEF_DLL_FN (void, gcc_jit_block_add_comment,
+            (gcc_jit_block *block, gcc_jit_location *loc, const char *text));
+DEF_DLL_FN (void, gcc_jit_context_release, (gcc_jit_context *ctxt));
+DEF_DLL_FN (const char *, gcc_jit_context_get_first_error,
+            (gcc_jit_context *ctxt));
+DEF_DLL_FN (gcc_jit_block *, gcc_jit_function_new_block,
+            (gcc_jit_function *func, const char *name));
+DEF_DLL_FN (gcc_jit_context *, gcc_jit_context_acquire, (void));
+DEF_DLL_FN (gcc_jit_field *, gcc_jit_context_new_field,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_function *, gcc_jit_context_get_builtin_function,
+            (gcc_jit_context *ctxt, const char *name));
+DEF_DLL_FN (gcc_jit_function *, gcc_jit_context_new_function,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_function_kind kind, gcc_jit_type *return_type,
+             const char *name, int num_params, gcc_jit_param **params,
+             int is_variadic));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_context_new_array_access,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *ptr,
+             gcc_jit_rvalue *index));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_context_new_global,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_global_kind kind, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_function_new_local,
+            (gcc_jit_function *func, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_lvalue_access_field,
+            (gcc_jit_lvalue *struct_or_union, gcc_jit_location *loc,
+             gcc_jit_field *field));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_param_as_lvalue, (gcc_jit_param *param));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_rvalue_dereference,
+            (gcc_jit_rvalue *rvalue, gcc_jit_location *loc));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_rvalue_dereference_field,
+            (gcc_jit_rvalue *ptr, gcc_jit_location *loc, gcc_jit_field *field));
+DEF_DLL_FN (gcc_jit_param *, gcc_jit_context_new_param,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_param *, gcc_jit_function_get_param,
+            (gcc_jit_function *func, int index));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_binary_op,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_binary_op op, gcc_jit_type *result_type,
+             gcc_jit_rvalue *a, gcc_jit_rvalue *b));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_function *func, int numargs , gcc_jit_rvalue **args));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call_through_ptr,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_rvalue *fn_ptr, int numargs, gcc_jit_rvalue **args));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_comparison,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_comparison op, gcc_jit_rvalue *a, gcc_jit_rvalue *b));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_long,
+            (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, long value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_ptr,
+            (gcc_jit_context *ctxt, gcc_jit_type *pointer_type, void *value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_unary_op,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_unary_op op, gcc_jit_type *result_type,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_lvalue_get_address,
+            (gcc_jit_lvalue *lvalue, gcc_jit_location *loc));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_param_as_rvalue, (gcc_jit_param *param));
+DEF_DLL_FN (gcc_jit_struct *, gcc_jit_context_new_opaque_struct,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name));
+DEF_DLL_FN (gcc_jit_struct *, gcc_jit_context_new_struct_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name,
+             int num_fields, gcc_jit_field **fields));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_get_int_type,
+            (gcc_jit_context *ctxt, int num_bytes, int is_signed));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_get_type,
+            (gcc_jit_context *ctxt, enum gcc_jit_types type_));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_array_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_type *element_type, int num_elements));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_function_ptr_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_type *return_type, int num_params,
+             gcc_jit_type **param_types, int is_variadic));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_union_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name,
+             int num_fields, gcc_jit_field **fields));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_rvalue_get_type, (gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_struct_as_type,
+            (gcc_jit_struct *struct_type));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_type_get_pointer, (gcc_jit_type *type));
+DEF_DLL_FN (void, gcc_jit_block_add_assignment,
+            (gcc_jit_block *block, gcc_jit_location *loc, gcc_jit_lvalue *lvalue,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_add_eval,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_end_with_conditional,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *boolval, gcc_jit_block *on_true,
+             gcc_jit_block *on_false));
+DEF_DLL_FN (void, gcc_jit_block_end_with_jump,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_block *target));
+DEF_DLL_FN (void, gcc_jit_block_end_with_return,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_end_with_void_return,
+            (gcc_jit_block *block, gcc_jit_location *loc));
+DEF_DLL_FN (void, gcc_jit_context_compile_to_file,
+            (gcc_jit_context *ctxt, enum gcc_jit_output_kind output_kind,
+             const char *output_path));
+DEF_DLL_FN (void, gcc_jit_context_dump_reproducer_to_file,
+            (gcc_jit_context *ctxt, const char *path));
+DEF_DLL_FN (void, gcc_jit_context_dump_to_file,
+            (gcc_jit_context *ctxt, const char *path, int update_locations));
+DEF_DLL_FN (void, gcc_jit_context_set_bool_option,
+            (gcc_jit_context *ctxt, enum gcc_jit_bool_option opt, int value));
+DEF_DLL_FN (void, gcc_jit_context_set_int_option,
+            (gcc_jit_context *ctxt, enum gcc_jit_int_option opt, int value));
+DEF_DLL_FN (void, gcc_jit_context_set_logfile,
+            (gcc_jit_context *ctxt, FILE *logfile, int flags, int verbosity));
+DEF_DLL_FN (void, gcc_jit_struct_set_fields,
+            (gcc_jit_struct *struct_type, gcc_jit_location *loc, int num_fields,
+             gcc_jit_field **fields));
+
+static bool
+init_gccjit_functions(void)
+{
+  HMODULE library;
+
+  if (!(library = w32_delayed_load (Qgccjit)))
+    {
+      return false;
+    }
+
+  /* In alphabetical order */
+  LOAD_DLL_FN(library, gcc_jit_block_add_assignment);
+  LOAD_DLL_FN(library, gcc_jit_block_add_comment);
+  LOAD_DLL_FN(library, gcc_jit_block_add_eval);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_conditional);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_jump);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_return);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_void_return);
+  LOAD_DLL_FN(library, gcc_jit_context_acquire);
+  LOAD_DLL_FN(library, gcc_jit_context_compile_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_dump_reproducer_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_dump_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_get_builtin_function);
+  LOAD_DLL_FN(library, gcc_jit_context_get_first_error);
+  LOAD_DLL_FN(library, gcc_jit_context_get_int_type);
+  LOAD_DLL_FN(library, gcc_jit_context_get_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_array_access);
+  LOAD_DLL_FN(library, gcc_jit_context_new_array_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_binary_op);
+  LOAD_DLL_FN(library, gcc_jit_context_new_call);
+  LOAD_DLL_FN(library, gcc_jit_context_new_call_through_ptr);
+  LOAD_DLL_FN(library, gcc_jit_context_new_comparison);
+  LOAD_DLL_FN(library, gcc_jit_context_new_field);
+  LOAD_DLL_FN(library, gcc_jit_context_new_function);
+  LOAD_DLL_FN(library, gcc_jit_context_new_function_ptr_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_global);
+  LOAD_DLL_FN(library, gcc_jit_context_new_opaque_struct);
+  LOAD_DLL_FN(library, gcc_jit_context_new_param);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_int);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_long);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_ptr);
+  LOAD_DLL_FN(library, gcc_jit_context_new_struct_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_unary_op);
+  LOAD_DLL_FN(library, gcc_jit_context_new_union_type);
+  LOAD_DLL_FN(library, gcc_jit_context_release);
+  LOAD_DLL_FN(library, gcc_jit_context_set_bool_option);
+  LOAD_DLL_FN(library, gcc_jit_context_set_int_option);
+  LOAD_DLL_FN(library, gcc_jit_context_set_logfile);
+  LOAD_DLL_FN(library, gcc_jit_function_get_param);
+  LOAD_DLL_FN(library, gcc_jit_function_new_block);
+  LOAD_DLL_FN(library, gcc_jit_function_new_local);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_access_field);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_as_rvalue);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_get_address);
+  LOAD_DLL_FN(library, gcc_jit_param_as_lvalue);
+  LOAD_DLL_FN(library, gcc_jit_param_as_rvalue);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_access_field);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_dereference);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_dereference_field);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_get_type);
+  LOAD_DLL_FN(library, gcc_jit_struct_as_type);
+  LOAD_DLL_FN(library, gcc_jit_struct_set_fields);
+  LOAD_DLL_FN(library, gcc_jit_type_get_pointer);
+
+  return true;
+}
+
+/* In alphabetical order */
+#define gcc_jit_block_add_assignment fn_gcc_jit_block_add_assignment
+#define gcc_jit_block_add_comment fn_gcc_jit_block_add_comment
+#define gcc_jit_block_add_eval fn_gcc_jit_block_add_eval
+#define gcc_jit_block_end_with_conditional fn_gcc_jit_block_end_with_conditional
+#define gcc_jit_block_end_with_jump fn_gcc_jit_block_end_with_jump
+#define gcc_jit_block_end_with_return fn_gcc_jit_block_end_with_return
+#define gcc_jit_block_end_with_void_return fn_gcc_jit_block_end_with_void_return
+#define gcc_jit_context_acquire fn_gcc_jit_context_acquire
+#define gcc_jit_context_compile_to_file fn_gcc_jit_context_compile_to_file
+#define gcc_jit_context_dump_reproducer_to_file fn_gcc_jit_context_dump_reproducer_to_file
+#define gcc_jit_context_dump_to_file fn_gcc_jit_context_dump_to_file
+#define gcc_jit_context_get_builtin_function fn_gcc_jit_context_get_builtin_function
+#define gcc_jit_context_get_first_error fn_gcc_jit_context_get_first_error
+#define gcc_jit_context_get_int_type fn_gcc_jit_context_get_int_type
+#define gcc_jit_context_get_type fn_gcc_jit_context_get_type
+#define gcc_jit_context_new_array_access fn_gcc_jit_context_new_array_access
+#define gcc_jit_context_new_array_type fn_gcc_jit_context_new_array_type
+#define gcc_jit_context_new_binary_op fn_gcc_jit_context_new_binary_op
+#define gcc_jit_context_new_call fn_gcc_jit_context_new_call
+#define gcc_jit_context_new_call_through_ptr fn_gcc_jit_context_new_call_through_ptr
+#define gcc_jit_context_new_comparison fn_gcc_jit_context_new_comparison
+#define gcc_jit_context_new_field fn_gcc_jit_context_new_field
+#define gcc_jit_context_new_function fn_gcc_jit_context_new_function
+#define gcc_jit_context_new_function_ptr_type fn_gcc_jit_context_new_function_ptr_type
+#define gcc_jit_context_new_global fn_gcc_jit_context_new_global
+#define gcc_jit_context_new_opaque_struct fn_gcc_jit_context_new_opaque_struct
+#define gcc_jit_context_new_param fn_gcc_jit_context_new_param
+#define gcc_jit_context_new_rvalue_from_int fn_gcc_jit_context_new_rvalue_from_int
+#define gcc_jit_context_new_rvalue_from_long fn_gcc_jit_context_new_rvalue_from_long
+#define gcc_jit_context_new_rvalue_from_ptr fn_gcc_jit_context_new_rvalue_from_ptr
+#define gcc_jit_context_new_struct_type fn_gcc_jit_context_new_struct_type
+#define gcc_jit_context_new_unary_op fn_gcc_jit_context_new_unary_op
+#define gcc_jit_context_new_union_type fn_gcc_jit_context_new_union_type
+#define gcc_jit_context_release fn_gcc_jit_context_release
+#define gcc_jit_context_set_bool_option fn_gcc_jit_context_set_bool_option
+#define gcc_jit_context_set_int_option fn_gcc_jit_context_set_int_option
+#define gcc_jit_context_set_logfile fn_gcc_jit_context_set_logfile
+#define gcc_jit_function_get_param fn_gcc_jit_function_get_param
+#define gcc_jit_function_new_block fn_gcc_jit_function_new_block
+#define gcc_jit_function_new_local fn_gcc_jit_function_new_local
+#define gcc_jit_lvalue_access_field fn_gcc_jit_lvalue_access_field
+#define gcc_jit_lvalue_as_rvalue fn_gcc_jit_lvalue_as_rvalue
+#define gcc_jit_lvalue_get_address fn_gcc_jit_lvalue_get_address
+#define gcc_jit_param_as_lvalue fn_gcc_jit_param_as_lvalue
+#define gcc_jit_param_as_rvalue fn_gcc_jit_param_as_rvalue
+#define gcc_jit_rvalue_access_field fn_gcc_jit_rvalue_access_field
+#define gcc_jit_rvalue_dereference fn_gcc_jit_rvalue_dereference
+#define gcc_jit_rvalue_dereference_field fn_gcc_jit_rvalue_dereference_field
+#define gcc_jit_rvalue_get_type fn_gcc_jit_rvalue_get_type
+#define gcc_jit_struct_as_type fn_gcc_jit_struct_as_type
+#define gcc_jit_struct_set_fields fn_gcc_jit_struct_set_fields
+#define gcc_jit_type_get_pointer fn_gcc_jit_type_get_pointer
+
+#endif
+
+static bool
+load_gccjit_if_necessary(bool mandatory)
+{
+#ifdef WINDOWSNT
+  if (!gccjit_initialized)
+    {
+      Lisp_Object status;
+      gccjit_initialized = init_gccjit_functions ();
+      status = gccjit_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
+    }
+
+  if (mandatory && !gccjit_initialized)
+    xsignal1(Qnative_compiler_error, build_string("libgccjit not found"));
+
+  return gccjit_initialized;
+#else
+  return true;
+#endif
+}
+
+\f
 /* C symbols emitted for the load relocation mechanism.  */
 #define CURRENT_THREAD_RELOC_SYM "current_thread_reloc"
 #define PURE_PTR_SYM "pure_ptr"
@@ -3328,6 +3666,8 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
        doc: /* Initialize the native compiler context. Return t on success.  */)
      (void)
 {
+  load_gccjit_if_necessary(true);
+
   if (comp.ctxt)
     {
       xsignal1 (Qnative_ice,
@@ -3474,6 +3814,8 @@ DEFUN ("comp--release-ctxt", Fcomp__release_ctxt, Scomp__release_ctxt,
        doc: /* Release the native compiler context.  */)
      (void)
 {
+  load_gccjit_if_necessary(true);
+
   if (comp.ctxt)
     gcc_jit_context_release (comp.ctxt);
 
@@ -3490,6 +3832,8 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
        doc: /* Compile as native code the current context to file.  */)
      (Lisp_Object base_name)
 {
+  load_gccjit_if_necessary(true);
+
   CHECK_STRING (base_name);
 
   gcc_jit_context_set_int_option (comp.ctxt,
@@ -3660,6 +4004,9 @@ maybe_defer_native_compilation (Lisp_Object function_name,
       fflush (f);
     }
 #endif
+  if (!load_gccjit_if_necessary(false))
+    return;
+
   if (!comp_deferred_compilation
       || noninteractive
       || !NILP (Vpurify_flag)
@@ -3928,6 +4275,15 @@ DEFUN ("native-elisp-load", Fnative_elisp_load, Snative_elisp_load, 1, 2, 0,
   return Qt;
 }
 
+DEFUN ("native-comp-available-p", Fnative_comp_available_p,
+       Snative_comp_available_p, 0, 0, 0,
+       doc: /* Returns t if native compilation of Lisp files is available in
+this instance of Emacs. */)
+  (void)
+{
+  return load_gccjit_if_necessary(false) ? Qt : Qnil;
+}
+
 \f
 void
 syms_of_comp (void)
@@ -4039,6 +4395,7 @@ syms_of_comp (void)
   defsubr (&Scomp__register_subr);
   defsubr (&Scomp__late_register_subr);
   defsubr (&Snative_elisp_load);
+  defsubr (&Snative_comp_available_p);
 
   staticpro (&comp.exported_funcs_h);
   comp.exported_funcs_h = Qnil;
diff --git a/src/w32fns.c b/src/w32fns.c
index e595b0285a..eeb73489dd 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10462,6 +10462,7 @@ syms_of_w32fns (void)
   DEFSYM (Qzlib, "zlib");
   DEFSYM (Qlcms2, "lcms2");
   DEFSYM (Qjson, "json");
+  DEFSYM (Qgccjit, "gccjit");
 
   Fput (Qundefined_color, Qerror_conditions,
 	pure_list (Qundefined_color, Qerror));
-- 
2.25.1.windows.1


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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-12 17:25                           ` Nicolas Bértolo
@ 2020-05-12 18:21                             ` Andrea Corallo
  2020-05-12 20:33                               ` Andrea Corallo
  0 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-12 18:21 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> libdl exists only in MinGW64, I think.
>
>> Why do you need it? is it because the code uses dlopen/dlsym
>> somewhere?
>
> The code uses `dynlib_open` and `dynlib_sym` which are implemented using libdl
> in Posix systems. The original libgccjit uses it to implement the
> `compile_to_memory` function that we do not use. The version of libgccjit I am
> using implements that feature using native Windows functions, so libdl is not
> necessary.
>
> I don't think we can remove it because that part of the code runs only when the
> platform is not Mingw, and in that case libdl is necessary.
>
>> I think it's good to #undef each symbol before defining it.
>
> Fixed in the new patch.

Hi Nicolas,

I think would be handy to have 'native-comp-available-p' always defined
also when compiling without the native compiler.  Similarly to what we
have for gnutls-available-p and libxml-available-p.

+static bool
+load_gccjit_if_necessary(bool mandatory)
                       ^^^
                    space here
+{
+#ifdef WINDOWSNT
+  if (!gccjit_initialized)
+    {
+      Lisp_Object status;
+      gccjit_initialized = init_gccjit_functions ();
+

Also I think gccjit_initialized should be declared be static inside
load_gccjit_if_necessary given should and is used only there.

Thanks

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-12 18:21                             ` Andrea Corallo
@ 2020-05-12 20:33                               ` Andrea Corallo
  2020-05-13 14:09                                 ` Nicolas Bértolo
  0 siblings, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-12 20:33 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Andrea Corallo <akrl@sdf.org> writes:

> Nicolas Bértolo <nicolasbertolo@gmail.com> writes:
>
>>> libdl exists only in MinGW64, I think.
>>
>>> Why do you need it? is it because the code uses dlopen/dlsym
>>> somewhere?
>>
>> The code uses `dynlib_open` and `dynlib_sym` which are implemented using libdl
>> in Posix systems. The original libgccjit uses it to implement the
>> `compile_to_memory` function that we do not use. The version of libgccjit I am
>> using implements that feature using native Windows functions, so libdl is not
>> necessary.
>>
>> I don't think we can remove it because that part of the code runs only when the
>> platform is not Mingw, and in that case libdl is necessary.
>>
>>> I think it's good to #undef each symbol before defining it.
>>
>> Fixed in the new patch.
>
> Hi Nicolas,
>
> I think would be handy to have 'native-comp-available-p' always defined
> also when compiling without the native compiler.  Similarly to what we
> have for gnutls-available-p and libxml-available-p.
>
> +static bool
> +load_gccjit_if_necessary(bool mandatory)
>                        ^^^
>                     space here
> +{
> +#ifdef WINDOWSNT
> +  if (!gccjit_initialized)
> +    {
> +      Lisp_Object status;
> +      gccjit_initialized = init_gccjit_functions ();
> +
>
> Also I think gccjit_initialized should be declared be static inside
> load_gccjit_if_necessary given should and is used only there.
>
> Thanks
>
>   Andrea

Also

+      gccjit_initialized = init_gccjit_functions ();
+      status = gccjit_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);

I think Qjson is a refuse from kill and yank.

Thanks

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-12  2:46                       ` Nicolas Bértolo
  2020-05-12 16:56                         ` Eli Zaretskii
@ 2020-05-13  3:59                         ` Richard Stallman
  2020-05-13 14:02                           ` Nicolas Bértolo
  2020-05-13 14:52                           ` Eli Zaretskii
  1 sibling, 2 replies; 71+ messages in thread
From: Richard Stallman @ 2020-05-13  3:59 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: eliz, akrl, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > The attached patch does implement dynamic loading of libgccjit in Windows.

Does Emacs already support comparable functionality on GNU/Linux?

-- 
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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
  1 sibling, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-13 14:02 UTC (permalink / raw)
  To: rms; +Cc: Eli Zaretskii, Andrea Corallo, emacs-devel

> Does Emacs already support comparable functionality on GNU/Linux?

It is not necessary unless we want users to be able to install an Emacs
compiled with native compilation enabled and have it run even if libgccjit
is not installed in their system.

In GNU/Linux once Emacs has been built with support for a library,
it requires it to be installed. Otherwise it fails with a message like this:

emacs: error while loading shared libraries: libpng16.so.16: cannot
open shared object file: No such file or directory

If I understand the code correctly, only the Windows build supports
dynamically testing for a library and disabling the features that depend
on it if it is not installed.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:48                                   ` Eli Zaretskii
  0 siblings, 2 replies; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-13 14:09 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2426 bytes --]

> I think Qjson is a refuse from kill and yank.

Heh, it turns out that fixing that uncovered a bug. We need to clear
Vlibrary_cache when loading a dump (or prevent it from being dumped) because
otherwise it will have a `gccjit` entry from when temacs loaded libgccjit and
then w32_delayed_load() will think that libgccjit is already loaded in the
process.

New version attached.

PS: Shall I open a bug where we can track this?

Nicolas

El mar., 12 may. 2020 a las 17:33, Andrea Corallo (<akrl@sdf.org>) escribió:
>
> Andrea Corallo <akrl@sdf.org> writes:
>
> > Nicolas Bértolo <nicolasbertolo@gmail.com> writes:
> >
> >>> libdl exists only in MinGW64, I think.
> >>
> >>> Why do you need it? is it because the code uses dlopen/dlsym
> >>> somewhere?
> >>
> >> The code uses `dynlib_open` and `dynlib_sym` which are implemented using libdl
> >> in Posix systems. The original libgccjit uses it to implement the
> >> `compile_to_memory` function that we do not use. The version of libgccjit I am
> >> using implements that feature using native Windows functions, so libdl is not
> >> necessary.
> >>
> >> I don't think we can remove it because that part of the code runs only when the
> >> platform is not Mingw, and in that case libdl is necessary.
> >>
> >>> I think it's good to #undef each symbol before defining it.
> >>
> >> Fixed in the new patch.
> >
> > Hi Nicolas,
> >
> > I think would be handy to have 'native-comp-available-p' always defined
> > also when compiling without the native compiler.  Similarly to what we
> > have for gnutls-available-p and libxml-available-p.
> >
> > +static bool
> > +load_gccjit_if_necessary(bool mandatory)
> >                        ^^^
> >                     space here
> > +{
> > +#ifdef WINDOWSNT
> > +  if (!gccjit_initialized)
> > +    {
> > +      Lisp_Object status;
> > +      gccjit_initialized = init_gccjit_functions ();
> > +
> >
> > Also I think gccjit_initialized should be declared be static inside
> > load_gccjit_if_necessary given should and is used only there.
> >
> > Thanks
> >
> >   Andrea
>
> Also
>
> +      gccjit_initialized = init_gccjit_functions ();
> +      status = gccjit_initialized ? Qt : Qnil;
> +      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
>
> I think Qjson is a refuse from kill and yank.
>
> Thanks
>
>   Andrea
>
> --
> akrl@sdf.org

[-- Attachment #2: Load-libgccjit-dynamically-in-Windows.patch --]
[-- Type: application/octet-stream, Size: 26329 bytes --]

From 5119898fbd347752c46b09deecb2365d6c7fce7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Mon, 11 May 2020 20:43:06 -0300
Subject: [PATCH] Load libgccjit dynamically in Windows.

* configure.ac: don't add linker flags if compiling on
Windows. Compile dynlib.c if modules or native compilation are
enabled. Always compile comp.c
* lisp/term/w32-win.el: Map 'gccjit to "libgccjit.dll" in
`dynamic-library-alist`.
* src/Makefile.in: Update comments. Update to handle changes in
configure.ac.
* src/comp.c: Add declarations of used libgccjit functions using
DEF_DLL_FN. Add calls to load_gccjit_if_necessary() where necessary.
Add `native-comp-available-p`
* src/comp.h: Remove Fnative_elisp_load. Add syms_of_comp().
* src/emacs.c (main): Always call syms_of_comp()
* src/w32.c (globals_of_w32): Clear Vlibrary_cache when starting
because the libraries loaded when dumping will not be loaded when
starting.
* src/w32fns.c: Add Qgccjit symbol.
---
 configure.ac         |  19 ++-
 lisp/term/w32-win.el |   3 +-
 src/Makefile.in      |   9 +-
 src/comp.c           | 374 ++++++++++++++++++++++++++++++++++++++++++-
 src/comp.h           |   6 +-
 src/emacs.c          |   2 -
 src/w32.c            |   4 +
 src/w32fns.c         |   1 +
 8 files changed, 398 insertions(+), 20 deletions(-)

diff --git a/configure.ac b/configure.ac
index 23b94cf6ca..ea0144f404 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3666,6 +3666,7 @@ AC_DEFUN
 LIBMODULES=
 HAVE_MODULES=no
 MODULES_OBJ=
+NEED_DYNLIB=no
 case $opsys in
   cygwin|mingw32) MODULES_SUFFIX=".dll" ;;
   darwin) MODULES_SUFFIX=".dylib" ;;
@@ -3701,7 +3702,8 @@ AC_DEFUN
 fi
 
 if test "${HAVE_MODULES}" = yes; then
-   MODULES_OBJ="dynlib.o emacs-module.o"
+   MODULES_OBJ="emacs-module.o"
+   NEED_DYNLIB=yes
    AC_DEFINE(HAVE_MODULES, 1, [Define to 1 if dynamic modules are enabled])
    AC_DEFINE_UNQUOTED(MODULES_SUFFIX, "$MODULES_SUFFIX",
      [System extension for dynamic libraries])
@@ -3785,7 +3787,6 @@ AC_DEFUN
 
 HAVE_NATIVE_COMP=no
 LIBGCCJIT_LIB=
-COMP_OBJ=
 if test "${with_nativecomp}" != "no"; then
     emacs_save_LIBS=$LIBS
     LIBS="-lgccjit"
@@ -3793,8 +3794,11 @@ AC_DEFUN
       [AC_LINK_IFELSE([libgccjit_smoke_test], [], [libgccjit_not_found])])
     LIBS=$emacs_save_LIBS
     HAVE_NATIVE_COMP=yes
-    LIBGCCJIT_LIB="-lgccjit -ldl"
-    COMP_OBJ="comp.o"
+    # mingw32 loads the library dynamically.
+    if test "${opsys}" != "mingw32"; then
+      LIBGCCJIT_LIB="-lgccjit -ldl"
+    fi
+    NEED_DYNLIB=yes
     AC_DEFINE(HAVE_NATIVE_COMP, 1, [Define to 1 if you have the libgccjit library (-lgccjit).])
 fi
 if test "${HAVE_NATIVE_COMP}" = yes && test "${HAVE_PDUMPER}" = no; then
@@ -3804,7 +3808,12 @@ AC_DEFUN
   [System extension for native compiled elisp])
 AC_SUBST(HAVE_NATIVE_COMP)
 AC_SUBST(LIBGCCJIT_LIB)
-AC_SUBST(COMP_OBJ)
+
+DYNLIB_OBJ=
+if test "${NEED_DYNLIB}" = yes; then
+  DYNLIB_OBJ="dynlib.o"
+fi
+AC_SUBST(DYNLIB_OBJ)
 
 ### Use -lpng if available, unless '--with-png=no'.
 HAVE_PNG=no
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index 5901e0295e..6b9716ca30 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -289,7 +289,8 @@ libgnutls-version
        '(libxml2 "libxml2-2.dll" "libxml2.dll")
        '(zlib "zlib1.dll" "libz-1.dll")
        '(lcms2 "liblcms2-2.dll")
-       '(json "libjansson-4.dll")))
+       '(json "libjansson-4.dll")
+       '(gccjit "libgccjit.dll")))
 
 ;;; multi-tty support
 (defvar w32-initialized nil
diff --git a/src/Makefile.in b/src/Makefile.in
index 63f909ae14..85709184da 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -241,7 +241,7 @@ LIBZ =
 
 ## system-specific libs for dynamic modules, else empty
 LIBMODULES = @LIBMODULES@
-## dynlib.o emacs-module.o if modules enabled, else empty
+## emacs-module.o if modules enabled, else empty
 MODULES_OBJ = @MODULES_OBJ@
 
 XRANDR_LIBS = @XRANDR_LIBS@
@@ -327,8 +327,9 @@ GMP_LIB =
 GMP_OBJ = @GMP_OBJ@
 
 LIBGCCJIT = @LIBGCCJIT_LIB@
-## dynlib.o comp.o if native compiler is enabled, otherwise empty.
-COMP_OBJ = @COMP_OBJ@
+
+## dynlib.o if necessary, else empty
+DYNLIB_OBJ = @DYNLIB_OBJ@
 
 RUN_TEMACS = ./temacs
 
@@ -418,7 +419,7 @@ base_obj =
 	cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \
 	alloc.o pdumper.o data.o doc.o editfns.o callint.o \
 	eval.o floatfns.o fns.o font.o print.o lread.o $(MODULES_OBJ) \
-	syntax.o $(UNEXEC_OBJ) bytecode.o $(COMP_OBJ) \
+	syntax.o $(UNEXEC_OBJ) bytecode.o comp.o $(DYNLIB_OBJ) \
 	process.o gnutls.o callproc.o \
 	region-cache.o sound.o timefns.o atimer.o \
 	doprnt.o intervals.o textprop.o composite.o xml.o lcms.o $(NOTIFY_OBJ) \
diff --git a/src/comp.c b/src/comp.c
index 69525acfc0..b43d3eddb3 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -20,6 +20,8 @@
 
 #include <config.h>
 
+#include "lisp.h"
+
 #ifdef HAVE_NATIVE_COMP
 
 #include <setjmp.h>
@@ -28,7 +30,6 @@
 #include <signal.h>
 #include <libgccjit.h>
 
-#include "lisp.h"
 #include "puresize.h"
 #include "window.h"
 #include "dynlib.h"
@@ -36,6 +37,347 @@
 #include "blockinput.h"
 #include "sha512.h"
 
+\f
+/********************************/
+/* Dynamic loading of libgccjit */
+/********************************/
+
+#ifdef WINDOWSNT
+# include "w32common.h"
+
+#undef gcc_jit_block_add_assignment
+#undef gcc_jit_block_add_comment
+#undef gcc_jit_block_add_eval
+#undef gcc_jit_block_end_with_conditional
+#undef gcc_jit_block_end_with_jump
+#undef gcc_jit_block_end_with_return
+#undef gcc_jit_block_end_with_void_return
+#undef gcc_jit_context_acquire
+#undef gcc_jit_context_compile_to_file
+#undef gcc_jit_context_dump_reproducer_to_file
+#undef gcc_jit_context_dump_to_file
+#undef gcc_jit_context_get_builtin_function
+#undef gcc_jit_context_get_first_error
+#undef gcc_jit_context_get_int_type
+#undef gcc_jit_context_get_type
+#undef gcc_jit_context_new_array_access
+#undef gcc_jit_context_new_array_type
+#undef gcc_jit_context_new_binary_op
+#undef gcc_jit_context_new_call
+#undef gcc_jit_context_new_call_through_ptr
+#undef gcc_jit_context_new_comparison
+#undef gcc_jit_context_new_field
+#undef gcc_jit_context_new_function
+#undef gcc_jit_context_new_function_ptr_type
+#undef gcc_jit_context_new_global
+#undef gcc_jit_context_new_opaque_struct
+#undef gcc_jit_context_new_param
+#undef gcc_jit_context_new_rvalue_from_int
+#undef gcc_jit_context_new_rvalue_from_long
+#undef gcc_jit_context_new_rvalue_from_ptr
+#undef gcc_jit_context_new_struct_type
+#undef gcc_jit_context_new_unary_op
+#undef gcc_jit_context_new_union_type
+#undef gcc_jit_context_release
+#undef gcc_jit_context_set_bool_option
+#undef gcc_jit_context_set_int_option
+#undef gcc_jit_context_set_logfile
+#undef gcc_jit_function_get_param
+#undef gcc_jit_function_new_block
+#undef gcc_jit_function_new_local
+#undef gcc_jit_lvalue_access_field
+#undef gcc_jit_lvalue_as_rvalue
+#undef gcc_jit_lvalue_get_address
+#undef gcc_jit_param_as_lvalue
+#undef gcc_jit_param_as_rvalue
+#undef gcc_jit_rvalue_access_field
+#undef gcc_jit_rvalue_dereference
+#undef gcc_jit_rvalue_dereference_field
+#undef gcc_jit_rvalue_get_type
+#undef gcc_jit_struct_as_type
+#undef gcc_jit_struct_set_fields
+#undef gcc_jit_type_get_pointer
+
+/* In alphabetical order */
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_int,
+            (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, int value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_lvalue_as_rvalue,
+            (gcc_jit_lvalue *lvalue));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_rvalue_access_field,
+            (gcc_jit_rvalue *struct_or_union, gcc_jit_location *loc,
+             gcc_jit_field *field));
+DEF_DLL_FN (void, gcc_jit_block_add_comment,
+            (gcc_jit_block *block, gcc_jit_location *loc, const char *text));
+DEF_DLL_FN (void, gcc_jit_context_release, (gcc_jit_context *ctxt));
+DEF_DLL_FN (const char *, gcc_jit_context_get_first_error,
+            (gcc_jit_context *ctxt));
+DEF_DLL_FN (gcc_jit_block *, gcc_jit_function_new_block,
+            (gcc_jit_function *func, const char *name));
+DEF_DLL_FN (gcc_jit_context *, gcc_jit_context_acquire, (void));
+DEF_DLL_FN (gcc_jit_field *, gcc_jit_context_new_field,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_function *, gcc_jit_context_get_builtin_function,
+            (gcc_jit_context *ctxt, const char *name));
+DEF_DLL_FN (gcc_jit_function *, gcc_jit_context_new_function,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_function_kind kind, gcc_jit_type *return_type,
+             const char *name, int num_params, gcc_jit_param **params,
+             int is_variadic));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_context_new_array_access,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *ptr,
+             gcc_jit_rvalue *index));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_context_new_global,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_global_kind kind, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_function_new_local,
+            (gcc_jit_function *func, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_lvalue_access_field,
+            (gcc_jit_lvalue *struct_or_union, gcc_jit_location *loc,
+             gcc_jit_field *field));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_param_as_lvalue, (gcc_jit_param *param));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_rvalue_dereference,
+            (gcc_jit_rvalue *rvalue, gcc_jit_location *loc));
+DEF_DLL_FN (gcc_jit_lvalue *, gcc_jit_rvalue_dereference_field,
+            (gcc_jit_rvalue *ptr, gcc_jit_location *loc, gcc_jit_field *field));
+DEF_DLL_FN (gcc_jit_param *, gcc_jit_context_new_param,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type,
+             const char *name));
+DEF_DLL_FN (gcc_jit_param *, gcc_jit_function_get_param,
+            (gcc_jit_function *func, int index));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_binary_op,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_binary_op op, gcc_jit_type *result_type,
+             gcc_jit_rvalue *a, gcc_jit_rvalue *b));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_function *func, int numargs , gcc_jit_rvalue **args));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call_through_ptr,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_rvalue *fn_ptr, int numargs, gcc_jit_rvalue **args));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_comparison,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_comparison op, gcc_jit_rvalue *a, gcc_jit_rvalue *b));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_long,
+            (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, long value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_ptr,
+            (gcc_jit_context *ctxt, gcc_jit_type *pointer_type, void *value));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_unary_op,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             enum gcc_jit_unary_op op, gcc_jit_type *result_type,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_lvalue_get_address,
+            (gcc_jit_lvalue *lvalue, gcc_jit_location *loc));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_param_as_rvalue, (gcc_jit_param *param));
+DEF_DLL_FN (gcc_jit_struct *, gcc_jit_context_new_opaque_struct,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name));
+DEF_DLL_FN (gcc_jit_struct *, gcc_jit_context_new_struct_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name,
+             int num_fields, gcc_jit_field **fields));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_get_int_type,
+            (gcc_jit_context *ctxt, int num_bytes, int is_signed));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_get_type,
+            (gcc_jit_context *ctxt, enum gcc_jit_types type_));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_array_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_type *element_type, int num_elements));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_function_ptr_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_type *return_type, int num_params,
+             gcc_jit_type **param_types, int is_variadic));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_context_new_union_type,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc, const char *name,
+             int num_fields, gcc_jit_field **fields));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_rvalue_get_type, (gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_struct_as_type,
+            (gcc_jit_struct *struct_type));
+DEF_DLL_FN (gcc_jit_type *, gcc_jit_type_get_pointer, (gcc_jit_type *type));
+DEF_DLL_FN (void, gcc_jit_block_add_assignment,
+            (gcc_jit_block *block, gcc_jit_location *loc, gcc_jit_lvalue *lvalue,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_add_eval,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_end_with_conditional,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *boolval, gcc_jit_block *on_true,
+             gcc_jit_block *on_false));
+DEF_DLL_FN (void, gcc_jit_block_end_with_jump,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_block *target));
+DEF_DLL_FN (void, gcc_jit_block_end_with_return,
+            (gcc_jit_block *block, gcc_jit_location *loc,
+             gcc_jit_rvalue *rvalue));
+DEF_DLL_FN (void, gcc_jit_block_end_with_void_return,
+            (gcc_jit_block *block, gcc_jit_location *loc));
+DEF_DLL_FN (void, gcc_jit_context_compile_to_file,
+            (gcc_jit_context *ctxt, enum gcc_jit_output_kind output_kind,
+             const char *output_path));
+DEF_DLL_FN (void, gcc_jit_context_dump_reproducer_to_file,
+            (gcc_jit_context *ctxt, const char *path));
+DEF_DLL_FN (void, gcc_jit_context_dump_to_file,
+            (gcc_jit_context *ctxt, const char *path, int update_locations));
+DEF_DLL_FN (void, gcc_jit_context_set_bool_option,
+            (gcc_jit_context *ctxt, enum gcc_jit_bool_option opt, int value));
+DEF_DLL_FN (void, gcc_jit_context_set_int_option,
+            (gcc_jit_context *ctxt, enum gcc_jit_int_option opt, int value));
+DEF_DLL_FN (void, gcc_jit_context_set_logfile,
+            (gcc_jit_context *ctxt, FILE *logfile, int flags, int verbosity));
+DEF_DLL_FN (void, gcc_jit_struct_set_fields,
+            (gcc_jit_struct *struct_type, gcc_jit_location *loc, int num_fields,
+             gcc_jit_field **fields));
+
+static bool
+init_gccjit_functions (void)
+{
+  HMODULE library;
+
+  if (!(library = w32_delayed_load (Qgccjit)))
+    {
+      return false;
+    }
+
+  /* In alphabetical order */
+  LOAD_DLL_FN(library, gcc_jit_block_add_assignment);
+  LOAD_DLL_FN(library, gcc_jit_block_add_comment);
+  LOAD_DLL_FN(library, gcc_jit_block_add_eval);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_conditional);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_jump);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_return);
+  LOAD_DLL_FN(library, gcc_jit_block_end_with_void_return);
+  LOAD_DLL_FN(library, gcc_jit_context_acquire);
+  LOAD_DLL_FN(library, gcc_jit_context_compile_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_dump_reproducer_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_dump_to_file);
+  LOAD_DLL_FN(library, gcc_jit_context_get_builtin_function);
+  LOAD_DLL_FN(library, gcc_jit_context_get_first_error);
+  LOAD_DLL_FN(library, gcc_jit_context_get_int_type);
+  LOAD_DLL_FN(library, gcc_jit_context_get_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_array_access);
+  LOAD_DLL_FN(library, gcc_jit_context_new_array_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_binary_op);
+  LOAD_DLL_FN(library, gcc_jit_context_new_call);
+  LOAD_DLL_FN(library, gcc_jit_context_new_call_through_ptr);
+  LOAD_DLL_FN(library, gcc_jit_context_new_comparison);
+  LOAD_DLL_FN(library, gcc_jit_context_new_field);
+  LOAD_DLL_FN(library, gcc_jit_context_new_function);
+  LOAD_DLL_FN(library, gcc_jit_context_new_function_ptr_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_global);
+  LOAD_DLL_FN(library, gcc_jit_context_new_opaque_struct);
+  LOAD_DLL_FN(library, gcc_jit_context_new_param);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_int);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_long);
+  LOAD_DLL_FN(library, gcc_jit_context_new_rvalue_from_ptr);
+  LOAD_DLL_FN(library, gcc_jit_context_new_struct_type);
+  LOAD_DLL_FN(library, gcc_jit_context_new_unary_op);
+  LOAD_DLL_FN(library, gcc_jit_context_new_union_type);
+  LOAD_DLL_FN(library, gcc_jit_context_release);
+  LOAD_DLL_FN(library, gcc_jit_context_set_bool_option);
+  LOAD_DLL_FN(library, gcc_jit_context_set_int_option);
+  LOAD_DLL_FN(library, gcc_jit_context_set_logfile);
+  LOAD_DLL_FN(library, gcc_jit_function_get_param);
+  LOAD_DLL_FN(library, gcc_jit_function_new_block);
+  LOAD_DLL_FN(library, gcc_jit_function_new_local);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_access_field);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_as_rvalue);
+  LOAD_DLL_FN(library, gcc_jit_lvalue_get_address);
+  LOAD_DLL_FN(library, gcc_jit_param_as_lvalue);
+  LOAD_DLL_FN(library, gcc_jit_param_as_rvalue);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_access_field);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_dereference);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_dereference_field);
+  LOAD_DLL_FN(library, gcc_jit_rvalue_get_type);
+  LOAD_DLL_FN(library, gcc_jit_struct_as_type);
+  LOAD_DLL_FN(library, gcc_jit_struct_set_fields);
+  LOAD_DLL_FN(library, gcc_jit_type_get_pointer);
+
+  return true;
+}
+
+/* In alphabetical order */
+#define gcc_jit_block_add_assignment fn_gcc_jit_block_add_assignment
+#define gcc_jit_block_add_comment fn_gcc_jit_block_add_comment
+#define gcc_jit_block_add_eval fn_gcc_jit_block_add_eval
+#define gcc_jit_block_end_with_conditional fn_gcc_jit_block_end_with_conditional
+#define gcc_jit_block_end_with_jump fn_gcc_jit_block_end_with_jump
+#define gcc_jit_block_end_with_return fn_gcc_jit_block_end_with_return
+#define gcc_jit_block_end_with_void_return fn_gcc_jit_block_end_with_void_return
+#define gcc_jit_context_acquire fn_gcc_jit_context_acquire
+#define gcc_jit_context_compile_to_file fn_gcc_jit_context_compile_to_file
+#define gcc_jit_context_dump_reproducer_to_file fn_gcc_jit_context_dump_reproducer_to_file
+#define gcc_jit_context_dump_to_file fn_gcc_jit_context_dump_to_file
+#define gcc_jit_context_get_builtin_function fn_gcc_jit_context_get_builtin_function
+#define gcc_jit_context_get_first_error fn_gcc_jit_context_get_first_error
+#define gcc_jit_context_get_int_type fn_gcc_jit_context_get_int_type
+#define gcc_jit_context_get_type fn_gcc_jit_context_get_type
+#define gcc_jit_context_new_array_access fn_gcc_jit_context_new_array_access
+#define gcc_jit_context_new_array_type fn_gcc_jit_context_new_array_type
+#define gcc_jit_context_new_binary_op fn_gcc_jit_context_new_binary_op
+#define gcc_jit_context_new_call fn_gcc_jit_context_new_call
+#define gcc_jit_context_new_call_through_ptr fn_gcc_jit_context_new_call_through_ptr
+#define gcc_jit_context_new_comparison fn_gcc_jit_context_new_comparison
+#define gcc_jit_context_new_field fn_gcc_jit_context_new_field
+#define gcc_jit_context_new_function fn_gcc_jit_context_new_function
+#define gcc_jit_context_new_function_ptr_type fn_gcc_jit_context_new_function_ptr_type
+#define gcc_jit_context_new_global fn_gcc_jit_context_new_global
+#define gcc_jit_context_new_opaque_struct fn_gcc_jit_context_new_opaque_struct
+#define gcc_jit_context_new_param fn_gcc_jit_context_new_param
+#define gcc_jit_context_new_rvalue_from_int fn_gcc_jit_context_new_rvalue_from_int
+#define gcc_jit_context_new_rvalue_from_long fn_gcc_jit_context_new_rvalue_from_long
+#define gcc_jit_context_new_rvalue_from_ptr fn_gcc_jit_context_new_rvalue_from_ptr
+#define gcc_jit_context_new_struct_type fn_gcc_jit_context_new_struct_type
+#define gcc_jit_context_new_unary_op fn_gcc_jit_context_new_unary_op
+#define gcc_jit_context_new_union_type fn_gcc_jit_context_new_union_type
+#define gcc_jit_context_release fn_gcc_jit_context_release
+#define gcc_jit_context_set_bool_option fn_gcc_jit_context_set_bool_option
+#define gcc_jit_context_set_int_option fn_gcc_jit_context_set_int_option
+#define gcc_jit_context_set_logfile fn_gcc_jit_context_set_logfile
+#define gcc_jit_function_get_param fn_gcc_jit_function_get_param
+#define gcc_jit_function_new_block fn_gcc_jit_function_new_block
+#define gcc_jit_function_new_local fn_gcc_jit_function_new_local
+#define gcc_jit_lvalue_access_field fn_gcc_jit_lvalue_access_field
+#define gcc_jit_lvalue_as_rvalue fn_gcc_jit_lvalue_as_rvalue
+#define gcc_jit_lvalue_get_address fn_gcc_jit_lvalue_get_address
+#define gcc_jit_param_as_lvalue fn_gcc_jit_param_as_lvalue
+#define gcc_jit_param_as_rvalue fn_gcc_jit_param_as_rvalue
+#define gcc_jit_rvalue_access_field fn_gcc_jit_rvalue_access_field
+#define gcc_jit_rvalue_dereference fn_gcc_jit_rvalue_dereference
+#define gcc_jit_rvalue_dereference_field fn_gcc_jit_rvalue_dereference_field
+#define gcc_jit_rvalue_get_type fn_gcc_jit_rvalue_get_type
+#define gcc_jit_struct_as_type fn_gcc_jit_struct_as_type
+#define gcc_jit_struct_set_fields fn_gcc_jit_struct_set_fields
+#define gcc_jit_type_get_pointer fn_gcc_jit_type_get_pointer
+
+#endif
+
+static bool
+load_gccjit_if_necessary (bool mandatory)
+{
+#ifdef WINDOWSNT
+  static bool tried_to_initialize_once;
+  static bool gccjit_initialized;
+
+  if (!tried_to_initialize_once)
+    {
+      tried_to_initialize_once = true;
+      Lisp_Object status;
+      gccjit_initialized = init_gccjit_functions ();
+      status = gccjit_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qgccjit, status), Vlibrary_cache);
+    }
+
+  if (mandatory && !gccjit_initialized)
+    xsignal1(Qnative_compiler_error, build_string("libgccjit not found"));
+
+  return gccjit_initialized;
+#else
+  return true;
+#endif
+}
+
+\f
 /* C symbols emitted for the load relocation mechanism.  */
 #define CURRENT_THREAD_RELOC_SYM "current_thread_reloc"
 #define PURE_PTR_SYM "pure_ptr"
@@ -3328,6 +3670,8 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
        doc: /* Initialize the native compiler context. Return t on success.  */)
      (void)
 {
+  load_gccjit_if_necessary(true);
+
   if (comp.ctxt)
     {
       xsignal1 (Qnative_ice,
@@ -3474,6 +3818,8 @@ DEFUN ("comp--release-ctxt", Fcomp__release_ctxt, Scomp__release_ctxt,
        doc: /* Release the native compiler context.  */)
      (void)
 {
+  load_gccjit_if_necessary(true);
+
   if (comp.ctxt)
     gcc_jit_context_release (comp.ctxt);
 
@@ -3490,6 +3836,8 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
        doc: /* Compile as native code the current context to file.  */)
      (Lisp_Object base_name)
 {
+  load_gccjit_if_necessary(true);
+
   CHECK_STRING (base_name);
 
   gcc_jit_context_set_int_option (comp.ctxt,
@@ -3660,6 +4008,9 @@ maybe_defer_native_compilation (Lisp_Object function_name,
       fflush (f);
     }
 #endif
+  if (!load_gccjit_if_necessary(false))
+    return;
+
   if (!comp_deferred_compilation
       || noninteractive
       || !NILP (Vpurify_flag)
@@ -3928,10 +4279,26 @@ DEFUN ("native-elisp-load", Fnative_elisp_load, Snative_elisp_load, 1, 2, 0,
   return Qt;
 }
 
+#endif /* HAVE_NATIVE_COMP */
+
+DEFUN ("native-comp-available-p", Fnative_comp_available_p,
+       Snative_comp_available_p, 0, 0, 0,
+       doc: /* Returns t if native compilation of Lisp files is available in
+this instance of Emacs. */)
+  (void)
+{
+#ifdef HAVE_NATIVE_COMP
+  return load_gccjit_if_necessary(false) ? Qt : Qnil;
+#else
+  return Qnil;
+#endif
+}
+
 \f
 void
 syms_of_comp (void)
 {
+#ifdef HAVE_NATIVE_COMP
   /* Compiler control customizes.  */
   DEFVAR_BOOL ("comp-deferred-compilation", comp_deferred_compilation,
 	       doc: /* If t compile asyncronously every .elc file loaded.  */);
@@ -4073,6 +4440,7 @@ syms_of_comp (void)
 	       doc: /* Hash table symbol-name -> function-value.  For
 		       internal use during  */);
   Vcomp_deferred_pending_h = CALLN (Fmake_hash_table, QCtest, Qeq);
-}
+#endif
 
-#endif /* HAVE_NATIVE_COMP */
+  defsubr (&Snative_comp_available_p);
+}
diff --git a/src/comp.h b/src/comp.h
index cbdcaccd5f..e6ab32ff8e 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -82,11 +82,7 @@ maybe_defer_native_compilation (Lisp_Object function_name,
 				Lisp_Object definition)
 {}
 
-static inline Lisp_Object
-Fnative_elisp_load (Lisp_Object file, Lisp_Object late_load)
-{
-  eassume (false);
-}
+extern void syms_of_comp (void);
 
 #endif
 
diff --git a/src/emacs.c b/src/emacs.c
index 2c90825742..e75cb58834 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1606,10 +1606,8 @@ main (int argc, char **argv)
   init_json ();
 #endif
 
-#ifdef HAVE_NATIVE_COMP
   if (!initialized)
     syms_of_comp ();
-#endif
 
   no_loadup
     = argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args);
diff --git a/src/w32.c b/src/w32.c
index a8c763f23e..ceb8f7ef66 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -10586,6 +10586,10 @@ globals_of_w32 (void)
 #endif
 
   w32_crypto_hprov = (HCRYPTPROV)0;
+
+  /* We need to forget about libraries that were loaded during the
+     dumping process (e.g. libgccjit) */
+  Vlibrary_cache = Qnil;
 }
 
 /* For make-serial-process  */
diff --git a/src/w32fns.c b/src/w32fns.c
index e595b0285a..eeb73489dd 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10462,6 +10462,7 @@ syms_of_w32fns (void)
   DEFSYM (Qzlib, "zlib");
   DEFSYM (Qlcms2, "lcms2");
   DEFSYM (Qjson, "json");
+  DEFSYM (Qgccjit, "gccjit");
 
   Fput (Qundefined_color, Qerror_conditions,
 	pure_list (Qundefined_color, Qerror));
-- 
2.25.1.windows.1


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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  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:48                                   ` Eli Zaretskii
  1 sibling, 1 reply; 71+ messages in thread
From: Andrea Corallo @ 2020-05-13 14:31 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> I think Qjson is a refuse from kill and yank.
>
> Heh, it turns out that fixing that uncovered a bug. We need to clear
> Vlibrary_cache when loading a dump (or prevent it from being dumped) because
> otherwise it will have a `gccjit` entry from when temacs loaded libgccjit and
> then w32_delayed_load() will think that libgccjit is already loaded in the
> process.
>
> New version attached.

Hi Nicolas, thanks

+  static bool tried_to_initialize_once;
+  static bool gccjit_initialized;
+
+  if (!tried_to_initialize_once)
+    {
+      tried_to_initialize_once = true;
+      Lisp_Object status;
+      gccjit_initialized = init_gccjit_functions ();
+      status = gccjit_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qgccjit, status), Vlibrary_cache);
+    }
+
+  if (mandatory && !gccjit_initialized)
+    xsignal1(Qnative_compiler_error, build_string("libgccjit not found"));
+
+  return gccjit_initialized;

I see you have introduced tried_to_initialize_once.  I'm not sure this
is convenient because a user could, after a failed attempt, fix his
environment to load libgccjit and do it without restarting Emacs.

Is there some specific reason for this choice?

> PS: Shall I open a bug where we can track this?

If affect all Emacs I think is the right thing to do.

> Nicolas

Thanks!

  Andrea
-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-13  3:59                         ` Richard Stallman
  2020-05-13 14:02                           ` Nicolas Bértolo
@ 2020-05-13 14:52                           ` Eli Zaretskii
  1 sibling, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-13 14:52 UTC (permalink / raw)
  To: rms; +Cc: nicolasbertolo, emacs-devel, akrl

> From: Richard Stallman <rms@gnu.org>
> Date: Tue, 12 May 2020 23:59:24 -0400
> Cc: eliz@gnu.org, akrl@sdf.org, emacs-devel@gnu.org
> 
>   > The attached patch does implement dynamic loading of libgccjit in Windows.
> 
> Does Emacs already support comparable functionality on GNU/Linux?

Yes, we have a branch in Git which currently supports only Posix
systems.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-13 14:31                                   ` Andrea Corallo
@ 2020-05-13 15:00                                     ` Nicolas Bértolo
  2020-05-13 15:17                                       ` Andrea Corallo
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas Bértolo @ 2020-05-13 15:00 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Eli Zaretskii, emacs-devel

> Is there some specific reason for this choice?

The problem is that w32_delayed_load will return a NULL handle if
Fassq (library_id, Vlibrary_cache)) returns non-nil. The only way to make this
work is to avoid adding gccjit to Vlibrary_cache if the initialization failed.
This would be different from what the code for loading other libraries does.
I don't know if it is worth it to introduce this difference.

Another issue is that this code is called from maybe_defer_native_compilation().
A version that searches for libgccjit all the time would call LoadLibrary() and
perform an expensive search throughout the filesystem everytime `defalias` is
called.

>> PS: Shall I open a bug where we can track this?
> If affect all Emacs I think is the right thing to do.

I referred to opening a bug report for the work related to porting
feature/native-comp to Windows.

El mié., 13 may. 2020 a las 11:31, Andrea Corallo (<akrl@sdf.org>) escribió:
>
> Nicolas Bértolo <nicolasbertolo@gmail.com> writes:
>
> >> I think Qjson is a refuse from kill and yank.
> >
> > Heh, it turns out that fixing that uncovered a bug. We need to clear
> > Vlibrary_cache when loading a dump (or prevent it from being dumped) because
> > otherwise it will have a `gccjit` entry from when temacs loaded libgccjit and
> > then w32_delayed_load() will think that libgccjit is already loaded in the
> > process.
> >
> > New version attached.
>
> Hi Nicolas, thanks
>
> +  static bool tried_to_initialize_once;
> +  static bool gccjit_initialized;
> +
> +  if (!tried_to_initialize_once)
> +    {
> +      tried_to_initialize_once = true;
> +      Lisp_Object status;
> +      gccjit_initialized = init_gccjit_functions ();
> +      status = gccjit_initialized ? Qt : Qnil;
> +      Vlibrary_cache = Fcons (Fcons (Qgccjit, status), Vlibrary_cache);
> +    }
> +
> +  if (mandatory && !gccjit_initialized)
> +    xsignal1(Qnative_compiler_error, build_string("libgccjit not found"));
> +
> +  return gccjit_initialized;
>
> I see you have introduced tried_to_initialize_once.  I'm not sure this
> is convenient because a user could, after a failed attempt, fix his
> environment to load libgccjit and do it without restarting Emacs.
>
> Is there some specific reason for this choice?
>
> > PS: Shall I open a bug where we can track this?
>
> If affect all Emacs I think is the right thing to do.
>
> > Nicolas
>
> Thanks!
>
>   Andrea
> --
> akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-13 15:00                                     ` Nicolas Bértolo
@ 2020-05-13 15:17                                       ` Andrea Corallo
  0 siblings, 0 replies; 71+ messages in thread
From: Andrea Corallo @ 2020-05-13 15:17 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: Eli Zaretskii, emacs-devel

Nicolas Bértolo <nicolasbertolo@gmail.com> writes:

>> Is there some specific reason for this choice?
>
> The problem is that w32_delayed_load will return a NULL handle if
> Fassq (library_id, Vlibrary_cache)) returns non-nil. The only way to make this
> work is to avoid adding gccjit to Vlibrary_cache if the initialization failed.
> This would be different from what the code for loading other libraries does.
> I don't know if it is worth it to introduce this difference.
>
> Another issue is that this code is called from maybe_defer_native_compilation().
> A version that searches for libgccjit all the time would call LoadLibrary() and
> perform an expensive search throughout the filesystem everytime `defalias` is
> called.

Uh I see!  Yes then I think this solution is okay if the behavior is
acceptable to win users.  Otherwise would be necessary a new way for
maybe_defer_native_compilation to check only for the last known state
without triggering a new search.

>>> PS: Shall I open a bug where we can track this?
>> If affect all Emacs I think is the right thing to do.
>
> I referred to opening a bug report for the work related to porting
> feature/native-comp to Windows.

I think is a good idea, Eli will suggest.

Thanks

  Andrea

-- 
akrl@sdf.org



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-13 14:02                           ` Nicolas Bértolo
@ 2020-05-13 15:23                             ` Eli Zaretskii
  0 siblings, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-13 15:23 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, rms, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Wed, 13 May 2020 11:02:33 -0300
> Cc: Eli Zaretskii <eliz@gnu.org>, Andrea Corallo <akrl@sdf.org>,
>  emacs-devel@gnu.org
> 
> > Does Emacs already support comparable functionality on GNU/Linux?
> 
> It is not necessary unless we want users to be able to install an Emacs
> compiled with native compilation enabled and have it run even if libgccjit
> is not installed in their system.

I think Richard was asking about libgccjit in general, not about
loading a shared library at run time.



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

* Re: [PATCH] [WIP] Port feature/native-comp to Windows.
  2020-05-13 14:09                                 ` Nicolas Bértolo
  2020-05-13 14:31                                   ` Andrea Corallo
@ 2020-05-13 15:48                                   ` Eli Zaretskii
  1 sibling, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-05-13 15:48 UTC (permalink / raw)
  To: Nicolas Bértolo; +Cc: emacs-devel, akrl

> From: Nicolas Bértolo <nicolasbertolo@gmail.com>
> Date: Wed, 13 May 2020 11:09:42 -0300
> Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org
> 
> PS: Shall I open a bug where we can track this?

It would be better, yes.

Thanks.



^ permalink raw reply	[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).