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] Move type descriptor construction from GENERIC to GOGO


This patch moves the construction of type descriptors from GENERIC to
GOGO.  This has no real effect on generated code, but it improves the
separation of the frontend proper from the gcc interface.  Committed to
gccgo branch.

Ian

diff -r 702d88f9b3d3 go/expressions.cc
--- a/go/expressions.cc	Fri Oct 08 13:54:30 2010 -0700
+++ b/go/expressions.cc	Fri Oct 22 12:31:01 2010 -0700
@@ -334,7 +334,7 @@
   // Otherwise it is the interface method table for RHS_TYPE.
   tree first_field_value;
   if (lhs_is_empty)
-    first_field_value = rhs_type->type_descriptor(gogo);
+    first_field_value = rhs_type->type_descriptor_pointer(gogo);
   else
     {
       // Build the interface method table for this interface and this
@@ -489,7 +489,7 @@
   if (for_type_guard)
     {
       // A type assertion fails when converting a nil interface.
-      tree lhs_type_descriptor = lhs_type->type_descriptor(gogo);
+      tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo);
       static tree assert_interface_decl;
       tree call = Gogo::call_builtin(&assert_interface_decl,
 				     location,
@@ -519,7 +519,7 @@
       // type assertion converting nil will always succeed.
       gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods")
 		 == 0);
-      tree lhs_type_descriptor = lhs_type->type_descriptor(gogo);
+      tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo);
       static tree convert_interface_decl;
       tree call = Gogo::call_builtin(&convert_interface_decl,
 				     location,
@@ -571,7 +571,7 @@
   // will panic with an appropriate runtime type error if the type is
   // not valid.
 
-  tree lhs_type_descriptor = lhs_type->type_descriptor(gogo);
+  tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo);
 
   if (!DECL_P(rhs_tree))
     rhs_tree = save_expr(rhs_tree);
@@ -580,7 +580,7 @@
     Expression::get_interface_type_descriptor(context, rhs_type, rhs_tree,
 					      location);
 
-  tree rhs_inter_descriptor = rhs_type->type_descriptor(gogo);
+  tree rhs_inter_descriptor = rhs_type->type_descriptor_pointer(gogo);
 
   static tree check_interface_type_decl;
   tree call = Gogo::call_builtin(&check_interface_type_decl,
@@ -3886,6 +3886,7 @@
       // at parse time.  Taking the address of a nonconstant
       // constructor will not do what the programmer expects.
       gcc_assert(TREE_CODE(expr) != CONSTRUCTOR || TREE_CONSTANT(expr));
+      gcc_assert(TREE_CODE(expr) != ADDR_EXPR);
 
       // Build a decl for a constant constructor.
       if (TREE_CODE(expr) == CONSTRUCTOR && TREE_CONSTANT(expr))
@@ -3897,6 +3898,7 @@
 	  TREE_READONLY(decl) = 1;
 	  TREE_CONSTANT(decl) = 1;
 	  TREE_STATIC(decl) = 1;
+	  TREE_ADDRESSABLE(decl) = 1;
 	  DECL_ARTIFICIAL(decl) = 1;
 	  DECL_INITIAL(decl) = expr;
 	  rest_of_decl_compilation(decl, 1, 0);
@@ -10241,10 +10243,10 @@
 // Make a struct composite literal.  This used by the thunk code.
 
 Expression*
-Expression::make_struct_composite_literal(Struct_type* type,
-					  Expression_list* vals,
+Expression::make_struct_composite_literal(Type* type, Expression_list* vals,
 					  source_location location)
 {
+  gcc_assert(type->struct_type() != NULL);
   return new Struct_construction_expression(type, vals, location);
 }
 
@@ -10662,6 +10664,17 @@
     return build2(COMPOUND_EXPR, type_tree, set, constructor);
 }
 
+// Make a slice composite literal.  This is used by the type
+// descriptor code.
+
+Expression*
+Expression::make_slice_composite_literal(Type* type, Expression_list* vals,
+					 source_location location)
+{
+  gcc_assert(type->is_open_array_type());
+  return new Open_array_construction_expression(type, vals, location);
+}
+
 // Construct a map.
 
 class Map_construction_expression : public Expression
@@ -11740,7 +11753,7 @@
 
   tree
   do_get_tree(Translate_context* context)
-  { return this->type_->type_descriptor(context->gogo()); }
+  { return this->type_->type_descriptor_pointer(context->gogo()); }
 
  private:
   // The type for which this is the descriptor.
@@ -11755,6 +11768,182 @@
   return new Type_descriptor_expression(type, location);
 }
 
+// An expression which evaluates to some characteristic of a type.
+// This is only used to initialize fields of a type descriptor.  Using
+// a new expression class is slightly inefficient but gives us a good
+// separation between the frontend and the middle-end with regard to
+// how types are laid out.
+
+class Type_info_expression : public Expression
+{
+ public:
+  Type_info_expression(Type* type, Type_info type_info)
+    : Expression(EXPRESSION_TYPE_INFO, BUILTINS_LOCATION),
+      type_(type), type_info_(type_info)
+  { }
+
+ protected:
+  Type*
+  do_type();
+
+  void
+  do_determine_type(const Type_context*)
+  { }
+
+  Expression*
+  do_copy()
+  { return this; }
+
+  tree
+  do_get_tree(Translate_context* context);
+
+ private:
+  // The type for which we are getting information.
+  Type* type_;
+  // What information we want.
+  Type_info type_info_;
+};
+
+// The type is chosen to match what the type descriptor struct
+// expects.
+
+Type*
+Type_info_expression::do_type()
+{
+  switch (this->type_info_)
+    {
+    case TYPE_INFO_SIZE:
+      return Type::lookup_integer_type("uintptr");
+    case TYPE_INFO_ALIGNMENT:
+    case TYPE_INFO_FIELD_ALIGNMENT:
+      return Type::lookup_integer_type("uint8");
+    default:
+      gcc_unreachable();
+    }
+}
+
+// Return type information in GENERIC.
+
+tree
+Type_info_expression::do_get_tree(Translate_context* context)
+{
+  tree type_tree = this->type_->get_tree(context->gogo());
+  if (type_tree == error_mark_node)
+    return error_mark_node;
+
+  tree val_type_tree = this->type()->get_tree(context->gogo());
+  gcc_assert(val_type_tree != error_mark_node);
+
+  if (this->type_info_ == TYPE_INFO_SIZE)
+    return fold_convert_loc(BUILTINS_LOCATION, val_type_tree,
+			    TYPE_SIZE_UNIT(type_tree));
+  else
+    {
+      unsigned HOST_WIDE_INT val;
+      if (this->type_info_ == TYPE_INFO_ALIGNMENT)
+	val = TYPE_ALIGN_UNIT(type_tree);
+      else
+	{
+	  gcc_assert(this->type_info_ == TYPE_INFO_FIELD_ALIGNMENT);
+	  val = TYPE_ALIGN(type_tree);
+#ifdef BIGGEST_FIELD_ALIGMENT
+	  if (val > BIGGEST_FIELD_ALIGNMENT)
+	    val = BIGGEST_FIELD_ALIGNMENT;
+#endif
+#ifdef ADJUST_FIELD_ALIGN
+	  {
+	    tree f = build_decl(UNKNOWN_LOCATION, FIELD_DECL, NULL, type_tree);
+	    val = ADJUST_FIELD_ALIGN(f, val);
+	  }
+#endif
+	  val /= BITS_PER_UNIT;
+	}
+
+      return build_int_cstu(val_type_tree, val);
+    }
+}
+
+// Make a type info expression.
+
+Expression*
+Expression::make_type_info(Type* type, Type_info type_info)
+{
+  return new Type_info_expression(type, type_info);
+}
+
+// An expression which evaluates to the offset of a field within a
+// struct.  This, like Type_info_expression, q.v., is only used to
+// initialize fields of a type descriptor.
+
+class Struct_field_offset_expression : public Expression
+{
+ public:
+  Struct_field_offset_expression(Struct_type* type, const Struct_field* field)
+    : Expression(EXPRESSION_STRUCT_FIELD_OFFSET, BUILTINS_LOCATION),
+      type_(type), field_(field)
+  { }
+
+ protected:
+  Type*
+  do_type()
+  { return Type::lookup_integer_type("uintptr"); }
+
+  void
+  do_determine_type(const Type_context*)
+  { }
+
+  Expression*
+  do_copy()
+  { return this; }
+
+  tree
+  do_get_tree(Translate_context* context);
+
+ private:
+  // The type of the struct.
+  Struct_type* type_;
+  // The field.
+  const Struct_field* field_;
+};
+
+// Return a struct field offset in GENERIC.
+
+tree
+Struct_field_offset_expression::do_get_tree(Translate_context* context)
+{
+  tree type_tree = this->type_->get_tree(context->gogo());
+  if (type_tree == error_mark_node)
+    return error_mark_node;
+
+  tree val_type_tree = this->type()->get_tree(context->gogo());
+  gcc_assert(val_type_tree != error_mark_node);
+
+  const Struct_field_list* fields = this->type_->fields();
+  tree struct_field_tree = TYPE_FIELDS(type_tree);
+  Struct_field_list::const_iterator p;
+  for (p = fields->begin();
+       p != fields->end();
+       ++p, struct_field_tree = TREE_CHAIN(struct_field_tree))
+    {
+      gcc_assert(struct_field_tree != NULL_TREE);
+      if (&*p == this->field_)
+	break;
+    }
+  gcc_assert(&*p == this->field_);
+
+  return fold_convert_loc(BUILTINS_LOCATION, val_type_tree,
+			  byte_position(struct_field_tree));
+}
+
+// Make an expression for a struct field offset.
+
+Expression*
+Expression::make_struct_field_offset(Struct_type* type,
+				     const Struct_field* field)
+{
+  return new Struct_field_offset_expression(type, field);
+}
+
 // An expression which evaluates to the address of an unnamed label.
 
 class Label_addr_expression : public Expression
diff -r 702d88f9b3d3 go/expressions.h
--- a/go/expressions.h	Fri Oct 08 13:54:30 2010 -0700
+++ b/go/expressions.h	Fri Oct 22 12:31:01 2010 -0700
@@ -19,6 +19,8 @@
 struct Type_context;
 class Function_type;
 class Map_type;
+class Struct_type;
+class Struct_field;
 class Expression_list;
 class Var_expression;
 class Temporary_reference_expression;
@@ -89,6 +91,8 @@
     EXPRESSION_RECEIVE,
     EXPRESSION_SEND,
     EXPRESSION_TYPE_DESCRIPTOR,
+    EXPRESSION_TYPE_INFO,
+    EXPRESSION_STRUCT_FIELD_OFFSET,
     EXPRESSION_LABEL_ADDR
   };
 
@@ -251,8 +255,11 @@
 
   // Make a struct composite literal.
   static Expression*
-  make_struct_composite_literal(Struct_type*, Expression_list*,
-				source_location);
+  make_struct_composite_literal(Type*, Expression_list*, source_location);
+
+  // Make a slice composite literal.
+  static Expression*
+  make_slice_composite_literal(Type*, Expression_list*, source_location);
 
   // Take a composite literal and allocate it on the heap.
   static Expression*
@@ -271,6 +278,29 @@
   static Expression*
   make_type_descriptor(Type* type, source_location);
 
+  // Make an expression which evaluates to some characteristic of a
+  // type.  These are only used for type descriptors, so there is no
+  // location parameter.
+  enum Type_info
+    {
+      // The size of a value of the type.
+      TYPE_INFO_SIZE,
+      // The required alignment of a value of the type.
+      TYPE_INFO_ALIGNMENT,
+      // The required alignment of a value of the type when used as a
+      // field in a struct.
+      TYPE_INFO_FIELD_ALIGNMENT
+    };
+
+  static Expression*
+  make_type_info(Type* type, Type_info);
+
+  // Make an expression which evaluates to the offset of a field in a
+  // struct.  This is only used for type descriptors, so there is no
+  // location parameter.
+  static Expression*
+  make_struct_field_offset(Struct_type*, const Struct_field*);
+
   // Make an expression which evaluates to the address of an unnamed
   // label.
   static Expression*
diff -r 702d88f9b3d3 go/gogo-tree.cc
--- a/go/gogo-tree.cc	Fri Oct 08 13:54:30 2010 -0700
+++ b/go/gogo-tree.cc	Fri Oct 22 12:31:01 2010 -0700
@@ -976,8 +976,9 @@
 	    // descriptor, even though we don't do anything with it.
 	    if (this->package_ == NULL)
 	      {
-		named_type->type_descriptor(gogo);
-		Type::make_pointer_type(named_type)->type_descriptor(gogo);
+		named_type->type_descriptor_pointer(gogo);
+		Type* pn = Type::make_pointer_type(named_type);
+		pn->type_descriptor_pointer(gogo);
 	      }
 	  }
       }
@@ -2111,6 +2112,8 @@
       fields = field;
     }
 
+  va_end(ap);
+
   if (struct_type == NULL_TREE)
     struct_type = make_node(RECORD_TYPE);
   finish_builtin_struct(struct_type, struct_name, fields, NULL_TREE);
@@ -2372,7 +2375,7 @@
 
   constructor_elt* elt = VEC_quick_push(constructor_elt, descriptor, NULL);
   elt->index = map_descriptor_field;
-  elt->value = maptype->type_descriptor(this);
+  elt->value = maptype->type_descriptor_pointer(this);
 
   elt = VEC_quick_push(constructor_elt, descriptor, NULL);
   elt->index = entry_size_field;
@@ -2413,7 +2416,7 @@
 Gogo::map_descriptor_type()
 {
   static tree struct_type;
-  tree dtype = this->map_type_descriptor_type_tree();
+  tree dtype = Type::make_type_descriptor_type()->get_tree(this);
   dtype = build_qualified_type(dtype, TYPE_QUAL_CONST);
   return Gogo::builtin_struct(&struct_type, "__go_map_descriptor", NULL_TREE,
 			      4,
@@ -2427,159 +2430,6 @@
 			      sizetype);
 }
 
