* [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 = ¤t_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-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 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: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 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: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: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 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: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: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: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-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-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 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 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: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
* 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-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 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-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: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 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-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 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: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 ` 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 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 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-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-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 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: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
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).