This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gccgo] Change string data type


This patch changes the string data type to just be a pointer and a
length, rather than a length and bytes allocated in a single memory
block.  This permits sharing of string constants and makes string
slicing much more efficient.  It also matches the data structure used
by the other Go compiler, which is convenient for SWIG.  Committed to
gccgo branch.

Ian

diff -r 581c6ed0cd02 go/expressions.cc
--- a/go/expressions.cc	Tue Jun 01 12:43:04 2010 -0700
+++ b/go/expressions.cc	Tue Jun 01 21:58:24 2010 -0700
@@ -9246,7 +9246,7 @@
   tree start_tree = this->start_->get_tree(context);
   if (start_tree == error_mark_node)
     return error_mark_node;
-  start_tree = fold_convert(sizetype, start_tree);
+  start_tree = fold_convert(integer_type_node, start_tree);
 
   tree string_type = TREE_TYPE(string_tree);
 
@@ -9273,7 +9273,8 @@
 
       tree bytes_tree = String_type::bytes_tree(context->gogo(), string_tree);
       tree ptr = fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(bytes_tree),
-			     bytes_tree, start_tree);
+			     bytes_tree,
+			     fold_convert(sizetype, start_tree));
       tree index = build_fold_indirect_ref(ptr);
 
       return fold_build2(COMPOUND_EXPR, TREE_TYPE(index),
@@ -9292,7 +9293,7 @@
 	  if (end_tree == error_mark_node)
 	    return error_mark_node;
 	}
-      end_tree = fold_convert(sizetype, end_tree);
+      end_tree = fold_convert(integer_type_node, end_tree);
       static tree strslice_fndecl;
       return Gogo::call_builtin(&strslice_fndecl,
 				this->location(),
@@ -9301,9 +9302,9 @@
 				string_type,
 				string_type,
 				string_tree,
-				sizetype,
+				integer_type_node,
 				start_tree,
-				sizetype,
+				integer_type_node,
 				end_tree);
     }
 }
diff -r 581c6ed0cd02 go/gogo-tree.cc
--- a/go/gogo-tree.cc	Tue Jun 01 12:43:04 2010 -0700
+++ b/go/gogo-tree.cc	Tue Jun 01 21:58:24 2010 -0700
@@ -538,14 +538,14 @@
 	  continue;
 	}
 
