public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Go patch committed: Pass type information to heap allocations
@ 2014-10-20 19:16 Ian Taylor
  0 siblings, 0 replies; only message in thread
From: Ian Taylor @ 2014-10-20 19:16 UTC (permalink / raw)
  To: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 397 bytes --]

This patch by Chris Manghane passes type information to
compiler-generated heap allocations in gccgo.  This gives us precise
type information for much of the gccgo heap, and means that garbage
collection is much more precise and less prone to errors due to
mistaking integer or float values as pointers.  Bootstrapped and ran
Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

[-- Attachment #2: foo.txt --]
[-- Type: text/plain, Size: 9136 bytes --]

diff -r f6e937cbbe5a go/expressions.cc
--- a/go/expressions.cc	Mon Oct 20 11:04:12 2014 -0700
+++ b/go/expressions.cc	Mon Oct 20 12:04:16 2014 -0700
@@ -12170,7 +12170,7 @@
   { return this->vals_ == NULL ? 0 : this->vals_->size(); }
 
 protected:
-  int
+  virtual int
   do_traverse(Traverse* traverse);
 
   bool
@@ -12495,11 +12495,33 @@
     : Array_construction_expression(EXPRESSION_SLICE_CONSTRUCTION,
 				    type, indexes, vals, location),
       valtype_(NULL)
-  { go_assert(type->is_slice_type()); }
+  {
+    go_assert(type->is_slice_type());
+
+    mpz_t lenval;
+    Expression* length;
+    if (vals == NULL || vals->empty())
+      mpz_init_set_ui(lenval, 0);
+    else
+      {
+	if (this->indexes() == NULL)
+	  mpz_init_set_ui(lenval, vals->size());
+	else
+	  mpz_init_set_ui(lenval, indexes->back() + 1);
+      }
+    Type* int_type = Type::lookup_integer_type("int");
+    length = Expression::make_integer(&lenval, int_type, location);
+    mpz_clear(lenval);
+    Type* element_type = type->array_type()->element_type();
+    this->valtype_ = Type::make_array_type(element_type, length);
+  }
 
  protected:
   // Note that taking the address of a slice literal is invalid.
 
+  int
+  do_traverse(Traverse* traverse);
+
   Expression*
   do_copy()
   {
@@ -12518,6 +12540,19 @@
   Type* valtype_;
 };
 
+// Traversal.
+
+int
+Slice_construction_expression::do_traverse(Traverse* traverse)
+{
+  if (this->Array_construction_expression::do_traverse(traverse)
+      == TRAVERSE_EXIT)
+    return TRAVERSE_EXIT;
+  if (Type::traverse(this->valtype_, traverse) == TRAVERSE_EXIT)
+    return TRAVERSE_EXIT;
+  return TRAVERSE_CONTINUE;
+}
+
 // Return the backend representation for constructing a slice.
 
 Bexpression*
@@ -12532,24 +12567,7 @@
 
   Location loc = this->location();
   Type* element_type = array_type->element_type();
-  if (this->valtype_ == NULL)
-    {
-      mpz_t lenval;
-      Expression* length;
-      if (this->vals() == NULL || this->vals()->empty())
-        mpz_init_set_ui(lenval, 0);
-      else
-        {
-          if (this->indexes() == NULL)
-            mpz_init_set_ui(lenval, this->vals()->size());
-          else
-            mpz_init_set_ui(lenval, this->indexes()->back() + 1);
-        }
-      Type* int_type = Type::lookup_integer_type("int");
-      length = Expression::make_integer(&lenval, int_type, loc);
-      mpz_clear(lenval);
-      this->valtype_ = Type::make_array_type(element_type, length);
-    }
+  go_assert(this->valtype_ != NULL);
 
   Expression_list* vals = this->vals();
   if (this->vals() == NULL || this->vals()->empty())
@@ -14028,7 +14046,7 @@
  protected:
   Type*
   do_type()
-  { return Type::make_pointer_type(Type::make_void_type()); }
+  { return Type::lookup_integer_type("uintptr"); }
 
   bool
   do_is_immutable() const
diff -r f6e937cbbe5a go/go.cc
--- a/go/go.cc	Mon Oct 20 11:04:12 2014 -0700
+++ b/go/go.cc	Mon Oct 20 12:04:16 2014 -0700
@@ -96,9 +96,6 @@
   // Create function descriptors as needed.
   ::gogo->create_function_descriptors();
 
-  // Write out queued up functions for hash and comparison of types.
-  ::gogo->write_specific_type_functions();
-
   // Now that we have seen all the names, verify that types are
   // correct.
   ::gogo->verify_types();
@@ -130,6 +127,9 @@
   // Convert complicated go and defer statements into simpler ones.
   ::gogo->simplify_thunk_statements();
 
+  // Write out queued up functions for hash and comparison of types.
+  ::gogo->write_specific_type_functions();
+
   // Flatten the parse tree.
   ::gogo->flatten();
 
diff -r f6e937cbbe5a go/gogo.cc
--- a/go/gogo.cc	Mon Oct 20 11:04:12 2014 -0700
+++ b/go/gogo.cc	Mon Oct 20 12:04:16 2014 -0700
@@ -4196,21 +4196,18 @@
 Expression*
 Gogo::allocate_memory(Type* type, Location location)
 {
-  Btype* btype = type->get_backend(this);
-  size_t size = this->backend()->type_size(btype);
-  mpz_t size_val;
-  mpz_init_set_ui(size_val, size);
-  Type* uintptr = Type::lookup_integer_type("uintptr");
-  Expression* size_expr =
-    Expression::make_integer(&size_val, uintptr, location);
-
-  // If the package imports unsafe, then it may play games with
-  // pointers that look like integers.
+  Expression* td = Expression::make_type_descriptor(type, location);
+  Expression* size =
+    Expression::make_type_info(type, Expression::TYPE_INFO_SIZE);
+
+  // If this package imports unsafe, then it may play games with
+  // pointers that look like integers.  We should be able to determine
+  // whether or not to use new pointers in libgo/go-new.c.  FIXME.
   bool use_new_pointers = this->imported_unsafe_ || type->has_pointer();
   return Runtime::make_call((use_new_pointers
 			     ? Runtime::NEW
 			     : Runtime::NEW_NOPOINTERS),
-                            location, 1, size_expr);
+			    location, 2, td, size);
 }
 
 // Traversal class used to check for return statements.
