OSDN Git Service

gccgo: Added code to dump the AST tree. The AST dump is
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / gogo.h
index 7a52a51..dae22f5 100644 (file)
@@ -8,6 +8,7 @@
 #define GO_GOGO_H
 
 class Traverse;
+class Statement_inserter;
 class Type;
 class Type_hash_identical;
 class Type_equal;
@@ -17,6 +18,7 @@ class Typed_identifier_list;
 class Function_type;
 class Expression;
 class Statement;
+class Temporary_statement;
 class Block;
 class Function;
 class Bindings;
@@ -37,8 +39,14 @@ class Methods;
 class Named_object;
 class Label;
 class Translate_context;
+class Backend;
 class Export;
 class Import;
+class Bexpression;
+class Bstatement;
+class Bblock;
+class Bvariable;
+class Blabel;
 
 // This file declares the basic classes used to hold the internal
 // representation of Go which is built by the parser.
@@ -102,7 +110,12 @@ class Gogo
  public:
   // Create the IR, passing in the sizes of the types "int" and
   // "uintptr" in bits.
-  Gogo(int int_type_size, int pointer_size);
+  Gogo(Backend* backend, int int_type_size, int pointer_size);
+
+  // Get the backend generator.
+  Backend*
+  backend()
+  { return this->backend_; }
 
   // Get the package name.
   const std::string&
@@ -144,7 +157,7 @@ class Gogo
   static std::string
   hidden_name_prefix(const std::string& name)
   {
-    gcc_assert(Gogo::is_hidden_name(name));
+    go_assert(Gogo::is_hidden_name(name));
     return name.substr(1, name.rfind('.') - 1);
   }
 
@@ -348,9 +361,13 @@ class Gogo
   void
   lower_parse_tree();
 
+  // Lower all the statements in a block.
+  void
+  lower_block(Named_object* function, Block*);
+
   // Lower an expression.
   void
-  lower_expression(Named_object* function, Expression**);
+  lower_expression(Named_object* function, Statement_inserter*, Expression**);
 
   // Lower a constant.
   void
@@ -405,6 +422,10 @@ class Gogo
   void
   simplify_thunk_statements();
 
+  // Dump AST if -fgo-dump-ast is set 
+  void
+  dump_ast(const char* basename);
+
   // Convert named types to the backend representation.
   void
   convert_named_types();
@@ -423,6 +444,10 @@ class Gogo
   void
   write_globals();
 
+  // Create trees for implicit builtin functions.
+  void
+  define_builtin_function_trees();
+
   // Build a call to a builtin function.  PDECL should point to a NULL
   // initialized static pointer which will hold the fndecl.  NAME is
   // the name of the function.  NARGS is the number of arguments.
@@ -445,16 +470,6 @@ class Gogo
   static void
   mark_fndecl_as_builtin_library(tree fndecl);
 
-  // Build the type of the struct that holds a slice for the given
-  // element type.
-  tree
-  slice_type_tree(tree element_type_tree);
-
-  // Given a tree for a slice type, return the tree for the element
-  // type.
-  static tree
-  slice_element_type_tree(tree slice_type_tree);
-
   // Build a constructor for a slice.  SLICE_TYPE_TREE is the type of
   // the slice.  VALUES points to the values.  COUNT is the size,
   // CAPACITY is the capacity.  If CAPACITY is NULL, it is set to
@@ -463,27 +478,6 @@ class Gogo
   slice_constructor(tree slice_type_tree, tree values, tree count,
                    tree capacity);
 
-  // Build a constructor for an empty slice.  SLICE_TYPE_TREE is the
-  // type of the slice.
-  static tree
-  empty_slice_constructor(tree slice_type_tree);
-
-  // Build a map descriptor.
-  tree
-  map_descriptor(Map_type*);
-
-  // Return a tree for the type of a map descriptor.  This is struct
-  // __go_map_descriptor in libgo/runtime/map.h.  This is the same for
-  // all map types.
-  tree
-  map_descriptor_type();
-
-  // Build a type descriptor for TYPE using INITIALIZER as the type
-  // descriptor.  This builds a new decl stored in *PDECL.
-  void
-  build_type_descriptor_decl(const Type*, Expression* initializer,
-                            tree* pdecl);
-
   // Build required interface method tables.
   void
   build_interface_method_tables();
@@ -512,11 +506,6 @@ class Gogo
   tree
   go_string_constant_tree(const std::string&);
 
-  // Send a value on a channel.
-  static tree
-  send_on_channel(tree channel, tree val, bool blocking, bool for_select,
-                 source_location);
-
   // Receive a value from a channel.
   static tree
   receive_from_channel(tree type_tree, tree channel, bool for_select,
@@ -527,7 +516,6 @@ class Gogo
   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, source_location);
@@ -547,10 +535,6 @@ class Gogo
   // The stack of functions.
   typedef std::vector<Open_function> Open_functions;
 
-  // Create trees for implicit builtin functions.
-  void
-  define_builtin_function_trees();
-
   // Set up the built-in unsafe package.
   void
   import_unsafe(const std::string&, bool is_exported, source_location);
@@ -596,32 +580,6 @@ class Gogo
   tree
   ptr_go_string_constant_tree(const std::string&);
 
-  // Return the name to use for a type descriptor decl for an unnamed
-  // type.
-  std::string
-  unnamed_type_descriptor_decl_name(const Type* type);
-
-  // Return the name to use for a type descriptor decl for a type
-  // named NO, defined in IN_FUNCTION.
-  std::string
-  type_descriptor_decl_name(const Named_object* no,
-                           const Named_object* in_function);
-
-  // Where a type descriptor should be defined.
-  enum Type_descriptor_location
-    {
-      // Defined in this file.
-      TYPE_DESCRIPTOR_DEFINED,
-      // Defined in some other file.
-      TYPE_DESCRIPTOR_UNDEFINED,
-      // Common definition which may occur in multiple files.
-      TYPE_DESCRIPTOR_COMMON
-    };
-
-  // Return where the decl for TYPE should be defined.
-  Type_descriptor_location
-  type_descriptor_location(const Type* type);
-
   // Return the type of a trampoline.
   static tree
   trampoline_type_tree();
@@ -635,14 +593,8 @@ class Gogo
   // Type used to map special names in the sys package.
   typedef std::map<std::string, std::string> Sys_names;
 
-  // Hash table mapping map types to map descriptor decls.
-  typedef Unordered_map_hash(const Map_type*, tree, Type_hash_identical,
-                            Type_identical) Map_descriptors;
-
-  // Map unnamed types to type descriptor decls.
-  typedef Unordered_map_hash(const Type*, tree, Type_hash_identical,
-                            Type_identical) Type_descriptor_decls;
-
+  // The backend generator.
+  Backend* backend_;
   // The package we are compiling.
   Package* package_;
   // The list of currently open functions during parsing.
@@ -657,10 +609,6 @@ class Gogo
   // Mapping from package names we have seen to packages.  This does
   // not include the package we are compiling.
   Packages packages_;
-  // Mapping from map types to map descriptors.
-  Map_descriptors* map_descriptors_;
-  // Mapping from unnamed types to type descriptor decls.
-  Type_descriptor_decls* type_descriptor_decls_;
   // The functions named "init", if there are any.
   std::vector<Named_object*> init_functions_;
   // Whether we need a magic initialization function.
@@ -755,9 +703,9 @@ class Block
   bool
   may_fall_through() const;
 
-  // Return a tree of the code in this block.
-  tree
-  get_tree(Translate_context*);
+  // Convert the block to the backend representation.
+  Bblock*
+  get_backend(Translate_context*);
 
   // Iterate over statements.
 
