Test with indirect returns
diff --git a/gcc/calls.cc b/gcc/calls.cc
index bb8a6d0..da665ff 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -61,6 +61,7 @@
 #include "value-query.h"
 #include "tree-pretty-print.h"
 #include "tree-eh.h"
+#include "print-tree.h"
 
 /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits.  */
 #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
@@ -1338,6 +1339,8 @@
   CUMULATIVE_ARGS *args_so_far_pnt = get_cumulative_args (args_so_far);
   location_t loc = EXPR_LOCATION (exp);
 
+  //debug_tree (exp);
+
   /* Count arg position in order args appear.  */
   int argpos;
 
@@ -2897,6 +2900,13 @@
 	  structure_value_addr = XEXP (target, 0);
 	else
 	  {
+	    fprintf (stderr, "HERE: %d %p, %d, %d\n", CALL_EXPR_RETURN_SLOT_OPT (exp),
+                    target, MEM_P (target),
+	       (TREE_ADDRESSABLE (rettype)
+		|| !(MEM_ALIGN (target) < TYPE_ALIGN (rettype)
+		     && targetm.slow_unaligned_access (TYPE_MODE (rettype),
+						       MEM_ALIGN (target)))));
+            debug_rtx (target);
 	    /* For variable-sized objects, we must be called with a target
 	       specified.  If we were to allocate space on the stack here,
 	       we would have no way of knowing when to free it.  */
diff --git a/gcc/function.cc b/gcc/function.cc
index 5a054a9..b1417f6 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -85,6 +85,7 @@
 #include "value-range.h"
 #include "gimple-range.h"
 #include "insn-attr.h"
+#include "print-tree.h"
 
 /* So we can assign to cfun in this file.  */
 #undef cfun
@@ -987,6 +988,9 @@
 
   /* Allocating temporaries of TREE_ADDRESSABLE type must be done in the front
      end.  See also create_tmp_var for the gimplification-time check.  */
+  //fprintf (stderr, "1\n");
+  /*debug_tree (type_or_decl);
+  debug_tree (type);*/
   gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));
 
   if (mode == BLKmode || memory_required)
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index b12242c..da79e70 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -467,7 +467,19 @@
 
   if (is_packed)
     TYPE_PACKED (t) = 1;
-  if (is_addressable) TREE_ADDRESSABLE(t) = 1;
+
+  //gcc_assert (!is_addressable);
+  if (is_addressable)
+  {
+      TREE_ADDRESSABLE(t) = 1;
+      /*if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR)
+      {
+        fprintf (stderr, "Is compound literal\n");
+        TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (t)) = 1;
+      }
+      else
+          fprintf (stderr, "Is NOT compound literal\n");*/
+  }
   if (loc)
     set_tree_location (t, loc);
 
@@ -653,7 +665,8 @@
 	      const std::vector<std::pair<gcc_jit_fn_attribute,
 					  std::vector<int>>>
 					  &int_array_attributes,
