OSDN Git Service

compiler: Add -fgo-pkgpath option.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / gogo.h
index 9d3b37a..deb9968 100644 (file)
@@ -138,16 +138,14 @@ class Gogo
   is_main_package() const;
 
   // If necessary, adjust the name to use for a hidden symbol.  We add
-  // a prefix of the package name, so that hidden symbols in different
-  // packages do not collide.
+  // the package name, so that hidden symbols in different packages do
+  // not collide.
   std::string
   pack_hidden_name(const std::string& name, bool is_exported) const
   {
     return (is_exported
            ? name
-           : ('.' + this->unique_prefix()
-              + '.' + this->package_name()
-              + '.' + name));
+           : '.' + this->pkgpath() + '.' + name);
   }
 
   // Unpack a name which may have been hidden.  Returns the
@@ -161,9 +159,9 @@ class Gogo
   is_hidden_name(const std::string& name)
   { return name[0] == '.'; }
 
-  // Return the package prefix of a hidden name.
+  // Return the package path of a hidden name.
   static std::string
-  hidden_name_prefix(const std::string& name)
+  hidden_name_pkgpath(const std::string& name)
   {
     go_assert(Gogo::is_hidden_name(name));
     return name.substr(1, name.rfind('.') - 1);
@@ -183,13 +181,30 @@ class Gogo
            && name[name.length() - 2] == '.');
   }
 
-  // Return the unique prefix to use for all exported symbols.
+  // Convert a pkgpath into a string suitable for a symbol
+  static std::string
+  pkgpath_for_symbol(const std::string& pkgpath);
+
+  // Return the package path to use for reflect.Type.PkgPath.
   const std::string&
-  unique_prefix() const;
+  pkgpath() const;
 
-  // Set the unique prefix.
+  // Return the package path to use for a symbol name.
+  const std::string&
+  pkgpath_symbol() const;
+
+  // Set the package path from a command line option.
   void
-  set_unique_prefix(const std::string&);
+  set_pkgpath(const std::string&);
+
+  // Set the prefix from a command line option.
+  void
+  set_prefix(const std::string&);
+
+  // Return whether pkgpath was set from a command line option.
+  bool
+  pkgpath_from_option() const
+  { return this->pkgpath_from_option_; }
 
   // Return the priority to use for the package we are compiling.
   // This is two more than the largest priority of any package we
@@ -229,7 +244,7 @@ class Gogo
   Package*
   add_imported_package(const std::string& real_name, const std::string& alias,
                       bool is_alias_exported,
-                      const std::string& unique_prefix,
+                      const std::string& pkgpath,
                       Location location,
                       bool* padd_to_globals);
 
@@ -237,8 +252,7 @@ class Gogo
   // This returns the Package structure for the package, creating if
   // it necessary.
   Package*
-  register_package(const std::string& name, const std::string& unique_prefix,
-                  Location);
+  register_package(const std::string& pkgpath, Location);
 
   // Start compiling a function.  ADD_METHOD_TO_TYPE is true if a
   // method function should be added to the type of its receiver.
@@ -267,6 +281,11 @@ class Gogo
   Block*
   finish_block(Location);
 
+  // Declare an erroneous name.  This is used to avoid knock-on errors
+  // after a parsing error.
+  Named_object*
+  add_erroneous_name(const std::string& name);
+
   // Declare an unknown name.  This is used while parsing.  The name
   // must be resolved by the end of the parse.  Unknown names are
   // always added at the package level.
@@ -277,6 +296,11 @@ class Gogo
   Named_object*
   declare_function(const std::string&, Function_type*, Location);
 
+  // Declare a function at the package level.  This is used for
+  // functions generated for a type.
+  Named_object*
+  declare_package_function(const std::string&, Function_type*, Location);
+
   // Add a label.
   Label*
   add_label_definition(const std::string&, Location);
@@ -334,11 +358,21 @@ class Gogo
   Named_object*
   add_sink();
 
+  // Add a type which needs to be verified.  This is used for sink
+  // types, just to give appropriate error messages.
+  void
+  add_type_to_verify(Type* type);
+
   // Add a named object to the current namespace.  This is used for
   // import . "package".
   void
   add_named_object(Named_object*);
 
