public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
From: Petter Tomner <tomner@kth.se>
To: "jit@gcc.gnu.org" <jit@gcc.gnu.org>
Subject: SV: [RFC] Setting data segment and loong constants - WIP
Date: Thu, 21 Oct 2021 13:27:08 +0000	[thread overview]
Message-ID: <67377ebd1d90482aa1123121d344cf92@kth.se> (raw)
In-Reply-To: <626c20889db34821ae574cae072b26c0@kth.se>

[-- Attachment #1: Type: text/plain, Size: 506 bytes --]

I think I more or less got a working patch for constructors and global rvalue init.

The remaining concern is that type matching on the other entry points
only remove one qualifier (not recursive), and does not match on eg. 
"pointer to const x" made from different function calls. Which makes cast 
pretty much mandatory for any nested type.

I made a "strip all and compare types" for the new entrypoints, but I wonder if that
just makes it more confusing for the user?

I attached a WIP patch.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-ctor.patch --]
[-- Type: text/x-patch; name="0003-ctor.patch", Size: 130533 bytes --]

From b69a55876a44187ffabec6ee37509f76e4a74a97 Mon Sep 17 00:00:00 2001
From: Petter Tomner <tomner@kth.se>
Date: Fri, 15 Oct 2021 20:17:40 +0200
Subject: [PATCH 3/3] ctor

Add suport for global rvalue initialization and ctors

This patch adds support for initialization of global variables
with rvalues and creating constructors for array, struct and
union types which can be used as rvalues.

gcc/jit/
	* jit-playback.c :
	(global_new_decl) : Handle const global generation
	(new_global) : New flag
	(global_set_init_rvalue) : New
	(new_ctor) : New
	(new_global_initialized) : Flag
	(as_truth_value) : Fold
	(new_unary_op) : Fold
	(new_binary_op) : Fold
	(new_comparison) : Fold
	(new_array_access) : Fold
	(new_dereference) : Fold
	(get_address) : Fold
	* jit-playback.h :
	(rvalue::as_tree) : Fold to DECL_INITIAL for const VAR_DECL
	* jit-recording.c : See .h
	* jit-recording.h :
	(new_global_init_rvalue) : New
	(new_ctor) : New
	(ctor) : New, inherits rvalue
	(global_init_rvalue) : New, inherits memento
	(type::is_struct) : New
	(type::is_union) : New
	(field::get_name) : New
	* libgccjit++.h : New entrypoints
	* libgccjit.c : See .h
	* libgccjit.h :
	(gcc_jit_context_new_constructor) : New
	(gcc_jit_global_set_initializer_rvalue) : New
	(LIBGCCJIT_HAVE_CTORS) : New
	* libgccjit.map : New entrypoints added to ABI 16

gcc/testsuite/
	* jit.dg/test-error-global-init-too-small-array.c : All new
	* jit.dg/test-error-global-lvalue-init.c
	* jit.dg/test-error-global-nonconst-init.c
	* jit.dg/test-global-init-rvalue.c
	* jit.dg/test-local-init-rvalue.c

gcc/jit/docs/topics/
	* expressions.rst : Updated docs
---
 gcc/jit/docs/topics/expressions.rst           |   89 ++
 gcc/jit/jit-common.h                          |    9 +
 gcc/jit/jit-playback.c                        |  280 +++-
 gcc/jit/jit-playback.h                        |   25 +-
 gcc/jit/jit-recording.c                       |  436 +++++-
 gcc/jit/jit-recording.h                       |   92 ++
 gcc/jit/libgccjit++.h                         |   44 +
 gcc/jit/libgccjit.c                           |  229 ++-
 gcc/jit/libgccjit.h                           |   77 +
 gcc/jit/libgccjit.map                         |    4 +-
 gcc/testsuite/jit.dg/all-non-failing-tests.h  |   14 +
 .../jit.dg/test-error-ctor-struct-too-big.c   |   86 +
 .../test-error-ctor-struct-wrong-field-name.c |   81 +
 .../test-error-ctor-struct-wrong-type.c       |   85 +
 .../test-error-ctor-union-wrong-field-name.c  |   80 +
 .../jit.dg/test-error-global-allready-init.c  |   46 +
 .../jit.dg/test-error-global-common-section.c |   54 +
 .../test-error-global-init-too-small-array.c  |   64 +
 .../jit.dg/test-error-global-lvalue-init.c    |   60 +
 .../jit.dg/test-error-global-nonconst-init.c  |   80 +
 .../jit.dg/test-global-init-rvalue.c          | 1394 +++++++++++++++++
 gcc/testsuite/jit.dg/test-local-init-rvalue.c |  576 +++++++
 22 files changed, 3880 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-error-ctor-struct-too-big.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-field-name.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-type.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-ctor-union-wrong-field-name.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-global-allready-init.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-global-common-section.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-global-init-too-small-array.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-global-lvalue-init.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-global-nonconst-init.c
 create mode 100644 gcc/testsuite/jit.dg/test-global-init-rvalue.c
 create mode 100644 gcc/testsuite/jit.dg/test-local-init-rvalue.c

diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 30a3b9780f9..3a1738e4628 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -176,6 +176,63 @@ Simple expressions
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function:: gcc_jit_rvalue *\
+	      gcc_jit_context_new_constructor (gcc_jit_context *ctxt,\
+                                               gcc_jit_location *loc,\
+				               gcc_jit_type *type,\
+				               size_t arr_length,\
+				               gcc_jit_field **fields,\
+				               gcc_jit_rvalue **values)
+
+   Create a constructor for an array, union or struct as a rvalue.
+
+   Returns NULL on error. The two parameter arrays are copied and
+   do not have to outlive the context.
+
+   ``type`` specifies what the constructor will build.
+
+   For a struct or union ``type``, each field in ``fields`` specifies
+   which field in the struct or union type to set to the corresponding
+   value in ``values``. ``fields`` and ``values`` are paired by index
+   and the pair need to have the same unqualified type.
+
+   For an array ``type``, the ``fields`` parameter is ignored.
+   
+   ``arr_length`` specifies the number of elements in ``values``.
+   For struct and unions, ``fields`` need to have the same length as
+   ``values``.
+
+   For unions, ``arr_length`` need to be 1.
+
+   For non-unions, if ``arr_length`` is 0, the array parameters will be
+   ignored and zero initialization will be used.
+ 
+   For an array ``type``, if the array type itself has more elements than
+   ``values``, the left-over elements will be zeroed. Each value in
+   ``values`` need to be the same unqualified type as the array elements.
+
+   For a struct ``type``, the fields in ``fields`` do not have to be in
+   definition order, but being in order avoids a sort operation. Any
+   field in the struct that is not specified in ``fields`` will be zeroed.
+      
+   A NULL value in ``values`` is a shorthand for zero initialization
+   of the corresponding field or array element. 
+
+   The constructor rvalue can be used for assignment to locals.
+   It can be used to initialize global variables with
+   :func:`gcc_jit_global_set_initializer_rvalue`. It can also be used as a
+   temporary value for function calls and return values.
+
+   The constructor can contain nested constructors. Note that a string
+   literal rvalue can't be used to construct a char array. It need one
+   rvalue for each char.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_16`; you can test for its
+   presense using:
+
+   .. code-block:: c
+     #ifdef LIBGCCJIT_HAVE_CTORS
+
 Vector expressions
 ******************
 
@@ -681,6 +738,38 @@ Global variables
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
 
+.. function:: gcc_jit_lvalue *\
+	      gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
+	                                             gcc_jit_rvalue *init_value)
+
+   Set the initial value of a global with an rvalue.
+
+   The rvalue need to be a constant expression, i.e. no function calls.
+
+   The global can't have the ``kind`` :ref:`GCC_JIT_GLOBAL_IMPORTED`.
+   
+   As a non-comprehensive example it is OK to do the equivalent of:
+
+   .. code-block:: c
+
+       int foo = 3 * 2; /* rvalue from gcc_jit_context_new_binary_op */
+       int arr[] = {1,2,3,4}; /* rvalue from gcc_jit_context_new_constructor */
+       int *bar = &arr[2] + 1; /* rvalue from nested "get address" of "array access" */
+       const int baz = 3; /* rvalue from gcc_jit_context_rvalue_from_int */
+       int boz = baz; /* rvalue from gcc_jit_lvalue_as_rvalue */
+
+   Use together with :ref:`gcc_jit_context_new_constructor` to
+   initialize structs, unions and arrays.
+
+   On success, returns the ``global`` parameter unchanged. Otherwise, ``NULL``.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_16`; you can test for its
+   presence using:
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_CTORS
+
 Working with pointers, structs and unions
 -----------------------------------------
 
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index bc0453fba05..7c937478793 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -203,6 +203,15 @@ enum inner_bool_option
   NUM_INNER_BOOL_OPTIONS
 };
 
+/* Flags for global variables class. For when the playback of the
+   global need to know what will happen to it later. */
+enum global_var_flags
+{
+  GLOBAL_VAR_FLAGS_NONE = 0,
+  GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT = 1,
+  GLOBAL_VAR_FLAGS_WILL_BE_BLOB_INIT = 2,
+};
+
 } // namespace gcc::jit
 
 } // namespace gcc
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 1f4dc31a1c1..914afd6bd9f 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -107,6 +107,43 @@ namespace jit {
  Playback.
  **********************************************************************/
 
+/* Fold a readonly non-volatile variable with an initial constant value,
+   to that value.
+
+   Otherwise return the argument unchanged.
+
+   This fold is needed for setting a variable's DECL_INITIAL to the value
+   of a const variable. The c-frontend does this in its own special
+   fold(), so we lift this part out and do it explicitly where there is a
+   potential for variables to be used as rvalues. */
+static tree
+fold_const_var (tree node)
+{
+  /* See c_fully_fold_internal in c-fold.c and decl_constant_value_1
+     in c-typeck.c */
+  if (VAR_P (node)
+      && TREE_READONLY (node)
+      && !TREE_THIS_VOLATILE (node)
+      && DECL_INITIAL (node) != NULL_TREE
+      /* "This is invalid if initial value is not constant.
+	  If it has either a function call, a memory reference,
+	  or a variable, then re-evaluating it could give different
+	  results." */
+      && TREE_CONSTANT (DECL_INITIAL (node)))
+    {
+      tree ret = DECL_INITIAL (node);
+      /* "Avoid unwanted tree sharing between the initializer and current
+	  function's body where the tree can be modified e.g. by the
+	  gimplifier."  */
+      if (TREE_STATIC (node))
+	ret = unshare_expr (ret);
+
+      return ret;
+    }
+
+  return node;
+}
+
 /* Build a STRING_CST tree for STR, or return NULL if it is NULL.
    The TREE_TYPE is not initialized.  */
 
@@ -547,15 +584,28 @@ playback::context::
 global_new_decl (location *loc,
 		 enum gcc_jit_global_kind kind,
 		 type *type,
-		 const char *name)
+		 const char *name,
+		 enum global_var_flags flags)
 {
   gcc_assert (type);
   gcc_assert (name);
+
+  tree type_tree = type->as_tree ();
+
   tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
 			   get_identifier (name),
-			   type->as_tree ());
+			   type_tree);
+
   TREE_PUBLIC (inner) = (kind != GCC_JIT_GLOBAL_INTERNAL);
-  DECL_COMMON (inner) = 1;
+
+
+  int will_be_init = flags & (GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT |
+			      GLOBAL_VAR_FLAGS_WILL_BE_BLOB_INIT);
+
+  /* A VAR_DECL with DECL_INITIAL will not end up in .common section */
+  if (!will_be_init)
+    DECL_COMMON (inner) = 1;
+
   switch (kind)
     {
     default:
@@ -574,6 +624,9 @@ global_new_decl (location *loc,
       break;
     }
 
+  if (TYPE_READONLY (type_tree))
+    TREE_READONLY(inner) = 1;
+
   if (loc)
     set_tree_location (inner, loc);
 
@@ -598,13 +651,178 @@ playback::context::
 new_global (location *loc,
 	    enum gcc_jit_global_kind kind,
 	    type *type,
-	    const char *name)
+	    const char *name,
+	    enum global_var_flags flags)
 {
-  tree inner = global_new_decl (loc, kind, type, name);
+  tree inner =
+    global_new_decl (loc, kind, type, name, flags);
 
   return global_finalize_lvalue (inner);
 }
 