@@ -806,18 +754,31 @@ class Function
   void
   set_enclosing(Function* enclosing)
   {
-    gcc_assert(this->enclosing_ == NULL);
+    go_assert(this->enclosing_ == NULL);
     this->enclosing_ = enclosing;
   }
 
-  // Create the named result variables in the outer block.
+  // The result variables.
+  typedef std::vector<Named_object*> Results;
+
+  // Create the result variables in the outer block.
   void
-  create_named_result_variables(Gogo*);
+  create_result_variables(Gogo*);
 
   // Update the named result variables when cloning a function which
   // calls recover.
   void
-  update_named_result_variables();
+  update_result_variables();
+
+  // Return the result variables.
+  Results*
+  result_variables()
+  { return this->results_; }
+
+  // Whether the result variables have names.
+  bool
+  results_are_named() const
+  { return this->results_are_named_; }
 
   // Add a new field to the closure variable.
   void
@@ -839,7 +800,7 @@ class Function
   void
   set_closure_var(Named_object* v)
   {
-    gcc_assert(this->closure_var_ == NULL);
+    go_assert(this->closure_var_ == NULL);
     this->closure_var_ = v;
   }
 
@@ -848,7 +809,7 @@ class Function
   Named_object*
   enclosing_var(unsigned int index)
   {
-    gcc_assert(index < this->closure_fields_.size());
+    go_assert(index < this->closure_fields_.size());
     return closure_fields_[index].first;
   }
 
@@ -878,6 +839,10 @@ class Function
   Label*
   add_label_reference(const std::string& label_name);
 
+  // Warn about labels that are defined but not used.
+  void
+  check_labels() const;
+
   // Whether this function calls the predeclared recover function.
   bool
   calls_recover() const
@@ -931,7 +896,7 @@ class Function
   tree
   get_decl() const
   {
-    gcc_assert(this->fndecl_ != NULL);
+    go_assert(this->fndecl_ != NULL);
     return this->fndecl_;
   }
 
@@ -945,7 +910,7 @@ class Function
   return_value(Gogo*, Named_object*, source_location, tree* stmt_list) const;
 
   // Get a tree for the variable holding the defer stack.
-  tree
+  Expression*
   defer_stack(source_location);
 
   // Export the function.
@@ -976,8 +941,6 @@ class Function
   void
   build_defer_wrapper(Gogo*, Named_object*, tree*, tree*);
 
-  typedef std::vector<Named_object*> Named_results;
-
   typedef std::vector<std::pair<Named_object*,
                                source_location> > Closure_fields;
 
@@ -986,8 +949,8 @@ class Function
   // The enclosing function.  This is NULL when there isn't one, which
   // is the normal case.
   Function* enclosing_;
-  // The named result variables, if any.
-  Named_results* named_results_;
+  // The result variables, if any.
+  Results* results_;
   // If there is a closure, this is the list of variables which appear
   // in the closure.  This is created by the parser, and then resolved
   // to a real type when we lower parse trees.
@@ -1003,9 +966,12 @@ class Function
   Labels labels_;
   // The function decl.
   tree fndecl_;
-  // A variable holding the defer stack variable.  This is NULL unless
-  // we actually need a defer stack.
-  tree defer_stack_;
+  // The defer stack variable.  A pointer to this variable is used to
+  // distinguish the defer stack for one function from another.  This
+  // is NULL unless we actually need a defer stack.
+  Temporary_statement* defer_stack_;
+  // True if the result variables are named.
+  bool results_are_named_;
   // True if this function calls the predeclared recover function.
   bool calls_recover_;
   // True if this a thunk built for a function which calls recover.
@@ -1116,7 +1082,7 @@ class Variable
   void
   set_is_receiver()
   {
-    gcc_assert(this->is_parameter_);
+    go_assert(this->is_parameter_);
     this->is_receiver_ = true;
   }
 
@@ -1125,7 +1091,7 @@ class Variable
   void
   set_is_not_receiver()
   {
-    gcc_assert(this->is_parameter_);
+    go_assert(this->is_parameter_);
     this->is_receiver_ = false;
   }
 
