Commit 791cfef8 by David Malcolm Committed by David Malcolm

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
parent 6c0fcb81
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> 2015-01-09 David Malcolm <dmalcolm@redhat.com>
* dummy-frontend.c: Include "fixed-value.h", "alias.h", "flags.h", * dummy-frontend.c: Include "fixed-value.h", "alias.h", "flags.h",
......
...@@ -504,12 +504,15 @@ Global variables ...@@ -504,12 +504,15 @@ Global variables
**************** ****************
.. function:: gccjit::lvalue \ .. 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, \ const char *name, \
gccjit::location loc) gccjit::location loc)
Add a new global variable of the given type and name to the context. 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 Working with pointers, structs and unions
----------------------------------------- -----------------------------------------
......
...@@ -460,11 +460,36 @@ Global variables ...@@ -460,11 +460,36 @@ Global variables
.. function:: gcc_jit_lvalue *\ .. function:: gcc_jit_lvalue *\
gcc_jit_context_new_global (gcc_jit_context *ctxt,\ gcc_jit_context_new_global (gcc_jit_context *ctxt,\
gcc_jit_location *loc,\ gcc_jit_location *loc,\
enum gcc_jit_global_kind kind,\
gcc_jit_type *type,\ gcc_jit_type *type,\
const char *name) const char *name)
Add a new global variable of the given type and name to the context. 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 Working with pointers, structs and unions
----------------------------------------- -----------------------------------------
......
...@@ -23,8 +23,8 @@ Compilation results ...@@ -23,8 +23,8 @@ Compilation results
.. type:: gcc_jit_result .. type:: gcc_jit_result
A `gcc_jit_result` encapsulates the result of compiling a context, A `gcc_jit_result` encapsulates the result of compiling a context,
and the lifetimes of any machine code functions that are and the lifetimes of any machine code functions or globals that are
returned. within it.
.. function:: gcc_jit_result *\ .. function:: gcc_jit_result *\
gcc_jit_context_compile (gcc_jit_context *ctxt) gcc_jit_context_compile (gcc_jit_context *ctxt)
...@@ -32,6 +32,9 @@ Compilation results ...@@ -32,6 +32,9 @@ Compilation results
This calls into GCC and builds the code, returning a This calls into GCC and builds the code, returning a
`gcc_jit_result *`. `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 *\ .. function:: void *\
gcc_jit_result_get_code (gcc_jit_result *result,\ gcc_jit_result_get_code (gcc_jit_result *result,\
...@@ -66,14 +69,59 @@ Compilation results ...@@ -66,14 +69,59 @@ Compilation results
Note that the resulting machine code becomes invalid after Note that the resulting machine code becomes invalid after
:func:`gcc_jit_result_release` is called on the :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. 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\ .. function:: void\
gcc_jit_result_release (gcc_jit_result *result) gcc_jit_result_release (gcc_jit_result *result)
Once we're done with the code, this unloads the built .so file. 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 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 valid to use the result, or any code or globals that were obtained
:func:`gcc_jit_result_get_code` on it. by calling :func:`gcc_jit_result_get_code` or
:func:`gcc_jit_result_get_global` on it.
...@@ -221,11 +221,16 @@ jit_langhook_getdecls (void) ...@@ -221,11 +221,16 @@ jit_langhook_getdecls (void)
static void static void
jit_langhook_write_globals (void) jit_langhook_write_globals (void)
{ {
gcc_assert (gcc::jit::active_playback_ctxt); gcc::jit::playback::context *ctxt = gcc::jit::active_playback_ctxt;
JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ()); gcc_assert (ctxt);
JIT_LOG_SCOPE (ctxt->get_logger ());
ctxt->write_global_decls_1 ();
/* This is the hook that runs the middle and backends: */ /* This is the hook that runs the middle and backends: */
symtab->finalize_compilation_unit (); symtab->finalize_compilation_unit ();
ctxt->write_global_decls_2 ();
} }
#undef LANG_HOOKS_NAME #undef LANG_HOOKS_NAME
......
...@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h" #include "attribs.h"
#include "context.h" #include "context.h"
#include "fold-const.h" #include "fold-const.h"
#include "debug.h"
#include "jit-common.h" #include "jit-common.h"
#include "jit-logging.h" #include "jit-logging.h"
...@@ -109,6 +110,7 @@ playback::context::context (recording::context *ctxt) ...@@ -109,6 +110,7 @@ playback::context::context (recording::context *ctxt)
{ {
JIT_LOG_SCOPE (get_logger ()); JIT_LOG_SCOPE (get_logger ());
m_functions.create (0); m_functions.create (0);
m_globals.create (0);
m_source_files.create (0); m_source_files.create (0);
m_cached_locations.create (0); m_cached_locations.create (0);
} }
...@@ -482,6 +484,7 @@ new_function (location *loc, ...@@ -482,6 +484,7 @@ new_function (location *loc,
playback::lvalue * playback::lvalue *
playback::context:: playback::context::
new_global (location *loc, new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type, type *type,
const char *name) const char *name)
{ {
...@@ -490,13 +493,33 @@ new_global (location *loc, ...@@ -490,13 +493,33 @@ new_global (location *loc,
tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL, tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier (name), get_identifier (name),
type->as_tree ()); type->as_tree ());
TREE_PUBLIC (inner) = 1; TREE_PUBLIC (inner) = (kind != GCC_JIT_GLOBAL_INTERNAL);
DECL_COMMON (inner) = 1; 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) if (loc)
set_tree_location (inner, loc); set_tree_location (inner, loc);
varpool_node::get_create (inner);
m_globals.safe_push (inner);
return new lvalue (this, inner); return new lvalue (this, inner);
} }
...@@ -649,6 +672,45 @@ as_truth_value (tree expr, location *loc) ...@@ -649,6 +672,45 @@ as_truth_value (tree expr, location *loc)
return expr; 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 /* Construct a playback::rvalue instance (wrapping a tree) for a
unary op. */ unary op. */
......
...@@ -90,6 +90,7 @@ public: ...@@ -90,6 +90,7 @@ public:
lvalue * lvalue *
new_global (location *loc, new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type, type *type,
const char *name); const char *name);
...@@ -206,6 +207,10 @@ public: ...@@ -206,6 +207,10 @@ public:
return m_recording_ctxt->errors_occurred (); return m_recording_ctxt->errors_occurred ();
} }
/* For use by jit_langhook_write_globals. */
void write_global_decls_1 ();
void write_global_decls_2 ();
private: private:
void dump_generated_code (); void dump_generated_code ();
...@@ -259,6 +264,7 @@ private: ...@@ -259,6 +264,7 @@ private:
tempdir *m_tempdir; tempdir *m_tempdir;
auto_vec<function *> m_functions; auto_vec<function *> m_functions;
auto_vec<tree> m_globals;
tree m_char_array_type_node; tree m_char_array_type_node;
tree m_const_char_ptr; tree m_const_char_ptr;
......
...@@ -177,6 +177,7 @@ recording::context::context (context *parent_ctxt) ...@@ -177,6 +177,7 @@ recording::context::context (context *parent_ctxt)
m_owns_last_error_str (false), m_owns_last_error_str (false),
m_mementos (), m_mementos (),
m_compound_types (), m_compound_types (),
m_globals (),
m_functions (), m_functions (),
m_FILE_type (NULL), m_FILE_type (NULL),
m_builtins_manager(NULL) m_builtins_manager(NULL)
...@@ -636,12 +637,15 @@ recording::context::get_builtin_function (const char *name) ...@@ -636,12 +637,15 @@ recording::context::get_builtin_function (const char *name)
recording::lvalue * recording::lvalue *
recording::context::new_global (recording::location *loc, recording::context::new_global (recording::location *loc,
enum gcc_jit_global_kind kind,
recording::type *type, recording::type *type,
const char *name) const char *name)
{ {
recording::lvalue *result = recording::global *result =
new recording::global (this, loc, type, new_string (name)); new recording::global (this, loc, kind, type, new_string (name));
record (result); record (result);
m_globals.safe_push (result);
return result; return result;
} }
...@@ -1016,6 +1020,15 @@ recording::context::dump_to_file (const char *path, bool update_locations) ...@@ -1016,6 +1020,15 @@ recording::context::dump_to_file (const char *path, bool update_locations)
d.write ("\n"); 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; function *fn;
FOR_EACH_VEC_ELT (m_functions, i, fn) FOR_EACH_VEC_ELT (m_functions, i, fn)
{ {
...@@ -2648,10 +2661,57 @@ void ...@@ -2648,10 +2661,57 @@ void
recording::global::replay_into (replayer *r) recording::global::replay_into (replayer *r)
{ {
set_playback_obj (r->new_global (playback_location (r, m_loc), set_playback_obj (r->new_global (playback_location (r, m_loc),
m_kind,
m_type->playback_type (), m_type->playback_type (),
playback_string (m_name))); 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: /* The implementation of the various const-handling classes:
gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */ gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
......
...@@ -132,6 +132,7 @@ public: ...@@ -132,6 +132,7 @@ public:
lvalue * lvalue *
new_global (location *loc, new_global (location *loc,
enum gcc_jit_global_kind kind,
type *type, type *type,
const char *name); const char *name);
...@@ -272,6 +273,7 @@ private: ...@@ -272,6 +273,7 @@ private:
/* Specific recordings, for use by dump_to_file. */ /* Specific recordings, for use by dump_to_file. */
auto_vec<compound_type *> m_compound_types; auto_vec<compound_type *> m_compound_types;
auto_vec<global *> m_globals;
auto_vec<function *> m_functions; auto_vec<function *> m_functions;
type *m_basic_types[NUM_GCC_JIT_TYPES]; type *m_basic_types[NUM_GCC_JIT_TYPES];
...@@ -1051,18 +1053,23 @@ class global : public lvalue ...@@ -1051,18 +1053,23 @@ class global : public lvalue
public: public:
global (context *ctxt, global (context *ctxt,
location *loc, location *loc,
enum gcc_jit_global_kind kind,
type *type, type *type,
string *name) string *name)
: lvalue (ctxt, loc, type), : lvalue (ctxt, loc, type),
m_kind (kind),
m_name (name) m_name (name)
{} {}
void replay_into (replayer *); void replay_into (replayer *);
void write_to_dump (dump &d);
private: private:
string * make_debug_string () { return m_name; } string * make_debug_string () { return m_name; }
private: private:
enum gcc_jit_global_kind m_kind;
string *m_name; string *m_name;
}; };
......
...@@ -86,6 +86,33 @@ get_code (const char *funcname) ...@@ -86,6 +86,33 @@ get_code (const char *funcname)
return code; 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::jit
} // namespace gcc } // namespace gcc
...@@ -36,6 +36,9 @@ public: ...@@ -36,6 +36,9 @@ public:
void * void *
get_code (const char *funcname); get_code (const char *funcname);
void *
get_global (const char *name);
private: private:
void *m_dso_handle; void *m_dso_handle;
tempdir *m_tempdir; tempdir *m_tempdir;
......
...@@ -155,7 +155,8 @@ namespace gccjit ...@@ -155,7 +155,8 @@ namespace gccjit
function get_builtin_function (const std::string &name); 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, const std::string &name,
location loc = location ()); location loc = location ());
...@@ -707,12 +708,14 @@ context::get_builtin_function (const std::string &name) ...@@ -707,12 +708,14 @@ context::get_builtin_function (const std::string &name)
} }
inline lvalue inline lvalue
context::new_global (type type_, context::new_global (enum gcc_jit_global_kind kind,
type type_,
const std::string &name, const std::string &name,
location loc) location loc)
{ {
return lvalue (gcc_jit_context_new_global (m_inner_ctxt, return lvalue (gcc_jit_context_new_global (m_inner_ctxt,
loc.get_inner_location (), loc.get_inner_location (),
kind,
type_.get_inner_type (), type_.get_inner_type (),
name.c_str ())); name.c_str ()));
} }
......
...@@ -987,16 +987,23 @@ gcc_jit_block_get_function (gcc_jit_block *block) ...@@ -987,16 +987,23 @@ gcc_jit_block_get_function (gcc_jit_block *block)
gcc_jit_lvalue * gcc_jit_lvalue *
gcc_jit_context_new_global (gcc_jit_context *ctxt, gcc_jit_context_new_global (gcc_jit_context *ctxt,
gcc_jit_location *loc, gcc_jit_location *loc,
enum gcc_jit_global_kind kind,
gcc_jit_type *type, gcc_jit_type *type,
const char *name) const char *name)
{ {
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ()); JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */ /* 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 (type, ctxt, loc, "NULL type");
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); 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. /* Public entrypoint. See description in libgccjit.h.
...@@ -2215,6 +2222,25 @@ gcc_jit_result_get_code (gcc_jit_result *result, ...@@ -2215,6 +2222,25 @@ gcc_jit_result_get_code (gcc_jit_result *result,
/* Public entrypoint. See description in libgccjit.h. /* 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 After error-checking, this is essentially a wrapper around the
destructor for gcc::jit::result in jit-result.c. */ destructor for gcc::jit::result in jit-result.c. */
......
...@@ -299,6 +299,13 @@ extern void * ...@@ -299,6 +299,13 @@ extern void *
gcc_jit_result_get_code (gcc_jit_result *result, gcc_jit_result_get_code (gcc_jit_result *result,
const char *funcname); 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. /* 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 This cleans up the result; after calling this, it's no longer
valid to use the result. */ valid to use the result. */
...@@ -606,10 +613,26 @@ gcc_jit_block_get_function (gcc_jit_block *block); ...@@ -606,10 +613,26 @@ gcc_jit_block_get_function (gcc_jit_block *block);
/********************************************************************** /**********************************************************************
lvalues, rvalues and expressions. 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 * extern gcc_jit_lvalue *
gcc_jit_context_new_global (gcc_jit_context *ctxt, gcc_jit_context_new_global (gcc_jit_context *ctxt,
gcc_jit_location *loc, gcc_jit_location *loc,
enum gcc_jit_global_kind kind,
gcc_jit_type *type, gcc_jit_type *type,
const char *name); const char *name);
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
gcc_jit_param_as_object; gcc_jit_param_as_object;
gcc_jit_param_as_rvalue; gcc_jit_param_as_rvalue;
gcc_jit_result_get_code; gcc_jit_result_get_code;
gcc_jit_result_get_global;
gcc_jit_result_release; gcc_jit_result_release;
gcc_jit_rvalue_access_field; gcc_jit_rvalue_access_field;
gcc_jit_rvalue_as_object; gcc_jit_rvalue_as_object;
......
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> 2015-01-12 Marc Glisse <marc.glisse@inria.fr>
PR testsuite/64427 PR testsuite/64427
......
...@@ -62,7 +62,8 @@ create_code (gcc_jit_context *ctxt, void *user_data) ...@@ -62,7 +62,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
0); 0);
gcc_jit_lvalue *buffer = 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"); gcc_jit_block *block = gcc_jit_function_new_block(test_fn, "entry");
......
...@@ -62,7 +62,10 @@ create_code (gcc_jit_context *ctxt, void *user_data) ...@@ -62,7 +62,10 @@ create_code (gcc_jit_context *ctxt, void *user_data)
0); 0);
gcc_jit_lvalue *buffer = 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"); gcc_jit_block *block = gcc_jit_function_new_block(test_fn, "entry");
......
...@@ -884,6 +884,7 @@ make_test_of_get_address (gcc_jit_context *ctxt) ...@@ -884,6 +884,7 @@ make_test_of_get_address (gcc_jit_context *ctxt)
gcc_jit_context_new_global ( gcc_jit_context_new_global (
ctxt, ctxt,
NULL, NULL,
GCC_JIT_GLOBAL_IMPORTED,
int_type, int_type,
"test_global"); "test_global");
......
...@@ -238,6 +238,7 @@ make_random_global (fuzzer *f) ...@@ -238,6 +238,7 @@ make_random_global (fuzzer *f)
sprintf (global_name, "g%i", f->num_globals); sprintf (global_name, "g%i", f->num_globals);
return gcc_jit_context_new_global (f->ctxt, return gcc_jit_context_new_global (f->ctxt,
get_random_location (f), get_random_location (f),
GCC_JIT_GLOBAL_EXPORTED,
get_random_type (f), get_random_type (f),
global_name); global_name);
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
extern "C" { extern "C" {
#endif #endif
extern int the_global; extern int imported_global;
#ifdef __cplusplus #ifdef __cplusplus
} }
...@@ -19,24 +19,47 @@ void ...@@ -19,24 +19,47 @@ void
create_code (gcc_jit_context *ctxt, void *user_data) create_code (gcc_jit_context *ctxt, void *user_data)
{ {
/* Let's try to inject the equivalent of: /* 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) 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_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); 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. */ /* Build the test_fn. */
gcc_jit_function *test_fn = gcc_jit_function *test_fn =
gcc_jit_context_new_function (ctxt, NULL, gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED, GCC_JIT_FUNCTION_EXPORTED,
void_type, int_type,
"test_using_global", "test_using_global",
0, NULL, 0, NULL,
0); 0);
...@@ -44,30 +67,64 @@ create_code (gcc_jit_context *ctxt, void *user_data) ...@@ -44,30 +67,64 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_block_add_assignment_op ( gcc_jit_block_add_assignment_op (
block, NULL, 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_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_BINARY_OP_PLUS,
gcc_jit_context_one (ctxt, int_type)); gcc_jit_context_one (ctxt, int_type));
gcc_jit_block_end_with_void_return (block, NULL); gcc_jit_block_end_with_return (block,
NULL,
gcc_jit_lvalue_as_rvalue (internal_global));
} }
int the_global; int imported_global;
void void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{ {
typedef void (*fn_type) (void); typedef int (*fn_type) (void);
CHECK_NON_NULL (result); CHECK_NON_NULL (result);
fn_type test_using_global = fn_type test_using_global =
(fn_type)gcc_jit_result_get_code (result, "test_using_global"); (fn_type)gcc_jit_result_get_code (result, "test_using_global");
CHECK_NON_NULL (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. */ /* Call the JIT-generated function. */
test_using_global (); int call_count = test_using_global ();
/* 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 that it correctly modified the_global. */ /* Verify the new values. */
CHECK_VALUE (the_global, 43); CHECK_VALUE (*exported_global, 13);
CHECK_VALUE (imported_global, 44);
CHECK_VALUE (call_count, 2);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment