From: Antoni Boucher <[email protected]>

gcc/jit/ChangeLog:

        * docs/topics/compatibility.rst (LIBGCCJIT_ABI_36): New ABI tag.
        * docs/topics/expressions.rst: Document gcc_jit_lvalue_add_attribute.
        * jit-playback.cc: Handle the weak attribute.
        * jit-playback.h: Add support for variable attributes without
        arguments.
        * jit-recording.cc: Handle the weak attribute.
        * jit-recording.h: Add support for variable attributes without
        arguments.
        * libgccjit.cc (gcc_jit_lvalue_add_attribute): New function.
        * libgccjit.h (gcc_jit_lvalue_add_attribute): New function.
        (GCC_JIT_VARIABLE_ATTRIBUTE_WEAK): New enum variant.
        * libgccjit.map: New function.

gcc/testsuite/ChangeLog:

        * jit.dg/all-non-failing-tests.h: Mention new test.
        * jit.dg/test-weak-var-attribute.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst         |  8 +++++
 gcc/jit/docs/topics/expressions.rst           | 13 ++++++++
 gcc/jit/jit-playback.cc                       | 32 +++++++++++++++----
 gcc/jit/jit-playback.h                        |  8 +++--
 gcc/jit/jit-recording.cc                      | 20 ++++++++++++
 gcc/jit/jit-recording.h                       |  5 ++-
 gcc/jit/libgccjit.cc                          | 18 +++++++++++
 gcc/jit/libgccjit.h                           |  8 +++++
 gcc/jit/libgccjit.map                         |  5 +++
 gcc/testsuite/jit.dg/all-non-failing-tests.h  |  3 ++
 .../jit.dg/test-weak-var-attribute.c          | 31 ++++++++++++++++++
 11 files changed, 142 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-weak-var-attribute.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 19be33eb4b5..c70fbd07929 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -466,3 +466,11 @@ information:
   * :func:`gcc_jit_target_info_cpu_supports`
   * :func:`gcc_jit_target_info_arch`
   * :func:`gcc_jit_target_info_supports_target_dependent_type`
+
+.. _LIBGCCJIT_ABI_36:
+
+``LIBGCCJIT_ABI_36``
+--------------------
+``LIBGCCJIT_ABI_36`` covers the addition of
+
+ * :func:`gcc_jit_lvalue_add_attribute`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 5dcb5d10bce..66538003706 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -1037,6 +1037,19 @@ Variables
 
       #ifdef LIBGCCJIT_HAVE_ATTRIBUTES
 