-// Return pointers to functions which compute a hash code for TYPE and
-// which compare whether two TYPEs are equal.
-
-void
-Gogo::type_functions(const Type* keytype, tree* hash_fn, tree* equal_fn)
-{
-  const char* hash_fn_name;
-  const char* equal_fn_name;
-  switch (keytype->base()->classification())
-    {
-    case Type::TYPE_ERROR:
-    case Type::TYPE_VOID:
-    case Type::TYPE_NIL:
-      // These types can not be hashed or compared.
-      hash_fn_name = "__go_type_hash_error";
-      equal_fn_name = "__go_type_equal_error";
-      break;
-
-    case Type::TYPE_BOOLEAN:
-    case Type::TYPE_INTEGER:
-    case Type::TYPE_FLOAT:
-    case Type::TYPE_COMPLEX:
-    case Type::TYPE_POINTER:
-    case Type::TYPE_FUNCTION:
-    case Type::TYPE_MAP:
-    case Type::TYPE_CHANNEL:
-      hash_fn_name = "__go_type_hash_identity";
-      equal_fn_name = "__go_type_equal_identity";
-      break;
-
-    case Type::TYPE_STRING:
-      hash_fn_name = "__go_type_hash_string";
-      equal_fn_name = "__go_type_equal_string";
-      break;
-
-    case Type::TYPE_STRUCT:
-    case Type::TYPE_ARRAY:
-      // These types can not be hashed or compared.
-      hash_fn_name = "__go_type_hash_error";
-      equal_fn_name = "__go_type_equal_error";
-      break;
-
-    case Type::TYPE_INTERFACE:
-      if (keytype->interface_type()->is_empty())
-	{
-	  hash_fn_name = "__go_type_hash_empty_interface";
-	  equal_fn_name = "__go_type_equal_empty_interface";
-	}
-      else
-	{
-	  hash_fn_name = "__go_type_hash_interface";
-	  equal_fn_name = "__go_type_equal_interface";
-	}
-      break;
-
-    case Type::TYPE_NAMED:
-    case Type::TYPE_FORWARD:
-      gcc_unreachable();
-
-    default:
-      gcc_unreachable();
-    }
-
-  tree id = get_identifier(hash_fn_name);
-  tree fntype = build_function_type_list(sizetype, const_ptr_type_node,
-					 sizetype, NULL_TREE);
-  tree decl = build_decl(BUILTINS_LOCATION, FUNCTION_DECL, id, fntype);
-  Gogo::mark_fndecl_as_builtin_library(decl);
-  *hash_fn = build_fold_addr_expr(decl);
-  go_preserve_from_gc(decl);
-
-  id = get_identifier(equal_fn_name);
-  fntype = build_function_type_list(boolean_type_node, const_ptr_type_node,
-				    sizetype, const_ptr_type_node,
-				    sizetype, NULL_TREE);
-  decl = build_decl(BUILTINS_LOCATION, FUNCTION_DECL, id, fntype);
-  Gogo::mark_fndecl_as_builtin_library(decl);
-  *equal_fn = build_fold_addr_expr(decl);
-  go_preserve_from_gc(decl);
-}
-
-// Build and return the tree type for a type descriptor.
-
-tree
-Gogo::type_descriptor_type_tree()
-{
-  static tree descriptor_type;
-  if (descriptor_type == NULL_TREE)
-    {
-      tree uncommon_type = make_node(RECORD_TYPE);
-
-      tree string_type = Type::make_string_type()->get_tree(this);
-      tree string_pointer_type = build_pointer_type(string_type);
-
-      tree hash_fntype = build_function_type_list(sizetype, const_ptr_type_node,
-						  sizetype, NULL_TREE);
-      hash_fntype = build_pointer_type(hash_fntype);
-
-      tree equal_fntype = build_function_type_list(boolean_type_node,
-						   const_ptr_type_node,
-						   const_ptr_type_node,
-						   sizetype,
-						   NULL_TREE);
-      equal_fntype = build_pointer_type(equal_fntype);
-
-      Gogo::builtin_struct(&descriptor_type, "__go_type_descriptor", NULL_TREE,
-			   9,
-			   "__kind",
-			   unsigned_char_type_node,
-			   "__align",
-			   unsigned_char_type_node,
-			   "__field_align",
-			   unsigned_char_type_node,
-			   "__size",
-			   Type::lookup_integer_type("uintptr")->get_tree(this),
-			   "__hash",
-			   Type::lookup_integer_type("uint32")->get_tree(this),
-			   "__hashfn",
-			   hash_fntype,
-			   "__equalfn",
-			   equal_fntype,
-			   "__reflection",
-			   string_pointer_type,
-			   "__uncommon",
-			   build_pointer_type(uncommon_type));
-
-      tree descriptor_pointer_type = build_pointer_type(descriptor_type);
-
-      tree method_type = Gogo::builtin_struct(NULL, "__go_method", NULL_TREE,
-					      5,
-					      "__name",
-					      string_pointer_type,
-					      "__pkg_path",
-					      string_pointer_type,
-					      "__mtype",
-					      descriptor_pointer_type,
-					      "__type",
-					      descriptor_pointer_type,
-					      "__function",
-					      const_ptr_type_node);
-
-      Gogo::builtin_struct(NULL, "__go_uncommon_type", uncommon_type, 3,
-			   "__name",
-			   string_pointer_type,
-			   "__pkg_path",
-			   string_pointer_type,
-			   "__methods",
-			   this->slice_type_tree(method_type));
-    }
-
-  return descriptor_type;
-}
-
 // Return the name to use for a type descriptor decl for TYPE.  This
 // is used when TYPE does not have a name.
 
@@ -2622,374 +2472,12 @@
   return ret;
 }
 
-// Build a constructor for a slice in a type descriptor.
-// SLICE_TYPE_TREE is the type of the slice.  INIT is a vector of
-// elements to store in the slice.  The result is a constant
-// constructor.  This is a static function to avoid putting the type
-// VEC(constructor_elt,gc) into gogo.h.
-
-static tree
-type_descriptor_slice(tree slice_type_tree, VEC(constructor_elt,gc)* init)
+// Where a type descriptor decl should be defined.
+
+Gogo::Type_descriptor_location
+Gogo::type_descriptor_location(const Type* type)
 {
-  // Build the array of initial values.
-  gcc_assert(!VEC_empty(constructor_elt, init));
-  tree max = size_int(VEC_length(constructor_elt, init) - 1);
-  tree entry_type = Gogo::slice_element_type_tree(slice_type_tree);
-  tree index_type = build_index_type(max);
-  tree array_type = build_array_type(entry_type, index_type);
-  tree constructor = build_constructor(array_type, init);
-  TREE_CONSTANT(constructor) = 1;
-
-  // Push the array into memory so that we can take its address.
-  tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
-			 create_tmp_var_name("C"), array_type);
-  DECL_EXTERNAL(decl) = 0;
-  TREE_PUBLIC(decl) = 0;
-  TREE_STATIC(decl) = 1;
-  DECL_ARTIFICIAL(decl) = 1;
-  TREE_READONLY(decl) = 1;
-  TREE_CONSTANT(decl) = 1;
-  DECL_INITIAL(decl) = constructor;
-  rest_of_decl_compilation(decl, 1, 0);
-
-  tree values = fold_convert(build_pointer_type(entry_type),
-			     build_fold_addr_expr(decl));
-  tree count = size_int(VEC_length(constructor_elt, init));
-  tree ret = Gogo::slice_constructor(slice_type_tree, values, count, count);
-  TREE_CONSTANT(ret) = 1;
-  return ret;
-}
-
-// Sort methods by name.
-
-class Sort_methods
-{
- public:
-  bool
-  operator()(const std::pair<std::string, const Method*>& m1,
-	     const std::pair<std::string, const Method*>& m2) const
-  { return m1.first < m2.first; }
-};
-
-// Build a constructor for one entry in a method table.
-
-tree
-Gogo::type_method_table_entry(tree method_entry_tree,
-			      const std::string& method_name,
-			      const Method* m)
-{
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 5);
-
-  Function_type* mtype = m->type();
-
-  tree field = TYPE_FIELDS(method_entry_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  const std::string& n(Gogo::unpack_hidden_name(method_name));
-  elt->value = this->ptr_go_string_constant_tree(Gogo::unpack_hidden_name(n));
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  if (!Gogo::is_hidden_name(method_name))
-    elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-  else
-    {
-      std::string s = Gogo::hidden_name_prefix(method_name);
-      elt->value = this->ptr_go_string_constant_tree(s);
-    }
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__mtype") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  gcc_assert(mtype->is_method());
-  Type* nonmethod_type = mtype->copy_without_receiver();
-  elt->value = nonmethod_type->type_descriptor(this);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = mtype->type_descriptor(this);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__function") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  Named_object* no = m->named_object();
-  tree fnid = no->get_id(this);
-  tree fndecl;
-  if (no->is_function())
-    fndecl = no->func_value()->get_or_make_decl(this, no, fnid);
-  else if (no->is_function_declaration())
-    fndecl = no->func_declaration_value()->get_or_make_decl(this, no, fnid);
-  else
-    gcc_unreachable();
-  elt->value = fold_convert(const_ptr_type_node,
-			    build_fold_addr_expr(fndecl));
-
-  tree ret = build_constructor(method_entry_tree, init);
-  TREE_CONSTANT(ret) = 1;
-  return ret;
-}
-
-// Build a method table for a type descriptor.  METHOD_TYPE_TREE is
-// the type of the method table, and should be the type of a slice.
-// METHODS is the list of methods.  If ONLY_VALUE_METHODS is true,
-// then only value methods are used.  This returns a constructor for a
-// slice.
-
-tree
-Gogo::type_method_table(tree method_type_tree, const Methods* methods,
-			bool only_value_methods)
-{
-  std::vector<std::pair<std::string, const Method*> > smethods;
-  if (methods != NULL)
-    {
-      for (Methods::const_iterator p = methods->begin();
-	   p != methods->end();
-	   ++p)
-	{
-	  if (p->second->is_ambiguous())
-	    continue;
-	  if (only_value_methods && !p->second->is_value_method())
-	    continue;
-	  smethods.push_back(std::make_pair(p->first, p->second));
-	}
-    }
-
-  if (smethods.empty())
-    return Gogo::empty_slice_constructor(method_type_tree);
-
-  std::sort(smethods.begin(), smethods.end(), Sort_methods());
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc,
-					    smethods.size());
-  tree method_entry_tree = Gogo::slice_element_type_tree(method_type_tree);
-  size_t i = 0;
-  for (std::vector<std::pair<std::string, const Method*> >::const_iterator p
-	 = smethods.begin();
-       p != smethods.end();
-       ++p, ++i)
-    {
-      constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-      elt->index = size_int(i);
-      elt->value = this->type_method_table_entry(method_entry_tree,
-						 p->first, p->second);
-    }
-
-  return type_descriptor_slice(method_type_tree, init);
-}
-
-// Build a decl for uncommon type information for a type descriptor.
-// UNCOMMON_TYPE_TREE is the type of the uncommon type struct--struct
-// __go_uncommon_type in libgo/runtime/go-type.h.  If NAME is not
-// NULL, it is the name of the type.  If METHODS is not NULL, it is
-// the list of methods.  ONLY_VALUE_METHODS is true if only value
-// methods should be included.  At least one of NAME and METHODS must
-// not be NULL.  This returns a pointer to the decl that it builds.
-
-tree
-Gogo::uncommon_type_information(tree uncommon_type_tree, Named_type* name,
-				const Methods* methods,
-				bool only_value_methods)
-{
-  gcc_assert(TREE_CODE(uncommon_type_tree) == RECORD_TYPE);
-
-  tree string_type_tree = Type::make_string_type()->get_tree(this);
-  tree ptr_string_type_tree = build_pointer_type(string_type_tree);
-
-  tree name_value;
-  tree pkg_path_value;
-  if (name == NULL)
-    {
-      name_value = fold_convert(ptr_string_type_tree, null_pointer_node);
-      pkg_path_value = fold_convert(ptr_string_type_tree, null_pointer_node);
-    }
-  else
-    {
-      Named_object* no = name->named_object();
-      std::string n = Gogo::unpack_hidden_name(no->name());
-      name_value = this->ptr_go_string_constant_tree(n);
-      if (name->is_builtin())
-	pkg_path_value = fold_convert(ptr_string_type_tree, null_pointer_node);
-      else
-	{
-	  const Package* package = no->package();
-	  const std::string& unique_prefix(package == NULL
-					   ? this->unique_prefix()
-					   : package->unique_prefix());
-	  const std::string& package_name(package == NULL
-					  ? this->package_name()
-					  : package->name());
-	  n.assign(unique_prefix);
-	  n.append(1, '.');
-	  n.append(package_name);
-	  if (name->in_function() != NULL)
-	    {
-	      n.append(1, '.');
-	      n.append(Gogo::unpack_hidden_name(name->in_function()->name()));
-	    }
-	  pkg_path_value = this->ptr_go_string_constant_tree(n);
-	}
-    }
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
-  tree field = TYPE_FIELDS(uncommon_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = name_value;
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = pkg_path_value;
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_method_table(TREE_TYPE(field), methods,
-				       only_value_methods);
-
-  tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, create_tmp_var_name("U"),
-			 uncommon_type_tree);
-  DECL_EXTERNAL(decl) = 0;
-  TREE_PUBLIC(decl) = 0;
-  TREE_STATIC(decl) = 1;
-  TREE_CONSTANT(decl) = 1;
-  TREE_READONLY(decl) = 1;
-
-  DECL_INITIAL(decl) = build_constructor(uncommon_type_tree, init);
-
-  rest_of_decl_compilation(decl, 1, 0);
-
-  return build_fold_addr_expr(decl);
-}
-
-// Build a constructor for the basic type descriptor struct for TYPE.
-// RUNTIME_TYPE_KIND is the value to store in the __kind field.  If
-// NAME is not NULL, it is the name to use.  If METHODS is not NULL,
-// it is the list of methods to use.  If METHODS is NULL, then we get
-// the methods from NAME.  ONLY_VALUE_METHODS is true if only value
-// methods should be included.
-
-tree
-Gogo::type_descriptor_constructor(int runtime_type_kind, Type* type,
-				  Named_type* name, const Methods* methods,
-				  bool only_value_methods)
-{
-  tree type_descriptor_type_tree = this->type_descriptor_type_tree();
-  tree type_tree = type->get_tree(this);
-  if (type_tree == error_mark_node)
-    return error_mark_node;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 9);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__kind") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = build_int_cstu(TREE_TYPE(field), runtime_type_kind);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__align") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = build_int_cstu(TREE_TYPE(field), TYPE_ALIGN_UNIT(type_tree));
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
-		    "__field_align") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  unsigned HOST_WIDE_INT val = TYPE_ALIGN(type_tree);
-#ifdef BIGGEST_FIELD_ALIGNMENT
-  if (val > BIGGEST_FIELD_ALIGNMENT)
-    val = BIGGEST_FIELD_ALIGNMENT;
-#endif
-#ifdef ADJUST_FIELD_ALIGN
-  {
-    // A separate declaration avoids a warning promoted to an error if
-    // ADJUST_FIELD_ALIGN ignores FIELD.
-    tree f;
-    f = build_decl(UNKNOWN_LOCATION, FIELD_DECL, NULL, type_tree);
-    val = ADJUST_FIELD_ALIGN(f, val);
-  }
-#endif
-  elt->value = build_int_cstu(TREE_TYPE(field), val / BITS_PER_UNIT);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__size") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = TYPE_SIZE_UNIT(type_tree);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__hash") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = build_int_cst_type(TREE_TYPE(field),
-				  type->hash_for_method(this));
-
-  tree hash_fn;
-  tree equal_fn;
-  this->type_functions(type, &hash_fn, &equal_fn);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__hashfn") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = hash_fn;
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__equalfn") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = equal_fn;
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
-		    "__reflection") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->ptr_go_string_constant_tree(name != NULL
-						 ? name->reflection(this)
-						 : type->reflection(this));
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
-		    "__uncommon") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-
-  if (name == NULL && methods == NULL)
-    elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-  else
-    {
-      if (methods == NULL)
-	methods = name->methods();
-      elt->value = this->uncommon_type_information(TREE_TYPE(TREE_TYPE(field)),
-						   name, methods,
-						   only_value_methods);
-    }
-
-  tree ret = build_constructor(type_descriptor_type_tree, init);
-  TREE_CONSTANT(ret) = 1;
-  return ret;
-}
-
-// Where a type descriptor decl should be defined.
-
-Gogo::Type_descriptor_location
-Gogo::type_descriptor_location(const Type* type, Named_type* name)
-{
+  const Named_type* name = type->named_type();
   if (name != NULL)
     {
       if (name->named_object()->package() != NULL)
@@ -3032,16 +2520,15 @@
     }
 }
 
