From 435ed84c6df4911b238f67c79492533e0c71ca46 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Sun, 31 May 2020 18:09:12 -0300
Subject: [PATCH 4/4] Throw an ICE when asked to emit a cast with sign
 extension.

* src/comp.c (cast_kind_of_type): Enum that specifies the kind of type
in the cast enum (unsigned, signed, pointer).
(emit_coerce): Throw an ICE when asked to emit a cast with sign
extension.
(define_cast_from_to): Return NULL for casts involving sign extension.
(define_cast_functions): Specify the kind of each type in the cast
union.
---
 src/comp.c | 58 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 15 deletions(-)

diff --git a/src/comp.c b/src/comp.c
index ed2e5f37338..8dc936f451a 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -450,6 +450,13 @@ #define F_RELOC_MAX_SIZE 1500
 
 #define NUM_CAST_TYPES 15
 
+enum cast_kind_of_type
+  {
+    kind_unsigned,
+    kind_signed,
+    kind_pointer
+  };
+
 /* C side of the compiler context.  */
 
 typedef struct {
@@ -514,6 +521,7 @@ #define NUM_CAST_TYPES 15
       member.  */
   gcc_jit_type *cast_types[NUM_CAST_TYPES+1];
   size_t cast_type_sizes[NUM_CAST_TYPES+1];
+  enum cast_kind_of_type cast_type_kind[NUM_CAST_TYPES+1];
   const char *cast_type_names[NUM_CAST_TYPES+1];
   gcc_jit_field *cast_union_fields[NUM_CAST_TYPES+1];
   size_t cast_union_field_biggest_type;
@@ -980,6 +988,13 @@ emit_coerce (gcc_jit_type *new_type, gcc_jit_rvalue *obj)
   int old_index = type_to_cast_index (old_type);
   int new_index = type_to_cast_index (new_type);
 
+  if (comp.cast_type_sizes[old_index] < comp.cast_type_sizes[new_index]
+      && comp.cast_type_kind[new_index] == kind_signed)
+    xsignal3 (Qnative_ice,
+              build_string ("FIXME: sign extension not implemented"),
+              build_string (comp.cast_type_names[old_index]),
+              build_string (comp.cast_type_names[new_index]));
+
   /* Lookup the appropriate cast function in the cast matrix.  */
   return gcc_jit_context_new_call (comp.ctxt,
            NULL,
@@ -2907,6 +2922,7 @@ define_thread_state_struct (void)
   gcc_jit_type *type;
   const char *name;
   size_t bytes_size;
+  enum cast_kind_of_type kind;
 };
 
 static gcc_jit_function *
@@ -2979,6 +2995,11 @@ define_cast_from_to (struct cast_type from, int from_index, struct cast_type to,
   if (to.type == comp.bool_type)
     return define_cast_to_bool (from, from_index);
 
+  /*  FIXME: sign extension not implemented.  */
+  if (comp.cast_type_sizes[from_index] < comp.cast_type_sizes[to_index]
+      && comp.cast_type_kind[to_index] == kind_signed)
+    return NULL;
+
   char *name = format_string ("cast_from_%s_to_%s", from.name, to.name);
   gcc_jit_param *param = gcc_jit_context_new_param (comp.ctxt, NULL,
                                                     from.type, "arg");
@@ -3027,22 +3048,27 @@ define_cast_from_to (struct cast_type from, int from_index, struct cast_type to,
 define_cast_functions (void)
 {
   struct cast_type cast_types[NUM_CAST_TYPES]
-    = { { comp.bool_type, "bool", sizeof (bool) },
-        { comp.char_ptr_type, "char_ptr", sizeof (char *) },
-        { comp.int_type, "int", sizeof (int) },
-        { comp.lisp_cons_ptr_type, "cons_ptr", sizeof (struct Lisp_Cons *) },
-        { comp.lisp_obj_ptr_type, "lisp_obj_ptr", sizeof (Lisp_Object *) },
-        { comp.lisp_word_tag_type, "lisp_word_tag", sizeof (Lisp_Word_tag) },
-        { comp.lisp_word_type, "lisp_word", sizeof (Lisp_Word) },
-        { comp.long_long_type, "long_long", sizeof (long long) },
-        { comp.long_type, "long", sizeof (long) },
-        { comp.ptrdiff_type, "ptrdiff", sizeof (ptrdiff_t) },
-        { comp.uintptr_type, "uintptr", sizeof (uintptr_t) },
+    = { { comp.bool_type, "bool", sizeof (bool), kind_unsigned },
+        { comp.char_ptr_type, "char_ptr", sizeof (char *), kind_pointer },
+        { comp.int_type, "int", sizeof (int), kind_signed },
+        { comp.lisp_cons_ptr_type, "cons_ptr", sizeof (struct Lisp_Cons *),
+          kind_pointer },
+        { comp.lisp_obj_ptr_type, "lisp_obj_ptr", sizeof (Lisp_Object *),
+          kind_pointer },
+        { comp.lisp_word_tag_type, "lisp_word_tag", sizeof (Lisp_Word_tag),
+          kind_unsigned },
+        { comp.lisp_word_type, "lisp_word", sizeof (Lisp_Word),
+          LISP_WORDS_ARE_POINTERS ? kind_pointer : kind_signed },
+        { comp.long_long_type, "long_long", sizeof (long long), kind_signed },
+        { comp.long_type, "long", sizeof (long), kind_signed },
+        { comp.ptrdiff_type, "ptrdiff", sizeof (ptrdiff_t), kind_signed },
+        { comp.uintptr_type, "uintptr", sizeof (uintptr_t), kind_unsigned },
         { comp.unsigned_long_long_type, "unsigned_long_long",
-          sizeof (unsigned long long) },
-        { comp.unsigned_long_type, "unsigned_long", sizeof (unsigned long) },
-        { comp.unsigned_type, "unsigned", sizeof (unsigned) },
-        { comp.void_ptr_type, "void_ptr", sizeof (void*) } };
+          sizeof (unsigned long long), kind_unsigned },
+        { comp.unsigned_long_type, "unsigned_long", sizeof (unsigned long),
+          kind_unsigned },
+        { comp.unsigned_type, "unsigned", sizeof (unsigned), kind_unsigned },
+        { comp.void_ptr_type, "void_ptr", sizeof (void*), kind_pointer } };
 
   /* Find the biggest size.  It should be unsigned long long, but to be
      sure we find it programmatically.  */
@@ -3060,6 +3086,7 @@ define_cast_functions (void)
                                     cast_types[i].name);
       comp.cast_type_names[i] = cast_types[i].name;
       comp.cast_type_sizes[i] = cast_types[i].bytes_size;
+      comp.cast_type_kind[i] = cast_types[i].kind;
     }
 
   gcc_jit_type *biggest_type = gcc_jit_context_get_int_type (comp.ctxt,
@@ -3070,6 +3097,7 @@ define_cast_functions (void)
     = gcc_jit_context_new_field (comp.ctxt, NULL, biggest_type, "biggest_type");
   comp.cast_type_names[NUM_CAST_TYPES] = "biggest_type";
   comp.cast_type_sizes[NUM_CAST_TYPES] = biggest_size;
+  comp.cast_type_kind[NUM_CAST_TYPES] = kind_unsigned;
 
   comp.cast_union_type =
     gcc_jit_context_new_union_type (comp.ctxt,
-- 
2.25.1.windows.1

