From f49cea6830b08a019958ef3f6a1ced1e416f80b3 Mon Sep 17 00:00:00 2001
From: Petter Tomner <tomner@kth.se>
Date: Sat, 16 Oct 2021 21:55:20 +0200
Subject: [PATCH 2/3] long long

Add long long, long double and complex long double constants

This patch adds entrypoints to make constants (literals) for long long,
long double and complex long double types.

Also, it fixes problems with all floating point numbers in write_reproducer.
I.e. support NAN and INF values, aswell as proper precision for double
and long double. Which is needed for testing this patch.

Signed-off-by:
2021-10-21	Petter Tomner	<tomner@kth.se>

gcc/jit/
	* jit-playback.c :
	(new_rvalue_from_const <long long>): New
	(new_rvalue_from_const <long>): Uses long long instead
	(new_rvalue_from_const <long double>): New
	(new_rvalue_from_const <_Complex long double>) : New
	* jit-recording.c :
	(dump_reproducer_to_file) : Type punning NANs
	(reproducer_write_arr) : arr -> "char array literal"-string
	(memento_of_new_rvalue_from_const <long long>) : New
	(memento_of_new_rvalue_from_const <long double>) : New
	(memento_of_new_rvalue_from_const <_Complex long double>) : New
	(memento_of_new_rvalue_from_const <double>::make_debug_string):
	%g instead of %f
	(memento_of_new_rvalue_from_const <double>::write_reproducer):
	%a instead of %f, handle NAN and INF
	(memento_of_new_rvalue_from_const <_Complex double>::write_reproducer):
	%a instead of %f, handle NAN and INF. Use CMPLX macro.
	* libgccjit.c :
	* libgccjit.h :
	(LIBGCCJIT_HAVE_LONGLONG_CONSTANTS) : New
	(gcc_jit_context_new_rvalue_from_long_long) : New
	(gcc_jit_context_new_rvalue_from_long_double) : New
	(gcc_jit_context_new_rvalue_from_complex_long_double) : New
	* libgccjit++.h : New entrypoints
	* libgccjit.map: New entrypoints added to ABI 16

gcc/testsuite/
	* jit.dg/all-non-failing-tests.h: Added test-long-literals.c
	* jit.dg/test-long-literals.c: New

gcc/jit/docs/topics/
	* expressions.rst : Updated docks
---
 gcc/jit/docs/topics/expressions.rst          |  43 +-
 gcc/jit/jit-playback.c                       | 143 +++++-
 gcc/jit/jit-recording.c                      | 442 ++++++++++++++++++-
 gcc/jit/libgccjit++.h                        |  39 ++
 gcc/jit/libgccjit.c                          |  46 ++
 gcc/jit/libgccjit.h                          |  33 +-
 gcc/jit/libgccjit.map                        |   3 +
 gcc/testsuite/jit.dg/all-non-failing-tests.h |   7 +
 gcc/testsuite/jit.dg/test-long-literals.c    | 283 ++++++++++++
 9 files changed, 1017 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-long-literals.c

diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index a98f35572b4..30a3b9780f9 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -70,6 +70,18 @@ Simple expressions
    Given a numeric type (integer or floating point), build an rvalue for
    the given constant :c:type:`long` value.
 
+.. function:: gcc_jit_rvalue *\
+              gcc_jit_context_new_rvalue_from_long_long (gcc_jit_context *ctxt, \
+                                                         gcc_jit_type *numeric_type, \
+                                                         long long value)
+
+   Given a numeric type (integer or floating point), build an rvalue for
+   the given constant :c:type:`long long` value.
+
+   This function was added in :ref:`LIBGCCJIT_ABI_16`;
+   you can test for its presence using
+       `#ifdef LIBGCCJIT_HAVE_LONGLONG_CONSTANTS`
+
 .. function::  gcc_jit_rvalue *gcc_jit_context_zero (gcc_jit_context *ctxt, \
                                                      gcc_jit_type *numeric_type)
 
@@ -98,6 +110,18 @@ Simple expressions
    Given a numeric type (integer or floating point), build an rvalue for
    the given constant :c:type:`double` value.
 
