all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#41615: [feature/native-comp] Dump prettier C code.
@ 2020-05-30 15:08 Nicolas Bértolo
  2020-05-30 22:20 ` Nicolas Bértolo
  0 siblings, 1 reply; 18+ messages in thread
From: Nicolas Bértolo @ 2020-05-30 15:08 UTC (permalink / raw)
  To: 41615


[-- Attachment #1.1: Type: text/plain, Size: 307 bytes --]

I found two ways to improve the looks of the dumped code.

- Define static data using string literals of at most 200 bytes. This
reduces
  the line count and lets us understand what the static object consists of.

- Define casts using functions. These functions should get always get
inlined.

Thanks, Nico

[-- Attachment #1.2: Type: text/html, Size: 402 bytes --]

[-- Attachment #2: 0002-Define-casts-using-functions.patch --]
[-- Type: application/octet-stream, Size: 11727 bytes --]

From 8ed42509e55e78e67d9989e4c119c1b8f6bea463 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Wed, 20 May 2020 00:46:30 -0300
Subject: [PATCH 2/2] Define casts using functions.

This is to dump prettier C files.
This does not affect compilation times in my tests.

* src/comp.c: Define a 15x15 cast matrix. Use it in emit_coerce().
---
 src/comp.c | 278 ++++++++++++++++++++---------------------------------
 1 file changed, 104 insertions(+), 174 deletions(-)

diff --git a/src/comp.c b/src/comp.c
index 3f4b3e03b7..f5f6b1baca 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -454,6 +454,8 @@ #define F_RELOC_MAX_SIZE 1500
 
 static f_reloc_t freloc;
 
+#define NUM_CAST_TYPES 15
+
 /* C side of the compiler context.  */
 
 typedef struct {
@@ -512,21 +514,9 @@ #define F_RELOC_MAX_SIZE 1500
   /* libgccjit has really limited support for casting therefore this union will
      be used for the scope.  */
   gcc_jit_type *cast_union_type;
-  gcc_jit_field *cast_union_as_ll;
-  gcc_jit_field *cast_union_as_ull;
-  gcc_jit_field *cast_union_as_l;
-  gcc_jit_field *cast_union_as_ul;
-  gcc_jit_field *cast_union_as_u;
-  gcc_jit_field *cast_union_as_i;
-  gcc_jit_field *cast_union_as_b;
-  gcc_jit_field *cast_union_as_uintptr;
-  gcc_jit_field *cast_union_as_ptrdiff;
-  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_word;
-  gcc_jit_field *cast_union_as_lisp_word_tag;
-  gcc_jit_field *cast_union_as_lisp_obj_ptr;
+  gcc_jit_function *cast_functions_from_to[NUM_CAST_TYPES][NUM_CAST_TYPES];
+  gcc_jit_type *cast_types[NUM_CAST_TYPES];
+  gcc_jit_field *cast_union_fields[NUM_CAST_TYPES];
   gcc_jit_function *func; /* Current function being compiled.  */
   bool func_has_non_local; /* From comp-func has-non-local slot.  */
   gcc_jit_lvalue **f_frame; /* "Floating" frame for the current function.  */
@@ -684,47 +674,6 @@ bcall0 (Lisp_Object f)
   Ffuncall (1, &f);
 }
 
-static gcc_jit_field *
-type_to_cast_field (gcc_jit_type *type)
-{
-  gcc_jit_field *field;
-
-  if (type == comp.long_long_type)
-    field = comp.cast_union_as_ll;
-  else if (type == comp.unsigned_long_long_type)
-    field = comp.cast_union_as_ull;
-  else if (type == comp.long_type)
-    field = comp.cast_union_as_l;
-  else if (type == comp.unsigned_long_type)
-    field = comp.cast_union_as_ul;
-  else if (type == comp.unsigned_type)
-    field = comp.cast_union_as_u;
-  else if (type == comp.int_type)
-    field = comp.cast_union_as_i;
-  else if (type == comp.bool_type)
-    field = comp.cast_union_as_b;
-  else if (type == comp.void_ptr_type)
-    field = comp.cast_union_as_v_p;
-  else if (type == comp.uintptr_type)
-    field = comp.cast_union_as_uintptr;
-  else if (type == comp.ptrdiff_type)
-    field = comp.cast_union_as_ptrdiff;
-  else if (type == comp.char_ptr_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_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
-    xsignal1 (Qnative_ice, build_string ("unsupported cast"));
-
-  return field;
-}
-
 static gcc_jit_block *
 retrive_block (Lisp_Object block_name)
 {
@@ -985,11 +934,19 @@ emit_cond_jump (gcc_jit_rvalue *test,
 
 }
 
+static int
+type_to_cast_index(gcc_jit_type * type)
+{
+  for (int i = 0; i < NUM_CAST_TYPES; ++i)
+    if (type == comp.cast_types[i])
+      return i;
+
+  xsignal1 (Qnative_ice, build_string ("unsupported cast"));
+}
+
 static gcc_jit_rvalue *
 emit_coerce (gcc_jit_type *new_type, gcc_jit_rvalue *obj)
 {
-  static ptrdiff_t i;
-
   gcc_jit_type *old_type = gcc_jit_rvalue_get_type (obj);
 
   if (new_type == old_type)
@@ -1021,25 +978,14 @@ emit_coerce (gcc_jit_type *new_type, gcc_jit_rvalue *obj)
     }
 #endif
 
-  gcc_jit_field *orig_field =
-    type_to_cast_field (old_type);
-  gcc_jit_field *dest_field = type_to_cast_field (new_type);
-
-  gcc_jit_lvalue *tmp_u =
-    gcc_jit_function_new_local (comp.func,
-				NULL,
-				comp.cast_union_type,
-				format_string ("union_cast_%td", i++));
-  gcc_jit_block_add_assignment (comp.block,
-				NULL,
-				gcc_jit_lvalue_access_field (tmp_u,
-							     NULL,
-							     orig_field),
-				obj);
+  int old_index = type_to_cast_index (old_type);
+  int new_index = type_to_cast_index (new_type);
 
-  return gcc_jit_rvalue_access_field ( gcc_jit_lvalue_as_rvalue (tmp_u),
-				       NULL,
-				       dest_field);
+  /* Lookup the appropriate cast function in the cast matrix. */
+  return gcc_jit_context_new_call (comp.ctxt,
+                                   NULL,
+                                   comp.cast_functions_from_to[old_index][new_index],
+                                   1, &obj);
 }
 
 static gcc_jit_rvalue *
@@ -3128,109 +3074,93 @@ define_thread_state_struct (void)
     gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.thread_state_s));
 }
 
-static void
-define_cast_union (void)
+struct cast_type
 {
+  gcc_jit_type * type;
+  const char *name;
+};
+
+static gcc_jit_function *
+define_cast_from_to(struct cast_type from, int from_index, struct cast_type to, int to_index)
+{
+  Lisp_Object name = CALLN(Fformat,
+                           build_string("cast_from_%s_to_%s"),
+                           build_string(from.name),
+                           build_string(to.name));
+  gcc_jit_param * param = gcc_jit_context_new_param(comp.ctxt, NULL,
+                                                    from.type, "arg");
+  gcc_jit_function * result =
+    gcc_jit_context_new_function (comp.ctxt,
+                                  NULL,
+                                  GCC_JIT_FUNCTION_ALWAYS_INLINE,
+                                  to.type,
+                                  SSDATA(name),
+                                  1,
+                                  &param,
+                                  0);
+
+  DECL_BLOCK (entry_block, result);
+
+  gcc_jit_lvalue *tmp_union
+    = gcc_jit_function_new_local (result, NULL, comp.cast_union_type, "union_cast");
+
+  gcc_jit_block_add_assignment (entry_block, NULL,
+                                gcc_jit_lvalue_access_field (tmp_union, NULL,
+                                  comp.cast_union_fields[from_index]),
+                                gcc_jit_param_as_rvalue(param));
+
+  gcc_jit_block_end_with_return(entry_block,
+                                NULL,
+                                gcc_jit_rvalue_access_field (
+                                  gcc_jit_lvalue_as_rvalue (tmp_union),
+                                  NULL,
+                                  comp.cast_union_fields[to_index]));
+
+  return result;
+}
+
+static void
+define_cast_functions (void)
+{
+  struct cast_type cast_types[NUM_CAST_TYPES] =
+    {{comp.bool_type, "bool"},
+     {comp.char_ptr_type, "char_ptr"},
+     {comp.int_type, "int"},
+     {comp.lisp_cons_ptr_type, "cons_ptr"},
+     {comp.lisp_obj_ptr_type, "lisp_obj_ptr"},
+     {comp.lisp_word_tag_type, "lisp_word_tag"},
+     {comp.lisp_word_type, "lisp_word"},
+     {comp.long_long_type, "long_long"},
+     {comp.long_type, "long"},
+     {comp.ptrdiff_type, "ptrdiff"},
+     {comp.uintptr_type, "uintptr"},
+     {comp.unsigned_long_long_type, "unsigned_long_long"},
+     {comp.unsigned_long_type, "unsigned_long"},
+     {comp.unsigned_type, "unsigned"},
+     {comp.void_ptr_type, "void_ptr"}};
+
+  /* Define the union used for casting. */
+  for (int i = 0; i < NUM_CAST_TYPES; ++i)
+    {
+      comp.cast_types[i] = cast_types[i].type;
+      comp.cast_union_fields[i] = gcc_jit_context_new_field (comp.ctxt,
+                                                             NULL,
+                                                             cast_types[i].type,
+                                                             cast_types[i].name);
+    }
 
-  comp.cast_union_as_ll =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.long_long_type,
-			       "ll");
-  comp.cast_union_as_ull =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.unsigned_long_long_type,
-			       "ull");
-  comp.cast_union_as_l =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.long_type,
-			       "l");
-  comp.cast_union_as_ul =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.unsigned_long_type,
-			       "ul");
-  comp.cast_union_as_u =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.unsigned_type,
-			       "u");
-  comp.cast_union_as_i =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.int_type,
-			       "i");
-  comp.cast_union_as_b =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.bool_type,
-			       "b");
-  comp.cast_union_as_uintptr =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.uintptr_type,
-			       "uintptr");
-  comp.cast_union_as_ptrdiff =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.ptrdiff_type,
-			       "ptrdiff");
-  comp.cast_union_as_c_p =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.char_ptr_type,
-			       "c_p");
-  comp.cast_union_as_v_p =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.void_ptr_type,
-			       "v_p");
-  comp.cast_union_as_lisp_cons_ptr =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       comp.lisp_cons_ptr_type,
-			       "cons_ptr");
-  comp.cast_union_as_lisp_word =
-    gcc_jit_context_new_field (comp.ctxt,
-			       NULL,
-			       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,
-			       comp.lisp_obj_ptr_type,
-			       "lisp_obj_ptr");
-
-
-  gcc_jit_field *cast_union_fields[] =
-    { comp.cast_union_as_ll,
-      comp.cast_union_as_ull,
-      comp.cast_union_as_l,
-      comp.cast_union_as_ul,
-      comp.cast_union_as_u,
-      comp.cast_union_as_i,
-      comp.cast_union_as_b,
-      comp.cast_union_as_uintptr,
-      comp.cast_union_as_ptrdiff,
-      comp.cast_union_as_c_p,
-      comp.cast_union_as_v_p,
-      comp.cast_union_as_lisp_cons_ptr,
-      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,
 				    NULL,
 				    "cast_union",
-				    ARRAYELTS (cast_union_fields),
-				    cast_union_fields);
+				    NUM_CAST_TYPES,
+				    comp.cast_union_fields);
+
+  /* Define the cast functions using a matrix. */
+  for (int i = 0; i < NUM_CAST_TYPES; ++i)
+    for (int j = 0; j < NUM_CAST_TYPES; ++j)
+        comp.cast_functions_from_to[i][j] =
+          define_cast_from_to (cast_types[i], i, cast_types[j], j);
 }
 
 static void
@@ -4041,7 +3971,7 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
   define_jmp_buf ();
   define_handler_struct ();
   define_thread_state_struct ();
-  define_cast_union ();
+  define_cast_functions ();
   define_naive_bzero ();
   define_naive_memcpy ();
 
-- 
2.25.1.windows.1


[-- Attachment #3: 0001-Define-static-data-using-string-literals.patch --]
[-- Type: application/octet-stream, Size: 16303 bytes --]

From 9a090c02aedd5ee23951bacb5f0c5275a373875d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Wed, 20 May 2020 00:34:32 -0300
Subject: [PATCH 1/2] Define static data using string literals.

The purpose of this change is to dump prettier C files.
This does not affect compilation times in my tests.

* src/comp.c (emit_static_object): Define static objects using string
literals, memcpy and bzero.
---
 src/comp.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 282 insertions(+), 18 deletions(-)

diff --git a/src/comp.c b/src/comp.c
index 996168bbb5..3f4b3e03b7 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -46,6 +46,7 @@
 # include "w32common.h"
 
 #undef gcc_jit_block_add_assignment
+#undef gcc_jit_block_add_assignment_op
 #undef gcc_jit_block_add_comment
 #undef gcc_jit_block_add_eval
 #undef gcc_jit_block_end_with_conditional
@@ -75,6 +76,7 @@
 #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_string_literal
 #undef gcc_jit_context_new_struct_type
 #undef gcc_jit_context_new_unary_op
 #undef gcc_jit_context_new_union_type
@@ -164,6 +166,8 @@ 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_string_literal,
+            (gcc_jit_context *ctxt, const char *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,
@@ -197,6 +201,9 @@ 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_assignment_op,
+            (gcc_jit_block *block, gcc_jit_location *loc, gcc_jit_lvalue *lvalue,
+             enum gcc_jit_binary_op op, 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));
@@ -239,6 +246,7 @@ init_gccjit_functions (void)
 
   /* In alphabetical order */
   LOAD_DLL_FN (library, gcc_jit_block_add_assignment);
+  LOAD_DLL_FN (library, gcc_jit_block_add_assignment_op);
   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);
@@ -268,6 +276,7 @@ init_gccjit_functions (void)
   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_string_literal);
   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);
@@ -296,6 +305,7 @@ init_gccjit_functions (void)
 
 /* In alphabetical order */
 #define gcc_jit_block_add_assignment fn_gcc_jit_block_add_assignment
+#define gcc_jit_block_add_assignment_op fn_gcc_jit_block_add_assignment_op
 #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
@@ -325,6 +335,7 @@ #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_string_literal fn_gcc_jit_context_new_string_literal
 #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
@@ -548,6 +559,8 @@ #define F_RELOC_MAX_SIZE 1500
   gcc_jit_rvalue *data_relocs_ephemeral;
   /* Synthesized struct holding func relocs.  */
   gcc_jit_lvalue *func_relocs;
+  gcc_jit_function *naive_bzero;
+  gcc_jit_function *naive_memcpy;
   Lisp_Object d_default_idx;
   Lisp_Object d_impure_idx;
   Lisp_Object d_ephemeral_idx;
@@ -2346,10 +2359,7 @@ emit_static_object (const char *name, Lisp_Object obj)
 {
   /* libgccjit has no support for initialized static data.
      The mechanism below is certainly not aesthetic but I assume the bottle neck
-     in terms of performance at load time will still be the reader.
-     NOTE: we can not relay on libgccjit even for valid NULL terminated C
-     strings cause of this funny bug that will affect all pre gcc10 era gccs:
-     https://gcc.gnu.org/ml/jit/2019-q3/msg00013.html  */
+     in terms of performance at load time will still be the reader. */
 
   Lisp_Object str = Fprin1_to_string (obj, Qnil);
   ptrdiff_t len = SBYTES (str);
@@ -2398,22 +2408,91 @@ emit_static_object (const char *name, Lisp_Object obj)
   gcc_jit_lvalue *arr =
       gcc_jit_lvalue_access_field (data_struct, NULL, fields[1]);
 
-  for (ptrdiff_t i = 0; i < len; i++, p++)
+  gcc_jit_lvalue *ptrvar = gcc_jit_function_new_local (f, NULL,
+                                                       comp.char_ptr_type,
+                                                       "ptr");
+
+  gcc_jit_block_add_assignment (
+    block,
+    NULL,
+    ptrvar,
+    gcc_jit_lvalue_get_address (
+      gcc_jit_context_new_array_access (
+        comp.ctxt,
+        NULL,
+        gcc_jit_lvalue_as_rvalue (arr),
+        gcc_jit_context_new_rvalue_from_int (comp.ctxt, comp.int_type, 0)),
+      NULL));
+
+  /* Emit a call to naive_bzero() to clear all the static object. It
+     is not strictly necessary since the dynamic linker will take care
+     of zeroing the memory too. */
+  gcc_jit_rvalue *bzero_args[2]
+    = {gcc_jit_lvalue_as_rvalue (ptrvar),
+       gcc_jit_context_new_rvalue_from_long (comp.ctxt,
+                                             comp.unsigned_long_long_type,
+                                             len + 1)};
+
+  gcc_jit_block_add_eval (block, NULL,
+                          gcc_jit_context_new_call (comp.ctxt, NULL,
+                                                    comp.naive_bzero, 2,
+                                                    bzero_args));
+
+  for (ptrdiff_t i = 0; i < len;)
     {
-      gcc_jit_block_add_assignment (
-	block,
-	NULL,
-	gcc_jit_context_new_array_access (
-	  comp.ctxt,
-	  NULL,
-	  gcc_jit_lvalue_as_rvalue (arr),
-	  gcc_jit_context_new_rvalue_from_int (comp.ctxt,
-					       comp.ptrdiff_type,
-					       i)),
-	gcc_jit_context_new_rvalue_from_int (comp.ctxt,
-					     comp.char_type,
-					     *p));
+      /* We can't use string literals longer that 200 bytes because
+         they cause a crash in older versions of gccjit.
+         https://gcc.gnu.org/ml/jit/2019-q3/msg00013.html  */
+      char str[200];
+      strncpy (str, p, 200);
+      str[199] = 0;
+      uintptr_t l = strlen (str);
+
+      if (l != 0)
+        {
+          p += l;
+          i += l;
+
+          gcc_jit_rvalue *args[3]
+            = {gcc_jit_lvalue_as_rvalue (ptrvar),
+               gcc_jit_context_new_string_literal (comp.ctxt, str),
+               gcc_jit_context_new_rvalue_from_int (comp.ctxt,
+                                                    comp.unsigned_long_long_type,
+                                                    l)};
+
+          gcc_jit_block_add_eval (block, NULL,
+                                  gcc_jit_context_new_call (comp.ctxt, NULL,
+                                                            comp.naive_memcpy,
+                                                            3, args));
+          gcc_jit_block_add_assignment (block, NULL, ptrvar,
+            gcc_jit_lvalue_get_address (
+              gcc_jit_context_new_array_access (comp.ctxt, NULL,
+                gcc_jit_lvalue_as_rvalue (ptrvar),
+                gcc_jit_context_new_rvalue_from_int (comp.ctxt,
+                                                     comp.uintptr_type,
+                                                     l)),
+              NULL));
+        }
+      else
+        {
+          /* If strlen returned 0 that means that the static object
+             contains a NULL byte. In that case just move over to the
+             next block. We can rely on the byte being zero because of
+             the previous call to bzero and because the dynamic linker
+             cleared it. */
+          p++;
+          i++;
+          gcc_jit_block_add_assignment (
+            block, NULL, ptrvar,
+            gcc_jit_lvalue_get_address (
+              gcc_jit_context_new_array_access (
+                comp.ctxt, NULL, gcc_jit_lvalue_as_rvalue (ptrvar),
+                gcc_jit_context_new_rvalue_from_int (comp.ctxt,
+                                                     comp.uintptr_type, 1)),
+              NULL));
+        }
     }
+
   gcc_jit_block_add_assignment (
 	block,
 	NULL,
@@ -2759,6 +2838,189 @@ define_jmp_buf (void)
 				     1, &field);
 }
 
+/*
+ * naive implementation of bzero. Hopefully it will be turned into a
+ * smarter implementation by the optimizer.
+ */
+
+static void
+define_naive_bzero (void)
+{
+  /*
+static void
+naive_bzero (char * ptr, unsigned long long len)
+{
+  unsigned long long i;
+
+entry_block:
+  i = (unsigned long long)0;
+  goto test_block;
+
+test_block:
+  if (len > i) goto loop_block; else goto return_block;
+
+loop_block:
+  ptr[i] = (char)0;
+  i += (unsigned long long)1;
+  goto test_block;
+
+return_block:
+  return;
+}
+  */
+  gcc_jit_param *params[2] = {
+    gcc_jit_context_new_param (comp.ctxt, NULL, comp.char_ptr_type, "ptr"),
+    gcc_jit_context_new_param (comp.ctxt, NULL, comp.unsigned_long_long_type,
+                               "len"),
+  };
+
+  comp.naive_bzero
+    = gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_INTERNAL,
+                                    comp.void_type, "naive_bzero", 2,
+                                    params, false);
+
+  DECL_BLOCK (entry_block, comp.naive_bzero);
+  DECL_BLOCK (test_block, comp.naive_bzero);
+  DECL_BLOCK (loop_block, comp.naive_bzero);
+  DECL_BLOCK (return_block, comp.naive_bzero);
+
+  gcc_jit_lvalue *ptr = gcc_jit_param_as_lvalue (params[0]);
+  gcc_jit_lvalue *i = gcc_jit_function_new_local (comp.naive_bzero, NULL,
+                                                  comp.uintptr_type, "i");
+
+  gcc_jit_block_add_assignment (entry_block, NULL, i,
+                                gcc_jit_context_new_rvalue_from_int (comp.ctxt,
+                                                                     comp.uintptr_type,
+                                                                     0));
+  gcc_jit_block_end_with_jump (entry_block, NULL, test_block);
+
+  /* if (len > i) */
+
+  gcc_jit_rvalue *comparison_result
+    = gcc_jit_context_new_comparison (comp.ctxt, NULL, GCC_JIT_COMPARISON_GT,
+                                      gcc_jit_param_as_rvalue (params[1]),
+                                      gcc_jit_lvalue_as_rvalue (i));
+
+  gcc_jit_block_end_with_conditional (test_block, NULL, comparison_result,
+                                      loop_block, return_block);
+
+  /* ptr[i] = 0; */
+  /* i += 1; */
+
+  gcc_jit_block_add_assignment (loop_block, NULL,
+    gcc_jit_context_new_array_access (comp.ctxt, NULL,
+                                      gcc_jit_lvalue_as_rvalue (ptr),
+                                      gcc_jit_lvalue_as_rvalue (i)),
+    gcc_jit_context_new_rvalue_from_int (comp.ctxt, comp.char_type, 0));
+
+  gcc_jit_block_add_assignment_op (
+    loop_block, NULL, i, GCC_JIT_BINARY_OP_PLUS,
+    gcc_jit_context_new_rvalue_from_int (comp.ctxt, comp.uintptr_type, 1));
+
+  gcc_jit_block_end_with_jump (loop_block, NULL, test_block);
+
+  /* return; */
+
+  gcc_jit_block_end_with_void_return (return_block, NULL);
+}
+
+/*
+ * naive implementation of memcpy. Hopefully it will be turned into a
+ * smarter implementation by the optimizer.
+ */
+
+static void
+define_naive_memcpy (void)
+{
+  /*
+static void *
+naive_memcpy (char * dest, char * src, unsigned long long len)
+{
+  unsigned long long i;
+
+entry_block:
+  i = (unsigned long long)0;
+  goto test_block;
+
+test_block:
+  if (len > i) goto loop_block; else goto return_block;
+
+loop_block:
+  dest[i] = src[i];
+  i += (unsigned long long)1;
+  goto test_block;
+
+return_block:
+  return dest;
+}
+  */
+  gcc_jit_param *params[3] = {
+    gcc_jit_context_new_param (comp.ctxt, NULL, comp.char_ptr_type, "dest"),
+    gcc_jit_context_new_param (comp.ctxt, NULL, comp.char_ptr_type, "src"),
+    gcc_jit_context_new_param (comp.ctxt, NULL, comp.unsigned_long_long_type,
+                               "len"),
+  };
+
+  comp.naive_memcpy
+    = gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_INTERNAL,
+                                    comp.void_ptr_type, "naive_memcpy", 3,
+                                    params, false);
+
+  DECL_BLOCK (entry_block, comp.naive_memcpy);
+  DECL_BLOCK (test_block, comp.naive_memcpy);
+  DECL_BLOCK (loop_block, comp.naive_memcpy);
+  DECL_BLOCK (return_block, comp.naive_memcpy);
+
+  gcc_jit_lvalue *dest = gcc_jit_param_as_lvalue (params[0]);
+  gcc_jit_lvalue *src = gcc_jit_param_as_lvalue (params[1]);
+  gcc_jit_lvalue *i = gcc_jit_function_new_local (comp.naive_memcpy, NULL,
+                                                  comp.uintptr_type, "i");
+
+  gcc_jit_block_add_assignment (entry_block, NULL, i,
+                                gcc_jit_context_new_rvalue_from_int (comp.ctxt,
+                                                                     comp.uintptr_type,
+                                                                     0));
+  gcc_jit_block_end_with_jump (entry_block, NULL, test_block);
+
+  /* if (len > i) */
+
+  gcc_jit_rvalue *comparison_result
+    = gcc_jit_context_new_comparison (comp.ctxt, NULL, GCC_JIT_COMPARISON_GT,
+                                      gcc_jit_param_as_rvalue (params[2]),
+                                      gcc_jit_lvalue_as_rvalue (i));
+
+  gcc_jit_block_end_with_conditional (test_block, NULL, comparison_result,
+                                      loop_block, return_block);
+
+  /* dest[i] = src[i]; */
+  /* i += 1; */
+
+  gcc_jit_block_add_assignment (loop_block, NULL,
+    gcc_jit_context_new_array_access (comp.ctxt, NULL,
+                                      gcc_jit_lvalue_as_rvalue (dest),
+                                      gcc_jit_lvalue_as_rvalue (i)),
+    gcc_jit_lvalue_as_rvalue (
+      gcc_jit_context_new_array_access (comp.ctxt, NULL,
+                                        gcc_jit_lvalue_as_rvalue (src),
+                                        gcc_jit_lvalue_as_rvalue (i))));
+
+  gcc_jit_block_add_assignment_op (loop_block,
+                                   NULL,
+                                   i,
+                                   GCC_JIT_BINARY_OP_PLUS,
+                                   gcc_jit_context_new_rvalue_from_int (
+                                     comp.ctxt,
+                                     comp.uintptr_type,
+                                     1));
+
+  gcc_jit_block_end_with_jump (loop_block, NULL, test_block);
+
+  /* return dest; */
+
+  gcc_jit_block_end_with_return (return_block, NULL,
+                                 gcc_jit_param_as_rvalue (params[0]));
+}
+
 /* struct handler definition  */
 
 static void
@@ -3780,6 +4042,8 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
   define_handler_struct ();
   define_thread_state_struct ();
   define_cast_union ();
+  define_naive_bzero ();
+  define_naive_memcpy ();
 
   return Qt;
 }
-- 
2.25.1.windows.1


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

end of thread, other threads:[~2020-06-04  9:52 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-30 15:08 bug#41615: [feature/native-comp] Dump prettier C code Nicolas Bértolo
2020-05-30 22:20 ` Nicolas Bértolo
2020-05-31 10:45   ` Andrea Corallo
2020-05-31 15:42     ` Nicolas Bértolo
2020-05-31 11:37   ` Andrea Corallo
2020-05-31 15:48     ` Andrea Corallo
2020-05-31 15:54     ` Nicolas Bértolo
2020-05-31 16:57       ` Andrea Corallo
2020-05-31 17:26         ` Nicolas Bértolo
2020-05-31 18:11           ` Andrea Corallo
2020-05-31 19:38             ` Nicolas Bértolo
2020-05-31 20:00               ` Andrea Corallo
2020-05-31 20:18                 ` Andrea Corallo
2020-06-01  7:19               ` Andrea Corallo
2020-06-01 12:25                 ` Nicolas Bértolo
2020-06-01 20:28                   ` Andrea Corallo
2020-06-01 23:11                     ` Nicolas Bértolo
2020-06-04  9:52                       ` Andrea Corallo

Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.