OSDN Git Service

Rewrite conversion of named types to backend representation.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / gogo.cc
index 0be8c66..bb2fcab 100644 (file)
@@ -34,7 +34,8 @@ Gogo::Gogo(int int_type_size, int pointer_size)
     imported_init_fns_(),
     unique_prefix_(),
     unique_prefix_specified_(false),
-    interface_types_()
+    interface_types_(),
+    named_types_are_converted_(false)
 {
   const source_location loc = BUILTINS_LOCATION;
 
@@ -682,10 +683,15 @@ Gogo::start_function(const std::string& name, Function_type* type,
   else if (!type->is_method())
     {
       ret = this->package_->bindings()->add_function(*pname, NULL, function);
-      if (!ret->is_function())
+      if (!ret->is_function() || ret->func_value() != function)
        {
-         // Redefinition error.
-         ret = Named_object::make_function(name, NULL, function);
+         // Redefinition error.  Invent a name to avoid knockon
+         // errors.
+         static int redefinition_count;
+         char buf[30];
+         snprintf(buf, sizeof buf, ".$redefined%d", redefinition_count);
+         ++redefinition_count;
+         ret = this->package_->bindings()->add_function(buf, NULL, function);
        }
     }
   else
@@ -1114,11 +1120,6 @@ class Verify_types : public Traverse
 int
 Verify_types::type(Type* t)
 {
-  // Don't verify types defined in other packages.
-  Named_type* nt = t->named_type();
-  if (nt != NULL && nt->named_object()->package() != NULL)
-    return TRAVERSE_SKIP_COMPONENTS;
-
   if (!t->verify())
     return TRAVERSE_SKIP_COMPONENTS;
   return TRAVERSE_CONTINUE;
@@ -2200,10 +2201,14 @@ Build_recover_thunks::function(Named_object* orig_no)
 
       const std::string& new_receiver_name(orig_fntype->receiver()->name());
       Named_object* new_rec_no = new_bindings->lookup_local(new_receiver_name);
-      gcc_assert(new_rec_no != NULL
-                && new_rec_no->is_variable()
-                && new_rec_no->var_value()->is_receiver());
-      new_rec_no->var_value()->set_is_not_receiver();
+      if (new_rec_no == NULL)
+       gcc_assert(saw_errors());
+      else
+       {
+         gcc_assert(new_rec_no->is_variable()
+                    && new_rec_no->var_value()->is_receiver());
+         new_rec_no->var_value()->set_is_not_receiver();
+       }
     }
 
   // Because we flipped blocks but not types, the can_recover
@@ -2511,6 +2516,83 @@ Gogo::do_exports()
                     this->package_->bindings());
 }
 
+// Find the blocks in order to convert named types defined in blocks.
+
+class Convert_named_types : public Traverse
+{
+ public:
+  Convert_named_types(Gogo* gogo)
+    : Traverse(traverse_blocks),
+      gogo_(gogo)
+  { }
+
+ protected:
+  int
+  block(Block* block);
+
+ private:
+  Gogo* gogo_;
+};
+
+int
+Convert_named_types::block(Block* block)
+{
+  this->gogo_->convert_named_types_in_bindings(block->bindings());
+  return TRAVERSE_CONTINUE;
+}
+
+// Convert all named types to the backend representation.  Since named
+// types can refer to other types, this needs to be done in the right
+// sequence, which is handled by Named_type::convert.  Here we arrange
+// to call that for each named type.
+
+void
+Gogo::convert_named_types()
+{
+  this->convert_named_types_in_bindings(this->globals_);
+  for (Packages::iterator p = this->packages_.begin();
+       p != this->packages_.end();
+       ++p)
+    {
+      Package* package = p->second;
+      this->convert_named_types_in_bindings(package->bindings());
+    }
+
+  Convert_named_types cnt(this);
+  this->traverse(&cnt);
+
+  // Make all the builtin named types used for type descriptors, and
+  // then convert them.  They will only be written out if they are
+  // needed.
+  Type::make_type_descriptor_type();
+  Type::make_type_descriptor_ptr_type();
+  Function_type::make_function_type_descriptor_type();
+  Pointer_type::make_pointer_type_descriptor_type();
+  Struct_type::make_struct_type_descriptor_type();
+  Array_type::make_array_type_descriptor_type();
+  Array_type::make_slice_type_descriptor_type();
+  Map_type::make_map_type_descriptor_type();
+  Channel_type::make_chan_type_descriptor_type();
+  Interface_type::make_interface_type_descriptor_type();
+  Type::convert_builtin_named_types(this);
+
+  this->named_types_are_converted_ = true;
+}
+
+// Convert all names types in a set of bindings.
+
+void
+Gogo::convert_named_types_in_bindings(Bindings* bindings)
+{
+  for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
+       p != bindings->end_definitions();
+       ++p)
+    {
+      if ((*p)->is_type())
+       (*p)->type_value()->convert(this);
+    }
+}
+
 // Class Function.
 
 Function::Function(Function_type* type, Function* enclosing, Block* block,
@@ -2553,7 +2635,8 @@ Function::create_named_result_variables(Gogo* gogo)
        }
       Result_variable* result = new Result_variable(p->type(), this, index);
       Named_object* no = block->bindings()->add_result_variable(name, result);
-      this->named_results_->push_back(no);
+      if (no->is_result_variable())
+       this->named_results_->push_back(no);
     }
 }