+.. function:: gcc_jit_rvalue *\
+              gcc_jit_context_new_rvalue_from_long_double (gcc_jit_context *ctxt, \
+                                                           gcc_jit_type *numeric_type, \
+                                                           long double value)
+
+   Given a floating point type, build an rvalue for
+   the given constant :c:type:`long double`.
+
+   This function was added in :ref:`LIBGCCJIT_ABI_16`;
+   you can test for its presence using
+       `#ifdef LIBGCCJIT_HAVE_LONGLONG_CONSTANTS`
+
 .. function:: gcc_jit_rvalue *\
               gcc_jit_context_new_rvalue_from_complex_double (gcc_jit_context *ctxt, \
                                                               gcc_jit_type *numeric_type, \
@@ -107,6 +131,23 @@ Simple expressions
    the given constant :c:type:`_Complex double`. When the result type is
    non-complex, the imaginary part is discarded.
 
+   This function was added in :ref:`LIBGCCJIT_ABI_16`;
+   you can test for its presence using
+       `#ifdef LIBGCCJIT_HAVE_COMPLEX`
+
+.. function:: extern gcc_jit_rvalue *\
+              gcc_jit_context_new_rvalue_from_complex_long_double (gcc_jit_context *ctxt,\
+                                                                   gcc_jit_type *numeric_type,\
+                                                                   _Complex long double value);
+
+   Given a floating point type, build an rvalue for
+   the given constant :c:type:`_Complex long double`. When the result type is
+   non-complex, the imaginary part is discarded.
+
+   This function was added in :ref:`LIBGCCJIT_ABI_16`;
+   you can test for its presence using
+       `#ifdef LIBGCCJIT_HAVE_LONGLONG_CONSTANTS`
+
 .. function:: gcc_jit_rvalue *\
               gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt, \
                                                    gcc_jit_type *pointer_type, \
@@ -403,7 +444,7 @@ Binary Operation                          C equivalent    Supported operand type
    the imaginary. Negative zeroes are preserved
    and Inf:s do not lead to NaNs.
 
-   This operator  was added in LIBGCCJIT_ABI_16;
+   This operator  was added in :ref:`LIBGCCJIT_ABI_16`;
    you can test for its presence using
        `#ifdef LIBGCCJIT_HAVE_COMPLEX`
 
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 8b1cb818b90..1f4dc31a1c1 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -61,6 +61,13 @@ along with GCC; see the file COPYING3.  If not see
 #define SET_DECL_JIT_BIT_FIELD(NODE) \
   (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 1)
 
+/* "There are always [atleast] 32 bits in each long, no matter the
+    size of the hosts long.  We handle floating point representations
+    with up to 192 bits", says native_interpret_real() in fold-const.c.
+    That means 6 longs to store a long double. We'll make it 8 to
+    be safe with padding. */
+#define N_LONGS_LDOUBLE 8
+
 /* gcc::jit::playback::context::build_cast uses the convert.h API,
    which in turn requires the frontend to provide a "convert"
    function, apparently as a fallback for casts that can be simplified
@@ -743,15 +750,14 @@ new_rvalue_from_const <int> (type *type,
     }
 }
 
-/* Specialization of making an rvalue from a const, for host <long>.  */
+/* Specialization of making an rvalue from a const, for host <long long>. */
 
 template <>
 rvalue *
 context::
-new_rvalue_from_const <long> (type *type,
-			      long value)
+new_rvalue_from_const <long long> (type *type,
+				   long long value)
 {
-  // FIXME: type-checking, or coercion?
   tree inner_type = type->as_tree ();
   if (INTEGRAL_TYPE_P (inner_type))
     {
@@ -786,6 +792,17 @@ new_rvalue_from_const <long> (type *type,
     }
 }
 
+/* Specialization of making an rvalue from a const, for host <long>.  */
+
+template <>
+rvalue *
+context::
+new_rvalue_from_const <long> (type *type,
+			      long value)
+{
+  return new_rvalue_from_const <long long> (type, value);
+}
+
 /* Specialization of making an rvalue from a const, for host <double>.  */
 
 template <>
@@ -847,6 +864,65 @@ new_rvalue_from_const <double> (type *type,
     }
 }
 
+/* Specialization of making an rvalue from a const, for host <long double>.  */
+
+template <>
+rvalue *
+context::
+new_rvalue_from_const <long double> (type *type,
+				     long double value)
+{
+  tree inner_type = type->as_tree ();
+
+  scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (long_double_type_node);
+
+  union
+  {
+    long double as_long_double;
+    uint32_t as_uint32s[N_LONGS_LDOUBLE];
+  } u_real, u_imag;
+
+  u_real.as_long_double = value;
+
+  long int as_long_ints[N_LONGS_LDOUBLE];
+
+  for (int i = 0; i < N_LONGS_LDOUBLE; i++)
+    as_long_ints[i] = u_real.as_uint32s[i];
+
+  REAL_VALUE_TYPE real_value;
+  real_from_target (&real_value, as_long_ints, mode);
+
+  if (COMPLEX_FLOAT_TYPE_P (inner_type))
+    {
+      tree tree_real;
+      tree tree_imag;
+      tree real_type;
+
+      REAL_VALUE_TYPE imag_value;
+
+      long int zero_as_long_ints[N_LONGS_LDOUBLE];
+      u_imag.as_long_double = 0.;
+
+      for (int i = 0; i < N_LONGS_LDOUBLE; i++)
+	zero_as_long_ints[i] = u_imag.as_uint32s[i];
+
+      real_from_target (&imag_value, zero_as_long_ints, mode);
+
+      real_type = complex_real_to_real (inner_type);
+
+      tree_real = build_real (real_type, real_value);
+      tree_imag = build_real (real_type, imag_value);
+
+      tree inner = build_complex (inner_type, tree_real, tree_imag);
+      return new rvalue (this, inner);
+    }
+  else
+    {
+      tree inner = build_real (inner_type, real_value);
+      return new rvalue (this, inner);
+    }
+}
+
 /* Specialization of making an rvalue from a const,
    for host <double _Complex>. */
 
@@ -902,6 +978,65 @@ new_rvalue_from_const <_Complex double> (type *type,
     }
 }
 
+/* Specialization of making an rvalue from a const,
+   for host <_Complex long double>. */
+
+template <>
+rvalue *
+context::
+new_rvalue_from_const <_Complex long double> (type *type,
+					      _Complex long double value)
+{
+  tree inner_type = type->as_tree ();
+
+  scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (long_double_type_node);
+
+  union
+  {
+    long double as_long_double;
+    uint32_t as_uint32s[N_LONGS_LDOUBLE];
+  } u_real, u_imag;
+
+  u_real.as_long_double = creall(value);
+  long int as_long_ints[N_LONGS_LDOUBLE];
+
+  for (int i = 0; i < N_LONGS_LDOUBLE; i++)
+    as_long_ints[i] = u_real.as_uint32s[i];
+
+  REAL_VALUE_TYPE real_value;
+  real_from_target (&real_value, as_long_ints, mode);
+
+  if (COMPLEX_FLOAT_TYPE_P (inner_type))
+    {
+      tree tree_real;
+      tree tree_imag;
+      tree real_type;
+
+      REAL_VALUE_TYPE imag_value;
+
+      long int value_as_long_ints[N_LONGS_LDOUBLE];
+      u_imag.as_long_double = cimagl(value);
+
+      for (int i = 0; i < N_LONGS_LDOUBLE; i++)
+	value_as_long_ints[i] = u_imag.as_uint32s[i];
+
+      real_from_target (&imag_value, value_as_long_ints, mode);
+
+      real_type = complex_real_to_real (inner_type);
+
+      tree_real = build_real (real_type, real_value);
+      tree_imag = build_real (real_type, imag_value);
+
+      tree inner = build_complex (inner_type, tree_real, tree_imag);
+      return new rvalue (this, inner);
+    }
+  else
+    {
+      tree inner = build_real (inner_type, real_value);
+      return new rvalue (this, inner);
+    }
+}
+
 /* Specialization of making an rvalue from a const, for host <void *>.  */
 
 template <>
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index b3bb6acfeb9..8d34956fc67 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include <pthread.h>
 #include <complex.h>