-	      bool is_target_builtin)
+	      bool is_target_builtin,
+	      bool is_indirect_return)
 {
   int i;
   param *param;
@@ -661,16 +674,23 @@
   //can return_type be NULL?
   gcc_assert (name);
 
+  tree func_return_type = return_type->as_tree ();
+  if (is_indirect_return)
+  {
+    func_return_type = build_variant_type_copy (func_return_type);
+    TREE_ADDRESSABLE (func_return_type) = 1;
+  }
+
   tree *arg_types = (tree *)xcalloc(params->length (), sizeof(tree*));
   FOR_EACH_VEC_ELT (*params, i, param)
     arg_types[i] = TREE_TYPE (param->as_tree ());
 
   tree fn_type;
   if (is_variadic)
-    fn_type = build_varargs_function_type_array (return_type->as_tree (),
+    fn_type = build_varargs_function_type_array (func_return_type,
 						 params->length (), arg_types);
   else
-    fn_type = build_function_type_array (return_type->as_tree (),
+    fn_type = build_function_type_array (func_return_type,
 					 params->length (), arg_types);
   free (arg_types);
 
@@ -682,7 +702,7 @@
     set_tree_location (fndecl, loc);
 
   tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
-			     NULL_TREE, return_type->as_tree ());
+			     NULL_TREE, func_return_type);
   DECL_ARTIFICIAL (resdecl) = 1;
   DECL_IGNORED_P (resdecl) = 1;
   DECL_RESULT (fndecl) = resdecl;
@@ -1593,7 +1613,17 @@
   vec<tree, va_gc> *tree_args;
   vec_alloc (tree_args, args->length ());
   for (unsigned i = 0; i < args->length (); i++)
+  {
+    if (TREE_ADDRESSABLE (TREE_TYPE ((*args)[i]->as_tree ())))
+    {
+      fprintf (stderr, "Function:\n");
+      debug_tree (fn_ptr);
+      fprintf (stderr, "Argument:\n");
+      debug_tree ((*args)[i]->as_tree ());
+      abort ();
+    }
     tree_args->quick_push ((*args)[i]->as_tree ());
+  }
 
   if (loc)
     set_tree_location (fn_ptr, loc);
@@ -1604,6 +1634,11 @@
 
   tree call = build_call_vec (return_type,
 			      fn_ptr, tree_args);
+  if (TREE_ADDRESSABLE (return_type))
+  {
+    CALL_EXPR_RETURN_SLOT_OPT (call) = true;
+    //fprintf (stderr, "Setting return slot opt\n");
+  }
 
   if (require_tail_call)
     CALL_EXPR_MUST_TAIL_CALL (call) = 1;
@@ -2053,6 +2088,18 @@
 }
 
 /* Construct a playback::type instance (wrapping a tree)
+   with TREE_ADDRESSABLE set.  */
+
+playback::type *
+playback::type::
+get_addressable () const
+{
+  tree t_new_type = build_variant_type_copy (m_inner);
+  TREE_ADDRESSABLE (t_new_type) = 1;
+  return new type (t_new_type);
+}
+
+/* Construct a playback::type instance (wrapping a tree)
    for the given vector type.  */
 
 playback::type *
@@ -2120,6 +2167,8 @@
 {
   tree ptr = as_tree ();
   tree datum = get_context ()->new_dereference (ptr, loc);
+  /*fprintf (stderr, "ptr: %p\n", ptr);
+  fprintf (stderr, "deref: %p\n", datum);*/
   return new lvalue (get_context (), datum);
 }
 
@@ -2294,12 +2343,13 @@
 			   type->as_tree ());
   else
   {
-    inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+    inner = create_tmp_var (type->as_tree (), "JITTMP");
+    /*inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
 			create_tmp_var_name ("JITTMP"),
 			type->as_tree ());
     DECL_ARTIFICIAL (inner) = 1;
     DECL_IGNORED_P (inner) = 1;
-    DECL_NAMELESS (inner) = 1;
+    DECL_NAMELESS (inner) = 1;*/
   }
   DECL_CONTEXT (inner) = this->m_inner_fndecl;
 
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 9769db5..c094400 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -27,6 +27,7 @@
 
 #include "timevar.h"
 #include "varasm.h"
+#include "print-tree.h"
 
 #include "jit-recording.h"
 #include "jit-target.h"
@@ -132,7 +133,8 @@
 		const std::vector<std::pair<gcc_jit_fn_attribute,
 					    std::vector<int>>>
 					    &int_array_attributes,
-		bool is_target_builtin);
+		bool is_target_builtin,
+		bool is_indirect_return);
 
   lvalue *
   new_global (location *loc,
@@ -542,6 +544,7 @@
   }
 
   type *get_aligned (size_t alignment_in_bytes) const;
