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.