@@ -1144,6 +1110,22 @@ class Variable
   is_in_heap() const
   { return this->is_address_taken_ && !this->is_global_; }
 
+  // Note that something takes the address of this variable.
+  void
+  set_address_taken()
+  { this->is_address_taken_ = true; }
+
+  // Return whether the address is taken but does not escape.
+  bool
+  is_non_escaping_address_taken() const
+  { return this->is_non_escaping_address_taken_; }
+
+  // Note that something takes the address of this variable such that
+  // the address does not escape the function.
+  void
+  set_non_escaping_address_taken()
+  { this->is_non_escaping_address_taken_ = true; }
+
   // Get the source location of the variable's declaration.
   source_location
   location() const
@@ -1153,7 +1135,7 @@ class Variable
   void
   set_is_varargs_parameter()
   {
-    gcc_assert(this->is_parameter_);
+    go_assert(this->is_parameter_);
     this->is_varargs_parameter_ = true;
   }
 
@@ -1179,7 +1161,7 @@ class Variable
 
   // Lower the initialization expression after parsing is complete.
   void
-  lower_init_expression(Gogo*, Named_object*);
+  lower_init_expression(Gogo*, Named_object*, Statement_inserter*);
 
   // A special case: the init value is used only to determine the
   // type.  This is used if the variable is defined using := with the
@@ -1219,7 +1201,7 @@ class Variable
   void
   clear_type_from_chan_element()
   {
-    gcc_assert(this->type_from_chan_element_);
+    go_assert(this->type_from_chan_element_);
     this->type_from_chan_element_ = false;
   }
 
@@ -1230,16 +1212,16 @@ class Variable
 
   // Traverse the initializer expression.
   int
-  traverse_expression(Traverse*);
+  traverse_expression(Traverse*, unsigned int traverse_mask);
 
   // Determine the type of the variable if necessary.
   void
   determine_type();
 
-  // Note that something takes the address of this variable.
-  void
-  set_address_taken()
-  { this->is_address_taken_ = true; }
+  // Get the backend representation of the variable.
+  Bvariable*
+  get_backend_variable(Gogo*, Named_object*, const Package*,
+                      const std::string&);
 
   // Get the initial value of the variable as a tree.  This may only
   // be called if has_pre_init() returns false.
@@ -1283,6 +1265,8 @@ class Variable
   Block* preinit_;
   // Location of variable definition.
   source_location location_;
+  // Backend representation.
+  Bvariable* backend_;
   // Whether this is a global variable.
   bool is_global_ : 1;
   // Whether this is a function parameter.
@@ -1291,8 +1275,13 @@ class Variable
   bool is_receiver_ : 1;
   // Whether this is the varargs parameter of a function.
   bool is_varargs_parameter_ : 1;
-  // Whether something takes the address of this variable.
+  // Whether something takes the address of this variable.  For a
+  // local variable this implies that the variable has to be on the
+  // heap.
   bool is_address_taken_ : 1;
+  // Whether something takes the address of this variable such that
+  // the address does not escape the function.
+  bool is_non_escaping_address_taken_ : 1;
   // True if we have seen this variable in a traversal.
   bool seen_ : 1;
   // True if we have lowered the initialization expression.
