From patchwork Fri Oct 11 22:17:49 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 282946 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 07EFF2C0141 for ; Sat, 12 Oct 2013 09:18:12 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=UfAzBFgGkXqc5ik8/klIvj7qClOpff5pCA0s9TsjxBjAD9wnrK6gR nYpda5iDTIY+PkyOOS3fGTcsCN+vC2aHYjl1SWRbk7w9K4eKVKNiw3nRQUzYtlEl 2hzvo4wX65RcQupFun7cVtQGq96eA4zvA2FeSXS3eAJWO78d5wLt/Q= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; s= default; bh=kmp4Gbad241nhD3s7L7ZIajdMfE=; b=uQTgSCIIK0FplTdA1QoV gd15qHxnP5UnomaZqa3sU/OPL8jiI6EMpqSaYxuUbBvKUw2zMdikCYmTYtN0ubxj 1ruG5fS4e3awfuF6dcX3qr3Vs4VLn+Wgzrkt7O+27YJOm0eLL2WwnrI96fnKfTCh vULok4Adu1SfoScsF7lDM2E= Received: (qmail 16777 invoked by alias); 11 Oct 2013 22:17:55 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 16628 invoked by uid 89); 11 Oct 2013 22:17:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS, T_TVD_MIME_NO_HEADERS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f41.google.com Received: from mail-pa0-f41.google.com (HELO mail-pa0-f41.google.com) (209.85.220.41) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 11 Oct 2013 22:17:53 +0000 Received: by mail-pa0-f41.google.com with SMTP id bj1so5025895pad.14 for ; Fri, 11 Oct 2013 15:17:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version:content-type; bh=aHdBAte5wGfIWRrGQssiZvq/yCvnPhkWF8aAuHgzTkM=; b=fkvIQ4Fru90MqxXCikAPcooCvz/B8U5pKdPHQFGzuYJNxr0vTLKX8O8AYQi9ulXjIS ewWF7exqU3NnnIJkKazT0ttb2F+xO6b8SLgN9yRNRFiTxJVP28pl040V+7avoE2uXb+T J7nOmViEbwvGX/79ugJcs9zt/7IAxCEjjmFZGOtmtRKrrwp/a6kczZHDPUWSx0N7GX5p +C2UkYw9qKtWbhgroJOaKaEMO+boKc/IkW9mxstw0hFjKMfhvp4LNBuV9w79Ovly6rtr NVCUCxTt8Q5Zu5gtFK46x7gSmuJ6IEVY+6gAiHo+gqdAoQ96jlSwsSqQyLRxPh24tiaz qYpA== X-Gm-Message-State: ALoCoQlE4gOrOglxUzT1sASbTbFWVF2YxcVAW1tJQLgIGxddYI6f5DXjQX1R2TUZAChGL3jS4n495a9fiRRwtVwLF+ItK5+JIIg6DnF+ULi1pgOEHthFY4x0x2TPYtgw+fyEd+nsxO9cqj4qQqdsB23GZZn5lG+p1RxlkazRCipa5oNW5GfdwpaS+Lz1u5bmHtJ4S1bCA6gxsszWOqonGy5Amx2bm2dlPw== X-Received: by 10.66.216.129 with SMTP id oq1mr24444111pac.75.1381529871215; Fri, 11 Oct 2013 15:17:51 -0700 (PDT) Received: from iant-glaptop.roam.corp.google.com.google.com ([2620:0:1000:3204:2d0f:b0a5:5b39:aae7]) by mx.google.com with ESMTPSA id bp4sm59511210pbb.42.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 11 Oct 2013 15:17:50 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Use backend interface for function code exprs Date: Fri, 11 Oct 2013 15:17:49 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes This patch by Chris Manghane changes the Go frontend to use the backend interface for function code expressions. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian 2013-10-11 Chris Manghane * go-gcc.cc (Gcc_backend::function_code_expression): New function. Index: gcc/go/gofrontend/gogo.h =================================================================== --- gcc/go/gofrontend/gogo.h (revision 203403) +++ gcc/go/gofrontend/gogo.h (working copy) @@ -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 Index: gcc/go/gofrontend/gogo-tree.cc =================================================================== --- gcc/go/gofrontend/gogo-tree.cc (revision 203403) +++ gcc/go/gofrontend/gogo-tree.cc (working copy) @@ -1089,7 +1089,7 @@ Named_object::get_tree(Gogo* gogo, Named 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, Nam 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(G 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(G 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(co 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); Index: gcc/go/gofrontend/gogo.cc =================================================================== --- gcc/go/gofrontend/gogo.cc (revision 203403) +++ gcc/go/gofrontend/gogo.cc (working copy) @@ -3819,6 +3819,80 @@ Function::import_func(Import* imp, std:: *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) Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 203454) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -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* 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* 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 : p 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_c 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 Index: gcc/go/gofrontend/expressions.h =================================================================== --- gcc/go/gofrontend/expressions.h (revision 203292) +++ gcc/go/gofrontend/expressions.h (working copy) @@ -1514,8 +1514,8 @@ class Func_expression : public Expressio 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: Index: gcc/go/gofrontend/backend.h =================================================================== --- gcc/go/gofrontend/backend.h (revision 203403) +++ gcc/go/gofrontend/backend.h (working copy) @@ -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 Index: gcc/go/go-gcc.cc =================================================================== --- gcc/go/go-gcc.cc (revision 203403) +++ gcc/go/go-gcc.cc (working copy) @@ -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* t 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*