Skip to content

Commit 19bd5d7

Browse files
committed
libgccjit: Add support for creating temporary variables
gcc/jit/ChangeLog: * docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): New ABI tag. * docs/topics/functions.rst: Document gcc_jit_function_new_temp. * jit-playback.cc (new_local): Add new is_temp parameter. * jit-playback.h: Add new is_temp parameter. * jit-recording.cc (recording::function::new_temp): New method. (recording::local::replay_into): Support temporary variables. (recording::local::write_reproducer): Support temporary variables. * jit-recording.h (new_temp): New method. (m_is_temp): New field. * libgccjit.cc (gcc_jit_function_new_temp): New function. * libgccjit.h (gcc_jit_function_new_temp): New function. * libgccjit.map: New function. gcc/testsuite/ChangeLog: * jit.dg/all-non-failing-tests.h: Mention test-temp.c. * jit.dg/test-temp.c: New test.
1 parent 4ff31c7 commit 19bd5d7

11 files changed

+205
-19
lines changed

gcc/jit/docs/topics/compatibility.rst

+9
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,12 @@ on functions and variables:
397397
--------------------
398398
``LIBGCCJIT_ABI_27`` covers the addition of
399399
:func:`gcc_jit_context_new_sizeof`
400+
401+
.. _LIBGCCJIT_ABI_28:
402+
403+
``LIBGCCJIT_ABI_28``
404+
--------------------
405+
``LIBGCCJIT_ABI_28`` covers the addition of a functions to create a new
406+
temporary variable:
407+
408+
* :func:`gcc_jit_function_new_temp`

gcc/jit/docs/topics/functions.rst

+20
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,26 @@ Functions
171171
underlying string, so it is valid to pass in a pointer to an on-stack
172172
buffer.
173173

174+
.. function:: gcc_jit_lvalue *\
175+
gcc_jit_function_new_temp (gcc_jit_function *func,\
176+
gcc_jit_location *loc,\
177+
gcc_jit_type *type)
178+
179+
Create a new local variable within the function, of the given type.
180+
This function is similar to :func:`gcc_jit_function_new_local`, but
181+
it is to be used for compiler-generated variables (as opposed to
182+
user-defined variables in the language to be compiled) and these
183+
variables won't show up in the debug info.
184+
185+
The parameter ``type`` must be non-`void`.
186+
187+
This entrypoint was added in :ref:`LIBGCCJIT_ABI_26`; you can test
188+
for its presence using
189+
190+
.. code-block:: c
191+
192+
#ifdef LIBGCCJIT_HAVE_gcc_jit_function_new_temp
193+
174194
.. function:: size_t \
175195
gcc_jit_function_get_param_count (gcc_jit_function *func)
176196

gcc/jit/jit-playback.cc

+18-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
3131
#include "toplev.h"
3232
#include "tree-cfg.h"
3333
#include "convert.h"
34+
#include "gimple-expr.h"
3435
#include "stor-layout.h"
3536
#include "print-tree.h"
3637
#include "gimplify.h"
@@ -2164,13 +2165,27 @@ new_local (location *loc,
21642165
type *type,
21652166
const char *name,
21662167
const std::vector<std::pair<gcc_jit_variable_attribute,
2167-
std::string>> &attributes)
2168+
std::string>> &attributes,
2169+
bool is_temp)
21682170
{
21692171
gcc_assert (type);
2170-
gcc_assert (name);
2171-
tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2172+
tree inner;
2173+
if (is_temp)
2174+
{
2175+
inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2176+
create_tmp_var_name("JITTMP"),
2177+
type->as_tree ());
2178+
DECL_ARTIFICIAL (inner) = 1;
2179+
DECL_IGNORED_P (inner) = 1;
2180+
DECL_NAMELESS (inner) = 1;
2181+
}
2182+
else
2183+
{
2184+
gcc_assert (name);
2185+
inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
21722186
get_identifier (name),
21732187
type->as_tree ());
2188+
}
21742189
DECL_CONTEXT (inner) = this->m_inner_fndecl;
21752190

21762191
/* Prepend to BIND_EXPR_VARS: */

gcc/jit/jit-playback.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,8 @@ class function : public wrapper
567567
type *type,
568568
const char *name,
569569
const std::vector<std::pair<gcc_jit_variable_attribute,
570-
std::string>> &attributes);
570+
std::string>> &attributes,
571+
bool is_temp);
571572

572573
block*
573574
new_block (const char *name);

gcc/jit/jit-recording.cc