@@ -1317,9 +1306,11 @@ class Variable
 class Result_variable
 {
  public:
-  Result_variable(Type* type, Function* function, int index)
-    : type_(type), function_(function), index_(index),
-      is_address_taken_(false)
+  Result_variable(Type* type, Function* function, int index,
+                 source_location location)
+    : type_(type), function_(function), index_(index), location_(location),
+      backend_(NULL), is_address_taken_(false),
+      is_non_escaping_address_taken_(false)
   { }
 
   // Get the type of the result variable.
@@ -1337,6 +1328,11 @@ class Result_variable
   index() const
   { return this->index_; }
 
+  // The location of the variable definition.
+  source_location
+  location() const
+  { return this->location_; }
+
   // Whether this variable's address is taken.
   bool
   is_address_taken() const
@@ -1347,6 +1343,17 @@ class Result_variable
   set_address_taken()
   { this->is_address_taken_ = true; }
 
+  // Return whether the address is taken but does not escape.
+  bool
+  is_non_escaping_address_taken() const
+  { return this->is_non_escaping_address_taken_; }
+
+  // Note that something takes the address of this variable such that
+  // the address does not escape the function.
+  void
+  set_non_escaping_address_taken()
+  { this->is_non_escaping_address_taken_ = true; }
+
   // Whether this variable should live in the heap.
   bool
   is_in_heap() const
@@ -1358,6 +1365,10 @@ class Result_variable
   set_function(Function* function)
   { this->function_ = function; }
 
+  // Get the backend representation of the variable.
+  Bvariable*
+  get_backend_variable(Gogo*, Named_object*, const std::string&);
+
  private:
   // Type of result variable.
   Type* type_;
@@ -1365,8 +1376,15 @@ class Result_variable
   Function* function_;
   // Index in list of results.
   int index_;
+  // Where the result variable is defined.
+  source_location location_;
+  // Backend representation.
+  Bvariable* backend_;
   // Whether something takes the address of this variable.
   bool is_address_taken_;
+  // Whether something takes the address of this variable such that
+  // the address does not escape the function.
+  bool is_non_escaping_address_taken_;
 };
 
 // The value we keep for a named constant.  This lets us hold a type
@@ -1670,126 +1688,126 @@ class Named_object
   Unknown_name*
   unknown_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_UNKNOWN);
+    go_assert(this->classification_ == NAMED_OBJECT_UNKNOWN);
     return this->u_.unknown_value;
   }
 
   const Unknown_name*
   unknown_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_UNKNOWN);
+    go_assert(this->classification_ == NAMED_OBJECT_UNKNOWN);
     return this->u_.unknown_value;
   }
 
   Named_constant*
   const_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_CONST);
+    go_assert(this->classification_ == NAMED_OBJECT_CONST);
     return this->u_.const_value;
   }
 
   const Named_constant*
   const_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_CONST);
+    go_assert(this->classification_ == NAMED_OBJECT_CONST);
     return this->u_.const_value;
   }
 
   Named_type*
   type_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_TYPE);
+    go_assert(this->classification_ == NAMED_OBJECT_TYPE);
     return this->u_.type_value;
   }
 
   const Named_type*
   type_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_TYPE);
+    go_assert(this->classification_ == NAMED_OBJECT_TYPE);
     return this->u_.type_value;
   }
 
   Type_declaration*
   type_declaration_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_TYPE_DECLARATION);
+    go_assert(this->classification_ == NAMED_OBJECT_TYPE_DECLARATION);
     return this->u_.type_declaration;
   }
 
   const Type_declaration*
   type_declaration_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_TYPE_DECLARATION);
+    go_assert(this->classification_ == NAMED_OBJECT_TYPE_DECLARATION);
     return this->u_.type_declaration;
   }
 
   Variable*
   var_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_VAR);
+    go_assert(this->classification_ == NAMED_OBJECT_VAR);
     return this->u_.var_value;
   }
 
   const Variable*
   var_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_VAR);
+    go_assert(this->classification_ == NAMED_OBJECT_VAR);
     return this->u_.var_value;
   }
 
   Result_variable*
   result_var_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_RESULT_VAR);
+    go_assert(this->classification_ == NAMED_OBJECT_RESULT_VAR);
     return this->u_.result_var_value;
   }
 
   const Result_variable*
   result_var_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_RESULT_VAR);
+    go_assert(this->classification_ == NAMED_OBJECT_RESULT_VAR);
     return this->u_.result_var_value;
   }
 
   Function*
   func_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_FUNC);