+  type *get_addressable () const;
   type *get_vector (size_t num_units) const;
 
 private:
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 3910e7a..983f67a 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -1409,6 +1409,16 @@
 			      int numargs , recording::rvalue **args)
 {
   recording::rvalue *result = new call (this, loc, func, numargs, args);
+  /*for (int i = 0 ; i < numargs ; i++)
+  {
+    type* type = args[i]->get_type ();
+    if (args[i]->is_addressable () || type->is_addressable ())
+    {
+      fprintf (stderr, "Function: %s\n", func->get_name ()->c_str ());
+      fprintf (stderr, "Argument: %s\n", args[i]->get_debug_string ());
+      abort ();
+    }
+  }*/
   record (result);
   return result;
 }
@@ -2596,6 +2606,15 @@
   return result;
 }
 
+recording::type *
+recording::type::get_addressable ()
+{
+  recording::type *result
+    = new memento_of_get_addressable (this);
+  m_ctxt->record_type (result);
+  return result;
+}
+
 void
 recording::type::set_packed ()
 {
@@ -3427,6 +3446,43 @@
 	   m_alignment_in_bytes);
 }
 
+/* The implementation of class gcc::jit::recording::memento_of_get_addressable.  */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+   for recording::memento_of_get_addressable.  */
+
+void
+recording::memento_of_get_addressable::replay_into (replayer *)
+{
+  set_playback_obj
+    (m_other_type->playback_type ()->get_addressable ());
+}
+
+/* Implementation of recording::memento::make_debug_string for
+   results of get_addressable.  */
+
+recording::string *
+recording::memento_of_get_addressable::make_debug_string ()
+{
+  return string::from_printf (m_ctxt,
+			      "%s adressable",
+			      m_other_type->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for addressable
+   types. */
+
+void
+recording::memento_of_get_addressable::write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "type");
+  r.write ("  gcc_jit_type *%s =\n"
+	   "    gcc_jit_type_get_addressable (%s);\n",
+	   id,
+	   r.get_identifier_as_type (m_other_type));
+}
+
+
 /* The implementation of class gcc::jit::recording::vector_type.  */
 
 /* Implementation of pure virtual hook recording::memento::replay_into
@@ -4164,6 +4220,10 @@
 recording::lvalue *
 recording::rvalue::dereference (recording::location *loc)
 {
+  if (this->get_type ()->dereference ()->is_addressable ())
+  {
+    abort();
+  }
   recording::lvalue *result =
     new dereference_rvalue (m_ctxt, loc, this);
   m_ctxt->record (result);
@@ -4515,7 +4575,8 @@
   m_attributes (),
   m_string_attributes (),
   m_int_array_attributes (),
-  m_is_target_builtin (is_target_builtin)
+  m_is_target_builtin (is_target_builtin),
+  m_indirect_return (false)
 {
   for (int i = 0; i< num_params; i++)
     {
@@ -4578,7 +4639,8 @@
 				     m_attributes,
 				     m_string_attributes,
 				     m_int_array_attributes,
-				     m_is_target_builtin));
+				     m_is_target_builtin,
+				     m_indirect_return));
 }
 
 /* Implementation of recording::memento::make_debug_string for
@@ -7628,7 +7690,7 @@
    for recording::memento_of_set_personality_function.  */
 
 void
-recording::memento_of_set_personality_function::replay_into (replayer *r)
+recording::memento_of_set_personality_function::replay_into (replayer * ARG_UNUSED (r))
 {
   m_function->playback_function ()->set_personality_function (m_personality_function->playback_function ());
 }
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index d0e6be9..5e39366 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -615,6 +615,7 @@
   type *get_restrict ();
   type *get_aligned (size_t alignment_in_bytes);
   type *get_vector (size_t num_units);
+  type *get_addressable ();
 
   void set_packed ();
   void set_addressable();
@@ -640,6 +641,8 @@
   virtual array_type *dyn_cast_array_type () { return NULL; }
   virtual memento_of_get_aligned *dyn_cast_aligned_type () { return NULL; }
 
