diff gcc/go/go-gcc.cc @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/go/go-gcc.cc	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/go/go-gcc.cc	Thu Feb 13 11:34:05 2020 +0900
@@ -1,5 +1,5 @@
 // go-gcc.cc -- Go frontend to gcc IR.
-// Copyright (C) 2011-2018 Free Software Foundation, Inc.
+// Copyright (C) 2011-2020 Free Software Foundation, Inc.
 // Contributed by Ian Lance Taylor, Google.
 
 // This file is part of GCC.
@@ -25,6 +25,7 @@
 #include <gmp.h>
 
 #include "tree.h"
+#include "opts.h"
 #include "fold-const.h"
 #include "stringpool.h"
 #include "stor-layout.h"
@@ -482,9 +483,7 @@
 
   Bfunction*
   function(Btype* fntype, const std::string& name, const std::string& asm_name,
-           bool is_visible, bool is_declaration, bool is_inlinable,
-           bool disable_split_stack, bool does_not_return,
-	   bool in_unique_section, Location);
+	   unsigned int flags, Location);
 
   Bstatement*
   function_defer_statement(Bfunction* function, Bexpression* undefer,
@@ -605,7 +604,25 @@
 						NULL_TREE),
 		       false, false);
 
-  // Used by runtime/internal/sys.
+  // We use __builtin_memmove for copying data.
+  this->define_builtin(BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove",
+		       build_function_type_list(void_type_node,
+						ptr_type_node,
+						const_ptr_type_node,
+						size_type_node,
+						NULL_TREE),
+		       false, false);
+
+  // We use __builtin_memset for zeroing data.
+  this->define_builtin(BUILT_IN_MEMSET, "__builtin_memset", "memset",
+		       build_function_type_list(void_type_node,
+						ptr_type_node,
+						integer_type_node,
+						size_type_node,
+						NULL_TREE),
+		       false, false);
+
+  // Used by runtime/internal/sys and math/bits.
   this->define_builtin(BUILT_IN_CTZ, "__builtin_ctz", "ctz",
 		       build_function_type_list(integer_type_node,
 						unsigned_type_node,
@@ -616,6 +633,31 @@
 						long_long_unsigned_type_node,
 						NULL_TREE),
 		       true, false);
