jit: API change to gcc_jit_context_new_global

gcc/jit/ChangeLog:
	* docs/cp/topics/expressions.rst (Global variables): Add
	enum gcc_jit_global_kind param to gccjit::context::new_global.
	* docs/topics/expressions.rst (Global variables): Likewise.
	Document the new enum.
	* docs/topics/results.rst (Compilation results): Document
	globals-handling.
	* dummy-frontend.c (jit_langhook_write_globals): Call into the
	playback context's write_global_decls_1 and write_global_decls_2
	before and after calling symtab->finalize_compilation_unit ().
	* jit-playback.c: Include "debug.h".
	(gcc::jit::playback::context::new_global): Add "kind" param and
	use it to set TREE_PUBLIC, TREE_STATIC and DECL_EXTERNAL on the
	underlying VAR_DECL.  Call varpool_node::get_create on the
	VAR_DECL, and add it to m_globals.
	(gcc::jit::playback::context::write_global_decls_1): New function.
	(gcc::jit::playback::context::write_global_decls_2): New function.
	* jit-playback.h (gcc::jit::playback::context::context): Call
	create on m_globals.
	(gcc::jit::playback::context::new_global): Add "kind" param.
	(gcc::jit::playback::context::write_global_decls_1): New function.
	(gcc::jit::playback::context::write_global_decls_2): New function.
	(gcc::jit::playback::context::m_globals): New field.
	* jit-recording.c (gcc::jit::recording::context::context):
	Initialize m_globals.
	(gcc::jit::recording::context::new_global): Add param "kind".
	Add the new global to m_globals.
	(gcc::jit::recording::context::dump_to_file): Dump the globals.
	(gcc::jit::recording::global::replay_into): Add field m_kind.
	(gcc::jit::recording::global::write_to_dump): New override.
	* jit-recording.h (gcc::jit::recording::context::new_global): Add
	param "kind".
	(gcc::jit::recording::context::m_globals): New field.
	(gcc::jit::recording::global::global): Add param kind.
	(gcc::jit::recording::global::write_to_dump): New override.
	(gcc::jit::recording::global::m_kind): New field.
	* jit-result.c (gcc::jit::result::get_global): New function.
	* jit-result.h (gcc::jit::result::get_global): New function.
	* libgccjit++.h (gccjit::context::new_global): Add "kind" param.
	* libgccjit.c (gcc_jit_context_new_global): Likewise.
	(gcc_jit_result_get_global): New API entrypoint.
	* libgccjit.h (gcc_jit_result_get_global): New API entrypoint.
	(enum gcc_jit_global_kind): New enum.
	(gcc_jit_context_new_global): API change: add "kind" param.
	* libgccjit.map (gcc_jit_result_get_global): New symbol.

gcc/testsuite/ChangeLog:
	* jit.dg/test-array-as-pointer.c (create_code): Update call
	to gcc_jit_context_new_global by setting "kind" to
	GCC_JIT_GLOBAL_IMPORTED.
	* jit.dg/test-error-array-as-pointer.c: Likewise.
	* jit.dg/test-expressions.c (make_test_of_get_address): Likewise.
	* jit.dg/test-fuzzer.c (make_random_global): Likewise, but
	setting kind to GCC_JIT_GLOBAL_EXPORTED.
	* jit.dg/test-using-global.c (the_global): Rename to...
	(imported_global): ...this.
	(create_code): Update to test the three kinds of global.
	(verify_code): Likewise.

From-SVN: r219480
This commit is contained in:
David Malcolm 2015-01-12 17:14:02 +00:00 committed by David Malcolm
parent 6c0fcb81da
commit 791cfef8e7
22 changed files with 828 additions and 309 deletions

View File

