* :func:`gcc_jit_struct_get_field`
* :func:`gcc_jit_struct_get_field_count`
+
+.. _LIBGCCJIT_ABI_17:
+
+``LIBGCCJIT_ABI_17``
+-----------------------
+``LIBGCCJIT_ABI_17`` covers the addition of an API entrypoint to set the
+thread-local storage model of a variable:
+
+ * :func:`gcc_jit_lvalue_set_tls_model`
in C.
+.. function:: void\
+ gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue,\
+ enum gcc_jit_tls_model model)
+
+ Make a variable a thread-local variable.
+
+ The "model" parameter determines the thread-local storage model of the "lvalue":
+
+ .. type:: enum gcc_jit_tls_model
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_NONE
+
+ Don't set the TLS model.
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_INITIAL_EXEC
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_LOCAL_EXEC
+
+ This is analogous to:
+
+ .. code-block:: c
+
+ _Thread_local int foo __attribute__ ((tls_model("MODEL")));
+
+ in C.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_17`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model
+
Global variables
****************
rvalue *
get_address (location *loc);
+ void
+ set_tls_model (enum tls_model tls_model)
+ {
+ set_decl_tls_model (as_tree (), tls_model);
+ }
+
private:
bool mark_addressable (location *loc);
};
return result;
}
+void
+recording::lvalue::set_tls_model (enum gcc_jit_tls_model model)
+{
+ m_tls_model = model;
+}
+
/* The implementation of class gcc::jit::recording::param. */
/* Implementation of pure virtual hook recording::memento::replay_into
# pragma GCC diagnostic pop
#endif
+namespace recording {
+static const enum tls_model tls_models[] = {
+ TLS_MODEL_NONE, /* GCC_JIT_TLS_MODEL_NONE */
+ TLS_MODEL_GLOBAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC */
+ TLS_MODEL_LOCAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC */
+ TLS_MODEL_INITIAL_EXEC, /* GCC_JIT_TLS_MODEL_INITIAL_EXEC */
+ TLS_MODEL_LOCAL_EXEC, /* GCC_JIT_TLS_MODEL_LOCAL_EXEC */
+};
+} /* namespace recording */
+
/* The implementation of class gcc::jit::recording::global. */
/* Implementation of pure virtual hook recording::memento::replay_into
void
recording::global::replay_into (replayer *r)
{
- set_playback_obj (
- m_initializer
+ playback::lvalue *global = m_initializer
? r->new_global_initialized (playback_location (r, m_loc),
m_kind,
m_type->playback_type (),
: r->new_global (playback_location (r, m_loc),
m_kind,
m_type->playback_type (),
- playback_string (m_name)));
+ playback_string (m_name));
+ if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
+ global->set_tls_model (recording::tls_models[m_tls_model]);
+
+ set_playback_obj (global);
}
/* Override the default implementation of
/* Implementation of recording::memento::write_reproducer for globals. */
+static const char * const tls_model_enum_strings[] = {
+ "GCC_JIT_TLS_MODEL_NONE",
+ "GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC",
+ "GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC",
+ "GCC_JIT_TLS_MODEL_INITIAL_EXEC",
+ "GCC_JIT_TLS_MODEL_LOCAL_EXEC",
+};
+
void
recording::global::write_reproducer (reproducer &r)
{
r.get_identifier_as_type (get_type ()),
m_name->get_debug_string ());
+ if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
+ r.write (" gcc_jit_lvalue_set_tls_model (%s, /* gcc_jit_lvalue *lvalue */\n"
+ " %s); /* enum gcc_jit_tls_model model */\n",
+ id,
+ tls_model_enum_strings[m_tls_model]);
+
if (m_initializer)
switch (m_type->dereference ()->get_size ())
{
lvalue (context *ctxt,
location *loc,
type *type_)
- : rvalue (ctxt, loc, type_)
+ : rvalue (ctxt, loc, type_),
+ m_tls_model (GCC_JIT_TLS_MODEL_NONE)
{}
playback::lvalue *
const char *access_as_rvalue (reproducer &r) OVERRIDE;
virtual const char *access_as_lvalue (reproducer &r);
virtual bool is_global () const { return false; }
+ void set_tls_model (enum gcc_jit_tls_model model);
+
+protected:
+ enum gcc_jit_tls_model m_tls_model;
};
class param : public lvalue
return (gcc_jit_rvalue *)lvalue->get_address (loc);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::lvalue::set_tls_model method in jit-recording.c. */
+
+void
+gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue,
+ enum gcc_jit_tls_model model)
+{
+ RETURN_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue");
+ JIT_LOG_FUNC (lvalue->get_context ()->get_logger ());
+ RETURN_IF_FAIL_PRINTF1 (lvalue->is_global (), lvalue->get_context (), NULL,
+ "lvalue \"%s\" not a global",
+ lvalue->get_debug_string ());
+
+ lvalue->set_tls_model (model);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
GCC_JIT_FUNCTION_ALWAYS_INLINE
};
+/* Thread local storage model. */
+enum gcc_jit_tls_model
+{
+ GCC_JIT_TLS_MODEL_NONE,
+ GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC,
+ GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC,
+ GCC_JIT_TLS_MODEL_INITIAL_EXEC,
+ GCC_JIT_TLS_MODEL_LOCAL_EXEC,
+};
+
/* Create a function. */
extern gcc_jit_function *
gcc_jit_context_new_function (gcc_jit_context *ctxt,
gcc_jit_lvalue_get_address (gcc_jit_lvalue *lvalue,
gcc_jit_location *loc);
+#define LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model
+
+/* Set the thread-local storage model of a global variable
+
+ This API entrypoint was added in LIBGCCJIT_ABI_17; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model */
+extern void
+gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue,
+ enum gcc_jit_tls_model model);
+
extern gcc_jit_lvalue *
gcc_jit_function_new_local (gcc_jit_function *func,
gcc_jit_location *loc,
gcc_jit_type_is_struct;
gcc_jit_struct_get_field_count;
} LIBGCCJIT_ABI_15;
+
+LIBGCCJIT_ABI_17 {
+ global:
+ gcc_jit_lvalue_set_tls_model;
+} LIBGCCJIT_ABI_16;
#undef create_code
#undef verify_code
+/* test-tls.c */
+#define create_code create_code_tls
+#define verify_code verify_code_tls
+#include "test-tls.c"
+#undef create_code
+#undef verify_code
+
/* test-hello-world.c */
#define create_code create_code_hello_world
#define verify_code verify_code_hello_world
{"switch",
create_code_switch,
verify_code_switch},
+ {"tls",
+ create_code_tls,
+ verify_code_tls},
{"types",
create_code_types,
verify_code_types},
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+
+ _Thread_local int foo;
+
+ int test_using_tls()
+ {
+ foo = 42;
+ return foo;
+ }
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+ gcc_jit_lvalue *foo =
+ gcc_jit_context_new_global (
+ ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, int_type, "foo");
+ gcc_jit_lvalue_set_tls_model (foo, GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC);
+
+ /* Build the test_fn. */
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "test_using_tls",
+ 0, NULL,
+ 0);
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+ gcc_jit_block_add_assignment (
+ block, NULL,
+ foo,
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 42));
+ gcc_jit_block_end_with_return (block,
+ NULL,
+ gcc_jit_lvalue_as_rvalue (foo));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*fn_type) (void);
+ CHECK_NON_NULL (result);
+
+ fn_type test_using_tls =
+ (fn_type)gcc_jit_result_get_code (result, "test_using_tls");
+ CHECK_NON_NULL (test_using_tls);
+ int return_value = test_using_tls();
+ CHECK_VALUE (return_value, 42);
+
+ int *foo = (int *)gcc_jit_result_get_global (result, "foo");
+ CHECK_NON_NULL (foo);
+ CHECK_VALUE (*foo, 42);
+}