diff -r f6e937cbbe5a go/runtime.cc
--- a/go/runtime.cc	Mon Oct 20 11:04:12 2014 -0700
+++ b/go/runtime.cc	Mon Oct 20 12:04:16 2014 -0700
@@ -82,6 +82,7 @@
 runtime_function_type(Runtime_function_type bft)
 {
   go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES);
+  Type* any = Type::make_pointer_type(Type::make_void_type());
   if (runtime_function_types[bft] == NULL)
     {
       const Location bloc = Linemap::predeclared_location();
@@ -145,13 +146,11 @@
 	  break;
 
 	case RFT_SLICE:
-	  t = Type::make_array_type(Type::make_void_type(), NULL);
+	  t = Type::make_array_type(any, NULL);
 	  break;
 
 	case RFT_MAP:
-	  t = Type::make_map_type(Type::make_void_type(),
-				  Type::make_void_type(),
-				  bloc);
+	  t = Type::make_map_type(any, any, bloc);
 	  break;
 
 	case RFT_MAPITER:
@@ -159,7 +158,7 @@
 	  break;
 
 	case RFT_CHAN:
-	  t = Type::make_channel_type(true, true, Type::make_void_type());
+	  t = Type::make_channel_type(true, true, any);
 	  break;
 
 	case RFT_IFACE:
diff -r f6e937cbbe5a go/runtime.def
--- a/go/runtime.def	Mon Oct 20 11:04:12 2014 -0700
+++ b/go/runtime.def	Mon Oct 20 12:04:16 2014 -0700
@@ -221,10 +221,10 @@
 
 
 // Allocate memory.
-DEF_GO_RUNTIME(NEW, "__go_new", P1(UINTPTR), R1(POINTER))
+DEF_GO_RUNTIME(NEW, "__go_new", P2(TYPE, UINTPTR), R1(POINTER))
 
 // Allocate memory which can not contain pointers.
-DEF_GO_RUNTIME(NEW_NOPOINTERS, "__go_new_nopointers", P1(UINTPTR), R1(POINTER))
+DEF_GO_RUNTIME(NEW_NOPOINTERS, "__go_new_nopointers", P2(TYPE, UINTPTR), R1(POINTER))
 
 
 // Start a new goroutine.
diff -r f6e937cbbe5a go/statements.cc
--- a/go/statements.cc	Mon Oct 20 11:04:12 2014 -0700
+++ b/go/statements.cc	Mon Oct 20 12:04:16 2014 -0700
@@ -1878,7 +1878,7 @@
 
   mpz_t oval;
   mpz_init_set_ui(oval, 1UL);
-  Expression* oexpr = Expression::make_integer(&oval, NULL, loc);
+  Expression* oexpr = Expression::make_integer(&oval, this->expr_->type(), loc);
   mpz_clear(oval);
 
   Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
diff -r f6e937cbbe5a go/types.cc
--- a/go/types.cc	Mon Oct 20 11:04:12 2014 -0700
+++ b/go/types.cc	Mon Oct 20 12:04:16 2014 -0700
@@ -1244,6 +1244,25 @@
       phash = &ins.first->second;
     }
 