-// Create the decl which will hold the type descriptor for TYPE.
-// DESCRIPTOR_TYPE_TREE is the type of the decl to create.  NAME is
-// the name of the type; it may be NULL.  The new decl is stored into
-// *PDECL.  This returns true if we need to build the descriptor,
-// false if not.
-
-bool
-Gogo::build_type_descriptor_decl(const Type* type, tree descriptor_type_tree,
-				 Named_type* name, tree* pdecl)
+// Build a type descriptor decl for TYPE.  INITIALIZER is a struct
+// composite literal which initializers the type descriptor.
+
+void
+Gogo::build_type_descriptor_decl(const Type* type, Expression* initializer,
+				 tree* pdecl)
 {
+  const Named_type* name = type->named_type();
+
   // We can have multiple instances of unnamed types, but we only want
   // to emit the type descriptor once.  We use a hash table to handle
   // this.  This is not necessary for named types, as they are unique,
@@ -3058,7 +2545,7 @@
 	{
 	  // We've already built a type descriptor for this type.
 	  *pdecl = ins.first->second;
-	  return false;
+	  return;
 	}
       phash = &ins.first->second;
     }
@@ -3070,65 +2557,47 @@
     decl_name = this->type_descriptor_decl_name(name->named_object(),
 						name->in_function());
   tree id = get_identifier_from_string(decl_name);
+  tree descriptor_type_tree = initializer->type()->get_tree(this);
   tree decl = build_decl(name == NULL ? BUILTINS_LOCATION : name->location(),
 			 VAR_DECL, id,
 			 build_qualified_type(descriptor_type_tree,
 					      TYPE_QUAL_CONST));
   TREE_READONLY(decl) = 1;
   TREE_CONSTANT(decl) = 1;
-  DECL_ARTIFICIAL (decl) = 1;
-
-  // Store the new decl now.  This breaks a potential recursion in
-  // which the length of an array calls the len function on another
-  // array with the same type descriptor, and that other array is
-  // initialized with values which require reference count
-  // adjustments.  This may no longer be required.
+  DECL_ARTIFICIAL(decl) = 1;
+
   go_preserve_from_gc(decl);
-  *pdecl = decl;
   if (phash != NULL)
     *phash = decl;
 
+  // We store the new DECL now because we may need to refer to it when
+  // expanding INITIALIZER.
+  *pdecl = decl;
+
   // If appropriate, just refer to the exported type identifier.
-  if (this->type_descriptor_location(type, name) == TYPE_DESCRIPTOR_UNDEFINED)
+  Gogo::Type_descriptor_location type_descriptor_location =
+    this->type_descriptor_location(type);
+  if (type_descriptor_location == TYPE_DESCRIPTOR_UNDEFINED)
     {
       TREE_PUBLIC(decl) = 1;
       DECL_EXTERNAL(decl) = 1;
-      return false;
+      return;
     }
-  else
+
+  TREE_STATIC(decl) = 1;
+  TREE_USED(decl) = 1;
+
+  Translate_context context(this, NULL, NULL, NULL);
+  context.set_is_const();
+  tree constructor = initializer->get_tree(&context);
+
+  if (constructor == error_mark_node)
+    gcc_assert(saw_errors());
+
+  DECL_INITIAL(decl) = constructor;
+
+  if (type_descriptor_location == TYPE_DESCRIPTOR_COMMON)
     {
-      TREE_STATIC(decl) = 1;
-      TREE_USED(decl) = 1;
-      return true;
-    }
-}
-
-// Initialize and finish the type descriptor decl *PDECL for TYPE.
-// NAME is the name of the type; it may be NULL.  CONSTRUCTOR is the
-// value to which is should be initialized.
-
-void
-Gogo::finish_type_descriptor_decl(tree* pdecl, const Type* type,
-				  Named_type* name, tree constructor)
-{
-  unsigned int ix;
-  tree elt;
-  FOR_EACH_CONSTRUCTOR_VALUE(CONSTRUCTOR_ELTS(constructor), ix, elt)
-    {
-      if (elt == error_mark_node)
-	{
-	  constructor = error_mark_node;
-	  break;
-	}
-    }
-
-  tree decl = *pdecl;
-  DECL_INITIAL(decl) = constructor;
-
-  if (this->type_descriptor_location(type, name) == TYPE_DESCRIPTOR_COMMON)
-    {
-      // All type descriptors for the same unnamed or builtin type
-      // should be shared.
       make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
       resolve_unique_section(decl, 1, 0);
     }
@@ -3138,7 +2607,9 @@
       // Give the decl protected visibility.  This avoids out-of-range
       // references with shared libraries with the x86_64 small model
       // when the type descriptor gets a COPY reloc into the main
-      // executable.
+      // executable.  There is no need to have unique pointers to type
+      // descriptors, as the runtime code compares reflection strings
+      // if necessary.
       DECL_VISIBILITY(decl) = VISIBILITY_PROTECTED;
       DECL_VISIBILITY_SPECIFIED(decl) = 1;
 #endif
@@ -3149,783 +2620,6 @@
   rest_of_decl_compilation(decl, 1, 0);
 }
 