+/* Helper function for usage with walk_tree in global_set_init_rvalue.
+   If the tree contains a DECL_VAR without DECL_INITIAL set, it will be
+   returned.
+
+   Otherwise, returns NULL_TREE. */
+static tree
+validate_var_has_init (tree *tp, int *walk_subtree, void *data)
+{
+  (void) data;
+  (void) walk_subtree;
+
+  if (VAR_P (*tp) && DECL_INITIAL (*tp) == NULL_TREE)
+    return *tp;
+  return NULL_TREE;
+}
+
+void
+playback::context::
+global_set_init_rvalue (lvalue* variable,
+			rvalue* init)
+{
+  tree inner = variable->as_tree ();
+
+  /* We need to fold all expressions as much as possible. The code
+     for a DECL_INITIAL only handles some operations,
+     etc addition, minus, 'address of'. See output_addressed_constants()
+     in varasm.c  */
+  tree init_tree = init->as_tree ();
+  tree folded = fold_const_var (init_tree);
+
+  if (!TREE_CONSTANT (folded))
+    {
+      tree name = DECL_NAME (inner);
+
+      add_error (NULL,
+		 "init rvalue for the global variable %s does not seem"
+		 " to be constant",
+		 name != NULL_TREE ? IDENTIFIER_POINTER (name) : NULL);
+      return;
+    }
+
+  /* Find any VAR_DECL without DECL_INITIAL set.
+     Assume that any ..._CST is OK to save some CPU.
+     Handle CONSTRUCTORs explicitly to avoid tree walks
+     on array inits consisting of only ..._CSTs. */
+  tree sinner = NULL_TREE;
+  
+  if (TREE_CODE (folded) == CONSTRUCTOR)
+    {
+      unsigned HOST_WIDE_INT idx;
+      tree elt;
+      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (folded), idx, elt)
+	{
+	  if (!CONSTANT_CLASS_P (elt))
+	    sinner = walk_tree (&elt, validate_var_has_init, NULL, NULL);
+	  if (sinner != NULL_TREE)
+	    break;
+	}
+    }
+  else if (!CONSTANT_CLASS_P (folded))
+    sinner = walk_tree (&folded, validate_var_has_init, NULL, NULL);
+
+  if (sinner != NULL_TREE)
+    {
+      tree name = DECL_NAME (inner);
+      tree rvname = DECL_NAME (sinner);
+      add_error (NULL,
+		 "can't initialize %s with %s since it has no "
+		 "initial value set",
+		 name != NULL_TREE ? IDENTIFIER_POINTER (name) : NULL,
+		 rvname != NULL_TREE ? IDENTIFIER_POINTER (rvname) : NULL);
+      return;
+    }
+
+  DECL_INITIAL (inner) = folded;
+}
+
+playback::rvalue *
+playback::context::
+new_ctor (location *loc,
+	  type *type,
+	  const auto_vec<field*> *fields,
+	  const auto_vec<rvalue*> *rvalues)
+{
+  tree type_tree = type->as_tree ();
+
+  /* Handle empty ctors first. I.e. set everything to 0 */
+  if (rvalues->length () == 0)
+    return new rvalue (this, build_constructor (type_tree, NULL));
+
+  /* Handle arrays (and return) */
+  if (TREE_CODE (type_tree) == ARRAY_TYPE)
+    {
+      int n = rvalues->length ();
+      /* The vec for the constructor node */
+      vec<constructor_elt, va_gc> *v = NULL;
+      vec_alloc(v, n);
+
+      for (int i = 0; i < n; i++)
+	{
+	  /* null rvalues indicate that the element should be zeroed */
+	  if ((*rvalues)[i])
+	    CONSTRUCTOR_APPEND_ELT(v,
+				   build_int_cst (size_type_node, i),
+				   (*rvalues)[i]->as_tree ());
+	  else
+	    CONSTRUCTOR_APPEND_ELT(v,
+				   build_int_cst (size_type_node, i),
+				   build_zero_cst (TREE_TYPE (type_tree)));
+	}
+
+      tree ctor = build_constructor (type_tree, v);
+
+      if (loc)
+	set_tree_location (ctor, loc);
+
+      return new rvalue(this, ctor);
+    }
+
+  /* Handle structs and unions */
+  int n = fields->length ();
+
+  /* The vec for the constructor node */
+  vec<constructor_elt, va_gc> *v = NULL;
+  vec_alloc(v, n);
+
+  int i = 0;
+  tree field = TYPE_FIELDS (type_tree);
+
+  /* Iterate over the fields, building initializations. */
+  for (; field && i < n; field = DECL_CHAIN (field), i++)
+    {
+      /* If the value is NULL, it means we should zero the field */
+      if ((*rvalues)[i])
+	CONSTRUCTOR_APPEND_ELT(v, field, (*rvalues)[i]->as_tree ());
+      else
+	{
+	  tree zero_cst = build_zero_cst (TREE_TYPE (field));
+	  CONSTRUCTOR_APPEND_ELT(v, field, zero_cst);
+	}
+    }
+
+  /* Any fields remaining are set to 0, for structs (not unions) */
+  if (TREE_CODE (type_tree) == RECORD_TYPE)
+    {
+      for (; field && i < n; field = DECL_CHAIN (field), i++)
+	{
+	  tree zero_cst = build_zero_cst (TREE_TYPE (field));
+	  CONSTRUCTOR_APPEND_ELT(v, field, zero_cst);
+	}
+      /* Assert that we got as many fields as we think we got */
+      gcc_assert (field == NULL_TREE);
+      gcc_assert (n == i);
+    }
+
+  tree ctor = build_constructor (type_tree, v);
+
+  if (loc)
+    set_tree_location (ctor, loc);
+
+  return new rvalue(this, build_constructor (type_tree, v));
+}
+
 /* Fill 'constructor_elements' with the memory content of
    'initializer'.  Each element of the initializer is of the size of
    type T.  In use by new_global_initialized.*/
