This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Go patch committed: Use function descriptors


This patch to gccgo changes the representation of values of function
type.  They used to be a pointer to function code, like a C function
pointer.  They are now a pointer to a struct.  The first field of the
struct points to the function code.  The remaining fields, if any, are
the addresses of variables referenced in enclosing functions.  For each
call to a function, the address of the function descriptor is passed as
the last argument.

This lets us avoid generating trampolines, and removes the use
of writable/executable sections of the heap.

This is also a prerequisite to a new Go 1.1 feature, method values.

Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline and 4.8 branch.

Ian


2013-06-18  Ian Lance Taylor  <iant@google.com>

	* go-gcc.cc (Gcc_backend::immutable_struct): Add is_hidden
	parameter.
	(Gcc_backend::immutable_struct_set_init): Likewise.


Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 199461)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -287,10 +287,10 @@ class Gcc_backend : public Backend
 		     Location, Bstatement**);
 
   Bvariable*
-  immutable_struct(const std::string&, bool, Btype*, Location);
+  immutable_struct(const std::string&, bool, bool, Btype*, Location);
 
   void
-  immutable_struct_set_init(Bvariable*, const std::string&, bool, Btype*,
+  immutable_struct_set_init(Bvariable*, const std::string&, bool, bool, Btype*,
 			    Location, Bexpression*);
 
   Bvariable*
@@ -1454,8 +1454,8 @@ Gcc_backend::temporary_variable(Bfunctio
 // Create a named immutable initialized data structure.
 
 Bvariable*
-Gcc_backend::immutable_struct(const std::string& name, bool, Btype* btype,
-			      Location location)
+Gcc_backend::immutable_struct(const std::string& name, bool, bool,
+			      Btype* btype, Location location)
 {
   tree type_tree = btype->get_tree();
   if (type_tree == error_mark_node)
@@ -1482,7 +1482,7 @@ Gcc_backend::immutable_struct(const std:
 
 void
 Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&,
-				       bool is_common, Btype*,
+				       bool is_hidden, bool is_common, Btype*,
 				       Location,
 				       Bexpression* initializer)
 {
@@ -1495,7 +1495,10 @@ Gcc_backend::immutable_struct_set_init(B
 
   // We can't call make_decl_one_only until we set DECL_INITIAL.
   if (!is_common)
-    TREE_PUBLIC(decl) = 1;
+    {
+      if (!is_hidden)
+	TREE_PUBLIC(decl) = 1;
+    }
   else
     {
       make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(revision 199461)
+++ gcc/go/gofrontend/gogo-tree.cc	(working copy)
@@ -755,6 +755,18 @@ Gogo::write_globals()
   this->build_interface_method_tables();
 
   Bindings* bindings = this->current_bindings();
+
+  for (Bindings::const_declarations_iterator p = bindings->begin_declarations();
+       p != bindings->end_declarations();
+       ++p)
+    {
+      // If any function declarations needed a descriptor, make sure
+      // we build it.
+      Named_object* no = p->second;
+      if (no->is_function_declaration())
+	no->func_declaration_value()->build_backend_descriptor(this);
+    }
+
   size_t count_definitions = bindings->size_definitions();
   size_t count = count_definitions;
 
@@ -782,6 +794,8 @@ Gogo::write_globals()
     {
       Named_object* no = *p;
 
+      go_assert(i < count);
+
       go_assert(!no->is_type_declaration() && !no->is_function_declaration());
       // There is nothing to do for a package.
       if (no->is_package())
@@ -1255,14 +1269,47 @@ Function::get_or_make_decl(Gogo* gogo, N
   if (this->fndecl_ == NULL_TREE)
     {
       tree functype = type_to_tree(this->type_->get_backend(gogo));
+
+      if (functype != error_mark_node)
+	{
+	  // The type of a function comes back as a pointer to a
+	  // struct whose first field is the function, but we want the
+	  // real function type for a function declaration.
+	  go_assert(POINTER_TYPE_P(functype)
+		    && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE);
+	  functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype)));
+	  go_assert(FUNCTION_POINTER_TYPE_P(functype));
+	  functype = TREE_TYPE(functype);
+
+	  // In the struct, the function type always has a trailing
+	  // closure argument.  For the function body, we only use
+	  // that trailing arg if this is a function literal or if it
+	  // is a wrapper created to store in a descriptor.  Remove it
+	  // in that case.
+	  if (this->enclosing_ == NULL && !this->is_descriptor_wrapper_)
+	    {
+	      tree old_params = TYPE_ARG_TYPES(functype);
+	      go_assert(old_params != NULL_TREE
+			&& old_params != void_list_node);
+	      tree new_params = NULL_TREE;
+	      tree *pp = &new_params;
+	      while (TREE_CHAIN (old_params) != void_list_node)
+		{
+		  tree p = TREE_VALUE(old_params);
+		  go_assert(TYPE_P(p));
+		  *pp = tree_cons(NULL_TREE, p, NULL_TREE);
+		  pp = &TREE_CHAIN(*pp);
+		  old_params = TREE_CHAIN (old_params);
+		}
+	      *pp = void_list_node;
+	      functype = build_function_type(TREE_TYPE(functype), new_params);
+	    }
+	}
+
       if (functype == error_mark_node)
 	this->fndecl_ = error_mark_node;
       else
 	{
-	  // The type of a function comes back as a pointer, but we
-	  // want the real function type for a function declaration.
-	  go_assert(POINTER_TYPE_P(functype));
-	  functype = TREE_TYPE(functype);
 	  tree decl = build_decl(this->location().gcc_location(), FUNCTION_DECL,
                                  id, functype);
 
@@ -1308,9 +1355,6 @@ Function::get_or_make_decl(Gogo* gogo, N
 	  DECL_CONTEXT(resdecl) = decl;
 	  DECL_RESULT(decl) = resdecl;
 
-	  if (this->enclosing_ != NULL)
-	    DECL_STATIC_CHAIN(decl) = 1;
-
 	  // If a function calls the predeclared recover function, we
 	  // can't inline it, because recover behaves differently in a
 	  // function passed directly to defer.  If this is a recover
@@ -1333,29 +1377,6 @@ Function::get_or_make_decl(Gogo* gogo, N
 	    resolve_unique_section (decl, 0, 1);
 
 	  go_preserve_from_gc(decl);
-
-	  if (this->closure_var_ != NULL)
-	    {
-	      push_struct_function(decl);
-
-	      Bvariable* bvar = this->closure_var_->get_backend_variable(gogo,
-									 no);
-	      tree closure_decl = var_to_tree(bvar);
-	      if (closure_decl == error_mark_node)
-		this->fndecl_ = error_mark_node;
-	      else
-		{
-		  DECL_ARTIFICIAL(closure_decl) = 1;
-		  DECL_IGNORED_P(closure_decl) = 1;
-		  TREE_USED(closure_decl) = 1;
-		  DECL_ARG_TYPE(closure_decl) = TREE_TYPE(closure_decl);
-		  TREE_READONLY(closure_decl) = 1;
-
-		  DECL_STRUCT_FUNCTION(decl)->static_chain_decl = closure_decl;
-		}
-
-	      pop_cfun();
-	    }
 	}
     }
   return this->fndecl_;
@@ -1382,15 +1403,44 @@ Function_declaration::get_or_make_decl(G
 	}
 
       tree functype = type_to_tree(this->fntype_->get_backend(gogo));
+
+      if (functype != error_mark_node)
+	{
+	  // The type of a function comes back as a pointer to a
+	  // struct whose first field is the function, but we want the
+	  // real function type for a function declaration.
+	  go_assert(POINTER_TYPE_P(functype)
+		    && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE);
+	  functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype)));
+	  go_assert(FUNCTION_POINTER_TYPE_P(functype));
+	  functype = TREE_TYPE(functype);
+
+	  // In the struct, the function type always has a trailing
+	  // closure argument.  Here we are referring to the function
+	  // code directly, and we know it is not a function literal,
+	  // and we know it is not a wrapper created to store in a
+	  // descriptor.  Remove that trailing argument.
+	  tree old_params = TYPE_ARG_TYPES(functype);
+	  go_assert(old_params != NULL_TREE && old_params != void_list_node);
+	  tree new_params = NULL_TREE;
+	  tree *pp = &new_params;
+	  while (TREE_CHAIN (old_params) != void_list_node)
+	    {
+	      tree p = TREE_VALUE(old_params);
+	      go_assert(TYPE_P(p));
+	      *pp = tree_cons(NULL_TREE, p, NULL_TREE);
+	      pp = &TREE_CHAIN(*pp);
+	      old_params = TREE_CHAIN (old_params);
+	    }
+	  *pp = void_list_node;
+	  functype = build_function_type(TREE_TYPE(functype), new_params);
+	}
+
       tree decl;
       if (functype == error_mark_node)
 	decl = error_mark_node;
       else
 	{
-	  // The type of a function comes back as a pointer, but we
-	  // want the real function type for a function declaration.
-	  go_assert(POINTER_TYPE_P(functype));
-	  functype = TREE_TYPE(functype);
 	  decl = build_decl(this->location().gcc_location(), FUNCTION_DECL, id,
                             functype);
 	  TREE_PUBLIC(decl) = 1;
@@ -1599,6 +1649,32 @@ Function::build_tree(Gogo* gogo, Named_o
 	    }
 	}
     }
+
+  // The closure variable is passed last, if this is a function
+  // literal or a descriptor wrapper.
+  if (this->closure_var_ != NULL)
+    {
+      Bvariable* bvar =
+	this->closure_var_->get_backend_variable(gogo, named_function);
+      tree var_decl = var_to_tree(bvar);
+      if (var_decl != error_mark_node)
+	{
+	  go_assert(TREE_CODE(var_decl) == PARM_DECL);
+	  *pp = var_decl;
+	  pp = &DECL_CHAIN(*pp);
+	}
+    }
+  else if (this->enclosing_ != NULL || this->is_descriptor_wrapper_)
+    {
+      tree parm_decl = build_decl(this->location_.gcc_location(), PARM_DECL,
+				  get_identifier("$closure"),
+				  const_ptr_type_node);
+      DECL_CONTEXT(parm_decl) = current_function_decl;
+      DECL_ARG_TYPE(parm_decl) = const_ptr_type_node;
+      *pp = parm_decl;
+      pp = &DECL_CHAIN(*pp);
+    }
+
   *pp = NULL_TREE;
 
   DECL_ARGUMENTS(fndecl) = params;
@@ -1681,6 +1757,13 @@ Function::build_tree(Gogo* gogo, Named_o
 
       DECL_SAVED_TREE(fndecl) = code;
     }
+
+  // If we created a descriptor for the function, make sure we emit it.
+  if (this->descriptor_ != NULL)
+    {
+      Translate_context context(gogo, NULL, NULL, NULL);
+      this->descriptor_->get_tree(&context);
+    }
 }
 
 // Build the wrappers around function code needed if the function has
@@ -1844,6 +1927,20 @@ Function::return_value(Gogo* gogo, Named
     }
 }
 
+// Build the descriptor for a function declaration.  This won't
+// necessarily happen if the package has just a declaration for the
+// function and no other reference to it, but we may still need the
+// descriptor for references from other packages.
+void
+Function_declaration::build_backend_descriptor(Gogo* gogo)
+{
+  if (this->descriptor_ != NULL)
+    {
+      Translate_context context(gogo, NULL, NULL, NULL);
+      this->descriptor_->get_tree(&context);
+    }
+}
+
 // Return the integer type to use for a size.
 
 GO_EXTERN_C
@@ -2437,70 +2534,3 @@ Gogo::receive_from_channel(tree type_tre
 		    build2(COMPOUND_EXPR, type_tree, call, tmp));
     }
 }