-// Build a type descriptor decl for TYPE.  RUNTIME_TYPE_KIND is the
-// value to store in the __kind field.  If NAME is not NULL, it is the
-// name to use as well as the list of methods.  Store the decl into
-// *PDECL.
-
-void
-Gogo::type_descriptor_decl(int runtime_type_kind, Type* type, Named_type* name,
-			   tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  tree constructor = this->type_descriptor_constructor(runtime_type_kind,
-						       type, name, NULL,
-						       true);
-
-  this->finish_type_descriptor_decl(pdecl, type, name, constructor);
-}
-
-// Build a decl for the type descriptor of an undefined type.
-
-void
-Gogo::undefined_type_descriptor_decl(Forward_declaration_type *forward,
-				     Named_type* name, tree* pdecl)
-{
-  Named_object* no = (name != NULL
-		      ? name->named_object()
-		      : forward->named_object());
-  std::string decl_name = this->type_descriptor_decl_name(no, NULL);
-  tree id = get_identifier_from_string(decl_name);
-  tree decl = build_decl(no->location(), VAR_DECL, id,
-			 this->type_descriptor_type_tree());
-  TREE_READONLY(decl) = 1;
-  TREE_CONSTANT(decl) = 1;
-  TREE_PUBLIC(decl) = 1;
-  DECL_EXTERNAL(decl) = 1;
-  go_preserve_from_gc(decl);
-  *pdecl = decl;
-}
-
-// The type of a type descriptor for a pointer.  This must match
-// struct __go_ptr_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::pointer_type_descriptor_type_tree()
-{
-  static tree ptr_descriptor_type;
-  if (ptr_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      Gogo::builtin_struct(&ptr_descriptor_type, "__go_ptr_type", NULL_TREE, 2,
-			   "__common",
-			   this->type_descriptor_type_tree(),
-			   "__element_type",
-			   build_pointer_type(common));
-    }
-  return ptr_descriptor_type;
-}
-
-// Build a type descriptor for the pointer type TYPE.
-
-void
-Gogo::pointer_type_descriptor_decl(Pointer_type* type, Named_type* name,
-				   tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->pointer_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  const Methods* methods;
-  Type* deref = type->points_to();
-  if (deref->named_type() != NULL)
-    methods = deref->named_type()->methods();
-  else if (deref->struct_type() != NULL)
-    methods = deref->struct_type()->methods();
-  else
-    methods = NULL;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_PTR, type,
-						 name, methods, false);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
-		    "__element_type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = type->points_to()->type_descriptor(this);
-
-  this->finish_type_descriptor_decl(pdecl,
-				    type,
-				    name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
-// The type of a type descriptor for a function.  This must match
-// struct __go_func_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::function_type_descriptor_type_tree()
-{
-  static tree func_descriptor_type;
-  if (func_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      tree ptr_common = build_pointer_type(common);
-      Gogo::builtin_struct(&func_descriptor_type, "__go_func_type",
-			   NULL_TREE, 4,
-			   "__common",
-			   common,
-			   "__dotdotdot",
-			   boolean_type_node,
-			   "__in",
-			   this->slice_type_tree(ptr_common),
-			   "__out",
-			   this->slice_type_tree(ptr_common));
-    }
-  return func_descriptor_type;
-}
-
-// Build a slice constructor for the parameters or results of a
-// function type.
-
-tree
-Gogo::function_type_params(tree slice_type_tree,
-			   const Typed_identifier* receiver,
-			   const Typed_identifier_list* params)
-{
-  size_t count = ((params == NULL ? 0 : params->size())
-		  + (receiver != NULL ? 1 : 0));
-  if (count == 0)
-    return Gogo::empty_slice_constructor(slice_type_tree);
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, count);
-  size_t i = 0;
-  if (receiver != NULL)
-    {
-      constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-      elt->index = size_int(i);
-      Type* rtype = receiver->type();
-      // The receiver is always passed as a pointer.
-      if (rtype->points_to() == NULL)
-	rtype = Type::make_pointer_type(rtype);
-      elt->value = rtype->type_descriptor(this);
-      ++i;
-    }
-  if (params != NULL)
-    {
-      for (Typed_identifier_list::const_iterator p = params->begin();
-	   p != params->end();
-	   ++p, ++i)
-	{
-	  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-	  elt->index = size_int(i);
-	  elt->value = p->type()->type_descriptor(this);
-	}
-    }
-  gcc_assert(i == count);
-
-  return type_descriptor_slice(slice_type_tree, init);
-}
-
-// Build a type descriptor for the function type TYPE.
-
-void
-Gogo::function_type_descriptor_decl(Function_type* type, Named_type* name,
-				    tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->function_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 4);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_FUNC, type,
-						 name, NULL, true);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__dotdotdot") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = type->is_varargs() ? boolean_true_node : boolean_false_node;
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__in") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->function_type_params(TREE_TYPE(field), type->receiver(),
-					  type->parameters());
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__out") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->function_type_params(TREE_TYPE(field), NULL,
-					  type->results());
-
-  this->finish_type_descriptor_decl(pdecl, type, name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
-// The type of a type descriptor for a struct.  This must match struct
-// __go_struct_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::struct_type_descriptor_type_tree()
-{
-  static tree struct_descriptor_type;
-  if (struct_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      tree ptr_common = build_pointer_type(common);
-
-      tree string_type_tree = Type::make_string_type()->get_tree(this);
-      tree ptr_string_type_tree = build_pointer_type(string_type_tree);
-
-      tree uintptr_type_tree =
-	Type::lookup_integer_type("uintptr")->get_tree(this);
-
-      tree struct_field_type = Gogo::builtin_struct(NULL, "__go_struct_field",
-						    NULL_TREE, 5,
-						    "__name",
-						    ptr_string_type_tree,
-						    "__pkg_path",
-						    ptr_string_type_tree,
-						    "__type",
-						    ptr_common,
-						    "__tag",
-						    ptr_string_type_tree,
-						    "__offset",
-						    uintptr_type_tree);
-
-      Gogo::builtin_struct(&struct_descriptor_type, "__go_struct_type",
-			   NULL_TREE, 2,
-			   "__common",
-			   common,
-			   "__fields",
-			   this->slice_type_tree(struct_field_type));
-    }
-  return struct_descriptor_type;
-}
-
-// Build a constructor for __go_struct_field describing a single
-// struct field.
-
-tree
-Gogo::struct_type_field(tree field_type_tree, const Struct_field* struct_field,
-			tree struct_field_tree)
-{
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 5);
-
-  tree field = TYPE_FIELDS(field_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  if (struct_field->is_anonymous())
-    elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-  else
-    {
-      std::string n = Gogo::unpack_hidden_name(struct_field->field_name());
-      elt->value = this->ptr_go_string_constant_tree(n);
-    }
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  if (!Gogo::is_hidden_name(struct_field->field_name()))
-    elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-  else
-    {
-      std::string s = Gogo::hidden_name_prefix(struct_field->field_name());
-      elt->value = this->ptr_go_string_constant_tree(s);
-    }
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = struct_field->type()->type_descriptor(this);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__tag") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  if (!struct_field->has_tag())
-    elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-  else
-    elt->value = this->ptr_go_string_constant_tree(struct_field->tag());
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__offset") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = fold_convert(TREE_TYPE(field), byte_position(struct_field_tree));
-
-  tree ret = build_constructor(field_type_tree, init);
-  TREE_CONSTANT(ret) = 1;
-  return ret;
-}
-
-// Build a slice constructor for the fields of a struct.
-
-tree
-Gogo::struct_type_fields(Struct_type* struct_type, tree slice_type_tree)
-{
-  const Struct_field_list* fields = struct_type->fields();
-  if (fields == NULL || fields->empty())
-    return Gogo::empty_slice_constructor(slice_type_tree);
-
-  tree field_type_tree = Gogo::slice_element_type_tree(slice_type_tree);
-  size_t count = fields->size();
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, count);
-  tree struct_type_tree = struct_type->get_tree(this);
-  if (struct_type_tree == error_mark_node)
-    return error_mark_node;
-  tree struct_field = TYPE_FIELDS(struct_type_tree);
-  size_t i = 0;
-  for (Struct_field_list::const_iterator p = fields->begin();
-       p != fields->end();
-       ++p, ++i, struct_field = TREE_CHAIN(struct_field))
-    {
-      gcc_assert(struct_field != NULL_TREE);
-      constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-      elt->index = size_int(i);
-      elt->value = this->struct_type_field(field_type_tree, &*p, struct_field);
-    }
-  gcc_assert(i == count && struct_field == NULL_TREE);
-
-  return type_descriptor_slice(slice_type_tree, init);
-}
-
-// Build a type descriptor for the struct type TYPE.
-
-void
-Gogo::struct_type_descriptor_decl(Struct_type* type, Named_type* name,
-				  tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->struct_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  const Methods* methods = type->methods();
-  // A named struct should not have methods--the methods should attach
-  // to the named type.
-  gcc_assert(methods == NULL || name == NULL);
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_STRUCT,
-						 type, name, methods, true);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__fields") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->struct_type_fields(type, TREE_TYPE(field));
-
-  this->finish_type_descriptor_decl(pdecl, type, name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
-// The type of a type descriptor for an array.  This must match struct
-// __go_array_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::array_type_descriptor_type_tree()
-{
-  static tree array_descriptor_type;
-  if (array_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      tree ptr_common = build_pointer_type(common);
-
-      tree uintptr_type_tree =
-	Type::lookup_integer_type("uintptr")->get_tree(this);
-
-      Gogo::builtin_struct(&array_descriptor_type, "__go_array_type",
-			   NULL_TREE, 3,
-			   "__common",
-			   common,
-			   "__element_type",
-			   ptr_common,
-			   "__len",
-			   uintptr_type_tree);
-    }
-  return array_descriptor_type;
-}
-
-// Build a type descriptor for the array type TYPE.
-
-void
-Gogo::array_type_descriptor_decl(Array_type* type, Named_type* name,
-				 tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->array_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_ARRAY,
-						 type, name, NULL, true);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
-		    "__element_type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = type->element_type()->type_descriptor(this);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__len") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = fold_convert(TREE_TYPE(field),
-			    type->length_tree(this, null_pointer_node));
-
-  this->finish_type_descriptor_decl(pdecl, type, name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
-// The type of a type descriptor for a slice.  This must match struct
-// __go_slice_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::slice_type_descriptor_type_tree()
-{
-  static tree slice_descriptor_type;
-  if (slice_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      tree ptr_common = build_pointer_type(common);
-
-      Gogo::builtin_struct(&slice_descriptor_type, "__go_slice_type",
-			   NULL_TREE, 2,
-			   "__common",
-			   common,
-			   "__element_type",
-			   ptr_common);
-    }
-  return slice_descriptor_type;
-}
-
-// Build a type descriptor for the slice type TYPE.
-
-void
-Gogo::slice_type_descriptor_decl(Array_type* type, Named_type* name,
-				 tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->slice_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_SLICE,
-						 type, name, NULL, true);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
-		    "__element_type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = type->element_type()->type_descriptor(this);
-
-  this->finish_type_descriptor_decl(pdecl, type, name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
-// The type of a type descriptor for a map.  This must match struct
-// __go_map_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::map_type_descriptor_type_tree()
-{
-  static tree map_descriptor_type;
-  if (map_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      tree ptr_common = build_pointer_type(common);
-
-      Gogo::builtin_struct(&map_descriptor_type, "__go_map_type",
-			   NULL_TREE, 3,
-			   "__common",
-			   common,
-			   "__key_type",
-			   ptr_common,
-			   "__val_type",
-			   ptr_common);
-    }
-  return map_descriptor_type;
-}
-
-// Build a type descriptor for the map type TYPE.
-
-void
-Gogo::map_type_descriptor_decl(Map_type* type, Named_type* name, tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->map_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_MAP,
-						 type, name, NULL, true);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__key_type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = type->key_type()->type_descriptor(this);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__val_type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = type->val_type()->type_descriptor(this);
-
-  this->finish_type_descriptor_decl(pdecl, type, name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
-// The type of a type descriptor for a channel.  This must match
-// struct __go_channel_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::channel_type_descriptor_type_tree()
-{
-  static tree channel_descriptor_type;
-  if (channel_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      tree ptr_common = build_pointer_type(common);
-
-      tree uintptr_type_tree =
-	Type::lookup_integer_type("uintptr")->get_tree(this);
-
-      Gogo::builtin_struct(&channel_descriptor_type, "__go_channel_type",
-			   NULL_TREE, 3,
-			   "__common",
-			   common,
-			   "__element_type",
-			   ptr_common,
-			   "__dir",
-			   uintptr_type_tree);
-    }
-  return channel_descriptor_type;
-}
-
-// Build a type descriptor for the channel type TYPE.
-
-void
-Gogo::channel_type_descriptor_decl(Channel_type* type, Named_type* name,
-				   tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->channel_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_CHAN,
-						 type, name, NULL, true);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
-		    "__element_type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = type->element_type()->type_descriptor(this);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__dir") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-
-  // These bits must match the ones in libgo/runtime/go-type.h.
-  int val = 0;
-  if (type->may_receive())
-    val |= 1;
-  if (type->may_send())
-    val |= 2;
-
-  elt->value = build_int_cst_type(TREE_TYPE(field), val);
-
-  this->finish_type_descriptor_decl(pdecl, type, name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
-// The type of a type descriptor for an interface.  This must match
-// struct __go_interface_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::interface_type_descriptor_type_tree()
-{
-  static tree interface_descriptor_type;
-  if (interface_descriptor_type == NULL_TREE)
-    {
-      tree common = this->type_descriptor_type_tree();
-      tree ptr_common = build_pointer_type(common);
-
-      tree string_type_tree = Type::make_string_type()->get_tree(this);
-      tree ptr_string_type_tree = build_pointer_type(string_type_tree);
-
-      tree method_type = Gogo::builtin_struct(NULL, "__go_interface_method",
-					      NULL_TREE, 3,
-					      "__name",
-					      ptr_string_type_tree,
-					      "__pkg_path",
-					      ptr_string_type_tree,
-					      "__type",
-					      ptr_common);
-
-      Gogo::builtin_struct(&interface_descriptor_type, "__go_interface_type",
-			   NULL_TREE, 2,
-			   "__common",
-			   common,
-			   "__methods",
-			   this->slice_type_tree(method_type));
-    }
-  return interface_descriptor_type;
-}
-
-// Build a constructor for __go_interface_method describing a single
-// interface method.
-
-tree
-Gogo::interface_type_method(tree method_type_tree,
-			    const Typed_identifier* method)
-{
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
-  tree field = TYPE_FIELDS(method_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  std::string n = Gogo::unpack_hidden_name(method->name());
-  elt->value = this->ptr_go_string_constant_tree(n);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index= field;
-  if (!Gogo::is_hidden_name(method->name()))
-    elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-  else
-    {
-      std::string s = Gogo::hidden_name_prefix(method->name());
-      elt->value = this->ptr_go_string_constant_tree(s);
-    }
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__type") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = method->type()->type_descriptor(this);
-
-  tree ret = build_constructor(method_type_tree, init);
-  TREE_CONSTANT(ret) = 1;
-  return ret;
-}
-
-// Build a slice constructor for the methods of an interface.
-
-tree
-Gogo::interface_type_methods(const Interface_type* interface_type,
-			     tree slice_type_tree)
-{
-  const Typed_identifier_list* methods = interface_type->methods();
-  if (methods == NULL)
-    return Gogo::empty_slice_constructor(slice_type_tree);
-  gcc_assert(!methods->empty());
-
-  tree method_type_tree = Gogo::slice_element_type_tree(slice_type_tree);
-  size_t count = methods->size();
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, count);
-  size_t i = 0;
-  for (Typed_identifier_list::const_iterator p = methods->begin();
-       p != methods->end();
-       ++p, ++i)
-    {
-      constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-      elt->index = size_int(i);
-      elt->value = this->interface_type_method(method_type_tree, &*p);
-    }
-  gcc_assert(i == count);
-
-  return type_descriptor_slice(slice_type_tree, init);
-}
-
-// Build a type descriptor for the interface type TYPE.
-
-void
-Gogo::interface_type_descriptor_decl(Interface_type* type, Named_type* name,
-				     tree* pdecl)
-{
-  tree type_descriptor_type_tree = this->interface_type_descriptor_type_tree();
-
-  if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
-					name, pdecl))
-    return;
-
-  VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
-  tree field = TYPE_FIELDS(type_descriptor_type_tree);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
-  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_INTERFACE,
-						 type, name, NULL, true);
-
-  field = TREE_CHAIN(field);
-  gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods") == 0);
-  elt = VEC_quick_push(constructor_elt, init, NULL);
-  elt->index = field;
-  elt->value = this->interface_type_methods(type, TREE_TYPE(field));
-
-  this->finish_type_descriptor_decl(pdecl, type, name,
-				    build_constructor(type_descriptor_type_tree,
-						      init));
-}
-
 // Build an interface method table for a type: a list of function
 // pointers, one for each interface method.  This is used for
 // interfaces.
@@ -3987,7 +2681,7 @@
   else
     td_type = Type::make_pointer_type(type);
   elt->value = fold_convert(const_ptr_type_node,
-			    td_type->type_descriptor(this));
+			    td_type->type_descriptor_pointer(this));
 
   size_t i = 1;
   for (Typed_identifier_list::const_iterator p = interface_methods->begin();
diff -r 702d88f9b3d3 go/gogo.h
--- a/go/gogo.h	Fri Oct 08 13:54:30 2010 -0700
+++ b/go/gogo.h	Fri Oct 22 12:31:01 2010 -0700
@@ -456,55 +456,11 @@
   tree
   map_descriptor_type();
 
-  // Return a tree for the type of a type descriptor.  This is
-  // __go_type_descriptor in libgo/runtime/go-type.h.
-  tree
-  type_descriptor_type_tree();
-
-  // Build a type descriptor for TYPE using RUNTIME_TYPE_KIND as the
-  // code.  NAME is the name of the type; it may be NULL.  PACKAGE is
-  // where the type is defined; it will be NULL for the current file.
-  // Store the DECL of the descriptor in *PDECL.
+  // Build a type descriptor for TYPE using INITIALIZER as the type
+  // descriptor.  This builds a new decl stored in *PDECL.
   void
-  type_descriptor_decl(int runtime_type_code, Type*, Named_type* name,
-		       tree* pdecl);
-
-  // Build a pointer type descriptor.
-  void
-  pointer_type_descriptor_decl(Pointer_type*, Named_type*, tree* pdecl);
-
-  // Build a function type descriptor.
-  void
-  function_type_descriptor_decl(Function_type*, Named_type*, tree* pdecl);
-
-  // Build a type descriptor for a struct.
-  void
-  struct_type_descriptor_decl(Struct_type*, Named_type*, tree* pdecl);
-
-  // Build a type descriptor for a fixed array.
-  void
-  array_type_descriptor_decl(Array_type*, Named_type*, tree* pdecl);
-
-  // Build a type descriptor for a slice.
-  void
-  slice_type_descriptor_decl(Array_type*, Named_type*, tree* pdecl);
-
-  // Build a type descriptor for a map.
-  void
-  map_type_descriptor_decl(Map_type*, Named_type*, tree* pdecl);
-
-  // Build a type descriptor for a channel.
-  void
-  channel_type_descriptor_decl(Channel_type*, Named_type*, tree* pdecl);
-
-  // Build a type descriptor for an interface.
-  void
-  interface_type_descriptor_decl(Interface_type*, Named_type*, tree* pdecl);
-
-  // Build a type descriptor for an undefined type.
-  void
-  undefined_type_descriptor_decl(Forward_declaration_type* forward,
-				 Named_type* name, tree* pdecl);
+  build_type_descriptor_decl(const Type*, Expression* initializer,
+			     tree* pdecl);
 
   // Build required interface method tables.
   void
@@ -629,27 +585,6 @@
   type_descriptor_decl_name(const Named_object* no,
 			    const Named_object* in_function);
 
-  // Return a constructor for one entry in a method table.
-  tree
-  type_method_table_entry(tree method_entry_tree,
-			  const std::string& method_name, const Method*);
-
-  // Return the method table for a type.
-  tree
-  type_method_table(tree method_type_tree, const Methods*,
-		    bool only_value_methods);
-
-  // Return the uncommon type information for a type descriptor.
-  tree
-  uncommon_type_information(tree uncommon_type_tree, Named_type* name,
-			    const Methods*, bool only_value_methods);
-
-  // Return a constructor for the basic type descriptor for TYPE.
-  tree
-  type_descriptor_constructor(int runtime_type_code, Type* type,
-			      Named_type* name, const Methods*,
-			      bool only_value_methods);
-
   // Where a type descriptor should be defined.
   enum Type_descriptor_location
     {
@@ -663,74 +598,7 @@
 
   // Return where the decl for TYPE should be defined.
   Type_descriptor_location
-  type_descriptor_location(const Type* type, Named_type*);
-
-  // Create a type descriptor decl.
-  bool
-  build_type_descriptor_decl(const Type*, tree, Named_type*, tree*);
-
-  // Finish building a type descriptor decl.
-  void
-  finish_type_descriptor_decl(tree*, const Type*, Named_type*, tree);
-
-  // Return the type of a pointer type descriptor.
-  tree
-  pointer_type_descriptor_type_tree();
-
-  // Return the type of a function type descriptor.
-  tree
-  function_type_descriptor_type_tree();
-
-  // Return a constructor for parameters or results of a function type
-  // in a type descriptor.
-  tree
-  function_type_params(tree, const Typed_identifier*,
-		       const Typed_identifier_list*);
-
-  // Return the type of a struct type descriptor.
-  tree
-  struct_type_descriptor_type_tree();
-
-  // A single struct field in a type descriptor.
-  tree
-  struct_type_field(tree, const Struct_field*, tree);
-
-  // Struct fields in a type descriptor.
-  tree
-  struct_type_fields(Struct_type*, tree);
-
-  // Return the type of an array type descriptor.
-  tree
-  array_type_descriptor_type_tree();
-
-  // Return the type of a slice type descriptor.
-  tree
-  slice_type_descriptor_type_tree();
-
-  // Return the type of an map type descriptor.
-  tree
-  map_type_descriptor_type_tree();
-
-  // Return the type of a channel type descriptor.
-  tree
-  channel_type_descriptor_type_tree();
-
-  // Return the type of an interface type descriptor.
-  tree
-  interface_type_descriptor_type_tree();
-
-  // Build a single method in an interface type descriptor.
-  tree
-  interface_type_method(tree, const Typed_identifier*);
-
-  // Build the methods in an interface type descriptor.
-  tree
-  interface_type_methods(const Interface_type*, tree);
-
-  // Return pointers to functions which compute a hash code for TYPE
-  // and which compare whether two objects of type TYPE are equal.
-  void
-  type_functions(const Type* type, tree* hash_fn, tree* equal_fn);
+  type_descriptor_location(const Type* type);
 
   // Return the type of a trampoline.
   static tree
@@ -2523,7 +2391,8 @@
  public:
   Translate_context(Gogo* gogo, Named_object* function, Block* block,
 		    tree block_tree)
-    : gogo_(gogo), function_(function), block_(block), block_tree_(block_tree)
+    : gogo_(gogo), function_(function), block_(block), block_tree_(block_tree),
+      is_const_(false)
   { }
 
   // Accessors.
@@ -2544,6 +2413,15 @@
   block_tree()
   { return this->block_tree_; }
 
+  bool
+  is_const()
+  { return this->is_const_; }
+
+  // Make a constant context.
+  void
+  set_is_const()
+  { this->is_const_ = true; }
+
  private:
   // The IR for the entire compilation unit.
   Gogo* gogo_;
@@ -2553,6 +2431,9 @@
   Block *block_;
   // The BLOCK node for the current block.
   tree block_tree_;
+  // Whether this is being evaluated in a constant context.  This is
+  // used for type descriptor initializers.
+  bool is_const_;
 };
 
 // Runtime error codes.  These must match the values in
diff -r 702d88f9b3d3 go/types.cc
--- a/go/types.cc	Fri Oct 08 13:54:30 2010 -0700
+++ b/go/types.cc	Fri Oct 22 12:31:01 2010 -0700
@@ -819,32 +819,540 @@
   gcc_unreachable();
 }
 