-      // Don't try to output anything for constants which still have
-      // abstract type.
+      // There is nothing useful we can output for constants which
+      // have ideal or non-integeral type.
       if (no->is_const())
 	{
 	  Type* type = no->const_value()->type();
 	  if (type == NULL)
 	    type = no->const_value()->expr()->type();
-	  if (type->is_abstract())
+	  if (type->is_abstract() || type->integer_type() == NULL)
 	    {
 	      --i;
 	      --count;
@@ -767,12 +767,21 @@
 	      expr_tree = fold_convert(type->get_tree(gogo), expr_tree);
 	    if (expr_tree == error_mark_node)
 	      decl = error_mark_node;
-	    else
+	    else if (INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
 	      {
 		decl = build_decl(named_constant->location(), CONST_DECL,
 				  name, TREE_TYPE(expr_tree));
 		DECL_INITIAL(decl) = expr_tree;
 		TREE_CONSTANT(decl) = 1;
+		TREE_READONLY(decl) = 1;
+	      }
+	    else
+	      {
+		// A CONST_DECL is only for an enum constant, so we
+		// shouldn't use for non-integral types.  Instead we
+		// just return the constant itself, rather than a
+		// decl.
+		decl = expr_tree;
 	      }
 	  }
       }
@@ -1502,7 +1511,8 @@
        ++pv)
     {
       if ((!(*pv)->is_variable() || !(*pv)->var_value()->is_parameter())
-	  && !(*pv)->is_result_variable())
+	  && !(*pv)->is_result_variable()
+	  && !(*pv)->is_const())
 	{
 	  tree var = (*pv)->get_tree(gogo, context->function());
 	  if (var != error_mark_node && TREE_TYPE(var) != error_mark_node)
@@ -1818,66 +1828,33 @@
 Gogo::go_string_constant_tree(const std::string& val)
 {
   tree string_type = Type::make_string_type()->get_tree(this);
-  tree struct_type = TREE_TYPE(string_type);
-
-  // Build a version of STRING_TYPE with the length of the array
-  // specified.
-  tree new_struct_type = make_node(RECORD_TYPE);
-
-  tree field = copy_node(TYPE_FIELDS(struct_type));
-  DECL_CONTEXT(field) = new_struct_type;
-  TYPE_FIELDS(new_struct_type) = field;
-
-  if (!val.empty())
-    {
-      field = copy_node(TREE_CHAIN(TYPE_FIELDS(struct_type)));
-      DECL_CONTEXT(field) = new_struct_type;
-      tree index_type = build_index_type(size_int(val.length() - 1));
-      TREE_TYPE(field) = build_array_type(TREE_TYPE(TREE_TYPE(field)),
-					  index_type);
-      TREE_CHAIN(TYPE_FIELDS(new_struct_type)) = field;
-    }
-
-  layout_type(new_struct_type);
 
   VEC(constructor_elt, gc)* init = VEC_alloc(constructor_elt, gc, 2);
 
   constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = TYPE_FIELDS(new_struct_type);
-  elt->value = size_int(val.length());
-
-  if (!val.empty())
-    {
-      elt = VEC_quick_push(constructor_elt, init, NULL);
-      elt->index = TREE_CHAIN(TYPE_FIELDS(new_struct_type));
-      elt->value = Gogo::string_constant_tree(val);
-    }
-
-  tree constructor = build_constructor(new_struct_type, init);
+  tree field = TYPE_FIELDS(string_type);
+  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__data") == 0);
+  elt->index = field;
+  tree str = Gogo::string_constant_tree(val);
+  elt->value = fold_convert(TREE_TYPE(field),
+			    build_fold_addr_expr(str));
+
+  elt = VEC_quick_push(constructor_elt, init, NULL);
+  field = TREE_CHAIN(field);
+  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__length") == 0);
+  elt->index = field;
+  elt->value = build_int_cst_type(TREE_TYPE(field), val.length());
+
+  tree constructor = build_constructor(string_type, init);
   TREE_READONLY(constructor) = 1;
   TREE_CONSTANT(constructor) = 1;
 
-  // FIXME: We won't merge string constants between object files.
-  tree decl = build_decl(UNKNOWN_LOCATION, VAR_DECL,
-			 create_tmp_var_name("S"), new_struct_type);
-  DECL_EXTERNAL(decl) = 0;
-  TREE_PUBLIC(decl) = 0;
-  TREE_USED(decl) = 1;
-  TREE_READONLY(decl) = 1;
-  TREE_CONSTANT(decl) = 1;
-  TREE_STATIC(decl) = 1;
-  DECL_ARTIFICIAL(decl) = 1;
-  DECL_INITIAL(decl) = constructor;
-  rest_of_decl_compilation(decl, 1, 0);
-
-  return fold_convert(string_type, build_fold_addr_expr(decl));
+  return constructor;
 }
 
 // Return a tree for a pointer to a Go string constant.  This is only
 // used for type descriptors, so we return a pointer to a constant
-// decl.  FIXME: In gc a string is a two word value, so it makes sense
-// for code to work with pointers to strings.  We should adapt the
-// code or something.
+// decl.
 
 tree
 Gogo::ptr_go_string_constant_tree(const std::string& val)
diff -r 581c6ed0cd02 go/types.cc
--- a/go/types.cc	Tue Jun 01 12:43:04 2010 -0700
+++ b/go/types.cc	Tue Jun 01 21:58:24 2010 -0700
@@ -1437,45 +1437,18 @@
 
 // Class String_type.
 
-// Return the tree for String_type.  We represent strings as a pointer
-// to a struct.
-//   struct __go_string { size_t __length; unsigned char __data[]; };
+// Return the tree for String_type.  A string is a struct with two
+// fields: a pointer to the characters and a length.
 
 tree
 String_type::do_get_tree(Gogo*)
 {
   static tree struct_type;
-  if (struct_type == NULL_TREE)
-    {
-      struct_type = make_node(RECORD_TYPE);
-
-      tree name = get_identifier("__length");
-      tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL, name, sizetype);
-      DECL_CONTEXT(field) = struct_type;
-      TYPE_FIELDS(struct_type) = field;
-      tree last_field = field;
-
-      name = get_identifier("__data");
-      tree t = build_qualified_type(unsigned_char_type_node, TYPE_QUAL_CONST);
-      t = build_array_type(t, NULL);
-      field = build_decl(BUILTINS_LOCATION, FIELD_DECL, name, t);
-      DECL_CONTEXT(field) = struct_type;
-      TREE_CHAIN(last_field) = field;
-
-      layout_type(struct_type);
-
-      go_preserve_from_gc(struct_type);
-
-      // Give the struct a name for better debugging info.
-      name = get_identifier("__go_string");
-      tree type_decl = build_decl(BUILTINS_LOCATION, TYPE_DECL, name,
-				  struct_type);
-      DECL_ARTIFICIAL(type_decl) = 1;
-      TYPE_NAME(struct_type) = type_decl;
-      go_preserve_from_gc(type_decl);
-      rest_of_decl_compilation(type_decl, 1, 0);
-    }
-  return build_pointer_type(struct_type);
+  return Gogo::builtin_struct(&struct_type, "__go_string", NULL_TREE, 2,
+			      "__data",
+			      build_pointer_type(unsigned_char_type_node),
+			      "__length",
+			      integer_type_node);
 }
 
 // Return a tree for the length of STRING.
@@ -1484,21 +1457,12 @@
 String_type::length_tree(Gogo*, tree string)
 {
   tree string_type = TREE_TYPE(string);
-  gcc_assert(POINTER_TYPE_P(string_type));
-  tree struct_type = TREE_TYPE(string_type);
-  gcc_assert(TREE_CODE(struct_type) == RECORD_TYPE);
-  tree length_field = TYPE_FIELDS(struct_type);
+  gcc_assert(TREE_CODE(string_type) == RECORD_TYPE);
+  tree length_field = TREE_CHAIN(TYPE_FIELDS(string_type));
   gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(length_field)),
 		    "__length") == 0);
