public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/3] jit: Add support for weak linkage
@ 2021-08-08 15:07 Petter Tomner
  2021-08-08 15:18 ` [PATCH 1/3] " Petter Tomner
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Petter Tomner @ 2021-08-08 15:07 UTC (permalink / raw)
  To: jit, gcc-patches

Hi,

To implement generics/C++ template-ish with libgccjit it would be very useful to have the possibility to declare functions and variables with weak linkage, to be able to have independent AOT compilation of object files without needing to keep track of what is "instantiated" where to prevent collisions.

I implemented this by giving 'gcc_jit_context_new_function()' and  'gcc_jit_context_new_global()' one new enum value EXPORTED_WEAK each that specifies an exported symbol with weak linkage. The variable or function is accessible from a 'result' as would it be EXPORTED.

I split the code up for it to be easier to read:

Patch 1 is the implementation.
Patch 2 is a test case.
Patch 3 is documentation updates.

I ran 'make check-jit' successfully on a x64-pc-gnu linux. I didn't make any ABI tag and the docs need regeneration in path 3.

Regards, Petter Tomner

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] jit: Add support for weak linkage
  2021-08-08 15:07 [PATCH 0/3] jit: Add support for weak linkage Petter Tomner
@ 2021-08-08 15:18 ` Petter Tomner
  2021-08-08 15:20 ` [PATCH 2/3] " Petter Tomner
  2021-08-08 15:21 ` [PATCH 3/3] " Petter Tomner
  2 siblings, 0 replies; 4+ messages in thread