+#include <float.h>
 
 #include "jit-builtins.h"
 #include "jit-recording.h"
@@ -1734,8 +1735,48 @@ recording::context::dump_reproducer_to_file (const char *path)
 	   " gcc_jit_context_dump_reproducer_to_file.\n\n");
   print_version (r.get_file (), "  ", false);
   r.write ("*/\n");
-  r.write ("#include <libgccjit.h>\n\n");
-  r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
+  r.write (
+    "#include <libgccjit.h>\n"
+    "#include <math.h>\n"
+    "#include <complex.h>\n"
+    "#include <string.h>\n\n");
+  r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n");
+  r.write ("#pragma GCC diagnostic ignored \"-Wunused-function\"\n\n");
+  /* Type punning unions */
+  r.write ("union dull { double d; unsigned long long ull; };\n\n");
+  r.write (
+    "union ldarr { long double ld; unsigned arr[sizeof (long double)];};\n\n");
+
+  /* Functions for type punning nan:s, keeping bit representation */
+  r.write (
+    "/* Convert type punned uint 64 to double NaN.\n"
+    "   Might lose/corrupt payload between architectures. */\n"
+    "static double\n"
+    "ull_to_d (unsigned long long ull)\n"
+    "{\n"
+    "  union dull u; u.ull = ull;\n"
+    "  /* Paranoia check for foreign NaN representation. */\n"
+    "  if (!isnan (u.d)) return NAN;\n"
+    "  return u.d;\n"
+    "}\n\n");
+  r.write (
+    "/* Convert array to long double NaN.\n"
+    "   Might lose/corrupt payload between architectures. */\n"
+    "static long double\n"
+    "arr_to_ld (unsigned char *arr, int len)\n"
+    "{\n"
+    "  union ldarr u;\n"
+    /* Since long double sizes can vary between architectures,
+       we need to handle that. */
+    "  /* For foreign long double sizes */\n"
+    "  if (sizeof u.arr != len) return NAN;\n"
+    "  memcpy (u.arr, arr, len);\n"
+    /* The size might fool us becouse of padding, so check it is a nan. */
+    "  /* Handle foreign representations that is not NaN on this machine. */\n"
+    "  if (!isnan (u.ld)) return NAN;\n"
+    "  return u.ld;\n"
+    "}\n\n");
+
   r.write ("static void\nset_options (");
   r.write_params (contexts);
   r.write (");\n\n");
@@ -4758,8 +4799,11 @@ recording::global::write_reproducer (reproducer &r)
 /* Explicit specialization of the various mementos we're interested in.  */
 template class recording::memento_of_new_rvalue_from_const <int>;
 template class recording::memento_of_new_rvalue_from_const <long>;
+template class recording::memento_of_new_rvalue_from_const <long long>;
 template class recording::memento_of_new_rvalue_from_const <double>;
+template class recording::memento_of_new_rvalue_from_const <long double>;
 template class recording::memento_of_new_rvalue_from_const <_Complex double>;
+template class recording::memento_of_new_rvalue_from_const <_Complex long double>;
 template class recording::memento_of_new_rvalue_from_const <void *>;
 
 /* Implementation of the pure virtual hook recording::memento::replay_into
@@ -4896,6 +4940,70 @@ recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer
 	   m_value);
 	   }
 
+/* The make_debug_string specialization for <long long>, rendering it as
+     (TARGET_TYPE)LITERAL
+   e.g.
+     "(long long)42". */
+
+template <>
+string *
+memento_of_new_rvalue_from_const <long long>::make_debug_string ()
+{
+  return string::from_printf (m_ctxt,
+			      "(%s)%lli",
+			      m_type->get_debug_string (),
+			      m_value);
+}
+
+/* The get_wide_int specialization for <long long>. */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <long long>::get_wide_int (wide_int *out) const
+{
+  *out = wi::shwi (m_value, sizeof (m_value) * 8);
+  return true;
+}
+
+/* The write_reproducer specialization for <long long>. */
+
+template <>
+void
+recording::memento_of_new_rvalue_from_const <long long>::
+write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "rvalue");
+
+  /* Same special case as in long */
+  if (m_value == LONG_LONG_MIN)
+    {
+      r.write (
+	"  gcc_jit_rvalue *%s =\n"
+	"    gcc_jit_context_new_rvalue_from_long_long (\n"
+	"      %s, /* gcc_jit_context *ctxt */\n"
+	"      %s, /* gcc_jit_type *numeric_type */\n"
+	"      %lldLL - 1); /* long long value */\n",
+	id,
+	r.get_identifier (get_context ()),
+	r.get_identifier_as_type (m_type),
+	m_value + 1);
+      return;
+    }
+
+  r.write (
+    "  gcc_jit_rvalue *%s =\n"
+    "    gcc_jit_context_new_rvalue_from_long_long (\n"
+    "      %s, /* gcc_jit_context *ctxt */\n"
+    "      %s, /* gcc_jit_type *numeric_type */\n"
+    "      %lldLL); /* long long value */\n",
+    id,
+    r.get_identifier (get_context ()),
+    r.get_identifier_as_type (m_type),
+    m_value);
+}
+
+
+
 /* The make_debug_string specialization for <double>, rendering it as
      (TARGET_TYPE)LITERAL
    e.g.
@@ -4906,7 +5014,7 @@ string *
 memento_of_new_rvalue_from_const <double>::make_debug_string ()
 {
   return string::from_printf (m_ctxt,
-			      "(%s)%f",
+			      "(%s)%g",
 			      m_type->get_debug_string (),
 			      m_value);
 }
@@ -4920,6 +5028,18 @@ memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
   return false;
 }
 
+/* For typepruning NaNs. */
+union dull {
+  double d;
+  unsigned long long ull;
+};
+
+union ldarr {
+  long double ld;
+  unsigned char arr[sizeof(long double)];
+};
+
+
 /* The write_reproducer specialization for <double>.  */
 
 template <>