@@ -638,9 +856,10 @@ new_global_initialized (location *loc,
                         size_t element_size,
 			size_t initializer_num_elem,
 			const void *initializer,
-			const char *name)
+			const char *name,
+			enum global_var_flags flags)
 {
-  tree inner = global_new_decl (loc, kind, type, name);
+  tree inner = global_new_decl (loc, kind, type, name, flags);
 
   vec<constructor_elt, va_gc> *constructor_elements = NULL;
 
@@ -1109,7 +1328,8 @@ as_truth_value (tree expr, location *loc)
   if (loc)
     set_tree_location (typed_zero, loc);
 
-  expr = build2 (NE_EXPR, integer_type_node, expr, typed_zero);
+  expr = fold_build2_loc (UNKNOWN_LOCATION,
+    NE_EXPR, integer_type_node, expr, typed_zero);
   if (loc)
     set_tree_location (expr, loc);
 
@@ -1145,6 +1365,8 @@ new_unary_op (location *loc,
   gcc_assert (a);
 
   tree node = a->as_tree ();
+  node = fold_const_var (node);
+
   tree inner_result = NULL;
 
   switch (op)
@@ -1176,6 +1398,10 @@ new_unary_op (location *loc,
   inner_result = build1 (inner_op,
 			 result_type->as_tree (),
 			 node);
+
+  /* Try to fold */
+  inner_result = fold (inner_result);
+
   if (loc)
     set_tree_location (inner_result, loc);
 
@@ -1200,7 +1426,10 @@ new_binary_op (location *loc,
   gcc_assert (b);
 
   tree node_a = a->as_tree ();
+  node_a = fold_const_var (node_a);
+
   tree node_b = b->as_tree ();
+  node_b = fold_const_var (node_b);
 
   switch (op)
     {
@@ -1275,6 +1504,10 @@ new_binary_op (location *loc,
 			    result_type->as_tree (),
 			    node_a,
 			    node_b);
+
+  /* Try to fold the expression */
+  inner_expr = fold (inner_expr);
+
   if (loc)
     set_tree_location (inner_expr, loc);
 
@@ -1322,10 +1555,19 @@ new_comparison (location *loc,
       break;
     }
 
+  tree node_a = a->as_tree ();
+  node_a = fold_const_var (node_a);
+  tree node_b = b->as_tree ();
+  node_b = fold_const_var (node_b);
+
   tree inner_expr = build2 (inner_op,
 			    boolean_type_node,
-			    a->as_tree (),
-			    b->as_tree ());
+			    node_a,
+			    node_b);
+
+  /* Try to fold */
+  inner_expr = fold (inner_expr);
+
   if (loc)
     set_tree_location (inner_expr, loc);
   return new rvalue (this, inner_expr);
@@ -1425,6 +1667,8 @@ playback::context::build_cast (playback::location *loc,
 
      Only some kinds of cast are currently supported here.  */
   tree t_expr = expr->as_tree ();
+  t_expr = fold_const_var (t_expr);
+
   tree t_dst_type = type_->as_tree ();
   tree t_ret = NULL;
   t_ret = targetm.convert_to_type (t_dst_type, t_expr);
@@ -1507,7 +1751,10 @@ new_array_access (location *loc,
        c-family/c-common.c: pointer_int_sum
   */
   tree t_ptr = ptr->as_tree ();
+  t_ptr = fold_const_var (t_ptr);
   tree t_index = index->as_tree ();
+  t_index = fold_const_var (t_index);
+
   tree t_type_ptr = TREE_TYPE (t_ptr);
   tree t_type_star_ptr = TREE_TYPE (t_type_ptr);
 
@@ -1515,6 +1762,7 @@ new_array_access (location *loc,
     {
       tree t_result = build4 (ARRAY_REF, t_type_star_ptr, t_ptr, t_index,
 			      NULL_TREE, NULL_TREE);
+      t_result = fold (t_result);
       if (loc)
 	set_tree_location (t_result, loc);
       return new lvalue (this, t_result);
@@ -1524,12 +1772,14 @@ new_array_access (location *loc,
       /* Convert index to an offset in bytes.  */
       tree t_sizeof = size_in_bytes (t_type_star_ptr);
       t_index = fold_build1 (CONVERT_EXPR, sizetype, t_index);
-      tree t_offset = build2 (MULT_EXPR, sizetype, t_index, t_sizeof);
+      tree t_offset = fold_build2_loc (UNKNOWN_LOCATION,
+	MULT_EXPR, sizetype, t_index, t_sizeof);
 
       /* Locate (ptr + offset).  */
-      tree t_address = build2 (POINTER_PLUS_EXPR, t_type_ptr, t_ptr, t_offset);
+      tree t_address = fold_build2_loc (UNKNOWN_LOCATION,
+	POINTER_PLUS_EXPR, t_type_ptr, t_ptr, t_offset);
 
-      tree t_indirection = build1 (INDIRECT_REF, t_type_star_ptr, t_address);
+      tree t_indirection = fold_build1 (INDIRECT_REF, t_type_star_ptr, t_address);
       if (loc)
 	{
 	  set_tree_location (t_sizeof, loc);
@@ -1577,7 +1827,7 @@ new_dereference (tree ptr,
   gcc_assert (ptr);
 
   tree type = TREE_TYPE (TREE_TYPE(ptr));
-  tree datum = build1 (INDIRECT_REF, type, ptr);
+  tree datum = fold_build1 (INDIRECT_REF, type, ptr);
   if (loc)
     set_tree_location (datum, loc);
   return datum;
@@ -1731,7 +1981,7 @@ get_address (location *loc)
   tree t_lvalue = as_tree ();
   tree t_thistype = TREE_TYPE (t_lvalue);
   tree t_ptrtype = build_pointer_type (t_thistype);
-  tree ptr = build1 (ADDR_EXPR, t_ptrtype, t_lvalue);
+  tree ptr = fold_build1 (ADDR_EXPR, t_ptrtype, t_lvalue);
   if (loc)
     get_context ()->set_tree_location (ptr, loc);
   if (mark_addressable (loc))
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index f670c9e81df..d445d7ccb95 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -109,7 +109,8 @@ public:
   new_global (location *loc,
 	      enum gcc_jit_global_kind kind,
 	      type *type,
-	      const char *name);
+	      const char *name,
+	      enum global_var_flags flags);
 
   lvalue *
   new_global_initialized (location *loc,
@@ -118,7 +119,19 @@ public:
                           size_t element_size,
                           size_t initializer_num_elem,
                           const void *initializer,
-                          const char *name);
+                          const char *name,
+			  enum global_var_flags flags);
+
+  rvalue *
+  new_ctor (location *log,
+	    type *type,
+	    const auto_vec<field*> *fields,
+	    const auto_vec<rvalue*> *rvalues);
+
+
+  void
+  global_set_init_rvalue (lvalue* variable,
+			  rvalue* init);
 
   template <typename HOST_TYPE>
   rvalue *
@@ -286,7 +299,8 @@ private:
   global_new_decl (location *loc,
                    enum gcc_jit_global_kind kind,
                    type *type,
-                   const char *name);
+		   const char *name,
+		   enum global_var_flags flags);
   lvalue *
   global_finalize_lvalue (tree inner);
 
@@ -635,7 +649,10 @@ public:
   rvalue *
   as_rvalue () { return this; }
 
-  tree as_tree () const { return m_inner; }
+  tree as_tree () const
+  {
+    return m_inner;
+  }
 
   context *get_context () const { return m_ctxt; }
 
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 8d34956fc67..2e266c95bef 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -1064,6 +1064,15 @@ recording::context::new_global (recording::location *loc,
   return result;
 }
 
+void
+recording::context::new_global_init_rvalue (lvalue *variable,
+					    rvalue *init)
+{
+  recording::global_init_rvalue *obj =
+    new recording::global_init_rvalue (this, variable, init);
+  record (obj);
+}
+
 /* Create a recording::memento_of_new_string_literal instance and add it
    to this context's list of mementos.
 
@@ -1096,6 +1105,233 @@ recording::context::new_rvalue_from_vector (location *loc,
   return result;
 }
 
+
+/* For sorting */
+struct fieldval_pair {
+  gcc::jit::recording::field *field;
+  gcc::jit::recording::rvalue *value;
+};
+
+static int cmp_fieldvalue (const void *l, const void *r)
+{
+  const fieldval_pair *p_l = (const fieldval_pair*)l;
+  const fieldval_pair *p_r = (const fieldval_pair*)r;
+  
+  return strcmp (p_l->field->get_name ()->c_str (),
+		 p_r->field->get_name ()->c_str ());
+}
+
+recording::rvalue *
+recording::context::new_ctor (recording::location *loc,
+			      recording::type *type,
+			      int arr_length,
+			      field **fields_arr,
+			      rvalue **values)
+{
+  recording::ctor *result = new ctor (this, loc, type);
+
+  /* We need to copy fields and values into result's auto_vec:s.
+
+     We also do some validation and return NULL on error, deleting
+     result. */
+
+  if (type->is_array () != NULL)
+    {
+      result->m_values.reserve (arr_length, false);
+
+      for (int i = 0; i < arr_length; i++)
+	result->m_values.quick_push (values[i]);
+    }
+  else if (type->is_union ())
+    {
+      /* Check that the field actually exists in the union, then copy */
+      
+      field *field_ctor = fields_arr[0];
+      
+      compound_type *ct = reinterpret_cast<compound_type *>(type);
+
+      fields *fields_union = ct->get_fields ();
+      int n_fields = fields_union->length ();
+
+      recording::type *field_ctor_type = field_ctor->get_type ()->unqualified ();
+      
+      const char *field_ctor_name = field_ctor->get_name ()->c_str ();
+
+      int hit = 0;
+      for (int i = 0; i < n_fields; i++)
+	{
+	  field *field_union = fields_union->get_field (i);
+
+	  /* Do the fields have the same unqualified type and the same name? */
+	  if (
+		types_kinda_same (field_union->get_type (),
+				  field_ctor_type)
+		&&
+		(0 == strcmp (field_union->get_name ()->c_str (),
+			      field_ctor_name))
+	     )
+	    {
+	      hit = 1;
+	      break;
+	    }
+	}
+
+      if (!hit)
+	{
+	  add_error(
+	    loc,
+	    "gcc_jit_context_new_constructor: constructor field does not exist "
+	    "in the union type (field: %s %s)(type: %s)",
+	    field_ctor->get_type ()->get_debug_string (),
+	    field_ctor->get_name ()->c_str (),
+	    type->get_debug_string ());
+	  goto err;
+	}
+   
+      result->m_values.safe_push (values[0]);
+      result->m_fields.safe_push (fields_arr[0]);
+    }
+  else if (type->is_struct ())
+    {
+      /* If the type is a struct, we might need to sort the fields and add
+	 intermittent fields with null values to zero them later.
+
+	 We also want any error here at the call site not at replay time. */
+
+      compound_type *ct = reinterpret_cast<compound_type *>(type);
+
+      fields *fields_struct = ct->get_fields ();
+      int n_fields = fields_struct->length ();
+
+      if (n_fields < arr_length)
+	{
+	  add_error(
+	    loc,
+	    "gcc_jit_context_new_constructor: more fields in constructor than "
+	    "in the target struct");
+	  goto err;
+	}
+
+      /* Sorted fields should be the normal case so we check if the fields
+	 are sorted before sorting them to save some CPU time */
+      int is_sorted = 1;
+
+      for (int i = 0; i < arr_length; i++)
+	{
+	  field *field_struct = fields_struct->get_field (i);
+
+	  field *field_ctor = fields_arr[i];
+
+	  /* Do the fields have the same unqualified type and the same name? */
+	  if (
+		types_kinda_same (field_struct->get_type (),
+				  field_ctor->get_type ())
+		&&
+		(0 == strcmp (field_struct->get_name ()->c_str (),
+			      field_ctor->get_name ()->c_str ()))
+	     )
+	    ;
+	  else
+	    {
+	      is_sorted = 0;
+	      break;
+	    }
+	}
+
+      if (is_sorted)
+	{
+	  result->m_values.reserve (arr_length, false);
+	  result->m_fields.reserve (arr_length, false);
+
+	  for (int i = 0; i < arr_length; i++)
+	    {
+	      result->m_values.quick_push (values[i]);
+	      result->m_fields.quick_push (fields_arr[i]);
+	    }
+	}
+      else
+	{
+	  int n_hits = 0;
+	  /* For all fields in the struct type, find the corrensponding
+	     field in the ctor and push it to the vectors. If a field is
+	     missing in the ctor, push a null value to indicate that it
+	     needs zeroing.
+
+	     The c-front end sorts the struct fields when they are more
+	     than 15, see c-decl.c : finish_struct(), to do fancy searches
+	     for big structs and fast linear for small, but we do binary
+	     always to save some code complexity. */
+	  auto_vec<fieldval_pair> v_fieldvals;
+	  v_fieldvals.reserve (arr_length, false);
+
+	  for (int i = 0; i < arr_length; i++)
+	    v_fieldvals.quick_push (
+	      {reinterpret_cast<field *>(fields_arr[i]),
+	       reinterpret_cast<rvalue *>(values[i])});
+
+	  v_fieldvals.qsort (cmp_fieldvalue);
+	  
+	  for (int i = 0; i < n_fields; i++)
+	    {
+	      field *field_struct = fields_struct->get_field (i);
+
+	      fieldval_pair key = {field_struct, NULL};
+
+	      fieldval_pair *ans = v_fieldvals.bsearch (&key, cmp_fieldvalue);
+
+	      if (ans)
+		{
+		  n_hits++;
+
+		  if (!types_kinda_same (field_struct->get_type (),
+					 ans->field->get_type ()))
+		    {
+		      add_error(
+			loc,
+			"gcc_jit_context_new_constructor:"
+			"type of struct field differs from type of construct field"
+			" (struct: %s %s)(ctor: %s %s)",
+			field_struct->get_type ()->get_debug_string (),
+			field_struct->get_name ()->c_str (),
+			ans->field->get_type ()->get_debug_string (),
+			ans->field->get_name ()->c_str ());
+		      goto err;
+		    }
+
+		  result->m_values.safe_push (ans->value);
+		  result->m_fields.safe_push (ans->field);
+		}
+	      else
+		{
+		  /* Push null value if not found, to zero the field. */
+		  result->m_values.safe_push (NULL);
+		  result->m_fields.safe_push (field_struct);
+		}
+	    }
+
+	  /* Verify that we found all the fields specified. */
+	  if (n_hits != arr_length)
+	    {
+	      add_error(
+		loc,
+		"gcc_jit_context_new_constructor:"
+		"could not find matching field in struct for"
+		" all fields in constructor");
+	      goto err;	    
+	    }
+	}
+    }
+  else
+    gcc_unreachable();
+
+  record (result);
+  return result;
+
+ err:
+  delete result;
+  return NULL;
+}
+
 /* Create a recording::unary_op instance and add it to this context's
    list of mementos.
 
@@ -4652,11 +4888,13 @@ recording::global::replay_into (replayer *r)
 				 m_initializer_num_bytes
 				 / m_type->dereference ()->get_size (),
 				 m_initializer,
-				 playback_string (m_name))
+				 playback_string (m_name),
+				 flags)
     : r->new_global (playback_location (r, m_loc),
 		     m_kind,
 		     m_type->playback_type (),
-		     playback_string (m_name)));
+		     playback_string (m_name),
+		     flags));
 }
 
 /* Override the default implementation of
@@ -5583,6 +5821,125 @@ recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
 	   elements_id);
 }
 
+void
+recording::ctor::visit_children (rvalue_visitor *v)
+{
+  for (unsigned int i = 0; i < m_values.length (); i++)
+    v->visit (m_values[i]);
+}
+
+recording::string *
+recording::ctor::make_debug_string ()
+{
+  return string::from_printf (m_ctxt,
+			      "ctor");
+}
+
+void
+recording::ctor::write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "rvalue");
+  type *type = get_type();
+
+  r.write ("  gcc_jit_rvalue *%s;\n", id);
+  r.write ("  {\n"); /* Open scope for locals */
+
+  /* Write the array of values */
+  r.write ("    gcc_jit_rvalue *values[] = {\n");
+  for (unsigned i = 0; i < m_values.length (); i++)
+    r.write ("        %s,\n", r.get_identifier (m_values[i]));
+  r.write ("      };\n");
+
+  /* Write the array of fields */
+  if (type->is_array ())
+    r.write ("    gcc_jit_field **fields = NULL;\n");
+  else
+    {
+      r.write ("    gcc_jit_field *fields[] = {\n");
+      for (unsigned i = 0; i < m_fields.length (); i++)
+	r.write ("        %s,\n", r.get_identifier (m_fields[i]));
+      r.write ("      };\n");
+    }
+  r.write (
+"    %s =\n"
+"      gcc_jit_context_new_constructor (%s,\n"
+"                                       %s, /* gcc_jit_location *loc */\n"
+"                                       %s, /* gcc_jit_type *type */\n"
+"                                       %i, /* int arr_length */\n"
+"                                       fields,\n"
+"                                       values);\n",
+	   id,
+	   r.get_identifier (get_context ()),
+	   r.get_identifier (m_loc),
+	   r.get_identifier_as_type (get_type ()),
+	   m_values.length ());
+
+  r.write ("  }\n"); /* Close scope for locals */
+}
+
+void
+recording::ctor::replay_into (replayer *r)
+{
+  auto_vec<playback::rvalue *> playback_values;
+  auto_vec<playback::field *> playback_fields;
+
+  int n = m_values.length();
+
+  type *type = get_type ();
+
+  /* Handle arrays, and return */
+  if (type->is_array ())
+    {
+      playback_values.reserve (n, false);
+
+      for (int i = 0; i < n; i++)
+	{
+	  /* null m_values element indicates zero ctor */
+	  playback_values.quick_push (m_values[i] ?
+				      m_values[i]->playback_rvalue () :
+				      NULL);
+	}
+      set_playback_obj (r->new_ctor (playback_location (r, m_loc),
+				     get_type ()->playback_type (),
+				     NULL,
+				     &playback_values));
+      return;
+    }
+  /* Handle unions, and return */
+  else if (type->is_union ())
+    {
+      playback_values.safe_push (m_values[0] ?
+				   m_values[0]->playback_rvalue () :
+				   NULL);
+      playback_fields.safe_push (m_fields[0]->playback_field ());
+
+      set_playback_obj (r->new_ctor (playback_location (r, m_loc),
+				     get_type ()->playback_type (),
+				     &playback_fields,
+				     &playback_values));
+
+      return;
+    }
+  /* ... else, handle structs */
+
+  playback_values.reserve (n, false);
+  playback_fields.reserve (n, false);
+
+  for (int i = 0; i < n; i++)
+    {
+      /* null m_values element indicates zero ctor */
+      playback_values.quick_push (m_values[i] ?
+				    m_values[i]->playback_rvalue () :
+				    NULL);
+      playback_fields.quick_push (m_fields[i]->playback_field ());
+    }
+
+  set_playback_obj (r->new_ctor (playback_location (r, m_loc),
+				 get_type ()->playback_type (),
+				 &playback_fields,
+				 &playback_values));
+}
+
 /* The implementation of class gcc::jit::recording::unary_op.  */
 
 /* Implementation of pure virtual hook recording::memento::replay_into
@@ -7556,6 +7913,81 @@ recording::top_level_asm::write_reproducer (reproducer &r)
 	   m_asm_stmts->get_debug_string ());
 }
 
+void
+recording::global_init_rvalue::replay_into (replayer *r)
+{
+  r->global_set_init_rvalue (m_variable->playback_lvalue(),
+			       m_init->playback_rvalue());
+}
+
+void
+recording::global_init_rvalue::write_reproducer (reproducer &r)
+{
+  r.write (
+    "  gcc_jit_global_set_initializer_rvalue (%s, /* lvalue *global */\n"
+    "                                         %s);/* rvalue *init */\n",
+    r.get_identifier (m_variable),
+    r.get_identifier_as_rvalue (m_init));
+}
+
+void
+recording::global_init_rvalue::write_to_dump (dump &d)
+{
+  d.write ("%s;\n", get_debug_string ());
+}
+
+recording::string *
+recording::global_init_rvalue::make_debug_string ()
+{
+    return string::from_printf(m_ctxt, "%s = %s",
+      m_variable->get_debug_string (),
+      m_init->get_debug_string ());
+}
+
+/* Strip qualifiers and count pointer depth, returning true
+   if the types' base type and pointer depth are
+   the same, otherwise false.
+
+   Do not call this directly. Call 'types_kinda_same' */
+bool
+types_kinda_same_internal (recording::type *a, recording::type *b)
+{
+  int ptr_depth[2] = {};
+  recording::type *base_types[2];
+  recording::type *types[2] = {a, b};
+
+  /* Strip qualifiers and count pointerness */
+  for (int i = 0; i < 2; i++)
+    {
+      recording::type *t = types[i];
+      while (true)
+	{
+	  if (!t)
+	    return false; /* Should only happen on bad input */
+
+	  recording::type *pointed_to_type = t->is_pointer();
+	  if (pointed_to_type != NULL)
+	    {
+	      ptr_depth[i]++;
+	      t = pointed_to_type;
+	      continue;
+	    }
+
+	  /* unqualified() returns 'this' on base types */
+	  recording::type *next = t->unqualified ();
+	  if (next == t)
+	    {
+	      base_types[i] = t;
+	      break;
+	    }
+	  t = next;
+	}
+    }
+
+  return base_types[0] == base_types[1] &&
+    (ptr_depth[0] == ptr_depth[1]);
+}
+
 } // namespace gcc::jit
 
 } // namespace gcc
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index d5e0c359a48..afd61132e69 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -149,6 +149,17 @@ public:
 	      type *type,
 	      const char *name);
 
+  rvalue *
+  new_ctor (location *loc,
+	    type *type,
+	    int arr_length,
+	    field **fields,
+	    rvalue **values);
+
+  void
+  new_global_init_rvalue (lvalue *variable,
+			  rvalue *init);
+
   template <typename HOST_TYPE>
   rvalue *
   new_rvalue_from_const (type *type,
@@ -547,6 +558,8 @@ public:
   virtual bool is_complex () const = 0;
   virtual type *is_pointer () = 0;
   virtual type *is_array () = 0;
+  virtual bool is_struct () const { return false; }
+  virtual bool is_union () const { return false; }
   virtual bool is_void () const { return false; }
   virtual bool has_known_size () const { return true; }
   /* Used to pair complex float types with real float type
@@ -873,6 +886,7 @@ public:
   {}
 
   type * get_type () const { return m_type; }
+  string * get_name () const { return m_name; }
 
   compound_type * get_container () const { return m_container; }
   void set_container (compound_type *c) { m_container = c; }
@@ -979,6 +993,8 @@ public:
 
   const char *access_as_type (reproducer &r) FINAL OVERRIDE;
 
+  virtual bool is_struct () const FINAL OVERRIDE { return true; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -1017,6 +1033,8 @@ public:
 
   void replay_into (replayer *r) FINAL OVERRIDE;
 
+  virtual bool is_union () const FINAL OVERRIDE { return true; }
+
 private:
   string * make_debug_string () FINAL OVERRIDE;
   void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -1414,6 +1432,21 @@ public:
     m_initializer_num_bytes = num_bytes;
   }
 
+  void set_flags (int flag_fields)
+  {
+    flags = (enum global_var_flags)(flags | flag_fields);
+  }
+  /* Returns true if any of the flags in the argument is set */
+  bool test_flags_anyof (int flag_fields) const
+  {
+    return flags & flag_fields;
+  }
+
+  enum gcc_jit_global_kind get_kind() const
+  {
+    return m_kind;
+  }
+
 private:
   string * make_debug_string () FINAL OVERRIDE { return m_name; }
   template <typename T>
@@ -1426,9 +1459,11 @@ private:
 
 private:
   enum gcc_jit_global_kind m_kind;
+  enum global_var_flags flags = GLOBAL_VAR_FLAGS_NONE;
   string *m_name;
   void *m_initializer;
   size_t m_initializer_num_bytes;
+  
 };
 
 template <typename HOST_TYPE>
@@ -1512,6 +1547,32 @@ private:
   auto_vec<rvalue *> m_elements;
 };
 
+class ctor : public rvalue
+{
+public:
+  ctor (context *ctxt,
+	location *loc,
+	type *type)
+  : rvalue (ctxt, loc, type)
+  { }
+
+  void replay_into (replayer *r) FINAL OVERRIDE;
+
+  void visit_children (rvalue_visitor *) FINAL OVERRIDE;
+
+private:
+  string * make_debug_string () FINAL OVERRIDE;
+  void write_reproducer (reproducer &r) FINAL OVERRIDE;
+  enum precedence get_precedence () const FINAL OVERRIDE
+  {
+    return PRECEDENCE_PRIMARY;
+  }
+
+public:
+  auto_vec<field *> m_fields;
+  auto_vec<rvalue *> m_values;
+};
+
 class unary_op : public rvalue
 {
 public:
@@ -2355,6 +2416,24 @@ private:
   string *m_asm_stmts;
 };
 
+class global_init_rvalue : public memento
+{
+public:
+  global_init_rvalue (context *ctxt, lvalue *variable, rvalue *init) :
+    memento(ctxt), m_variable (variable), m_init (init) {};
+
+  void write_to_dump (dump &d) FINAL OVERRIDE;
+
+private:
+  void replay_into (replayer *r) FINAL OVERRIDE;
+  string * make_debug_string () FINAL OVERRIDE;
+  void write_reproducer (reproducer &r) FINAL OVERRIDE;
+
+private:
+  lvalue *m_variable;
+  rvalue *m_init;
+};
+
 } // namespace gcc::jit::recording
 
 /* Create a recording::memento_of_new_rvalue_from_const instance and add
@@ -2374,6 +2453,19 @@ recording::context::new_rvalue_from_const (recording::type *type,
   return result;
 }
 
+bool
+types_kinda_same_internal (recording::type *a,
+			   recording::type *b);
+
+/* Strip *all* qualifiers and count pointer depth, returning true
+   if the types and pointer depth are the same, otherwise false. */
+static inline bool
+types_kinda_same (recording::type *a, recording::type *b)
+{
+  /* Handle trivial case here, to allow for inlining. */
+  return a == b || types_kinda_same_internal (a, b);
+}
+
 } // namespace gcc::jit
 
 } // namespace gcc
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index b94cdc85c8e..019172854a7 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -206,6 +206,11 @@ namespace gccjit
     rvalue new_rvalue (type vector_type,
 		       std::vector<rvalue> elements) const;
 
