From patchwork Wed Jul 10 18:13:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 1130528 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-504854-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=golang.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="R1lG/yLS"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=golang-org.20150623.gappssmtp.com header.i=@golang-org.20150623.gappssmtp.com header.b="CZrfoYsG"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45kS3s6qDZz9s7T for ; Thu, 11 Jul 2019 04:13:27 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=Xkt1IOegcjNHqQUQreu0mr9t+zMqzD55EQjpb39Vl9JTTN 2HBH7VSr7gSbH9OisRzZpGS0UAm9WLdOVTQOi2+K97owxadYfxbmdQPpjtiqzj5A H7+OqGFC/kcgTHVTUFRgfbcuOYUS7TUf8w0hycMtMH4eHO3Jquz80aRx3KNrw= 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 :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=ahWWJWMaKi40n65TbJkq3vQaJfU=; b=R1lG/yLS/wGaZKDezVJk RGGAUzNlL/Wsvh2hmZxgDgf813gGeQ/fBvaNhiqjUcpaHRs84DeY6lb8Z1KC2ZIJ ApiAxxpgOh//ynynAObY9htsVxybCLGVYvqSnc1i0Pb8qfBzg25EYLgct9XDdyRH Z7ey+obsX/uzowm31jr8t+0= Received: (qmail 50641 invoked by alias); 10 Jul 2019 18:13:20 -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 50633 invoked by uid 89); 10 Jul 2019 18:13:19 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mail-lf1-f41.google.com Received: from mail-lf1-f41.google.com (HELO mail-lf1-f41.google.com) (209.85.167.41) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 10 Jul 2019 18:13:17 +0000 Received: by mail-lf1-f41.google.com with SMTP id h28so2248063lfj.5 for ; Wed, 10 Jul 2019 11:13:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=golang-org.20150623.gappssmtp.com; s=20150623; h=mime-version:from:date:message-id:subject:to; bh=knv1M6S08fRNxMnZKHb6+vs3jATXarSKVJxtPSmNdwQ=; b=CZrfoYsG5YXivYCXf6oegzafGW31Q1EACeLcqVCjWfdT+bG9F9ANKFjKafOEv66aO2 JNOa9kkpXOJMFWfPE6Q65suQrhsXCnMhM7NpR/uUOm2tF9e7zbgWElG8IulaWwLRJvCS l3verGU6h3VEyUOIAU+Wg1GsS0snM1RPelR+tHHxk6DD7pKF6/Nin5QWU27simjkND/v V5XTlatefRwtwLIGe5enQ89yGRh9XaBq0r9Nx25afSqL1WZJXrSRQMKUWgo0EbjBDqaT /AnElTPrYV6qpmu5LDzc9DS2sX+jYNypyIu+yaWf2XWvF+5Eg229aOuhEvbDSlr5JSMk 7sBQ== MIME-Version: 1.0 From: Ian Lance Taylor Date: Wed, 10 Jul 2019 11:13:04 -0700 Message-ID: Subject: Go patch committed: Finalize methods when importing types To: gcc-patches , gofrontend-dev This patch to the Go frontend by Than McIntosh changes the compiler to be more aggressive about finalizing methods on imported types, to avoid problems with interface types that are imported but remain unreachable until a later stage in the compilation. The normal pattern prior to this change was that the import process would leave imported interface types alone, and rely on Gogo::finalize_methods to locate and finalize all interface types at a later point. This way of doing things was not working in all cases due to the fact that we can import an interface type that is only reachable from the body of an inlinable function, meaning that we can't "find" the type during the methods finalize phase. The importer's Import::read_types() now makes a pass over all imported types to finalize methods on any newly imported type, which takes care of the issue. New test case for this problem in https://golang.org/cl/185517. This fixes https://golang.org/issue/33013. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline. Ian Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 273359) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -170ecdf6b2eab8aac2b8c852fa95d3c36d6bf604 +ec754ff4617d564d3dc377121ea9ac5e55f6535a The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/gogo.cc =================================================================== --- gcc/go/gofrontend/gogo.cc (revision 273307) +++ gcc/go/gofrontend/gogo.cc (working copy) @@ -3422,24 +3422,6 @@ Gogo::create_function_descriptors() this->traverse(&cfd); } -// Look for interface types to finalize methods of inherited -// interfaces. - -class Finalize_methods : public Traverse -{ - public: - Finalize_methods(Gogo* gogo) - : Traverse(traverse_types), - gogo_(gogo) - { } - - int - type(Type*); - - private: - Gogo* gogo_; -}; - // Finalize the methods of an interface type. int Index: gcc/go/gofrontend/gogo.h =================================================================== --- gcc/go/gofrontend/gogo.h (revision 273307) +++ gcc/go/gofrontend/gogo.h (working copy) @@ -3556,6 +3556,24 @@ class Traverse Expressions_seen* expressions_seen_; }; +// This class looks for interface types to finalize methods of inherited +// interfaces. + +class Finalize_methods : public Traverse +{ + public: + Finalize_methods(Gogo* gogo) + : Traverse(traverse_types), + gogo_(gogo) + { } + + int + type(Type*); + + private: + Gogo* gogo_; +}; + // A class which makes it easier to insert new statements before the // current statement during a traversal. Index: gcc/go/gofrontend/import.cc =================================================================== --- gcc/go/gofrontend/import.cc (revision 273307) +++ gcc/go/gofrontend/import.cc (working copy) @@ -290,10 +290,16 @@ Import::Import(Stream* stream, Location : gogo_(NULL), stream_(stream), location_(location), package_(NULL), add_to_globals_(false), packages_(), type_data_(), type_pos_(0), type_offsets_(), builtin_types_((- SMALLEST_BUILTIN_CODE) + 1), - types_(), version_(EXPORT_FORMAT_UNKNOWN) + types_(), finalizer_(NULL), version_(EXPORT_FORMAT_UNKNOWN) { } +Import::~Import() +{ + if (this->finalizer_ != NULL) + delete this->finalizer_; +} + // Import the data in the associated stream. Package* @@ -672,9 +678,40 @@ Import::read_types() this->gogo_->add_named_type(nt); } + // Finalize methods for any imported types. This is done after most of + // read_types() is complete so as to avoid method finalization of a type + // whose methods refer to types that are only partially read in. + // See issue #33013 for more on why this is needed. + this->finalize_methods(); + return true; } +void +Import::finalize_methods() +{ + if (this->finalizer_ == NULL) + this->finalizer_ = new Finalize_methods(gogo_); + Unordered_set(Type*) real_for_named; + for (size_t i = 1; i < this->types_.size(); i++) + { + Type* type = this->types_[i]; + if (type != NULL && type->named_type() != NULL) + { + this->finalizer_->type(type); + real_for_named.insert(type->named_type()->real_type()); + } + } + for (size_t i = 1; i < this->types_.size(); i++) + { + Type* type = this->types_[i]; + if (type != NULL + && type->named_type() == NULL + && real_for_named.find(type) == real_for_named.end()) + this->finalizer_->type(type); + } +} + // Import a constant. void Index: gcc/go/gofrontend/import.h =================================================================== --- gcc/go/gofrontend/import.h (revision 273307) +++ gcc/go/gofrontend/import.h (working copy) @@ -20,6 +20,7 @@ class Expression; class Import_function_body; class Temporary_statement; class Unnamed_label; +class Finalize_methods; // Expressions can be imported either directly from import data (for // simple constant expressions that can appear in a const declaration @@ -207,8 +208,7 @@ class Import : public Import_expression // Constructor. Import(Stream*, Location); - virtual ~Import() - {} + virtual ~Import(); // Register the builtin types. void @@ -423,6 +423,10 @@ class Import : public Import_expression return true; } + // Finalize methods for newly imported types. + void + finalize_methods(); + // The general IR. Gogo* gogo_; // The stream from which to read import data. @@ -446,6 +450,8 @@ class Import : public Import_expression std::vector builtin_types_; // Mapping from exported type codes to Type structures. std::vector types_; + // Helper for finalizing methods. + Finalize_methods* finalizer_; // Version of export data we're reading. Export_data_version version_; };