@@ -4927,14 +5047,154 @@ void
 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
 {
   const char *id = r.make_identifier (this, "rvalue");
-  r.write ("  gcc_jit_rvalue *%s =\n"
-    "    gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
-    "                                            %s, /* gcc_jit_type *numeric_type */\n"
-    "                                            %f); /* double value */\n",
-    id,
-    r.get_identifier (get_context ()),
-    r.get_identifier_as_type (m_type),
-    m_value);
+
+  if (std::isfinite (m_value))
+    r.write ("  gcc_jit_rvalue *%s =\n"
+      "    gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
+      "                                            %s, /* gcc_jit_type *numeric_type */\n"
+      "                                            /* %.9g */\n"
+      "                                            %a);\n",
+      id,
+      r.get_identifier (get_context ()),
+      r.get_identifier_as_type (m_type),
+      m_value, m_value);
+   else if (std::isinf (m_value))
+     {
+       const char *sign = "";
+       if (m_value < 0)
+	 sign = "-";
+
+       r.write ("  gcc_jit_rvalue *%s =\n"
+	 "    gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
+	 "                                            %s, /* gcc_jit_type *numeric_type */\n"
+	 "                                            /* inf */\n"
+	 "                                            %sINFINITY);\n",
+	 id,
+	 r.get_identifier (get_context ()),
+	 r.get_identifier_as_type (m_type),
+	 sign);
+      }
+    else if (std::isnan (m_value)) {
+      union dull u;
+      u.d = m_value;
+      r.write ("  gcc_jit_rvalue *%s =\n"
+	"    gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
+	"                                            %s, /* gcc_jit_type *numeric_type */\n"
+	"                                            /* NaN */\n"
+	"                                            ull_to_d(%#llx));\n",
+	id,
+	r.get_identifier (get_context ()),
+	r.get_identifier_as_type (m_type),
+	u.ull);
+
+    }
+}
+
+/* The make_debug_string specialization for <long double>, rendering it as
+     (TARGET_TYPE)LITERAL
+   e.g.
+     "(float)42.0".  */
+
+template <>
+string *
+memento_of_new_rvalue_from_const <long double>::make_debug_string ()
+{
+  return string::from_printf (m_ctxt,
+			      "(%s)%Lg",
+			      m_type->get_debug_string (),
+			      m_value);
+}
+
+/* The get_wide_int specialization for <double>.  */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <long double>::get_wide_int (wide_int *) const
+{
+  return false;
+}
+
+/* Helper function for write_reproducer()
+
+   Write an array of unsigned chars to the reproducer, like:
+   {0x12, 0x34, ... } */
+static void
+reproducer_write_arr (reproducer &r, unsigned char *arr, int len)
+{
+  if (len == 0)
+    return;
+
+  r.write ("{");
+  for (int i = 0; i < len - 1; i++)
+    r.write ("%#x , ", arr[i]);
+  r.write ("%#x }", arr[len - 1]);
+}
+
+/* The write_reproducer specialization for <double>.  */
+
+template <>
+void
+recording::memento_of_new_rvalue_from_const <long double>::
+write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "rvalue");
+
+  if (std::isfinite (m_value))
+    r.write (
+      "  gcc_jit_rvalue *%s =\n"
+      "    gcc_jit_context_new_rvalue_from_long_double (\n"
+      "      %s, /* gcc_jit_context *ctxt */\n"
+      "      %s, /* gcc_jit_type *numeric_type */\n"
+      "      /* %.9Lg */\n"
+      "      %LaL); /* long double value */\n",
+      id,
+      r.get_identifier (get_context ()),
+      r.get_identifier_as_type (m_type),
+      m_value, m_value);
+  else if (std::isinf (m_value))
+    {
+      const char *sign = "";
+      if (m_value < 0)
+	sign = "-";
+      r.write (
+      "  gcc_jit_rvalue *%s =\n"
+      "    gcc_jit_context_new_rvalue_from_long_double (\n"
+      "      %s, /* gcc_jit_context *ctxt */\n"
+      "      %s, /* gcc_jit_type *numeric_type */\n"
+      "      /* inf */\n"
+      "      %sINFINITY);\n",
+      id,
+      r.get_identifier (get_context ()),
+      r.get_identifier_as_type (m_type),
+      sign);
+    }
+  else
+    {
+      union ldarr u; /* For type punning to array */
+      u.ld = m_value;
+
+      r.write ("  gcc_jit_rvalue *%s;\n", id);
+      /* Scope for local */
+      r.write ("  { /* long double NaN stored in char arr */\n");
+      /* Write an char arr of the bytes of the NaN */
+      r.write ("    unsigned char arr[] = ");
+      reproducer_write_arr (r, u.arr, sizeof u.arr);
+      r.write (";\n");
+
+      r.write (
+      "    %s =\n"
+      "      gcc_jit_context_new_rvalue_from_long_double (\n"
+      "        %s, /* gcc_jit_context *ctxt */\n"
+      "        %s, /* gcc_jit_type *numeric_type */\n"
+      "        /* %Lg */\n"
+      "        arr_to_ld (arr, sizeof arr));\n",
+      id,
+      r.get_identifier (get_context ()),
+      r.get_identifier_as_type (m_type),
+      m_value);
+
+      r.write ("  }\n"); /* Close scope */
+    }
 }
 
 /* The make_debug_string specialization for <double complex>, rendering it as
@@ -4964,7 +5224,7 @@ get_wide_int (wide_int *) const
   return false;
 }
 
-/* The write_reproducer specialization for <double>.  */
+/* The write_reproducer specialization for <_Complex double>.  */
 
 template <>
 void