+    rvalue new_constructor (type type_,
+			    std::vector<field> &fields,
+			    std::vector<rvalue> &values,
+			    location loc = location ());
+
     /* Generic unary operations...  */
     rvalue new_unary_op (enum gcc_jit_unary_op op,
 			 type result_type,
@@ -509,6 +514,7 @@ namespace gccjit
 
     rvalue get_address (location loc = location ());
     lvalue set_initializer (const void *blob, size_t num_bytes);
+    lvalue set_initializer_rvalue (rvalue init_value);
   };
 
   class param : public lvalue
@@ -1891,6 +1897,44 @@ lvalue::set_initializer (const void *blob, size_t num_bytes)
   return *this;
 }
 
+inline lvalue
+lvalue::set_initializer_rvalue (rvalue init_value)
+{
+  return lvalue (gcc_jit_global_set_initializer_rvalue (
+		   get_inner_lvalue (),
+		   init_value.get_inner_rvalue()));
+}
+
+inline rvalue
+context::new_constructor (type type_,
+			  std::vector<field> &fields,
+			  std::vector<rvalue> &values,
+			  location loc)
+{
+  field *pfields = nullptr;
+  if (fields.size())
+    pfields = &fields[0];
+
+  gcc_jit_field **fields_arr =
+    reinterpret_cast<gcc_jit_field **> (pfields);
+
+  rvalue *pvalues = nullptr;
+  if (values.size())
+    pvalues = &values[0];
+
+  gcc_jit_rvalue **values_arr =
+    reinterpret_cast<gcc_jit_rvalue **> (pvalues);
+
+  return rvalue (
+	   gcc_jit_context_new_constructor (m_inner_ctxt,
+					    loc.get_inner_location (),
+					    type_.get_inner_type(),
+					    (int)values.size(),
+					    fields_arr,
+					    values_arr));
+}
+
+
 // class param : public lvalue
 inline param::param () : lvalue () {}
 inline param::param (gcc_jit_param *inner)
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 97c5aba643e..56f310f398f 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -335,7 +335,7 @@ jit_error (gcc::jit::recording::context *ctxt,
 
    This is implemented by calling the
    gcc::jit::recording::type::accepts_writes_from virtual function on
-   LTYPE.  */
+   LTYPE. For const types accepts_writes_from always returns false. */
 
 static bool
 compatible_types (gcc::jit::recording::type *ltype,
@@ -1130,6 +1130,215 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt,
   return (gcc_jit_lvalue *)ctxt->new_global (loc, kind, type, name);
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   Builds a ctor for arrays, unions and structs.
+
+   The way many entrypoints compare types for sameness is abit
+   broken, since they only strip one qualifier, making eg.
+   'const volatile int' and 'volatile const int' incompatible,
+   or 'const volatile int' and 'int' incompatible. Or
+   'const volatile int' incompatible with it self if the types
+   were built from two different function calls.
+
+   However, for the constructor we need to strip everything. */
+
+extern gcc_jit_rvalue *
+gcc_jit_context_new_constructor (gcc_jit_context *ctxt,
+				 gcc_jit_location *loc,
+				 gcc_jit_type *type,
+				 int arr_length,
+				 gcc_jit_field **fields,
+				 gcc_jit_rvalue **values)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+
+  bool is_union = type->is_union ();
+  bool is_struct = type->is_struct ();
+  bool is_array = type->is_array () != NULL; /* is_array() returns ptr */
+
+  RETURN_NULL_IF_FAIL (is_union || is_struct || is_array,
+		       ctxt, loc,
+		       "constructor type not an union, array or struct");
+
+  if (is_array)
+    fields = NULL; /* fields are ignored for array constructors */
+  if (!arr_length)
+    {
+      /* Ignore fields and values if arr_length is zero */
+      fields = NULL;
+      values = NULL;
+    }
+
+  if (is_union)
+    RETURN_NULL_IF_FAIL (arr_length == 1, ctxt, loc,
+			 "union constructor 'arr_length' not 1");
+
+  if (arr_length)
+    {
+      if (is_struct || is_union)
+	RETURN_NULL_IF_FAIL (
+	  fields && values,
+	  ctxt, loc,
+	  "'fields' and/or 'values' NULL with non-zero 'arr_length'");
+      else if (is_array)
+	{
+	  RETURN_NULL_IF_FAIL (
+	    values,
+	    ctxt, loc,
+	    "'values' NULL with non-zero 'arr_length'");
+
+	  gcc::jit::recording::array_type *arr_type =
+	    reinterpret_cast<gcc::jit::recording::array_type*>(type);
+	  int n_el = arr_type->num_elements ();
+
+	  RETURN_NULL_IF_FAIL (
+	    n_el >= arr_length,
+	    ctxt, loc,
+	    "array constructor has more values than the array type's length");
+	}
+    }
+
+  if (fields && values) /* Union or struct */
+    {
+      for (int i = 0; i < arr_length; i++)
+	{
+	  RETURN_NULL_IF_FAIL_PRINTF1 (
+	    fields[i],
+	    ctxt, loc,
+	    "NULL field in 'fields', at index %d", i);
+
+	  if (values[i])
+	    {
+	      RETURN_NULL_IF_FAIL_PRINTF1 (
+		!values[i]->get_type ()->is_void (),
+		ctxt, loc,
+		"can't construct the void type, at index %d", i);
+	      RETURN_NULL_IF_FAIL_PRINTF3 (
+		gcc::jit::types_kinda_same (values[i]->get_type (),
+					    fields[i]->get_type ()),
+		ctxt, loc,
+		"value and field not the same unqualified type, at index %d"
+		" (field type: %s)(value type: %s)",
+		i,
+		fields[i]->get_type ()->get_debug_string (),
+		values[i]->get_type ()->get_debug_string ());
+	    }
+	}
+    }
+  else if (values) /* Array */
+    {
+      /* For arrays, all values need to be the same type */
+      gcc::jit::recording::type *type0 = NULL;
+      int i = 0;
+      /* Find first non-null value */
+      for (;i < arr_length; i++)
+	{
+	  if (values[i])
+	    break;
+	}
+
+      if (i < arr_length) /* All values might be null */
+       type0 = values[i]->get_type ();
+
+      /* If we got a type0, check that all other values have
+	 the same type */
+      for (; i < arr_length; i++)
+	{
+	  if (values[i])
+	    RETURN_NULL_IF_FAIL_PRINTF3 (
+	      gcc::jit::types_kinda_same (type0,
+					  values[i]->get_type ()),
+	      ctxt, loc,
+	      "value type at index %d differ from first value type"
+	      " (first type: %s)(different type: %s)",
+	      i,
+	      type0->get_debug_string (),
+	      values[i]->get_type ()->get_debug_string ());
+	}
+
+      /* Compare type0 with the element type specified in the
+	 type of the array. */
+      if (type0)
+	{
+	  gcc::jit::recording::type *el_type =
+	    type->is_array ();
+
+	  RETURN_NULL_IF_FAIL_PRINTF2 (
+	    gcc::jit::types_kinda_same (type0, el_type),
+	    ctxt, loc,
+	    "array element value types differ from types in 'values'"
+	    " (element type: %s)('values' type: %s)",
+	    el_type->get_debug_string (),
+	    type0->get_debug_string ());
+	}
+    }
+
+  return (gcc_jit_rvalue *)ctxt->new_ctor (
+    loc,
+    type,
+    arr_length,
+    reinterpret_cast<gcc::jit::recording::field**>(fields),
+    reinterpret_cast<gcc::jit::recording::rvalue**>(values));
+}
+
+/* Public entrypoint.  See description in libgccjit.h. */
+
+extern gcc_jit_lvalue *
+gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
+				       gcc_jit_rvalue *init_rvalue)
+{
+  RETURN_NULL_IF_FAIL (global, NULL, NULL,"NULL global");
+  
+  gcc::jit::recording::context *ctxt = global->get_context ();
+  RETURN_NULL_IF_FAIL (ctxt, NULL, NULL,"NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  RETURN_NULL_IF_FAIL (init_rvalue, ctxt, NULL,"NULL init_rvalue");
+
+  RETURN_NULL_IF_FAIL_PRINTF1 (global->is_global (),
+			       ctxt, NULL,
+			       "lvalue \"%s\" not a global",
+			       global->get_debug_string ());
+
+  gcc::jit::recording::global *gbl =
+    reinterpret_cast<gcc::jit::recording::global *> (global);
+  
+  RETURN_NULL_IF_FAIL_PRINTF1 (gbl->get_kind () !=
+			       GCC_JIT_GLOBAL_IMPORTED,
+			       ctxt, NULL,
+			       "can't initialize \"%s\", it is imported",
+			       global->get_debug_string ());
+
+  RETURN_NULL_IF_FAIL_PRINTF4 (gcc::jit::types_kinda_same (
+				 global->get_type (),
+				 init_rvalue->get_type()),
+			       ctxt, NULL,
+			       "mismatching types:"
+			       " initializing %s (type: %s) with %s (type: %s)",
+			       global->get_debug_string (),
+			       global->get_type ()->get_debug_string (),
+			       init_rvalue->get_debug_string (),
+			       init_rvalue->get_type ()->get_debug_string ());
+
+  /* Check that there are no initializers set for the global yet */
+  RETURN_NULL_IF_FAIL_PRINTF1 (!gbl->test_flags_anyof (
+				  gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT |
+				  gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_BLOB_INIT),
+			       ctxt, NULL,
+			       "global variable allready initialized: %s",
+			       global->get_debug_string ());
+
+  /* The global need to know during playback that it will be
+     initialized. */
+  gbl->set_flags (gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT);
+
+  ctxt->new_global_init_rvalue (global, init_rvalue);
+
+  return global;
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
@@ -1163,8 +1372,22 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
     " global \"%s\" has size %zu whereas initializer has size %zu",
     global->get_debug_string (), lvalue_size, num_bytes);
 
-  reinterpret_cast <gcc::jit::recording::global *> (global)
-    ->set_initializer (blob, num_bytes);
+  /* Check that the rvalue initializer is not set for this global.
+     Note that we do not check if this blob type initializer is
+     allready set, since that check was not present when the entrypoint
+     was initially written. */
+  gcc::jit::recording::global *gbl =
+    reinterpret_cast<gcc::jit::recording::global *> (global);
+  RETURN_NULL_IF_FAIL_PRINTF1 (!gbl->test_flags_anyof (
+				  gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT),
+			       NULL, NULL,
+			       "global variable allready initialized: %s",
+			       global->get_debug_string ());
+
+  gbl->set_initializer (blob, num_bytes);
+  /* The global need to know during playback that it will be
+     initialized. */  
+  gbl->set_flags (gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_BLOB_INIT);
 
   return global;
 }
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index c510c5cc902..2fce399d6ff 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -795,6 +795,83 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt,
 			    gcc_jit_type *type,
 			    const char *name);
 
+#define LIBGCCJIT_HAVE_CTORS
+
+/* Create a constructor for an array, union or struct as a rvalue.
+
+   Returns NULL on error. The two parameter arrays are copied and
+   do not have to outlive the context.
+
+   'type' specifies what the constructor will build.
+
+   For a struct or union 'type', each field in 'fields' specifies
+   which field in the struct or union type to set to the corresponding
+   value in 'values'. 'fields' and 'values' are paired by index
+   and the pair need to have the same unqualified type.
+
+   For an array 'type', the 'fields' parameter is ignored.
+   
+   'arr_length' specifies the number of elements in 'values'.
+   For struct and unions, 'fields' need to have the same length as
+   'values'.
+
+   For unions, 'arr_length' need to be 1.
+
+   For non-unions, if 'arr_length' is 0, the array parameters will be
+   ignored and zero initialization will be used.
+ 
+   For an array 'type', if the array type itself has more elements than
+   'values', the left-over elements will be zeroed. Each value in
+   'values' need to be the same unqualified type as the array elements.
+
+   For a struct 'type', the fields in 'fields' do not have to be in
+   definition order, but being in order avoids a sort operation. Any
+   field in the struct that is not specified in 'fields' will be zeroed.
+      
+   A NULL value in 'values' is a shorthand for zero initialization
+   of the corresponding field or array element. 
+
+   The constructor rvalue can be used for assignment to locals.
+   It can be used to initialize global variables with
+   'gcc_jit_global_set_initializer_rvalue'. It can also be used as a
+   temporary value for function calls and return values.
+
+   The constructor can contain nested constructors. Note that a string
+   literal rvalue can't be used to construct a char array. It need one
+   rvalue for each char.
+
+   This entrypoint was added in LIBGCCJIT_ABI_16; you can test for its
+   presense using:
+     #ifdef LIBGCCJIT_HAVE_CTORS
+
+*/
+extern gcc_jit_rvalue *
+gcc_jit_context_new_constructor (gcc_jit_context *ctxt,
+				 gcc_jit_location *loc,
+				 gcc_jit_type *type,
+				 int arr_length,
+				 gcc_jit_field **fields,
+				 gcc_jit_rvalue **values);
+
+/* Set the initial value of a global with an rvalue.
+
+   The rvalue need to be a constant expression, i.e. no function calls.
+
+   The global can't have the 'kind' GCC_JIT_GLOBAL_IMPORTED.
+   
+   Use together with gcc_jit_context_new_constructor() to
+   initialize structs, unions and arrays.
+
+   On success, returns the 'global' parameter. Otherwise, NULL.
+
+   This entrypoint was added in LIBGCCJIT_ABI_16; you can test for its
+   presence using:
+     #ifdef LIBGCCJIT_HAVE_CTORS
+*/
+extern gcc_jit_lvalue *
+gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
+				       gcc_jit_rvalue *init_value);
+
 #define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
 
 /* Set an initial value for a global, which must be an array of
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 4022dbb6fbc..c5a1afdeacf 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -208,9 +208,11 @@ LIBGCCJIT_ABI_15 {
 
 LIBGCCJIT_ABI_16 {
   global:
+    gcc_jit_context_new_constructor;
     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;
+    gcc_jit_context_set_bool_enable_complex_types;
+    gcc_jit_global_set_initializer_rvalue;
 } 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 8416b312bad..26f45fe0811 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -211,6 +211,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-global-init-rvalue.c */
+#define create_code create_code_global_init_rvalue
+#define verify_code verify_code_global_init_rvalue
+#include "test-global-init-rvalue.c"
+#undef create_code
+#undef verify_code
+
 /* test-global-set-initializer.c */
 #define create_code create_code_global_set_initializer
 #define verify_code verify_code_global_set_initializer