+    go_assert(this->classification_ == NAMED_OBJECT_FUNC);
     return this->u_.func_value;
   }
 
   const Function*
   func_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_FUNC);
+    go_assert(this->classification_ == NAMED_OBJECT_FUNC);
     return this->u_.func_value;
   }
 
   Function_declaration*
   func_declaration_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_FUNC_DECLARATION);
+    go_assert(this->classification_ == NAMED_OBJECT_FUNC_DECLARATION);
     return this->u_.func_declaration_value;
   }
 
   const Function_declaration*
   func_declaration_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_FUNC_DECLARATION);
+    go_assert(this->classification_ == NAMED_OBJECT_FUNC_DECLARATION);
     return this->u_.func_declaration_value;
   }
 
   Package*
   package_value()
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_PACKAGE);
+    go_assert(this->classification_ == NAMED_OBJECT_PACKAGE);
     return this->u_.package_value;
   }
 
   const Package*
   package_value() const
   {
-    gcc_assert(this->classification_ == NAMED_OBJECT_PACKAGE);
+    go_assert(this->classification_ == NAMED_OBJECT_PACKAGE);
     return this->u_.package_value;
   }
 
@@ -1839,6 +1857,10 @@ class Named_object
   source_location
   location() const;
 
+  // Convert a variable to the backend representation.
+  Bvariable*
+  get_backend_variable(Gogo*, Named_object* function);
+
   // Return a tree for the external identifier for this object.
   tree
   get_id(Gogo*);
@@ -2086,7 +2108,7 @@ class Label
 {
  public:
   Label(const std::string& name)
-    : name_(name), location_(0), decl_(NULL)
+    : name_(name), location_(0), is_used_(false), blabel_(NULL)
   { }
 
   // Return the label's name.
@@ -2099,6 +2121,16 @@ class Label
   is_defined() const
   { return this->location_ != 0; }
 
+  // Return whether the label has been used.
+  bool
+  is_used() const
+  { return this->is_used_; }
+
+  // Record that the label is used.
+  void
+  set_is_used()
+  { this->is_used_ = true; }
+
   // Return the location of the definition.
   source_location
   location() const
@@ -2108,17 +2140,19 @@ class Label
   void
   define(source_location location)
   {
-    gcc_assert(this->location_ == 0);
+    go_assert(this->location_ == 0);
     this->location_ = location;
   }
 
-  // Return the LABEL_DECL for this decl.
-  tree
-  get_decl();
+  // Return the backend representation for this label.
+  Blabel*
+  get_backend_label(Translate_context*);
 
-  // Return an expression for the address of this label.
-  tree
-  get_addr(source_location location);
+  // Return an expression for the address of this label.  This is used
+  // to get the return address of a deferred function to see whether
+  // the function may call recover.
+  Bexpression*
+  get_addr(Translate_context*, source_location location);
 
  private:
   // The name of the label.
@@ -2126,8 +2160,10 @@ class Label
   // The location of the definition.  This is 0 if the label has not
   // yet been defined.
   source_location location_;
-  // The LABEL_DECL.
-  tree decl_;
+  // Whether the label has been used.
+  bool is_used_;
+  // The backend representation.
+  Blabel* blabel_;
 };
 
 // An unnamed label.  These are used when lowering loops.
@@ -2136,7 +2172,7 @@ class Unnamed_label
 {
  public:
   Unnamed_label(source_location location)
-    : location_(location), decl_(NULL)
+    : location_(location), blabel_(NULL)
   { }
 
   // Get the location where the label is defined.
@@ -2150,22 +2186,22 @@ class Unnamed_label
   { this->location_ = location; }
 
   // Return a statement which defines this label.
-  tree
-  get_definition();
+  Bstatement*
+  get_definition(Translate_context*);
 
   // Return a goto to this label from LOCATION.
-  tree
-  get_goto(source_location location);
+  Bstatement*
+  get_goto(Translate_context*, source_location location);
 
  private:
-  // Return the LABEL_DECL to use with GOTO_EXPR.
-  tree
-  get_decl();
+  // Return the backend representation.
+  Blabel*
+  get_blabel(Translate_context*);
 
   // The location where the label is defined.
   source_location location_;
-  // The LABEL_DECL.
-  tree decl_;
+  // The backend representation of this label.
+  Blabel* blabel_;
 };
 
 // An imported package.