+  // Mark all local variables in current bindings as used.  This is
+  // used when there is a parse error to avoid useless errors.
+  void
+  mark_locals_used();
+
   // Return a name to use for a thunk function.  A thunk function is
   // one we create during the compilation, for a go statement or a
   // defer statement or a method expression.
@@ -364,6 +398,42 @@ class Gogo
   void
   clear_file_scope();
 
+  // Record that VAR1 must be initialized after VAR2.  This is used
+  // when VAR2 does not appear in VAR1's INIT or PREINIT.
+  void
+  record_var_depends_on(Variable* var1, Named_object* var2)
+  {
+    go_assert(this->var_deps_.find(var1) == this->var_deps_.end());
+    this->var_deps_[var1] = var2;
+  }
+
+  // Return the variable that VAR depends on, or NULL if none.
+  Named_object*
+  var_depends_on(Variable* var) const
+  {
+    Var_deps::const_iterator p = this->var_deps_.find(var);
+    return p != this->var_deps_.end() ? p->second : NULL;
+  }
+
+  // Queue up a type-specific function to be written out.  This is
+  // used when a type-specific function is needed when not at the top
+  // level.
+  void
+  queue_specific_type_function(Type* type, Named_type* name,
+                              const std::string& hash_name,
+                              Function_type* hash_fntype,
+                              const std::string& equal_name,
+                              Function_type* equal_fntype);
+
+  // Write out queued specific type functions.
+  void
+  write_specific_type_functions();
+
+  // Whether we are done writing out specific type functions.
+  bool
+  specific_type_functions_are_written() const
+  { return this->specific_type_functions_are_written_; }
+
   // Traverse the tree.  See the Traverse class.
   void
   traverse(Traverse*);
@@ -527,14 +597,9 @@ class Gogo
 
   // Receive a value from a channel.
   static tree
-  receive_from_channel(tree type_tree, tree channel, bool for_select,
+  receive_from_channel(tree type_tree, tree type_descriptor_tree, tree channel,
                       Location);
 
-  // Return a tree for receiving an integer on a channel.
-  static tree
-  receive_as_64bit_integer(tree type, tree channel, bool blocking,
-                          bool for_select);
-
   // Make a trampoline which calls FNADDR passing CLOSURE.
   tree
   make_trampoline(tree fnaddr, tree closure, Location);
@@ -558,11 +623,6 @@ class Gogo
   void
   import_unsafe(const std::string&, bool is_exported, Location);
 
-  // Add a new imported package.
-  Named_object*
-  add_package(const std::string& real_name, const std::string& alias,
-             const std::string& unique_prefix, Location location);
-
   // Return the current binding contour.
   Bindings*
   current_bindings();
@@ -605,8 +665,30 @@ class Gogo
   // Type used to map package names to packages.
   typedef std::map<std::string, Package*> Packages;
 
-  // Type used to map special names in the sys package.
-  typedef std::map<std::string, std::string> Sys_names;
+  // Type used to map variables to the function calls that set them.
+  // This is used for initialization dependency analysis.
+  typedef std::map<Variable*, Named_object*> Var_deps;
+
+  // Type used to queue writing a type specific function.
+  struct Specific_type_function
+  {
+    Type* type;
+    Named_type* name;
+    std::string hash_name;
+    Function_type* hash_fntype;
+    std::string equal_name;
+    Function_type* equal_fntype;
+
+    Specific_type_function(Type* atype, Named_type* aname,
+                          const std::string& ahash_name,
+                          Function_type* ahash_fntype,
+                          const std::string& aequal_name,
+                          Function_type* aequal_fntype)
+      : type(atype), name(aname), hash_name(ahash_name),
+       hash_fntype(ahash_fntype), equal_name(aequal_name),
+       equal_fntype(aequal_fntype)
+    { }
+  };
 
   // The backend generator.
   Backend* backend_;
@@ -628,18 +710,36 @@ class Gogo
   Packages packages_;
   // The functions named "init", if there are any.
   std::vector<Named_object*> init_functions_;
+  // A mapping from variables to the function calls that initialize
+  // them, if it is not stored in the variable's init or preinit.
+  // This is used for dependency analysis.
+  Var_deps var_deps_;
   // Whether we need a magic initialization function.
   bool need_init_fn_;
   // The name of the magic initialization function.
   std::string init_fn_name_;
   // A list of import control variables for packages that we import.
   std::set<Import_init> imported_init_fns_;
-  // The unique prefix used for all global symbols.
-  std::string unique_prefix_;
-  // Whether an explicit unique prefix was set by -fgo-prefix.
-  bool unique_prefix_specified_;
+  // The package path used for reflection data.
+  std::string pkgpath_;
+  // The package path to use for a symbol name.
+  std::string pkgpath_symbol_;
+  // The prefix to use for symbols, from the -fgo-prefix option.
+  std::string prefix_;
+  // Whether pkgpath_ has been set.
+  bool pkgpath_set_;
+  // Whether an explicit package path was set by -fgo-pkgpath.
+  bool pkgpath_from_option_;
+  // Whether an explicit prefix was set by -fgo-prefix.
+  bool prefix_from_option_;
+  // A list of types to verify.
+  std::vector<Type*> verify_types_;
   // A list of interface types defined while parsing.
   std::vector<Interface_type*> interface_types_;
+  // Type specific functions to write out.
+  std::vector<Specific_type_function*> specific_type_functions_;
+  // Whether we are done writing out specific type functions.
+  bool specific_type_functions_are_written_;
   // Whether named types have been converted.
   bool named_types_are_converted_;
 };