From: Petter Tomner @ 2021-08-08 15:18 UTC (permalink / raw)
  To: gcc-patches, Petter Tomner, jit

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	<tomner@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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/3] jit: Add support for weak linkage
  2021-08-08 15:07 [PATCH 0/3] jit: Add support for weak linkage Petter Tomner
  2021-08-08 15:18 ` [PATCH 1/3] " Petter Tomner
@ 2021-08-08 15:20 ` Petter Tomner
  2021-08-08 15:21 ` [PATCH 3/3] " Petter Tomner
  2 siblings, 0 replies; 4+ messages in thread
From: Petter Tomner @ 2021-08-08 15:20 UTC (permalink / raw)
  To: gcc-patches, Petter Tomner, jit

This patch has a test case for weak linkage as well as modification of helper functions. Essentially it produces two object files, one with weak and one with normal symbols, and a main which prints the values of those two symbols and a cehck to ensure that the normal symbols' values are printed.

2021-08-08	Petter Tomner	<tomner@kth.se>

gcc/testsuite/
	* all-non-failing-tests.h : "weak_symbols" added to test list
	* harness.h : Macro flag to be able to provide own test_jit()
	* jit.exp : Helper functions with support for 2+ outfiles
	* test-compile-weak-symbols.c : New test case
	* verify-weak-linkage.c : main function for linking to obj. files.
---
 gcc/testsuite/jit.dg/all-non-failing-tests.h  |  12 +-
 gcc/testsuite/jit.dg/harness.h                |   5 +
 gcc/testsuite/jit.dg/jit.exp                  |  69 ++++++
 .../jit.dg/test-compile-weak-symbols.c        | 207 ++++++++++++++++++
 gcc/testsuite/jit.dg/verify-weak-linkage.c    |  21 ++
 5 files changed, 313 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/jit.dg/test-compile-weak-symbols.c
 create mode 100644 gcc/testsuite/jit.dg/verify-weak-linkage.c

diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 84ef54a0386..4da34905a3d 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -105,6 +105,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-compile-weak-symbols.c */
+#define create_code create_code_weak_symbols
+#define verify_code verify_code_weak_symbols
+#include "test-compile-weak-symbols.c"
+#undef create_code
+#undef verify_code
+
 /* test-compound-assignment.c */
 #define create_code create_code_compound_assignment
 #define verify_code verify_code_compound_assignment
@@ -454,7 +461,10 @@ const struct testcase testcases[] = {
    verify_code_version},
   {"volatile",
    create_code_volatile,
-   verify_code_volatile}
+   verify_code_volatile},
+  {"weak_symbols",
+   create_code_weak_symbols,
+   verify_code_weak_symbols}
 };
 
 const int num_testcases = (sizeof (testcases) / sizeof (testcases[0]));
diff --git a/gcc/testsuite/jit.dg/harness.h b/gcc/testsuite/jit.dg/harness.h
index 6b59fb57aae..84c248303f4 100644
--- a/gcc/testsuite/jit.dg/harness.h
+++ b/gcc/testsuite/jit.dg/harness.h
@@ -331,6 +331,10 @@ dump_reproducer (gcc_jit_context *ctxt, const char *argv0)
   free (reproducer_name);
 }
 
+static void
+test_jit (const char *argv0, void *user_data);
+
+#ifndef TEST_PROVIDES_TEST_JIT
 /* Run one iteration of the test.  */
 static void
 test_jit (const char *argv0, void *user_data)
@@ -383,6 +387,7 @@ test_jit (const char *argv0, void *user_data)
   if (logfile)
     fclose (logfile);
 }
+#endif /* #ifndef TEST_PROVIDES_TEST_JIT */
 #endif /* #ifndef TEST_ESCHEWS_TEST_JIT */
 
 /* We want to prefix all unit test results with the test, but dejagnu.exp's
diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index 9af87f9c6ad..f26970a41e6 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -692,6 +692,19 @@ proc jit-verify-output-file-was-created { args } {
     }
 }
 
+proc jit-verify-output-files-were-created { args } {
+    verbose "jit-verify-output-files-were-created: $args"
+
+    foreach output_filename $args {
+        # Verify that the expected files was written out
+        if { [file exists $output_filename] == 1} {
+        pass "$output_filename exists"
+        } else {
+        fail "$output_filename does not exist"
+        }
+    }
+}
+
 # Verify that the given file exists, and is executable.
 # Attempt to execute it, and verify that its stdout matches
 # the given regex.
@@ -840,6 +853,62 @@ proc jit-verify-object { args } {
     jit-run-executable ${executable_from_obj} ${dg-output-text}
 }
 
+# Compile 'sources' and link in 'objects' and execute the program 
+# and check that its output matches 'expected_output'.
+#
+# The path to the JIT test source folder is prepended to each
+# word in 'source'.
+#
+# For use with test-compile-weak-symbols.c testcase.
+proc jit-verify-sources-objects { expected_output sources objects } {
+    global srcdir
+    global subdir
+
+    verbose "jit-verify-objects: $expected_output $sources $objects"
+    set dg-output-text $expected_output
+
+    # prepend the path to the folder with the JIT tests
+    # to each source
+    set rel_path "$srcdir/$subdir/"
+    set srcs [lmap i $sources { string cat $rel_path $i }]
+    verbose "sources full path: ${srcs}"
+
+    upvar 2 name name
+    verbose "name: $name"
+
+    upvar 2 prog prog
+    verbose "prog: $prog"
+
+    # Name the linked executable as the first source
+    # with ".exe" appended.
+    set executable_from_obj [lindex $sources 0].exe
+    verbose "  executable_from_obj: ${executable_from_obj}"
+
+    # Invoke the driver to link the .o file to the .exe
+    set comp_output [gcc_target_compile \
+            "${srcs} ${objects}" \
+             ${executable_from_obj} \
+             "executable" \
+             "{}"]
+    if ![jit_check_compile \
+         "$name" \
+         "link of ${executable_from_obj}" \
+         ${executable_from_obj} \
+         $comp_output] then {
+      return
+    }
+
+    # Verify that the executable was created.
+    if { [file exists $executable_from_obj] == 1} {
+    pass "$executable_from_obj exists"
+    } else {
+    fail "$executable_from_obj does not exist"
+    }
+
+    # Run it and verify that the output matches the regex.
+    jit-run-executable ${executable_from_obj} ${dg-output-text}
+}
+
 # Assuming that a .so file has been written out named
 # OUTPUT_FILENAME, build a test executable to use it,
 # and try to run the result.
diff --git a/gcc/testsuite/jit.dg/test-compile-weak-symbols.c b/gcc/testsuite/jit.dg/test-compile-weak-symbols.c
new file mode 100644
index 00000000000..5a746850341
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-compile-weak-symbols.c
@@ -0,0 +1,207 @@
+/* Essentially the goal of the test is to create a two object files:
+
+   weaksymtest_foobar_weak.o:
+    int __attribute__((weak)) weaksymtest_foo() {return 1;}
+    int __attribute__((weak)) weaksymtest_bar[] = {1};
+
+   weaksymtest_foobar.o:   
+    int weaksymtest_foo() {return 2;}
+    int weaksymtest_bar[] = {2};
+
+   and then link them together and verify that the weak symbol is actually 
+   weak and not the one used after linking.
+
+   Since multiple outfiles are needed this test uses TEST_COMPILING_TO_FILE
+   in a slightly different way then the other tests. It provides its own
+   test_jit() via TEST_PROVIDES_TEST_JIT.
+   
+   This test is dependent on verify-weak-linkage.c which is a main function
+   with declarations of foo and bar and that outputs foo() and bar[0] to 
+   stdout. */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+/* When included in all-non-failing-tests.h with COMBINED_TEST defined 
+   this testfile does not produce any output files. */
+#ifndef COMBINED_TEST
+#define TEST_COMPILING_TO_FILE
+#define TEST_PROVIDES_TEST_JIT
+#include "harness.h"
+#undef TEST_PROVIDES_TEST_JIT
+#else
+#include "harness.h"
+#endif
+
+extern void
+create_code_weak_or_normal (gcc_jit_context *ctxt, int create_weak);
+
+typedef int (*fooptr)(void);
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  (void) ctxt; /* Not used */
+
+  fooptr foo = gcc_jit_result_get_code (result, "weaksymtest_foo");
+  int *bar = gcc_jit_result_get_global (result, "weaksymtest_bar");
+
+  /* Just do a simple test accessing the weak symbols from the
+     JIT context */
+  CHECK_VALUE (*bar, 1);
+  CHECK_VALUE (foo(), 1);
+}
+
+/* Do not provide test_jit() when included in all-non-failing-test.h */
+#ifndef COMBINED_TEST
+/* Runs one iteration of the test. */
+static void
+test_jit (const char *argv0, void *user_data)
+{
+  gcc_jit_context *ctxt_normal, *ctxt_weak;
+  FILE *logfile_normal, *logfile_weak;
+  char *argv0_weak, *argv0_normal;
+
+  (void) user_data; /* Not used */
+
+  argv0_weak = concat_strings (argv0, ".weak");
+  argv0_normal = concat_strings (argv0, ".normal");
+
+  unlink ("weaksymtest_foobar_weak.o");
+  unlink ("weaksymtest_foobar.o");
+  
+  ctxt_weak = gcc_jit_context_acquire ();
+  ctxt_normal = gcc_jit_context_acquire ();
+  if (!ctxt_normal || !ctxt_weak)
+    {
+      fail ("gcc_jit_context_acquire failed");
+      return;
+    }
+  
+  logfile_weak = set_up_logging (ctxt_weak, argv0_weak);
+  logfile_normal = set_up_logging (ctxt_normal, argv0_normal);
+
+  set_options (ctxt_normal, argv0_normal);
+  set_options (ctxt_weak, argv0_weak);
+
+  free (argv0_weak); argv0_weak = 0;
+  free (argv0_normal); argv0_normal = 0;
+
+  create_code_weak_or_normal (ctxt_normal, 0);
+  create_code_weak_or_normal (ctxt_weak, 1);
+
+  /* Note that argv0 is used instead of argv0_weak since 
+     jit-dg-test expects a certain name of the dumpfile. */
+  dump_reproducer (ctxt_weak, argv0);
+
+  gcc_jit_context_compile_to_file (ctxt_normal,
+           GCC_JIT_OUTPUT_KIND_OBJECT_FILE,
+           "weaksymtest_foobar_n.o");
+  gcc_jit_context_compile_to_file (ctxt_weak,
+           GCC_JIT_OUTPUT_KIND_OBJECT_FILE,
+           "weaksymtest_foobar_w.o");
+
+  /* ld treats weak symbols in shared libraries like
+     normal symbols unless env.var. LD_DYNAMIC_WEAK is set,
+     so dynamic libraries are a bit awkward to test in
+     a unit test like we do here. However it is easy 
+     to check manually that the symbols are weak with 
+     objdump etc. */
+#if 0
+  unlink ("weaksymtest_foobar_weak.so");
+  unlink ("weaksymtest_foobar.so");
+  gcc_jit_context_compile_to_file (ctxt_weak,
+                  GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY,
+                  "libweaksymtest_foobar_w.so");
+  gcc_jit_context_compile_to_file (ctxt_normal,
+                  GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY,
+                  "libweaksymtest_foobar_n.so");
+#endif
+
+  /* For checking wether the c-like dump looks ok */
+#if 0
+  unlink("libweaksymtest_foobar_w.c");
+  gcc_jit_context_dump_to_file (ctxt_weak, "libweaksymtest_foobar_w.c", 0);
+#endif
+
+  CHECK_NO_ERRORS (ctxt_normal);
+  CHECK_NO_ERRORS (ctxt_weak);
+
+  gcc_jit_result *result_weak = gcc_jit_context_compile (ctxt_weak);
+  CHECK_NON_NULL (result_weak);
+  /* Just does some simple access and value check of the weak symbols */
+  CHECK_NO_ERRORS (ctxt_weak);
+  verify_code (ctxt_weak, result_weak);
+
+  gcc_jit_result_release (result_weak);
+
+  gcc_jit_context_release (ctxt_normal);
+  gcc_jit_context_release (ctxt_weak);
+
+  if (logfile_normal)
+    fclose (logfile_normal);
+  if (logfile_weak)
+    fclose (logfile_weak);
+}
+#endif /* #ifndef COMBINED_TEST */
+
+extern void
+create_code_weak_or_normal (gcc_jit_context *ctxt, int create_weak)
+{
+  enum gcc_jit_function_kind fn_kind;
+  enum gcc_jit_global_kind var_kind;
+  int value;
+  int arr[1];
+
+  if (create_weak) 
+    {
+      fn_kind = GCC_JIT_FUNCTION_EXPORTED_WEAK;
+      var_kind = GCC_JIT_GLOBAL_EXPORTED_WEAK;
+      value = 1;
+    } 
+  else 
+    {
+      fn_kind = GCC_JIT_FUNCTION_EXPORTED;
+      var_kind = GCC_JIT_GLOBAL_EXPORTED;
+      value = 2;
+    }
+
+  /* int __attribute__((weak)) foo() { return 1;}
+     int foo() { return 2;} */
+  gcc_jit_type *int_type = 
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_function *foo = 
+    gcc_jit_context_new_function (ctxt, 0, fn_kind, int_type, 
+    "weaksymtest_foo", 0,0,0);
+  gcc_jit_block *block1 =
+    gcc_jit_function_new_block (foo, "block1");
+  gcc_jit_block_end_with_return (block1, 0, 
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, value));
+  
+  /* int __attribute__((weak)) bar[] = {1};
+     int bar[] = {2}; */
+  gcc_jit_lvalue *bar = gcc_jit_context_new_global (ctxt, 0, var_kind, 
+    gcc_jit_context_new_array_type (ctxt, 0, int_type, 1), "weaksymtest_bar");
+  
+  arr[0] = value;
+  gcc_jit_global_set_initializer (bar, (const void *)arr, sizeof(int));
+}
+
+/* This function is used in all-non-failing-test.h and just creates the
+   weak context */
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  (void) user_data;
+  create_code_weak_or_normal (ctxt, 1);
+}
+
+/* { dg-final { jit-verify-output-files-were-created "weaksymtest_foobar_w.o" "weaksymtest_foobar_n.o"} } */
+
+/* jit-verify-sources-objects compiles "verify-weak-linkage.c" with the object files
+   and checks that the stdout of the resulting executable matches "2\n2\n" which 
+   indicates that the weak symbols are not used. */
+
+/* { dg-final { jit-verify-sources-objects "2\\n2\\n" "verify-weak-linkage.c" "weaksymtest_foobar_w.o weaksymtest_foobar_n.o"} } */
diff --git a/gcc/testsuite/jit.dg/verify-weak-linkage.c b/gcc/testsuite/jit.dg/verify-weak-linkage.c
new file mode 100644
index 00000000000..c3ac1b9a50d
--- /dev/null
+++ b/gcc/testsuite/jit.dg/verify-weak-linkage.c
@@ -0,0 +1,21 @@
+/* For use with jit-verify-sources-objects
+   used by test-compile-weak-symbols.c
+
+   This file is linked to two object files . One with
+   weak symbols, one with normal. It prints the value 
+   of bar[0] and foo() and should print 2\n2\n if the
+   weak symbols are not linked in. */
+
+#include <stdio.h>
+
+extern int weaksymtest_bar[1];
+int weaksymtest_foo();
+
+int
+main (int argc, char **argv)
+{
+  printf ("%d\n", weaksymtest_foo());
+  printf ("%d\n", weaksymtest_bar[0]);
+  return 0;
+}
+
-- 
2.20.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 3/3] jit: Add support for weak linkage
  2021-08-08 15:07 [PATCH 0/3] jit: Add support for weak linkage Petter Tomner
  2021-08-08 15:18 ` [PATCH 1/3] " Petter Tomner
  2021-08-08 15:20 ` [PATCH 2/3] " Petter Tomner
@ 2021-08-08 15:21 ` Petter Tomner
  2 siblings, 0 replies; 4+ messages in thread
