From patchwork Sat Dec 1 00:15:42 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 203087 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]) by ozlabs.org (Postfix) with SMTP id BF8932C0082 for ; Sat, 1 Dec 2012 11:16:03 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1354925765; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:From:To:Subject:Date:Message-ID:User-Agent:MIME-Version: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=aXDBPDy VLJ2wIfxoiCn5C6mdW94=; b=hbANpjqCs34+wddwV77H1vI0NL5uma1OanYw8QP AaSduwBbTlpvKJoJa1YTC9kVkrBy+53X/c0YiysEvPGK+CduPjGBq9wD3sLvuS/e WiLODuKXb6GZzhKdrHGCNNyqudb6kquuPzOsYUHowocuJjJDOzuHQfO8FVxan2QB fkL8= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:Received:Received:From:To:Subject:Date:Message-ID:User-Agent:MIME-Version:Content-Type:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=IRyDunBNQsGTDMXXsJY2vlay917sIkDj7JMHrwlVYzwTcuTAFzdJWwU8y9Dh8I +S8TRrp5v4P06WQxYpEvrQAnAKh51WmTahndzbiefai8MSuuruudmRowuLaZsjj/ J5sEEW7ZIqR/fmfbMepCNpw5gpLWVMhyMgFD81C+88ZSU=; Received: (qmail 21506 invoked by alias); 1 Dec 2012 00:15:55 -0000 Received: (qmail 21495 invoked by uid 22791); 1 Dec 2012 00:15:52 -0000 X-SWARE-Spam-Status: No, hits=-4.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from mail-pb0-f47.google.com (HELO mail-pb0-f47.google.com) (209.85.160.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 01 Dec 2012 00:15:46 +0000 Received: by mail-pb0-f47.google.com with SMTP id un1so715199pbc.20 for ; Fri, 30 Nov 2012 16:15:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:subject:date:message-id:user-agent:mime-version :content-type:x-gm-message-state; bh=4Z+e5IJE676ernXYsBTJIk/BbukHOdhX11k/x8tgpVg=; b=jPwSJe6WsPD4FV2LzAC8CyYH4GYTBXux/O0u5e+uQR2iXcV7Sh6gFxlR2kvUwCpc6l WVZFOO32Dwf9EfKZq2/7pZLYbKHr5TxkyKMfpFyjihy+wKp1pXteP8Jut+6huMfg/Rhl f5/fIbYjcuYS70Yb1OvAGU7ZkYWD+hqs6/HYlNKoVtHF+bQmpTDFPwe4Al8KrhwRb23z ygFwBlqrwK299gkYtKvIkLPpZP+6iFFN/driDBuW2U8B2k50PIA3HFMddM2rLG6ZLkUQ xNs7q8JwMwKSHz+yhqKCSlLplJoidhhQFHThjgUfPVB6ZGy+dx84VxrT7ZOY9qEG7PpD kucw== Received: by 10.66.87.33 with SMTP id u1mr7290735paz.73.1354320945689; Fri, 30 Nov 2012 16:15:45 -0800 (PST) Received: from coign.google.com ([2620:0:1000:1804:224:d7ff:fe8f:f634]) by mx.google.com with ESMTPS id uq5sm3781486pbc.56.2012.11.30.16.15.43 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 30 Nov 2012 16:15:44 -0800 (PST) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Fix bug converting unnamed types Date: Fri, 30 Nov 2012 16:15:42 -0800 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-Gm-Message-State: ALoCoQnRWNijguv2hRVo8rIVpTUClyXAKNVJdI0Vjgr191gBESdG0WXoLk6ZO06bSGr8eseAosk6b0CdJU/YxtVkR+u+vC1iGkwpgRwTAMC9vV6jYpIGGKPWRRRNJCqPOxgkZPkq6sinnD0hcQYotMx2xcTC05rGvQQezpSwicCw2fhiQHrV0eg1hBgfFFAbsGd+j9N0Wgy9 X-IsSubscribed: yes 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 This patch to the Go frontend fixes a bug converting unnamed types to GIMPLE. It's important to convert all identical unnamed Go types to the same GIMPLE type, to avoid middle-end errors in assignments and type conversions. This is done via a hash table. Unfortunately Type::get_backend_placeholder was not using the hash table, so it was possible to get two different placeholder types for two identical unnamed Go types, leading in some cases to getting two different GIMPLE types. This would then cause an ICE if the two types appeared in an assignment of some sort. This patch fixes the problem by recording placeholder information in the hash table, so that get_backend_placeholder can use it. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline and 4.7 branch. Ian diff -r b7d0a78bc2df go/types.cc --- a/go/types.cc Thu Nov 29 23:01:48 2012 -0800 +++ b/go/types.cc Fri Nov 30 15:36:47 2012 -0800 @@ -45,8 +45,7 @@ // Class Type. Type::Type(Type_classification classification) - : classification_(classification), btype_is_placeholder_(false), - btype_(NULL), type_descriptor_var_(NULL) + : classification_(classification), btype_(NULL), type_descriptor_var_(NULL) { } @@ -910,11 +909,7 @@ Type::get_backend(Gogo* gogo) { if (this->btype_ != NULL) - { - if (this->btype_is_placeholder_ && gogo->named_types_are_converted()) - this->finish_backend(gogo); - return this->btype_; - } + return this->btype_; if (this->forward_declaration_type() != NULL || this->named_type() != NULL) @@ -928,20 +923,36 @@ // that. There is no need to use the hash table for named types, as // named types are only identical to themselves. - std::pair val(this, NULL); + std::pair val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; std::pair ins = Type::type_btypes.insert(val); - if (!ins.second && ins.first->second != NULL) - { - if (gogo != NULL && gogo->named_types_are_converted()) - this->btype_ = ins.first->second; - return ins.first->second; + if (!ins.second && ins.first->second.btype != NULL) + { + // Note that GOGO can be NULL here, but only when the GCC + // middle-end is asking for a frontend type. That will only + // happen for simple types, which should never require + // placeholders. + if (!ins.first->second.is_placeholder) + this->btype_ = ins.first->second.btype; + else if (gogo->named_types_are_converted()) + { + this->finish_backend(gogo, ins.first->second.btype); + ins.first->second.is_placeholder = false; + } + + return ins.first->second.btype; } Btype* bt = this->get_btype_without_hash(gogo); - if (ins.first->second == NULL) - ins.first->second = bt; + if (ins.first->second.btype == NULL) + { + ins.first->second.btype = bt; + ins.first->second.is_placeholder = false; + } else { // We have already created a backend representation for this @@ -949,10 +960,9 @@ // a named type which in turns uses an identical unnamed type. // Use the tree we created earlier and ignore the one we just // built. - bt = ins.first->second; - if (gogo == NULL || !gogo->named_types_are_converted()) - return bt; - this->btype_ = bt; + if (this->btype_ == bt) + this->btype_ = ins.first->second.btype; + bt = ins.first->second.btype; } return bt; @@ -1019,6 +1029,37 @@ // These are simple types that can just be created directly. return this->get_backend(gogo); + case TYPE_MAP: + case TYPE_CHANNEL: + // All maps and channels have the same backend representation. + return this->get_backend(gogo); + + case TYPE_NAMED: + case TYPE_FORWARD: + // Named types keep track of their own dependencies and manage + // their own placeholders. + return this->get_backend(gogo); + + case TYPE_INTERFACE: + if (this->interface_type()->is_empty()) + return Interface_type::get_backend_empty_interface_type(gogo); + break; + + default: + break; + } + + std::pair val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; + std::pair ins = + Type::type_btypes.insert(val); + if (!ins.second && ins.first->second.btype != NULL) + return ins.first->second.btype; + + switch (this->classification_) + { case TYPE_FUNCTION: { Location loc = this->function_type()->location(); @@ -1061,37 +1102,36 @@ } break; - case TYPE_MAP: - case TYPE_CHANNEL: - // All maps and channels have the same backend representation. - return this->get_backend(gogo); - case TYPE_INTERFACE: - if (this->interface_type()->is_empty()) - return Interface_type::get_backend_empty_interface_type(gogo); - else - { - std::vector bfields; - get_backend_interface_fields(gogo, this->interface_type(), true, - &bfields); - bt = gogo->backend()->struct_type(bfields); - } + { + go_assert(!this->interface_type()->is_empty()); + std::vector bfields; + get_backend_interface_fields(gogo, this->interface_type(), true, + &bfields); + bt = gogo->backend()->struct_type(bfields); + } break; - case TYPE_NAMED: - case TYPE_FORWARD: - // Named types keep track of their own dependencies and manage - // their own placeholders. - return this->get_backend(gogo); - case TYPE_SINK: case TYPE_CALL_MULTIPLE_RESULT: + /* Note that various classifications were handled in the earlier + switch. */ default: go_unreachable(); } - this->btype_ = bt; - this->btype_is_placeholder_ = true; + if (ins.first->second.btype == NULL) + { + ins.first->second.btype = bt; + ins.first->second.is_placeholder = true; + } + else + { + // A placeholder for this type got created along the way. Use + // that one and ignore the one we just built. + bt = ins.first->second.btype; + } + return bt; } @@ -1099,12 +1139,8 @@ // using a placeholder type. void -Type::finish_backend(Gogo* gogo) -{ - go_assert(this->btype_ != NULL); - if (!this->btype_is_placeholder_) - return; - +Type::finish_backend(Gogo* gogo, Btype *placeholder) +{ switch (this->classification_) { case TYPE_ERROR: @@ -1120,7 +1156,7 @@ case TYPE_FUNCTION: { Btype* bt = this->do_get_backend(gogo); - if (!gogo->backend()->set_placeholder_function_type(this->btype_, bt)) + if (!gogo->backend()->set_placeholder_function_type(placeholder, bt)) go_assert(saw_errors()); } break; @@ -1128,7 +1164,7 @@ case TYPE_POINTER: { Btype* bt = this->do_get_backend(gogo); - if (!gogo->backend()->set_placeholder_pointer_type(this->btype_, bt)) + if (!gogo->backend()->set_placeholder_pointer_type(placeholder, bt)) go_assert(saw_errors()); } break; @@ -1165,7 +1201,7 @@ go_unreachable(); } - this->btype_is_placeholder_ = false; + this->btype_ = placeholder; } // Return a pointer to the type descriptor for this type. @@ -2968,8 +3004,8 @@ // backend representation, so force it to be finished now. if (!gogo->named_types_are_converted()) { - pb->get_backend_placeholder(gogo); - pb->finish_backend(gogo); + Btype* bt = pb->get_backend_placeholder(gogo); + pb->finish_backend(gogo, bt); } fields[0].name = "__data"; diff -r b7d0a78bc2df go/types.h --- a/go/types.h Thu Nov 29 23:01:48 2012 -0800 +++ b/go/types.h Fri Nov 30 15:36:47 2012 -0800 @@ -888,7 +888,7 @@ // Finish the backend representation of a placeholder. void - finish_backend(Gogo*); + finish_backend(Gogo*, Btype*); // Build a type descriptor entry for this type. Return a pointer to // it. The location is the location which causes us to need the @@ -1210,10 +1210,18 @@ Btype* get_btype_without_hash(Gogo*); + // A backend type that may be a placeholder. + struct Type_btype_entry + { + Btype *btype; + bool is_placeholder; + }; + // A mapping from Type to Btype*, used to ensure that the backend - // representation of identical types is identical. - typedef Unordered_map_hash(const Type*, Btype*, Type_hash_identical, - Type_identical) Type_btypes; + // representation of identical types is identical. This is only + // used for unnamed types. + typedef Unordered_map_hash(const Type*, Type_btype_entry, + Type_hash_identical, Type_identical) Type_btypes; static Type_btypes type_btypes; @@ -1230,9 +1238,6 @@ // The type classification. Type_classification classification_; - // Whether btype_ is a placeholder type used while named types are - // being converted. - bool btype_is_placeholder_; // The backend representation of the type, once it has been // determined. Btype* btype_;