@@ -1098,8 +1198,7 @@ class Variable
 
   // Return whether the type is defined yet.
   bool
-  has_type() const
-  { return this->type_ != NULL; }
+  has_type() const;
 
   // Get the initial value.
   Expression*
@@ -1193,6 +1292,16 @@ class Variable
     this->is_varargs_parameter_ = true;
   }
 
+  // Return whether the variable has been used.
+  bool
+  is_used() const
+  { return this->is_used_; }
+
+  // Mark that the variable has been used.
+  void
+  set_is_used()
+  { this->is_used_ = true; }
+
   // Clear the initial value; used for error handling.
   void
   clear_init()
@@ -1329,6 +1438,8 @@ class Variable
   bool is_receiver_ : 1;
   // Whether this is the varargs parameter of a function.
   bool is_varargs_parameter_ : 1;
+  // Whether this variable is ever referenced.
+  bool is_used_ : 1;
   // Whether something takes the address of this variable.  For a
   // local variable this implies that the variable has to be on the
   // heap.
@@ -1554,8 +1665,8 @@ class Type_declaration
 
   // Add a method declaration to this type.
   Named_object*
-  add_method_declaration(const std::string& name, Function_type* type,
-                        Location location);
+  add_method_declaration(const std::string& name, Package*,
+                        Function_type* type, Location location);
 
   // Return whether any methods were defined.
   bool
