Make sized integer types compatible with normal integer types
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index f721e5c..096c899 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -283,6 +283,25 @@
 }
 
 /* Construct a playback::type instance (wrapping a tree) for the given
+   sign and number of bits.  */
+
+playback::type *
+playback::context::
+make_type (bool is_signed, size_t num_bits)
+{
+  tree int_type;
+  if (is_signed)
+  {
+    int_type = make_signed_type(num_bits);
+  }
+  else
+  {
+    int_type = make_unsigned_type(num_bits);
+  }
+  return new type (int_type);
+}
+
+/* Construct a playback::type instance (wrapping a tree) for the given
    array type.  */
 
 playback::type *
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index b5d71aa..25e0d5c 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -67,6 +67,9 @@
   get_type (enum gcc_jit_types type);
 
   type *
+  make_type (bool is_signed, size_t num_bits);
+
+  type *
   new_array_type (location *loc,
 		  type *element_type,
 		  int num_elements);
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 1a412b5..5ea2320 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -564,8 +564,8 @@
     m_compound_types (),
     m_globals (),
     m_functions (),
-    m_signed_int_types(),
-    m_unsigned_int_types(),
+    /*m_signed_int_types(),
+    m_unsigned_int_types(),*/
     m_FILE_type (NULL),
     m_builtins_manager(NULL)
 {
@@ -796,6 +796,10 @@
    Implements the post-error-checking part of
    gcc_jit_context_get_int_type.  */
 
+int nextPowerOfTwo(int x) {
+  return 1 << sizeof(x)*8 - __builtin_clz(x);
+}
+
 recording::type *
 recording::context::get_int_type (int num_bytes, int is_signed)
 {
@@ -805,7 +809,7 @@
      Compare with tree.c's make_or_reuse_type.  Note that the _SIZE macros
      are in bits, rather than bytes.
   */
-  const int num_bits = num_bytes * 8;
+  /*const*/ int num_bits = num_bytes * 8;
   if (num_bits == INT_TYPE_SIZE)
     return get_type (is_signed
 		     ? GCC_JIT_TYPE_INT
@@ -832,33 +836,38 @@
 		     : GCC_JIT_TYPE_UINT128_T);
 
   // TODO: check in num_bits > 0?
-  tree int_type;
+  /*tree int_type;*/
+  /*printf("Before: %d\n", num_bits);*/
+  /*num_bits = nextPowerOfTwo(num_bits);
+  printf("After: %d\n", num_bits);*/
   if (is_signed)
   {
-    if (tree type = m_signed_int_types[num_bits])
+    /*if (tree type = m_signed_int_types[num_bits])
     {
       int_type = type;
     }
     else
-    {
-      int_type = make_signed_type(num_bits);
-      m_signed_int_types[num_bits] = int_type;
-    }
+    {*/
+      // FIXME: seems like we cannot create a type here because the ggc is not initialized: instead, create it in
+      // playback.
+      /*int_type = make_signed_type(num_bits);*/
+      /*m_signed_int_types[num_bits] = int_type;
+    }*/
   }
   else
   {
-    if (tree type = m_unsigned_int_types[num_bits])
+    /*if (tree type = m_unsigned_int_types[num_bits])
     {
       int_type = type;
     }
     else
-    {
-      int_type = make_unsigned_type(num_bits);
-      m_unsigned_int_types[num_bits] = int_type;
-    }
+    {*/
+      /*int_type = make_unsigned_type(num_bits);*/
+      /*m_unsigned_int_types[num_bits] = int_type;
+    }*/
   }
 
-  recording::type *result = new memento_of_make_type (this, int_type, num_bits);
+  recording::type *result = new memento_of_make_type (this, is_signed, num_bits);
   record (result);
   return result;
 }
@@ -2358,14 +2367,22 @@
       size = LONG_LONG_TYPE_SIZE;
       break;
     case GCC_JIT_TYPE_UINT8_T:
-    case GCC_JIT_TYPE_UINT16_T:
-    case GCC_JIT_TYPE_UINT32_T:
-    case GCC_JIT_TYPE_UINT64_T:
-    case GCC_JIT_TYPE_UINT128_T:
     case GCC_JIT_TYPE_INT8_T:
+      size = 8;
+      break;
+    case GCC_JIT_TYPE_UINT16_T:
     case GCC_JIT_TYPE_INT16_T:
+      size = 16;
+      break;
+    case GCC_JIT_TYPE_UINT32_T:
     case GCC_JIT_TYPE_INT32_T:
+      size = 32;
+      break;
+    case GCC_JIT_TYPE_UINT64_T:
     case GCC_JIT_TYPE_INT64_T:
+      size = 64;
+      break;
+    case GCC_JIT_TYPE_UINT128_T:
     case GCC_JIT_TYPE_INT128_T:
       size = 128;
       break;
@@ -2378,6 +2395,10 @@
     case GCC_JIT_TYPE_LONG_DOUBLE:
       size = LONG_DOUBLE_TYPE_SIZE;
       break;
+    case GCC_JIT_TYPE_SIZE_T:
+      size = POINTER_TYPE;
+      /*size = TYPE_PRECISION(size_type_node); // TODO: check that this code works.*/
+      break;
     default:
       /* As this function is called by
 	 'gcc_jit_global_set_initializer' and
@@ -2512,6 +2533,60 @@
     }
 }
 
+/* Implementation of pure virtual hook recording::type::is_signed for
+   recording::memento_of_get_type.  */
+
+bool
+recording::memento_of_get_type::is_signed () const
+{
+  switch (m_kind)
+    {
+    default: gcc_unreachable ();
+
+    case GCC_JIT_TYPE_SIGNED_CHAR:
+    case GCC_JIT_TYPE_CHAR:
+    case GCC_JIT_TYPE_SHORT:
+    case GCC_JIT_TYPE_INT:
+    case GCC_JIT_TYPE_LONG:
+    case GCC_JIT_TYPE_LONG_LONG:
+    case GCC_JIT_TYPE_INT8_T:
+    case GCC_JIT_TYPE_INT16_T:
+    case GCC_JIT_TYPE_INT32_T:
+    case GCC_JIT_TYPE_INT64_T:
+    case GCC_JIT_TYPE_INT128_T:
+      return true;
+
+    case GCC_JIT_TYPE_VOID:
+    case GCC_JIT_TYPE_VOID_PTR:
+    case GCC_JIT_TYPE_BOOL:
+    case GCC_JIT_TYPE_UNSIGNED_CHAR:
+    case GCC_JIT_TYPE_UNSIGNED_SHORT:
+    case GCC_JIT_TYPE_UNSIGNED_INT:
+    case GCC_JIT_TYPE_UNSIGNED_LONG:
+    case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+    case GCC_JIT_TYPE_UINT8_T:
+    case GCC_JIT_TYPE_UINT16_T:
+    case GCC_JIT_TYPE_UINT32_T:
+    case GCC_JIT_TYPE_UINT64_T:
+    case GCC_JIT_TYPE_UINT128_T:
+
+    case GCC_JIT_TYPE_FLOAT:
+    case GCC_JIT_TYPE_DOUBLE:
+    case GCC_JIT_TYPE_LONG_DOUBLE:
+
+    case GCC_JIT_TYPE_CONST_CHAR_PTR:
+
+    case GCC_JIT_TYPE_SIZE_T:
+
+    case GCC_JIT_TYPE_FILE_PTR:
+
+    case GCC_JIT_TYPE_COMPLEX_FLOAT:
+    case GCC_JIT_TYPE_COMPLEX_DOUBLE:
+    case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
+      return false;
+    }
+}
+
 /* Implementation of pure virtual hook recording::type::is_float for
    recording::memento_of_get_type.  */
 
@@ -2761,7 +2836,7 @@
 void
 recording::memento_of_make_type::replay_into (replayer *r)
 {
-  set_playback_obj (this);
+  set_playback_obj (r->make_type(m_is_signed, m_num_bits));
 }
 
 recording::string *
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index c06874e..343cd6c 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -369,8 +369,8 @@
 
   type *m_basic_types[NUM_GCC_JIT_TYPES];
   /* Map from num_bits to integer types. */
-  tree m_signed_int_types[128];
-  tree m_unsigned_int_types[128];
+  /*tree m_signed_int_types[128];
+  tree m_unsigned_int_types[128];*/
   type *m_FILE_type;
 
   builtins_manager *m_builtins_manager; // lazily created
@@ -573,6 +573,7 @@
   virtual bool is_void () const { return false; }
   virtual vector_type *is_vector () { return NULL; }
   virtual bool has_known_size () const { return true; }
+  virtual bool is_signed () const = 0;
 
   bool is_numeric () const
   {
@@ -613,12 +614,19 @@
   bool accepts_writes_from (type *rtype) FINAL OVERRIDE
   {
     if (m_kind == GCC_JIT_TYPE_VOID_PTR)
+    {
       if (rtype->is_pointer ())
 	{
 	  /* LHS (this) is type (void *), and the RHS is a pointer:
 	     accept it:  */
 	  return true;
 	}
+    }
+    else if (is_int () && rtype->is_int () && get_size () == rtype->get_size () && is_signed () == rtype->is_signed ())
+    {
+      /* LHS (this) is an integer of the size size and sign as rtype.  */
+      return true;
+    }
 
     return type::accepts_writes_from (rtype);
   }
@@ -629,6 +637,7 @@
   type *is_pointer () FINAL OVERRIDE { return dereference (); }
   type *is_array () FINAL OVERRIDE { return NULL; }
   bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; }
+  bool is_signed () const FINAL OVERRIDE;
 
 public:
   void replay_into (replayer *r) FINAL OVERRIDE;
@@ -646,10 +655,10 @@
 {
 public:
   memento_of_make_type (context *ctxt,
-			tree int_type,
+			bool is_signed,
 			size_t num_bits)
   : type (ctxt),
-    m_type (int_type),
+    m_is_signed (is_signed),
     m_num_bits (num_bits) {}
 
   type *dereference () FINAL OVERRIDE { return NULL; };
@@ -667,6 +676,7 @@
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
   bool is_void () const FINAL OVERRIDE { return false; }
+  bool is_signed () const FINAL OVERRIDE { return m_is_signed; }
 
 public:
   void replay_into (replayer *r) FINAL OVERRIDE;
@@ -676,7 +686,7 @@
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
 
 private:
-  tree m_type;
+  bool m_is_signed;
   size_t m_num_bits;
 };
 
@@ -702,6 +712,7 @@
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return m_other_type; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
 private:
   string * make_debug_string () FINAL OVERRIDE;
@@ -723,12 +734,15 @@
 
   type *dereference () FINAL OVERRIDE { return m_other_type->dereference (); }
 
+  size_t get_size () FINAL OVERRIDE { return m_other_type->get_size (); };
+
   bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); }
   bool is_float () const FINAL OVERRIDE { return m_other_type->is_float (); }
   bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
   type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
   type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
   struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
