diff options
author | Chris Manghane <cmang@google.com> | 2013-10-11 22:17:47 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-10-11 22:17:47 +0000 |
commit | b7d93b468a08d46d5bd7d0ed9e08695eef89ce24 (patch) | |
tree | 99f0ea46175de93ca5f449a6f4e1c690d5ff89c1 /gcc/go | |
parent | ef3cfba23d0f9c518cc71ff053994e77e80f1d1a (diff) | |
download | gcc-b7d93b468a08d46d5bd7d0ed9e08695eef89ce24.zip gcc-b7d93b468a08d46d5bd7d0ed9e08695eef89ce24.tar.gz gcc-b7d93b468a08d46d5bd7d0ed9e08695eef89ce24.tar.bz2 |
compiler: Use backend interface for function code expressions.
* go-gcc.cc (Gcc_backend::function_code_expression): New
function.
From-SVN: r203467
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/ChangeLog | 27 | ||||
-rw-r--r-- | gcc/go/go-gcc.cc | 16 | ||||
-rw-r--r-- | gcc/go/gofrontend/backend.h | 5 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 19 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 4 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo-tree.cc | 92 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 74 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 8 |
8 files changed, 135 insertions, 110 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 6d6217b..4d0dd11 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,26 +1,31 @@ +2013-10-11 Chris Manghane <cmang@google.com> + + * go-gcc.cc (Gcc_backend::function_code_expression): New + function. + 2013-10-10 Chris Manghane <cmang@google.com> - * go-gcc.cc (Backend::error_function): New function. - (Backend::function): New function. - (Backend::make_function): New function. + * go-gcc.cc (Gcc_backend::error_function): New function. + (Gcc_backend::function): New function. + (Gcc_backend::make_function): New function. (function_to_tree): New function. 2013-10-04 Chris Manghane <cmang@google.com> - * go-gcc.cc (Backend::convert_expression): New function. + * go-gcc.cc (Gcc_backend::convert_expression): New function. 2013-10-02 Chris Manghane <cmang@google.com> * go-gcc.cc: Include "real.h" and "realmpfr.h". - (Backend::integer_constant_expression): New function. - (Backend::float_constant_expression): New function. - (Backend::complex_constant_expression): New function. + (Gcc_backend::integer_constant_expression): New function. + (Gcc_backend::float_constant_expression): New function. + (Gcc_backend::complex_constant_expression): New function. 2013-09-30 Chris Manghane <cmang@google.com> - * go-gcc.cc (Backend::error_expression): New function. - (Backend::var_expression): New function. - (Backend::indirect_expression): New function. + * go-gcc.cc (Gcc_backend::error_expression): New function. + (Gcc_backend::var_expression): New function. + (Gcc_backend::indirect_expression): New function. 2013-09-25 Tom Tromey <tromey@redhat.com> @@ -515,7 +520,7 @@ 2011-04-14 Ian Lance Taylor <iant@google.com> - * go-gcc.cc (Backend::error_statement): New function. + * go-gcc.cc (Gcc_backend::error_statement): New function. 2011-04-13 Ian Lance Taylor <iant@google.com> diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 6b77d94..81e9ad1 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -232,6 +232,9 @@ class Gcc_backend : public Backend Bexpression* convert_expression(Btype* type, Bexpression* expr, Location); + Bexpression* + function_code_expression(Bfunction*, Location); + // Statements. Bstatement* @@ -981,6 +984,19 @@ Gcc_backend::convert_expression(Btype* type, Bexpression* expr, Location) return tree_to_expr(ret); } +// Get the address of a function. + +Bexpression* +Gcc_backend::function_code_expression(Bfunction* bfunc, Location location) +{ + tree func = bfunc->get_tree(); + if (func == error_mark_node) + return this->error_expression(); + + tree ret = build_fold_addr_expr_loc(location.gcc_location(), func); + return this->make_expression(ret); +} + // An expression as a statement. Bstatement* diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index e73c98c..ca997f0 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -266,6 +266,11 @@ class Backend virtual Bexpression* convert_expression(Btype* type, Bexpression* expr, Location) = 0; + // Create an expression for the address of a function. This is used to + // get the address of the code for a function. + virtual Bexpression* + function_code_expression(Bfunction*, Location) = 0; + // Statements. // Create an error statement. This is used for cases which should diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 258953f..6ba351e 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -1219,7 +1219,7 @@ Func_expression::do_type() // Get the tree for the code of a function expression. -tree +Bexpression* Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc) { Function_type* fntype; @@ -1237,10 +1237,10 @@ Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc) error_at(loc, "invalid use of special builtin function %qs; must be called", no->message_name().c_str()); - return error_mark_node; + return gogo->backend()->error_expression(); } - tree fndecl; + Bfunction* fndecl; if (no->is_function()) fndecl = no->func_value()->get_or_make_decl(gogo, no); else if (no->is_function_declaration()) @@ -1248,10 +1248,7 @@ Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc) else go_unreachable(); - if (fndecl == error_mark_node) - return error_mark_node; - - return build_fold_addr_expr_loc(loc.gcc_location(), fndecl); + return gogo->backend()->function_code_expression(fndecl, loc); } // Get the tree for a function expression. This is used when we take @@ -1488,8 +1485,10 @@ class Func_code_reference_expression : public Expression tree Func_code_reference_expression::do_get_tree(Translate_context* context) { - return Func_expression::get_code_pointer(context->gogo(), this->function_, - this->location()); + Bexpression* ret = + Func_expression::get_code_pointer(context->gogo(), this->function_, + this->location()); + return expr_to_tree(ret); } // Make a reference to the code of a function. @@ -9846,7 +9845,7 @@ Call_expression::do_get_tree(Translate_context* context) if (func != NULL) { Named_object* no = func->named_object(); - fn = Func_expression::get_code_pointer(gogo, no, location); + fn = expr_to_tree(Func_expression::get_code_pointer(gogo, no, location)); if (!has_closure) closure_tree = NULL_TREE; else diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index bc7a25f..35bfcfe 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -1514,8 +1514,8 @@ class Func_expression : public Expression closure() { return this->closure_; } - // Return a tree for the code for a function. - static tree + // Return a backend expression for the code of a function. + static Bexpression* get_code_pointer(Gogo*, Named_object* function, Location loc); protected: diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc index 78a8c6a..fbc4652 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -1089,7 +1089,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function) case NAMED_OBJECT_FUNC: { Function* func = this->u_.func_value; - decl = func->get_or_make_decl(gogo, this); + decl = function_to_tree(func->get_or_make_decl(gogo, this)); if (decl != error_mark_node) { if (func->block() != NULL) @@ -1214,83 +1214,9 @@ Variable::get_init_block(Gogo* gogo, Named_object* function, tree var_decl) return block_tree; } -// Get a tree for a function decl. +// Get the backend representation. -tree -Function::get_or_make_decl(Gogo* gogo, Named_object* no) -{ - if (this->fndecl_ == NULL) - { - std::string asm_name; - bool is_visible = false; - if (no->package() != NULL) - ; - else if (this->enclosing_ != NULL || Gogo::is_thunk(no)) - ; - else if (Gogo::unpack_hidden_name(no->name()) == "init" - && !this->type_->is_method()) - ; - else if (Gogo::unpack_hidden_name(no->name()) == "main" - && gogo->is_main_package()) - is_visible = true; - // Methods have to be public even if they are hidden because - // they can be pulled into type descriptors when using - // anonymous fields. - else if (!Gogo::is_hidden_name(no->name()) - || this->type_->is_method()) - { - is_visible = true; - std::string pkgpath = gogo->pkgpath_symbol(); - if (this->type_->is_method() - && Gogo::is_hidden_name(no->name()) - && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath()) - { - // This is a method we created for an unexported - // method of an imported embedded type. We need to - // use the pkgpath of the imported package to avoid - // a possible name collision. See bug478 for a test - // case. - pkgpath = Gogo::hidden_name_pkgpath(no->name()); - pkgpath = Gogo::pkgpath_for_symbol(pkgpath); - } - - asm_name = pkgpath; - asm_name.append(1, '.'); - asm_name.append(Gogo::unpack_hidden_name(no->name())); - if (this->type_->is_method()) - { - asm_name.append(1, '.'); - Type* rtype = this->type_->receiver()->type(); - asm_name.append(rtype->mangled_name(gogo)); - } - } - - // 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 - // thunk that we built to test whether a function can be - // recovered, we can't inline it, because that will mess up - // our return address comparison. - bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_); - - // If this is a thunk created to call a function which calls - // the predeclared recover function, we need to disable - // stack splitting for the thunk. - bool disable_split_stack = this->is_recover_thunk_; - - Btype* functype = this->type_->get_backend_fntype(gogo); - this->fndecl_ = - gogo->backend()->function(functype, no->get_id(gogo), asm_name, - is_visible, false, is_inlinable, - disable_split_stack, - this->in_unique_section_, this->location()); - } - return function_to_tree(this->fndecl_); -} - -// Get a tree for a function declaration. - -tree +Bfunction* Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) { if (this->fndecl_ == NULL) @@ -1304,7 +1230,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) if (p != builtin_functions.end()) { this->fndecl_ = tree_to_function(p->second); - return p->second; + return this->fndecl_; } } @@ -1331,7 +1257,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) this->location()); } - return function_to_tree(this->fndecl_); + return this->fndecl_; } // Return the function's decl after it has been built. @@ -2202,14 +2128,14 @@ Gogo::interface_method_table_for_type(const Interface_type* interface, go_assert(m != NULL); Named_object* no = m->named_object(); - tree fndecl; + Bfunction* bf; if (no->is_function()) - fndecl = no->func_value()->get_or_make_decl(this, no); + bf = no->func_value()->get_or_make_decl(this, no); else if (no->is_function_declaration()) - fndecl = no->func_declaration_value()->get_or_make_decl(this, no); + bf = no->func_declaration_value()->get_or_make_decl(this, no); else go_unreachable(); - fndecl = build_fold_addr_expr(fndecl); + tree fndecl = build_fold_addr_expr(function_to_tree(bf)); elt = pointers->quick_push(empty); elt->index = size_int(i); diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index a8f7754..0796caa 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -3819,6 +3819,80 @@ Function::import_func(Import* imp, std::string* pname, *presults = results; } +// Get the backend representation. + +Bfunction* +Function::get_or_make_decl(Gogo* gogo, Named_object* no) +{ + if (this->fndecl_ == NULL) + { + std::string asm_name; + bool is_visible = false; + if (no->package() != NULL) + ; + else if (this->enclosing_ != NULL || Gogo::is_thunk(no)) + ; + else if (Gogo::unpack_hidden_name(no->name()) == "init" + && !this->type_->is_method()) + ; + else if (Gogo::unpack_hidden_name(no->name()) == "main" + && gogo->is_main_package()) + is_visible = true; + // Methods have to be public even if they are hidden because + // they can be pulled into type descriptors when using + // anonymous fields. + else if (!Gogo::is_hidden_name(no->name()) + || this->type_->is_method()) + { + is_visible = true; + std::string pkgpath = gogo->pkgpath_symbol(); + if (this->type_->is_method() + && Gogo::is_hidden_name(no->name()) + && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath()) + { + // This is a method we created for an unexported + // method of an imported embedded type. We need to + // use the pkgpath of the imported package to avoid + // a possible name collision. See bug478 for a test + // case. + pkgpath = Gogo::hidden_name_pkgpath(no->name()); + pkgpath = Gogo::pkgpath_for_symbol(pkgpath); + } + + asm_name = pkgpath; + asm_name.append(1, '.'); + asm_name.append(Gogo::unpack_hidden_name(no->name())); + if (this->type_->is_method()) + { + asm_name.append(1, '.'); + Type* rtype = this->type_->receiver()->type(); + asm_name.append(rtype->mangled_name(gogo)); + } + } + + // 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 + // thunk that we built to test whether a function can be + // recovered, we can't inline it, because that will mess up + // our return address comparison. + bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_); + + // If this is a thunk created to call a function which calls + // the predeclared recover function, we need to disable + // stack splitting for the thunk. + bool disable_split_stack = this->is_recover_thunk_; + + Btype* functype = this->type_->get_backend_fntype(gogo); + this->fndecl_ = + gogo->backend()->function(functype, no->get_id(gogo), asm_name, + is_visible, false, is_inlinable, + disable_split_stack, + this->in_unique_section_, this->location()); + } + return this->fndecl_; +} + // Class Block. Block::Block(Block* enclosing, Location location) diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 5b416b0..8c4ccf9 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -1090,8 +1090,8 @@ class Function this->descriptor_ = descriptor; } - // Return the function's decl given an identifier. - tree + // Return the backend representation. + Bfunction* get_or_make_decl(Gogo*, Named_object*); // Return the function's decl after it has been built. @@ -1262,8 +1262,8 @@ class Function_declaration has_descriptor() const { return this->descriptor_ != NULL; } - // Return a decl for the function given an identifier. - tree + // Return a backend representation. + Bfunction* get_or_make_decl(Gogo*, Named_object*); // If there is a descriptor, build it into the backend |