From: Petter Tomner @ 2021-08-08 15:21 UTC (permalink / raw)
  To: gcc-patches, Petter Tomner, jit

This patch updates the documentation concerning the addition of weak linkage for 'gcc_jit_context_new_function()' and  'gcc_jit_context_new_global()'. The documentation needs regeneration.

gcc/jit/docs/topics/
	* compilation.rst
	* expressions.rst
	* functions.rst
---
 gcc/jit/docs/topics/compilation.rst |  3 ++-
 gcc/jit/docs/topics/expressions.rst | 13 +++++++++++++
 gcc/jit/docs/topics/functions.rst   | 20 +++++++++++++++++---
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/gcc/jit/docs/topics/compilation.rst b/gcc/jit/docs/topics/compilation.rst
index b6ace12120f..67c7ac5f7f3 100644
--- a/gcc/jit/docs/topics/compilation.rst
+++ b/gcc/jit/docs/topics/compilation.rst
@@ -57,7 +57,8 @@ In-memory compilation
    with a name matching `funcname` must have been created on
    `result`'s context (or a parent context) via a call to
    :func:`gcc_jit_context_new_function` with `kind`
-   :macro:`GCC_JIT_FUNCTION_EXPORTED`:
+   :macro:`GCC_JIT_FUNCTION_EXPORTED` or 
+   :macro:`GCC_JIT_FUNCTION_EXPORTED_WEAK`:
 
    .. code-block:: c
 
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 396259ef07e..e3a57264732 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -582,6 +582,19 @@ Global variables
       referring to it.  Analogous to using an "extern" global from a
       header file.
 