@@ -4974,14 +5234,164 @@ write_reproducer (reproducer &r)
   const char *id = r.make_identifier (this, "rvalue");
   double real = creal(m_value);
   double imag = cimag(m_value);
-  r.write ("  gcc_jit_rvalue *%s =\n"
-    "    gcc_jit_context_new_rvalue_from_complex_double (%s, /* gcc_jit_context *ctxt */\n"
-    "                                            %s, /* gcc_jit_type *numeric_type */\n"
-    "                                            %f+%fj); /* double value */\n",
+
+  r.write (
+    "  gcc_jit_rvalue *%s =\n"
+    "    gcc_jit_context_new_rvalue_from_complex_double (\n"
+    "      %s, /* gcc_jit_context *ctxt */\n"
+    "      %s, /* gcc_jit_type *numeric_type */\n"
+    "      /* %.9g + %.9gj */\n"
+    "      CMPLX (",/* ... real, imag)); */
+    id,
+    r.get_identifier (get_context ()),
+    r.get_identifier_as_type (m_type),
+    real, imag);
+
+  if (std::isfinite (real))
+    r.write("%a,", real);
+  else if (std::isinf (real))
+    {
+      if (real < 0)
+	r.write ("-INFINITY,");
+      else
+	r.write ("INFINITY,");
+    }
+  else /* NaN */
+    {
+      /* Store the NaN as a unsigned long long literal.
+	 ull_to_d() will convert it back to double */
+      union dull u;
+      u.d = real;
+      r.write ("ull_to_d (%#llx),", u.ull);
+    }
+
+  if (std::isfinite (imag))
+    r.write("%a)", imag);
+  else if (std::isinf (imag))
+    {
+      if (real < 0)
+	r.write ("-INFINITY)");
+      else
+	r.write ("INFINITY)");
+    }
+  else /* NaN */
+    {
+      union dull u;
+      u.d = imag;
+      r.write ("ull_to_d (%#llx))", u.ull);
+    }
+
+  r.write (");\n\n"); /* Close the function call */
+}
+
+template <>
+string *
+memento_of_new_rvalue_from_const <_Complex long double>::make_debug_string ()
+{
+  long double real = creall(m_value);
+  long double imag = cimagl(m_value);
+  return string::from_printf (m_ctxt,
+			      "(%s)(%Lg%+Lgj)",
+			      m_type->get_debug_string (),
+			      real, imag);
+}
+
+/* The get_wide_int specialization for <_Complex long double>.  */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <_Complex long double>::
+get_wide_int (wide_int *) const
+{
+  return false;
+}
+
+/* The write_reproducer specialization for <_Complex long double>.  */
+
+template <>
+void
+recording::memento_of_new_rvalue_from_const <_Complex long double>::
+write_reproducer (reproducer &r)
+{
+  union ldarr ureal, uimag;
+  const char *id = r.make_identifier (this, "rvalue");
+  long double real = creall(m_value);
+  long double imag = cimagl(m_value);
+
+  int has_nan = std::isnan (real) || std::isnan (imag);
+
+  if (has_nan)
+    {
+      r.write ("  gcc_jit_rvalue *%s;\n", id);
+      /* Scope for multiple "NaN-arrays" in the source file  to not clash */
+      r.write ("  {\n");
+    }
+  if (std::isnan (real))
+    {
+      /* Write the raw bytes of the long double as an char array
+	 to store it in the source code.
+	 I.e. unsigned char arr[] = {0x1, 0x2, 0x3 ... }; */
+      ureal.ld = real;
+      r.write ("    unsigned char arr_real[] = ");
+      reproducer_write_arr (r, ureal.arr, sizeof ureal.arr);
+      r.write (";\n");
+    }
+  if (std::isnan (imag))
+    {
+      uimag.ld = imag;
+      r.write ("    unsigned char arr_imag[] = ");
+      reproducer_write_arr (r, uimag.arr, sizeof uimag.arr);
+      r.write (";\n");
+    }
+
+  if (has_nan)
+    r.write ("  "); /* Definition is outside the scope for NaNs */
+  else
+    r.write ("  gcc_jit_rvalue *");
+
+  r.write ("%s =\n"
+    "    gcc_jit_context_new_rvalue_from_complex_long_double (\n"
+    "      %s, /* gcc_jit_context *ctxt */\n"
+    "      %s, /* gcc_jit_type *numeric_type */\n"
+    "      /* %.9Lg + i*%.9Lg */\n"
+    "      CMPLXL (",
     id,
     r.get_identifier (get_context ()),
     r.get_identifier_as_type (m_type),
     real, imag);
+
+  if (std::isfinite (real))
+    r.write ("%LaL, ", real);
+  else if (std::isinf (real))
+    {
+      if (real < 0)
+	r.write ("-INFINITY, ");
+      else
+	r.write ("INFINITY, ");
+    }
+  else if (std::isnan (real))
+    {
+      /* Convert the char array written above, to a long double */
+      r.write ("arr_to_ld (arr_real, sizeof arr_real), ");
+    }
+
+  if (std::isfinite (imag))
+    r.write ("%LaL)", imag);
+  else if (std::isinf (imag))
+    {
+      if (imag < 0)
+	r.write ("-INFINITY)");
+      else
+	r.write ("INFINITY)");
+    }
+  else if (std::isnan (imag))
+    {
+      r.write ("arr_to_ld (arr_imag, sizeof arr_imag))");
+    }
+  r.write(");\n\n"); /* Close function call */
+
+  if (has_nan)
+    r.write ("  }\n"); /* Close NaN-array scope */
 }
 
 /* The make_debug_string specialization for <void *>, rendering it as
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index c97aeb82812..b94cdc85c8e 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -188,12 +188,18 @@ namespace gccjit
 		       int value) const;
     rvalue new_rvalue (type numeric_type,
 		       long value) const;
+    rvalue new_rvalue (type numeric_type,
+		       long long value) const;
     rvalue zero (type numeric_type) const;
     rvalue one (type numeric_type) const;
     rvalue new_rvalue (type numeric_type,
 		       double value) const;
+    rvalue new_rvalue (type numeric_type,
+		       long double value) const;
     rvalue new_rvalue (type numeric_type,
 		       _Complex double value) const;
+    rvalue new_rvalue (type numeric_type,
+		       _Complex long double value) const;
     rvalue new_rvalue (type pointer_type,
 		       void *value) const;
     rvalue new_rvalue (const std::string &value) const;
@@ -936,6 +942,17 @@ context::new_rvalue (type numeric_type,
 					  value));
 }
 
+inline rvalue
+context::new_rvalue (type numeric_type,
+		     long long value) const
+{
+  return rvalue (
+    gcc_jit_context_new_rvalue_from_long_long (
+      m_inner_ctxt,
+      numeric_type.get_inner_type (),
+      value));
+}
+
 inline rvalue
 context::zero (type numeric_type) const
 {
@@ -960,6 +977,17 @@ context::new_rvalue (type numeric_type,
 					    value));
 }
 
+inline rvalue
+context::new_rvalue (type numeric_type,
+		     long double value) const
+{
+  return rvalue (
+    gcc_jit_context_new_rvalue_from_long_double (
+      m_inner_ctxt,
+      numeric_type.get_inner_type (),
+      value));
+}
+
 inline rvalue
 context::new_rvalue (type numeric_type,
 		     _Complex double value) const
@@ -971,6 +999,17 @@ context::new_rvalue (type numeric_type,
       value));
 }
 
+inline rvalue
+context::new_rvalue (type numeric_type,
+		     _Complex long double value) const
+{
+  return rvalue (
+    gcc_jit_context_new_rvalue_from_complex_long_double (
+      m_inner_ctxt,
+      numeric_type.get_inner_type (),
+      value));
+}
+
 inline rvalue
 context::new_rvalue (type pointer_type,
 		     void *value) const
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 64630b810f4..97c5aba643e 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -1275,6 +1275,19 @@ gcc_jit_context_new_rvalue_from_long (gcc_jit_context *ctxt,
 	  ->new_rvalue_from_const <long> (numeric_type, value));
 }
 
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_long_long (gcc_jit_context *ctxt,
+					   gcc_jit_type *numeric_type,
+					   long long value)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type);
+
+  return ((gcc_jit_rvalue *)ctxt
+	  ->new_rvalue_from_const <long long> (numeric_type, value));
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    This is essentially equivalent to:
@@ -1328,6 +1341,19 @@ gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt,
 	  ->new_rvalue_from_const <double> (numeric_type, value));
 }
 
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_long_double (gcc_jit_context *ctxt,
+					     gcc_jit_type *numeric_type,
+					     long double value)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type);
+
+  return ((gcc_jit_rvalue *)ctxt
+	  ->new_rvalue_from_const <long double> (numeric_type, value));
+}
+
 gcc_jit_rvalue *
 gcc_jit_context_new_rvalue_from_complex_double (gcc_jit_context *ctxt,
 						gcc_jit_type *numeric_type,
@@ -1347,6 +1373,26 @@ gcc_jit_context_new_rvalue_from_complex_double (gcc_jit_context *ctxt,
 	   ->new_rvalue_from_const <double _Complex> (numeric_type, value));
 }
 
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_complex_long_double (
+  gcc_jit_context *ctxt,
+  gcc_jit_type *numeric_type,
+  _Complex long double value)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type);
+
+  RETURN_NULL_IF_FAIL_PRINTF1 (
+    numeric_type->is_float (),
+    ctxt, NULL,
+    "not a floating point type (type: %s)",
+    numeric_type->get_debug_string ());
+
+  return ((gcc_jit_rvalue *)ctxt
+      ->new_rvalue_from_const <_Complex long double> (numeric_type, value));
+}
+
 
 /* Public entrypoint.  See description in libgccjit.h.
 
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index d4b10fc0644..c510c5cc902 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -834,6 +834,16 @@ gcc_jit_context_new_rvalue_from_long (gcc_jit_context *ctxt,
 				      gcc_jit_type *numeric_type,
 				      long value);
 
+#define LIBGCCJIT_HAVE_LONGLONG_CONSTANTS
+/* Get a constant from a long long.
+
+   This function was added in LIBGCCJIT_ABI_16. You can test for
+   its presens with:
+     #ifdef LIBGCCJIT_HAVE_LONGLONG_CONSTANTS */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_long_long (gcc_jit_context *ctxt,
+					   gcc_jit_type *numeric_type,
+					   long long value);
 extern gcc_jit_rvalue *
 gcc_jit_context_zero (gcc_jit_context *ctxt,
 		      gcc_jit_type *numeric_type);