@@ -232,6 +239,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-local-init-rvalue.c */
+#define create_code create_code_local_init_rvalue
+#define verify_code verify_code_local_init_rvalue
+#include "test-local-init-rvalue.c"
+#undef create_code
+#undef verify_code
+
 /* test-long-names.c */
 #define create_code create_code_long_names
 #define verify_code verify_code_long_names
diff --git a/gcc/testsuite/jit.dg/test-error-ctor-struct-too-big.c b/gcc/testsuite/jit.dg/test-error-ctor-struct-too-big.c
new file mode 100644
index 00000000000..6f0b9806285
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-ctor-struct-too-big.c
@@ -0,0 +1,86 @@
+/*
+
+  Test that the proper error is triggered when we build a ctor
+  for an struct type, but have too many fields.
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+  
+  gcc_jit_field *b1 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "a");
+  gcc_jit_field *b2 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "b");
+  gcc_jit_field *b3 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "c");
+  gcc_jit_field *fields_b[] = {b1, b2, b3};
+
+  gcc_jit_type *struct_bar_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt,
+				       0,
+				       "bar",
+				       3,
+				       fields_b));
+  
+  gcc_jit_field *b11 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "a");
+  gcc_jit_field *b22 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "b");
+  gcc_jit_field *b33 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "c");
+  gcc_jit_field *b44 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "c");
+
+  gcc_jit_field *fields_ctor[] = {b11, b22, b33, b44};
+  gcc_jit_rvalue *values[] = {0,0,0,0};
+
+  gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+    (ctxt, 0,
+     struct_bar_type,
+     4,
+     fields_ctor,
+     values);
+
+  CHECK_VALUE (ctor, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "gcc_jit_context_new_constructor: more fields in "
+		      "constructor than in the target struct");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "gcc_jit_context_new_constructor: more fields in "
+		      "constructor than in the target struct");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-field-name.c b/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-field-name.c
new file mode 100644
index 00000000000..f269ccad488
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-field-name.c
@@ -0,0 +1,81 @@
+/*
+
+  Test that the proper error is triggered when we build a ctor
+  for an struct type, but has the name wrong on a field.
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+  
+  gcc_jit_field *b1 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "a");
+  gcc_jit_field *b2 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "b");
+  gcc_jit_field *b3 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "c");
+  gcc_jit_field *fields_b[] = {b1, b2, b3};
+
+  gcc_jit_type *struct_bar_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt,
+				       0,
+				       "bar",
+				       3,
+				       fields_b));
+  
+  gcc_jit_field *b11 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "a");
+  gcc_jit_field *b22 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "bb"); /* wrong */
+  gcc_jit_field *b33 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "c");
+  gcc_jit_field *fields_ctor[] = {b11, b22, b33};
+  gcc_jit_rvalue *values[] = {0,0,0};
+
+  gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+    (ctxt, 0,
+     struct_bar_type,
+     3,
+     fields_ctor,
+     values);
+
+  CHECK_VALUE (ctor, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "gcc_jit_context_new_constructor: could not find "
+		      "matching field in struct for all fields in constructor");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "gcc_jit_context_new_constructor: could not find "
+		      "matching field in struct for all fields in constructor");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-type.c b/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-type.c
new file mode 100644
index 00000000000..3effa0bfd8b
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-type.c
@@ -0,0 +1,85 @@
+/*
+
+  Test that the proper error is triggered when we build a ctor
+  for an struct type, but has the type wrong on a field.
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+  gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_FLOAT);
+  
+  gcc_jit_field *b1 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "a");
+  gcc_jit_field *b2 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "b");
+  gcc_jit_field *b3 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "c");
+  gcc_jit_field *fields_b[] = {b1, b2, b3};
+
+  gcc_jit_type *struct_bar_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt,
+				       0,
+				       "bar",
+				       3,
+				       fields_b));
+  
+  gcc_jit_field *b11 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "a");
+  gcc_jit_field *b22 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  float_type, /* wrong */
+						  "b");
+  gcc_jit_field *b33 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  int_type,
+						  "c");
+  gcc_jit_field *fields_ctor[] = {b11, b22, b33};
+  gcc_jit_rvalue *values[] = {0,0,0};
+
+  gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+    (ctxt, 0,
+     struct_bar_type,
+     3,
+     fields_ctor,
+     values);
+
+  CHECK_VALUE (ctor, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "gcc_jit_context_new_constructor: type of struct "
+		      "field differs from type of construct field "
+		      "(struct: int b)(ctor: float b)");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "gcc_jit_context_new_constructor: type of struct "
+		      "field differs from type of construct field "
+		      "(struct: int b)(ctor: float b)");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-ctor-union-wrong-field-name.c b/gcc/testsuite/jit.dg/test-error-ctor-union-wrong-field-name.c
new file mode 100644
index 00000000000..f5b76095f69
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-ctor-union-wrong-field-name.c
@@ -0,0 +1,80 @@
+/*
+
+  Test that the proper error is triggered when we build a ctor
+  for an union type, but don't provide a correct field.
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+  gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_FLOAT);
+  gcc_jit_type *double_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_DOUBLE);
+
+  gcc_jit_field *b1 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "a");
+  gcc_jit_field *b2 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 float_type,
+						 "b");
+  gcc_jit_field *b3 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 double_type,
+						 "c");
+  gcc_jit_field *fields_b[] = {b1, b2, b3};
+
+  gcc_jit_type *union_bar_type =
+      gcc_jit_context_new_union_type (ctxt,
+				      0,
+				      "bar",
+				      3,
+				      fields_b);
+  
+  gcc_jit_field *b33 = gcc_jit_context_new_field (ctxt,
+						  0,
+						  double_type,
+						  "cc"); /* wrong */
+
+
+  gcc_jit_field *fields_ctor[] = {b33};
+  gcc_jit_rvalue *values[] = {0};
+
+  gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+    (ctxt, 0,
+     union_bar_type,
+     1,
+     fields_ctor,
+     values);
+
+  CHECK_VALUE (ctor, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "gcc_jit_context_new_constructor: constructor field "
+		      "does not exist in the union type (field: double cc)"
+		      "(type: union bar)");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "gcc_jit_context_new_constructor: constructor field "
+		      "does not exist in the union type (field: double cc)"
+		      "(type: union bar)");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-global-allready-init.c b/gcc/testsuite/jit.dg/test-error-global-allready-init.c
new file mode 100644
index 00000000000..7eaf182029d
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-global-allready-init.c
@@ -0,0 +1,46 @@
+/*
+
+  Test that we can't set the initializer on a global twice.
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+    ctxt, NULL,
+    GCC_JIT_GLOBAL_EXPORTED,
+    int_type,
+    "global_lvalueinit_int_0");
+
+  gcc_jit_global_set_initializer_rvalue (
+    bar,
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1));
+  gcc_jit_global_set_initializer_rvalue (
+    bar,
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "gcc_jit_global_set_initializer_rvalue: global variable "
+		      "allready initialized: global_lvalueinit_int_0");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "gcc_jit_global_set_initializer_rvalue: global variable "
+		      "allready initialized: global_lvalueinit_int_0");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-global-common-section.c b/gcc/testsuite/jit.dg/test-error-global-common-section.c
new file mode 100644
index 00000000000..000f59489a2
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-global-common-section.c
@@ -0,0 +1,54 @@
+/*
+
+  Test that the proper error is triggered when we initialize
+  a global with a global that has no DECL_INITIAL (and is marked
+  DECL_COMMON(NODE) = 1).
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+
+  /* const int foo;
+     int bar = foo;
+   */
+  gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+    ctxt, NULL,
+    GCC_JIT_GLOBAL_EXPORTED,
+    gcc_jit_type_get_const (int_type),
+    "global_const_int_0");
+  gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+    ctxt, NULL,
+    GCC_JIT_GLOBAL_EXPORTED,
+    int_type,
+    "global_lvalueinit_int_0"); 
+  gcc_jit_global_set_initializer_rvalue (bar,
+					 gcc_jit_lvalue_as_rvalue (foo));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "can't initialize global_lvalueinit_int_0 "
+		      "with global_const_int_0 since it has no "
+		      "initial value set");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "can't initialize global_lvalueinit_int_0 "
+		      "with global_const_int_0 since it has no "
+		      "initial value set");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-global-init-too-small-array.c b/gcc/testsuite/jit.dg/test-error-global-init-too-small-array.c
new file mode 100644
index 00000000000..137bae6c6b5
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-global-init-too-small-array.c
@@ -0,0 +1,64 @@
+/*
+
+  Test that the proper error is triggered when we initialize
+  a global with another non-const global's rvalue.
+
+  Using gcc_jit_global_set_initializer_rvalue()
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{ /* float foo[1] = {1,2}; */
+
+  gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_FLOAT);
+  gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							   0,
+							   float_type,
+							   1);
+  gcc_jit_rvalue *rval_1 = gcc_jit_context_new_rvalue_from_int (
+    ctxt, float_type, 1);
+  gcc_jit_rvalue *rval_2 = gcc_jit_context_new_rvalue_from_int (
+    ctxt, float_type, 2);
+
+  gcc_jit_rvalue *values[] = {rval_1, rval_2};
+
+  gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							  0,
+							  arr_type,
+							  2,
+							  0,
+							  values);
+  if (!ctor)
+    return;
+  
+  gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+    ctxt, NULL,
+    GCC_JIT_GLOBAL_EXPORTED,
+    arr_type,
+    "global_floatarr_12");
+  gcc_jit_global_set_initializer_rvalue (foo, ctor);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "gcc_jit_context_new_constructor: array constructor has"
+		      " more values than the array type's length");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "gcc_jit_context_new_constructor: array constructor has"
+		      " more values than the array type's length");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-global-lvalue-init.c b/gcc/testsuite/jit.dg/test-error-global-lvalue-init.c
new file mode 100644
index 00000000000..c6e1f0ea4fe
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-global-lvalue-init.c
@@ -0,0 +1,60 @@
+/*
+
+  Test that the proper error is triggered when we initialize
+  a global with another non-const global's rvalue.
+
+  Using gcc_jit_global_set_initializer_rvalue()
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+
+  gcc_jit_lvalue *foo;
+  { /* int bar; */
+    foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_lvalueinit_int1");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval);
+  }
+  { /* int foo = bar; */
+	     
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_lvalueinit_int2"); 
+    gcc_jit_global_set_initializer_rvalue (bar,
+					   gcc_jit_lvalue_as_rvalue (foo));
+  }
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "init rvalue for the global variable "
+		      "global_lvalueinit_int2 does not seem to be constant");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "init rvalue for the global variable "
+		      "global_lvalueinit_int2 does not seem to be constant");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-global-nonconst-init.c b/gcc/testsuite/jit.dg/test-error-global-nonconst-init.c
new file mode 100644
index 00000000000..d04db8ba8ab
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-global-nonconst-init.c
@@ -0,0 +1,80 @@
+/*
+
+  Test that the proper error is triggered when we initialize
+  a global with a function call.
+
+  Using gcc_jit_global_set_initializer_rvalue()
+
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+  
+  gcc_jit_function *fn_int_3; 
+  { /* int foo () { int local = 3; return local;} */
+    fn_int_3 =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    int_type,
+				    "fn_int_3",
+				    0,
+				    0,
+				    0);
+    gcc_jit_block *block = gcc_jit_function_new_block (fn_int_3, "start");
+    gcc_jit_lvalue *local = gcc_jit_function_new_local (fn_int_3,
+							0,
+							int_type,
+							"local");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+
+    gcc_jit_block_add_assignment (block, 0, local, rval);
+
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(local));
+							  
+  }
+
+  { /* int bar = foo(); */
+    gcc_jit_rvalue *rval =
+      gcc_jit_context_new_call (ctxt,
+			        0,
+				fn_int_3,
+				0,0);
+						     
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_nonconst_int"); 
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval);
+  }
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted. */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "init rvalue for the global variable "
+		      "global_nonconst_int does not seem to be constant");
+  CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+		      "init rvalue for the global variable "
+		      "global_nonconst_int does not seem to be constant");
+}
diff --git a/gcc/testsuite/jit.dg/test-global-init-rvalue.c b/gcc/testsuite/jit.dg/test-global-init-rvalue.c
new file mode 100644
index 00000000000..dd7c4277c68
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-global-init-rvalue.c
@@ -0,0 +1,1394 @@
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+#include "harness.h"
+
+/* This testcase checks that gcc_jit_global_set_initializer_rvalue() works
+   with rvalues, especially with gcc_jit_context_new_constructor() for
+   struct, unions and arrays. */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+  gcc_jit_type *short_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_SHORT);
+  gcc_jit_type *pint_type = gcc_jit_type_get_pointer (int_type);
+  gcc_jit_type *double_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_DOUBLE);
+  gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_FLOAT);
+  gcc_jit_type *bool_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_BOOL);
+  gcc_jit_type *char_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_CHAR);
+  gcc_jit_type *cpchar_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_CONST_CHAR_PTR);
+  gcc_jit_type *size_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_SIZE_T);
+
+  /* Make a struct: struct fi { float f; int i;} */
+  gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 float_type,
+						 "f");
+  gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "i");
+  gcc_jit_field *fields[] = {f1, f2};
+
+  gcc_jit_type *struct_fi_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt,
+				       0,
+				       "fi",
+				       2,
+				       fields));
+
+  /* Make a struct:
+
+     struct bar {
+       int ii;
+       struct fi fi;
+       float ff;
+     }
+  */
+  f1 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  float_type,
+				  "ff");
+  f2 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  int_type,
+				  "ii");
+  gcc_jit_field *fi = gcc_jit_context_new_field (ctxt,
+						 0,
+						 struct_fi_type,
+						 "fi");
+  gcc_jit_field *fields2[] = {f1, fi, f2};
+
+  gcc_jit_type *struct_bar_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt,
+				       0,
+				       "bar",
+				       3,
+				       fields2));
+
+  /* Make an union:
+
+     union ubar {
+       float ff;
+       int ii;
+     };
+  */
+  f1 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  float_type,
+				  "ff");
+  f2 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  int_type,
+				  "ii");
+  gcc_jit_field *fields3[] = {f1, f2};
+  
+  gcc_jit_type *ubar = gcc_jit_context_new_union_type (ctxt,
+						       0,
+						       "ubar",
+						       2,
+						       fields3);
+  
+  { /* struct bar bar = {.ii = 4, .ff = 1, .fi = {.i = 3, .f = 2}};
+       I.e. nested struct and nested ctors in "wrong" order.
+     */
+    gcc_jit_lvalue *bar = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_bar_type,
+      "global_struct_bar_1");
+
+    gcc_jit_rvalue *fval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+    gcc_jit_rvalue *ival = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    
+    gcc_jit_field *fi_f = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *fi_i = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");   
+    
+    gcc_jit_rvalue *vals[] = { ival, fval};
+    gcc_jit_field *fields[] = {fi_i, fi_f};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+
+    ival = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 4);
+    fval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 1);
+
+    gcc_jit_field *bar_fi = gcc_jit_context_new_field (ctxt,
+						       0,
+						       struct_fi_type,
+						       "fi");
+    gcc_jit_field *bar_ff = gcc_jit_context_new_field (ctxt,
+						       0,
+						       float_type,
+						       "ff");
+    gcc_jit_field *bar_ii = gcc_jit_context_new_field (ctxt,
+						       0,
+						       int_type,
+						       "ii");
+    
+    gcc_jit_rvalue *vals2[] = {ival, fval, ctor};
+    gcc_jit_field *fields2[] = {bar_ii, bar_ff, bar_fi};
+
+    gcc_jit_rvalue *ctor_bar = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_bar_type,
+       3,
+       fields2,
+       vals2);
+    
+    gcc_jit_global_set_initializer_rvalue (bar, ctor_bar);
+  }
+  { /* struct bar bar = {1, {2, 3}, 4};
+       I.e. nested struct and nested ctors in "right" order.
+     */
+    gcc_jit_lvalue *bar = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_bar_type,
+      "global_struct_bar_2");
+
+    gcc_jit_rvalue *fval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+    gcc_jit_rvalue *ival = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    
+    gcc_jit_field *fi_f = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *fi_i = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");   
+    
+    gcc_jit_rvalue *vals[] = { fval, ival};
+    gcc_jit_field *fields[] = {fi_f, fi_i};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+
+    ival = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 4);
+    fval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 1);
+
+    gcc_jit_field *bar_fi = gcc_jit_context_new_field (ctxt,
+						       0,
+						       struct_fi_type,
+						       "fi");
+    gcc_jit_field *bar_ff = gcc_jit_context_new_field (ctxt,
+						       0,
+						       float_type,
+						       "ff");
+    gcc_jit_field *bar_ii = gcc_jit_context_new_field (ctxt,
+						       0,
+						       int_type,
+						       "ii");
+    
+    gcc_jit_rvalue *vals2[] = {fval, ctor, ival};
+    gcc_jit_field *fields2[] = {bar_ff, bar_fi, bar_ii};
+
+    gcc_jit_rvalue *ctor_bar = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_bar_type,
+       3,
+       fields2,
+       vals2);
+    
+    gcc_jit_global_set_initializer_rvalue (bar, ctor_bar);
+  }
+  { /* struct fi foo = {2, 3}; */
+    gcc_jit_lvalue *foo = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_fi_type,
+      "global_struct_fi_1");
+
+    gcc_jit_rvalue *fval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+    gcc_jit_rvalue *ival = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    
+    gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");    
+    
+    gcc_jit_rvalue *vals[] = { fval, ival};
+    gcc_jit_field *fields[] = {f1, f2};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+    
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* struct fi foo = {.i = 3, .f = 2};
+
+       I.e. "wrong" order of fields.  */
+    gcc_jit_lvalue *foo = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_fi_type,
+      "global_struct_fi_2");
+
+    gcc_jit_rvalue *fval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+    gcc_jit_rvalue *ival = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    
+    gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");    
+    
+    gcc_jit_rvalue *vals[] = { ival, fval};
+    gcc_jit_field *fields[] = {f2, f1};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* struct fi foo = {0, 0}; (null init) */
+    gcc_jit_lvalue *foo = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_fi_type,
+      "global_struct_fi_4");
+
+    gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");    
+    
+    gcc_jit_rvalue *vals[] = { 0, 0};
+    gcc_jit_field *fields[] = {f1, f2};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+    
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* struct fi foo = {.i = 0};
+
+       I.e. "wrong" order of fields.
+       Null init values. */
+    gcc_jit_lvalue *foo = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_fi_type,
+      "global_struct_fi_5");
+
+    gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");    
+    
+    gcc_jit_rvalue *vals[] = {0};
+    gcc_jit_field *fields[] = {f2};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       1,
+       fields,
+       vals);
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* struct fi foo = {}; (null init)
+
+       Null fields and values. */
+    gcc_jit_lvalue *foo = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_fi_type,
+      "global_struct_fi_6");
+
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       0,
+       0,
+       0);
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* struct fi foo = {2 * 2, 3}; */
+    gcc_jit_lvalue *foo = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      struct_fi_type,
+      "global_struct_fi_3");
+
+    gcc_jit_rvalue *fval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+    gcc_jit_rvalue *fval2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+    gcc_jit_rvalue *ival = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval_mul = gcc_jit_context_new_binary_op (ctxt, 0,
+      GCC_JIT_BINARY_OP_MULT,
+      float_type,
+      fval,
+      fval2);
+    
+    gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");    
+    
+    gcc_jit_rvalue *vals[] = { rval_mul, ival};
+    gcc_jit_field *fields[] = {f1, f2};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+    
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* union ubar foo = {.ff = 3}; */
+     gcc_jit_lvalue *foo = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      ubar,
+      "global_union_ufoo_ff3");
+     
+     gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						    0,
+						    float_type,
+						    "ff");
+     gcc_jit_rvalue *fval = gcc_jit_context_new_rvalue_from_int (
+       ctxt, float_type, 3);
+     
+     gcc_jit_rvalue *vals[] = {fval};
+     gcc_jit_field *fields[] = {f1};
+
+     gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (
+       ctxt,
+       0,
+       ubar,
+       1,
+       fields,
+       vals);
+     
+     gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* int foo = 3; */
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3); 
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_int1_3"); 
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval);
+  }
+  { /* Try the above, but with opposite order of global and literal calls */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_int2_3");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);    
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval);
+  }
+  { /* int foo = 3 * (3 + 3) */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_int3_18");
+    gcc_jit_rvalue *rval3_0 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval3_1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval3_2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval_plus = gcc_jit_context_new_binary_op (ctxt, 0,
+      GCC_JIT_BINARY_OP_PLUS,
+      int_type,
+      rval3_0,
+      rval3_1);
+    gcc_jit_rvalue *rval_mul = gcc_jit_context_new_binary_op (ctxt, 0,
+      GCC_JIT_BINARY_OP_MULT,
+      int_type,
+      rval_plus,
+      rval3_2);
+    
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval_mul);
+  }
+  { /* int foo = 3; int *pfoo = &foo; */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_int4_3");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);    
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval);
+
+    gcc_jit_lvalue *pfoo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      pint_type,
+      "global_pint5");
+    gcc_jit_global_set_initializer_rvalue (pfoo,
+      gcc_jit_lvalue_get_address (foo, 0));
+  }
+  { /* int foo = 3; int *pfoo = &foo + 1; */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_int6_3");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);    
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval);
+
+    gcc_jit_lvalue *pfoo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      pint_type,
+      "global_pint7");
+    gcc_jit_global_set_initializer_rvalue (pfoo,
+      gcc_jit_lvalue_get_address (
+	gcc_jit_context_new_array_access(
+	  ctxt,
+	  0,
+	  gcc_jit_lvalue_get_address(foo, 0),
+	  gcc_jit_context_one(ctxt, int_type)),
+	0));
+  }
+  { /* double foo = 3; */
+    gcc_jit_lvalue *double1 =  gcc_jit_context_new_global (
+	ctxt, NULL,
+	GCC_JIT_GLOBAL_EXPORTED,
+	double_type,
+	"global_double1_3");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, double_type, 3);
+    gcc_jit_global_set_initializer_rvalue (double1,
+      rval);
+  }
+  { /* double foo = 3 * 3 + 3 */
+    gcc_jit_lvalue *double1 =  gcc_jit_context_new_global (
+	ctxt, NULL,
+	GCC_JIT_GLOBAL_EXPORTED,
+	double_type,
+	"global_double2_12");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, double_type, 3);
+    gcc_jit_rvalue *rval_mul = gcc_jit_context_new_binary_op (ctxt, 0,
+      GCC_JIT_BINARY_OP_MULT,
+      double_type,
+      rval,
+      rval);
+    gcc_jit_rvalue *rval_plus = gcc_jit_context_new_binary_op (ctxt, 0,
+      GCC_JIT_BINARY_OP_PLUS,
+      double_type,
+      rval_mul,
+      rval);
+    gcc_jit_global_set_initializer_rvalue (double1,
+      rval_plus);
+  }
+  { /* bool foo = 3 + 3 <= 6; */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      bool_type,
+      "global_bool1_1");
+    gcc_jit_rvalue *rval3_0 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval3_1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval6 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 6);
+    gcc_jit_rvalue *rval_plus = gcc_jit_context_new_binary_op (ctxt,
+      0,
+      GCC_JIT_BINARY_OP_PLUS,
+      int_type,
+      rval3_0,
+      rval3_1);
+    gcc_jit_rvalue *rval_le = gcc_jit_context_new_comparison (ctxt,
+      0,
+      GCC_JIT_COMPARISON_LE,
+      rval_plus,
+      rval6);
+    
+    gcc_jit_global_set_initializer_rvalue (foo,
+      rval_le);
+  }
+  gcc_jit_lvalue *global_intarr_1234;
+  { /* int foo[] = {1,2,3,4}; */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     int_type,
+							     4);
+    gcc_jit_rvalue *rval_1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 1);
+    gcc_jit_rvalue *rval_2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 2);
+    gcc_jit_rvalue *rval_3 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval_4 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 4);
+
+    gcc_jit_rvalue *values[] = {rval_1, rval_2, rval_3, rval_4};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    4,
+							    0,
+							    values);
+    global_intarr_1234 = gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_intarr_1234");
+    gcc_jit_global_set_initializer_rvalue (global_intarr_1234, ctor);
+  }
+  { /* float foo[4] = {1,2}; */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     float_type,
+							     4);
+    gcc_jit_rvalue *rval_1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 1);
+    gcc_jit_rvalue *rval_2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+
+    gcc_jit_rvalue *values[] = {rval_1, rval_2};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    2,
+							    0,
+							    values);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_floatarr_12");
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* float foo[4] = {1,2,0}; (null init) */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     float_type,
+							     4);
+    gcc_jit_rvalue *rval_1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 1);
+    gcc_jit_rvalue *rval_2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 2);
+
+    gcc_jit_rvalue *values[] = {rval_1, rval_2, 0};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    2,
+							    0,
+							    values);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_floatarr_120");
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* float foo[4] = {}; (null init) */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     float_type,
+							     4);
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    0,
+							    0,
+							    0);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_floatarr_0000");
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* float foo[4] = {NULL , NULL, 3, NULL}; (null init) */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     float_type,
+							     8);
+    gcc_jit_rvalue *rval3 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 3);
+    gcc_jit_rvalue *rval5 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 5);
+    gcc_jit_rvalue *rval6 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 6);
+
+    gcc_jit_rvalue *values[] = {0, 0, rval3, 0, rval5, rval6, 0 };
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    7,
+							    0,
+							    values);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_floatarr_00305600");
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* int *foo[4] = {0, &global_intarr_1234[1]}; */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     pint_type,
+							     4);
+    gcc_jit_rvalue *rval_1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 1);
+    gcc_jit_lvalue *arr_access = gcc_jit_context_new_array_access (
+      ctxt,
+      0,
+      gcc_jit_lvalue_as_rvalue (global_intarr_1234),
+      rval_1);
+    gcc_jit_rvalue *rval_2 = gcc_jit_lvalue_get_address (arr_access, 0);
+
+    gcc_jit_rvalue *values[] = {0, rval_2};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    2,
+							    0,
+							    values);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_pintarr_x2xx");
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* char foo[4] = {'q','w','e',0}; */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     char_type,
+							     4);
+
+
+    gcc_jit_rvalue *rvals[] = {
+      gcc_jit_context_new_rvalue_from_int ( ctxt, char_type, 'q'),
+      gcc_jit_context_new_rvalue_from_int ( ctxt, char_type, 'w'),
+      gcc_jit_context_new_rvalue_from_int ( ctxt, char_type, 'e'),
+      gcc_jit_context_new_rvalue_from_int ( ctxt, char_type, 0)     
+    };
+
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    4,
+							    0,
+							    rvals);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_chararr_qwe");
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* int foo[2][2] = {{1,2},{3,4}}; */
+
+    gcc_jit_type *row_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     int_type,
+							     2);
+    
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     row_type,
+							     2);
+    gcc_jit_rvalue *rvals_row0[] = {
+      gcc_jit_context_new_rvalue_from_int ( ctxt, int_type, 1),
+      gcc_jit_context_new_rvalue_from_int ( ctxt, int_type, 2)
+    };
+    gcc_jit_rvalue *rvals_row1[] = {
+      gcc_jit_context_new_rvalue_from_int ( ctxt, int_type, 3),
+      gcc_jit_context_new_rvalue_from_int ( ctxt, int_type, 4)
+    };
+
+    gcc_jit_rvalue *ctor_row0 =
+      gcc_jit_context_new_constructor (ctxt,
+				       0,
+				       row_type,
+				       2,
+				       0,
+				       rvals_row0);
+    gcc_jit_rvalue *ctor_row1 =
+      gcc_jit_context_new_constructor (ctxt,
+				       0,
+				       row_type,
+				       2,
+				       0,
+				       rvals_row1);
+    gcc_jit_rvalue *ctors_row[] = {ctor_row0, ctor_row1};
+    
+    gcc_jit_rvalue *ctor_arr =
+      gcc_jit_context_new_constructor (ctxt,
+				       0,
+				       arr_type,
+				       2,
+				       0,
+				       ctors_row);
+    
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_int2x2matrix_1234");
+    
+    gcc_jit_global_set_initializer_rvalue (foo, ctor_arr);
+  }  
+  { /* const char *foo[4] = {"qwe", "asd"}; */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     cpchar_type,
+							     4);
+
+
+    gcc_jit_rvalue *rvals[] = {
+      gcc_jit_context_new_string_literal (ctxt, "qwe"),
+      gcc_jit_context_new_string_literal (ctxt, "asd")
+    };
+
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    2,
+							    0,
+							    rvals);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      arr_type,
+      "global_cpchararr_qwe_asd");
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+  { /* const int foo = 3;
+       int bar = foo;
+     */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (int_type),
+      "global_const_int_3");
+    gcc_jit_rvalue *rval3 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_global_set_initializer_rvalue (foo,
+	rval3);
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_lvalueinit_int_3"); 
+    gcc_jit_global_set_initializer_rvalue (bar,
+					   gcc_jit_lvalue_as_rvalue (foo));
+  }
+  { /* int foo = 3 * 2;
+       int arr[] = {1,2,3,4};
+       int *bar = &arr[2] + 1
+
+       Example in the docs.
+     */
+
+    gcc_jit_type *arr_type = gcc_jit_context_new_array_type (ctxt,
+							     0,
+							     int_type,
+							     4);
+    gcc_jit_rvalue *rval_1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 1);
+    gcc_jit_rvalue *rval_2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 2);
+    gcc_jit_rvalue *rval_3 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_rvalue *rval_4 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 4);
+
+    gcc_jit_rvalue *values[] = {rval_1, rval_2, rval_3, rval_4};
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor (ctxt,
+							    0,
+							    arr_type,
+							    4,
+							    0,
+							    values);
+    gcc_jit_lvalue *global_intarr_1234 =
+      gcc_jit_context_new_global (ctxt, NULL,
+				  GCC_JIT_GLOBAL_EXPORTED,
+				  arr_type,
+				  "global_intarr_1234_2");
+    
+    gcc_jit_global_set_initializer_rvalue (global_intarr_1234, ctor);
+
+    gcc_jit_lvalue *bar =
+      gcc_jit_context_new_global (ctxt, NULL,
+				  GCC_JIT_GLOBAL_EXPORTED,
+				  int_type,
+				  "global_int_6");
+    gcc_jit_global_set_initializer_rvalue
+      (bar,
+       gcc_jit_context_new_binary_op
+	 (ctxt, 0, GCC_JIT_BINARY_OP_MULT,
+	  int_type,
+	  gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 3),
+	  gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2)));
+    
+    gcc_jit_lvalue *pfoo =
+      gcc_jit_context_new_global (ctxt, NULL,
+				  GCC_JIT_GLOBAL_EXPORTED,
+				  gcc_jit_type_get_pointer (int_type),
+				  "global_pint_4");
+    /* int *bar = &arr[2] + 1;
+
+       In practice we could just do &foo[3]
+       but just prove folding this works. */
+    gcc_jit_global_set_initializer_rvalue (
+       pfoo,
+       gcc_jit_lvalue_get_address (
+         gcc_jit_context_new_array_access (
+           ctxt, 0, 
+           gcc_jit_lvalue_get_address (
+	     gcc_jit_context_new_array_access (
+	       ctxt, 0,
+	       gcc_jit_lvalue_as_rvalue (global_intarr_1234),
+	       gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2)),
+	       0),
+	   gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1)),
+	   0));
+  }
+  { /*  static int bar = 11;
+        int foo () { return bar; } */
+    
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_static_int_11");
+    gcc_jit_rvalue *rval1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 11);
+    gcc_jit_global_set_initializer_rvalue (bar,
+	rval1);
+
+    gcc_jit_function *fn11 =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    int_type,
+				    "fn_int_11",
+				    0,
+				    0,
+				    0);
+    gcc_jit_block *block = gcc_jit_function_new_block (fn11, "start");
+
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(bar));
+							  
+  }
+  { /* static const int cbar = 11;
+       int cfoo () { return cbar; } */
+
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (int_type),
+      "global_static_cint_11");
+    gcc_jit_rvalue *rval1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 11);
+    gcc_jit_global_set_initializer_rvalue (bar,
+	rval1);
+
+    gcc_jit_function *fn11 =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    int_type,
+				    "fn_cint_11",
+				    0,
+				    0,
+				    0);
+    gcc_jit_block *block = gcc_jit_function_new_block (fn11, "start");
+
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(bar));
+  }
+  { /* static const int cbar = 12;
+       const int* cfoo () { return &cbar; } */
+
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (int_type),
+      "global_static_cint_12");
+    gcc_jit_rvalue *rval1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 12);
+    gcc_jit_global_set_initializer_rvalue (bar,
+	rval1);
+
+    gcc_jit_function *fn11 =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    gcc_jit_type_get_pointer(int_type),
+				    "fn_cint_12",
+				    0,
+				    0,
+				    0);
+
+    gcc_jit_block *block = gcc_jit_function_new_block (fn11, "start");
+
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_get_address (bar, 0));
+  }
+  { /* const int foo = 3;
+       short bar = (short)foo;
+
+       Assure casts fold
+     */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (int_type),
+      "global_const_int_4");
+    gcc_jit_rvalue *rval3 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_global_set_initializer_rvalue (foo,
+	rval3);
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      short_type,
+      "global_lvalueinit_short_3"); 
+    gcc_jit_global_set_initializer_rvalue (
+      bar,
+      gcc_jit_context_new_cast( ctxt, 0,
+				gcc_jit_lvalue_as_rvalue (foo),
+				short_type));
+  }
+  { /* const int foo = 3;
+       const int const *bar = &foo; */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (int_type),
+      "global_const_int_6");
+    gcc_jit_rvalue *rval3 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+    gcc_jit_global_set_initializer_rvalue (foo,
+	rval3);
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (
+        gcc_jit_type_get_pointer (
+          gcc_jit_type_get_const (
+	    int_type))),
+      "global_lvalueinit_cpcint_3"); 
+    gcc_jit_global_set_initializer_rvalue (
+      bar,
+      gcc_jit_lvalue_get_address (foo, 0));
+  }
+  { /* const int __attribute__ ((aligned (64))) foo = 3;
+       int bar = foo;
+
+       Assure alignement does not make the constant "miss"
+       or something strange.
+     */
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (gcc_jit_type_get_aligned (int_type, 64)),
+      "global_const_int_7");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 4);
+    gcc_jit_global_set_initializer_rvalue (foo,
+	rval);
+    gcc_jit_lvalue *bar =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      int_type,
+      "global_lvalueinit_int_4"); 
+    gcc_jit_global_set_initializer_rvalue (bar,
+					   gcc_jit_lvalue_as_rvalue (foo));
+  }
+  {
+    /* union upintsize { size_t s; int *p } u = {.s = 0x0EEFBEEF}; */
+    gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   size_type,
+						   "s");
+    gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						   0,
+						   pint_type,
+						   "p");
+    gcc_jit_field *fields1[] = {f1, f2};
+  
+    gcc_jit_type *ubar = gcc_jit_context_new_union_type (ctxt,
+							 0,
+							 "upintsize",
+							 2,
+							 fields1);
+    gcc_jit_lvalue *foo =  gcc_jit_context_new_global (
+      ctxt, NULL,
+      GCC_JIT_GLOBAL_EXPORTED,
+      gcc_jit_type_get_const (ubar),
+      "global_const_upintsize_1");
+
+    
+    gcc_jit_field *ff = gcc_jit_context_new_field (ctxt,
+						   0,
+						   size_type,
+						   "s");
+    gcc_jit_rvalue *val = gcc_jit_context_new_rvalue_from_long_long (
+      ctxt, size_type, 0xBAAAABBEEEEFBEEF);
+     
+    gcc_jit_rvalue *vals[] = {val};
+    gcc_jit_field *fields2[] = {ff};
+
+    gcc_jit_rvalue *ctor =
+      gcc_jit_context_new_constructor (ctxt,
+				       0,
+				       ubar,
+				       1,
+				       fields2,
+				       vals);
+
+    gcc_jit_global_set_initializer_rvalue (foo, ctor);
+  }
+}
+
+struct fi {
+  float f;
+  int i;
+};
+
+struct bar1 {
+  float ff;
+  struct fi fi;
+  int ii;
+};
+
+union ubar1 {
+  float ff;
+  int ii;
+};
+
+union upintsize {
+  size_t s;
+  int *p;
+};
+
+int test_aligned64_works_in_linker_1 __attribute__ ((aligned (64))) = 0;
+int test_aligned64_works_in_linker_2 __attribute__ ((aligned (64))) = 0;
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_NON_NULL (result);
+  gcc_jit_context_compile_to_file (ctxt, GCC_JIT_OUTPUT_KIND_OBJECT_FILE, "a.out");
+  {
+    struct fi *fi = gcc_jit_result_get_global (result, "global_struct_fi_1");
+
+    CHECK_VALUE (fi->f, 2);
+    CHECK_VALUE (fi->i, 3);
+  }
+  {
+    struct fi *fi = gcc_jit_result_get_global (result, "global_struct_fi_2");
+
+    CHECK_VALUE (fi->f, 2);
+    CHECK_VALUE (fi->i, 3);
+  }
+  {
+    struct fi *fi = gcc_jit_result_get_global (result, "global_struct_fi_3");
+
+    CHECK_VALUE (fi->f, 2 * 2);
+    CHECK_VALUE (fi->i, 3);
+  }
+  {
+    struct fi *fi = gcc_jit_result_get_global (result, "global_struct_fi_4");
+
+    CHECK_VALUE (fi->f, 0);
+    CHECK_VALUE (fi->i, 0);
+  }
+  {
+    struct fi *fi = gcc_jit_result_get_global (result, "global_struct_fi_5");
+
+    CHECK_VALUE (fi->f, 0);
+    CHECK_VALUE (fi->i, 0);
+  }
+  {
+    struct fi *fi = gcc_jit_result_get_global (result, "global_struct_fi_6");
+
+    CHECK_VALUE (fi->f, 0);
+    CHECK_VALUE (fi->i, 0);
+  }  
+  {
+    struct bar1 *bar = gcc_jit_result_get_global (result, "global_struct_bar_1");
+
+    CHECK_VALUE (bar->ff, 1);
+    CHECK_VALUE (bar->ii, 4);
+    CHECK_VALUE (bar->fi.f, 2);
+    CHECK_VALUE (bar->fi.i, 3);
+
+    bar = gcc_jit_result_get_global (result, "global_struct_bar_2");
+
+    CHECK_VALUE (bar->ff, 1);
+    CHECK_VALUE (bar->ii, 4);
+    CHECK_VALUE (bar->fi.f, 2);
+    CHECK_VALUE (bar->fi.i, 3);
+  }
+  {
+    union ubar1 *foo = gcc_jit_result_get_global (result,
+						 "global_union_ufoo_ff3");
+    CHECK_VALUE (foo->ff, 3);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_int1_3");
+
+    CHECK_VALUE (*foo, 3);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_int2_3");
+
+    CHECK_VALUE (*foo, 3);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_int3_18");
+
+    CHECK_VALUE (*foo, 18);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_int4_3");
+    int **pfoo = gcc_jit_result_get_global (result, "global_pint5");
+
+    CHECK_VALUE (*foo, 3);
+    CHECK_VALUE (foo, *pfoo);
+    CHECK_VALUE (**pfoo, 3);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_int6_3");
+    int **pfoo = gcc_jit_result_get_global (result, "global_pint7");
+
+    CHECK_VALUE (*foo, 3);
+    CHECK_VALUE (foo + 1, *pfoo);
+    CHECK_VALUE (*(*pfoo - 1), 3);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_lvalueinit_int_3");
+
+    CHECK_VALUE (*foo, 3);
+  }
+  {
+    double *foo = gcc_jit_result_get_global (result, "global_double1_3");
+
+    CHECK_VALUE (*foo, 3);
+  }
+  {
+    double *foo = gcc_jit_result_get_global (result, "global_double2_12");
+
+    CHECK_VALUE (*foo, 12);
+  }
+  {
+    _Bool *foo = gcc_jit_result_get_global (result, "global_bool1_1");
+
+    CHECK_VALUE (*foo, 1);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_intarr_1234");
+
+    CHECK_VALUE (foo[0], 1);
+    CHECK_VALUE (foo[1], 2);
+    CHECK_VALUE (foo[2], 3);
+    CHECK_VALUE (foo[3], 4);
+  }
+  {
+    float *foo = gcc_jit_result_get_global (result, "global_floatarr_12");
+
+    CHECK_VALUE (foo[0], 1);
+    CHECK_VALUE (foo[1], 2);
+    CHECK_VALUE (foo[2], 0);
+    CHECK_VALUE (foo[3], 0);
+  }
+  {
+    float *foo = gcc_jit_result_get_global (result, "global_floatarr_120");
+
+    CHECK_VALUE (foo[0], 1);
+    CHECK_VALUE (foo[1], 2);
+    CHECK_VALUE (foo[2], 0);
+    CHECK_VALUE (foo[3], 0);
+  }
+  {
+    float *foo = gcc_jit_result_get_global (result, "global_floatarr_0000");
+
+    CHECK_VALUE (foo[0], 0);
+    CHECK_VALUE (foo[1], 0);
+    CHECK_VALUE (foo[2], 0);
+    CHECK_VALUE (foo[3], 0);
+  }
+  {
+    float *foo = gcc_jit_result_get_global (result, "global_floatarr_00305600");
+
+    float key[] = {0,0,3,0,5,6,0,0};
+
+    CHECK_VALUE (memcmp (foo, key, sizeof key), 0);
+  }    
+  {
+    int **foo = gcc_jit_result_get_global (result, "global_pintarr_x2xx");
+
+    CHECK_VALUE (foo[0], 0);
+    CHECK_VALUE (*foo[1], 2);
+  }
+  {
+    char *foo = gcc_jit_result_get_global (result, "global_chararr_qwe");
+    const char *key = "qwe";
+    CHECK_VALUE (strcmp (foo, key), 0);
+  }
+  {
+    int *foo = gcc_jit_result_get_global (result, "global_int2x2matrix_1234");
+
+    for (int i = 0; i < 4; i++)
+      CHECK_VALUE (foo[i], i + 1);
+  }
+  {
+    const char **foo =
+      gcc_jit_result_get_global (result, "global_cpchararr_qwe_asd");
+
+    CHECK_VALUE (strcmp (foo[0], "qwe"), 0);
+    CHECK_VALUE (strcmp (foo[1], "asd"), 0);    
+  }
+  {
+    int **pint =
+      gcc_jit_result_get_global (result, "global_pint_4");
+    int *foo =
+      gcc_jit_result_get_global (result, "global_int_6");    
+    CHECK_VALUE (**pint, 4);
+    CHECK_VALUE (*foo, 6);    
+  }
+  {
+    int (*fn)(void) = gcc_jit_result_get_code (result, "fn_int_11");
+    CHECK_VALUE (fn (), 11);
+  }
+  {
+    int (*fn)(void) = gcc_jit_result_get_code (result, "fn_cint_11");
+    CHECK_VALUE (fn (), 11);
+  }
+  {
+    short *foo =
+      gcc_jit_result_get_code (result, "global_lvalueinit_short_3");
+    CHECK_VALUE (*foo, 3);
+  }
+  {
+    int **foo =
+      gcc_jit_result_get_code (result, "global_lvalueinit_cpcint_3");
+    CHECK_VALUE (**foo, 3);
+  }
+  {
+    int *foo =
+      gcc_jit_result_get_code (result, "global_lvalueinit_int_4");
+    CHECK_VALUE (*foo, 4);
+
+    int *bar =
+      gcc_jit_result_get_code (result, "global_const_int_7");
+    CHECK_VALUE (*bar, 4);
+    /* The linker does not have to support up to 64 alignment, so test that
+       it does before testing that it works in libgccjit. */
+    if ((size_t) &test_aligned64_works_in_linker_1 % 64 == 0 &&
+	(size_t) &test_aligned64_works_in_linker_2 % 64 == 0)
+      CHECK_VALUE ((size_t) bar % 64, 0); /* __attribute__ ((aligned (64))) */
+  }
+  {
+    union upintsize *foo =
+      gcc_jit_result_get_code (result, "global_const_upintsize_1");
+    CHECK_VALUE (foo->p, (void*)0xBAAAABBEEEEFBEEF);
+  }  
+}
diff --git a/gcc/testsuite/jit.dg/test-local-init-rvalue.c b/gcc/testsuite/jit.dg/test-local-init-rvalue.c
new file mode 100644
index 00000000000..7ca26e9034f
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-local-init-rvalue.c
@@ -0,0 +1,576 @@
+
+
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* This testcase checks that gcc_jit_context_new_constructor() works
+   with locals. Tests that constructors can be used as return
+   values or function call values. Test that constructors can have side
+   effects and be assigned to locals.
+ */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_INT);
+  gcc_jit_type *pint_type = gcc_jit_type_get_pointer (int_type);
+  gcc_jit_type *double_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_DOUBLE);
+  gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_FLOAT);
+  gcc_jit_type *bool_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_BOOL);
+  gcc_jit_type *size_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_SIZE_T);
+  gcc_jit_type *voidptr_type = gcc_jit_context_get_type (ctxt,
+    GCC_JIT_TYPE_VOID_PTR);  
+
+  /* Make a struct: struct fi { float f; int i;} */
+  gcc_jit_field *f1 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 float_type,
+						 "f");
+  gcc_jit_field *f2 = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int_type,
+						 "i");
+  gcc_jit_field *fields[] = {f1, f2};
+
+  gcc_jit_type *struct_fi_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt,
+				       0,
+				       "fi",
+				       2,
+				       fields));
+
+  /* Make a struct:
+
+     struct bar {
+       int ii;
+       int arr[50];
+       float ff;
+     }
+  */
+  f1 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  float_type,
+				  "ff");
+  f2 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  int_type,
+				  "ii");
+  gcc_jit_type *int50arr_type =
+    gcc_jit_context_new_array_type (ctxt,
+				    0,
+				    int_type,
+				    50);
+  gcc_jit_field *fi = gcc_jit_context_new_field (ctxt,
+						 0,
+						 int50arr_type,
+						 "arr");
+  gcc_jit_field *fields2[] = {f1, fi, f2};
+
+  gcc_jit_type *struct_bar_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt,
+				       0,
+				       "bar",
+				       3,
+				       fields2));
+
+  /* Make an union:
+
+     union ubar {
+       float ff;
+       int ii;
+     };
+  */
+  f1 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  float_type,
+				  "ff");
+  f2 = gcc_jit_context_new_field (ctxt,
+				  0,
+				  int_type,
+				  "ii");
+  gcc_jit_field *fields3[] = {f1, f2};
+  
+  gcc_jit_type *ubar = gcc_jit_context_new_union_type (ctxt,
+						       0,
+						       "ubar",
+						       2,
+						       fields3);
+  
+  (void) ubar;
+  (void) struct_bar_type;
+  (void) struct_fi_type;
+  (void) bool_type;
+  (void) double_type;
+  (void) pint_type;
+  (void) voidptr_type;
+  (void) size_type;
+
+  gcc_jit_function *fn_int_3; 
+  { /* int foo () { int local = 3; return local;} */
+    fn_int_3 =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    int_type,
+				    "fn_int_3",
+				    0,
+				    0,
+				    0);
+    gcc_jit_block *block = gcc_jit_function_new_block (fn_int_3, "start");
+    gcc_jit_lvalue *local = gcc_jit_function_new_local (fn_int_3,
+							0,
+							int_type,
+							"local");
+    gcc_jit_rvalue *rval = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 3);
+
+    gcc_jit_block_add_assignment (block, 0, local, rval);
+
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(local));
+							  
+  }
+  { /* struct fi foo() { return (struct fi){1,2};} */
+    gcc_jit_function *fn =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    struct_fi_type,
+				    "fn_fi_1_2",
+				    0,
+				    0,
+				    0);
+    gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
+
+    gcc_jit_rvalue *rval_f1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 1);
+    gcc_jit_rvalue *rval_i2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 2);
+
+    gcc_jit_field *f_f = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *f_i = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");
+
+    gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
+    gcc_jit_field *fields[] = {f_f, f_i};
+
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   ctor);
+  }
+  { /* struct fi foo() { struct fi local = {1,2};
+                         local = (struct fi){5,6};
+                         return local;} */
+    gcc_jit_function *fn =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    struct_fi_type,
+				    "fn_fi_5_6",
+				    0,
+				    0,
+				    0);
+    gcc_jit_lvalue *local = gcc_jit_function_new_local (fn,
+							0,
+							struct_fi_type,
+							"local");
+    gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
+
+    {
+      gcc_jit_rvalue *rval_f1 =
+	gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 1);
+      gcc_jit_rvalue *rval_i2 =
+	gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2);
+
+      gcc_jit_field *f_f = gcc_jit_context_new_field (ctxt,
+						      0,
+						      float_type,
+						      "f");
+      gcc_jit_field *f_i = gcc_jit_context_new_field (ctxt,
+						      0,
+						      int_type,
+						      "i");
+
+      gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
+      gcc_jit_field *fields[] = {f_f, f_i};
+
+      gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+	(ctxt, 0,
+	 struct_fi_type,
+	 2,
+	 fields,
+	 vals);
+      gcc_jit_block_add_assignment (block, 0, local, ctor);
+    }
+    {
+      gcc_jit_rvalue *rval_f1 =
+	gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 5);
+      gcc_jit_rvalue *rval_i2 =
+	gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 6);
+
+      gcc_jit_field *f_f = gcc_jit_context_new_field (ctxt,
+						      0,
+						      float_type,
+						      "f");
+      gcc_jit_field *f_i = gcc_jit_context_new_field (ctxt,
+						      0,
+						      int_type,
+						      "i");
+
+      gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
+      gcc_jit_field *fields[] = {f_f, f_i};
+
+      gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+	(ctxt, 0,
+	 struct_fi_type,
+	 2,
+	 fields,
+	 vals);
+      gcc_jit_block_add_assignment (block, 0, local, ctor);
+    }
+    
+    
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(local));
+  }
+  { /* struct fi foo() { struct fi local = {1, fn_int_3()};
+                         return local;}
+
+       The ctor has a side effect (funccall) */
+    gcc_jit_function *fn =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    struct_fi_type,
+				    "fn_fi_1_3",
+				    0,
+				    0,
+				    0);
+    gcc_jit_lvalue *local = gcc_jit_function_new_local (fn,
+							0,
+							struct_fi_type,
+							"local");
+    gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
+
+    {
+      gcc_jit_rvalue *rval_f1 =
+	gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 1);
+      gcc_jit_rvalue *rval_i2 =
+	gcc_jit_context_new_call (ctxt, 0, fn_int_3, 0, 0);
+
+      gcc_jit_field *f_f = gcc_jit_context_new_field (ctxt,
+						      0,
+						      float_type,
+						      "f");
+      gcc_jit_field *f_i = gcc_jit_context_new_field (ctxt,
+						      0,
+						      int_type,
+						      "i");
+
+      gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
+      gcc_jit_field *fields[] = {f_f, f_i};
+
+      gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+	(ctxt, 0,
+	 struct_fi_type,
+	 2,
+	 fields,
+	 vals);
+      gcc_jit_block_add_assignment (block, 0, local, ctor);
+    }
+    
+    
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(local));
+  }   
+  { /* struct fi foo(fi) { return fi;}
+       struct fi bar() { return foo((struct fi){3, 4}); } 
+     */
+
+    gcc_jit_param *fi_param =
+      gcc_jit_context_new_param (ctxt, 0, struct_fi_type, "fi");
+    
+    gcc_jit_function *fn0 =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    struct_fi_type,
+				    "fn_fi_x_x",
+				    1,
+				    &fi_param,
+				    0);
+    gcc_jit_block *block0 = gcc_jit_function_new_block (fn0, "start");
+    gcc_jit_block_end_with_return (block0,
+				   0,
+				   gcc_jit_param_as_rvalue (
+	                             gcc_jit_function_get_param (fn0, 0)));
+
+    gcc_jit_function *fn =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    struct_fi_type,
+				    "fn_fi_3_4",
+				    0,
+				    0,
+				    0);
+    gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
+
+    gcc_jit_rvalue *rval_f1 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, float_type, 3);
+    gcc_jit_rvalue *rval_i2 = gcc_jit_context_new_rvalue_from_int (
+      ctxt, int_type, 4);
+
+    gcc_jit_field *f_f = gcc_jit_context_new_field (ctxt,
+						   0,
+						   float_type,
+						   "f");
+    gcc_jit_field *f_i = gcc_jit_context_new_field (ctxt,
+						   0,
+						   int_type,
+						   "i");
+
+    gcc_jit_rvalue *vals[] = { rval_f1, rval_i2};
+    gcc_jit_field *fields[] = {f_f, f_i};
+
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+      (ctxt, 0,
+       struct_fi_type,
+       2,
+       fields,
+       vals);
+
+    gcc_jit_rvalue *call = gcc_jit_context_new_call (ctxt, 0, fn0, 1, &ctor);
+
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   call);
+  }
+  { /* struct bar foo() { struct bar local = {};
+                          return local;}
+     */
+    gcc_jit_function *fn =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    struct_bar_type,
+				    "fn_bar_0s",
+				    0,
+				    0,
+				    0);
+    gcc_jit_lvalue *local =
+      gcc_jit_function_new_local (fn,
+				  0,
+				  struct_bar_type,
+				  "local");
+    gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
+
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+	(ctxt, 0,
+	 struct_bar_type,
+	 0,
+	 0,
+	 0);
+    gcc_jit_block_add_assignment (block, 0, local, ctor);
+   
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(local));
+  }
+  { /* struct bar foo() { struct bar local;
+                          local.arr = (int [50]){1,2,3,4,5,6};
+                          return local;}
+     */
+    gcc_jit_function *fn =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    struct_bar_type,
+				    "fn_bar_123s",
+				    0,
+				    0,
+				    0);
+    gcc_jit_lvalue *local =
+      gcc_jit_function_new_local (fn,
+				  0,
+				  struct_bar_type,
+				  "local");
+    gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
+
+    gcc_jit_rvalue *values[6];
+
+    for (int i = 0; i < 6; i++)
+      values[i] = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, i + 1);
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+	(ctxt, 0,
+	 int50arr_type,
+	 6,
+	 0,
+	 values);
+
+    gcc_jit_lvalue *arr_lv = gcc_jit_lvalue_access_field (local,
+							  0,
+							  fi);
+    gcc_jit_block_add_assignment (block, 0, arr_lv, ctor);
+							  
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(local));
+  }
+  { /* int[50] foo() { int arr[50];
+                       arr = (int [50]){1,2,3,4,5,6};
+                       return arr;}
+
+       N.B: Not a typo, returning an array. 
+     */
+    gcc_jit_function *fn =
+      gcc_jit_context_new_function (ctxt,
+				    0,
+				    GCC_JIT_FUNCTION_EXPORTED,
+				    int50arr_type,
+				    "fn_int50arr_123s",
+				    0,
+				    0,
+				    0);
+    gcc_jit_lvalue *local =
+      gcc_jit_function_new_local (fn,
+				  0,
+				  int50arr_type,
+				  "local");
+    gcc_jit_block *block = gcc_jit_function_new_block (fn, "start");
+
+    gcc_jit_rvalue *values[6];
+
+    for (int i = 0; i < 6; i++)
+      values[i] = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, i + 1);
+    
+    gcc_jit_rvalue *ctor = gcc_jit_context_new_constructor
+	(ctxt, 0,
+	 int50arr_type,
+	 6,
+	 0,
+	 values);
+
+    gcc_jit_block_add_assignment (block, 0, local, ctor);
+							  
+    gcc_jit_block_end_with_return (block,
+				   0,
+				   gcc_jit_lvalue_as_rvalue(local));
+  }
+}
+
+struct fi2 {
+  float f;
+  int i;
+};
+
+struct bar2 {
+  float ff;
+  int arr[50];
+  int ii;
+};
+
+union ubar2 {
+  float ff;
+  int ii;
+};
+
+struct int50arr {
+  int arr[50];
+};
+
+void
+scramble_stack(void)
+  {
+    char *p = alloca(100);
+    for (int i = 0; i < 100; i++)
+      *p++ = 0xF0;
+    asm(""); /* Don't touch my code, optimizers. */
+  }
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_NON_NULL (result);
+
+  {
+    struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_1_2");
+    scramble_stack();
+    struct fi2 fi = fn();
+    CHECK_VALUE (fi.f, 1);
+    CHECK_VALUE (fi.i, 2);
+  }
+  {
+    struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_5_6");
+    struct fi2 fi = fn();
+    CHECK_VALUE (fi.f, 5);
+    CHECK_VALUE (fi.i, 6);
+  }
+  {
+    struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_1_3");
+    struct fi2 fi = fn();
+    CHECK_VALUE (fi.f, 1);
+    CHECK_VALUE (fi.i, 3);
+  }  
+  {
+    struct fi2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_fi_3_4");
+    struct fi2 fi = fn();
+    CHECK_VALUE (fi.f, 3);
+    CHECK_VALUE (fi.i, 4);
+  }
+  {
+    scramble_stack();
+    struct bar2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_bar_0s");
+    struct bar2 bar = fn();
+    struct bar2 key = {};
+
+    CHECK_VALUE (bar.ff, 0);
+    CHECK_VALUE (bar.ii, 0);
+    CHECK_VALUE (memcmp (&bar.arr, &key.arr, sizeof (key.arr)), 0);
+  }
+  {
+    scramble_stack();
+    struct bar2 (*fn) (void) = gcc_jit_result_get_code (result, "fn_bar_123s");
+    struct bar2 bar = fn();
+    struct bar2 key = {.arr = {1,2,3,4,5,6} };
+
+    CHECK_VALUE (memcmp (&bar.arr, &key.arr, sizeof (key.arr)), 0);
+  }
+  {
+    scramble_stack();
+    /* This is abit shady. Lets just pretend that array returns à la Fortran
+       is the same thing as returning a struct with an array in it in C. */
+    struct int50arr (*fn) (void) =
+      gcc_jit_result_get_code (result, "fn_int50arr_123s");
+    struct int50arr ans = fn();
+    int key[50] = {1,2,3,4,5,6};
+
+    CHECK_VALUE (memcmp (ans.arr, key, sizeof (key)), 0);
+  }
+}
-- 
2.30.2


      parent reply	other threads:[~2021-10-21 13:27 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-06  8:23 Petter Tomner
2021-10-06  8:40 ` Basile Starynkevitch
2021-10-21 13:27 ` Petter Tomner [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=67377ebd1d90482aa1123121d344cf92@kth.se \
    --to=tomner@kth.se \
    --cc=jit@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).