diff options
author | Richard Henderson <rth@redhat.com> | 2015-01-16 14:58:53 -0800 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-01-16 22:58:53 +0000 |
commit | 38bf819a5f995ae4621496df2324d68b9e24900f (patch) | |
tree | c90d2bfba44756e26640c50ad1389375693ef832 /gcc/go/go-gcc.cc | |
parent | 21cb351825d45c42e9e5148715a2fd2051cf4ed1 (diff) | |
download | gcc-38bf819a5f995ae4621496df2324d68b9e24900f.zip gcc-38bf819a5f995ae4621496df2324d68b9e24900f.tar.gz gcc-38bf819a5f995ae4621496df2324d68b9e24900f.tar.bz2 |
compiler, reflect, runtime: Use static chain for closures.
Change from using __go_set_closure to passing the closure
value in the static chain field. Uses new backend support for
setting the closure chain in a call from C via
__builtin_call_with_static_chain. Uses new support in libffi
for Go closures.
The old architecture specific support for reflect.MakeFunc is
removed, replaced by the libffi support.
All work done by Richard Henderson.
* go-gcc.cc (Gcc_backend::call_expression): Add chain_expr argument.
(Gcc_backend::static_chain_variable): New method.
From-SVN: r219776
Diffstat (limited to 'gcc/go/go-gcc.cc')
-rw-r--r-- | gcc/go/go-gcc.cc | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index d8b80b6..1ce1ff2 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -322,7 +322,7 @@ class Gcc_backend : public Backend Bexpression* call_expression(Bexpression* fn, const std::vector<Bexpression*>& args, - Location); + Bexpression* static_chain, Location); // Statements. @@ -403,6 +403,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**); @@ -1808,7 +1811,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) @@ -1868,6 +1871,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. @@ -2489,6 +2495,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* |