-// Return a type descriptor for this type.
+// Return a pointer to the type descriptor for this type.
 
 tree
-Type::type_descriptor(Gogo* gogo)
-{
-  if (this->type_descriptor_decl_ == NULL_TREE)
-    {
-      this->do_type_descriptor_decl(gogo, NULL, &this->type_descriptor_decl_);
-      gcc_assert(this->type_descriptor_decl_ != NULL_TREE
-		 && (this->type_descriptor_decl_ == error_mark_node
-		     || DECL_P(this->type_descriptor_decl_)));
-    }
-  if (this->type_descriptor_decl_ == error_mark_node)
+Type::type_descriptor_pointer(Gogo* gogo)
+{
+  Type* t = this->forwarded();
+  if (t->type_descriptor_decl_ == NULL_TREE)
+    {
+      Expression* e = t->do_type_descriptor(gogo, NULL);
+      gogo->build_type_descriptor_decl(t, e, &t->type_descriptor_decl_);
+      gcc_assert(t->type_descriptor_decl_ != NULL_TREE
+		 && (t->type_descriptor_decl_ == error_mark_node
+		     || DECL_P(t->type_descriptor_decl_)));
+    }
+  if (t->type_descriptor_decl_ == error_mark_node)
     return error_mark_node;
-  return build_fold_addr_expr(this->type_descriptor_decl_);
-}
-
-// Set *PDECL to the decl for a type descriptor for TYPE with name
-// NAME.
+  return build_fold_addr_expr(t->type_descriptor_decl_);
+}
+
+// Return a composite literal for a type descriptor.
+
+Expression*
+Type::type_descriptor(Gogo* gogo, Type* type)
+{
+  return type->do_type_descriptor(gogo, NULL);
+}
+
+// Return a composite literal for a type descriptor with a name.
+
+Expression*
+Type::named_type_descriptor(Gogo* gogo, Type* type, Named_type* name)
+{
+  gcc_assert(name != NULL && type->named_type() != name);
+  return type->do_type_descriptor(gogo, name);
+}
+
+// Make a builtin struct type from a list of fields.  The fields are
+// pairs of a name and a type.
+
+Struct_type*
+Type::make_builtin_struct_type(int nfields, ...)
+{
+  va_list ap;
+  va_start(ap, nfields);
+
+  source_location bloc = BUILTINS_LOCATION;
+  Struct_field_list* sfl = new Struct_field_list();
+  for (int i = 0; i < nfields; i++)
+    {
+      const char* field_name = va_arg(ap, const char *);
+      Type* type = va_arg(ap, Type*);
+      sfl->push_back(Struct_field(Typed_identifier(field_name, type, bloc)));
+    }
+
+  va_end(ap);
+
+  return Type::make_struct_type(sfl, bloc);
+}
+
+// Make a builtin named type.
+
+Named_type*
+Type::make_builtin_named_type(const char* name, Type* type)
+{
+  source_location bloc = BUILTINS_LOCATION;
+  Named_object* no = Named_object::make_type(name, NULL, type, bloc);
+  return no->type_value();
+}
+
+// Return the type of a type descriptor.  We should really tie this to
+// runtime.Type rather than copying it.  This must match commonType in
+// libgo/go/runtime/type.go.
+
+Type*
+Type::make_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      source_location bloc = BUILTINS_LOCATION;
+
+      Type* uint8_type = Type::lookup_integer_type("uint8");
+      Type* uint32_type = Type::lookup_integer_type("uint32");
+      Type* uintptr_type = Type::lookup_integer_type("uintptr");
+      Type* string_type = Type::lookup_string_type();
+      Type* pointer_string_type = Type::make_pointer_type(string_type);
+
+      // This is an unnamed version of unsafe.Pointer.  Perhaps we
+      // should use the named version instead, although that would
+      // require us to create the unsafe package if it has not been
+      // imported.  It probably doesn't matter.
+      Type* void_type = Type::make_void_type();
+      Type* unsafe_pointer_type = Type::make_pointer_type(void_type);
+
+      // Forward declaration for the type descriptor type.
+      Named_object* named_type_descriptor_type =
+	Named_object::make_type_declaration("commonType", NULL, bloc);
+      Type* ft = Type::make_forward_declaration(named_type_descriptor_type);
+      Type* pointer_type_descriptor_type = Type::make_pointer_type(ft);
+
+      // The type of a method on a concrete type.
+      Struct_type* method_type =
+	Type::make_builtin_struct_type(5,
+				       "name", pointer_string_type,
+				       "pkgPath", pointer_string_type,
+				       "mtyp", pointer_type_descriptor_type,
+				       "typ", pointer_type_descriptor_type,
+				       "tfn", unsafe_pointer_type);
+      Named_type* named_method_type =
+	Type::make_builtin_named_type("method", method_type);
+
+      // Information for types with a name or methods.
+      Type* slice_named_method_type =
+	Type::make_array_type(named_method_type, NULL);
+      Struct_type* uncommon_type =
+	Type::make_builtin_struct_type(3,
+				       "name", pointer_string_type,
+				       "pkgPath", pointer_string_type,
+				       "methods", slice_named_method_type);
+      Named_type* named_uncommon_type =
+	Type::make_builtin_named_type("uncommonType", uncommon_type);
+
+      Type* pointer_uncommon_type =
+	Type::make_pointer_type(named_uncommon_type);
+
+      // The type descriptor type.
+
+      Typed_identifier_list* params = new Typed_identifier_list();
+      params->push_back(Typed_identifier("", unsafe_pointer_type, bloc));
+      params->push_back(Typed_identifier("", uintptr_type, bloc));
+
+      Typed_identifier_list* results = new Typed_identifier_list();
+      results->push_back(Typed_identifier("", uintptr_type, bloc));
+
+      Type* hashfn_type = Type::make_function_type(NULL, params, results, bloc);
+
+      params = new Typed_identifier_list();
+      params->push_back(Typed_identifier("", unsafe_pointer_type, bloc));
+      params->push_back(Typed_identifier("", unsafe_pointer_type, bloc));
+      params->push_back(Typed_identifier("", uintptr_type, bloc));
+
+      results = new Typed_identifier_list();
+      results->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
+
+      Type* equalfn_type = Type::make_function_type(NULL, params, results,
+						    bloc);
+
+      Struct_type* type_descriptor_type =
+	Type::make_builtin_struct_type(9,
+				       "Kind", uint8_type,
+				       "align", uint8_type,
+				       "fieldAlign", uint8_type,
+				       "size", uintptr_type,
+				       "hash", uint32_type,
+				       "hashfn", hashfn_type,
+				       "equalfn", equalfn_type,
+				       "string", pointer_string_type,
+				       "", pointer_uncommon_type);
+
+      Named_type* named = Type::make_builtin_named_type("commonType",
+							type_descriptor_type);
+
+      named_type_descriptor_type->set_type_value(named);
+
+      ret = named;
+    }
+
+  return ret;
+}
+
+// Make the type of a pointer to a type descriptor as represented in
+// Go.
+
+Type*
+Type::make_type_descriptor_ptr_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    ret = Type::make_pointer_type(Type::make_type_descriptor_type());
+  return ret;
+}
+
+// Return the names of runtime functions which compute a hash code for
+// this type and which compare whether two values of this type are
+// equal.
 
 void
