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;