@ -1,3 +1,51 @@
2015-01-12 David Malcolm <dmalcolm@redhat.com>
* docs/cp/topics/expressions.rst (Global variables): Add
enum gcc_jit_global_kind param to gccjit::context::new_global.
* docs/topics/expressions.rst (Global variables): Likewise.
Document the new enum.
* docs/topics/results.rst (Compilation results): Document
globals-handling.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* dummy-frontend.c (jit_langhook_write_globals): Call into the
playback context's write_global_decls_1 and write_global_decls_2
before and after calling symtab->finalize_compilation_unit ().
* jit-playback.c: Include "debug.h".
(gcc::jit::playback::context::new_global): Add "kind" param and
use it to set TREE_PUBLIC, TREE_STATIC and DECL_EXTERNAL on the
underlying VAR_DECL. Call varpool_node::get_create on the
VAR_DECL, and add it to m_globals.
(gcc::jit::playback::context::write_global_decls_1): New function.
(gcc::jit::playback::context::write_global_decls_2): New function.
* jit-playback.h (gcc::jit::playback::context::context): Call
create on m_globals.
(gcc::jit::playback::context::new_global): Add "kind" param.
(gcc::jit::playback::context::write_global_decls_1): New function.
(gcc::jit::playback::context::write_global_decls_2): New function.
(gcc::jit::playback::context::m_globals): New field.
* jit-recording.c (gcc::jit::recording::context::context):
Initialize m_globals.
(gcc::jit::recording::context::new_global): Add param "kind".
Add the new global to m_globals.
(gcc::jit::recording::context::dump_to_file): Dump the globals.
(gcc::jit::recording::global::replay_into): Add field m_kind.
(gcc::jit::recording::global::write_to_dump): New override.
* jit-recording.h (gcc::jit::recording::context::new_global): Add
param "kind".
(gcc::jit::recording::context::m_globals): New field.
(gcc::jit::recording::global::global): Add param kind.
(gcc::jit::recording::global::write_to_dump): New override.
(gcc::jit::recording::global::m_kind): New field.
* jit-result.c (gcc::jit::result::get_global): New function.
* jit-result.h (gcc::jit::result::get_global): New function.
* libgccjit++.h (gccjit::context::new_global): Add "kind" param.
* libgccjit.c (gcc_jit_context_new_global): Likewise.
(gcc_jit_result_get_global): New API entrypoint.
* libgccjit.h (gcc_jit_result_get_global): New API entrypoint.
(enum gcc_jit_global_kind): New enum.
(gcc_jit_context_new_global): API change: add "kind" param.
* libgccjit.map (gcc_jit_result_get_global): New symbol.
2015-01-09 David Malcolm <dmalcolm@redhat.com>
* dummy-frontend.c: Include "fixed-value.h", "alias.h", "flags.h",

File diff suppressed because it is too large Load Diff

View File