-
-  string = save_expr(string);
-  return fold_build3(COND_EXPR, sizetype,
-		     fold_build2(EQ_EXPR, boolean_type_node, string,
-				 fold_convert(string_type, null_pointer_node)),
-		     size_zero_node,
-		     fold_build3(COMPONENT_REF, sizetype,
-				 build_fold_indirect_ref(string),
-				 length_field, NULL_TREE));
+  return fold_build3(COMPONENT_REF, integer_type_node, string,
+		     length_field, NULL_TREE);
 }
 
 // Return a tree for a pointer to the bytes of STRING.
@@ -1507,34 +1471,51 @@
 String_type::bytes_tree(Gogo*, tree string)
 {
   tree string_type = TREE_TYPE(string);
-  gcc_assert(POINTER_TYPE_P(string_type));
-  tree struct_type = TREE_TYPE(string_type);
-  gcc_assert(TREE_CODE(struct_type) == RECORD_TYPE);
-  tree bytes_field = TREE_CHAIN(TYPE_FIELDS(struct_type));
+  gcc_assert(TREE_CODE(string_type) == RECORD_TYPE);
+  tree bytes_field = TYPE_FIELDS(string_type);
   gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(bytes_field)),
 		    "__data") == 0);
-
-  string = save_expr(string);
-
-  tree r = fold_build3(COMPONENT_REF, TREE_TYPE(bytes_field),
-		       build_fold_indirect_ref(string),
-		       bytes_field, NULL_TREE);
-  r = build_fold_addr_expr(r);
-  r = fold_convert(Gogo::const_char_pointer_type_tree(), r);
-
-  return fold_build3(COND_EXPR, TREE_TYPE(r),
-		     fold_build2(EQ_EXPR, boolean_type_node, string,
-				 fold_convert(string_type, null_pointer_node)),
-		     fold_convert(TREE_TYPE(r), null_pointer_node),
-		     r);
-}
-
-// We initialize a string to simply a nil pointer.
+  return fold_build3(COMPONENT_REF, TREE_TYPE(bytes_field), string,
+		     bytes_field, NULL_TREE);
+}
+
+// We initialize a string to { NULL, 0 }.
 
 tree
 String_type::do_init_tree(Gogo* gogo, bool is_clear)
 {
-  return is_clear ? NULL : build_int_cst(this->get_tree(gogo), 0);
+  if (is_clear)
+    return NULL_TREE;
+
+  tree type_tree = this->get_tree(gogo);
+  gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE);
+
+  VEC(constructor_elt, gc)* init = VEC_alloc(constructor_elt, gc, 2);
+
+  for (tree field = TYPE_FIELDS(type_tree);
+       field != NULL_TREE;
+       field = TREE_CHAIN(field))
+    {
+      constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
+      elt->index = field;
+      elt->value = fold_convert(TREE_TYPE(field), size_zero_node);
+    }
+
+  tree ret = build_constructor(type_tree, init);
+  TREE_CONSTANT(ret) = 1;
+  return ret;
+}
+
+// Copy a string into the reference count queue.
+
+tree
+String_type::do_set_refcount_queue_entry(Gogo *gogo, Refcounts* refcounts,
+					 Refcount_entry *entry, tree val) const
+{
+  tree ret = refcounts->set_entry_tree(gogo, *entry,
+				       this->bytes_tree(gogo, val));
+  entry->increment();
+  return ret;
 }
 
 // The type descriptor for the string type.
diff -r 581c6ed0cd02 go/types.h
--- a/go/types.h	Tue Jun 01 12:43:04 2010 -0700
+++ b/go/types.h	Tue Jun 01 21:58:24 2010 -0700
@@ -1493,6 +1493,10 @@
   tree
   do_init_tree(Gogo* gogo, bool);
 
+  tree
+  do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
+			      Refcount_entry* entry, tree val) const;
+
   void
   do_type_descriptor_decl(Gogo*, Named_type*, tree*);
 
diff -r 581c6ed0cd02 libgo/runtime/go-byte-array-to-string.c
--- a/libgo/runtime/go-byte-array-to-string.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-byte-array-to-string.c	Tue Jun 01 21:58:24 2010 -0700
@@ -4,18 +4,21 @@
    Use of this source code is governed by a BSD-style
    license that can be found in the LICENSE file.  */
 
-#include "go-alloc.h"
 #include "go-string.h"
+#include "runtime.h"
+#include "malloc.h"
 
-const struct __go_string *
+struct __go_string
 __go_byte_array_to_string (const void* p, size_t len)
 {
   const unsigned char *bytes;
-  struct __go_string *ret;
+  unsigned char *retdata;
+  struct __go_string ret;
 
   bytes = (const unsigned char *) p;
-  ret = __go_alloc (sizeof (struct __go_string) + len);
-  ret->__length = len;
-  __builtin_memcpy (ret->__data, bytes, len);
+  retdata = mallocgc (len, RefNoPointers, 1, 0);
+  __builtin_memcpy (retdata, bytes, len);
+  ret.__data = retdata;
+  ret.__length = len;
   return ret;
 }
diff -r 581c6ed0cd02 libgo/runtime/go-caller.c
--- a/libgo/runtime/go-caller.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-caller.c	Tue Jun 01 21:58:24 2010 -0700
@@ -15,7 +15,7 @@
 struct caller_ret
 {
   uintptr_t pc;
-  const struct __go_string *file;
+  struct __go_string file;
   int line;
   _Bool ok;
 };