-Type::named_type_descriptor(Gogo* gogo, Type* type, Named_type* name,
-			    tree* pdecl)
-{
-  gcc_assert(name != NULL && type->named_type() != name);
-  type->do_type_descriptor_decl(gogo, name, pdecl);
+Type::type_functions(const char** hash_fn, const char** equal_fn) const
+{
+  switch (this->base()->classification())
+    {
+    case Type::TYPE_ERROR:
+    case Type::TYPE_VOID:
+    case Type::TYPE_NIL:
+      // These types can not be hashed or compared.
+      *hash_fn = "__go_type_hash_error";
+      *equal_fn = "__go_type_equal_error";
+      break;
+
+    case Type::TYPE_BOOLEAN:
+    case Type::TYPE_INTEGER:
+    case Type::TYPE_FLOAT:
+    case Type::TYPE_COMPLEX:
+    case Type::TYPE_POINTER:
+    case Type::TYPE_FUNCTION:
+    case Type::TYPE_MAP:
+    case Type::TYPE_CHANNEL:
+      *hash_fn = "__go_type_hash_identity";
+      *equal_fn = "__go_type_equal_identity";
+      break;
+
+    case Type::TYPE_STRING:
+      *hash_fn = "__go_type_hash_string";
+      *equal_fn = "__go_type_equal_string";
+      break;
+
+    case Type::TYPE_STRUCT:
+    case Type::TYPE_ARRAY:
+      // These types can not be hashed or compared.
+      *hash_fn = "__go_type_hash_error";
+      *equal_fn = "__go_type_equal_error";
+      break;
+
+    case Type::TYPE_INTERFACE:
+      if (this->interface_type()->is_empty())
+	{
+	  *hash_fn = "__go_type_hash_empty_interface";
+	  *equal_fn = "__go_type_equal_empty_interface";
+	}
+      else
+	{
+	  *hash_fn = "__go_type_hash_interface";
+	  *equal_fn = "__go_type_equal_interface";
+	}
+      break;
+
+    case Type::TYPE_NAMED:
+    case Type::TYPE_FORWARD:
+      gcc_unreachable();
+
+    default:
+      gcc_unreachable();
+    }
+}
+
+// Return a composite literal for the type descriptor for a plain type
+// of kind RUNTIME_TYPE_KIND named NAME.
+
+Expression*
+Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
+				  Named_type* name, const Methods* methods,
+				  bool only_value_methods)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* td_type = Type::make_type_descriptor_type();
+  const Struct_field_list* fields = td_type->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(9);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "Kind");
+  mpz_t iv;
+  mpz_init_set_ui(iv, runtime_type_kind);
+  vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "align");
+  Expression::Type_info type_info = Expression::TYPE_INFO_ALIGNMENT;
+  vals->push_back(Expression::make_type_info(this, type_info));
+
+  ++p;
+  gcc_assert(p->field_name() == "fieldAlign");
+  type_info = Expression::TYPE_INFO_FIELD_ALIGNMENT;
+  vals->push_back(Expression::make_type_info(this, type_info));
+
+  ++p;
+  gcc_assert(p->field_name() == "size");
+  type_info = Expression::TYPE_INFO_SIZE;
+  vals->push_back(Expression::make_type_info(this, type_info));
+
+  ++p;
+  gcc_assert(p->field_name() == "hash");
+  mpz_set_ui(iv, this->hash_for_method(gogo));
+  vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
+
+  const char* hash_fn;
+  const char* equal_fn;
+  this->type_functions(&hash_fn, &equal_fn);
+
+  ++p;
+  gcc_assert(p->field_name() == "hashfn");
+  Function_type* fntype = p->type()->function_type();
+  Named_object* no = Named_object::make_function_declaration(hash_fn, NULL,
+							     fntype,
+							     bloc);
+  no->func_declaration_value()->set_asm_name(hash_fn);
+  vals->push_back(Expression::make_func_reference(no, NULL, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "equalfn");
+  fntype = p->type()->function_type();
+  no = Named_object::make_function_declaration(equal_fn, NULL, fntype, bloc);
+  no->func_declaration_value()->set_asm_name(equal_fn);
+  vals->push_back(Expression::make_func_reference(no, NULL, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "string");
+  Expression* s = Expression::make_string((name != NULL
+					   ? name->reflection(gogo)
+					   : this->reflection(gogo)),
+					  bloc);
+  vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "uncommonType");
+  if (name == NULL && methods == NULL)
+    vals->push_back(Expression::make_nil(bloc));
+  else
+    {
+      if (methods == NULL)
+	methods = name->methods();
+      vals->push_back(this->uncommon_type_constructor(gogo,
+						      p->type()->deref(),
+						      name, methods,
+						      only_value_methods));
+    }
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  mpz_clear(iv);
+
+  return Expression::make_struct_composite_literal(td_type, vals, bloc);
+}
+
+// Return a composite literal for the uncommon type information for
+// this type.  UNCOMMON_STRUCT_TYPE is the type of the uncommon type
+// struct.  If name is not NULL, it is the name of the type.  If
+// METHODS is not NULL, it is the list of methods.  ONLY_VALUE_METHODS
+// is true if only value methods should be included.  At least one of
+// NAME and METHODS must not be NULL.
+
+Expression*
+Type::uncommon_type_constructor(Gogo* gogo, Type* uncommon_type,
+				Named_type* name, const Methods* methods,
+				bool only_value_methods) const
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  const Struct_field_list* fields = uncommon_type->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(3);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "name");
+
+  ++p;
+  gcc_assert(p->field_name() == "pkgPath");
+
+  if (name == NULL)
+    {
+      vals->push_back(Expression::make_nil(bloc));
+      vals->push_back(Expression::make_nil(bloc));
+    }
+  else
+    {
+      Named_object* no = name->named_object();
+      std::string n = Gogo::unpack_hidden_name(no->name());
+      Expression* s = Expression::make_string(n, bloc);
+      vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+
+      if (name->is_builtin())
+	vals->push_back(Expression::make_nil(bloc));
+      else
+	{
+	  const Package* package = no->package();
+	  const std::string& unique_prefix(package == NULL
+					   ? gogo->unique_prefix()
+					   : package->unique_prefix());
+	  const std::string& package_name(package == NULL
+					  ? gogo->package_name()
+					  : package->name());
+	  n.assign(unique_prefix);
+	  n.append(1, '.');
+	  n.append(package_name);
+	  if (name->in_function() != NULL)
+	    {
+	      n.append(1, '.');
+	      n.append(Gogo::unpack_hidden_name(name->in_function()->name()));
+	    }
+	  s = Expression::make_string(n, bloc);
+	  vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+	}
+    }
+
+  ++p;
+  gcc_assert(p->field_name() == "methods");
+  vals->push_back(this->methods_constructor(gogo, p->type(), methods,
+					    only_value_methods));
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  Expression* r = Expression::make_struct_composite_literal(uncommon_type,
+							    vals, bloc);
+  return Expression::make_unary(OPERATOR_AND, r, bloc);
+}
+
+// Sort methods by name.
+
+class Sort_methods
+{
+ public:
+  bool
+  operator()(const std::pair<std::string, const Method*>& m1,
+	     const std::pair<std::string, const Method*>& m2) const
+  { return m1.first < m2.first; }
+};
+
+// Return a composite literal for the type method table for this type.
+// METHODS_TYPE is the type of the table, and is a slice type.
+// METHODS is the list of methods.  If ONLY_VALUE_METHODS is true,
+// then only value methods are used.
+
+Expression*
+Type::methods_constructor(Gogo* gogo, Type* methods_type,
+			  const Methods* methods,
+			  bool only_value_methods) const
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  std::vector<std::pair<std::string, const Method*> > smethods;
+  if (methods != NULL)
+    {
+      smethods.reserve(methods->count());
+      for (Methods::const_iterator p = methods->begin();
+	   p != methods->end();
+	   ++p)
+	{
+	  if (p->second->is_ambiguous())
+	    continue;
+	  if (only_value_methods && !p->second->is_value_method())
+	    continue;
+	  smethods.push_back(std::make_pair(p->first, p->second));
+	}
+    }
+
+  if (smethods.empty())
+    return Expression::make_slice_composite_literal(methods_type, NULL, bloc);
+
+  std::sort(smethods.begin(), smethods.end(), Sort_methods());
+
+  Type* method_type = methods_type->array_type()->element_type();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(smethods.size());
+  for (std::vector<std::pair<std::string, const Method*> >::const_iterator p
+	 = smethods.begin();
+       p != smethods.end();
+       ++p)
+    vals->push_back(this->method_constructor(gogo, method_type, p->first,
+					     p->second));
+
+  return Expression::make_slice_composite_literal(methods_type, vals, bloc);
+}
+
+// Return a composite literal for a single method.  METHOD_TYPE is the
+// type of the entry.  METHOD_NAME is the name of the method and M is
+// the method information.
+
+Expression*
+Type::method_constructor(Gogo*, Type* method_type,
+			 const std::string& method_name,
+			 const Method* m) const
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  const Struct_field_list* fields = method_type->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(5);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "name");
+  const std::string n = Gogo::unpack_hidden_name(method_name);
+  Expression* s = Expression::make_string(n, bloc);
+  vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "pkgPath");
+  if (!Gogo::is_hidden_name(method_name))
+    vals->push_back(Expression::make_nil(bloc));
+  else
+    {
+      s = Expression::make_string(Gogo::hidden_name_prefix(method_name), bloc);
+      vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+    }
+
+  Function_type* mtype = m->type();
+  gcc_assert(mtype->is_method());
+  Type* nonmethod_type = mtype->copy_without_receiver();
+
+  ++p;
+  gcc_assert(p->field_name() == "mtyp");
+  vals->push_back(Expression::make_type_descriptor(nonmethod_type, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "typ");
+  vals->push_back(Expression::make_type_descriptor(mtype, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "tfn");
+  vals->push_back(Expression::make_func_reference(m->named_object(), NULL,
+						  bloc));
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  return Expression::make_struct_composite_literal(method_type, vals, bloc);
+}
+
+// Return a composite literal for the type descriptor of a plain type.
+// RUNTIME_TYPE_KIND is the value of the kind field.  If NAME is not
+// NULL, it is the name to use as well as the list of methods.
+
+Expression*
+Type::plain_type_descriptor(Gogo* gogo, int runtime_type_kind,
+			    Named_type* name)
+{
+  return this->type_descriptor_constructor(gogo, runtime_type_kind,
+					   name, NULL, true);
 }
 
 // Return the type reflection string for this type.
@@ -929,9 +1437,9 @@
   do_get_init_tree(Gogo*, tree, bool)
   { return error_mark_node; }
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree* pdecl)
-  { *pdecl = error_mark_node; }
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*)
+  { return Expression::make_error(BUILTINS_LOCATION); }
 
   void
   do_reflection(Gogo*, std::string*) const
@@ -967,8 +1475,8 @@
   do_get_init_tree(Gogo*, tree, bool)
   { gcc_unreachable(); }
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*)
   { gcc_unreachable(); }
 
   void
@@ -1005,8 +1513,8 @@
   do_get_init_tree(Gogo*, tree type_tree, bool is_clear)
   { return is_clear ? NULL : fold_convert(type_tree, boolean_false_node); }
 
-  void
-  do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type* name);
 
   // We should not be asked for the reflection string of a basic type.
   void
@@ -1020,16 +1528,16 @@
 
 // Make the type descriptor.
 
-void
-Boolean_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+Boolean_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   if (name != NULL)
-    gogo->type_descriptor_decl(RUNTIME_TYPE_KIND_BOOL, this, name, pdecl);
+    return this->plain_type_descriptor(gogo, RUNTIME_TYPE_KIND_BOOL, name);
   else
     {
       Named_object* no = gogo->lookup_global("bool");
       gcc_assert(no != NULL);
-      *pdecl = build_fold_indirect_ref(no->type_value()->type_descriptor(gogo));
+      return Type::type_descriptor(gogo, no->type_value());
     }
 }
 
@@ -1180,11 +1688,11 @@
 // The type descriptor for an integer type.  Integer types are always
 // named.
 
-void
-Integer_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+Integer_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   gcc_assert(name != NULL);
-  gogo->type_descriptor_decl(this->runtime_type_kind_, this, name, pdecl);
+  return this->plain_type_descriptor(gogo, this->runtime_type_kind_, name);
 }
 
 // We should not be asked for the reflection string of a basic type.
@@ -1337,11 +1845,11 @@
 
 // The type descriptor for a float type.  Float types are always named.
 
-void
-Float_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+Float_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   gcc_assert(name != NULL);
-  gogo->type_descriptor_decl(this->runtime_type_kind_, this, name, pdecl);
+  return this->plain_type_descriptor(gogo, this->runtime_type_kind_, name);
 }
 
 // We should not be asked for the reflection string of a basic type.
@@ -1498,12 +2006,11 @@
 // The type descriptor for a complex type.  Complex types are always
 // named.
 
-void
-Complex_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
-				      tree* pdecl)
+Expression*
+Complex_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   gcc_assert(name != NULL);
-  gogo->type_descriptor_decl(this->runtime_type_kind_, this, name, pdecl);
+  return this->plain_type_descriptor(gogo, this->runtime_type_kind_, name);
 }
 
 // We should not be asked for the reflection string of a basic type.
@@ -1622,16 +2129,16 @@
 
 // The type descriptor for the string type.
 
-void
-String_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+String_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   if (name != NULL)
-    gogo->type_descriptor_decl(RUNTIME_TYPE_KIND_STRING, this, name, pdecl);
+    return this->plain_type_descriptor(gogo, RUNTIME_TYPE_KIND_STRING, name);
   else
     {
       Named_object* no = gogo->lookup_global("string");
       gcc_assert(no != NULL);
-      *pdecl = build_fold_indirect_ref(no->type_value()->type_descriptor(gogo));
+      return Type::type_descriptor(gogo, no->type_value());
     }
 }
 
@@ -1705,8 +2212,8 @@
   do_get_init_tree(Gogo*, tree, bool)
   { gcc_unreachable(); }
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*)
   { gcc_unreachable(); }
 
   void
@@ -2070,13 +2577,109 @@
   return fold_convert(type_tree, null_pointer_node);
 }
 
-// The type descriptor for a function.
-
-void
-Function_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
-				       tree* pdecl)
-{
-  gogo->function_type_descriptor_decl(this, name, pdecl);
+// The type of a function type descriptor.
+
+Type*
+Function_type::make_function_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Type* bool_type = Type::lookup_bool_type();
+
+      Type* slice_type = Type::make_array_type(ptdt, NULL);
+
+      Struct_type* s = Type::make_builtin_struct_type(4,
+						      "", tdt,
+						      "dotdotdot", bool_type,
+						      "in", slice_type,
+						      "out", slice_type);
+
+      ret = Type::make_builtin_named_type("FuncType", s);
+    }
+
+  return ret;
+}
+
+// The type descriptor for a function type.
+
+Expression*
+Function_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* ftdt = Function_type::make_function_type_descriptor_type();
+
+  const Struct_field_list* fields = ftdt->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(4);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "commonType");
+  vals->push_back(this->type_descriptor_constructor(gogo,
+						    RUNTIME_TYPE_KIND_FUNC,
+						    name, NULL, true));
+
+  ++p;
+  gcc_assert(p->field_name() == "dotdotdot");
+  vals->push_back(Expression::make_boolean(this->is_varargs(), bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "in");
+  vals->push_back(this->type_descriptor_params(p->type(), this->receiver(),
+					       this->parameters()));
+
+  ++p;
+  gcc_assert(p->field_name() == "out");
+  vals->push_back(this->type_descriptor_params(p->type(), NULL,
+					       this->results()));
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  return Expression::make_struct_composite_literal(ftdt, vals, bloc);
+}
+
+// Return a composite literal for the parameters or results of a type
+// descriptor.
+
+Expression*
+Function_type::type_descriptor_params(Type* params_type,
+				      const Typed_identifier* receiver,
+				      const Typed_identifier_list* params)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  if (receiver == NULL && params == NULL)
+    return Expression::make_slice_composite_literal(params_type, NULL, bloc);
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve((params == NULL ? 0 : params->size())
+		+ (receiver != NULL ? 1 : 0));
+
+  if (receiver != NULL)
+    {
+      Type* rtype = receiver->type();
+      // The receiver is always passed as a pointer.  FIXME: Is this
+      // right?  Should that fact affect the type descriptor?
+      if (rtype->points_to() == NULL)
+	rtype = Type::make_pointer_type(rtype);
+      vals->push_back(Expression::make_type_descriptor(rtype, bloc));
+    }
+
+  if (params != NULL)
+    {
+      for (Typed_identifier_list::const_iterator p = params->begin();
+	   p != params->end();
+	   ++p)
+	vals->push_back(Expression::make_type_descriptor(p->type(), bloc));
+    }
+
+  return Expression::make_slice_composite_literal(params_type, vals, bloc);
 }
 
 // The reflection string.
@@ -2396,18 +2999,70 @@
   return fold_convert(type_tree, null_pointer_node);
 }
 