@ -504,12 +504,15 @@ Global variables
****************
.. function:: gccjit::lvalue \
gccjit::context::new_global (gccjit::type type, \
gccjit::context::new_global (enum gcc_jit_global_kind,\
gccjit::type type, \
const char *name, \
gccjit::location loc)
Add a new global variable of the given type and name to the context.
This is a thin wrapper around :c:func:`gcc_jit_context_new_global` from
the C API; the "kind" parameter has the same meaning as there.
Working with pointers, structs and unions
-----------------------------------------

View File

@ -460,11 +460,36 @@ Global variables
.. function:: gcc_jit_lvalue *\
gcc_jit_context_new_global (gcc_jit_context *ctxt,\
gcc_jit_location *loc,\
enum gcc_jit_global_kind kind,\
gcc_jit_type *type,\
const char *name)
Add a new global variable of the given type and name to the context.
The "kind" parameter determines the visibility of the "global" outside
of the :c:type:`gcc_jit_result`:
.. type:: enum gcc_jit_global_kind
.. c:macro:: GCC_JIT_GLOBAL_EXPORTED
Global is defined by the client code and is visible
by name outside of this JIT context via
:c:func:`gcc_jit_result_get_global` (and this value is required for
the global to be accessible via that entrypoint).
.. c:macro:: GCC_JIT_GLOBAL_INTERNAL
Global is defined by the client code, but is invisible
outside of it. Analogous to a "static" global within a .c file.
Specifically, the variable will only be visible within this
context and within child contexts.
.. c:macro:: GCC_JIT_GLOBAL_IMPORTED
Global is not defined by the client code; we're merely
referring to it. Analogous to using an "extern" global from a
header file.
Working with pointers, structs and unions
-----------------------------------------

View File

@ -23,8 +23,8 @@ Compilation results
.. type:: gcc_jit_result
A `gcc_jit_result` encapsulates the result of compiling a context,
and the lifetimes of any machine code functions that are
returned.
and the lifetimes of any machine code functions or globals that are
within it.
.. function:: gcc_jit_result *\
gcc_jit_context_compile (gcc_jit_context *ctxt)
@ -32,6 +32,9 @@ Compilation results
This calls into GCC and builds the code, returning a
`gcc_jit_result *`.
If this is non-NULL, the caller becomes responsible for
calling :func:`gcc_jit_result_release` on it once they're done
with it.
.. function:: void *\
gcc_jit_result_get_code (gcc_jit_result *result,\
@ -66,14 +69,59 @@ Compilation results
Note that the resulting machine code becomes invalid after
:func:`gcc_jit_result_release` is called on the
`gcc_jit_result *`; attempting to call it after that may lead
:type:`gcc_jit_result *`; attempting to call it after that may lead
to a segmentation fault.
.. function:: void *\
gcc_jit_result_get_global (gcc_jit_result *result,\
const char *name)
Locate a given global within the built machine code.
Globals are looked up by name. For this to succeed, a global
with a name matching `name` must have been created on
`result`'s context (or a parent context) via a call to
:func:`gcc_jit_context_new_global` with `kind`
:macro:`GCC_JIT_GLOBAL_EXPORTED`.
If the global is found, the result will need to be cast to a
pointer of the correct type before it can be called.
This is a *pointer* to the global, so e.g. for an :c:type:`int` this is
an :c:type:`int *`.
For example, given an ``int foo;`` created this way:
.. code-block:: c
gcc_jit_lvalue *exported_global =
gcc_jit_context_new_global (ctxt,
any_location, /* or NULL */
GCC_JIT_GLOBAL_EXPORTED,
int_type,
"foo");
we can access it like this:
.. code-block:: c
int *ptr_to_foo =
(int *)gcc_jit_result_get_global (result, "foo");
If such a global is not found (or `result` or `name` are
``NULL``), an error message will be emitted on stderr and
``NULL`` will be returned.
Note that the resulting address becomes invalid after
:func:`gcc_jit_result_release` is called on the
:type:`gcc_jit_result *`; attempting to use it after that may lead
to a segmentation fault.
.. function:: void\
gcc_jit_result_release (gcc_jit_result *result)
Once we're done with the code, this unloads the built .so file.
This cleans up the result; after calling this, it's no longer
valid to use the result, or any code that was obtained by calling
:func:`gcc_jit_result_get_code` on it.
valid to use the result, or any code or globals that were obtained
by calling :func:`gcc_jit_result_get_code` or
:func:`gcc_jit_result_get_global` on it.

View File

@ -221,11 +221,16 @@ jit_langhook_getdecls (void)
static void
jit_langhook_write_globals (void)
{
gcc_assert (gcc::jit::active_playback_ctxt);
JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
gcc::jit::playback::context *ctxt = gcc::jit::active_playback_ctxt;
gcc_assert (ctxt);
JIT_LOG_SCOPE (ctxt->get_logger ());
ctxt->write_global_decls_1 ();
/* This is the hook that runs the middle and backends: */
symtab->finalize_compilation_unit ();
ctxt->write_global_decls_2 ();
}
#undef LANG_HOOKS_NAME

View File

@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "context.h"
#include "fold-const.h"
#include "debug.h"
#include "jit-common.h"
#include "jit-logging.h"
@ -109,6 +110,7 @@ playback::context::context (recording::context *ctxt)
{
JIT_LOG_SCOPE (get_logger ());
m_functions.create (0);
m_globals.create (0);
m_source_files.create (0);
m_cached_locations.create (0);
}
@ -482,6 +484,7 @@ new_function (location *loc,
playback::lvalue *
playback::context::
new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name)
{
@ -490,13 +493,33 @@ new_global (location *loc,
tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier (name),
type->as_tree ());
TREE_PUBLIC (inner) = 1;
TREE_PUBLIC (inner) = (kind != GCC_JIT_GLOBAL_INTERNAL);
DECL_COMMON (inner) = 1;
DECL_EXTERNAL (inner) = 1;
switch (kind)
{
default:
gcc_unreachable ();
case GCC_JIT_GLOBAL_EXPORTED:
TREE_STATIC (inner) = 1;
break;
case GCC_JIT_GLOBAL_INTERNAL:
TREE_STATIC (inner) = 1;
break;
case GCC_JIT_GLOBAL_IMPORTED:
DECL_EXTERNAL (inner) = 1;
break;
}
if (loc)
set_tree_location (inner, loc);
varpool_node::get_create (inner);
m_globals.safe_push (inner);
return new lvalue (this, inner);
}
@ -649,6 +672,45 @@ as_truth_value (tree expr, location *loc)
return expr;
}
/* For use by jit_langhook_write_globals.
Calls varpool_node::finalize_decl on each global. */
void
playback::context::
write_global_decls_1 ()
{
/* Compare with e.g. the C frontend's c_write_global_declarations. */
JIT_LOG_SCOPE (get_logger ());
int i;
tree decl;
FOR_EACH_VEC_ELT (m_globals, i, decl)
{
gcc_assert (TREE_CODE (decl) == VAR_DECL);
varpool_node::finalize_decl (decl);
}
}
/* For use by jit_langhook_write_globals.
Calls debug_hooks->global_decl on each global. */
void
playback::context::
write_global_decls_2 ()
{
/* Compare with e.g. the C frontend's c_write_global_declarations_2. */
JIT_LOG_SCOPE (get_logger ());
int i;
tree decl;
FOR_EACH_VEC_ELT (m_globals, i, decl)
{
gcc_assert (TREE_CODE (decl) == VAR_DECL);
debug_hooks->global_decl (decl);
}
}
/* Construct a playback::rvalue instance (wrapping a tree) for a
unary op. */

View File

@ -90,6 +90,7 @@ public:
lvalue *
new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name);
@ -206,6 +207,10 @@ public:
return m_recording_ctxt->errors_occurred ();
}
/* For use by jit_langhook_write_globals. */
void write_global_decls_1 ();
void write_global_decls_2 ();
private:
void dump_generated_code ();
@ -259,6 +264,7 @@ private:
tempdir *m_tempdir;
auto_vec<function *> m_functions;
auto_vec<tree> m_globals;
tree m_char_array_type_node;
tree m_const_char_ptr;