@@ -32,7 +32,8 @@
   /* A proper implementation needs to dig through the debugging
      information.  */
   ret.pc = (uint64_t) (uintptr_t) __builtin_return_address (1);
-  ret.file = NULL;
+  ret.file.__data = NULL;
+  ret.file.__length = 0;
   ret.line = 0;
   ret.ok = 0;
 
diff -r 581c6ed0cd02 libgo/runtime/go-int-array-to-string.c
--- a/libgo/runtime/go-int-array-to-string.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-int-array-to-string.c	Tue Jun 01 21:58:24 2010 -0700
@@ -6,16 +6,18 @@
 
 #include <assert.h>
 
-#include "go-alloc.h"
 #include "go-string.h"
+#include "runtime.h"
+#include "malloc.h"
 
-const struct __go_string *
+struct __go_string
 __go_int_array_to_string (const void* p, size_t len)
 {
   const int *ints;
   size_t slen;
   size_t i;
-  struct __go_string *ret;
+  unsigned char *retdata;
+  struct __go_string ret;
   unsigned char *s;
 
   ints = (const int *) p;
@@ -40,10 +42,11 @@
 	slen += 4;
     }
 
-  ret = __go_alloc (sizeof (struct __go_string) + slen);
-  ret->__length = slen;
+  retdata = mallocgc (slen, RefNoPointers, 1, 0);
+  ret.__data = retdata;
+  ret.__length = slen;
 
-  s = ret->__data;
+  s = retdata;
   for (i = 0; i < len; ++i)
     {
       int v;
@@ -77,7 +80,7 @@
 	}
     }
 
-  assert ((size_t) (s - ret->__data) == slen);
+  assert ((size_t) (s - retdata) == slen);
 
   return ret;
 }
diff -r 581c6ed0cd02 libgo/runtime/go-int-to-string.c
--- a/libgo/runtime/go-int-to-string.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-int-to-string.c	Tue Jun 01 21:58:24 2010 -0700
@@ -4,15 +4,17 @@
    Use of this source code is governed by a BSD-style
    license that can be found in the LICENSE file.  */
 
-#include "go-alloc.h"
 #include "go-string.h"
+#include "runtime.h"
+#include "malloc.h"
 
-const struct __go_string *
+struct __go_string
 __go_int_to_string (int v)
 {
   char buf[4];
-  size_t len;
-  struct __go_string *ret;
+  int len;
+  unsigned char *retdata;
+  struct __go_string ret;
 
   if (v <= 0x7f)
     {
@@ -49,9 +51,10 @@
 	}
     }
 
-  ret = (struct __go_string *) __go_alloc (sizeof (struct __go_string) + len);
-  ret->__length = len;
-  __builtin_memcpy (ret->__data, buf, len);
+  retdata = mallocgc (len, RefNoPointers, 1, 0);
+  __builtin_memcpy (retdata, buf, len);
+  ret.__data = retdata;
+  ret.__length = len;
 
   return ret;
 }
diff -r 581c6ed0cd02 libgo/runtime/go-main.c
--- a/libgo/runtime/go-main.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-main.c	Tue Jun 01 21:58:24 2010 -0700
@@ -39,23 +39,17 @@
 main (int argc, char **argv)
 {
   int i;
-  struct __go_string **values;
+  struct __go_string *values;
 
   mallocinit ();
 
   Args.__count = argc;
   Args.__capacity = argc;
-  values = __go_alloc (argc * sizeof (struct __go_string *));
+  values = __go_alloc (argc * sizeof (struct __go_string));
   for (i = 0; i < argc; ++i)
     {
-      size_t len;
-      struct __go_string *s;
-
-      len = __builtin_strlen (argv[i]);
-      s = __go_alloc (sizeof (struct __go_string) + len);
-      s->__length = len;
-      __builtin_memcpy (&s->__data[0], argv[i], len);
-      values[i] = s;
+      values[i].__data = (unsigned char *) argv[i];
+      values[i].__length = __builtin_strlen (argv[i]);
     }
   Args.__values = values;
 
@@ -63,17 +57,11 @@
     ;
   Envs.__count = i;
   Envs.__capacity = i;
-  values = __go_alloc (i * sizeof (struct __go_string *));
+  values = __go_alloc (i * sizeof (struct __go_string));
   for (i = 0; environ[i] != NULL; ++i)
     {
-      size_t len;
-      struct __go_string *s;
-
-      len = __builtin_strlen (environ[i]);
-      s = __go_alloc (sizeof (struct __go_string) + len);
-      s->__length = len;
-      __builtin_memcpy (&s->__data[0], environ[i], len);
-      values[i] = s;
+      values[i].__data = (unsigned char *) environ[i];
+      values[i].__length = __builtin_strlen (environ[i]);
     }
   Envs.__values = values;
 
diff -r 581c6ed0cd02 libgo/runtime/go-panic.h
--- a/libgo/runtime/go-panic.h	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-panic.h	Tue Jun 01 21:58:24 2010 -0700
@@ -13,4 +13,4 @@
 extern void __go_print_msg (_Bool is_panic, const char* msg);
 
 struct __go_string;
-extern void __go_print_string (_Bool is_panic, const struct __go_string *);
+extern void __go_print_string (_Bool is_panic, struct __go_string);
diff -r 581c6ed0cd02 libgo/runtime/go-print.c
--- a/libgo/runtime/go-print.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-print.c	Tue Jun 01 21:58:24 2010 -0700
@@ -27,10 +27,10 @@
 }
 
 void
