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:
parent
6c0fcb81da
commit
791cfef8e7
@ -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",
|
||||
|
649
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
649
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
-----------------------------------------
|
||||
|
@ -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
|
||||
-----------------------------------------
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>. */
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 ()));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user