View File

@ -177,6 +177,7 @@ recording::context::context (context *parent_ctxt)
m_owns_last_error_str (false),
m_mementos (),
m_compound_types (),
m_globals (),
m_functions (),
m_FILE_type (NULL),
m_builtins_manager(NULL)
@ -636,12 +637,15 @@ recording::context::get_builtin_function (const char *name)
recording::lvalue *
recording::context::new_global (recording::location *loc,
enum gcc_jit_global_kind kind,
recording::type *type,
const char *name)
{
recording::lvalue *result =
new recording::global (this, loc, type, new_string (name));
recording::global *result =
new recording::global (this, loc, kind, type, new_string (name));
record (result);
m_globals.safe_push (result);
return result;
}
@ -1016,6 +1020,15 @@ recording::context::dump_to_file (const char *path, bool update_locations)
d.write ("\n");
}
/* Globals. */
global *g;
FOR_EACH_VEC_ELT (m_globals, i, g)
{
g->write_to_dump (d);
}
if (!m_globals.is_empty ())
d.write ("\n");
function *fn;
FOR_EACH_VEC_ELT (m_functions, i, fn)
{
@ -2648,10 +2661,57 @@ void
recording::global::replay_into (replayer *r)
{
set_playback_obj (r->new_global (playback_location (r, m_loc),
m_kind,
m_type->playback_type (),
playback_string (m_name)));
}
/* Override the default implementation of
recording::memento::write_to_dump for globals.
This will be of the form:
GCC_JIT_GLOBAL_EXPORTED:
"TYPE NAME;"
e.g. "int foo;"
GCC_JIT_GLOBAL_INTERNAL:
"static TYPE NAME;"
e.g. "static int foo;"
GCC_JIT_GLOBAL_IMPORTED:
"extern TYPE NAME;"
e.g. "extern int foo;"
These are written to the top of the dump by
recording::context::dump_to_file. */
void
recording::global::write_to_dump (dump &d)
{
if (d.update_locations ())
m_loc = d.make_location ();
switch (m_kind)
{
default:
gcc_unreachable ();
case GCC_JIT_GLOBAL_EXPORTED:
break;
case GCC_JIT_GLOBAL_INTERNAL:
d.write ("static ");
break;
case GCC_JIT_GLOBAL_IMPORTED:
d.write ("extern ");
break;
}
d.write ("%s %s;\n",
m_type->get_debug_string (),
get_debug_string ());
}
/* The implementation of the various const-handling classes:
gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */

View File

@ -132,6 +132,7 @@ public:
lvalue *
new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type,
const char *name);
@ -272,6 +273,7 @@ private:
/* Specific recordings, for use by dump_to_file. */
auto_vec<compound_type *> m_compound_types;
auto_vec<global *> m_globals;
auto_vec<function *> m_functions;
type *m_basic_types[NUM_GCC_JIT_TYPES];
@ -1051,18 +1053,23 @@ class global : public lvalue
public:
global (context *ctxt,
location *loc,
enum gcc_jit_global_kind kind,
type *type,
string *name)
: lvalue (ctxt, loc, type),
m_kind (kind),
m_name (name)
{}
void replay_into (replayer *);
void write_to_dump (dump &d);
private:
string * make_debug_string () { return m_name; }
private:
enum gcc_jit_global_kind m_kind;
string *m_name;
};