-__go_print_string (_Bool is_panic, const struct __go_string* val)
+__go_print_string (_Bool is_panic, struct __go_string val)
 {
-  fprintf (is_panic ? stderr : stdout, "%.*s", (int) val->__length,
-	   (const char *) &val->__data[0]);
+  fprintf (is_panic ? stderr : stdout, "%.*s", (int) val.__length,
+	   (const char *) val.__data);
 }
 
 void
diff -r 581c6ed0cd02 libgo/runtime/go-reflect-call.c
--- a/libgo/runtime/go-reflect-call.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-reflect-call.c	Tue Jun 01 21:58:24 2010 -0700
@@ -84,6 +84,23 @@
   return ret;
 }
 
+/* Return an ffi_type for a Go string type.  This describes the
+   __go_string struct.  */
+
+static ffi_type *
+go_string_to_ffi (void)
+{
+  ffi_type *ret;
+
+  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+  ret->type = FFI_TYPE_STRUCT;
+  ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
+  ret->elements[0] = &ffi_type_pointer;
+  ret->elements[1] = &ffi_type_sint;
+  ret->elements[2] = NULL;
+  return ret;
+}
+
 /* Return an ffi_type for a type described by a
    __go_type_descriptor.  */
 
@@ -148,6 +165,7 @@
     case GO_STRUCT:
       return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
     case GO_STRING:
+      return go_string_to_ffi ();
     case GO_CHAN:
     case GO_FUNC:
     case GO_INTERFACE:
diff -r 581c6ed0cd02 libgo/runtime/go-strcmp.c
--- a/libgo/runtime/go-strcmp.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-strcmp.c	Tue Jun 01 21:58:24 2010 -0700
@@ -7,33 +7,20 @@
 #include "go-string.h"
 
 int