+40-12
Original file line numberDiff line numberDiff line change
@@ -4450,7 +4450,24 @@ recording::function::new_local (recording::location *loc,
44504450
type *type,
44514451
const char *name)
44524452
{
4453-
local *result = new local (this, loc, type, new_string (name));
4453+
local *result = new local (this, loc, type, new_string (name), false);
4454+
m_ctxt->record (result);
4455+
m_locals.safe_push (result);
4456+
return result;
4457+
}
4458+
4459+
/* Create a recording::local instance and add it to
4460+
the functions's context's list of mementos, and to the function's
4461+
list of locals.
4462+
4463+
Implements the post-error-checking part of
4464+
gcc_jit_function_new_temp. */
4465+
4466+
recording::lvalue *
4467+
recording::function::new_temp (recording::location *loc,
4468+
type *type)
4469+
{
4470+
local *result = new local (this, loc, type, NULL, true);
44544471
m_ctxt->record (result);
44554472
m_locals.safe_push (result);
44564473
return result;
@@ -7295,7 +7312,8 @@ recording::local::replay_into (replayer *r)
72957312
->new_local (playback_location (r, m_loc),
72967313
m_type->playback_type (),
72977314
playback_string (m_name),
7298-
m_string_attributes);
7315+
m_string_attributes,
7316+
m_is_temp);
72997317

73007318
if (m_reg_name != NULL)
73017319
obj->set_register_name (m_reg_name->c_str ());
@@ -7326,16 +7344,26 @@ void
73267344
recording::local::write_reproducer (reproducer &r)
73277345
{
73287346
const char *id = r.make_identifier (this, "local");
7329-
r.write (" gcc_jit_lvalue *%s =\n"
7330-
" gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
7331-
" %s, /* gcc_jit_location *loc */\n"
7332-
" %s, /* gcc_jit_type *type */\n"
7333-
" %s); /* const char *name */\n",
7334-
id,
7335-
r.get_identifier (m_func),
7336-
r.get_identifier (m_loc),
7337-
r.get_identifier_as_type (m_type),
7338-
m_name->get_debug_string ());
7347+
if (m_is_temp)
7348+
r.write (" gcc_jit_lvalue *%s =\n"
7349+
" gcc_jit_function_new_temp (%s, /* gcc_jit_function *func */\n"
7350+
" %s, /* gcc_jit_location *loc */\n"
7351+
" %s); /* gcc_jit_type *type */\n",
7352+
id,
7353+
r.get_identifier (m_func),
7354+
r.get_identifier (m_loc),
7355+
r.get_identifier_as_type (m_type));
7356+
else
7357+
r.write (" gcc_jit_lvalue *%s =\n"
7358+
" gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
7359+
" %s, /* gcc_jit_location *loc */\n"
7360+
" %s, /* gcc_jit_type *type */\n"
7361+
" %s); /* const char *name */\n",
7362+
id,
7363+
r.get_identifier (m_func),
7364+
r.get_identifier (m_loc),
7365+
r.get_identifier_as_type (m_type),
7366+
m_name->get_debug_string ());
73397367
}
73407368

73417369
/* The implementation of class gcc::jit::recording::statement. */

gcc/jit/jit-recording.h

+14-3
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,10 @@ class function : public memento
15041504
type *type,
15051505
const char *name);
15061506

1507+
lvalue *
1508+
new_temp (location *loc,
1509+
type *type);
1510+
15071511
block*
15081512
new_block (const char *name);
15091513