+  this->define_builtin(BUILT_IN_CLZ, "__builtin_clz", "clz",
+		       build_function_type_list(integer_type_node,
+						unsigned_type_node,
+						NULL_TREE),
+		       true, false);
+  this->define_builtin(BUILT_IN_CLZLL, "__builtin_clzll", "clzll",
+		       build_function_type_list(integer_type_node,
+						long_long_unsigned_type_node,
+						NULL_TREE),
+		       true, false);
+  this->define_builtin(BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount",
+		       build_function_type_list(integer_type_node,
+						unsigned_type_node,
+						NULL_TREE),
+		       true, false);
+  this->define_builtin(BUILT_IN_POPCOUNTLL, "__builtin_popcountll", "popcountll",
+		       build_function_type_list(integer_type_node,
+						long_long_unsigned_type_node,
+						NULL_TREE),
+		       true, false);
+  this->define_builtin(BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16",
+		       build_function_type_list(uint16_type_node,
+						uint16_type_node,
+						NULL_TREE),
+		       true, false);
   this->define_builtin(BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32",
 		       build_function_type_list(uint32_type_node,
 						uint32_type_node,
@@ -736,8 +778,9 @@
   this->define_builtin(BUILT_IN_RETURN_ADDRESS, "__builtin_return_address",
 		       NULL, t, false, false);
 
-  // The runtime calls __builtin_frame_address for runtime.getcallersp.
-  this->define_builtin(BUILT_IN_FRAME_ADDRESS, "__builtin_frame_address",
+  // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp.
+  t = build_function_type_list(ptr_type_node, NULL_TREE);
+  this->define_builtin(BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa",
 		       NULL, t, false, false);
 
   // The runtime calls __builtin_extract_return_addr when recording
@@ -762,11 +805,118 @@
 							NULL_TREE),
 		       false, false);
 
-  // The compiler uses __builtin_unreachable for cases that can not
+  // The compiler uses __builtin_unreachable for cases that cannot
   // occur.
   this->define_builtin(BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL,
 		       build_function_type(void_type_node, void_list_node),
 		       true, true);
+
+  // We provide some atomic functions.
+  t = build_function_type_list(uint32_type_node,
+                               ptr_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(uint64_type_node,
+                               ptr_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(void_type_node,
+                               ptr_type_node,
+                               uint32_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(void_type_node,
+                               ptr_type_node,
+                               uint64_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(uint32_type_node,
+                               ptr_type_node,
+                               uint32_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(uint64_type_node,
+                               ptr_type_node,
+                               uint64_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(boolean_type_node,
+                               ptr_type_node,
+                               ptr_type_node,
+                               uint32_type_node,
+                               boolean_type_node,
+                               integer_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
+                       "__atomic_compare_exchange_4", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(boolean_type_node,
+                               ptr_type_node,
+                               ptr_type_node,
+                               uint64_type_node,
+                               boolean_type_node,
+                               integer_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
+                       "__atomic_compare_exchange_8", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(uint32_type_node,
+                               ptr_type_node,
+                               uint32_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(uint64_type_node,
+                               ptr_type_node,
+                               uint64_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(unsigned_char_type_node,
+                               ptr_type_node,
+                               unsigned_char_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", NULL,
+                       t, false, false);
+  this->define_builtin(BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", NULL,
+                       t, false, false);
+
+  t = build_function_type_list(unsigned_char_type_node,
+                               ptr_type_node,
+                               unsigned_char_type_node,
+                               integer_type_node,
+                               NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL,
+                       t, false, false);
+  this->define_builtin(BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL,
+                       t, false, false);
 }
 
 // Get an unnamed integer type.
@@ -911,7 +1061,7 @@
   if (result == error_mark_node)
     return this->error_type();
 
-  // The libffi library can not represent a zero-sized object.  To
+  // The libffi library cannot represent a zero-sized object.  To
   // avoid causing confusion on 32-bit SPARC, we treat a function that
   // returns a zero-sized value as returning void.  That should do no
   // harm since there is no actual value to be returned.  See
@@ -1051,6 +1201,7 @@
     }
   gcc_assert(TREE_CODE(tt) == POINTER_TYPE);
   TREE_TYPE(pt) = TREE_TYPE(tt);
+  TYPE_CANONICAL(pt) = TYPE_CANONICAL(tt);
   if (TYPE_NAME(pt) != NULL_TREE)
     {
       // Build the data structure gcc wants to see for a typedef.
@@ -1082,6 +1233,12 @@
 			     get_identifier_from_string(name),
 			     ret);
       TYPE_NAME(ret) = decl;
+
+      // The struct type that eventually replaces this placeholder will require
+      // structural equality. The placeholder must too, so that the requirement
+      // for structural equality propagates to references that are constructed
+      // before the replacement occurs.
+      SET_TYPE_STRUCTURAL_EQUALITY(ret);
     }
   return this->make_type(ret);
 }
@@ -1100,9 +1257,13 @@
   if (TYPE_NAME(t) != NULL_TREE)
     {
       // Build the data structure gcc wants to see for a typedef.
-      tree copy = build_variant_type_copy(t);
+      tree copy = build_distinct_type_copy(t);
       TYPE_NAME(copy) = NULL_TREE;
       DECL_ORIGINAL_TYPE(TYPE_NAME(t)) = copy;
+      TYPE_SIZE(copy) = NULL_TREE;
+      Btype* bc = this->make_type(copy);
+      this->fill_in_struct(bc, fields);
+      delete bc;
     }
 
   return r->get_tree() != error_mark_node;
@@ -2245,9 +2406,9 @@
     {
       if (pc->empty())
 	{
-	  source_location loc = (*ps != NULL
-                                 ? EXPR_LOCATION((*ps)->get_tree())
-                                 : UNKNOWN_LOCATION);
+	  location_t loc = (*ps != NULL
+			    ? EXPR_LOCATION((*ps)->get_tree())
+			    : UNKNOWN_LOCATION);
 	  tree label = create_artificial_label(loc);
 	  tree c = build_case_label(NULL_TREE, NULL_TREE, label);
 	  append_to_statement_list(c, &stmt_list);
@@ -2261,7 +2422,7 @@
 	      tree t = (*pcv)->get_tree();
 	      if (t == error_mark_node)
 		return this->error_statement();
-	      source_location loc = EXPR_LOCATION(t);
+	      location_t loc = EXPR_LOCATION(t);
 	      tree label = create_artificial_label(loc);
 	      tree c = build_case_label((*pcv)->get_tree(), NULL_TREE, label);
 	      append_to_statement_list(c, &stmt_list);
@@ -3047,10 +3208,8 @@
 
 Bfunction*
 Gcc_backend::function(Btype* fntype, const std::string& name,
-                      const std::string& asm_name, bool is_visible,
-                      bool is_declaration, bool is_inlinable,
-                      bool disable_split_stack, bool does_not_return,
-		      bool in_unique_section, Location location)
+                      const std::string& asm_name, unsigned int flags,
+		      Location location)
 {
   tree functype = fntype->get_tree();
   if (functype != error_mark_node)
@@ -3065,9 +3224,9 @@
   tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype);
   if (! asm_name.empty())
     SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
-  if (is_visible)
+  if ((flags & function_is_visible) != 0)
     TREE_PUBLIC(decl) = 1;
-  if (is_declaration)
+  if ((flags & function_is_declaration) != 0)
     DECL_EXTERNAL(decl) = 1;
   else
     {
@@ -3079,17 +3238,58 @@
       DECL_CONTEXT(resdecl) = decl;
       DECL_RESULT(decl) = resdecl;
     }
-  if (!is_inlinable)
+  if ((flags & function_is_inlinable) == 0)
     DECL_UNINLINABLE(decl) = 1;
-  if (disable_split_stack)
+  if ((flags & function_no_split_stack) != 0)
     {
       tree attr = get_identifier ("no_split_stack");
       DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
     }
-  if (does_not_return)
+  if ((flags & function_does_not_return) != 0)
     TREE_THIS_VOLATILE(decl) = 1;
-  if (in_unique_section)
+  if ((flags & function_in_unique_section) != 0)
     resolve_unique_section(decl, 0, 1);
+  if ((flags & function_only_inline) != 0)
+    {
+      TREE_PUBLIC (decl) = 1;
+      DECL_EXTERNAL(decl) = 1;
+      DECL_DECLARED_INLINE_P(decl) = 1;
+    }
+
+  // Optimize thunk functions for size.  A thunk created for a defer
+  // statement that may call recover looks like:
+  //     if runtime.setdeferretaddr(L1) {
+  //         goto L1
+  //     }
+  //     realfn()
+  // L1:
+  // The idea is that L1 should be the address to which realfn
+  // returns.  This only works if this little function is not over
+  // optimized.  At some point GCC started duplicating the epilogue in
+  // the basic-block reordering pass, breaking this assumption.
+  // Optimizing the function for size avoids duplicating the epilogue.
+  // This optimization shouldn't matter for any thunk since all thunks
+  // are small.
+  size_t pos = name.find("..thunk");
+  if (pos != std::string::npos)
+    {
+      for (pos += 7; pos < name.length(); ++pos)
+	{
+	  if (name[pos] < '0' || name[pos] > '9')
+	    break;
+	}
+      if (pos == name.length())
+	{
+	  struct cl_optimization cur_opts;
+	  cl_optimization_save(&cur_opts, &global_options);
+	  global_options.x_optimize_size = 1;
+	  global_options.x_optimize_fast = 0;
+	  global_options.x_optimize_debug = 0;
+	  DECL_FUNCTION_SPECIFIC_OPTIMIZATION(decl) =
+	    build_optimization_node(&global_options);
+	  cl_optimization_restore(&global_options, &cur_opts);
+	}
+    }
 
   go_preserve_from_gc(decl);
   return new Bfunction(decl);
@@ -3250,7 +3450,8 @@
       if (decl != error_mark_node)
         {
           go_preserve_from_gc(decl);
-          gimplify_function_tree(decl);
+	  if (DECL_STRUCT_FUNCTION(decl) == NULL)
+	    allocate_struct_function(decl, false);
           cgraph_node::finalize_function(decl, true);
 
           defs[i] = decl;