-__go_strcmp(const struct __go_string* s1, const struct __go_string* s2)
+__go_strcmp(struct __go_string s1, struct __go_string s2)
 {
   int i;
 
-  if (s1 == NULL)
-    {
-      if (s2 == NULL || s2->__length == 0)
-	return 0;
-      return -1;
-    }
-  else if (s2 == NULL)
-    {
-      if (s1->__length == 0)
-	return 0;
-      return 1;
-    }
-
-  i = __builtin_memcmp(s1->__data, s2->__data,
-		       (s1->__length < s2->__length
-			? s1->__length
-			: s2->__length));
+  i = __builtin_memcmp(s1.__data, s2.__data,
+		       (s1.__length < s2.__length
+			? s1.__length
+			: s2.__length));
   if (i != 0)
     return i;
 
-  if (s1->__length < s2->__length)
+  if (s1.__length < s2.__length)
     return -1;
-  else if (s1->__length > s2->__length)
+  else if (s1.__length > s2.__length)
     return 1;
   else
     return 0;
diff -r 581c6ed0cd02 libgo/runtime/go-string-to-byte-array.c
--- a/libgo/runtime/go-string-to-byte-array.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-string-to-byte-array.c	Tue Jun 01 21:58:24 2010 -0700
@@ -4,22 +4,21 @@
    Use of this source code is governed by a BSD-style
    license that can be found in the LICENSE file.  */
 
-#include "go-alloc.h"
 #include "go-string.h"
 #include "array.h"
 #include "runtime.h"
 #include "malloc.h"
 
 struct __go_open_array
-__go_string_to_byte_array (const struct __go_string *str)
+__go_string_to_byte_array (struct __go_string str)
 {
   unsigned char *data;
   struct __go_open_array ret;
 
-  data = (unsigned char *) mallocgc (str->__length, RefNoPointers, 0, 0);
-  __builtin_memcpy (data, str->__data, str->__length);
+  data = (unsigned char *) mallocgc (str.__length, RefNoPointers, 1, 0);
+  __builtin_memcpy (data, str.__data, str.__length);
   ret.__values = (void *) data;
-  ret.__count = str->__length;
-  ret.__capacity = ret.__count;
+  ret.__count = str.__length;
+  ret.__capacity = str.__length;
   return ret;
 }
diff -r 581c6ed0cd02 libgo/runtime/go-string-to-int-array.c
--- a/libgo/runtime/go-string-to-int-array.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-string-to-int-array.c	Tue Jun 01 21:58:24 2010 -0700
@@ -11,7 +11,7 @@
 #include "malloc.h"
 
 struct __go_open_array
-__go_string_to_int_array (const struct __go_string *str)
+__go_string_to_int_array (struct __go_string str)
 {
   size_t c;
   const unsigned char *p;
@@ -21,8 +21,8 @@
   struct __go_open_array ret;
 
   c = 0;
-  p = str->__data;
-  pend = p + str->__length;
+  p = str.__data;
+  pend = p + str.__length;
   while (p < pend)
     {
       int rune;
@@ -31,8 +31,8 @@
       p += __go_get_rune (p, pend - p, &rune);
     }
 
-  data = (uint32_t *) mallocgc (c * sizeof (uint32_t), RefNoPointers, 0, 0);
-  p = str->__data;
+  data = (uint32_t *) mallocgc (c * sizeof (uint32_t), RefNoPointers, 1, 0);
+  p = str.__data;
   pd = data;
   while (p < pend)
     {
diff -r 581c6ed0cd02 libgo/runtime/go-string.h
--- a/libgo/runtime/go-string.h	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-string.h	Tue Jun 01 21:58:24 2010 -0700
@@ -9,31 +9,26 @@
 
 #include <stddef.h>
 
-/* A string is represented as a pointer to this structure.  */
+/* A string is an instance of this structure.  */
 
 struct __go_string
 {
-  /* The number of bytes in the string.  */
-  size_t __length;
-  /* The actual bytes.  */
-  unsigned char __data[];
+  /* The bytes.  */
+  const unsigned char *__data;
+  /* The length.  */
+  int __length;
 };
 
 static inline _Bool
-__go_strings_equal (const struct __go_string *s1, const struct __go_string *s2)
+__go_strings_equal (struct __go_string s1, struct __go_string s2)
 {
-  if (s1 == NULL)
-    return s2 == NULL || s2->__length == 0;
-  if (s2 == NULL)
-    return s1->__length == 0;
-  if (s1->__length != s2->__length)
-    return 0;
-  return __builtin_memcmp (s1->__data, s2->__data, s1->__length) == 0;
+  return (s1.__length == s2.__length
+	  && __builtin_memcmp (s1.__data, s2.__data, s1.__length) == 0);
 }
 
 static inline _Bool
-__go_ptr_strings_equal (const struct __go_string * const *ps1,
-			const struct __go_string * const *ps2)
+__go_ptr_strings_equal (const struct __go_string *ps1,
+			const struct __go_string *ps2)
 {
   if (ps1 == NULL)
     return ps2 == NULL;
diff -r 581c6ed0cd02 libgo/runtime/go-strplus.c
--- a/libgo/runtime/go-strplus.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-strplus.c	Tue Jun 01 21:58:24 2010 -0700
@@ -4,24 +4,27 @@
    Use of this source code is governed by a BSD-style
    license that can be found in the LICENSE file.  */
 
-#include "go-alloc.h"
 #include "go-string.h"
+#include "runtime.h"
+#include "malloc.h"
 
-const struct __go_string *
-__go_string_plus (const struct __go_string *s1, const struct __go_string *s2)
+struct __go_string
+__go_string_plus (struct __go_string s1, struct __go_string s2)
 {
-  size_t len;
-  struct __go_string* ret;
+  int len;
+  unsigned char *retdata;
+  struct __go_string ret;
 
-  if (s1 == NULL)
+  if (s1.__length == 0)
     return s2;
-  else if (s2 == NULL)
+  else if (s2.__length == 0)
     return s1;
 
-  len = s1->__length + s2->__length;
-  ret = (struct __go_string *) __go_alloc (sizeof (struct __go_string) + len);
-  ret->__length = len;
-  __builtin_memcpy (ret->__data, s1->__data, s1->__length);
-  __builtin_memcpy (ret->__data + s1->__length, s2->__data, s2->__length);
+  len = s1.__length + s2.__length;
+  retdata = mallocgc (len, RefNoPointers, 1, 0);
+  __builtin_memcpy (retdata, s1.__data, s1.__length);
+  __builtin_memcpy (retdata + s1.__length, s2.__data, s2.__length);
+  ret.__data = retdata;
+  ret.__length = len;
   return ret;
 }
diff -r 581c6ed0cd02 libgo/runtime/go-strslice.c
--- a/libgo/runtime/go-strslice.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-strslice.c	Tue Jun 01 21:58:24 2010 -0700
@@ -4,26 +4,23 @@
    Use of this source code is governed by a BSD-style
    license that can be found in the LICENSE file.  */
 
-#include "go-alloc.h"
 #include "go-string.h"
 #include "go-panic.h"
+#include "runtime.h"
+#include "malloc.h"
 
-const struct __go_string*
-__go_string_slice (const struct __go_string *s, size_t start, size_t end)
+struct __go_string
+__go_string_slice (struct __go_string s, int start, int end)
 {
-  size_t len;
-  struct __go_string *ret;
+  int len;
+  struct __go_string ret;
 
-  len = s == NULL ? 0 : s->__length;
-  if (end == (size_t) -1)
+  len = s.__length;
+  if (end == -1)
     end = len;
   if (start > len || end < start || end > len)
     __go_panic_msg ("string index out of bounds");
-  if (s == NULL)
-    return NULL;
-  len = end - start;
-  ret = (struct __go_string *) __go_alloc (sizeof (struct __go_string) + len);
-  ret->__length = len;
-  __builtin_memcpy (ret->__data, s->__data + start, len);
+  ret.__data = s.__data + start;
+  ret.__length = end - start;
   return ret;
 }
diff -r 581c6ed0cd02 libgo/runtime/go-type-string.c
--- a/libgo/runtime/go-type-string.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-type-string.c	Tue Jun 01 21:58:24 2010 -0700
@@ -22,9 +22,7 @@
   const unsigned char *p;
 
   ret = 5381;
-  key = *(const struct __go_string * const *) vkey;
-  if (key == NULL)
-    return ret;
+  key = (const struct __go_string *) vkey;
   len = key->__length;
   for (i = 0, p = key->__data; i < len; i++, p++)
     ret = ret * 33 + *p;
@@ -40,14 +38,8 @@
   const struct __go_string *k1;
   const struct __go_string *k2;
 
-  k1 = *(const struct __go_string * const *) vk1;
-  k2 = *(const struct __go_string * const *) vk2;
-  if (k1 == NULL)
-    return k2 == NULL || k2->__length == 0;
-  else if (k2 == NULL)
-    return k1->__length == 0;
-  else if (k1->__length != k2->__length)
-    return 0;
-  else
-    return __builtin_memcmp (k1->__data, k2->__data, k1->__length) == 0;
+  k1 = (const struct __go_string *) vk1;
+  k2 = (const struct __go_string *) vk2;
+  return (k1->__length == k2->__length
+	  && __builtin_memcmp (k1->__data, k2->__data, k1->__length) == 0);
 }
diff -r 581c6ed0cd02 libgo/runtime/go-type.h
--- a/libgo/runtime/go-type.h	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-type.h	Tue Jun 01 21:58:24 2010 -0700
@@ -95,7 +95,7 @@
 
   /* A string describing this type.  This is only used for
      debugging.  */
-  const struct __go_string * const *__reflection;
+  const struct __go_string *__reflection;
 
   /* A pointer to fields which are only used for some types.  */
   const struct __go_uncommon_type *__uncommon;
@@ -106,11 +106,11 @@
 struct __go_method
 {
   /* The name of the method.  */
-  const struct __go_string **__name;
+  const struct __go_string *__name;
 
   /* This is NULL for an exported method, or the name of the package
      where it lives.  */
-  const struct __go_string **__pkg_path;
+  const struct __go_string *__pkg_path;
 
   /* The type of the method, without the receiver.  This will be a
      function type.  */
@@ -131,10 +131,10 @@
 struct __go_uncommon_type
 {
   /* The name of the type.  */
-  const struct __go_string **__name;
+  const struct __go_string *__name;
 
   /* The type's package.  This is NULL for builtin types.  */
-  const struct __go_string **__pkg_path;
+  const struct __go_string *__pkg_path;
 
   /* The type's methods.  This is an array of struct __go_method.  */
   struct __go_open_array __methods;
@@ -210,11 +210,11 @@
 struct __go_interface_method
 {
   /* The name of the method.  */
-  const struct __go_string **__name;
+  const struct __go_string *__name;
 
   /* This is NULL for an exported method, or the name of the package
      where it lives.  */
-  const struct __go_string **__pkg_path;
+  const struct __go_string *__pkg_path;
 
   /* The real type of the method.  */
   struct __go_type_descriptor *__type;
@@ -263,17 +263,17 @@
 struct __go_struct_field
 {
   /* The name of the field--NULL for an anonymous field.  */
-  const struct __go_string **__name;
+  const struct __go_string *__name;
 
   /* This is NULL for an exported method, or the name of the package
      where it lives.  */
-  const struct __go_string **__pkg_path;
+  const struct __go_string *__pkg_path;
 
   /* The type of the field.  */
   const struct __go_type_descriptor *__type;
 
   /* The field tag, or NULL.  */
-  const struct __go_string **__tag;
+  const struct __go_string *__tag;
 
   /* The offset of the field in the struct.  */
   uintptr_t __offset;
diff -r 581c6ed0cd02 libgo/runtime/go-unsafe-pointer.c
--- a/libgo/runtime/go-unsafe-pointer.c	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/go-unsafe-pointer.c	Tue Jun 01 21:58:24 2010 -0700
@@ -26,20 +26,12 @@
 
 /* The reflection string.  */
 #define REFLECTION "unsafe.Pointer"
-#define REFLECTION_LEN 14
-static const struct
+static const struct __go_string reflection_string =
 {
-  size_t length;
-  char data[REFLECTION_LEN];
-} reflection_string =
-{
-  sizeof REFLECTION - 1,
-  { REFLECTION }
+  (const unsigned char *) REFLECTION,
+  sizeof REFLECTION - 1
 };
 
-static const struct __go_string * const ptr_reflection_string =
-  (const struct __go_string *) &reflection_string;
-
 const struct __go_type_descriptor unsafe_Pointer =
 {
   /* __code */
@@ -57,7 +49,7 @@
   /* __equalfn */
   __go_type_equal_identity,
   /* __reflection */
-  &ptr_reflection_string,
+  &reflection_string,
   /* __uncommon */
   NULL
 };
@@ -71,20 +63,12 @@
 
 /* The reflection string.  */
 #define PREFLECTION "*unsafe.Pointer"
-#define PREFLECTION_LEN 15
-static const struct
+static const struct __go_string preflection_string =
 {
-  size_t length;
-  char data[PREFLECTION_LEN];
-} preflection_string =
-{
+  (const unsigned char *) PREFLECTION,
   sizeof PREFLECTION - 1,
-  { PREFLECTION }
 };
 
-static const struct __go_string * const ptr_preflection_string =
-  (const struct __go_string *) &preflection_string;
-
 const struct __go_ptr_type pointer_unsafe_Pointer =
 {
   /* __common */
@@ -104,7 +88,7 @@
     /* __equalfn */
     __go_type_equal_identity,
     /* __reflection */
-    &ptr_preflection_string,
+    &preflection_string,
     /* __uncommon */
     NULL
   },
diff -r 581c6ed0cd02 libgo/runtime/malloc.cgo
--- a/libgo/runtime/malloc.cgo	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/malloc.cgo	Tue Jun 01 21:58:24 2010 -0700
@@ -300,7 +300,7 @@
 		throw("runtime.SetFinalizer");
 	}
 	if(obj->__type_descriptor->__code != GO_PTR) {
-		printf("runtime.SetFinalizer: first argument is %.*s, not pointer\n", (int)(*obj->__type_descriptor->__reflection)->__length, (*obj->__type_descriptor->__reflection)->__data);
+		printf("runtime.SetFinalizer: first argument is %.*s, not pointer\n", (int)obj->__type_descriptor->__reflection->__length, obj->__type_descriptor->__reflection->__data);
 		goto throw;
 	}
 	if(!mlookup(obj->__object, &base, &size, nil, nil) || obj->__object != base) {
@@ -311,7 +311,7 @@
 	if(finalizer != nil) {
 		if(finalizer->__type_descriptor->__code != GO_FUNC) {
 		badfunc:
-		  printf("runtime.SetFinalizer: second argument is %.*s, not func(%.*s)\n", (int)(*finalizer->__type_descriptor->__reflection)->__length, (*finalizer->__type_descriptor->__reflection)->__data, (int)(*obj->__type_descriptor->__reflection)->__length, (*obj->__type_descriptor->__reflection)->__data);
+		  printf("runtime.SetFinalizer: second argument is %.*s, not func(%.*s)\n", (int)finalizer->__type_descriptor->__reflection->__length, finalizer->__type_descriptor->__reflection->__data, (int)obj->__type_descriptor->__reflection->__length, obj->__type_descriptor->__reflection->__data);
 			goto throw;
 		}
 		ft = (const FuncType*)finalizer->__type_descriptor;
diff -r 581c6ed0cd02 libgo/runtime/runtime.h
--- a/libgo/runtime/runtime.h	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/runtime.h	Tue Jun 01 21:58:24 2010 -0700
@@ -21,7 +21,7 @@
 #include "go-panic.h"
 #include "go-string.h"
 
-typedef struct __go_string *String;
+typedef struct __go_string String;
 
 /* This file supports C files copied from the 6g runtime library.
    This is a version of the 6g runtime.h rewritten for gccgo's version
diff -r 581c6ed0cd02 libgo/runtime/sigqueue.cgo
--- a/libgo/runtime/sigqueue.cgo	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/sigqueue.cgo	Tue Jun 01 21:58:24 2010 -0700
@@ -39,6 +39,7 @@
 package runtime
 #include "config.h"
 #include "runtime.h"
+#include "malloc.h"
 #include "defs.h"
 
 static struct {
@@ -100,10 +101,11 @@
 		snprintf(buf, sizeof buf, "signal %d", sig);
 		s = buf;
 	}
-	int32 len = strlen(s);
-	name = __go_alloc(sizeof(struct __go_string) + len);
-	name->__length = len;
-	memcpy(name->__data, s, len);
+	int32 len = __builtin_strlen(s);
+	unsigned char *data = mallocgc(len, RefNoPointers, 0, 0);
+	__builtin_memcpy(data, s, len);
+	name.__data = data;
+	name.__length = len;
 }
 
 func Siginit() {
diff -r 581c6ed0cd02 libgo/runtime/string.cgo
--- a/libgo/runtime/string.cgo	Tue Jun 01 12:43:04 2010 -0700
+++ b/libgo/runtime/string.cgo	Tue Jun 01 21:58:24 2010 -0700
@@ -3,58 +3,54 @@
 // license that can be found in the LICENSE file.
 
 package runtime
-#include "go-string.h"
-#define nil NULL
+#include "runtime.h"
 #define charntorune(pv, str, len) __go_get_rune(str, len, pv)
 
-typedef struct __go_string __go_string;
-typedef int int32;
-
 enum
 {
 	Runeself	= 0x80,
 };
 
-func stringiter(s *__go_string, k int32) (retk int32) {
+func stringiter(s String, k int32) (retk int32) {
 	int32 l, n;
 
-	if(s == nil || (size_t) k >= s->__length) {
+	if(k >= s.__length) {
 		// retk=0 is end of iteration
 		retk = 0;
 		goto out;
 	}
 
-	l = s->__data[k];
+	l = s.__data[k];
 	if(l < Runeself) {
 		retk = k+1;
 		goto out;
 	}
 
 	// multi-char rune
-	n = charntorune(&l, s->__data+k, s->__length+k);
+	n = charntorune(&l, s.__data+k, s.__length-k);
 	retk = k + (n ? n : 1);
 
 out:
 }
 
-func stringiter2(s *__go_string, k int32) (retk int32, retv int32) {
+func stringiter2(s String, k int32) (retk int32, retv int32) {
 	int32 n;
 
-	if(s == nil || (size_t) k >= s->__length) {
+	if(k >= s.__length) {
 		// retk=0 is end of iteration
 		retk = 0;
 		retv = 0;
 		goto out;
 	}
 
-	retv = s->__data[k];
+	retv = s.__data[k];
 	if(retv < Runeself) {
 		retk = k+1;
 		goto out;
 	}
 
 	// multi-char rune
-	n = charntorune(&retv, s->__data+k, s->__length-k);
+	n = charntorune(&retv, s.__data+k, s.__length-k);
 	retk = k + (n ? n : 1);
 
 out:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]