Skip to content

Commit 58d3828

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 72331ec commit 58d3828

File tree

11 files changed

+205
-19
lines changed

11 files changed

+205
-19
lines changed

gcc/jit/docs/topics/compatibility.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,12 @@ alignment of a variable:
371371

372372
* :func:`gcc_jit_lvalue_set_alignment`
373373
* :func:`gcc_jit_lvalue_get_alignment`
374+
375+
.. _LIBGCCJIT_ABI_26:
376+
377+
``LIBGCCJIT_ABI_26``
378+
--------------------
379+
``LIBGCCJIT_ABI_26`` covers the addition of a functions to create a new
380+
temporary variable:
381+
382+
* :func:`gcc_jit_function_new_temp`

gcc/jit/docs/topics/functions.rst

Lines changed: 20 additions & 0 deletions
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

Lines changed: 18 additions & 3 deletions
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"
@@ -2153,13 +2154,27 @@ playback::function::
21532154
new_local (location *loc,
21542155
type *type,
21552156
const char *name,
2156-
const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes)
2157+
const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes,
2158+
bool is_temp)
21572159
{
21582160
gcc_assert (type);
2159-
gcc_assert (name);
2160-
tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2161+
tree inner;
2162+
if (is_temp)
2163+
{
2164+
inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2165+
create_tmp_var_name("JITTMP"),
2166+
type->as_tree ());
2167+
DECL_ARTIFICIAL (inner) = 1;
2168+
DECL_IGNORED_P (inner) = 1;
2169+
DECL_NAMELESS (inner) = 1;
2170+
}
2171+
else
2172+
{
2173+
gcc_assert (name);
2174+
inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
21612175
get_identifier (name),
21622176
type->as_tree ());
2177+
}
21632178
DECL_CONTEXT (inner) = this->m_inner_fndecl;
21642179

21652180
/* Prepend to BIND_EXPR_VARS: */

gcc/jit/jit-playback.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,8 @@ class function : public wrapper
554554
new_local (location *loc,
555555
type *type,
556556
const char *name,
557-
const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes);
557+
const std::vector<std::pair<gcc_jit_variable_attribute, std::string>> &attributes,
558+
bool is_temp);
558559

559560
block*
560561
new_block (const char *name);

gcc/jit/jit-recording.cc

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4447,7 +4447,24 @@ recording::function::new_local (recording::location *loc,
44474447
type *type,
44484448
const char *name)
44494449
{
4450-
local *result = new local (this, loc, type, new_string (name));
4450+
local *result = new local (this, loc, type, new_string (name), false);
4451+
m_ctxt->record (result);
4452+
m_locals.safe_push (result);
4453+
return result;
4454+
}
4455+
4456+
/* Create a recording::local instance and add it to
4457+
the functions's context's list of mementos, and to the function's
4458+
list of locals.
4459+
4460+
Implements the post-error-checking part of
4461+
gcc_jit_function_new_temp. */
4462+
4463+
recording::lvalue *
4464+
recording::function::new_temp (recording::location *loc,
4465+
type *type)
4466+
{
4467+
local *result = new local (this, loc, type, NULL, true);
44514468
m_ctxt->record (result);
44524469
m_locals.safe_push (result);
44534470
return result;
@@ -7213,7 +7230,8 @@ recording::local::replay_into (replayer *r)
72137230
->new_local (playback_location (r, m_loc),
72147231
m_type->playback_type (),
72157232
playback_string (m_name),
7216-
m_attributes);
7233+
m_attributes,
7234+
m_is_temp);
72177235