-// The type descriptor.
-
-void
-Pointer_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
-  if (!this->is_unsafe_pointer_type())
-    gogo->pointer_type_descriptor_decl(this, name, pdecl);
+// The type of a pointer type descriptor.
+
+Type*
+Pointer_type::make_pointer_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Struct_type* s = Type::make_builtin_struct_type(2,
+						      "", tdt,
+						      "elem", ptdt);
+
+      ret = Type::make_builtin_named_type("PtrType", s);
+    }
+
+  return ret;
+}
+
+// The type descriptor for a pointer type.
+
+Expression*
+Pointer_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  if (this->is_unsafe_pointer_type())
+    {
+      gcc_assert(name != NULL);
+      return this->plain_type_descriptor(gogo,
+					 RUNTIME_TYPE_KIND_UNSAFE_POINTER,
+					 name);
+    }
   else
     {
-      gcc_assert(name != NULL);
-      gogo->type_descriptor_decl(RUNTIME_TYPE_KIND_UNSAFE_POINTER, this,
-				 name, pdecl);
+      source_location bloc = BUILTINS_LOCATION;
+
+      const Methods* methods;
+      Type* deref = this->points_to();
+      if (deref->named_type() != NULL)
+	methods = deref->named_type()->methods();
+      else if (deref->struct_type() != NULL)
+	methods = deref->struct_type()->methods();
+      else
+	methods = NULL;
+
+      Type* ptr_tdt = Pointer_type::make_pointer_type_descriptor_type();
+
+      const Struct_field_list* fields = ptr_tdt->struct_type()->fields();
+
+      Expression_list* vals = new Expression_list();
+      vals->reserve(2);
+
+      Struct_field_list::const_iterator p = fields->begin();
+      gcc_assert(p->field_name() == "commonType");
+      vals->push_back(this->type_descriptor_constructor(gogo,
+							RUNTIME_TYPE_KIND_PTR,
+							name, methods, false));
+
+      ++p;
+      gcc_assert(p->field_name() == "elem");
+      vals->push_back(Expression::make_type_descriptor(deref, bloc));
+
+      return Expression::make_struct_composite_literal(ptr_tdt, vals, bloc);
     }
 }
 
@@ -2491,8 +3146,8 @@
   do_get_init_tree(Gogo*, tree type_tree, bool is_clear)
   { return is_clear ? NULL : fold_convert(type_tree, null_pointer_node); }
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*)
   { gcc_unreachable(); }
 
   void
@@ -2538,8 +3193,8 @@
   do_get_init_tree(Gogo*, tree, bool)
   { gcc_unreachable(); }
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*)
   { gcc_unreachable(); }
 
   void
@@ -3079,12 +3734,131 @@
   return ret;
 }
 
-// Type descriptor.
-
-void
-Struct_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
-  gogo->struct_type_descriptor_decl(this, name, pdecl);
+// The type of a struct type descriptor.
+
+Type*
+Struct_type::make_struct_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Type* uintptr_type = Type::lookup_integer_type("uintptr");
+      Type* string_type = Type::lookup_string_type();
+      Type* pointer_string_type = Type::make_pointer_type(string_type);
+
+      Struct_type* sf =
+	Type::make_builtin_struct_type(5,
+				       "name", pointer_string_type,
+				       "pkgPath", pointer_string_type,
+				       "typ", ptdt,
+				       "tag", pointer_string_type,
+				       "offset", uintptr_type);
+      Type* nsf = Type::make_builtin_named_type("structField", sf);
+
+      Type* slice_type = Type::make_array_type(nsf, NULL);
+
+      Struct_type* s = Type::make_builtin_struct_type(2,
+						      "", tdt,
+						      "fields", slice_type);
+
+      ret = Type::make_builtin_named_type("StructType", s);
+    }
+
+  return ret;
+}
+
+// Build a type descriptor for a struct type.
+
+Expression*
+Struct_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* stdt = Struct_type::make_struct_type_descriptor_type();
+
+  const Struct_field_list* fields = stdt->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(2);
+
+  const Methods* methods = this->methods();
+  // A named struct should not have methods--the methods should attach
+  // to the named type.
+  gcc_assert(methods == NULL || name == NULL);
+
+  Struct_field_list::const_iterator ps = fields->begin();
+  gcc_assert(ps->field_name() == "commonType");
+  vals->push_back(this->type_descriptor_constructor(gogo,
+						    RUNTIME_TYPE_KIND_STRUCT,
+						    name, methods, true));
+
+  ++ps;
+  gcc_assert(ps->field_name() == "fields");
+
+  Expression_list* elements = new Expression_list();
+  elements->reserve(this->fields_->size());
+  Type* element_type = ps->type()->array_type()->element_type();
+  for (Struct_field_list::const_iterator pf = this->fields_->begin();
+       pf != this->fields_->end();
+       ++pf)
+    {
+      const Struct_field_list* f = element_type->struct_type()->fields();
+
+      Expression_list* fvals = new Expression_list();
+      fvals->reserve(5);
+
+      Struct_field_list::const_iterator q = f->begin();
+      gcc_assert(q->field_name() == "name");
+      if (pf->is_anonymous())
+	fvals->push_back(Expression::make_nil(bloc));
+      else
+	{
+	  std::string n = Gogo::unpack_hidden_name(pf->field_name());
+	  Expression* s = Expression::make_string(n, bloc);
+	  fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+	}
+
+      ++q;
+      gcc_assert(q->field_name() == "pkgPath");
+      if (!Gogo::is_hidden_name(pf->field_name()))
+	fvals->push_back(Expression::make_nil(bloc));
+      else
+	{
+	  std::string n = Gogo::hidden_name_prefix(pf->field_name());
+	  Expression* s = Expression::make_string(n, bloc);
+	  fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+	}
+
+      ++q;
+      gcc_assert(q->field_name() == "typ");
+      fvals->push_back(Expression::make_type_descriptor(pf->type(), bloc));
+
+      ++q;
+      gcc_assert(q->field_name() == "tag");
+      if (!pf->has_tag())
+	fvals->push_back(Expression::make_nil(bloc));
+      else
+	{
+	  Expression* s = Expression::make_string(pf->tag(), bloc);
+	  fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+	}
+
+      ++q;
+      gcc_assert(q->field_name() == "offset");
+      fvals->push_back(Expression::make_struct_field_offset(this, &*pf));
+
+      Expression* v = Expression::make_struct_composite_literal(element_type,
+								fvals, bloc);
+      elements->push_back(v);
+    }
+
+  vals->push_back(Expression::make_slice_composite_literal(ps->type(),
+							   elements, bloc));
+
+  return Expression::make_struct_composite_literal(stdt, vals, bloc);
 }
 
 // Reflection string.
@@ -3894,15 +4668,126 @@
   return Type::make_array_type(element_type, length);
 }
 
-// Type descriptor.
-
-void
-Array_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+// The type of an array type descriptor.
+
+Type*
+Array_type::make_array_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Type* uintptr_type = Type::lookup_integer_type("uintptr");
+
+      Struct_type* sf =
+	Type::make_builtin_struct_type(3,
+				       "", tdt,
+				       "elem", ptdt,
+				       "len", uintptr_type);
+
+      ret = Type::make_builtin_named_type("ArrayType", sf);
+    }
+
+  return ret;
+}
+
+// The type of an slice type descriptor.
+
+Type*
+Array_type::make_slice_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Struct_type* sf =
+	Type::make_builtin_struct_type(2,
+				       "", tdt,
+				       "elem", ptdt);
+
+      ret = Type::make_builtin_named_type("SliceType", sf);
+    }
+
+  return ret;
+}
+
+// Build a type descriptor for an array/slice type.
+
+Expression*
+Array_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   if (this->length_ != NULL)
-    gogo->array_type_descriptor_decl(this, name, pdecl);
+    return this->array_type_descriptor(gogo, name);
   else
-    gogo->slice_type_descriptor_decl(this, name, pdecl);
+    return this->slice_type_descriptor(gogo, name);
+}
+
+// Build a type descriptor for an array type.
+
+Expression*
+Array_type::array_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* atdt = Array_type::make_array_type_descriptor_type();
+
+  const Struct_field_list* fields = atdt->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(3);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "commonType");
+  vals->push_back(this->type_descriptor_constructor(gogo,
+						    RUNTIME_TYPE_KIND_ARRAY,
+						    name, NULL, true));
+
+  ++p;
+  gcc_assert(p->field_name() == "elem");
+  vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "len");
+  vals->push_back(this->length_);
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  return Expression::make_struct_composite_literal(atdt, vals, bloc);
+}
+
+// Build a type descriptor for a slice type.
+
+Expression*
+Array_type::slice_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* stdt = Array_type::make_slice_type_descriptor_type();
+
+  const Struct_field_list* fields = stdt->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(2);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "commonType");
+  vals->push_back(this->type_descriptor_constructor(gogo,
+						    RUNTIME_TYPE_KIND_SLICE,
+						    name, NULL, true));
+
+  ++p;
+  gcc_assert(p->field_name() == "elem");
+  vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  return Expression::make_struct_composite_literal(stdt, vals, bloc);
 }
 
 // Reflection string.
@@ -4162,12 +5047,61 @@
     }
 }
 
-// Type descriptor.
-
-void
-Map_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
-  gogo->map_type_descriptor_decl(this, name, pdecl);
+// The type of a map type descriptor.
+
+Type*
+Map_type::make_map_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Struct_type* sf =
+	Type::make_builtin_struct_type(3,
+				       "", tdt,
+				       "key", ptdt,
+				       "elem", ptdt);
+
+      ret = Type::make_builtin_named_type("MapType", sf);
+    }
+
+  return ret;
+}
+
+// Build a type descriptor for a map type.
+
+Expression*
+Map_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* mtdt = Map_type::make_map_type_descriptor_type();
+
+  const Struct_field_list* fields = mtdt->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(3);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "commonType");
+  vals->push_back(this->type_descriptor_constructor(gogo,
+						    RUNTIME_TYPE_KIND_MAP,
+						    name, NULL, true));
+
+  ++p;
+  gcc_assert(p->field_name() == "key");
+  vals->push_back(Expression::make_type_descriptor(this->key_type_, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "elem");
+  vals->push_back(Expression::make_type_descriptor(this->val_type_, bloc));
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  return Expression::make_struct_composite_literal(mtdt, vals, bloc);
 }
 
 // Reflection string for a map.
@@ -4361,12 +5295,72 @@
     }
 }
 
-// Type descriptor.
-
-void
-Channel_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
-  gogo->channel_type_descriptor_decl(this, name, pdecl);
+// Build a type descriptor for a channel type.
+
+Type*
+Channel_type::make_chan_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Type* uintptr_type = Type::lookup_integer_type("uintptr");
+
+      Struct_type* sf =
+	Type::make_builtin_struct_type(3,
+				       "", tdt,
+				       "elem", ptdt,
+				       "dir", uintptr_type);
+
+      ret = Type::make_builtin_named_type("ChanType", sf);
+    }
+
+  return ret;
+}
+
+// Build a type descriptor for a map type.
+
+Expression*
+Channel_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* ctdt = Channel_type::make_chan_type_descriptor_type();
+
+  const Struct_field_list* fields = ctdt->struct_type()->fields();
+
+  Expression_list* vals = new Expression_list();
+  vals->reserve(3);
+
+  Struct_field_list::const_iterator p = fields->begin();
+  gcc_assert(p->field_name() == "commonType");
+  vals->push_back(this->type_descriptor_constructor(gogo,
+						    RUNTIME_TYPE_KIND_CHAN,
+						    name, NULL, true));
+
+  ++p;
+  gcc_assert(p->field_name() == "elem");
+  vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
+
+  ++p;
+  gcc_assert(p->field_name() == "dir");
+  // These bits must match the ones in libgo/runtime/go-type.h.
+  int val = 0;
+  if (this->may_receive_)
+    val |= 1;
+  if (this->may_send_)
+    val |= 2;
+  mpz_t iv;
+  mpz_init_set_ui(iv, val);
+  vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
+  mpz_clear(iv);
+
+  ++p;
+  gcc_assert(p == fields->end());
+
+  return Expression::make_struct_composite_literal(ctdt, vals, bloc);
 }
 
 // Reflection string.
@@ -4840,7 +5834,7 @@
       // At the tree level, use the same type for all empty
       // interfaces.  This lets us assign them to each other directly
       // without triggering GIMPLE type errors.
-      tree dtype = gogo->type_descriptor_type_tree();
+      tree dtype = Type::make_type_descriptor_type()->get_tree(gogo);
       dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST));
       static tree empty_interface;
       return Gogo::builtin_struct(&empty_interface, "__go_empty_interface",
@@ -4868,7 +5862,7 @@
 
   // The first field is a pointer to the type descriptor.
   tree name_tree = get_identifier("__type_descriptor");
-  tree dtype = gogo->type_descriptor_type_tree();
+  tree dtype = Type::make_type_descriptor_type()->get_tree(gogo);
   dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST));
   tree field = build_decl(this->location_, FIELD_DECL, name_tree, dtype);
   DECL_CONTEXT(field) = method_table;
@@ -4941,13 +5935,115 @@
   return ret;
 }
 
