diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 27845ea9a84e3..ba9360124b75e 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -371,3 +371,12 @@ alignment of a variable: * :func:`gcc_jit_lvalue_set_alignment` * :func:`gcc_jit_lvalue_get_alignment` + +.. _LIBGCCJIT_ABI_26: + +``LIBGCCJIT_ABI_26`` +-------------------- +``LIBGCCJIT_ABI_26`` covers the addition of a functions to create a new +temporary variable: + + * :func:`gcc_jit_function_new_temp` diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst index d6d4fe90834d0..dc5c64729312e 100644 --- a/gcc/jit/docs/topics/functions.rst +++ b/gcc/jit/docs/topics/functions.rst @@ -171,6 +171,26 @@ Functions underlying string, so it is valid to pass in a pointer to an on-stack buffer. +.. function:: gcc_jit_lvalue *\ + gcc_jit_function_new_temp (gcc_jit_function *func,\ + gcc_jit_location *loc,\ + gcc_jit_type *type) + + Create a new local variable within the function, of the given type. + This function is similar to :func:`gcc_jit_function_new_local`, but + it is to be used for compiler-generated variables (as opposed to + user-defined variables in the language to be compiled) and these + variables won't show up in the debug info. + + The parameter ``type`` must be non-`void`. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_26`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_function_new_temp + .. function:: size_t \ gcc_jit_function_get_param_count (gcc_jit_function *func) diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index ea6ac82774080..a73cef8eda736 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "tree-cfg.h" #include "convert.h" +#include "gimple-expr.h" #include "stor-layout.h" #include "print-tree.h" #include "gimplify.h" @@ -2153,13 +2154,27 @@ playback::function:: new_local (location *loc, type *type, const char *name, - const std::vector> &attributes) + const std::vector> &attributes, + bool is_temp) { gcc_assert (type); - gcc_assert (name); - tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL, + tree inner; + if (is_temp) + { + 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; + } + else + { + gcc_assert (name); + inner = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (name), type->as_tree ()); + } DECL_CONTEXT (inner) = this->m_inner_fndecl; /* Prepend to BIND_EXPR_VARS: */ diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 81c61d3e3b591..1d3b49d365094 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -554,7 +554,8 @@ class function : public wrapper new_local (location *loc, type *type, const char *name, - const std::vector> &attributes); + const std::vector> &attributes, + bool is_temp); block* new_block (const char *name); diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 2416a325539b4..0858f1219486a 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -4447,7 +4447,24 @@ recording::function::new_local (recording::location *loc, type *type, const char *name) { - local *result = new local (this, loc, type, new_string (name)); + local *result = new local (this, loc, type, new_string (name), false); + m_ctxt->record (result); + m_locals.safe_push (result); + return result; +} + +/* Create a recording::local instance and add it to + the functions's context's list of mementos, and to the function's + list of locals. + + Implements the post-error-checking part of + gcc_jit_function_new_temp. */ + +recording::lvalue * +recording::function::new_temp (recording::location *loc, + type *type) +{ + local *result = new local (this, loc, type, NULL, true); m_ctxt->record (result); m_locals.safe_push (result); return result; @@ -7213,7 +7230,8 @@ recording::local::replay_into (replayer *r) ->new_local (playback_location (r, m_loc), m_type->playback_type (), playback_string (m_name), - m_attributes); + m_attributes, + m_is_temp); if (m_reg_name != NULL) obj->set_register_name (m_reg_name->c_str ()); @@ -7244,16 +7262,26 @@ void recording::local::write_reproducer (reproducer &r) { const char *id = r.make_identifier (this, "local"); - r.write (" gcc_jit_lvalue *%s =\n" - " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n" - " %s, /* gcc_jit_location *loc */\n" - " %s, /* gcc_jit_type *type */\n" - " %s); /* const char *name */\n", - id, - r.get_identifier (m_func), - r.get_identifier (m_loc), - r.get_identifier_as_type (m_type), - m_name->get_debug_string ()); + if (m_is_temp) + r.write (" gcc_jit_lvalue *%s =\n" + " gcc_jit_function_new_temp (%s, /* gcc_jit_function *func */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s); /* gcc_jit_type *type */\n", + id, + r.get_identifier (m_func), + r.get_identifier (m_loc), + r.get_identifier_as_type (m_type)); + else + r.write (" gcc_jit_lvalue *%s =\n" + " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_type *type */\n" + " %s); /* const char *name */\n", + id, + r.get_identifier (m_func), + r.get_identifier (m_loc), + r.get_identifier_as_type (m_type), + m_name->get_debug_string ()); } /* The implementation of class gcc::jit::recording::statement. */ diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 656ba8cce864e..6284fa4a38928 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -1515,6 +1515,10 @@ class function : public memento type *type, const char *name); + lvalue * + new_temp (location *loc, + type *type); + block* new_block (const char *name); @@ -2418,10 +2422,11 @@ class function_pointer : public rvalue class local : public lvalue { public: - local (function *func, location *loc, type *type_, string *name) + local (function *func, location *loc, type *type_, string *name, bool is_temp) : lvalue (func->m_ctxt, loc, type_), m_func (func), - m_name (name) + m_name (name), + m_is_temp (is_temp) { set_scope (func); } @@ -2433,7 +2438,12 @@ class local : public lvalue void write_to_dump (dump &d) final override; private: - string * make_debug_string () final override { return m_name; } + string * make_debug_string () final override { + if (m_is_temp) + return m_ctxt->new_string ("temp"); + else + return m_name; + } void write_reproducer (reproducer &r) final override; enum precedence get_precedence () const final override { @@ -2443,6 +2453,7 @@ class local : public lvalue private: function *m_func; string *m_name; + bool m_is_temp; }; class statement : public memento diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 1ea3ce54ea771..8eafaf98babcf 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -2928,6 +2928,37 @@ gcc_jit_function_new_local (gcc_jit_function *func, return (gcc_jit_lvalue *)func->new_local (loc, type, name); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::function::new_temp method in jit-recording.cc. */ + +gcc_jit_lvalue * +gcc_jit_function_new_temp (gcc_jit_function *func, + gcc_jit_location *loc, + gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (func, NULL, loc, "NULL function"); + gcc::jit::recording::context *ctxt = func->m_ctxt; + JIT_LOG_FUNC (ctxt->get_logger ()); + /* LOC can be NULL. */ + RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED, + ctxt, loc, + "Cannot add temps to an imported function"); + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); + RETURN_NULL_IF_FAIL_PRINTF1 ( + type->has_known_size (), + ctxt, loc, + "unknown size for temp (type: %s)", + type->get_debug_string ()); + RETURN_NULL_IF_FAIL ( + !type->is_void (), + ctxt, loc, + "void type for temp"); + + return (gcc_jit_lvalue *)func->new_temp (loc, type); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index ea75a478cde82..8745f5e0a12b6 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1409,6 +1409,13 @@ gcc_jit_function_new_local (gcc_jit_function *func, gcc_jit_type *type, const char *name); +extern gcc_jit_lvalue * +gcc_jit_function_new_temp (gcc_jit_function *func, + gcc_jit_location *loc, + gcc_jit_type *type); + +#define LIBGCCJIT_HAVE_gcc_jit_function_new_temp + /********************************************************************** Statement-creation. **********************************************************************/ diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 77c5b2e827556..60cef3776a903 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -342,3 +342,8 @@ LIBGCCJIT_ABI_36 { global: gcc_jit_context_set_output_ident; } LIBGCCJIT_ABI_35; + +LIBGCCJIT_ABI_37 { + global: + gcc_jit_function_new_temp; +} LIBGCCJIT_ABI_36; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 988e14ae9bcd4..817ea9a0c0280 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -322,6 +322,9 @@ /* test-target-builtins.c: This can't be in the testcases array as it is target-specific. */ +/* test-temp.c: This can't be in the testcases array as it + is target-specific. */ + /* test-string-literal.c */ #define create_code create_code_string_literal #define verify_code verify_code_string_literal diff --git a/gcc/testsuite/jit.dg/test-temp.c b/gcc/testsuite/jit.dg/test-temp.c new file mode 100644 index 0000000000000..9b1ba9b010077 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-temp.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +#include "libgccjit.h" + +#define TEST_COMPILING_TO_FILE +#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER +#define OUTPUT_FILENAME "output-of-test-test-temp.c.s" +#include "harness.h" + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: +int +func () +{ + int temp = 10; + return temp; +} + */ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + gcc_jit_function *func = + gcc_jit_context_new_function (ctxt, + NULL, + GCC_JIT_FUNCTION_EXPORTED, + int_type, + "func", + 0, NULL, 0); + + gcc_jit_block *initial = + gcc_jit_function_new_block (func, "initial"); + + gcc_jit_lvalue *temp = + gcc_jit_function_new_temp (func, NULL, int_type); + + gcc_jit_rvalue *ten = + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 10); + gcc_jit_block_add_assignment (initial, NULL, temp, ten); + + gcc_jit_block_end_with_return(initial, NULL, + gcc_jit_lvalue_as_rvalue (temp)); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_NON_NULL (result); +} + +/* { dg-final { jit-verify-output-file-was-created "" } } */ +/* { dg-final { jit-verify-assembler-output-not "JITTMP" } } */