-
-// Return the type of a function trampoline.  This is like
-// get_trampoline_type in tree-nested.c.
-
-tree
-Gogo::trampoline_type_tree()
-{
-  static tree type_tree;
-  if (type_tree == NULL_TREE)
-    {
-      unsigned int size;
-      unsigned int align;
-      go_trampoline_info(&size, &align);
-      tree t = build_index_type(build_int_cst(integer_type_node, size - 1));
-      t = build_array_type(char_type_node, t);
-
-      type_tree = Gogo::builtin_struct(NULL, "__go_trampoline", NULL_TREE, 1,
-				       "__data", t);
-      t = TYPE_FIELDS(type_tree);
-      DECL_ALIGN(t) = align;
-      DECL_USER_ALIGN(t) = 1;
-
-      go_preserve_from_gc(type_tree);
-    }
-  return type_tree;
-}
-
-// Make a trampoline which calls FNADDR passing CLOSURE.
-
-tree
-Gogo::make_trampoline(tree fnaddr, tree closure, Location location)
-{
-  tree trampoline_type = Gogo::trampoline_type_tree();
-  tree trampoline_size = TYPE_SIZE_UNIT(trampoline_type);
-
-  closure = save_expr(closure);
-
-  // We allocate the trampoline using a special function which will
-  // mark it as executable.
-  static tree trampoline_fndecl;
-  tree x = Gogo::call_builtin(&trampoline_fndecl,
-			      location,
-			      "__go_allocate_trampoline",
-			      2,
-			      ptr_type_node,
-			      size_type_node,
-			      trampoline_size,
-			      ptr_type_node,
-			      fold_convert_loc(location.gcc_location(),
-                                               ptr_type_node, closure));
-  if (x == error_mark_node)
-    return error_mark_node;
-
-  x = save_expr(x);
-
-  // Initialize the trampoline.
-  tree calldecl = builtin_decl_implicit(BUILT_IN_INIT_HEAP_TRAMPOLINE);
-  tree ini = build_call_expr(calldecl, 3, x, fnaddr, closure);
-
-  // On some targets the trampoline address needs to be adjusted.  For
-  // example, when compiling in Thumb mode on the ARM, the address
-  // needs to have the low bit set.
-  x = build_call_expr(builtin_decl_explicit(BUILT_IN_ADJUST_TRAMPOLINE), 1, x);
-  x = fold_convert(TREE_TYPE(fnaddr), x);
-
-  return build2(COMPOUND_EXPR, TREE_TYPE(x), ini, x);
-}
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 199461)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -364,7 +364,7 @@ Gogo::set_package_name(const std::string
       // Declare "main" as a function which takes no parameters and
       // returns no value.
       Location uloc = Linemap::unknown_location();
-      this->declare_function("main",
+      this->declare_function(Gogo::pack_hidden_name("main", false),
 			     Type::make_function_type (NULL, NULL, NULL, uloc),
 			     uloc);
     }
@@ -1599,14 +1599,23 @@ Lower_parse_tree::constant(Named_object*
   return TRAVERSE_CONTINUE;
 }
 
-// Lower function closure types.  Record the function while lowering
-// it, so that we can pass it down when lowering an expression.
+// Lower the body of a function, and set the closure type.  Record the
+// function while lowering it, so that we can pass it down when
+// lowering an expression.
 
 int
 Lower_parse_tree::function(Named_object* no)
 {
   no->func_value()->set_closure_type();
 
+  // Make sure that every externally visible function has a
+  // descriptor, so that packages that import this one can refer to
+  // it.
+  if (!Gogo::is_hidden_name(no->name())
+      && !no->func_value()->is_method()
+      && !no->func_value()->is_descriptor_wrapper())
+    no->func_value()->descriptor(this->gogo_, no);
+
   go_assert(this->function_ == NULL);
   this->function_ = no;
   int t = no->func_value()->traverse(this);
@@ -1694,6 +1703,28 @@ Lower_parse_tree::expression(Expression*
 void
 Gogo::lower_parse_tree()
 {
+  // Create a function descriptor for any function that is declared in
+  // this package.  This is so that we have a descriptor for functions
+  // written in assembly.  Gather the descriptors first so that we
+  // don't add declarations while looping over them.
+  std::vector<Named_object*> fndecls;
+  Bindings* b = this->package_->bindings();
+  for (Bindings::const_declarations_iterator p = b->begin_declarations();
+       p != b->end_declarations();
+       ++p)
+    {
+      Named_object* no = p->second;
+      if (no->is_function_declaration()
+	  && !no->func_declaration_value()->type()->is_method()
+	  && !Linemap::is_predeclared_location(no->location()))
+	fndecls.push_back(no);
+    }
+  for (std::vector<Named_object*>::const_iterator p = fndecls.begin();
+       p != fndecls.end();
+       ++p)
+    (*p)->func_declaration_value()->descriptor(this, *p);
+  fndecls.clear();
+
   Lower_parse_tree lower_parse_tree(this, NULL);
   this->traverse(&lower_parse_tree);
 }
@@ -2643,6 +2674,13 @@ Build_recover_thunks::function(Named_obj
   Expression* closure = NULL;
   if (orig_func->needs_closure())
     {
+      // For the new function we are creating, declare a new parameter
+      // variable NEW_CLOSURE_NO and set it to be the closure variable
+      // of the function.  This will be set to the closure value
+      // passed in by the caller.  Then pass a reference to this
+      // variable as the closure value when calling the original
+      // function.  In other words, simply pass the closure value
+      // through the thunk we are creating.
       Named_object* orig_closure_no = orig_func->closure_var();
       Variable* orig_closure_var = orig_closure_no->var_value();
       Variable* new_var = new Variable(orig_closure_var->type(), NULL, false,
@@ -3101,6 +3139,7 @@ Gogo::convert_named_types()
   Map_type::make_map_descriptor_type();
   Channel_type::make_chan_type_descriptor_type();
   Interface_type::make_interface_type_descriptor_type();
+  Expression::make_func_descriptor_type();
   Type::convert_builtin_named_types(this);
 
   Runtime::convert_types(this);
@@ -3128,10 +3167,10 @@ Function::Function(Function_type* type,
 		   Location location)
   : type_(type), enclosing_(enclosing), results_(NULL),
     closure_var_(NULL), block_(block), location_(location), labels_(),
-    local_type_count_(0), fndecl_(NULL), defer_stack_(NULL),
+    local_type_count_(0), descriptor_(NULL), fndecl_(NULL), defer_stack_(NULL),
     results_are_named_(false), nointerface_(false), calls_recover_(false),
     is_recover_thunk_(false), has_recover_thunk_(false),
-    in_unique_section_(false)
+    in_unique_section_(false), is_descriptor_wrapper_(false)
 {
 }
 
@@ -3206,6 +3245,7 @@ Function::closure_var()
 {
   if (this->closure_var_ == NULL)
     {
+      go_assert(this->descriptor_ == NULL);
       // We don't know the type of the variable yet.  We add fields as
       // we find them.
       Location loc = this->type_->location();
@@ -3229,6 +3269,13 @@ Function::set_closure_type()
     return;
   Named_object* closure = this->closure_var_;
   Struct_type* st = closure->var_value()->type()->deref()->struct_type();
+
+  // The first field of a closure is always a pointer to the function
+  // code.
+  Type* voidptr_type = Type::make_pointer_type(Type::make_void_type());
+  st->push_field(Struct_field(Typed_identifier(".$f", voidptr_type,
+					       this->location_)));
+
   unsigned int index = 0;
   for (Closure_fields::const_iterator p = this->closure_fields_.begin();
        p != this->closure_fields_.end();
@@ -3410,6 +3457,136 @@ Function::determine_types()
     this->block_->determine_types();
 }
 
+// Build a wrapper function for a function descriptor.  A function
+// descriptor refers to a function that takes a closure as its last
+// argument.  In this case there will be no closure, but an indirect
+// call will pass nil as the last argument.  We need to build a
+// wrapper function that accepts and discards that last argument, so
+// that cases like -mrtd will work correctly.  In most cases the
+// wrapper function will simply be a jump.
+
+Named_object*
+Function::make_descriptor_wrapper(Gogo* gogo, Named_object* no,
+				  Function_type* orig_fntype)
+{
+  Location loc = no->location();
+
+  Typed_identifier_list* new_params = new Typed_identifier_list();
+  const Typed_identifier_list* orig_params = orig_fntype->parameters();
+  if (orig_params != NULL && !orig_params->empty())
+    {
+      static int count;
+      char buf[50];
+      for (Typed_identifier_list::const_iterator p = orig_params->begin();
+	   p != orig_params->end();
+	   ++p)
+	{
+	  snprintf(buf, sizeof buf, "pt.%u", count);
+	  ++count;
+	  new_params->push_back(Typed_identifier(buf, p->type(),
+						 p->location()));
+	}
+    }
+  Type* vt = Type::make_pointer_type(Type::make_void_type());
+  new_params->push_back(Typed_identifier("closure.0", vt, loc));
+
+  const Typed_identifier_list* orig_results = orig_fntype->results();
+  Typed_identifier_list* new_results;
+  if (orig_results == NULL || orig_results->empty())
+    new_results = NULL;
+  else
+    {
+      new_results = new Typed_identifier_list();
+      for (Typed_identifier_list::const_iterator p = orig_results->begin();
+	   p != orig_results->end();
+	   ++p)
+	new_results->push_back(Typed_identifier("", p->type(),
+						p->location()));
+    }
+
+  Function_type* new_fntype = Type::make_function_type(NULL, new_params,
+						       new_results,
+						       loc);
+
+  std::string name = no->name() + "$descriptorfn";
+  Named_object* dno = gogo->start_function(name, new_fntype, false, loc);
+  dno->func_value()->is_descriptor_wrapper_ = true;
+
+  gogo->start_block(loc);
+
+  Expression* fn = Expression::make_func_reference(no, NULL, loc);
+
+  // Call the wrapper function, passing all of the arguments except
+  // for the last one (the last argument is the ignored closure).
+  Expression_list* args;
+  if (orig_params == NULL || orig_params->empty())
+    args = NULL;
+  else
+    {
+      args = new Expression_list();
+      for (Typed_identifier_list::const_iterator p = new_params->begin();
+	   p + 1 != new_params->end();
+	   ++p)
+	{
+	  Named_object* p_no = gogo->lookup(p->name(), NULL);
+	  go_assert(p_no != NULL
+		    && p_no->is_variable()
+		    && p_no->var_value()->is_parameter());
+	  args->push_back(Expression::make_var_reference(p_no, loc));
+	}
+    }
+
+  Call_expression* call = Expression::make_call(fn, args,
+						orig_fntype->is_varargs(),
+						loc);
+  call->set_varargs_are_lowered();
+
+  Statement* s;
+  if (orig_results == NULL || orig_results->empty())
+    s = Statement::make_statement(call, true);
+  else
+    {
+      Expression_list* vals = new Expression_list();
+      size_t rc = orig_results->size();
+      if (rc == 1)
+	vals->push_back(call);
+      else
+	{
+	  for (size_t i = 0; i < rc; ++i)
+	    vals->push_back(Expression::make_call_result(call, i));
+	}
+      s = Statement::make_return_statement(vals, loc);
+    }
+
+  gogo->add_statement(s);
+  gogo->add_block(gogo->finish_block(loc), loc);
+  gogo->finish_function(loc);
+
+  return dno;
+}
+
+// Return the function descriptor, the value you get when you refer to
+// the function in Go code without calling it.
+
+Expression*
+Function::descriptor(Gogo* gogo, Named_object* no)
+{
+  go_assert(!this->is_method());
+  go_assert(this->closure_var_ == NULL);
+  go_assert(!this->is_descriptor_wrapper_);
+  if (this->descriptor_ == NULL)
+    {
+      Named_object* dno;
+      if (no->package() != NULL
+	  || Linemap::is_predeclared_location(no->location()))
+	dno = NULL;
+      else
+	dno = Function::make_descriptor_wrapper(gogo, no, this->type_);
+      this->descriptor_ = Expression::make_func_descriptor(no, dno);
+    }
+  return this->descriptor_;
+}
+
 // Get a pointer to the variable representing the defer stack for this
 // function, making it if necessary.  The value of the variable is set
 // by the runtime routines to true if the function is returning,
@@ -3940,6 +4117,27 @@ Bindings_snapshot::check_goto_defs(Locat
     }
 }
 
+// Class Function_declaration.
+
+// Return the function descriptor.
+
+Expression*
+Function_declaration::descriptor(Gogo* gogo, Named_object* no)
+{
+  go_assert(!this->fntype_->is_method());
+  if (this->descriptor_ == NULL)
+    {
+      Named_object* dno;
+      if (no->package() != NULL
+	  || Linemap::is_predeclared_location(no->location()))
+	dno = NULL;
+      else
+	dno = Function::make_descriptor_wrapper(gogo, no, this->fntype_);
+      this->descriptor_ = Expression::make_func_descriptor(no, dno);
+    }
+  return this->descriptor_;
+}
+
 // Class Variable.
 
 Variable::Variable(Type* type, Expression* init, bool is_global,
@@ -4755,6 +4953,12 @@ void
 Named_object::set_function_value(Function* function)
 {
   go_assert(this->classification_ == NAMED_OBJECT_FUNC_DECLARATION);
+  if (this->func_declaration_value()->has_descriptor())
+    {
+      Expression* descriptor =
+	this->func_declaration_value()->descriptor(NULL, NULL);
+      function->set_descriptor(descriptor);
+    }
   this->classification_ = NAMED_OBJECT_FUNC;
   // FIXME: We should free the old value.
   this->u_.func_value = function;
Index: gcc/go/gofrontend/runtime.def
===================================================================
--- gcc/go/gofrontend/runtime.def	(revision 199461)
+++ gcc/go/gofrontend/runtime.def	(working copy)
@@ -224,11 +224,6 @@ DEF_GO_RUNTIME(NEW, "__go_new", P1(UINTP
 DEF_GO_RUNTIME(NEW_NOPOINTERS, "__go_new_nopointers", P1(UINTPTR), R1(POINTER))
 
 
-// Allocate a trampoline for a function literal.
-DEF_GO_RUNTIME(ALLOCATE_GO_TRAMPOLINE, "__go_allocate_trampoline",
-	       P2(UINTPTR, POINTER), R1(POINTER))
-
-
 // Start a new goroutine.
 DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0())
 
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 200098)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -1298,8 +1298,8 @@ Type::make_type_descriptor_var(Gogo* gog
   // converting INITIALIZER.
 
   this->type_descriptor_var_ =
-    gogo->backend()->immutable_struct(var_name, is_common, initializer_btype,
-				      loc);
+    gogo->backend()->immutable_struct(var_name, false, is_common,
+				      initializer_btype, loc);
   if (phash != NULL)
     *phash = this->type_descriptor_var_;
 
@@ -1308,7 +1308,7 @@ Type::make_type_descriptor_var(Gogo* gog
   Bexpression* binitializer = tree_to_expr(initializer->get_tree(&context));
 
   gogo->backend()->immutable_struct_set_init(this->type_descriptor_var_,
-					     var_name, is_common,
+					     var_name, false, is_common,
 					     initializer_btype, loc,
 					     binitializer);
 }
@@ -1528,26 +1528,6 @@ Type::make_type_descriptor_type()
 
       // The type descriptor type.
 
-      Typed_identifier_list* params = new Typed_identifier_list();
-      params->push_back(Typed_identifier("key", unsafe_pointer_type, bloc));
-      params->push_back(Typed_identifier("key_size", 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("key1", unsafe_pointer_type, bloc));
-      params->push_back(Typed_identifier("key2", unsafe_pointer_type, bloc));
-      params->push_back(Typed_identifier("key_size", 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(10,
 				       "Kind", uint8_type,
@@ -1555,8 +1535,8 @@ Type::make_type_descriptor_type()
 				       "fieldAlign", uint8_type,
 				       "size", uintptr_type,
 				       "hash", uint32_type,
-				       "hashfn", hashfn_type,
-				       "equalfn", equalfn_type,
+				       "hashfn", uintptr_type,
+				       "equalfn", uintptr_type,
 				       "string", pointer_string_type,
 				       "", pointer_uncommon_type,
 				       "ptrToThis",
@@ -1946,8 +1926,8 @@ Type::type_descriptor_constructor(Gogo*
   Named_object* equal_fn;
   this->type_functions(gogo, name, hash_fntype, equal_fntype, &hash_fn,
 		       &equal_fn);
-  vals->push_back(Expression::make_func_reference(hash_fn, NULL, bloc));
-  vals->push_back(Expression::make_func_reference(equal_fn, NULL, bloc));
+  vals->push_back(Expression::make_func_code_reference(hash_fn, bloc));
+  vals->push_back(Expression::make_func_code_reference(equal_fn, bloc));
 
   ++p;
   go_assert(p->is_field_name("string"));
@@ -2207,7 +2187,7 @@ Type::method_constructor(Gogo*, Type* me
 
   ++p;
   go_assert(p->is_field_name("tfn"));
-  vals->push_back(Expression::make_func_reference(no, NULL, bloc));
+  vals->push_back(Expression::make_func_code_reference(no, bloc));
 
   ++p;
   go_assert(p == fields->end());
@@ -3407,6 +3387,18 @@ Function_type::do_hash_for_method(Gogo*
 Btype*
 Function_type::do_get_backend(Gogo* gogo)
 {
+  // When we do anything with a function value other than call it, it
+  // is represented as a pointer to a struct whose first field is the
+  // actual function.  So that is what we return as the type of a Go
+  // function.  The function stored in the first field always that
+  // takes one additional trailing argument: the closure pointer.  For
+  // a top-level function, this additional argument will only be
+  // passed when invoking the function indirectly, via the struct.
+
+  Location loc = this->location();
+  Btype* struct_type = gogo->backend()->placeholder_struct_type("", loc);
+  Btype* ptr_struct_type = gogo->backend()->pointer_type(struct_type);
+
   Backend::Btyped_identifier breceiver;
   if (this->receiver_ != NULL)
     {
@@ -3422,9 +3414,15 @@ Function_type::do_get_backend(Gogo* gogo
     }
 
   std::vector<Backend::Btyped_identifier> bparameters;
-  if (this->parameters_ != NULL)
+  size_t last;
+  if (this->parameters_ == NULL)
+    {
+      bparameters.resize(1);
+      last = 0;
+    }
+  else
     {
-      bparameters.resize(this->parameters_->size());
+      bparameters.resize(this->parameters_->size() + 1);
       size_t i = 0;
       for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
 	   p != this->parameters_->end();
@@ -3434,8 +3432,12 @@ Function_type::do_get_backend(Gogo* gogo
 	  bparameters[i].btype = p->type()->get_backend(gogo);
 	  bparameters[i].location = p->location();
 	}
-      go_assert(i == bparameters.size());
+      last = i;
     }
+  go_assert(last + 1 == bparameters.size());
+  bparameters[last].name = "$closure";
+  bparameters[last].btype = ptr_struct_type;
+  bparameters[last].location = loc;
 
   std::vector<Backend::Btyped_identifier> bresults;
   if (this->results_ != NULL)
@@ -3453,8 +3455,15 @@ Function_type::do_get_backend(Gogo* gogo
       go_assert(i == bresults.size());
     }
 
-  return gogo->backend()->function_type(breceiver, bparameters, bresults,
-					this->location());
+  Btype* fntype = gogo->backend()->function_type(breceiver, bparameters,
+						 bresults, loc);
+  std::vector<Backend::Btyped_identifier> fields(1);
+  fields[0].name = "code";
+  fields[0].btype = fntype;
+  fields[0].location = loc;
+  if (!gogo->backend()->set_placeholder_struct_type(struct_type, fields))
+    return gogo->backend()->error_type();
+  return ptr_struct_type;
 }
 
 // The type of a function type descriptor.
@@ -6228,7 +6237,8 @@ Map_type::map_descriptor(Gogo* gogo)
 
   std::string mangled_name = "__go_map_" + this->mangled_name(gogo);
   Btype* map_descriptor_btype = map_descriptor_type->get_backend(gogo);
-  Bvariable* bvar = gogo->backend()->immutable_struct(mangled_name, true,
+  Bvariable* bvar = gogo->backend()->immutable_struct(mangled_name, false,
+						      true,
 						      map_descriptor_btype,
 						      bloc);
 
@@ -6236,7 +6246,7 @@ Map_type::map_descriptor(Gogo* gogo)
   context.set_is_const();
   Bexpression* binitializer = tree_to_expr(initializer->get_tree(&context));
 
-  gogo->backend()->immutable_struct_set_init(bvar, mangled_name, true,
+  gogo->backend()->immutable_struct_set_init(bvar, mangled_name, false, true,
 					     map_descriptor_btype, bloc,
 					     binitializer);
 
Index: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 199461)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -523,6 +523,14 @@ class Type
   static Type*
   make_forward_declaration(Named_object*);
 
+  // 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);
+
   // Traverse a type.
   static int
   traverse(Type*, Traverse*);
@@ -1035,14 +1043,6 @@ class Type
   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
   append_reflection(const Type* type, Gogo* gogo, std::string* ret) const
@@ -1796,7 +1796,7 @@ class Function_type : public Type
   int
   do_traverse(Traverse*);
 
-  // A trampoline function has a pointer which matters for GC.
+  // A function descriptor may be allocated on the heap.
   bool
   do_has_pointer() const
   { return true; }
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 200098)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -1242,6 +1242,24 @@ Func_expression::do_traverse(Traverse* t
 	  : Expression::traverse(&this->closure_, traverse));
 }
 
+// Lower a function reference.  If this reference is not called
+// directly, make sure there is a function descriptor.
+
+Expression*
+Func_expression::do_lower(Gogo* gogo, Named_object*, Statement_inserter*, int)
+{
+  // Make sure that the descriptor exists.  FIXME: If the function is
+  // only ever called, and is never referenced otherwise, then we
+  // don't need the descriptor.  We could do that with another pass
+  // over the tree.
+  if (this->closure_ == NULL
+      && this->function_->is_function()
+      && !this->function_->func_value()->is_method())
+    this->function_->func_value()->descriptor(gogo, this->function_);
+
+  return this;
+}
+
 // Return the type of a function expression.
 
 Type*
@@ -1255,17 +1273,16 @@ Func_expression::do_type()
     go_unreachable();
 }
 
-// Get the tree for a function expression without evaluating the
-// closure.
+// Get the tree for the code of a function expression.
 
 tree
-Func_expression::get_tree_without_closure(Gogo* gogo)
+Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
 {
   Function_type* fntype;
-  if (this->function_->is_function())
-    fntype = this->function_->func_value()->type();
-  else if (this->function_->is_function_declaration())
-    fntype = this->function_->func_declaration_value()->type();
+  if (no->is_function())
+    fntype = no->func_value()->type();
+  else if (no->is_function_declaration())
+    fntype = no->func_declaration_value()->type();
   else
     go_unreachable();
 
@@ -1273,14 +1290,12 @@ Func_expression::get_tree_without_closur
   // can't take their address.
   if (fntype->is_builtin())
     {
-      error_at(this->location(),
+      error_at(loc,
 	       "invalid use of special builtin function %qs; must be called",
-	       this->function_->name().c_str());
+	       no->message_name().c_str());
       return error_mark_node;
     }
 
-  Named_object* no = this->function_;
-
   tree id = no->get_id(gogo);
   if (id == error_mark_node)
     return error_mark_node;
@@ -1296,46 +1311,55 @@ Func_expression::get_tree_without_closur
   if (fndecl == error_mark_node)
     return error_mark_node;
 
-  return build_fold_addr_expr_loc(this->location().gcc_location(), fndecl);
+  return build_fold_addr_expr_loc(loc.gcc_location(), fndecl);
 }
 
 // Get the tree for a function expression.  This is used when we take
-// the address of a function rather than simply calling it.  If the
-// function has a closure, we must use a trampoline.
+// the address of a function rather than simply calling it.  A func
+// value is represented as a pointer to a block of memory.  The first
+// word of that memory is a pointer to the function code.  The
+// remaining parts of that memory are the addresses of variables that
+// the function closes over.
 
 tree
 Func_expression::do_get_tree(Translate_context* context)
 {
-  Gogo* gogo = context->gogo();
-
-  tree fnaddr = this->get_tree_without_closure(gogo);
-  if (fnaddr == error_mark_node)
-    return error_mark_node;
-
-  go_assert(TREE_CODE(fnaddr) == ADDR_EXPR
-	     && TREE_CODE(TREE_OPERAND(fnaddr, 0)) == FUNCTION_DECL);
-  TREE_ADDRESSABLE(TREE_OPERAND(fnaddr, 0)) = 1;
-
-  // If there is no closure, that is all have to do.
+  // If there is no closure, just use the function descriptor.
   if (this->closure_ == NULL)
-    return fnaddr;
-
-  go_assert(this->function_->func_value()->enclosing() != NULL);
+    {
+      Gogo* gogo = context->gogo();
+      Named_object* no = this->function_;
+      Expression* descriptor;
+      if (no->is_function())
+	descriptor = no->func_value()->descriptor(gogo, no);
+      else if (no->is_function_declaration())
+	{
+	  if (no->func_declaration_value()->type()->is_builtin())
+	    {
+	      error_at(this->location(),
+		       ("invalid use of special builtin function %qs; "
+			"must be called"),
+		       no->message_name().c_str());
+	      return error_mark_node;
+	    }
+	  descriptor = no->func_declaration_value()->descriptor(gogo, no);
+	}
+      else
+	go_unreachable();
 
-  // Get the value of the closure.  This will be a pointer to space
-  // allocated on the heap.
-  tree closure_tree = this->closure_->get_tree(context);
-  if (closure_tree == error_mark_node)
-    return error_mark_node;
-  go_assert(POINTER_TYPE_P(TREE_TYPE(closure_tree)));
+      tree dtree = descriptor->get_tree(context);
+      if (dtree == error_mark_node)
+	return error_mark_node;
+      return build_fold_addr_expr_loc(this->location().gcc_location(), dtree);
+    }
 
-  // Now we need to build some code on the heap.  This code will load
-  // the static chain pointer with the closure and then jump to the
-  // body of the function.  The normal gcc approach is to build the
-  // code on the stack.  Unfortunately we can not do that, as Go
-  // permits us to return the function pointer.
+  go_assert(this->function_->func_value()->enclosing() != NULL);
 
-  return gogo->make_trampoline(fnaddr, closure_tree, this->location());
+  // If there is a closure, then the closure is itself the function
+  // expression.  It is a pointer to a struct whose first field points
+  // to the function code and whose remaining fields are the addresses
+  // of the closed-over variables.
+  return this->closure_->get_tree(context);
 }
 
 // Ast dump for function.
@@ -1361,6 +1385,215 @@ Expression::make_func_reference(Named_ob
   return new Func_expression(function, closure, location);
 }
 
+// A function descriptor.  A function descriptor is a struct with a
+// single field pointing to the function code.  This is used for
+// functions without closures.
+
+class Func_descriptor_expression : public Expression
+{
+ public:
+  Func_descriptor_expression(Named_object* fn, Named_object* dfn)
+    : Expression(EXPRESSION_FUNC_DESCRIPTOR, fn->location()),
+      fn_(fn), dfn_(dfn), dvar_(NULL)
+  {
+    go_assert(!fn->is_function() || !fn->func_value()->needs_closure());
+  }
+
+  // Make the function descriptor type, so that it can be converted.
+  static void
+  make_func_descriptor_type();
+
+ protected:
+  int
+  do_traverse(Traverse*)
+  { return TRAVERSE_CONTINUE; }
+
+  Type*
+  do_type();
+
+  void
+  do_determine_type(const Type_context*)
+  { }
+
+  Expression*
+  do_copy()
+  { return Expression::make_func_descriptor(this->fn_, this->dfn_); }
+
+  bool
+  do_is_addressable() const
+  { return true; }
+
+  tree
+  do_get_tree(Translate_context*);
+
+  void
+  do_dump_expression(Ast_dump_context* context) const
+  { context->ostream() << "[descriptor " << this->fn_->name() << "]"; }
+
+ private:
+  // The type of all function descriptors.
+  static Type* descriptor_type;
+
+  // The function for which this is the descriptor.
+  Named_object* fn_;
+  // The descriptor function.
+  Named_object* dfn_;
+  // The descriptor variable.
+  Bvariable* dvar_;
+};
+
+// All function descriptors have the same type.
+
+Type* Func_descriptor_expression::descriptor_type;
+
+void
+Func_descriptor_expression::make_func_descriptor_type()
+{
+  if (Func_descriptor_expression::descriptor_type != NULL)
+    return;
+  Type* uintptr_type = Type::lookup_integer_type("uintptr");
+  Type* struct_type = Type::make_builtin_struct_type(1, "code", uintptr_type);
+  Func_descriptor_expression::descriptor_type =
+    Type::make_builtin_named_type("functionDescriptor", struct_type);
+}
+
+Type*
+Func_descriptor_expression::do_type()
+{
+  Func_descriptor_expression::make_func_descriptor_type();
+  return Func_descriptor_expression::descriptor_type;
+}
+
+// The tree for a function descriptor.
+
+tree
+Func_descriptor_expression::do_get_tree(Translate_context* context)
+{
+  if (this->dvar_ != NULL)
+    return var_to_tree(this->dvar_);
+
+  Gogo* gogo = context->gogo();
+  Named_object* no = this->fn_;
+  Location loc = no->location();
+
+  std::string var_name;
+  if (no->package() == NULL)
+    var_name = gogo->pkgpath_symbol();
+  else
+    var_name = no->package()->pkgpath_symbol();
+  var_name.push_back('.');
+  var_name.append(Gogo::unpack_hidden_name(no->name()));
+  var_name.append("$descriptor");
+
+  Btype* btype = this->type()->get_backend(gogo);
+
+  Bvariable* bvar;
+  if (no->package() != NULL
+      || Linemap::is_predeclared_location(no->location()))
+    {
+      bvar = context->backend()->immutable_struct_reference(var_name, btype,
+							    loc);
+      go_assert(this->dfn_ == NULL);
+    }
+  else
+    {
+      Location bloc = Linemap::predeclared_location();
+      bool is_hidden = ((no->is_function()
+			 && no->func_value()->enclosing() != NULL)
+			|| Gogo::is_thunk(no));
+      bvar = context->backend()->immutable_struct(var_name, is_hidden, false,
+						  btype, bloc);
+      Expression_list* vals = new Expression_list();
+      go_assert(this->dfn_ != NULL);
+      vals->push_back(Expression::make_func_code_reference(this->dfn_, bloc));
+      Expression* init =
+	Expression::make_struct_composite_literal(this->type(), vals, bloc);
+      Translate_context bcontext(gogo, NULL, NULL, NULL);
+      bcontext.set_is_const();
+      Bexpression* binit = tree_to_expr(init->get_tree(&bcontext));
+      context->backend()->immutable_struct_set_init(bvar, var_name, is_hidden,
+						    false, btype, bloc, binit);
+    }
+
+  this->dvar_ = bvar;
+  return var_to_tree(bvar);
+}
+
+// Make a function descriptor expression.
+
+Expression*
+Expression::make_func_descriptor(Named_object* fn, Named_object* dfn)
+{
+  return new Func_descriptor_expression(fn, dfn);
+}
+
+// Make the function descriptor type, so that it can be converted.
+
+void
+Expression::make_func_descriptor_type()
+{
+  Func_descriptor_expression::make_func_descriptor_type();
+}
+
+// A reference to just the code of a function.
+
+class Func_code_reference_expression : public Expression
+{
+ public:
+  Func_code_reference_expression(Named_object* function, Location location)
+    : Expression(EXPRESSION_FUNC_CODE_REFERENCE, location),
+      function_(function)
+  { }
+
+ protected:
+  int
+  do_traverse(Traverse*)
+  { return TRAVERSE_CONTINUE; }
+
+  Type*
+  do_type()
+  { return Type::make_pointer_type(Type::make_void_type()); }
+
+  void
+  do_determine_type(const Type_context*)
+  { }
+
+  Expression*
+  do_copy()
+  {
+    return Expression::make_func_code_reference(this->function_,
+						this->location());
+  }
+
+  tree
+  do_get_tree(Translate_context*);
+
+  void
+  do_dump_expression(Ast_dump_context* context) const
+  { context->ostream() << "[raw " << this->function_->name() << "]" ; }
+
+ private:
+  // The function.
+  Named_object* function_;
+};
+
+// Get the tree for a reference to function code.
+
+tree
+Func_code_reference_expression::do_get_tree(Translate_context* context)
+{
+  return Func_expression::get_code_pointer(context->gogo(), this->function_,
+					   this->location());
+}
+
+// Make a reference to the code of a function.
+
+Expression*
+Expression::make_func_code_reference(Named_object* function, Location location)
+{
+  return new Func_code_reference_expression(function, location);
+}
+
 // Class Unknown_expression.
 
 // Return the name of an unknown expression.
@@ -8521,6 +8754,74 @@ Builtin_call_expression::do_export(Expor
 
 // Class Call_expression.
 
+// A Go function can be viewed in a couple of different ways.  The
+// code of a Go function becomes a backend function with parameters
+// whose types are simply the backend representation of the Go types.
+// If there are multiple results, they are returned as a backend
+// struct.
+
+// However, when Go code refers to a function other than simply
+// calling it, the backend type of that function is actually a struct.
+// The first field of the struct points to the Go function code
+// (sometimes a wrapper as described below).  The remaining fields
+// hold addresses of closed-over variables.  This struct is called a
+// closure.
+
+// There are a few cases to consider.
+
+// A direct function call of a known function in package scope.  In
+// this case there are no closed-over variables, and we know the name
+// of the function code.  We can simply produce a backend call to the
+// function directly, and not worry about the closure.
+
+// A direct function call of a known function literal.  In this case
+// we know the function code and we know the closure.  We generate the
+// function code such that it expects an additional final argument of
+// the closure type.  We pass the closure as the last argument, after
+// the other arguments.
+
+// An indirect function call.  In this case we have a closure.  We
+// load the pointer to the function code from the first field of the
+// closure.  We pass the address of the closure as the last argument.
+
+// A call to a method of an interface.  Type methods are always at
+// package scope, so we call the function directly, and don't worry
+// about the closure.
+
+// This means that for a function at package scope we have two cases.
+// One is the direct call, which has no closure.  The other is the
+// indirect call, which does have a closure.  We can't simply ignore
+// the closure, even though it is the last argument, because that will
+// fail on targets where the function pops its arguments.  So when
+// generating a closure for a package-scope function we set the
+// function code pointer in the closure to point to a wrapper
+// function.  This wrapper function accepts a final argument that
+// points to the closure, ignores it, and calls the real function as a
+// direct function call.  This wrapper will normally be efficient, and
+// can often simply be a tail call to the real function.
+
+// We don't use GCC's static chain pointer because 1) we don't need
+// it; 2) GCC only permits using a static chain to call a known
+// function, so we can't use it for an indirect call anyhow.  Since we
+// can't use it for an indirect call, we may as well not worry about
+// using it for a direct call either.
+
+// We pass the closure last rather than first because it means that
+// the function wrapper we put into a closure for a package-scope
+// function can normally just be a tail call to the real function.
+
+// For method expressions we generate a wrapper that loads the
+// receiver from the closure and then calls the method.  This
+// unfortunately forces reshuffling the arguments, since there is a
+// new first argument, but we can't avoid reshuffling either for
+// method expressions or for indirect calls of package-scope
+// functions, and since the latter are more common we reshuffle for
+// method expressions.
+
+// Note that the Go code retains the Go types.  The extra final
+// argument only appears when we convert to the backend
+// representation.
+
 // Traversal.
 
 int
@@ -9129,11 +9430,21 @@ Call_expression::do_get_tree(Translate_c
   const bool has_closure = func != NULL && func->closure() != NULL;
   const bool is_interface_method = interface_method != NULL;
 
+  int closure_arg;
+  if (has_closure)
+    closure_arg = 1;
+  else if (func != NULL)
+    closure_arg = 0;
+  else if (is_interface_method)
+    closure_arg = 0;
+  else
+    closure_arg = 1;
+
   int nargs;
   tree* args;
   if (this->args_ == NULL || this->args_->empty())
     {
-      nargs = is_interface_method ? 1 : 0;
+      nargs = (is_interface_method ? 1 : 0) + closure_arg;
       args = nargs == 0 ? NULL : new tree[nargs];
     }
   else if (fntype->parameters() == NULL || fntype->parameters()->empty())
@@ -9142,7 +9453,7 @@ Call_expression::do_get_tree(Translate_c
       go_assert(!is_interface_method
 		&& fntype->is_method()
 		&& this->args_->size() == 1);
-      nargs = 1;
+      nargs = 1 + closure_arg;
       args = new tree[nargs];
       args[0] = this->args_->front()->get_tree(context);
     }
@@ -9153,6 +9464,7 @@ Call_expression::do_get_tree(Translate_c
       nargs = this->args_->size();
       int i = is_interface_method ? 1 : 0;
       nargs += i;
+      nargs += closure_arg;
       args = new tree[nargs];
 
       Typed_identifier_list::const_iterator pp = params->begin();
@@ -9173,36 +9485,71 @@ Call_expression::do_get_tree(Translate_c
 						       arg_val,
 						       location);
 	  if (args[i] == error_mark_node)
-	    {
-	      delete[] args;
-	      return error_mark_node;
-	    }
+	    return error_mark_node;
 	}
       go_assert(pp == params->end());
-      go_assert(i == nargs);
+      go_assert(i + closure_arg == nargs);
     }
 
-  tree rettype = TREE_TYPE(TREE_TYPE(type_to_tree(fntype->get_backend(gogo))));
+  tree fntype_tree = type_to_tree(fntype->get_backend(gogo));
+  if (fntype_tree == error_mark_node)
+    return error_mark_node;
+  go_assert(POINTER_TYPE_P(fntype_tree));
+  if (TREE_TYPE(fntype_tree) == error_mark_node)
+    return error_mark_node;
+  go_assert(TREE_CODE(TREE_TYPE(fntype_tree)) == RECORD_TYPE);
+  tree fnfield_type = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(fntype_tree)));
+  if (fnfield_type == error_mark_node)
+    return error_mark_node;
+  go_assert(FUNCTION_POINTER_TYPE_P(fnfield_type));
+  tree rettype = TREE_TYPE(TREE_TYPE(fnfield_type));
   if (rettype == error_mark_node)
-    {
-      delete[] args;
-      return error_mark_node;
-    }
+    return error_mark_node;
 
   tree fn;
-  if (has_closure)
-    fn = func->get_tree_without_closure(gogo);
+  if (func != NULL)
+    {
+      Named_object* no = func->named_object();
+      go_assert(!no->is_function()
+		|| !no->func_value()->is_descriptor_wrapper());
+      fn = Func_expression::get_code_pointer(gogo, no, location);
+      if (has_closure)
+	{
+	  go_assert(closure_arg == 1 && nargs > 0);
+	  args[nargs - 1] = func->closure()->get_tree(context);
+	}
+    }
   else if (!is_interface_method)
-    fn = this->fn_->get_tree(context);
-  else
-    fn = this->interface_method_function(context, interface_method, &args[0]);
-
-  if (fn == error_mark_node || TREE_TYPE(fn) == error_mark_node)
     {
-      delete[] args;
-      return error_mark_node;
+      tree closure_tree = this->fn_->get_tree(context);
+      if (closure_tree == error_mark_node)
+	return error_mark_node;
+      tree fnc = fold_convert_loc(location.gcc_location(), fntype_tree,
+				  closure_tree);
+      go_assert(POINTER_TYPE_P(TREE_TYPE(fnc))
+		&& (TREE_CODE(TREE_TYPE(TREE_TYPE(fnc)))
+		    == RECORD_TYPE));
+      tree field = TYPE_FIELDS(TREE_TYPE(TREE_TYPE(fnc)));
+      fn = fold_build3_loc(location.gcc_location(), COMPONENT_REF,
+			   TREE_TYPE(field),
+			   build_fold_indirect_ref_loc(location.gcc_location(),
+						       fnc),
+			   field, NULL_TREE);
+      go_assert(closure_arg == 1 && nargs > 0);
+      args[nargs - 1] = closure_tree;
+    }      
+  else
+    {
+      fn = this->interface_method_function(context, interface_method,
+					   &args[0]);
+      if (fn == error_mark_node)
+	return error_mark_node;
+      go_assert(closure_arg == 0);
     }
 
+  if (fn == error_mark_node || TREE_TYPE(fn) == error_mark_node)
+    return error_mark_node;
+
   tree fndecl = fn;
   if (TREE_CODE(fndecl) == ADDR_EXPR)
     fndecl = TREE_OPERAND(fndecl, 0);
@@ -9210,12 +9557,7 @@ Call_expression::do_get_tree(Translate_c
   // Add a type cast in case the type of the function is a recursive
   // type which refers to itself.
   if (!DECL_P(fndecl) || !DECL_IS_BUILTIN(fndecl))
-    {
-      tree fnt = type_to_tree(fntype->get_backend(gogo));
-      if (fnt == error_mark_node)
-	return error_mark_node;
-      fn = fold_convert_loc(location.gcc_location(), fnt, fn);
-    }
+    fn = fold_convert_loc(location.gcc_location(), fnfield_type, fn);
 
   // This is to support builtin math functions when using 80387 math.
   tree excess_type = NULL_TREE;
@@ -9259,13 +9601,6 @@ Call_expression::do_get_tree(Translate_c
 
   SET_EXPR_LOCATION(ret, location.gcc_location());
 
-  if (has_closure)
-    {
-      tree closure_tree = func->closure()->get_tree(context);
-      if (closure_tree != error_mark_node)
-	CALL_EXPR_STATIC_CHAIN(ret) = closure_tree;
-    }
-
   // If this is a recursive function type which returns itself, as in
   //   type F func() F
   // we have used ptr_type_node for the return type.  Add a cast here
@@ -9286,24 +9621,6 @@ Call_expression::do_get_tree(Translate_c
   if (this->results_ != NULL)
     ret = this->set_results(context, ret);
 
-  // We can't unwind the stack past a call to nil, so we need to
-  // insert an explicit check so that the panic can be recovered.
-  if (func == NULL)
-    {
-      tree compare = fold_build2_loc(location.gcc_location(), EQ_EXPR,
-				     boolean_type_node, fn,
-				     fold_convert_loc(location.gcc_location(),
-						      TREE_TYPE(fn),
-						      null_pointer_node));
-      tree crash = build3_loc(location.gcc_location(), COND_EXPR,
-			      void_type_node, compare,
-			      gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE,
-						  location),
-			      NULL_TREE);
-      ret = fold_build2_loc(location.gcc_location(), COMPOUND_EXPR,
-			    TREE_TYPE(ret), crash, ret);
-    }
-
   this->tree_ = ret;
 
   return ret;
@@ -11126,8 +11443,10 @@ Selector_expression::lower_method_expres
   // as their first argument.  If this is for a pointer type, we can
   // simply reuse the existing function.  We use an internal hack to
   // get the right type.
-
-  if (method != NULL && is_pointer)
+  // FIXME: This optimization is disabled because it doesn't yet work
+  // with function descriptors when the method expression is not
+  // directly called.
+  if (method != NULL && is_pointer && false)
     {
       Named_object* mno = (method->needs_stub_method()
 			   ? method->stub_object()
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 200098)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -67,6 +67,8 @@ class Expression
     EXPRESSION_SET_AND_USE_TEMPORARY,
     EXPRESSION_SINK,
     EXPRESSION_FUNC_REFERENCE,
+    EXPRESSION_FUNC_DESCRIPTOR,
+    EXPRESSION_FUNC_CODE_REFERENCE,
     EXPRESSION_UNKNOWN_REFERENCE,
     EXPRESSION_BOOLEAN,
     EXPRESSION_STRING,
@@ -150,10 +152,25 @@ class Expression
   static Expression*
   make_sink(Location);
 
-  // Make a reference to a function in an expression.
+  // Make a reference to a function in an expression.  This returns a
+  // pointer to the struct holding the address of the function
+  // followed by any closed-over variables.
   static Expression*
   make_func_reference(Named_object*, Expression* closure, Location);
 
+  // Make a function descriptor, an immutable struct with a single
+  // field that points to the function code.  This may only be used
+  // with functions that do not have closures.  FN is the function for
+  // which we are making the descriptor.  DFN is the descriptor
+  // function wrapper.
+  static Expression*
+  make_func_descriptor(Named_object* fn, Named_object* dfn);
+
+  // Make a reference to the code of a function.  This is used to set
+  // descriptor and closure fields.
+  static Expression*
+  make_func_code_reference(Named_object*, Location);
+
   // Make a reference to an unknown name.  In a correct program this
   // will always be lowered to a real const/var/func reference.
   static Unknown_expression*
@@ -523,6 +540,11 @@ class Expression
   bool
   is_local_variable() const;
 
+  // Make the builtin function descriptor type, so that it can be
+  // converted.
+  static void
+  make_func_descriptor_type();
+
   // Traverse an expression.
   static int
   traverse(Expression**, Traverse*);
@@ -1484,7 +1506,7 @@ class Func_expression : public Expressio
   { }
 
   // Return the object associated with the function.
-  const Named_object*
+  Named_object*
   named_object() const
   { return this->function_; }
 
@@ -1494,14 +1516,17 @@ class Func_expression : public Expressio
   closure()
   { return this->closure_; }
 
-  // Return a tree for this function without evaluating the closure.
-  tree
-  get_tree_without_closure(Gogo*);
+  // Return a tree for the code for a function.
+  static tree
+  get_code_pointer(Gogo*, Named_object* function, Location loc);
 
  protected:
   int
   do_traverse(Traverse*);
 
+  Expression*
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
+
   Type*
   do_type();
 
@@ -1532,8 +1557,8 @@ class Func_expression : public Expressio
   // The function itself.
   Named_object* function_;
   // A closure.  This is normally NULL.  For a nested function, it may
-  // be a heap-allocated struct holding pointers to all the variables
-  // referenced by this function and defined in enclosing functions.
+  // be a struct holding pointers to all the variables referenced by
+  // this function and defined in enclosing functions.
   Expression* closure_;
 };
 
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 200047)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -1959,10 +1959,15 @@ Thunk_statement::is_simple(Function_type
 	      && results->begin()->type()->points_to() == NULL)))
     return false;
 
-  // If this calls something which is not a simple function, then we
+  // If this calls something that is not a simple function, then we
   // need a thunk.
   Expression* fn = this->call_->call_expression()->fn();
-  if (fn->interface_field_reference_expression() != NULL)
+  if (fn->func_expression() == NULL)
+    return false;
+
+  // If the function uses a closure, then we need a thunk.  FIXME: We
+  // could accept a zero argument function with a closure.
+  if (fn->func_expression()->closure() != NULL)
     return false;
 
   return true;
@@ -2502,7 +2507,11 @@ Thunk_statement::get_fn_and_arg(Expressi
 
   Call_expression* ce = this->call_->call_expression();
 
-  *pfn = ce->fn();
+  Expression* fn = ce->fn();
+  Func_expression* fe = fn->func_expression();
+  go_assert(fe != NULL);
+  *pfn = Expression::make_func_code_reference(fe->named_object(),
+					      fe->location());
 
   const Expression_list* args = ce->args();
   if (args == NULL || args->empty())
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 199461)
+++ gcc/go/gofrontend/backend.h	(working copy)
@@ -95,7 +95,10 @@ class Backend
 
   // Get a function type.  The receiver, parameter, and results are
   // generated from the types in the Function_type.  The Function_type
-  // is provided so that the names are available.
+  // is provided so that the names are available.  This should return
+  // not the type of a Go function (which is a pointer to a struct)
+  // but the type of a C function pointer (which will be used as the
+  // type of the first field of the struct).
   virtual Btype*
   function_type(const Btyped_identifier& receiver,
 		const std::vector<Btyped_identifier>& parameters,
@@ -388,18 +391,22 @@ class Backend
 		     Bstatement** pstatement) = 0;
 
   // Create a named immutable initialized data structure.  This is
-  // used for type descriptors and map descriptors.  This returns a
-  // Bvariable because it corresponds to an initialized const global
-  // variable in C.
+  // used for type descriptors, map descriptors, and function
+  // descriptors.  This returns a Bvariable because it corresponds to
+  // an initialized const variable in C.
   //
   // NAME is the name to use for the initialized global variable which
   // this call will create.
   //
+  // IS_HIDDEN will be true if the descriptor should only be visible
+  // within the current object.
+  //
   // IS_COMMON is true if NAME may be defined by several packages, and
   // the linker should merge all such definitions.  If IS_COMMON is
   // false, NAME should be defined in only one file.  In general
   // IS_COMMON will be true for the type descriptor of an unnamed type
-  // or a builtin type.
+  // or a builtin type.  IS_HIDDEN and IS_COMMON will never both be
+  // true.
   //
   // TYPE will be a struct type; the type of the returned expression
   // must be a pointer to this struct type.
@@ -409,20 +416,20 @@ class Backend
   // address.  After calling this the frontend will call
   // immutable_struct_set_init.
   virtual Bvariable*
-  immutable_struct(const std::string& name, bool is_common, Btype* type,
-		   Location) = 0;
+  immutable_struct(const std::string& name, bool is_hidden, bool is_common,
+		   Btype* type, Location) = 0;
 
   // Set the initial value of a variable created by immutable_struct.
-  // The NAME, IS_COMMON, TYPE, and location parameters are the same
-  // ones passed to immutable_struct.  INITIALIZER will be a composite
-  // literal of type TYPE.  It will not contain any function calls or
-  // anything else which can not be put into a read-only data section.
-  // It may contain the address of variables created by
+  // The NAME, IS_HIDDEN, IS_COMMON, TYPE, and location parameters are
+  // the same ones passed to immutable_struct.  INITIALIZER will be a
+  // composite literal of type TYPE.  It will not contain any function
+  // calls or anything else that can not be put into a read-only data
+  // section.  It may contain the address of variables created by
   // immutable_struct.
   virtual void
   immutable_struct_set_init(Bvariable*, const std::string& name,
-			    bool is_common, Btype* type, Location,
-			    Bexpression* initializer) = 0;
+			    bool is_hidden, bool is_common, Btype* type,
+			    Location, Bexpression* initializer) = 0;
 
   // Create a reference to a named immutable initialized data
   // structure defined in some other package.  This will be a
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 199461)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -614,10 +614,6 @@ class Gogo
   receive_from_channel(tree type_tree, tree type_descriptor_tree, tree channel,
 		       Location);
 
-  // Make a trampoline which calls FNADDR passing CLOSURE.
-  tree
-  make_trampoline(tree fnaddr, tree closure, Location);
-
  private:
   // During parsing, we keep a stack of functions.  Each function on
   // the stack is one that we are currently parsing.  For each
@@ -669,10 +665,6 @@ class Gogo
   tree
   ptr_go_string_constant_tree(const std::string&);
 
-  // Return the type of a trampoline.
-  static tree
-  trampoline_type_tree();
-
   // Type used to map import names to packages.
   typedef std::map<std::string, Package*> Imports;
 
@@ -1046,6 +1038,12 @@ class Function
   set_in_unique_section()
   { this->in_unique_section_ = true; }
 
+  // Whether this function was created as a descriptor wrapper for
+  // another function.
+  bool
+  is_descriptor_wrapper() const
+  { return this->is_descriptor_wrapper_; }
+
   // Swap with another function.  Used only for the thunk which calls
   // recover.
   void
@@ -1059,6 +1057,26 @@ class Function
   void
   determine_types();
 
+  // Return an expression for the function descriptor, given the named
+  // object for this function.  This may only be called for functions
+  // without a closure.  This will be an immutable struct with one
+  // field that points to the function's code.
+  Expression*
+  descriptor(Gogo*, Named_object*);
+
+  // Set the descriptor for this function.  This is used when a
+  // function declaration is followed by a function definition.
+  void
+  set_descriptor(Expression* descriptor)
+  {
+    go_assert(this->descriptor_ == NULL);
+    this->descriptor_ = descriptor;
+  }
+
+  // Build a descriptor wrapper function.
+  static Named_object*
+  make_descriptor_wrapper(Gogo*, Named_object*, Function_type*);
+
   // Return the function's decl given an identifier.
   tree
   get_or_make_decl(Gogo*, Named_object*, tree id);
@@ -1137,6 +1155,8 @@ class Function
   Labels labels_;
   // The number of local types defined in this function.
   unsigned int local_type_count_;
+  // The function descriptor, if any.
+  Expression* descriptor_;
   // The function decl.
   tree fndecl_;
   // The defer stack variable.  A pointer to this variable is used to
@@ -1156,6 +1176,9 @@ class Function
   // True if this function should be put in a unique section.  This is
   // turned on for field tracking.
   bool in_unique_section_ : 1;
+  // True if this is a function wrapper created to put in a function
+  // descriptor.
+  bool is_descriptor_wrapper_ : 1;
 };
 
 // A snapshot of the current binding state.
@@ -1198,7 +1221,8 @@ class Function_declaration
 {
  public:
   Function_declaration(Function_type* fntype, Location location)
-    : fntype_(fntype), location_(location), asm_name_(), fndecl_(NULL)
+    : fntype_(fntype), location_(location), asm_name_(), descriptor_(NULL),
+      fndecl_(NULL)
   { }
 
   Function_type*
@@ -1218,10 +1242,27 @@ class Function_declaration
   set_asm_name(const std::string& asm_name)
   { this->asm_name_ = asm_name; }
 
+  // Return an expression for the function descriptor, given the named
+  // object for this function.  This may only be called for functions
+  // without a closure.  This will be an immutable struct with one
+  // field that points to the function's code.
+  Expression*
+  descriptor(Gogo*, Named_object*);
+
+  // Return true if we have created a descriptor for this declaration.
+  bool
+  has_descriptor() const
+  { return this->descriptor_ != NULL; }
+
   // Return a decl for the function given an identifier.
   tree
   get_or_make_decl(Gogo*, Named_object*, tree id);
 
+  // If there is a descriptor, build it into the backend
+  // representation.
+  void
+  build_backend_descriptor(Gogo*);
+
   // Export a function declaration.
   void
   export_func(Export* exp, const std::string& name) const
@@ -1235,6 +1276,8 @@ class Function_declaration
   // The assembler name: this is the name to use in references to the
   // function.  This is normally empty.
   std::string asm_name_;
+  // The function descriptor, if any.
+  Expression* descriptor_;
   // The function decl if needed.
   tree fndecl_;
 };
Index: gcc/go/gofrontend/parse.cc
===================================================================
--- gcc/go/gofrontend/parse.cc	(revision 199461)
+++ gcc/go/gofrontend/parse.cc	(working copy)
@@ -2627,7 +2627,11 @@ Parse::enclosing_var_reference(Named_obj
   Named_object* this_function = this->gogo_->current_function();
   Named_object* closure = this_function->func_value()->closure_var();
 
-  Enclosing_var ev(var, in_function, this->enclosing_vars_.size());
+  // The last argument to the Enclosing_var constructor is the index
+  // of this variable in the closure.  We add 1 to the current number
+  // of enclosed variables, because the first field in the closure
+  // points to the function code.
+  Enclosing_var ev(var, in_function, this->enclosing_vars_.size() + 1);
   std::pair<Enclosing_vars::iterator, bool> ins =
     this->enclosing_vars_.insert(ev);
   if (ins.second)
@@ -2882,8 +2886,9 @@ Parse::function_lit()
 // Create a closure for the nested function FUNCTION.  This is based
 // on ENCLOSING_VARS, which is a list of all variables defined in
 // enclosing functions and referenced from FUNCTION.  A closure is the
-// address of a struct which contains the addresses of all the
-// referenced variables.  This returns NULL if no closure is required.
+// address of a struct which point to the real function code and
+// contains the addresses of all the referenced variables.  This
+// returns NULL if no closure is required.
 
 Expression*
 Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars,
@@ -2899,16 +2904,25 @@ Parse::create_closure(Named_object* func
   for (Enclosing_vars::const_iterator p = enclosing_vars->begin();
        p != enclosing_vars->end();
        ++p)
-    ev[p->index()] = *p;
+    {
+      // Subtract 1 because index 0 is the function code.
+      ev[p->index() - 1] = *p;
+    }
 
   // Build an initializer for a composite literal of the closure's
   // type.
 
   Named_object* enclosing_function = this->gogo_->current_function();
   Expression_list* initializer = new Expression_list;
+
+  initializer->push_back(Expression::make_func_code_reference(function,
+							      location));
+
   for (size_t i = 0; i < enclosing_var_count; ++i)
     {
-      go_assert(ev[i].index() == i);
+      // Add 1 to i because the first field in the closure is a
+      // pointer to the function code.
+      go_assert(ev[i].index() == i + 1);
       Named_object* var = ev[i].var();
       Expression* ref;
       if (ev[i].in_function() == enclosing_function)
Index: libgo/configure.ac
===================================================================
--- libgo/configure.ac	(revision 199461)
+++ libgo/configure.ac	(working copy)
@@ -11,7 +11,7 @@ AC_INIT(package-unused, version-unused,,
 AC_CONFIG_SRCDIR(Makefile.am)
 AC_CONFIG_HEADER(config.h)
 
-libtool_VERSION=3:1:0
+libtool_VERSION=5:0:0
 AC_SUBST(libtool_VERSION)
 
 AM_ENABLE_MULTILIB(, ..)
Index: libgo/go/runtime/parfor_test.go
===================================================================
--- libgo/go/runtime/parfor_test.go	(revision 199461)
+++ libgo/go/runtime/parfor_test.go	(working copy)
@@ -13,6 +13,8 @@ import (
 	"unsafe"
 )
 
+var gdata []uint64
+
 // Simple serial sanity test for parallelfor.
 func TestParFor(t *testing.T) {
 	const P = 1
@@ -22,7 +24,12 @@ func TestParFor(t *testing.T) {
 		data[i] = i
 	}
 	desc := NewParFor(P)
+	// Avoid making func a closure: parfor cannot invoke them.
+	// Since it doesn't happen in the C code, it's not worth doing
+	// just for the test.
+	gdata = data
 	ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
+		data := gdata
 		data[i] = data[i]*data[i] + 1
 	})
 	ParForDo(desc)
@@ -111,7 +118,9 @@ func TestParForParallel(t *testing.T) {
 	P := GOMAXPROCS(-1)
 	c := make(chan bool, P)
 	desc := NewParFor(uint32(P))
+	gdata = data
 	ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
+		data := gdata
 		data[i] = data[i]*data[i] + 1
 	})
 	for p := 1; p < P; p++ {
Index: libgo/go/runtime/extern.go
===================================================================
--- libgo/go/runtime/extern.go	(revision 199461)
+++ libgo/go/runtime/extern.go	(working copy)
@@ -59,9 +59,6 @@ func (f *Func) FileLine(pc uintptr) (fil
 // implemented in symtab.c
 func funcline_go(*Func, uintptr) (string, int)
 
-// mid returns the current OS thread (m) id.
-func mid() uint32
-
 // SetFinalizer sets the finalizer associated with x to f.
 // When the garbage collector finds an unreachable block
 // with an associated finalizer, it clears the association and runs
Index: libgo/go/reflect/all_test.go
===================================================================
--- libgo/go/reflect/all_test.go	(revision 199461)
+++ libgo/go/reflect/all_test.go	(working copy)
@@ -1891,6 +1891,7 @@ func (*inner) m() {}
 func (*outer) m() {}
 
 func TestNestedMethods(t *testing.T) {
+	t.Skip("fails on gccgo due to function wrappers")
 	typ := TypeOf((*outer)(nil))
 	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() {
 		t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m)
@@ -1915,6 +1916,7 @@ func (i *InnerInt) M() int {
 }
 
 func TestEmbeddedMethods(t *testing.T) {
+	/* This part of the test fails on gccgo due to function wrappers.
 	typ := TypeOf((*OuterInt)(nil))
 	if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() {
 		t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M)
@@ -1923,6 +1925,7 @@ func TestEmbeddedMethods(t *testing.T) {
 			t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
 		}
 	}
+	*/
 
 	i := &InnerInt{3}
 	if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {
Index: libgo/go/reflect/value.go
===================================================================
--- libgo/go/reflect/value.go	(revision 199461)
+++ libgo/go/reflect/value.go	(working copy)
@@ -377,7 +377,7 @@ func (v Value) call(method string, in []
 			if iface.itab == nil {
 				panic(method + " of method on nil interface value")
 			}
-			fn = iface.itab.fun[i]
+			fn = unsafe.Pointer(&iface.itab.fun[i])
 			rcvr = iface.word
 		} else {
 			ut := v.typ.uncommon()
@@ -388,7 +388,7 @@ func (v Value) call(method string, in []
 			if m.pkgPath != nil {
 				panic(method + " of unexported method")
 			}
-			fn = m.tfn
+			fn = unsafe.Pointer(&m.tfn)
 			t = m.mtyp
 			rcvr = v.iword()
 		}
@@ -462,6 +462,10 @@ func (v Value) call(method string, in []
 	if v.flag&flagMethod != 0 {
 		nin++
 	}
+	firstPointer := len(in) > 0 && Kind(t.In(0).(*rtype).kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ)
+	if v.flag&flagMethod == 0 && !firstPointer {
+		nin++
+	}
 	params := make([]unsafe.Pointer, nin)
 	off := 0
 	if v.flag&flagMethod != 0 {
@@ -471,7 +475,6 @@ func (v Value) call(method string, in []
 		params[0] = unsafe.Pointer(p)
 		off = 1
 	}
-	first_pointer := false
 	for i, pv := range in {
 		pv.mustBeExported()
 		targ := t.In(i).(*rtype)
@@ -483,14 +486,17 @@ func (v Value) call(method string, in []
 		} else {
 			params[off] = pv.val
 		}
-		if i == 0 && Kind(targ.kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ) {
+		if i == 0 && firstPointer {
 			p := new(unsafe.Pointer)
 			*p = params[off]
 			params[off] = unsafe.Pointer(p)
-			first_pointer = true
 		}
 		off++
 	}
+	if v.flag&flagMethod == 0 && !firstPointer {
+		// Closure argument.
+		params[off] = unsafe.Pointer(&fn)
+	}
 
 	ret := make([]Value, nout)
 	results := make([]unsafe.Pointer, nout)
@@ -509,7 +515,7 @@ func (v Value) call(method string, in []
 		pr = &results[0]
 	}
 
-	call(t, fn, v.flag&flagMethod != 0, first_pointer, pp, pr)
+	call(t, fn, v.flag&flagMethod != 0, firstPointer, pp, pr)
 
 	return ret
 }
@@ -1209,18 +1215,35 @@ func (v Value) OverflowUint(x uint64) bo
 // code using reflect cannot obtain unsafe.Pointers
 // without importing the unsafe package explicitly.
 // It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
+//
+// If v's Kind is Func, the returned pointer is an underlying
+// code pointer, but not necessarily enough to identify a
+// single function uniquely. The only guarantee is that the
+// result is zero if and only if v is a nil func Value.
 func (v Value) Pointer() uintptr {
 	k := v.kind()
 	switch k {
-	case Chan, Func, Map, Ptr, UnsafePointer:
-		if k == Func && v.flag&flagMethod != 0 {
+	case Chan, Map, Ptr, UnsafePointer:
+		p := v.val
+		if v.flag&flagIndir != 0 {
+			p = *(*unsafe.Pointer)(p)
+		}
+		return uintptr(p)
+	case Func:
+		if v.flag&flagMethod != 0 {
 			panic("reflect.Value.Pointer of method Value")
 		}
 		p := v.val
 		if v.flag&flagIndir != 0 {
 			p = *(*unsafe.Pointer)(p)
 		}
+		// Non-nil func value points at data block.
+		// First word of data block is actual code.
+		if p != nil {
+			p = *(*unsafe.Pointer)(p)
+		}
 		return uintptr(p)
+
 	case Slice:
 		return (*SliceHeader)(v.val).Data
 	}
Index: libgo/go/reflect/type.go
===================================================================
--- libgo/go/reflect/type.go	(revision 199461)
+++ libgo/go/reflect/type.go	(working copy)
@@ -243,8 +243,8 @@ type rtype struct {
 	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
+	hashfn  uintptr // hash function code
+	equalfn uintptr // equality function code
 
 	string        *string // string form; unnecessary  but undeniably useful
 	*uncommonType         // (relatively) uncommon fields
@@ -485,7 +485,7 @@ func (t *uncommonType) Method(i int) (m
 	mt := p.typ
 	m.Type = toType(mt)
 	x := new(unsafe.Pointer)
-	*x = p.tfn
+	*x = unsafe.Pointer(&p.tfn)
 	m.Func = Value{mt, unsafe.Pointer(x), fl | flagIndir}
 	m.Index = i
 	return
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 199461)
+++ libgo/Makefile.am	(working copy)
@@ -487,7 +487,6 @@ runtime_files = \
 	runtime/go-strplus.c \
 	runtime/go-strslice.c \
 	runtime/go-traceback.c \
-	runtime/go-trampoline.c \
 	runtime/go-type-complex.c \
 	runtime/go-type-eface.c \
 	runtime/go-type-error.c \
Index: libgo/runtime/malloc.h
===================================================================
--- libgo/runtime/malloc.h	(revision 199461)
+++ libgo/runtime/malloc.h	(working copy)
@@ -485,7 +485,7 @@ void	runtime_helpgc(int32 nproc);
 void	runtime_gchelper(void);
 
 struct __go_func_type;
-bool	runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft);
+bool	runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft);
 void	runtime_walkfintab(void (*fn)(void*), void (*scan)(Obj));
 
 enum
@@ -505,4 +505,3 @@ void	runtime_gc_itab_ptr(Eface*);
 void	runtime_memorydump(void);
 
 void	runtime_time_scan(void (*)(Obj));
-void	runtime_trampoline_scan(void (*)(Obj));
Index: libgo/runtime/time.goc
===================================================================
--- libgo/runtime/time.goc	(revision 199461)
+++ libgo/runtime/time.goc	(working copy)
@@ -49,13 +49,16 @@ static void siftdown(int32);
 
 // Ready the goroutine e.data.
 static void
-ready(int64 now, Eface e)
+ready(int64 now, Eface e, void *closure)
 {
 	USED(now);
+	USED(closure);
 
 	runtime_ready(e.__object);
 }
 
+static FuncVal readyv = {(void(*)(void))ready};
+
 // Put the current goroutine to sleep for ns nanoseconds.
 void
 runtime_tsleep(int64 ns, const char *reason)
@@ -70,7 +73,7 @@ runtime_tsleep(int64 ns, const char *rea
 
 	t.when = runtime_nanotime() + ns;
 	t.period = 0;
-	t.f = ready;
+	t.fv = &readyv;
 	t.arg.__object = g;
 	runtime_lock(&timers);
 	addtimer(&t);
@@ -158,7 +161,7 @@ timerproc(void* dummy __attribute__ ((un
 {
 	int64 delta, now;
 	Timer *t;
-	void (*f)(int64, Eface);
+	void (*f)(int64, Eface, void *);
 	Eface arg;
 
 	for(;;) {
@@ -184,12 +187,12 @@ timerproc(void* dummy __attribute__ ((un
 				siftdown(0);
 				t->i = -1;  // mark as removed
 			}
-			f = t->f;
+			f = (void*)t->fv->fn;
 			arg = t->arg;
 			runtime_unlock(&timers);
 			if(raceenabled)
 				runtime_raceacquire(t);
-			f(now, arg);
+			f(now, arg, &t->fv);
 			runtime_lock(&timers);
 		}
 		if(delta < 0) {
Index: libgo/runtime/runtime.h
===================================================================
--- libgo/runtime/runtime.h	(revision 199461)
+++ libgo/runtime/runtime.h	(working copy)
@@ -57,6 +57,7 @@ typedef	struct	G		G;
 typedef	union	Lock		Lock;
 typedef	struct	M		M;
 typedef	union	Note		Note;
+typedef	struct	FuncVal		FuncVal;
 typedef	struct	SigTab		SigTab;
 typedef	struct	MCache		MCache;
 typedef struct	FixAlloc	FixAlloc;
@@ -147,6 +148,11 @@ struct String
 	const byte*	str;
 	intgo		len;
 };
+struct FuncVal
+{
+	void	(*fn)(void);
+	// variable-size, fn-specific data here
+};
 struct	GCStats
 {
 	// the struct must consist of only uint64's,
@@ -313,7 +319,7 @@ struct	Timer
 	// a well-behaved function and not block.
 	int64	when;
 	int64	period;
-	void	(*f)(int64, Eface);
+	FuncVal	*fv;
 	Eface	arg;
 };
 
@@ -540,7 +546,7 @@ void	runtime_printslice(Slice);
 void	runtime_printcomplex(__complex double);
 
 struct __go_func_type;
-void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
+void reflect_call(const struct __go_func_type *, FuncVal *, _Bool, _Bool,
 		  void **, void **)
   __asm__ (GOSYM_PREFIX "reflect.call");
 
@@ -570,7 +576,7 @@ void	free(void *v);
 #define PREFETCH(p) __builtin_prefetch(p)
 
 struct __go_func_type;
-bool	runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
+bool	runtime_addfinalizer(void*, FuncVal *fn, const struct __go_func_type *);
 #define runtime_getcallersp(p) __builtin_frame_address(1)
 int32	runtime_mcount(void);
 int32	runtime_gcount(void);
Index: libgo/runtime/mgc0.c
===================================================================
--- libgo/runtime/mgc0.c	(revision 199461)
+++ libgo/runtime/mgc0.c	(working copy)
@@ -120,7 +120,7 @@ struct Workbuf
 typedef struct Finalizer Finalizer;
 struct Finalizer
 {
-	void (*fn)(void*);
+	FuncVal *fn;
 	void *arg;
 	const struct __go_func_type *ft;
 };
@@ -1130,7 +1130,6 @@ addroots(void)
 	addroot((Obj){(byte*)&runtime_allm, sizeof runtime_allm, 0});
 	runtime_MProf_Mark(addroot);
 	runtime_time_scan(addroot);
-	runtime_trampoline_scan(addroot);
 
 	// MSpan.types
 	allspans = runtime_mheap.allspans;
@@ -1182,7 +1181,7 @@ addroots(void)
 static bool
 handlespecial(byte *p, uintptr size)
 {
-	void (*fn)(void*);
+	FuncVal *fn;
 	const struct __go_func_type *ft;
 	FinBlock *block;
 	Finalizer *f;
@@ -1731,11 +1730,12 @@ runfinq(void* dummy __attribute__ ((unus
 		for(; fb; fb=next) {
 			next = fb->next;
 			for(i=0; i<(uint32)fb->cnt; i++) {
-				void *params[1];
+				void *params[2];
 
 				f = &fb->fin[i];
 				params[0] = &f->arg;
-				reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
+				params[1] = f;
+				reflect_call(f->ft, f->fn, 0, 0, params, nil);
 				f->fn = nil;
 				f->arg = nil;
 			}
Index: libgo/runtime/parfor.c
===================================================================
--- libgo/runtime/parfor.c	(revision 199461)
+++ libgo/runtime/parfor.c	(working copy)
@@ -83,7 +83,7 @@ void runtime_parforsetup2(ParFor *, uint
 void
 runtime_parforsetup2(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void *body)
 {
-	runtime_parforsetup(desc, nthr, n, ctx, wait, (void(*)(ParFor*, uint32))body);
+	runtime_parforsetup(desc, nthr, n, ctx, wait, *(void(**)(ParFor*, uint32))body);
 }
 
 void
Index: libgo/runtime/go-reflect-call.c
===================================================================
--- libgo/runtime/go-reflect-call.c	(revision 199461)
+++ libgo/runtime/go-reflect-call.c	(working copy)
@@ -302,7 +302,9 @@ go_func_to_cif (const struct __go_func_t
   in_types = ((const struct __go_type_descriptor **)
 	      func->__in.__values);
 
-  num_args = num_params + (is_interface ? 1 : 0);
+  num_args = (num_params
+	      + (is_interface ? 1 : 0)
+	      + (!is_interface && !is_method ? 1 : 0));
   args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
   i = 0;
   off = 0;
@@ -319,6 +321,12 @@ go_func_to_cif (const struct __go_func_t
   for (; i < num_params; ++i)
     args[i + off] = go_type_to_ffi (in_types[i]);
 
+  if (!is_interface && !is_method)
+    {
+      // There is a closure argument, a pointer.
+      args[i + off] = &ffi_type_pointer;
+    }
+
   rettype = go_func_return_ffi (func);
 
   status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
@@ -491,11 +499,24 @@ go_set_results (const struct __go_func_t
 }
 
 /* Call a function.  The type of the function is FUNC_TYPE, and the
-   address is FUNC_ADDR.  PARAMS is an array of parameter addresses.
-   RESULTS is an array of result addresses.  */
+   closure is FUNC_VAL.  PARAMS is an array of parameter addresses.
+   RESULTS is an array of result addresses.
+
+   If IS_INTERFACE is true this is a call to an interface method and
+   the first argument is the receiver, which is always a pointer.
+   This argument, the receiver, is not described in FUNC_TYPE.
+
+   If IS_METHOD is true this is a call to a method expression.  The
+   first argument is the receiver.  It is described in FUNC_TYPE, but
+   regardless of FUNC_TYPE, it is passed as a pointer.
+
+   If neither IS_INTERFACE nor IS_METHOD is true then we are calling a
+   function indirectly, and the caller is responsible for passing a
+   trailing closure argument, a pointer, which is not described in
+   FUNC_TYPE.  */
 
 void
-reflect_call (const struct __go_func_type *func_type, const void *func_addr,
+reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
 	      _Bool is_interface, _Bool is_method, void **params,
 	      void **results)
 {
@@ -507,7 +528,7 @@ reflect_call (const struct __go_func_typ
 
   call_result = (unsigned char *) malloc (go_results_size (func_type));
 
-  ffi_call (&cif, func_addr, call_result, params);
+  ffi_call (&cif, func_val->fn, call_result, params);
 
   /* Some day we may need to free result values if RESULTS is
      NULL.  */
@@ -521,7 +542,7 @@ reflect_call (const struct __go_func_typ
 
 void
 reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
-	      const void *func_addr __attribute__ ((unused)),
+	      FuncVal *func_val __attribute__ ((unused)),
 	      _Bool is_interface __attribute__ ((unused)),
 	      _Bool is_method __attribute__ ((unused)),
 	      void **params __attribute__ ((unused)),
Index: libgo/runtime/mfinal.c
===================================================================
--- libgo/runtime/mfinal.c	(revision 199461)
+++ libgo/runtime/mfinal.c	(working copy)
@@ -11,7 +11,7 @@ enum { debug = 0 };
 typedef struct Fin Fin;
 struct Fin
 {
-	void (*fn)(void*);
+	FuncVal *fn;
 	const struct __go_func_type *ft;
 };
 
@@ -42,7 +42,7 @@ static struct {
 } fintab[TABSZ];
 
 static void
-addfintab(Fintab *t, void *k, void (*fn)(void*), const struct __go_func_type *ft)
+addfintab(Fintab *t, void *k, FuncVal *fn, const struct __go_func_type *ft)
 {
 	int32 i, j;
 
@@ -137,7 +137,7 @@ resizefintab(Fintab *tab)
 }
 
 bool
-runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
+runtime_addfinalizer(void *p, FuncVal *f, const struct __go_func_type *ft)
 {
 	Fintab *tab;
 	byte *base;
@@ -175,7 +175,7 @@ runtime_addfinalizer(void *p, void (*f)(
 // get finalizer; if del, delete finalizer.
 // caller is responsible for updating RefHasFinalizer (special) bit.
 bool
-runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft)
+runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft)
 {
 	Fintab *tab;
 	bool res;

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