This patch adds support for weak linkage variables and functions in libgccjit. 'gcc_jit_context_new_function()' and 'gcc_jit_context_new_global()' gets one new enum value each which specifies weak linkage. The macro 'LIBGCCJIT_HAVE_WEAK_SYMBOLS' indicates weak linkage support. Analogous to declaring with "__attribute__((weak))".
2021-08-08 Petter Tomner <tom...@kth.se> gcc/jit/ * libgccjit.c: Range check for enum * libgccjit.h (LIBGCCJIT_HAVE_WEAK_SYMBOLS): Feuture macro (enum gcc_jit_function_kind): New enum value (enum gcc_jit_global_kind): New enum value * jit-playback.c : Make nodes weak * jit-recording.c : Reproduce and dump properly --- gcc/jit/jit-playback.c | 11 ++++++++++ gcc/jit/jit-recording.c | 22 +++++++++++++++----- gcc/jit/libgccjit.c | 4 ++-- gcc/jit/libgccjit.h | 45 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 79ac525e5df..58ba23fa3b4 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -565,6 +565,11 @@ global_new_decl (location *loc, case GCC_JIT_GLOBAL_IMPORTED: DECL_EXTERNAL (inner) = 1; break; + + case GCC_JIT_GLOBAL_EXPORTED_WEAK: + TREE_STATIC (inner) = 1; + DECL_WEAK (inner) = 1; + break; } if (loc) @@ -1640,6 +1645,12 @@ postprocess () DECL_PRESERVE_P (m_inner_fndecl) = 1; } + if (m_kind == GCC_JIT_FUNCTION_EXPORTED_WEAK) + { + DECL_WEAK (m_inner_fndecl) = 1; + DECL_EXTERNAL (m_inner_fndecl) = 0; + DECL_PRESERVE_P (m_inner_fndecl) = 1; + } if (m_kind == GCC_JIT_FUNCTION_INTERNAL ||m_kind == GCC_JIT_FUNCTION_ALWAYS_INLINE) { diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 117ff70114c..77c069358ef 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -3902,6 +3902,7 @@ recording::function::write_to_dump (dump &d) default: gcc_unreachable (); case GCC_JIT_FUNCTION_EXPORTED: case GCC_JIT_FUNCTION_IMPORTED: + case GCC_JIT_FUNCTION_EXPORTED_WEAK: d.write ("extern "); break; case GCC_JIT_FUNCTION_INTERNAL: @@ -3913,6 +3914,9 @@ recording::function::write_to_dump (dump &d) } d.write ("%s\n", m_return_type->get_debug_string ()); + if (m_kind == GCC_JIT_FUNCTION_EXPORTED_WEAK) + d.write ("__attribute__((weak)) "); + if (d.update_locations ()) m_loc = d.make_location (); @@ -4107,7 +4111,8 @@ static const char * const names_of_function_kinds[] = { "GCC_JIT_FUNCTION_EXPORTED", "GCC_JIT_FUNCTION_INTERNAL", "GCC_JIT_FUNCTION_IMPORTED", - "GCC_JIT_FUNCTION_ALWAYS_INLINE" + "GCC_JIT_FUNCTION_ALWAYS_INLINE", + "GCC_JIT_FUNCTION_EXPORTED_WEAK" }; /* Implementation of recording::memento::write_reproducer for functions. */ @@ -4579,6 +4584,10 @@ recording::global::replay_into (replayer *r) "extern TYPE NAME;" e.g. "extern int foo;" + GCC_JIT_GLOBAL_EXPORTED_WEAK: + "TYPE __attribute__((weak)) NAME" + e.g. "int __attribute__((weak)) foo" + These are written to the top of the dump by recording::context::dump_to_file. */ @@ -4594,6 +4603,7 @@ recording::global::write_to_dump (dump &d) gcc_unreachable (); case GCC_JIT_GLOBAL_EXPORTED: + case GCC_JIT_GLOBAL_EXPORTED_WEAK: break; case GCC_JIT_GLOBAL_INTERNAL: @@ -4605,9 +4615,10 @@ recording::global::write_to_dump (dump &d) break; } - d.write ("%s %s", - m_type->get_debug_string (), - get_debug_string ()); + d.write ("%s ", m_type->get_debug_string ()); + if (m_kind == GCC_JIT_GLOBAL_EXPORTED_WEAK) + d.write ("__attribute__((weak)) "); + d.write ("%s", get_debug_string ()); if (!m_initializer) { @@ -4632,7 +4643,8 @@ recording::global::write_to_dump (dump &d) static const char * const global_kind_reproducer_strings[] = { "GCC_JIT_GLOBAL_EXPORTED", "GCC_JIT_GLOBAL_INTERNAL", - "GCC_JIT_GLOBAL_IMPORTED" + "GCC_JIT_GLOBAL_IMPORTED", + "GCC_JIT_GLOBAL_EXPORTED_WEAK" }; template <typename T> diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 7fa948007ad..d290f908774 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -902,7 +902,7 @@ gcc_jit_context_new_function (gcc_jit_context *ctxt, /* LOC can be NULL. */ RETURN_NULL_IF_FAIL_PRINTF1 ( ((kind >= GCC_JIT_FUNCTION_EXPORTED) - && (kind <= GCC_JIT_FUNCTION_ALWAYS_INLINE)), + && (kind <= GCC_JIT_FUNCTION_EXPORTED_WEAK)), ctxt, loc, "unrecognized value for enum gcc_jit_function_kind: %i", kind); @@ -1101,7 +1101,7 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt, /* LOC can be NULL. */ RETURN_NULL_IF_FAIL_PRINTF1 ( ((kind >= GCC_JIT_GLOBAL_EXPORTED) - && (kind <= GCC_JIT_GLOBAL_IMPORTED)), + && (kind <= GCC_JIT_GLOBAL_EXPORTED_WEAK)), ctxt, loc, "unrecognized value for enum gcc_jit_global_kind: %i", kind); diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 5c722c2c57f..87e60f2b8eb 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -444,7 +444,8 @@ 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. + It must have been created using GCC_JIT_GLOBAL_EXPORTED or + GCC_JIT_GLOBAL_EXPORTED_WEAK. 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, @@ -694,13 +695,22 @@ gcc_jit_param_as_lvalue (gcc_jit_param *param); extern gcc_jit_rvalue * gcc_jit_param_as_rvalue (gcc_jit_param *param); +/* Feature macro to indicate the presence of: + GCC_JIT_FUNCTION_EXPORTED_WEAK in gcc_jit_function_kind + and: + GCC_JIT_GLOBAL_EXPORTED_WEAK in gcc_jit_global_kind + + These give weak linkage for function and variables + when compiled to files. */ +#define LIBGCCJIT_HAVE_WEAK_SYMBOLS + /* Kinds of function. */ enum gcc_jit_function_kind { /* Function is defined by the client code and visible by name outside of the JIT. */ GCC_JIT_FUNCTION_EXPORTED, - + /* Function is defined by the client code, but is invisible outside of the JIT. Analogous to a "static" function. */ GCC_JIT_FUNCTION_INTERNAL, @@ -719,7 +729,20 @@ enum gcc_jit_function_kind Inlining will only occur when the optimization level is above 0; when optimization is off, this is essentially the same as GCC_JIT_FUNCTION_INTERNAL. */ - GCC_JIT_FUNCTION_ALWAYS_INLINE + GCC_JIT_FUNCTION_ALWAYS_INLINE, + + /* Function is defined by the client code with weak linkage and + visible by name outside of the JIT at runtime. + + When compiled to file weak linkage allow multiple definitions + of the same symbol name in different files all being linked + together. + + Analogous to a extern function with "__attribute__((weak))". + + Note that child contexts include their parent and can't have a + exported function with the same name no matter if weak or not. */ + GCC_JIT_FUNCTION_EXPORTED_WEAK }; /* Create a function. */ @@ -785,7 +808,21 @@ enum gcc_jit_global_kind /* 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 + GCC_JIT_GLOBAL_IMPORTED, + + /* Global is defined by the client code with weak linkage and is + visible at runtime by name outside of this JIT context via + gcc_jit_result_get_global. + + When compiled to file weak linkage allow multiple definitions + of the same symbol name in different files all being linked + together. + + Analogous to a "__attribute__((weak))" global. + + Note that child contexts include their parent and can't have a + symbol with the same name no matter if weak or not. */ + GCC_JIT_GLOBAL_EXPORTED_WEAK }; extern gcc_jit_lvalue * -- 2.20.1