+  virtual type* is_addressable () const { return NULL; }
+
   /* Is it typesafe to copy to this type from rtype?  */
   virtual bool accepts_writes_from (type *rtype)
   {
@@ -649,7 +652,7 @@
 
   virtual bool is_same_type_as (type *other)
   {
-    if ((is_int () && other->is_int () || is_float() && other->is_float())
+    if (((is_int () && other->is_int ()) || (is_float() && other->is_float()))
 		 && get_size () == other->get_size ()
 		 && is_signed () == other->is_signed ())
     {
@@ -998,6 +1001,50 @@
   size_t m_alignment_in_bytes;
 };
 
+/* Result of "gcc_jit_type_get_addressable".  */
+class memento_of_get_addressable : public decorated_type
+{
+public:
+  memento_of_get_addressable (type *other_type)
+  : decorated_type (other_type) {}
+
+  bool is_same_type_as (type *other) final override
+  {
+    if (!other->is_addressable ())
+    {
+      return m_other_type->is_same_type_as (other);
+    }
+    return m_other_type->is_same_type_as (other->is_addressable ());
+  }
+
+  type *is_addressable () const final override { return m_other_type; }
+
+  type* copy (context* ctxt) final override
+  {
+    type* result = new memento_of_get_addressable (m_other_type->copy (ctxt));
+    ctxt->record_type (result);
+    return result;
+  }
+
+  /* Strip off the addressable, giving the underlying type.  */
+  type *unqualified () final override { return m_other_type; }
+
+  void replay_into (replayer *) final override;
+
+  array_type *dyn_cast_array_type () final override
+  {
+    return m_other_type->dyn_cast_array_type ();
+  }
+
+  vector_type *dyn_cast_vector_type () final override {
+    return m_other_type->dyn_cast_vector_type ();
+  }
+
+private:
+  string * make_debug_string () final override;
+  void write_reproducer (reproducer &r) final override;
+};
+
 /* Result of "gcc_jit_type_get_vector".  */
 class vector_type : public decorated_type
 {
@@ -1621,6 +1668,8 @@
 
   void write_to_dump (dump &d) final override;
 
+  void set_indirect_return () { m_indirect_return = true; }
+
   void validate ();
 
   void dump_to_dot (const char *path);
@@ -1651,6 +1700,7 @@
   std::vector<std::pair<gcc_jit_fn_attribute, std::string>> m_string_attributes;
   std::vector<std::pair<gcc_jit_fn_attribute, std::vector<int>>> m_int_array_attributes;
   bool m_is_target_builtin;
+  bool m_indirect_return;
 };
 
 class block : public memento
@@ -2274,7 +2324,7 @@
 
   void replay_into (replayer *r) final override;
 
-  void set_name (const char *new_name) final override {
+  void set_name (const char * ARG_UNUSED (new_name)) final override {
     m_ctxt->add_error (NULL, "cannot change the name of type `array_access`");
   }
 
@@ -2339,7 +2389,7 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
-  void set_name (const char *new_name) final override {
+  void set_name (const char *ARG_UNUSED (new_name)) final override {
     m_ctxt->add_error (NULL, "cannot change the name of type `vector_access`");
   }
 
@@ -2372,7 +2422,7 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
-  void set_name (const char *new_name) final override {
+  void set_name (const char * ARG_UNUSED (new_name)) final override {
     m_ctxt->add_error (
       NULL, "cannot change the name of type `access_field_of_lvalue`");
   }
@@ -2435,7 +2485,7 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
-  void set_name (const char *new_name) final override {
+  void set_name (const char * ARG_UNUSED (new_name)) final override {
     m_ctxt->add_error (
       NULL, "cannot change the name of type `dereference_field_rvalue`");
   }
@@ -2466,7 +2516,7 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
-  void set_name (const char *new_name) final override {
+  void set_name (const char * ARG_UNUSED (new_name)) final override {
     m_ctxt->add_error (
       NULL, "cannot change the name of type `dereference_rvalue`");
   }
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 71ab902..f25ca25 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -805,7 +805,6 @@
   JIT_LOG_FUNC (ctxt->get_logger ());
   /* LOC can be NULL.  */
   RETURN_NULL_IF_FAIL (element_type, ctxt, loc, "NULL type");
-  RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size");
   RETURN_NULL_IF_FAIL (!element_type->is_void (), ctxt, loc,
 		       "void type for elements");
 
@@ -3058,7 +3057,7 @@
   RETURN_IF_FAIL (try_block, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL (catch_block, ctxt, loc, "NULL rvalue");
 
-  gcc::jit::recording::statement *stmt = block->add_try_catch (loc, try_block, catch_block);
+  /*gcc::jit::recording::statement *stmt =*/ block->add_try_catch (loc, try_block, catch_block);
 
   // TODO: remove this or use it.
   /* "stmt" should be good enough to be usable in error-messages,
@@ -3087,7 +3086,7 @@
   RETURN_IF_FAIL (try_block, ctxt, loc, "NULL rvalue");
   RETURN_IF_FAIL (finally_block, ctxt, loc, "NULL rvalue");
 
-  gcc::jit::recording::statement *stmt = block->add_try_catch (loc, try_block, finally_block, true);
+  /*gcc::jit::recording::statement *stmt =*/ block->add_try_catch (loc, try_block, finally_block, true);
 
   // TODO: remove this or use it.
   /* "stmt" should be good enough to be usable in error-messages,
@@ -3133,6 +3132,8 @@
     "cannot assign to readonly variable: %s",
     lvalue->get_debug_string ());
 
+  //RETURN_IF_FAIL (lvalue->get_type ()->get_addressable () == NULL, ctxt, loc, "addressable lvalue");
+
   gcc::jit::recording::statement *stmt = block->add_assignment (loc, lvalue, rvalue);
 
   /* "stmt" should be good enough to be usable in error-messages,
@@ -3903,6 +3904,13 @@
   fn->set_personality_function (personality_func);
 }
 
+void
+gcc_jit_function_set_indirect_return (gcc_jit_function *fn)
+{
+  RETURN_IF_FAIL (fn, NULL, NULL, "NULL function");
+  fn->set_indirect_return ();
+}
+
 extern char* jit_personality_func_name;
 
 void
@@ -4346,6 +4354,18 @@
   return (gcc_jit_type *)type->get_aligned (alignment_in_bytes);
 }
 
+gcc_jit_type *
+gcc_jit_type_get_addressable (gcc_jit_type *type)
+{
+  RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+  gcc::jit::recording::context *ctxt = type->m_ctxt;
+
+  JIT_LOG_FUNC (ctxt->get_logger ());
+
+  return (gcc_jit_type *)type->get_addressable ();
+}
+
 void
 gcc_jit_function_add_attribute (gcc_jit_function *func,
 				gcc_jit_fn_attribute attribute)
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 2a16834..b0456a1 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1909,6 +1909,9 @@
 gcc_jit_type_get_aligned (gcc_jit_type *type,
 			  size_t alignment_in_bytes);
 
+extern gcc_jit_type *
+gcc_jit_type_get_addressable (gcc_jit_type *type);
+
 #define LIBGCCJIT_HAVE_gcc_jit_type_get_vector
 
 /* Given type "T", get type:
@@ -1942,6 +1945,9 @@
 gcc_jit_function_set_personality_function (gcc_jit_function *fn,
                                            gcc_jit_function *personality_func);
 
+void
+gcc_jit_function_set_indirect_return (gcc_jit_function *fn);
+
 extern void
 gcc_jit_set_global_personality_function_name (char* name);
 
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 3099c95..77910a1 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -393,3 +393,13 @@
   global:
     gcc_jit_is_lto_supported;
 } LIBGCCJIT_ABI_45;
+
+LIBGCCJIT_ABI_47 {
+  global:
+    gcc_jit_type_get_addressable;
+} LIBGCCJIT_ABI_46;
+
+LIBGCCJIT_ABI_48 {
+  global:
+    gcc_jit_function_set_indirect_return;
+} LIBGCCJIT_ABI_47;