From patchwork Mon Dec 3 03:26:13 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: 203283 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 D57B52C008E for ; Mon, 3 Dec 2012 14:26:55 +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=1355110016; 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=hrmSVd7 YxNlL3OOyVdGUVzB7eLQ=; b=A8YOyMkMY/gbD9iGNGI/iAeB/Udh9Wfwitb01hA e/AAq5xTSQ8qDMGEWmP4GtjMd1eetcMXNE1QfeTEKm9dwsg/ndfUrPgI185npIAC 2qkV51xdzkrFf6TlXyYmXW0xCFRClUYI5ZjxbEkfhoutCbvHfBKrZKWcFW/Ng0xv j390= 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=iGs+LxO08pqw22dusWQ9aW2nH7rpFwsKJFFb/TfxccCimI1pPP7wlXI39H0FqR TY1JPy3FInbl/xqXpai0a2B6KdlDKB+CdbbTJq5BkpJhAzsvKqeI9p3e/ZMM2SYD 7QeSY/ihi36jkplgmfUxtD0wWKyWf4+iMBCQQv9axUXhg=; Received: (qmail 20783 invoked by alias); 3 Dec 2012 03:26:36 -0000 Received: (qmail 20771 invoked by uid 22791); 3 Dec 2012 03:26:35 -0000 X-SWARE-Spam-Status: No, hits=-4.4 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; Mon, 03 Dec 2012 03:26:22 +0000 Received: by mail-pb0-f47.google.com with SMTP id un1so1482137pbc.20 for ; Sun, 02 Dec 2012 19:26:20 -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=U7uXw/T6PwSNfL8XzxMc1mSbY3yekfTKYqvYiSPeiuA=; b=OrdcSamqAdS8m6Xx6RBAsZwdlOOVwLdrEdJKzdzdNdznrm7tsTUqloS2fsES11fPPk NmPnBJUxLzeExVtB0TeOLTPBhMksmXsw+po5PtlisZz9I3NSuULLC4RiZNeTE/aI/E+0 Laq8jtPMDSHr5F5iubv5dKJb6+mA3i1sTA2Qk8oMHkjqrZWUQunFY3/srCfpEVsOA+dO mE7Y7m9R0RegdYhxtmt4AVxTQrYg/LhIXZBppkfDKdGpaoeI7GlfEm/zgXDgSCqrSjSj zgQppR/qKvXOpmL+7s9X6OAAflqmi87IHaKUG4mRZRvmBFC66MABu1/nu4F2foYBxV4p 6how== Received: by 10.68.252.4 with SMTP id zo4mr25872002pbc.126.1354505180537; Sun, 02 Dec 2012 19:26:20 -0800 (PST) Received: from coign.google.com ([2401:fa00:0:9:224:d7ff:fe8f:f634]) by mx.google.com with ESMTPS id m7sm7243432paz.3.2012.12.02.19.26.16 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 02 Dec 2012 19:26:19 -0800 (PST) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Fix nil func calls, constant float type conversions Date: Sun, 02 Dec 2012 19:26:13 -0800 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-Gm-Message-State: ALoCoQmBp4GAjQQvFiVi+xuTi+hZuXilzibQ7G9wYoQ0XWXOoAVDsnggqkHaCxIDkOouLrDI2hF2cl0Gfh2NP5SY2Q2siIfNz8ESChSQmBVhcEDKY9yhe3XiyKWWaNQZTw6KjtfPkLNNcrbDVOSWeYdLnusMBaVDvB/lfbUq3rg1rKaRewHRKcbir0Vqskcsx1htzNomzxtC 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 two small, unrelated, things. Calls to a nil func value (corresponding to a NULL function pointer in C) should panic in Go, and panics should be recoverable. They were not recoverable in gccgo, because the exception unwinder does not unwind past a zero PC (because uw_frame_state_for checks for this and returns _URC_END_OF_STACK). To fix this I added a runtime nil check before every call through a func value. I changed the way the code handles explicit conversions of constant float or complex values. Rather than postponing them to runtime, I use mpfr_set_prec to reduce the precision as needed. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline and 4.7 branch. Ian diff -r 623a0f780e0f go/expressions.cc --- a/go/expressions.cc Fri Nov 30 16:14:46 2012 -0800 +++ b/go/expressions.cc Sun Dec 02 18:57:12 2012 -0800 @@ -2965,46 +2965,6 @@ { if (!nc.set_type(type, true, location)) return Expression::make_error(location); - - // Don't simply convert to or from a float or complex type - // with a different size. That may change the value. - Type* vtype = val->type(); - if (vtype->is_abstract()) - ; - else if (type->float_type() != NULL) - { - if (vtype->float_type() != NULL) - { - if (type->float_type()->bits() != vtype->float_type()->bits()) - return this; - } - else if (vtype->complex_type() != NULL) - { - if (type->float_type()->bits() * 2 - != vtype->complex_type()->bits()) - return this; - } - } - else if (type->complex_type() != NULL) - { - if (vtype->complex_type() != NULL) - { - if (type->complex_type()->bits() - != vtype->complex_type()->bits()) - return this; - } - else if (vtype->float_type() != NULL) - { - if (type->complex_type()->bits() - != vtype->float_type()->bits() * 2) - return this; - } - } - else if (vtype->float_type() != NULL) - return this; - else if (vtype->complex_type() != NULL) - return this; - return nc.expression(location); } } @@ -9239,6 +9199,9 @@ } } + if (func == NULL) + fn = save_expr(fn); + tree ret = build_call_array(excess_type != NULL_TREE ? excess_type : rettype, fn, nargs, args); delete[] args; @@ -9272,6 +9235,24 @@ if (this->results_ != NULL) ret = this->set_results(context, ret); + // We can't unwind the stack past a call to nil, so we need to + // insert an explicit check so that the panic can be recovered. + if (func == NULL) + { + tree compare = fold_build2_loc(location.gcc_location(), EQ_EXPR, + boolean_type_node, fn, + fold_convert_loc(location.gcc_location(), + TREE_TYPE(fn), + null_pointer_node)); + tree crash = build3_loc(location.gcc_location(), COND_EXPR, + void_type_node, compare, + gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, + location), + NULL_TREE); + ret = fold_build2_loc(location.gcc_location(), COMPOUND_EXPR, + TREE_TYPE(ret), crash, ret); + } + this->tree_ = ret; return ret; @@ -14229,7 +14210,7 @@ bool Numeric_constant::check_float_type(Float_type* type, bool issue_error, - Location location) const + Location location) { mpfr_t val; switch (this->classification_) @@ -14282,6 +14263,29 @@ } ret = exp <= max_exp; + + if (ret) + { + // Round the constant to the desired type. + mpfr_t t; + mpfr_init(t); + switch (type->bits()) + { + case 32: + mpfr_set_prec(t, 24); + break; + case 64: + mpfr_set_prec(t, 53); + break; + default: + go_unreachable(); + } + mpfr_set(t, val, GMP_RNDN); + mpfr_set(val, t, GMP_RNDN); + mpfr_clear(t); + + this->set_float(type, val); + } } mpfr_clear(val); @@ -14296,7 +14300,7 @@ bool Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, - Location location) const + Location location) { if (type->is_abstract()) return true; @@ -14315,46 +14319,77 @@ } mpfr_t real; + mpfr_t imag; switch (this->classification_) { case NC_INT: case NC_RUNE: mpfr_init_set_z(real, this->u_.int_val, GMP_RNDN); + mpfr_init_set_ui(imag, 0, GMP_RNDN); break; case NC_FLOAT: mpfr_init_set(real, this->u_.float_val, GMP_RNDN); + mpfr_init_set_ui(imag, 0, GMP_RNDN); break; case NC_COMPLEX: - if (!mpfr_nan_p(this->u_.complex_val.imag) - && !mpfr_inf_p(this->u_.complex_val.imag) - && !mpfr_zero_p(this->u_.complex_val.imag)) - { - if (mpfr_get_exp(this->u_.complex_val.imag) > max_exp) - { - if (issue_error) - error_at(location, "complex imaginary part overflow"); - return false; - } - } mpfr_init_set(real, this->u_.complex_val.real, GMP_RNDN); + mpfr_init_set(imag, this->u_.complex_val.imag, GMP_RNDN); break; default: go_unreachable(); } - bool ret; - if (mpfr_nan_p(real) || mpfr_inf_p(real) || mpfr_zero_p(real)) - ret = true; - else - ret = mpfr_get_exp(real) <= max_exp; + bool ret = true; + if (!mpfr_nan_p(real) + && !mpfr_inf_p(real) + && !mpfr_zero_p(real) + && mpfr_get_exp(real) > max_exp) + { + if (issue_error) + error_at(location, "complex real part overflow"); + ret = false; + } + + if (!mpfr_nan_p(imag) + && !mpfr_inf_p(imag) + && !mpfr_zero_p(imag) + && mpfr_get_exp(imag) > max_exp) + { + if (issue_error) + error_at(location, "complex imaginary part overflow"); + ret = false; + } + + if (ret) + { + // Round the constant to the desired type. + mpfr_t t; + mpfr_init(t); + switch (type->bits()) + { + case 64: + mpfr_set_prec(t, 24); + break; + case 128: + mpfr_set_prec(t, 53); + break; + default: + go_unreachable(); + } + mpfr_set(t, real, GMP_RNDN); + mpfr_set(real, t, GMP_RNDN); + mpfr_set(t, imag, GMP_RNDN); + mpfr_set(imag, t, GMP_RNDN); + mpfr_clear(t); + + this->set_complex(type, real, imag); + } mpfr_clear(real); - - if (!ret && issue_error) - error_at(location, "complex real part overflow"); + mpfr_clear(imag); return ret; } diff -r 623a0f780e0f go/expressions.h --- a/go/expressions.h Fri Nov 30 16:14:46 2012 -0800 +++ b/go/expressions.h Sun Dec 02 18:57:12 2012 -0800 @@ -2224,10 +2224,10 @@ check_int_type(Integer_type*, bool, Location) const; bool - check_float_type(Float_type*, bool, Location) const; + check_float_type(Float_type*, bool, Location); bool - check_complex_type(Complex_type*, bool, Location) const; + check_complex_type(Complex_type*, bool, Location); // The kinds of constants. enum Classification