View File

@ -86,6 +86,33 @@ get_code (const char *funcname)
return code;
}
/* Attempt to locate the given global by name within the
playback::result, using dlsym.
Implements the post-error-checking part of
gcc_jit_result_get_global. */
void *
result::
get_global (const char *name)
{
JIT_LOG_SCOPE (get_logger ());
void *global;
const char *error;
/* Clear any existing error. */
dlerror ();
global = dlsym (m_dso_handle, name);
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
}
return global;
}
} // namespace gcc::jit
} // namespace gcc

View File

@ -36,6 +36,9 @@ public:
void *
get_code (const char *funcname);
void *
get_global (const char *name);
private:
void *m_dso_handle;
tempdir *m_tempdir;

View File

@ -155,7 +155,8 @@ namespace gccjit
function get_builtin_function (const std::string &name);
lvalue new_global (type type_,
lvalue new_global (enum gcc_jit_global_kind kind,
type type_,
const std::string &name,
location loc = location ());
@ -707,12 +708,14 @@ context::get_builtin_function (const std::string &name)
}
inline lvalue
context::new_global (type type_,
context::new_global (enum gcc_jit_global_kind kind,
type type_,
const std::string &name,
location loc)
{
return lvalue (gcc_jit_context_new_global (m_inner_ctxt,
loc.get_inner_location (),
kind,
type_.get_inner_type (),
name.c_str ()));
}

View File

@ -987,16 +987,23 @@ gcc_jit_block_get_function (gcc_jit_block *block)
gcc_jit_lvalue *
gcc_jit_context_new_global (gcc_jit_context *ctxt,
gcc_jit_location *loc,
enum gcc_jit_global_kind kind,
gcc_jit_type *type,
const char *name)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL_PRINTF1 (
((kind >= GCC_JIT_GLOBAL_EXPORTED)
&& (kind <= GCC_JIT_GLOBAL_IMPORTED)),
ctxt, loc,
"unrecognized value for enum gcc_jit_global_kind: %i",
kind);
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
return (gcc_jit_lvalue *)ctxt->new_global (loc, type, name);
return (gcc_jit_lvalue *)ctxt->new_global (loc, kind, type, name);
}
/* Public entrypoint. See description in libgccjit.h.
@ -2213,6 +2220,25 @@ gcc_jit_result_get_code (gcc_jit_result *result,
return code;
}
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
gcc::jit::result::get_global method in jit-result.c. */
void *
gcc_jit_result_get_global (gcc_jit_result *result,
const char *name)
{
RETURN_NULL_IF_FAIL (result, NULL, NULL, "NULL result");
JIT_LOG_FUNC (result->get_logger ());
RETURN_NULL_IF_FAIL (name, NULL, NULL, "NULL name");
void *global = result->get_global (name);
result->log ("%s: returning (void *)%p", __func__, global);
return global;
}
/* Public entrypoint. See description in libgccjit.h.
After error-checking, this is essentially a wrapper around the

View File

@ -299,6 +299,13 @@ extern void *
gcc_jit_result_get_code (gcc_jit_result *result,
const char *funcname);
/* Locate a given global within the built machine code.
It must have been created using GCC_JIT_GLOBAL_EXPORTED.
This is a ptr to the global, so e.g. for an int this is an int *. */
extern void *
gcc_jit_result_get_global (gcc_jit_result *result,
const char *name);
/* Once we're done with the code, this unloads the built .so file.
This cleans up the result; after calling this, it's no longer
valid to use the result. */
@ -606,10 +613,26 @@ gcc_jit_block_get_function (gcc_jit_block *block);
/**********************************************************************
lvalues, rvalues and expressions.
**********************************************************************/
enum gcc_jit_global_kind
{
/* Global is defined by the client code and visible
by name outside of this JIT context via gcc_jit_result_get_global. */
GCC_JIT_GLOBAL_EXPORTED,
/* Global is defined by the client code, but is invisible
outside of this JIT context. Analogous to a "static" global. */
GCC_JIT_GLOBAL_INTERNAL,
/* Global is not defined by the client code; we're merely
referring to it. Analogous to using an "extern" global from a
header file. */
GCC_JIT_GLOBAL_IMPORTED
};
extern gcc_jit_lvalue *
gcc_jit_context_new_global (gcc_jit_context *ctxt,
gcc_jit_location *loc,
enum gcc_jit_global_kind kind,
gcc_jit_type *type,
const char *name);