+.. function:: void\
+              gcc_jit_lvalue_add_attribute (gcc_jit_lvalue *variable,
+                                            enum gcc_jit_variable_attribute attribute);
+
+     Add an attribute ``attribute`` without value to a variable ``variable``.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_36`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_add_attribute
+
 .. function:: void\
               gcc_jit_global_set_readonly (gcc_jit_lvalue *global)
 
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 291ddeb2cca..2a4d4860d39 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -559,6 +559,8 @@ const char* variable_attribute_to_string (gcc_jit_variable_attribute attr)
   {
     case GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY:
       return "visibility";
+    case GCC_JIT_VARIABLE_ATTRIBUTE_WEAK:
+      return "weak";
     case GCC_JIT_VARIABLE_ATTRIBUTE_MAX:
       return NULL;
   }
@@ -743,7 +745,8 @@ global_new_decl (location *loc,
 		 const char *name,
 		 enum global_var_flags flags,
 		 const std::vector<std::pair<gcc_jit_variable_attribute,
-					     std::string>> &attributes,
+				   std::string>> &string_attributes,
+		 const std::vector<gcc_jit_variable_attribute> &attributes,
 		 bool readonly)
 {
   gcc_assert (type);
@@ -789,7 +792,19 @@ global_new_decl (location *loc,
   if (loc)
     set_tree_location (inner, loc);
 
-  set_variable_string_attribute (attributes, inner);
+  set_variable_string_attribute (string_attributes, inner);
+
+  tree var_attributes = NULL_TREE;
+  for (auto attr: attributes)
+  {
+    const char* attribute = variable_attribute_to_string (attr);
+    if (attribute)
+    {
+      tree ident = get_identifier (attribute);
+      var_attributes = tree_cons (ident, NULL_TREE, var_attributes);
+    }
+  }
+  decl_attributes (&inner, var_attributes, 0);
 
   return inner;
 }
@@ -836,11 +851,13 @@ new_global (location *loc,
 	    const char *name,
 	    enum global_var_flags flags,
 	    const std::vector<std::pair<gcc_jit_variable_attribute,
-					std::string>> &attributes,
+					std::string>> &string_attributes,
+	    const std::vector<gcc_jit_variable_attribute> &attributes,
 	    bool readonly)
 {
   tree inner =
-    global_new_decl (loc, kind, type, name, flags, attributes, readonly);
+    global_new_decl (loc, kind, type, name, flags, string_attributes,
+      attributes, readonly);
 
   return global_finalize_lvalue (inner);
 }
@@ -987,10 +1004,13 @@ new_global_initialized (location *loc,
 			const char *name,
 			enum global_var_flags flags,
 			const std::vector<std::pair<gcc_jit_variable_attribute,
-						    std::string>> &attributes,
+					  std::string>> &string_attributes,
+			const std::vector<gcc_jit_variable_attribute>
+					  &attributes,
 			bool readonly)
 {
-  tree inner = global_new_decl (loc, kind, type, name, flags, attributes, readonly);
+  tree inner = global_new_decl (loc, kind, type, name, flags,
+    string_attributes, attributes, readonly);
 
   vec<constructor_elt, va_gc> *constructor_elements = NULL;
 
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 07dab6fa389..e1088409d33 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -139,7 +139,8 @@ public:
 	      const char *name,
 	      enum global_var_flags flags,
 	      const std::vector<std::pair<gcc_jit_variable_attribute,
-					  std::string>> &attributes,
+					  std::string>> &string_attributes,
+	      const std::vector<gcc_jit_variable_attribute> &attributes,
 	      bool readonly);
 
   lvalue *
@@ -154,6 +155,8 @@ public:
 			  const std::vector<std::pair<
 					    gcc_jit_variable_attribute,
 					    std::string>>
+					    &string_attributes,
+			  const std::vector<gcc_jit_variable_attribute>
 					    &attributes,
 			  bool readonly);
 
@@ -375,7 +378,8 @@ private:
 		   const char *name,
 		   enum global_var_flags flags,
 		   const std::vector<std::pair<gcc_jit_variable_attribute,
-					       std::string>> &attributes,
+					       std::string>> &string_attributes,
+		   const std::vector<gcc_jit_variable_attribute> &attributes,
 		   bool readonly);
   lvalue *
   global_finalize_lvalue (tree inner);
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 2f4ecc31825..c0b9afe5c5b 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -4285,6 +4285,12 @@ void recording::lvalue::add_string_attribute (
   m_string_attributes.push_back (std::make_pair (attribute, std::string (value)));
 }
 
+void recording::lvalue::add_attribute (
+	gcc_jit_variable_attribute attribute)
+{
+  m_attributes.push_back (attribute);
+}
+
 /* The implementation of class gcc::jit::recording::param.  */
 
 /* Implementation of pure virtual hook recording::memento::replay_into
@@ -5278,6 +5284,7 @@ recording::global::replay_into (replayer *r)
 				 playback_string (m_name),
 				 m_flags,
 				 m_string_attributes,
+				 m_attributes,
 				 m_readonly)
     : r->new_global (playback_location (r, m_loc),
 		     m_kind,
@@ -5285,6 +5292,7 @@ recording::global::replay_into (replayer *r)
 		     playback_string (m_name),
 		     m_flags,
 		     m_string_attributes,
+		     m_attributes,
 		     m_readonly);
 
   if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
@@ -5353,6 +5361,13 @@ recording::global::write_to_dump (dump &d)
     if (attribute)
       d.write ("__attribute(%s(\"%s\"))__\n", attribute, value.c_str());
   }
+  for (auto name: m_attributes)
+  {
+    const char* attribute = variable_attribute_to_string (name);
+
+    if (attribute)
+      d.write ("__attribute (%s)__\n", attribute);
+  }
   d.write ("%s %s",
 	   m_type->get_debug_string (),
 	   get_debug_string ());
@@ -5425,6 +5440,7 @@ static const char * const tls_model_enum_strings[] = {
 
 static const char * const gcc_jit_variable_attribute_enum_strings[] = {
   "GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY",
+  "GCC_JIT_VARIABLE_ATTRIBUTE_WEAK",
 };
 
 void
@@ -5462,6 +5478,10 @@ recording::global::write_reproducer (reproducer &r)
 	    gcc_jit_variable_attribute_enum_strings[std::get<0>(attribute)],
 	    std::get<1>(attribute).c_str());
 
+  for (auto attribute: m_attributes)
+    r.write ("  gcc_jit_lvalue_add_attribute (%s, %s);\n", id,
+	     gcc_jit_variable_attribute_enum_strings[attribute]);
+
   if (m_readonly)
     r.write ("  gcc_jit_global_set_readonly (%s /* gcc_jit_lvalue *lvalue */);\n",
      id);
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 4d41faa0446..e7d4d79cfe7 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -1439,7 +1439,8 @@ public:
     m_reg_name (NULL),
     m_tls_model (GCC_JIT_TLS_MODEL_NONE),
     m_alignment (0),
-    m_string_attributes ()
+    m_string_attributes (),
+    m_attributes ()
   {}
 
   playback::lvalue *
@@ -1461,6 +1462,7 @@ public:
   const char *access_as_rvalue (reproducer &r) override;
 
   void add_string_attribute (gcc_jit_variable_attribute attribute, const char* value);
+  void add_attribute (gcc_jit_variable_attribute attribute);
 
   bool get_readonly () const
   {
@@ -1488,6 +1490,7 @@ protected:
   unsigned m_alignment;
   std::vector<std::pair<gcc_jit_variable_attribute,
 	      std::string>> m_string_attributes;
+  std::vector<gcc_jit_variable_attribute> m_attributes;
   bool m_readonly = false;
 };
 
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 33369447074..01e9f2875cd 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -4603,6 +4603,24 @@ gcc_jit_extended_asm_as_object (gcc_jit_extended_asm *ext_asm)
    gcc::jit::recording::extended_asm::set_volatile_flag, in
    jit-recording.cc.  */
 
+void
+gcc_jit_lvalue_add_attribute (gcc_jit_lvalue *variable,
+			      gcc_jit_variable_attribute attribute)
+{
+  RETURN_IF_FAIL (variable, NULL, NULL, "NULL variable");
+  RETURN_IF_FAIL (variable->is_global () || variable->is_local (),
+		  NULL,
+		  NULL,
+		  "variable should be a variable");
+  RETURN_IF_FAIL ((attribute >= 0
+	&& attribute < GCC_JIT_VARIABLE_ATTRIBUTE_MAX),
+	NULL,
+	NULL,
+	"attribute should be a `gcc_jit_variable_attribute` enum value");
+
+  variable->add_attribute (attribute);
+}
+
 void
 gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm *ext_asm,
 					int flag)
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index a5855100793..6628e619d8b 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -2199,6 +2199,7 @@ gcc_jit_function_add_integer_array_attribute (
 enum gcc_jit_variable_attribute
 {
   GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY,
+  GCC_JIT_VARIABLE_ATTRIBUTE_WEAK,
 
   /* Maximum value of this enum, should always be last. */
   GCC_JIT_VARIABLE_ATTRIBUTE_MAX,
@@ -2210,6 +2211,13 @@ gcc_jit_lvalue_add_string_attribute (gcc_jit_lvalue *variable,
 				     enum gcc_jit_variable_attribute attribute,
 				     const char* value);
 
+/* Add an attribute to a variable.  */
+extern void
+gcc_jit_lvalue_add_attribute (gcc_jit_lvalue *variable,
+			      enum gcc_jit_variable_attribute attribute);
+
+#define LIBGCCJIT_HAVE_gcc_jit_lvalue_add_attribute
+
 extern void
 gcc_jit_context_set_output_ident (gcc_jit_context *ctxt,
 				  const char* output_ident);
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 4662ca4b3c0..3cc51810554 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -334,3 +334,8 @@ LIBGCCJIT_ABI_35 {
     gcc_jit_target_info_arch;
     gcc_jit_target_info_supports_target_dependent_type;
 } LIBGCCJIT_ABI_34;
+
+LIBGCCJIT_ABI_36 {
+  global:
+    gcc_jit_lvalue_add_attribute;
+} LIBGCCJIT_ABI_35;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4aa18e3b767..f72c1ccd131 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -474,6 +474,9 @@
 /* test-weak-attribute.c: This can't be in the testcases array as it
    doesn't have a verify_code implementation.  */
 
+/* test-weak-var-attribute.c: This can't be in the testcases array as it
+   doesn't have a verify_code implementation.  */
+
 /* test-vector-perm.c */
 #define create_code create_code_vector_perm
 #define verify_code verify_code_vector_perm
diff --git a/gcc/testsuite/jit.dg/test-weak-var-attribute.c b/gcc/testsuite/jit.dg/test-weak-var-attribute.c
new file mode 100644
index 00000000000..2c1dc96556c
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-weak-var-attribute.c
@@ -0,0 +1,31 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#define TEST_COMPILING_TO_FILE
+#define OUTPUT_KIND      GCC_JIT_OUTPUT_KIND_ASSEMBLER
+#define OUTPUT_FILENAME  "output-of-test-weak-var-attribute.c.s"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+__attribute__ ((weak))
+int var;
+  */
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_lvalue *variable =
+    gcc_jit_context_new_global (ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, int_type,
+      "my_var");
+  gcc_jit_lvalue_add_attribute (variable, GCC_JIT_VARIABLE_ATTRIBUTE_WEAK);
+}
+
+/* { dg-final { jit-verify-output-file-was-created "" } } */
+/* Check that the attribute was applied correctly */
+/* { dg-final { jit-verify-assembler-output ".weak\\s+my_var" { target { ! *-*-darwin* } } } } */

Reply via email to