+   .. c:macro:: GCC_JIT_GLOBAL_EXPORTED_WEAK
+
+      Global is defined by the client code with weak linkage and is visible
+      by name outside of this JIT context via
+      :c:func:`gcc_jit_result_get_global`.  Analogous to declaring a variable
+      with ``__attribute__((weak))``.
+
+      When compiled to file weak linkage allow multiple definitions
+      of the same symbol name in different files all being linked 
+      together. Note that child contexts include their parent and 
+      can't have more than one variable with the same name no matter
+      if weak or not.
+
 .. function:: gcc_jit_lvalue *\
               gcc_jit_global_set_initializer (gcc_jit_lvalue *global,\
                                               const void *blob,\
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index b2d9239aa0a..31de2147e10 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -90,9 +90,8 @@ Functions
          Function is defined by the client code and visible
          by name outside of the JIT.
 
-         This value is required if you want to extract machine code
-         for this function from a :type:`gcc_jit_result` via
-         :func:`gcc_jit_result_get_code`.
+         With this value you can extract machine code for this function
+         from a :type:`gcc_jit_result` via :func:`gcc_jit_result_get_code`.
 
       .. macro::   GCC_JIT_FUNCTION_INTERNAL
 
@@ -117,6 +116,21 @@ Functions
          above 0; when optimization is off, this is essentially the
          same as GCC_JIT_FUNCTION_INTERNAL.
 
+      .. macro:: GCC_JIT_FUNCTION_EXPORTED_WEAK
+
+         Function is defined by the client code with weak linkage and 
+         is visible by name outside of the JIT.  Analogous to a function
+         with ``__attribute__((weak))``.
+
+         When compiled to file weak linkage allow multiple definitions
+         of the same symbol name in different files all being linked 
+         together. Note that child contexts include their parent and 
+         can't have more than one function with the same name no matter
+         if weak or not.
+
+         With this value you can extract machine code for this function
+         from a :type:`gcc_jit_result` via :func:`gcc_jit_result_get_code`.
+
    The parameter ``name`` must be non-NULL.  The call takes a copy of the
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
-- 
2.20.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-08-08 15:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-08 15:07 [PATCH 0/3] jit: Add support for weak linkage Petter Tomner
2021-08-08 15:18 ` [PATCH 1/3] " Petter Tomner
2021-08-08 15:20 ` [PATCH 2/3] " Petter Tomner
2021-08-08 15:21 ` [PATCH 3/3] " Petter Tomner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).