This is the non-gofrontend patch corresponding to https://codereview.appspot.com/180890043/
Ian, I thought I'd sent it out at the same time as the codereview, but I guess it never went. r~
commit 5a78f18cf8cd2160c62472693222cc72bd4379b6 Author: Richard Henderson <r...@redhat.com> Date: Tue Oct 7 12:28:55 2014 -0700 Use the static chain as the closure parameter from Go This is not a standalone patch; it only touches the Go front end. Further changes are required for the Go runtime. diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 9aad6b0..74be2d6 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -315,7 +315,7 @@ class Gcc_backend : public Backend Bexpression* call_expression(Bexpression* fn, const std::vector<Bexpression*>& args, - Location); + Bexpression* static_chain, Location); // Statements. @@ -396,6 +396,9 @@ class Gcc_backend : public Backend Location); Bvariable* + static_chain_variable(Bfunction*, const std::string&, Btype*, Location); + + Bvariable* temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression*, bool, Location, Bstatement**); @@ -1770,7 +1773,7 @@ Gcc_backend::array_index_expression(Bexpression* array, Bexpression* index, Bexpression* Gcc_backend::call_expression(Bexpression* fn_expr, const std::vector<Bexpression*>& fn_args, - Location location) + Bexpression* chain_expr, Location location) { tree fn = fn_expr->get_tree(); if (fn == error_mark_node || TREE_TYPE(fn) == error_mark_node) @@ -1830,6 +1833,9 @@ Gcc_backend::call_expression(Bexpression* fn_expr, excess_type != NULL_TREE ? excess_type : rettype, fn, nargs, args); + if (chain_expr) + CALL_EXPR_STATIC_CHAIN (ret) = chain_expr->get_tree(); + if (excess_type != NULL_TREE) { // Calling convert here can undo our excess precision change. @@ -2451,6 +2457,40 @@ Gcc_backend::parameter_variable(Bfunction* function, const std::string& name, return new Bvariable(decl); } +// Make a static chain variable. + +Bvariable* +Gcc_backend::static_chain_variable(Bfunction* function, const std::string& name, + Btype* btype, Location location) +{ + tree type_tree = btype->get_tree(); + if (type_tree == error_mark_node) + return this->error_variable(); + tree decl = build_decl(location.gcc_location(), PARM_DECL, + get_identifier_from_string(name), type_tree); + tree fndecl = function->get_tree(); + DECL_CONTEXT(decl) = fndecl; + DECL_ARG_TYPE(decl) = type_tree; + TREE_USED(decl) = 1; + DECL_ARTIFICIAL(decl) = 1; + DECL_IGNORED_P(decl) = 1; + TREE_READONLY(decl) = 1; + + struct function *f = DECL_STRUCT_FUNCTION(fndecl); + if (f == NULL) + { + push_struct_function(fndecl); + pop_cfun(); + f = DECL_STRUCT_FUNCTION(fndecl); + } + gcc_assert(f->static_chain_decl == NULL); + f->static_chain_decl = decl; + DECL_STATIC_CHAIN(fndecl) = 1; + + go_preserve_from_gc(decl); + return new Bvariable(decl); +} + // Make a temporary variable. Bvariable*