@@ -1632,6 +1743,9 @@ class Named_object
   {
     // An uninitialized Named_object.  We should never see this.
     NAMED_OBJECT_UNINITIALIZED,
+    // An erroneous name.  This indicates a parse error, to avoid
+    // later errors about undefined references.
+    NAMED_OBJECT_ERRONEOUS,
     // An unknown name.  This is used for forward references.  In a
     // correct program, these will all be resolved by the end of the
     // parse.
@@ -1664,6 +1778,10 @@ class Named_object
   // Classifiers.
 
   bool
+  is_erroneous() const
+  { return this->classification_ == NAMED_OBJECT_ERRONEOUS; }
+
+  bool
   is_unknown() const
   { return this->classification_ == NAMED_OBJECT_UNKNOWN; }
 
@@ -1706,6 +1824,10 @@ class Named_object
   // Creators.
 
   static Named_object*
+  make_erroneous_name(const std::string& name)
+  { return new Named_object(name, NULL, NAMED_OBJECT_ERRONEOUS); }
+
+  static Named_object*
   make_unknown_name(const std::string& name, Location);
 
   static Named_object*
@@ -1976,6 +2098,11 @@ class Bindings
 
   Bindings(Bindings* enclosing);
 
+  // Add an erroneous name.
+  Named_object*
+  add_erroneous_name(const std::string& name)
+  { return this->add_named_object(Named_object::make_erroneous_name(name)); }
+
   // Add an unknown name.
   Named_object*
   add_unknown_name(const std::string& name, Location location)
@@ -2085,6 +2212,11 @@ class Bindings
   void
   remove_binding(Named_object*);
 
+  // Mark all variables as used.  This is used for some types of parse
+  // error.
+  void
+  mark_locals_used();
+
   // Traverse the tree.  See the Traverse class.
   int
   traverse(Traverse*, bool is_global);
@@ -2294,28 +2426,37 @@ class Unnamed_label
 class Package
 {
  public:
-  Package(const std::string& name, const std::string& unique_prefix,
-         Location location);
+  Package(const std::string& pkgpath, Location location);
 
-  // The real name of this package.  This may be different from the
-  // name in the associated Named_object if the import statement used
-  // an alias.
+  // Get the package path used for all symbols exported from this
+  // package.
   const std::string&
-  name() const
-  { return this->name_; }
+  pkgpath() const
+  { return this->pkgpath_; }
+
+  // Return the package path to use for a symbol name.
+  const std::string&
+  pkgpath_symbol() const
+  { return this->pkgpath_symbol_; }
 
   // Return the location of the import statement.
   Location
   location() const
   { return this->location_; }
 
-  // Get the unique prefix used for all symbols exported from this
-  // package.
+  // Return whether we know the name of this package yet.
+  bool
+  has_package_name() const
+  { return !this->package_name_.empty(); }
+
+  // The name that this package uses in its package clause.  This may
+  // be different from the name in the associated Named_object if the
+  // import statement used an alias.
   const std::string&
-  unique_prefix() const
+  package_name() const
   {
-    go_assert(!this->unique_prefix_.empty());
-    return this->unique_prefix_;
+    go_assert(!this->package_name_.empty());
+    return this->package_name_;
   }
 
   // The priority of this package.  The init function of packages with
@@ -2385,8 +2526,12 @@ class Package
   lookup(const std::string& name) const
   { return this->bindings_->lookup(name); }
 
-  // Set the location of the package.  This is used if it is seen in a
-  // different import before it is really imported.
+  // Set the name of the package.
+  void
+  set_package_name(const std::string& name, Location);
+
+  // Set the location of the package.  This is used to record the most
+  // recent import location.
   void
   set_location(Location location)
   { this->location_ = location; }
@@ -2422,10 +2567,13 @@ class Package
   determine_types();
 
  private:
-  // The real name of this package.
-  std::string name_;
-  // The unique prefix for all exported global symbols.
-  std::string unique_prefix_;
+  // The package path for type reflection data.
+  std::string pkgpath_;
+  // The package path for symbol names.
+  std::string pkgpath_symbol_;
+  // The name that this package uses in the package clause.  This may
+  // be the empty string if it is not yet known.
+  std::string package_name_;
   // The names in this package.
   Bindings* bindings_;
   // The priority of this package.  A package has a priority higher
@@ -2539,8 +2687,13 @@ class Traverse
   type(Type*);
 
  private:
-  typedef Unordered_set_hash(const Type*, Type_hash_identical,
-                            Type_identical) Types_seen;
+  // A hash table for types we have seen during this traversal.  Note
+  // that this uses the default hash functions for pointers rather
+  // than Type_hash_identical and Type_identical.  This is because for
+  // traversal we care about seeing a specific type structure.  If
+  // there are two separate instances of identical types, we want to
+  // traverse both.
+  typedef Unordered_set(const Type*) Types_seen;
 
   typedef Unordered_set(const Expression*) Expressions_seen;
 
@@ -2693,6 +2846,9 @@ static const int RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS = 8;
 // Channel capacity out of bounds in make: negative or overflow.
 static const int RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS = 9;
 
+// Division by zero.
+static const int RUNTIME_ERROR_DIVISION_BY_ZERO = 10;
+
 // This is used by some of the langhooks.
 extern Gogo* go_get_gogo();