-// Type descriptor.
-
-void
-Interface_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
-					tree* pdecl)
-{
-  gogo->interface_type_descriptor_decl(this, name, pdecl);
+// The type of an interface type descriptor.
+
+Type*
+Interface_type::make_interface_type_descriptor_type()
+{
+  static Type* ret;
+  if (ret == NULL)
+    {
+      Type* tdt = Type::make_type_descriptor_type();
+      Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+      Type* string_type = Type::lookup_string_type();
+      Type* pointer_string_type = Type::make_pointer_type(string_type);
+
+      Struct_type* sm =
+	Type::make_builtin_struct_type(3,
+				       "name", pointer_string_type,
+				       "pkgPath", pointer_string_type,
+				       "typ", ptdt);
+
+      Type* nsm = Type::make_builtin_named_type("imethod", sm);
+
+      Type* slice_nsm = Type::make_array_type(nsm, NULL);
+
+      Struct_type* s = Type::make_builtin_struct_type(2,
+						      "", tdt,
+						      "methods", slice_nsm);
+
+      ret = Type::make_builtin_named_type("InterfaceType", s);
+    }
+
+  return ret;
+}
+
+// Build a type descriptor for an interface type.
+
+Expression*
+Interface_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+  source_location bloc = BUILTINS_LOCATION;
+
+  Type* itdt = Interface_type::make_interface_type_descriptor_type();
+
+  const Struct_field_list* ifields = itdt->struct_type()->fields();
+
+  Expression_list* ivals = new Expression_list();
+  ivals->reserve(2);
+
+  Struct_field_list::const_iterator pif = ifields->begin();
+  gcc_assert(pif->field_name() == "commonType");
+  ivals->push_back(this->type_descriptor_constructor(gogo,
+						     RUNTIME_TYPE_KIND_INTERFACE,
+						     name, NULL, true));
+
+  ++pif;
+  gcc_assert(pif->field_name() == "methods");
+
+  Expression_list* methods = new Expression_list();
+  if (this->methods_ != NULL && !this->methods_->empty())
+    {
+      Type* elemtype = pif->type()->array_type()->element_type();
+
+      methods->reserve(this->methods_->size());
+      for (Typed_identifier_list::const_iterator pm = this->methods_->begin();
+	   pm != this->methods_->end();
+	   ++pm)
+	{
+	  const Struct_field_list* mfields = elemtype->struct_type()->fields();
+
+	  Expression_list* mvals = new Expression_list();
+	  mvals->reserve(3);
+
+	  Struct_field_list::const_iterator pmf = mfields->begin();
+	  gcc_assert(pmf->field_name() == "name");
+	  std::string s = Gogo::unpack_hidden_name(pm->name());
+	  Expression* e = Expression::make_string(s, bloc);
+	  mvals->push_back(Expression::make_unary(OPERATOR_AND, e, bloc));
+
+	  ++pmf;
+	  gcc_assert(pmf->field_name() == "pkgPath");
+	  if (!Gogo::is_hidden_name(pm->name()))
+	    mvals->push_back(Expression::make_nil(bloc));
+	  else
+	    {
+	      s = Gogo::hidden_name_prefix(pm->name());
+	      e = Expression::make_string(s, bloc);
+	      mvals->push_back(Expression::make_unary(OPERATOR_AND, e, bloc));
+	    }
+
+	  ++pmf;
+	  gcc_assert(pmf->field_name() == "typ");
+	  mvals->push_back(Expression::make_type_descriptor(pm->type(), bloc));
+
+	  ++pmf;
+	  gcc_assert(pmf == mfields->end());
+
+	  e = Expression::make_struct_composite_literal(elemtype, mvals,
+							bloc);
+	  methods->push_back(e);
+	}
+    }
+
+  ivals->push_back(Expression::make_slice_composite_literal(pif->type(),
+							    methods, bloc));
+
+  ++pif;
+  gcc_assert(pif == ifields->end());
+
+  return Expression::make_struct_composite_literal(itdt, ivals, bloc);
 }
 
 // Reflection string.
@@ -5190,39 +6286,6 @@
   return new Interface_type(methods, location);
 }
 
-// Make the type of a pointer to a type descriptor as represented in
-// Go.  We should really tie this to runtime.Type rather than copying
-// it.
-
-Type*
-Type::make_type_descriptor_ptr_type()
-{
-  static Type* ret;
-  if (ret == NULL)
-    {
-      source_location bloc = BUILTINS_LOCATION;
-      Struct_field_list* sfl = new Struct_field_list();
-      Type* uint8_type = Type::lookup_integer_type("uint8");
-      Type* uintptr_type = Type::lookup_integer_type("uintptr");
-      sfl->push_back(Struct_field(Typed_identifier("Code", uint8_type, bloc)));
-      sfl->push_back(Struct_field(Typed_identifier("align", uint8_type, bloc)));
-      sfl->push_back(Struct_field(Typed_identifier("fieldAlign", uint8_type,
-						   bloc)));
-      sfl->push_back(Struct_field(Typed_identifier("size", uintptr_type,
-						   bloc)));
-      // We don't try to represent the real function type.
-      Type* fntype = Type::make_function_type(NULL, NULL, NULL, bloc);
-      sfl->push_back(Struct_field(Typed_identifier("hash", fntype, bloc)));
-      sfl->push_back(Struct_field(Typed_identifier("equal", fntype, bloc)));
-      Type* stype = Type::make_pointer_type(Type::lookup_string_type());
-      sfl->push_back(Struct_field(Typed_identifier("string", stype, bloc)));
-      // We omit the pointer to uncommonType.
-      Type* t = Type::make_struct_type(sfl, bloc);
-      ret = Type::make_pointer_type(t);
-    }
-  return ret;
-}
-
 // Class Method.
 
 // Bind a method to an object.
@@ -5829,17 +6892,16 @@
   return t;
 }
 
-// Type descriptor decl.
-
-void
-Named_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+// Build a type descriptor for a named type.
+
+Expression*
+Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   // If NAME is not NULL, then we don't really want the type
   // descriptor for this type; we want the descriptor for the
-  // underlying type, given the name NAME.
-  this->named_type_descriptor(gogo, this->type_,
-			      name == NULL ? this : name,
-			      pdecl);
+  // underlying type, giving it the name NAME.
+  return this->named_type_descriptor(gogo, this->type_,
+				     name == NULL ? this : name);
 }
 
 // Add to the reflection string.  This is used mostly for the name of
@@ -6863,26 +7925,20 @@
   return type_tree;
 }
 
-// The type descriptor.
-
-void
-Forward_declaration_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
-						  tree* pdecl)
+// Build a type descriptor for a forwarded type.
+
+Expression*
+Forward_declaration_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
   if (!this->is_defined())
-    gogo->undefined_type_descriptor_decl(this, name, pdecl);
+    return Expression::make_nil(BUILTINS_LOCATION);
   else
     {
       Type* t = this->real_type();
       if (name != NULL)
-	this->named_type_descriptor(gogo, t, name, pdecl);
+	return this->named_type_descriptor(gogo, t, name);
       else
-	{
-	  tree descriptor = t->type_descriptor(gogo);
-	  gcc_assert(TREE_CODE(descriptor) == ADDR_EXPR
-		     && DECL_P(TREE_OPERAND(descriptor, 0)));
-	  *pdecl = TREE_OPERAND(descriptor, 0);
-	}
+	return Expression::make_type_descriptor(t, BUILTINS_LOCATION);
     }
 }
 
diff -r 702d88f9b3d3 go/types.h
--- a/go/types.h	Fri Oct 08 13:54:30 2010 -0700
+++ b/go/types.h	Fri Oct 22 12:31:01 2010 -0700
@@ -476,6 +476,9 @@
   make_interface_type(Typed_identifier_list* methods, source_location);
 
   static Type*
+  make_type_descriptor_type();
+
+  static Type*
   make_type_descriptor_ptr_type();
 
   static Named_type*
@@ -814,7 +817,7 @@
   // Build a type descriptor entry for this type.  Return a pointer to
   // it.
   tree
-  type_descriptor(Gogo* gogo);
+  type_descriptor_pointer(Gogo* gogo);
 
   // Return the type reflection string for this type.
   std::string
@@ -870,8 +873,8 @@
   do_make_expression_tree(Translate_context*, Expression_list*,
 			  source_location);
 
-  virtual void
-  do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl) = 0;
+  virtual Expression*
+  do_type_descriptor(Gogo*, Named_type* name) = 0;
 
   virtual void
   do_reflection(Gogo*, std::string*) const = 0;
@@ -900,12 +903,33 @@
   method_function(const Methods*, const std::string& name,
 		  bool* is_ambiguous);
 
-  // Build a type descriptor entry for TYPE, using NAME as the name of
-  // the type.  PACKAGE is the package where TYPE is defined, or NULL
-  // if defined in the package currently being compiled.  Store the
-  // decl in *PDECL.
-  void
-  named_type_descriptor(Gogo* gogo, Type* type, Named_type* name, tree* pdecl);
+  // Return a composite literal for the type descriptor entry for a
+  // type.
+  static Expression*
+  type_descriptor(Gogo*, Type*);
+
+  // Return a composite literal for the type descriptor entry for
+  // TYPE, using NAME as the name of the type.
+  static Expression*
+  named_type_descriptor(Gogo*, Type* type, Named_type* name);
+
+  // Return a composite literal for a plain type descriptor for this
+  // type with the given kind and name.
+  Expression*
+  plain_type_descriptor(Gogo*, int runtime_type_kind, Named_type* name);
+
+  // Build a composite literal for the basic type descriptor.
+  Expression*
+  type_descriptor_constructor(Gogo*, int runtime_type_kind, Named_type*,
+			      const Methods*, bool only_value_methods);
+
+  // Make a builtin struct type from a list of fields.
+  static Struct_type*
+  make_builtin_struct_type(int nfields, ...);
+
+  // Make a builtin named type.
+  static Named_type*
+  make_builtin_named_type(const char* name, Type* type);
 
   // For the benefit of child class reflection string generation.
   void
@@ -962,6 +986,26 @@
 	    : NULL);
   }
 
+  // Get the hash and equality functions for a type.
+  void
+  type_functions(const char** hash_fn, const char** equal_fn) const;
+
+  // Build a composite literal for the uncommon type information.
+  Expression*
+  uncommon_type_constructor(Gogo*, Type* uncommon_type,
+			    Named_type*, const Methods*,
+			    bool only_value_methods) const;
+
+  // Build a composite literal for the methods.
+  Expression*
+  methods_constructor(Gogo*, Type* methods_type, const Methods*,
+		      bool only_value_methods) const;
+
+  // Build a composite literal for one method.
+  Expression*
+  method_constructor(Gogo*, Type* method_type, const std::string& name,
+		     const Method*) const;
+
   static tree
   build_receive_return_type(tree type);
 
@@ -1236,8 +1280,8 @@
   tree
   do_get_init_tree(Gogo*, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1312,8 +1356,8 @@
   tree
   do_get_init_tree(Gogo*, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1384,8 +1428,8 @@
   tree
   do_get_init_tree(Gogo*, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1440,8 +1484,8 @@
   tree
   do_get_init_tree(Gogo* gogo, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1553,8 +1597,8 @@
   tree
   do_get_init_tree(Gogo*, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1566,6 +1610,13 @@
   do_export(Export*) const;
 
  private:
+  static Type*
+  make_function_type_descriptor_type();
+
+  Expression*
+  type_descriptor_params(Type*, const Typed_identifier*,
+			 const Typed_identifier_list*);
+
   // The receiver name and type.  This will be NULL for a normal
   // function, non-NULL for a method.
   Typed_identifier* receiver_;
@@ -1620,8 +1671,8 @@
   tree
   do_get_init_tree(Gogo*, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1633,6 +1684,9 @@
   do_export(Export*) const;
 
  private:
+  static Type*
+  make_pointer_type_descriptor_type();
+
   // The type to which this type points.
   Type* to_type_;
 };
@@ -1875,8 +1929,8 @@
   tree
   do_get_init_tree(Gogo*, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1892,6 +1946,9 @@
   field_reference_depth(Expression* struct_expr, const std::string& name,
 			source_location, unsigned int* depth) const;
 
+  static Type*
+  make_struct_type_descriptor_type();
+
   // The fields of the struct.
   Struct_field_list* fields_;
   // The place where the struct was declared.
@@ -1978,8 +2035,8 @@
   do_make_expression_tree(Translate_context*, Expression_list*,
 			  source_location);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -1997,6 +2054,18 @@
   tree
   get_length_tree(Gogo*);
 
+  Type*
+  make_array_type_descriptor_type();
+
+  Type*
+  make_slice_type_descriptor_type();
+
+  Expression*
+  array_type_descriptor(Gogo*, Named_type*);
+
+  Expression*
+  slice_type_descriptor(Gogo*, Named_type*);
+
   // A mapping from Type to tree, used to ensure that arrays of
   // identical types are identical.
   typedef std::tr1::unordered_map<const Type*, tree, Type_hash_identical,
@@ -2067,8 +2136,8 @@
   do_make_expression_tree(Translate_context*, Expression_list*,
 			  source_location);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -2080,6 +2149,9 @@
   do_export(Export*) const;
 
  private:
+  static Type*
+  make_map_type_descriptor_type();
+
   // The key type.
   Type* key_type_;
   // The value type.
@@ -2148,8 +2220,8 @@
   do_make_expression_tree(Translate_context*, Expression_list*,
 			  source_location);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -2161,6 +2233,9 @@
   do_export(Export*) const;
 
  private:
+  static Type*
+  make_chan_type_descriptor_type();
+
   // Whether this channel can send data.
   bool may_send_;
   // Whether this channel can receive data.
@@ -2254,8 +2329,8 @@
   tree
   do_get_init_tree(Gogo* gogo, tree, bool);
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -2267,6 +2342,9 @@
   do_export(Export*) const;
 
  private:
+  static Type*
+  make_interface_type_descriptor_type();
+
   // The list of methods associated with the interface.  This will be
   // NULL for the empty interface.
   Typed_identifier_list* methods_;
@@ -2464,8 +2542,8 @@
 			  source_location location)
   { return this->type_->make_expression_tree(context, args, location); }
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
@@ -2590,8 +2668,8 @@
 			  source_location location)
   { return this->base()->make_expression_tree(context, args, location); }
 
-  void
-  do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+  Expression*
+  do_type_descriptor(Gogo*, Named_type*);
 
   void
   do_reflection(Gogo*, std::string*) const;
diff -r 702d88f9b3d3 libgo/go/runtime/type.go
--- a/libgo/go/runtime/type.go	Fri Oct 08 13:54:30 2010 -0700
+++ b/libgo/go/runtime/type.go	Fri Oct 22 12:31:01 2010 -0700
@@ -20,16 +20,17 @@
 // All types begin with a few common fields needed for
 // the interface runtime.
 type commonType struct {
-	Kind          uint8                                         // type kind
-	align         uint8                                         // alignment of variable with this type
-	fieldAlign    uint8                                         // alignment of struct field with this type
-	size          uintptr                                       // size in bytes
-	hash          uint32  					    // hash of type; avoids computation in hash tables
+	Kind       uint8   // type kind
+	align      uint8   // alignment of variable with this type
+	fieldAlign uint8   // alignment of struct field with this type
+	size       uintptr // size in bytes
+	hash       uint32  // hash of type; avoids computation in hash tables
 
-	hashfn        func(unsafe.Pointer, uintptr)                 // hash function
-	equalfn       func(unsafe.Pointer, unsafe.Pointer, uintptr) // equality function
-	string        *string                                       // string form; unnecessary  but undeniably useful
-	*uncommonType                                               // (relatively) uncommon fields
+	hashfn  func(unsafe.Pointer, uintptr) uintptr              // hash function
+	equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) bool // equality function
+
+	string        *string // string form; unnecessary  but undeniably useful
+	*uncommonType         // (relatively) uncommon fields
 }
 
 // Values for commonType.kind.

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