72187236
if (m_reg_name != NULL)
72197237
obj->set_register_name (m_reg_name->c_str ());
@@ -7244,16 +7262,26 @@ void
72447262
recording::local::write_reproducer (reproducer &r)
72457263
{
72467264
const char *id = r.make_identifier (this, "local");
7247-
r.write (" gcc_jit_lvalue *%s =\n"
7248-
" gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
7249-
" %s, /* gcc_jit_location *loc */\n"
7250-
" %s, /* gcc_jit_type *type */\n"
7251-
" %s); /* const char *name */\n",
7252-
id,
7253-
r.get_identifier (m_func),
7254-
r.get_identifier (m_loc),
7255-
r.get_identifier_as_type (m_type),
7256-
m_name->get_debug_string ());
7265+
if (m_is_temp)
7266+
r.write (" gcc_jit_lvalue *%s =\n"
7267+
" gcc_jit_function_new_temp (%s, /* gcc_jit_function *func */\n"
7268+
" %s, /* gcc_jit_location *loc */\n"
7269+
" %s); /* gcc_jit_type *type */\n",
7270+
id,
7271+
r.get_identifier (m_func),
7272+
r.get_identifier (m_loc),
7273+
r.get_identifier_as_type (m_type));
7274+
else
7275+
r.write (" gcc_jit_lvalue *%s =\n"
7276+
" gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
7277+
" %s, /* gcc_jit_location *loc */\n"
7278+
" %s, /* gcc_jit_type *type */\n"
7279+
" %s); /* const char *name */\n",
7280+
id,
7281+
r.get_identifier (m_func),
7282+
r.get_identifier (m_loc),
7283+
r.get_identifier_as_type (m_type),
7284+
m_name->get_debug_string ());
72577285
}
72587286

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

gcc/jit/jit-recording.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,10 @@ class function : public memento
15151515
type *type,
15161516
const char *name);
15171517

1518+
lvalue *
1519+
new_temp (location *loc,
1520+
type *type);
1521+
15181522
block*
15191523
new_block (const char *name);
15201524

@@ -2418,10 +2422,11 @@ class function_pointer : public rvalue
24182422
class local : public lvalue
24192423
{
24202424
public:
2421-
local (function *func, location *loc, type *type_, string *name)
2425+
local (function *func, location *loc, type *type_, string *name, bool is_temp)
24222426
: lvalue (func->m_ctxt, loc, type_),
24232427
m_func (func),
2424-
m_name (name)
2428+
m_name (name),
2429+
m_is_temp (is_temp)
24252430
{
24262431
set_scope (func);
24272432
}
@@ -2433,7 +2438,12 @@ class local : public lvalue
24332438
void write_to_dump (dump &d) final override;
24342439

24352440
private:
2436-
string * make_debug_string () final override { return m_name; }
2441+
string * make_debug_string () final override {
2442+
if (m_is_temp)
2443+
return m_ctxt->new_string ("temp");
2444+
else
2445+
return m_name;
2446+
}
24372447
void write_reproducer (reproducer &r) final override;
24382448
enum precedence get_precedence () const final override
24392449
{
@@ -2443,6 +2453,7 @@ class local : public lvalue
24432453
private:
24442454
function *m_func;
24452455
string *m_name;
2456+
bool m_is_temp;
24462457
};
24472458

24482459
class statement : public memento

gcc/jit/libgccjit.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2928,6 +2928,37 @@ gcc_jit_function_new_local (gcc_jit_function *func,
29282928
return (gcc_jit_lvalue *)func->new_local (loc, type, name);
29292929
}
29302930

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

gcc/jit/libgccjit.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,13 @@ gcc_jit_function_new_local (gcc_jit_function *func,
14091409
gcc_jit_type *type,
14101410
const char *name);
14111411

1412+
extern gcc_jit_lvalue *
1413+
gcc_jit_function_new_temp (gcc_jit_function *func,
1414+
gcc_jit_location *loc,
1415+
gcc_jit_type *type);
1416+
1417+
#define LIBGCCJIT_HAVE_gcc_jit_function_new_temp
1418+
14121419
/**********************************************************************
14131420
Statement-creation.
14141421
**********************************************************************/

gcc/jit/libgccjit.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,8 @@ LIBGCCJIT_ABI_36 {
342342
global:
343343
gcc_jit_context_set_output_ident;
344344
} LIBGCCJIT_ABI_35;
345+
346+
LIBGCCJIT_ABI_37 {
347+
global:
348+
gcc_jit_function_new_temp;
349+
} LIBGCCJIT_ABI_36;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@
322322
/* test-target-builtins.c: This can't be in the testcases array as it
323323
is target-specific. */
324324

325+
/* test-temp.c: This can't be in the testcases array as it
326+
is target-specific. */
327+
325328
/* test-string-literal.c */
326329
#define create_code create_code_string_literal
327330
#define verify_code verify_code_string_literal

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

Lines changed: 56 additions & 0 deletions
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)