+  bool is_signed () const FINAL OVERRIDE { return m_other_type->is_signed (); }
 
 protected:
   type *m_other_type;
@@ -844,6 +858,7 @@
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return m_element_type; }
   int num_elements () { return m_num_elements; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -877,6 +892,7 @@
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   void replay_into (replayer *) FINAL OVERRIDE;
 
@@ -990,6 +1006,7 @@
   bool is_bool () const FINAL OVERRIDE { return false; }
   type *is_pointer () FINAL OVERRIDE { return NULL; }
   type *is_array () FINAL OVERRIDE { return NULL; }
+  bool is_signed () const FINAL OVERRIDE { return false; }
 
   bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; }
 
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 3758400..e03817f 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -537,6 +537,19 @@
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
+   gcc::jit::recording::type::get_size method, in
+   jit-recording.c.  */
+
+ssize_t
+gcc_jit_type_get_size (gcc_jit_type *type)
+{
+  RETURN_VAL_IF_FAIL (type->is_int (), -1, NULL, NULL, "only getting the size of an int type is supported for now");
+  return type->get_size ();
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
    gcc::jit::recording::type::is_array method, in
    jit-recording.c.  */
 
@@ -1865,7 +1878,7 @@
   RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a");
   RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b");
   RETURN_NULL_IF_FAIL_PRINTF4 (
-    a->get_type ()->unqualified () == b->get_type ()->unqualified (),
+    compatible_types (a->get_type (), b->get_type ()),
     ctxt, loc,
     "mismatching types for binary op:"
     " a: %s (type: %s) b: %s (type: %s)",
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index e4ec6cf..8c737f1 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -612,6 +612,10 @@
 extern gcc_jit_type *
 gcc_jit_type_get_volatile (gcc_jit_type *type);
 
+/* Given type "T", get its size.  */
+extern ssize_t
+gcc_jit_type_get_size (gcc_jit_type *type);
+
 /* Given type "T", get type "T[N]" (for a constant N).  */
 extern gcc_jit_type *
 gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a30cca5..53b4246 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -252,3 +252,8 @@
     gcc_jit_context_new_rvalue_from_struct;
     gcc_jit_context_new_rvalue_from_array;
 } LIBGCCJIT_ABI_20;
+
+LIBGCCJIT_ABI_22 {
+  global:
+    gcc_jit_type_get_size;
+} LIBGCCJIT_ABI_21;