@@ -2407,10 +2411,11 @@ class function_pointer : public rvalue
24072411
class local : public lvalue
24082412
{
24092413
public:
2410-
local (function *func, location *loc, type *type_, string *name)
2414+
local (function *func, location *loc, type *type_, string *name, bool is_temp)
24112415
: lvalue (func->m_ctxt, loc, type_),
24122416
m_func (func),
2413-
m_name (name)
2417+
m_name (name),
2418+
m_is_temp (is_temp)
24142419
{
24152420
set_scope (func);
24162421
}
@@ -2424,7 +2429,12 @@ class local : public lvalue
24242429
void write_to_dump (dump &d) final override;
24252430

24262431
private:
2427-
string * make_debug_string () final override { return m_name; }
2432+
string * make_debug_string () final override {
2433+
if (m_is_temp)
2434+
return m_ctxt->new_string ("temp");
2435+
else
2436+
return m_name;
2437+
}
24282438
void write_reproducer (reproducer &r) final override;
24292439
enum precedence get_precedence () const final override
24302440
{
@@ -2434,6 +2444,7 @@ class local : public lvalue
24342444
private:
24352445
function *m_func;
24362446
string *m_name;
2447+
bool m_is_temp;
24372448
};
24382449

24392450
class statement : public memento

gcc/jit/libgccjit.cc

+31
Original file line numberDiff line numberDiff line change
@@ -2929,6 +2929,37 @@ gcc_jit_function_new_local (gcc_jit_function *func,
29292929
return (gcc_jit_lvalue *)func->new_local (loc, type, name);
29302930
}
29312931

2932+
/* Public entrypoint. See description in libgccjit.h.
2933+
2934+
After error-checking, the real work is done by the
2935+
gcc::jit::recording::function::new_temp method in jit-recording.cc. */
2936+
2937+
gcc_jit_lvalue *
2938+
gcc_jit_function_new_temp (gcc_jit_function *func,
2939+
gcc_jit_location *loc,
2940+
gcc_jit_type *type)
2941+
{
2942+
RETURN_NULL_IF_FAIL (func, NULL, loc, "NULL function");
2943+
gcc::jit::recording::context *ctxt = func->m_ctxt;
2944+
JIT_LOG_FUNC (ctxt->get_logger ());
2945+
/* LOC can be NULL. */
2946+
RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED,
2947+
ctxt, loc,
2948+
"Cannot add temps to an imported function");
2949+
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
2950+
RETURN_NULL_IF_FAIL_PRINTF1 (
2951+
type->has_known_size (),
2952+
ctxt, loc,
2953+
"unknown size for temp (type: %s)",
2954+
type->get_debug_string ());
2955+
RETURN_NULL_IF_FAIL (
2956+
!type->is_void (),
2957+
ctxt, loc,
2958+
"void type for temp");
2959+
2960+
return (gcc_jit_lvalue *)func->new_temp (loc, type);
2961+
}
2962+
29322963
/* Public entrypoint. See description in libgccjit.h.
29332964
29342965
After error-checking, the real work is done by the

gcc/jit/libgccjit.h

+7
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,13 @@ gcc_jit_function_new_local (gcc_jit_function *func,
14221422
gcc_jit_type *type,
14231423
const char *name);
14241424

1425+
extern gcc_jit_lvalue *
1426+
gcc_jit_function_new_temp (gcc_jit_function *func,
1427+
gcc_jit_location *loc,
1428+
gcc_jit_type *type);
1429+
1430+
#define LIBGCCJIT_HAVE_gcc_jit_function_new_temp
1431+
14251432
/**********************************************************************
14261433
Statement-creation.
14271434
**********************************************************************/

gcc/jit/libgccjit.map

+5
Original file line numberDiff line numberDiff line change
@@ -335,3 +335,8 @@ LIBGCCJIT_ABI_34 {
335335
global:
336336
gcc_jit_context_set_output_ident;
337337
} LIBGCCJIT_ABI_33;
338+
339+
LIBGCCJIT_ABI_35 {
340+
global:
341+
gcc_jit_function_new_temp;
342+
} LIBGCCJIT_ABI_34;

gcc/testsuite/jit.dg/all-non-failing-tests.h

+3
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,9 @@
363363
/* test-target-builtins.c: This can't be in the testcases array as it
364364
is target-specific. */
365365

366+
/* test-temp.c: This can't be in the testcases array as it
367+
is target-specific. */
368+
366369
/* test-string-literal.c */
367370
#define create_code create_code_string_literal
368371
#define verify_code verify_code_string_literal

gcc/testsuite/jit.dg/test-temp.c

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <stdint.h>
5+
6+
#include "libgccjit.h"
7+
8+
#define TEST_COMPILING_TO_FILE
9+
#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER
10+
#define OUTPUT_FILENAME "output-of-test-test-temp.c.s"
11+
#include "harness.h"
12+
13+
void
14+
create_code (gcc_jit_context *ctxt, void *user_data)
15+
{
16+
/* Let's try to inject the equivalent of:
17+
int
18+
func ()
19+
{
20+
int temp = 10;
21+
return temp;
22+
}
23+
*/
24+
gcc_jit_type *int_type =
25+
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
26+
27+
gcc_jit_function *func =
28+
gcc_jit_context_new_function (ctxt,
29+
NULL,
30+
GCC_JIT_FUNCTION_EXPORTED,
31+
int_type,
32+
"func",
33+
0, NULL, 0);
34+
35+
gcc_jit_block *initial =
36+
gcc_jit_function_new_block (func, "initial");
37+
38+
gcc_jit_lvalue *temp =
39+
gcc_jit_function_new_temp (func, NULL, int_type);
40+
41+
gcc_jit_rvalue *ten =
42+
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 10);
43+
gcc_jit_block_add_assignment (initial, NULL, temp, ten);
44+
45+
gcc_jit_block_end_with_return(initial, NULL,
46+
gcc_jit_lvalue_as_rvalue (temp));
47+
}
48+
49+
void
50+
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
51+
{
52+
CHECK_NON_NULL (result);
53+
}
54+
55+
/* { dg-final { jit-verify-output-file-was-created "" } } */
56+
/* { dg-final { jit-verify-assembler-output-not "JITTMP" } } */

0 commit comments

Comments
 (0)