@@ -848,7 +858,17 @@ gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt,
 					gcc_jit_type *numeric_type,
 					double value);
 
-/* Complex floating-point constants.
+/* Get a constant from a long double.
+
+   This function was added in LIBGCCJIT_ABI_16. You can test for
+   its presence with:
+     #ifdef LIBGCCJIT_HAVE_LONGLONG_CONSTANTS */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_long_double (gcc_jit_context *ctxt,
+					     gcc_jit_type *numeric_type,
+					     long double value);
+
+/* Get a constant from a complex double.
 
    This API entrypoint was added in LIBGCCJIT_ABI_16; you can test for its
    presence using
@@ -858,6 +878,17 @@ gcc_jit_context_new_rvalue_from_complex_double (gcc_jit_context *ctxt,
 						gcc_jit_type *numeric_type,
 						_Complex double value);
 
+/* Get a constant from a complex long double.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_16; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_LONGLONG_CONSTANTS */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_complex_long_double (
+  gcc_jit_context *ctxt,
+  gcc_jit_type *numeric_type,
+  _Complex long double value);
+
 /* Pointers.  */
 extern gcc_jit_rvalue *
 gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index c9b044dc8f5..4022dbb6fbc 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -209,5 +209,8 @@ LIBGCCJIT_ABI_15 {
 LIBGCCJIT_ABI_16 {
   global:
     gcc_jit_context_new_rvalue_from_complex_double;
+    gcc_jit_context_new_rvalue_from_complex_long_double;
     gcc_jit_context_set_bool_enable_complex_types;
+    gcc_jit_context_new_rvalue_from_long_double;
+    gcc_jit_context_new_rvalue_from_long_long;
 } LIBGCCJIT_ABI_15;
\ No newline at end of file
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 7b45acd4b9c..8416b312bad 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -239,6 +239,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-long-literals.c */
+#define create_code create_code_long_literals
+#define verify_code verify_code_long_literals
+#include "test-long-literals.c"
+#undef create_code
+#undef verify_code
+
 /* test-long-string-literal.c */
 #define create_code create_code_long_string_literal
 #define verify_code verify_code_long_string_literal
diff --git a/gcc/testsuite/jit.dg/test-long-literals.c b/gcc/testsuite/jit.dg/test-long-literals.c
new file mode 100644
index 00000000000..a83af8b0eb1
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-long-literals.c
@@ -0,0 +1,283 @@
+/* Test long literals.
+
+   I.e. long long, long double and long complex doubles.
+
+   Also test NaN:s and inf:s with double. */
+
+
+#include <complex.h>
+#include <limits.h>
+#include <math.h>
+#include <string.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+int compare_nans(double d1, double d2)
+{
+  union {double d; unsigned long long ull;} u1, u2;
+
+  u1.d = d1;
+  u2.d = d2;
+
+  return u1.ull == u2.ull;
+}
+
+int compare_nansl(long double d1, long double d2)
+{
+  union { long double ld; unsigned char arr[sizeof (long double)];}
+    u1 = {.arr = {0}},
+    u2 = {.arr = {0}};
+  /* Zero the arrs. I don't know if long double zeroes all its size
+     since some of it is padding. */
+
+  u1.ld = d1;
+  u2.ld = d2;
+
+  return memcmp (u1.arr, u2.arr, sizeof u1.arr) == 0;
+}
+
+static void
+make_code_lit_cld(gcc_jit_context *ctxt,
+                  const char *fn_name,
+                  int type,
+                  _Complex long double local_val,
+                  int lit_type)
+{
+  gcc_jit_type *tt = gcc_jit_context_get_type (ctxt, type);
+
+  gcc_jit_function *foo = gcc_jit_context_new_function (ctxt, 0,
+    GCC_JIT_FUNCTION_EXPORTED,
+    tt, fn_name, 0, 0, 0);
+
+  gcc_jit_block *block = gcc_jit_function_new_block (foo, "start");
+
+  /* local_type f1 = local_val; */
+  gcc_jit_lvalue *f1 = gcc_jit_function_new_local (foo, 0, tt, "f1");
+
+  gcc_jit_rvalue *r1;
+
+  if (lit_type == 'L')
+    r1 = gcc_jit_context_new_rvalue_from_long_double (
+      ctxt, tt, creall(local_val));
+  else if (lit_type == 'C')
+    r1 = gcc_jit_context_new_rvalue_from_complex_long_double (
+      ctxt, tt, local_val);
+
+  gcc_jit_block_add_assignment (block, 0, f1, r1);
+
+  gcc_jit_block_end_with_return (block, 0, gcc_jit_lvalue_as_rvalue(f1));
+}
+
+static void
+make_code_lit_d (gcc_jit_context *ctxt,
+                 const char *fn_name,
+                 int type,
+                 _Complex  double local_val,
+                int lit_type)
+{
+  gcc_jit_type *tt = gcc_jit_context_get_type (ctxt, type);
+
+  gcc_jit_function *foo = gcc_jit_context_new_function (ctxt, 0,
+    GCC_JIT_FUNCTION_EXPORTED,
+    tt, fn_name, 0, 0, 0);
+
+  gcc_jit_block *block = gcc_jit_function_new_block (foo, "start");
+
+  /* local_type f1 = local_val; */
+  gcc_jit_lvalue *f1 = gcc_jit_function_new_local (foo, 0, tt, "f1");
+
+  gcc_jit_rvalue *r1;
+
+  if (lit_type == 'd')
+    r1 = gcc_jit_context_new_rvalue_from_double (
+      ctxt, tt, local_val);
+  else if (lit_type == 'c')
+    r1 = gcc_jit_context_new_rvalue_from_complex_double (
+      ctxt, tt, local_val);
+
+  gcc_jit_block_add_assignment (block, 0, f1, r1);
+
+  gcc_jit_block_end_with_return (block, 0, gcc_jit_lvalue_as_rvalue(f1));
+}
+
+static void
+make_code_lit_ll (gcc_jit_context *ctxt,
+                  const char *fn_name,
+                  int type,
+                  long long local_val)
+{
+  gcc_jit_type *tt = gcc_jit_context_get_type (ctxt, type);
+
+  gcc_jit_function *foo = gcc_jit_context_new_function (ctxt, 0,
+    GCC_JIT_FUNCTION_EXPORTED,
+    tt, fn_name, 0, 0, 0);
+
+  gcc_jit_block *block = gcc_jit_function_new_block (foo, "start");
+
+  /* local_type f1 = local_val; */
+  gcc_jit_lvalue *f1 = gcc_jit_function_new_local (foo, 0, tt, "f1");
+
+  gcc_jit_rvalue *r1;
+
+  r1 = gcc_jit_context_new_rvalue_from_long_long (
+    ctxt, tt, creall(local_val));
+
+  gcc_jit_block_add_assignment (block, 0, f1, r1);
+
+  gcc_jit_block_end_with_return (block, 0, gcc_jit_lvalue_as_rvalue(f1));
+}
+
+
+union uu { double d; long long l; } u;
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  (void) user_data;
+
+  gcc_jit_context_set_bool_enable_complex_types (ctxt, 1);
+
+  make_code_lit_cld (ctxt, "long_double_ldlit_1c1",
+    GCC_JIT_TYPE_LONG_DOUBLE,
+    -1.1L, 'L');
+  make_code_lit_cld (ctxt, "long_double_ldlit_1Ldiv3L",
+    GCC_JIT_TYPE_LONG_DOUBLE,
+    1/3.L, 'L');
+  make_code_lit_cld (ctxt, "long_double_ldlit_inf",
+    GCC_JIT_TYPE_LONG_DOUBLE,
+    INFINITY, 'L');
+  make_code_lit_cld (ctxt, "long_double_ldlit_minf",
+    GCC_JIT_TYPE_LONG_DOUBLE,
+    -INFINITY, 'L');
+  make_code_lit_cld (ctxt, "long_double_ldlit_nan1",
+    GCC_JIT_TYPE_LONG_DOUBLE,
+    nanl("1"), 'L');
+
+  make_code_lit_cld (ctxt, "complex_long_double_cldlit_1div3_2div3j",
+    GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
+    1/3.L + 2.Lj/3, 'C');
+
+  make_code_lit_cld (ctxt, "complex_long_double_cldlit_inf_infj",
+    GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
+    CMPLXL (INFINITY, INFINITY), 'C');
+  make_code_lit_cld (ctxt, "complex_long_double_cldlit_minf_minfj",
+    GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
+    CMPLXL (-INFINITY, -INFINITY), 'C');
+  make_code_lit_cld (ctxt, "complex_long_double_cldlit_nan1_nan2j",
+    GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE,
+    CMPLXL (nanl ("1"), nanl ("2")), 'C');
+
+  make_code_lit_ll (ctxt, "long_long_lllit_2",
+    GCC_JIT_TYPE_LONG_LONG,
+    2);
+
+  make_code_lit_ll (ctxt, "long_long_lllit_min",
+    GCC_JIT_TYPE_LONG_LONG,
+    LLONG_MIN);
+
+  make_code_lit_ll (ctxt, "long_long_lllit_max",
+    GCC_JIT_TYPE_LONG_LONG,
+    LLONG_MAX);
+
+  make_code_lit_ll (ctxt, "ulong_long_lllit_max",
+    GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
+    ULLONG_MAX);
+
+  make_code_lit_d (ctxt, "double_nan1",
+    GCC_JIT_TYPE_DOUBLE,
+    nan("1"), 'd');
+  make_code_lit_d (ctxt, "double_inf",
+    GCC_JIT_TYPE_DOUBLE,
+    INFINITY, 'd');
+  make_code_lit_d (ctxt, "double_minf",
+    GCC_JIT_TYPE_DOUBLE,
+    -INFINITY, 'd');
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_NON_NULL (result);
+  {
+    double (*f)() = gcc_jit_result_get_code (
+      result, "double_nan1");
+
+    CHECK(compare_nans (f(), nan("1")));
+  }
+  {
+    double (*f)() = gcc_jit_result_get_code (
+      result, "double_inf");
+
+    CHECK_VALUE (f(), INFINITY);
+  }
+  {
+    double (*f)() = gcc_jit_result_get_code (
+      result, "double_minf");
+
+    CHECK_VALUE (f(), -INFINITY);
+  }
+  {
+    long double (*f)() = gcc_jit_result_get_code (
+      result, "long_double_ldlit_1c1");
+
+    CHECK_VALUE(f (), -1.1L);
+  }
+  {
+    long double (*f)() = gcc_jit_result_get_code (
+      result, "long_double_ldlit_1Ldiv3L");
+
+    CHECK_VALUE(f (), 1.L/3.L);
+  }
+  {
+    _Complex long double (*f)() = gcc_jit_result_get_code (
+      result, "complex_long_double_cldlit_1div3_2div3j");
+
+    CHECK_VALUE (f(), 1/3.L + 2.Lj/3);
+  }
+  {
+    _Complex long double (*f)() = gcc_jit_result_get_code (
+      result, "complex_long_double_cldlit_inf_infj");
+
+    CHECK_VALUE (f(),CMPLXL (INFINITY, INFINITY));
+  }
+  {
+    _Complex long double (*f)() = gcc_jit_result_get_code (
+      result, "complex_long_double_cldlit_minf_minfj");
+
+    CHECK_VALUE (f(),CMPLXL (-INFINITY, -INFINITY));
+  }
+  {
+    _Complex long double (*f)() = gcc_jit_result_get_code (
+      result, "complex_long_double_cldlit_nan1_nan2j");
+    _Complex double key = CMPLXL (nanl ("1"), nanl ("2"));
+    _Complex double ans = f();
+
+    CHECK (compare_nansl (creall (key), creall (ans)));
+    CHECK (compare_nansl (cimagl (key), cimagl (ans)));
+  }
+  {
+    long long (*f)() = gcc_jit_result_get_code (
+      result, "long_long_lllit_2");
+
+    CHECK_VALUE (f(), 2);
+  }
+  {
+    long long (*f)() = gcc_jit_result_get_code (
+      result, "long_long_lllit_min");
+
+    CHECK_VALUE (f(), LLONG_MIN);
+  }
+  {
+    long long (*f)() = gcc_jit_result_get_code (
+      result, "long_long_lllit_max");
+
+    CHECK_VALUE (f(), LLONG_MAX);
+  }
+  {
+    unsigned long long (*f)() = gcc_jit_result_get_code (
+      result, "ulong_long_lllit_max");
+
+    CHECK_VALUE (f(), ULLONG_MAX);
+  }
+}
-- 
2.30.2

