Skip to content

Commit d8cf891

Browse files
committed
libgccjit: Add support for creating temporary variables
gcc/jit/ChangeLog: * docs/topics/compatibility.rst (LIBGCCJIT_ABI_33): New ABI tag. * docs/topics/functions.rst: Document gcc_jit_function_new_temp. * jit-playback.cc (new_local): Add support for temporary variables. * jit-recording.cc (recording::function::new_temp): New method. (recording::local::write_reproducer): Support temporary variables. * jit-recording.h (new_temp): New method. * 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 56fc6a6 commit d8cf891

File tree

10 files changed

+191
-13
lines changed

10 files changed

+191
-13
lines changed

gcc/jit/docs/topics/compatibility.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,12 @@ on functions and variables:
436436
``LIBGCCJIT_ABI_32`` covers the addition of a function to get target builtins:
437437

438438
* :func:`gcc_jit_context_get_target_builtin_function`
439+
440+
.. _LIBGCCJIT_ABI_33:
441+
442+
``LIBGCCJIT_ABI_33``
443+
--------------------
444+
``LIBGCCJIT_ABI_33`` covers the addition of a function to create a new
445+
temporary variable:
446+
447+
* :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
@@ -190,6 +190,26 @@ Functions
190190
underlying string, so it is valid to pass in a pointer to an on-stack
191191
buffer.
192192

193+
.. function:: gcc_jit_lvalue *\
194+
gcc_jit_function_new_temp (gcc_jit_function *func,\
195+
gcc_jit_location *loc,\
196+
gcc_jit_type *type)
197+
198+
Create a new local variable within the function, of the given type.
199+
This function is similar to :func:`gcc_jit_function_new_local`, but
200+
it is to be used for compiler-generated variables (as opposed to
201+
user-defined variables in the language to be compiled) and these
202+
variables won't show up in the debug info.
203+
204+
The parameter ``type`` must be non-`void`.
205+
206+
This entrypoint was added in :ref:`LIBGCCJIT_ABI_33`; you can test
207+
for its presence using
208+
209+
.. code-block:: c
210+
211+
#ifdef LIBGCCJIT_HAVE_gcc_jit_function_new_temp
212+
193213
.. function:: size_t \
194214
gcc_jit_function_get_param_count (gcc_jit_function *func)
195215

gcc/jit/jit-playback.cc

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
3232
#include "toplev.h"
3333
#include "tree-cfg.h"
3434
#include "convert.h"
35+
#include "gimple-expr.h"
3536
#include "stor-layout.h"
3637
#include "print-tree.h"
3738
#include "gimplify.h"
@@ -2167,10 +2168,20 @@ new_local (location *loc,
21672168
std::string>> &attributes)
21682169
{
21692170
gcc_assert (type);
2170-
gcc_assert (name);
2171-
tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2171+
tree inner;
2172+
if (name)
2173+
inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
21722174
get_identifier (name),
21732175
type->as_tree ());
2176+
else
2177+
{
2178+
inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
2179+
create_tmp_var_name ("JITTMP"),
2180+
type->as_tree ());
2181+
DECL_ARTIFICIAL (inner) = 1;
2182+
DECL_IGNORED_P (inner) = 1;
2183+
DECL_NAMELESS (inner) = 1;
2184+
}
21742185
DECL_CONTEXT (inner) = this->m_inner_fndecl;
21752186

21762187
/* Prepend to BIND_EXPR_VARS: */

gcc/jit/jit-recording.cc

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4356,6 +4356,23 @@ recording::function::new_local (recording::location *loc,
43564356
return result;
43574357
}
43584358