@@ -2193,7 +2229,7 @@ class Package
   const std::string&
   unique_prefix() const
   {
-    gcc_assert(!this->unique_prefix_.empty());
+    go_assert(!this->unique_prefix_.empty());
     return this->unique_prefix_;
   }
 
@@ -2431,16 +2467,56 @@ class Traverse
   Expressions_seen* expressions_seen_;
 };
 
-// When translating the gogo IR into trees, this is the context we
-// pass down the blocks and statements.
+// A class which makes it easier to insert new statements before the
+// current statement during a traversal.
+
+class Statement_inserter
+{
+ public:
+  // Empty constructor.
+  Statement_inserter()
+    : block_(NULL), pindex_(NULL), gogo_(NULL), var_(NULL)
+  { }
+
+  // Constructor for a statement in a block.
+  Statement_inserter(Block* block, size_t *pindex)
+    : block_(block), pindex_(pindex), gogo_(NULL), var_(NULL)
+  { }
+
+  // Constructor for a global variable.
+  Statement_inserter(Gogo* gogo, Variable* var)
+    : block_(NULL), pindex_(NULL), gogo_(gogo), var_(var)
+  { go_assert(var->is_global()); }
+
+  // We use the default copy constructor and assignment operator.
+
+  // Insert S before the statement we are traversing, or before the
+  // initialization expression of a global variable.
+  void
+  insert(Statement* s);
+
+ private:
+  // The block that the statement is in.
+  Block* block_;
+  // The index of the statement that we are traversing.
+  size_t* pindex_;
+  // The IR, needed when looking at an initializer expression for a
+  // global variable.
+  Gogo* gogo_;
+  // The global variable, when looking at an initializer expression.
+  Variable* var_;
+};
+
+// When translating the gogo IR into the backend data structure, this
+// is the context we pass down the blocks and statements.
 
 class Translate_context
 {
  public:
   Translate_context(Gogo* gogo, Named_object* function, Block* block,
-                   tree block_tree)
-    : gogo_(gogo), function_(function), block_(block), block_tree_(block_tree),
-      is_const_(false)
+                   Bblock* bblock)
+    : gogo_(gogo), backend_(gogo->backend()), function_(function),
+      block_(block), bblock_(bblock), is_const_(false)
   { }
 
   // Accessors.
@@ -2449,6 +2525,10 @@ class Translate_context
   gogo()
   { return this->gogo_; }
 
+  Backend*
+  backend()
+  { return this->backend_; }
+
   Named_object*
   function()
   { return this->function_; }
@@ -2457,9 +2537,9 @@ class Translate_context
   block()
   { return this->block_; }
 
-  tree
-  block_tree()
-  { return this->block_tree_; }
+  Bblock*
+  bblock()
+  { return this->bblock_; }
 
   bool
   is_const()
@@ -2473,12 +2553,17 @@ class Translate_context
  private:
   // The IR for the entire compilation unit.
   Gogo* gogo_;
-  // The function we are currently translating.
+  // The generator for the backend data structures.
+  Backend* backend_;
+  // The function we are currently translating.  NULL if not in a
+  // function, e.g., the initializer of a global variable.
   Named_object* function_;
-  // The block we are currently translating.
+  // The block we are currently translating.  NULL if not in a
+  // function.
   Block *block_;
-  // The BLOCK node for the current block.
-  tree block_tree_;
+  // The backend representation of the current block.  NULL if block_
+  // is NULL.
+  Bblock* bblock_;
   // Whether this is being evaluated in a constant context.  This is
   // used for type descriptor initializers.
   bool is_const_;