View File

@ -87,6 +87,7 @@
gcc_jit_param_as_object;
gcc_jit_param_as_rvalue;
gcc_jit_result_get_code;
gcc_jit_result_get_global;
gcc_jit_result_release;
gcc_jit_rvalue_access_field;
gcc_jit_rvalue_as_object;

View File

@ -1,3 +1,17 @@
2015-01-12 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-array-as-pointer.c (create_code): Update call
to gcc_jit_context_new_global by setting "kind" to
GCC_JIT_GLOBAL_IMPORTED.
* jit.dg/test-error-array-as-pointer.c: Likewise.
* jit.dg/test-expressions.c (make_test_of_get_address): Likewise.
* jit.dg/test-fuzzer.c (make_random_global): Likewise, but
setting kind to GCC_JIT_GLOBAL_EXPORTED.
* jit.dg/test-using-global.c (the_global): Rename to...
(imported_global): ...this.
(create_code): Update to test the three kinds of global.
(verify_code): Likewise.
2015-01-12 Marc Glisse <marc.glisse@inria.fr>
PR testsuite/64427

View File

@ -62,7 +62,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
0);
gcc_jit_lvalue *buffer =
gcc_jit_context_new_global (ctxt, NULL, buf_type, "test_buffer");
gcc_jit_context_new_global (ctxt, NULL, GCC_JIT_GLOBAL_IMPORTED,
buf_type, "test_buffer");
gcc_jit_block *block = gcc_jit_function_new_block(test_fn, "entry");

View File

@ -62,7 +62,10 @@ create_code (gcc_jit_context *ctxt, void *user_data)
0);
gcc_jit_lvalue *buffer =
gcc_jit_context_new_global (ctxt, NULL, buf_type, "test_buffer");
gcc_jit_context_new_global (ctxt, NULL,
GCC_JIT_GLOBAL_IMPORTED,
buf_type,
"test_buffer");
gcc_jit_block *block = gcc_jit_function_new_block(test_fn, "entry");