4359+
/* Create a recording::local instance and add it to
4360+
the functions's context's list of mementos, and to the function's
4361+
list of locals.
4362+
4363+
Implements the post-error-checking part of
4364+
gcc_jit_function_new_temp. */
4365+
4366+
recording::lvalue *
4367+
recording::function::new_temp (recording::location *loc,
4368+
type *type)
4369+
{
4370+
local *result = new local (this, loc, type, NULL);
4371+
m_ctxt->record (result);
4372+
m_locals.safe_push (result);
4373+
return result;
4374+
}
4375+
43594376
/* Create a recording::block instance and add it to
43604377
the functions's context's list of mementos, and to the function's
43614378
list of blocks.
@@ -7226,16 +7243,26 @@ void
72267243
recording::local::write_reproducer (reproducer &r)
72277244
{
72287245
const char *id = r.make_identifier (this, "local");
7229-
r.write (" gcc_jit_lvalue *%s =\n"
7230-
" gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
7231-
" %s, /* gcc_jit_location *loc */\n"
7232-
" %s, /* gcc_jit_type *type */\n"
7233-
" %s); /* const char *name */\n",
7234-
id,
7235-
r.get_identifier (m_func),
7236-
r.get_identifier (m_loc),
7237-
r.get_identifier_as_type (m_type),
7238-
m_name->get_debug_string ());
7246+
if (m_name)
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 ());
7257+
else
7258+
r.write (" gcc_jit_lvalue *%s =\n"
7259+
" gcc_jit_function_new_temp (%s, /* gcc_jit_function *func */\n"
7260+
" %s, /* gcc_jit_location *loc */\n"
7261+
" %s); /* gcc_jit_type *type */\n",
7262+
id,
7263+
r.get_identifier (m_func),
7264+
r.get_identifier (m_loc),
7265+
r.get_identifier_as_type (m_type));
72397266
}
72407267

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

gcc/jit/jit-recording.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,10 @@ class function : public memento
15231523
type *type,
15241524
const char *name);
15251525

1526+
lvalue *
1527+
new_temp (location *loc,
1528+
type *type);
1529+
15261530
block*
15271531
new_block (const char *name);
15281532

@@ -2417,7 +2421,12 @@ class local : public lvalue
24172421
void write_to_dump (dump &d) final override;
24182422

24192423
private:
2420-
string * make_debug_string () final override { return m_name; }
2424+
string * make_debug_string () final override {
2425+
if (m_name)
2426+
return m_name;
2427+
else
2428+
return m_ctxt->new_string ("temp");
2429+
}
24212430
void write_reproducer (reproducer &r) final override;
24222431
enum precedence get_precedence () const final override
24232432
{

gcc/jit/libgccjit.cc

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

2950+
/* Public entrypoint. See description in libgccjit.h.
2951+
2952+
After error-checking, the real work is done by the
2953+
gcc::jit::recording::function::new_temp method in jit-recording.cc. */
2954+
2955+
gcc_jit_lvalue *
2956+
gcc_jit_function_new_temp (gcc_jit_function *func,
2957+
gcc_jit_location *loc,
2958+
gcc_jit_type *type)
2959+
{
2960+
RETURN_NULL_IF_FAIL (func, NULL, loc, "NULL function");
2961+
gcc::jit::recording::context *ctxt = func->m_ctxt;
2962+
JIT_LOG_FUNC (ctxt->get_logger ());
2963+
/* LOC can be NULL. */
2964+
RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED,
2965+
ctxt, loc,
2966+
"Cannot add temps to an imported function");
2967+
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
2968+
RETURN_NULL_IF_FAIL_PRINTF1 (
2969+
type->has_known_size (),
2970+
ctxt, loc,
2971+
"unknown size for temp (type: %s)",
2972+
type->get_debug_string ());
2973+
RETURN_NULL_IF_FAIL (
2974+
!type->is_void (),
2975+
ctxt, loc,
2976+
"void type for temp");
2977+
2978+
return (gcc_jit_lvalue *)func->new_temp (loc, type);
2979+
}
2980+
29502981
/* Public entrypoint. See description in libgccjit.h.
29512982
29522983
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
@@ -1476,6 +1476,13 @@ gcc_jit_function_new_local (gcc_jit_function *func,
14761476
gcc_jit_type *type,
14771477
const char *name);
14781478

1479+
extern gcc_jit_lvalue *
1480+
gcc_jit_function_new_temp (gcc_jit_function *func,
1481+
gcc_jit_location *loc,
1482+
gcc_jit_type *type);
1483+
1484+
#define LIBGCCJIT_HAVE_gcc_jit_function_new_temp
1485+
14791486
/**********************************************************************
14801487
Statement-creation.
14811488
**********************************************************************/

gcc/jit/libgccjit.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,8 @@ LIBGCCJIT_ABI_32 {
315315
global:
316316
gcc_jit_context_get_target_builtin_function;
317317
} LIBGCCJIT_ABI_31;
318+
319+
LIBGCCJIT_ABI_33 {
320+
global:
321+
gcc_jit_function_new_temp;
322+
} LIBGCCJIT_ABI_32;

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

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

393+
/* test-temp.c: This can't be in the testcases array as it
394+
is target-specific. */
395+
393396
/* test-string-literal.c */
394397
#define create_code create_code_string_literal
395398
#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)