+  // The type descriptor symbol for the unsafe.Pointer type is defined in
+  // libgo/go-unsafe-pointer.c, so we just return a reference to that
+  // symbol if necessary.
+  if (this->is_unsafe_pointer_type())
+    {
+      Location bloc = Linemap::predeclared_location();
+
+      Type* td_type = Type::make_type_descriptor_type();
+      Btype* td_btype = td_type->get_backend(gogo);
+      this->type_descriptor_var_ =
+	gogo->backend()->immutable_struct_reference("__go_tdn_unsafe.Pointer",
+						    td_btype,
+						    bloc);
+
+      if (phash != NULL)
+	*phash = this->type_descriptor_var_;
+      return;
+    }
+
   std::string var_name = this->type_descriptor_var_name(gogo, nt);
 
   // Build the contents of the type descriptor.
@@ -1540,7 +1559,7 @@
 				       "hash", uint32_type,
 				       "hashfn", uintptr_type,
 				       "equalfn", uintptr_type,
-				       "gc", unsafe_pointer_type,
+				       "gc", uintptr_type,
 				       "string", pointer_string_type,
 				       "", pointer_uncommon_type,
 				       "ptrToThis",
@@ -6027,7 +6046,6 @@
   tref->set_is_lvalue();
   s = Statement::make_assignment_operation(OPERATOR_PLUSEQ, tref, ele_size,
 					   bloc);
-
   Block* statements = gogo->finish_block(bloc);
 
   for_range->add_statements(statements);
diff -r f6e937cbbe5a libgo/runtime/go-new.c
--- a/libgo/runtime/go-new.c	Mon Oct 20 11:04:12 2014 -0700
+++ b/libgo/runtime/go-new.c	Mon Oct 20 12:04:16 2014 -0700
@@ -10,13 +10,17 @@
 #include "malloc.h"
 
 void *
-__go_new (uintptr_t size)
+__go_new (const struct __go_type_descriptor *td, uintptr_t size)
 {
-  return runtime_mallocgc (size, 0, 0);
+  return runtime_mallocgc (size,
+			   (uintptr) td | TypeInfo_SingleObject,
+			   0);
 }
 
 void *
-__go_new_nopointers (uintptr_t size)
+__go_new_nopointers (const struct __go_type_descriptor *td,  uintptr_t size)
 {
-  return runtime_mallocgc (size, 0, FlagNoScan);
+  return runtime_mallocgc (size,
+			   (uintptr) td | TypeInfo_SingleObject,
+			   FlagNoScan);
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-10-20 19:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-20 19:16 Go patch committed: Pass type information to heap allocations Ian Taylor

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).