View File

@ -884,6 +884,7 @@ make_test_of_get_address (gcc_jit_context *ctxt)
gcc_jit_context_new_global (
ctxt,
NULL,
GCC_JIT_GLOBAL_IMPORTED,
int_type,
"test_global");

View File

@ -238,6 +238,7 @@ make_random_global (fuzzer *f)
sprintf (global_name, "g%i", f->num_globals);
return gcc_jit_context_new_global (f->ctxt,
get_random_location (f),
GCC_JIT_GLOBAL_EXPORTED,
get_random_type (f),
global_name);
}

View File

@ -9,7 +9,7 @@
extern "C" {
#endif
extern int the_global;
extern int imported_global;
#ifdef __cplusplus
}
@ -19,24 +19,47 @@ void
create_code (gcc_jit_context *ctxt, void *user_data)
{
/* Let's try to inject the equivalent of:
extern int the_global;
void
int exported_global;
extern int imported_global;
static int internal_global;
int
test_using_global (void)
{
the_global += 1;
exported_global += 1;
imported_global += 1;
internal_global += 1;
return internal_global;
}
*/
gcc_jit_type *void_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
gcc_jit_lvalue *exported_global =
gcc_jit_context_new_global (ctxt,
NULL,
GCC_JIT_GLOBAL_EXPORTED,
int_type,
"exported_global");
gcc_jit_lvalue *imported_global =
gcc_jit_context_new_global (ctxt,
NULL,
GCC_JIT_GLOBAL_IMPORTED,
int_type,
"imported_global");
gcc_jit_lvalue *internal_global =
gcc_jit_context_new_global (ctxt,
NULL,
GCC_JIT_GLOBAL_INTERNAL,
int_type,
"internal_global");
/* Build the test_fn. */
gcc_jit_function *test_fn =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
void_type,
int_type,
"test_using_global",
0, NULL,
0);
@ -44,30 +67,64 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_block_add_assignment_op (
block, NULL,
gcc_jit_context_new_global (ctxt, NULL, int_type, "the_global"),
exported_global,
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_context_one (ctxt, int_type));
gcc_jit_block_end_with_void_return (block, NULL);
gcc_jit_block_add_assignment_op (
block, NULL,
imported_global,
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_context_one (ctxt, int_type));
gcc_jit_block_add_assignment_op (
block, NULL,
internal_global,
GCC_JIT_BINARY_OP_PLUS,
gcc_jit_context_one (ctxt, int_type));
gcc_jit_block_end_with_return (block,
NULL,
gcc_jit_lvalue_as_rvalue (internal_global));
}
int the_global;
int imported_global;
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef void (*fn_type) (void);
typedef int (*fn_type) (void);
CHECK_NON_NULL (result);
fn_type test_using_global =
(fn_type)gcc_jit_result_get_code (result, "test_using_global");
CHECK_NON_NULL (test_using_global);
the_global = 42;
/* The exported global should be visible. */
int *exported_global = (int *)gcc_jit_result_get_global (result, "exported_global");
CHECK_NON_NULL (exported_global);
/* ...and should be zero-initialized. */
CHECK_VALUE (*exported_global, 0);
/* Set some nonzero values. */
*exported_global = 11;
imported_global = 42;
/* The internal global shouldn't be visible. */
int *internal_global = (int *)gcc_jit_result_get_global (result, "internal_global");
CHECK_VALUE (internal_global, NULL);
/* Call the JIT-generated function. */
test_using_global ();
int call_count = test_using_global ();
/* Verify that it correctly modified the_global. */
CHECK_VALUE (the_global, 43);
/* Verify that it correctly modified imported_global and exported_global. */
CHECK_VALUE (*exported_global, 12);
CHECK_VALUE (imported_global, 43);
CHECK_VALUE (call_count, 1);
/* Try calling it again. */
call_count = test_using_global ();
/* Verify the new values. */
CHECK_VALUE (*exported_global, 13);
CHECK_VALUE (imported_global, 44);
CHECK_VALUE (call_count, 2);
}