From patchwork Wed Oct 2 19:22:47 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: 280167 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 10B662C007E for ; Thu, 3 Oct 2013 05:23:00 +1000 (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=EtsBc2cB36/5KDpFuB7fR5bExbiDGq8YvwcTVbjTyctElB8bsX3fA 2t+tNs2DqslGg4UNJqR0hgr5fNw43PeAME+/knfm/AqRnHSoccLCRej47BcWUOP6 gyvCkeas3hRSIWlxqoHBz4MgLyB/moDMgjc0bnDPAc/jx5l6/jvdqo= 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=DuLMUr/Ve6t6TuEqCVPwJFO9S68=; b=aqxxMqjdAgQQjEp4fs0T FVaNmL8h/FVls0lZPSC4HSw6EEcW3J5Q4N2CVpXRwSLEBFQIFgBTNgX/6hdzG49l 5O+jbP1UTEyaoi1+Vk/hV4h+Znh19z9B/8FYJzAia4cFi09SAUcFoZQKdmWUat7R slZ5th4Rs0Eayic3Ke8Blv0= Received: (qmail 16395 invoked by alias); 2 Oct 2013 19:22:54 -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 16386 invoked by uid 89); 2 Oct 2013 19:22:53 -0000 Received: from mail-pa0-f53.google.com (HELO mail-pa0-f53.google.com) (209.85.220.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 02 Oct 2013 19:22:53 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=ALL_TRUSTED, AWL, BAYES_00, T_TVD_MIME_NO_HEADERS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f53.google.com Received: by mail-pa0-f53.google.com with SMTP id kq14so1457562pab.26 for ; Wed, 02 Oct 2013 12:22:50 -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=YcLg9XSWaCzn1MHoISLNpzpM9Tgd2W8PwRJh2bGTzgo=; b=kVJI2yy35FHN0wn1gvzT74+JKCSrMm7nVXfbc1YMois1jLSZO6++3Nlqm1dfWrFBMB cmKwyAbH2bTBkBZB/LMPtw3czO+cpKP6MTfU7T/5kD1ULkKSvD+j8gfsdxRwQVMeqA7o SpgFAZkrTk1Phzf585P58/OCk3WNApzkViXPq6dy3ZelNdFbbFjSSp5tndLmSCarNaEz o2gBPNuvhzvBLZDPrLNS7vWYgr8bq9N0qW7BYiBk+SLKqKWj/Nyt/shMd4FBfTaOfnUu hFBjVy+iivGuMtza6Pe4f7vakUc/uMyp/97JzisATaefr9vEjwrTTellW//my953lt5d 3Q6A== X-Gm-Message-State: ALoCoQkoYe6/OQSzeVmjSZA1sSa2eae19fnQdQixi81Zcz8Mqkik3dAXxcoyy3n4YRY255LK6sl4nQr9TtDIrQo62SAJ6jJHIETxy1YzDellXbUg+Q4E8l3Szx9Yw20yPT0Lq0Ha5TSIoQflxLlelWqmTEBbCubr95WEj4SfEIk8F9Kt7u0EQYCd9DVF2as6d/9Ny67fSV0jPnVkWSpIUYL2yEmkRARdnA== X-Received: by 10.68.33.34 with SMTP id o2mr4284312pbi.128.1380741769851; Wed, 02 Oct 2013 12:22:49 -0700 (PDT) Received: from iant-glaptop.roam.corp.google.com.google.com ([2620:0:1000:3204:2406:292:f3ff:97c3]) by mx.google.com with ESMTPSA id og5sm3573072pbb.10.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Wed, 02 Oct 2013 12:22:48 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Use backend interface for numeric constants Date: Wed, 02 Oct 2013 12:22:47 -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 from Chris Manghane changes the Go frontend to use the backend interface for numeric constants. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline and 4.8 branch. Ian 2013-10-02 Chris Manghane * 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. Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 203039) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -610,102 +610,57 @@ Expression::get_tree(Translate_context* return this->do_get_tree(context); } -// Return a tree for VAL in TYPE. - -tree -Expression::integer_constant_tree(mpz_t val, tree type) +// Return a backend expression for VAL. +Bexpression* +Expression::backend_numeric_constant_expression(Translate_context* context, + Numeric_constant* val) { - if (type == error_mark_node) - return error_mark_node; - else if (TREE_CODE(type) == INTEGER_TYPE) - return double_int_to_tree(type, - mpz_get_double_int(type, val, true)); - else if (TREE_CODE(type) == REAL_TYPE) + Gogo* gogo = context->gogo(); + Type* type = val->type(); + if (type == NULL) + return gogo->backend()->error_expression(); + + Btype* btype = type->get_backend(gogo); + Bexpression* ret; + if (type->integer_type() != NULL) { - mpfr_t fval; - mpfr_init_set_z(fval, val, GMP_RNDN); - tree ret = Expression::float_constant_tree(fval, type); - mpfr_clear(fval); - return ret; + mpz_t ival; + if (!val->to_int(&ival)) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } + ret = gogo->backend()->integer_constant_expression(btype, ival); + mpz_clear(ival); } - else if (TREE_CODE(type) == COMPLEX_TYPE) + else if (type->float_type() != NULL) { mpfr_t fval; - mpfr_init_set_z(fval, val, GMP_RNDN); - tree real = Expression::float_constant_tree(fval, TREE_TYPE(type)); + if (!val->to_float(&fval)) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } + ret = gogo->backend()->float_constant_expression(btype, fval); mpfr_clear(fval); - tree imag = build_real_from_int_cst(TREE_TYPE(type), - integer_zero_node); - return build_complex(type, real, imag); } - else - go_unreachable(); -} - -// Return a tree for VAL in TYPE. - -tree -Expression::float_constant_tree(mpfr_t val, tree type) -{ - if (type == error_mark_node) - return error_mark_node; - else if (TREE_CODE(type) == INTEGER_TYPE) - { - mpz_t ival; - mpz_init(ival); - mpfr_get_z(ival, val, GMP_RNDN); - tree ret = Expression::integer_constant_tree(ival, type); - mpz_clear(ival); - return ret; - } - else if (TREE_CODE(type) == REAL_TYPE) + else if (type->complex_type() != NULL) { - REAL_VALUE_TYPE r1; - real_from_mpfr(&r1, val, type, GMP_RNDN); - REAL_VALUE_TYPE r2; - real_convert(&r2, TYPE_MODE(type), &r1); - return build_real(type, r2); - } - else if (TREE_CODE(type) == COMPLEX_TYPE) - { - REAL_VALUE_TYPE r1; - real_from_mpfr(&r1, val, TREE_TYPE(type), GMP_RNDN); - REAL_VALUE_TYPE r2; - real_convert(&r2, TYPE_MODE(TREE_TYPE(type)), &r1); - tree imag = build_real_from_int_cst(TREE_TYPE(type), - integer_zero_node); - return build_complex(type, build_real(TREE_TYPE(type), r2), imag); + mpfr_t real; + mpfr_t imag; + if (!val->to_complex(&real, &imag)) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } + ret = gogo->backend()->complex_constant_expression(btype, real, imag); + mpfr_clear(real); + mpfr_clear(imag); } else go_unreachable(); -} - -// Return a tree for REAL/IMAG in TYPE. -tree -Expression::complex_constant_tree(mpfr_t real, mpfr_t imag, tree type) -{ - if (type == error_mark_node) - return error_mark_node; - else if (TREE_CODE(type) == INTEGER_TYPE || TREE_CODE(type) == REAL_TYPE) - return Expression::float_constant_tree(real, type); - else if (TREE_CODE(type) == COMPLEX_TYPE) - { - REAL_VALUE_TYPE r1; - real_from_mpfr(&r1, real, TREE_TYPE(type), GMP_RNDN); - REAL_VALUE_TYPE r2; - real_convert(&r2, TYPE_MODE(TREE_TYPE(type)), &r1); - - REAL_VALUE_TYPE r3; - real_from_mpfr(&r3, imag, TREE_TYPE(type), GMP_RNDN); - REAL_VALUE_TYPE r4; - real_convert(&r4, TYPE_MODE(TREE_TYPE(type)), &r3); - - return build_complex(type, build_real(TREE_TYPE(type), r2), - build_real(TREE_TYPE(type), r4)); - } - else - go_unreachable(); + return ret; } // Return a tree which evaluates to true if VAL, of arbitrary integer @@ -1998,21 +1953,18 @@ Integer_expression::do_check_types(Gogo* tree Integer_expression::do_get_tree(Translate_context* context) { - Gogo* gogo = context->gogo(); - tree type; + Type* resolved_type = NULL; if (this->type_ != NULL && !this->type_->is_abstract()) - type = type_to_tree(this->type_->get_backend(gogo)); + resolved_type = this->type_; else if (this->type_ != NULL && this->type_->float_type() != NULL) { // We are converting to an abstract floating point type. - Type* ftype = Type::lookup_float_type("float64"); - type = type_to_tree(ftype->get_backend(gogo)); + resolved_type = Type::lookup_float_type("float64"); } else if (this->type_ != NULL && this->type_->complex_type() != NULL) { // We are converting to an abstract complex type. - Type* ctype = Type::lookup_complex_type("complex128"); - type = type_to_tree(ctype->get_backend(gogo)); + resolved_type = Type::lookup_complex_type("complex128"); } else { @@ -2023,16 +1975,23 @@ Integer_expression::do_get_tree(Translat int bits = mpz_sizeinbase(this->val_, 2); Type* int_type = Type::lookup_integer_type("int"); if (bits < int_type->integer_type()->bits()) - type = type_to_tree(int_type->get_backend(gogo)); + resolved_type = int_type; else if (bits < 64) - { - Type* t = Type::lookup_integer_type("int64"); - type = type_to_tree(t->get_backend(gogo)); - } + resolved_type = Type::lookup_integer_type("int64"); else - type = long_long_integer_type_node; + { + if (!saw_errors()) + error_at(this->location(), + "unknown type for large integer constant"); + Bexpression* ret = context->gogo()->backend()->error_expression(); + return expr_to_tree(ret); + } } - return Expression::integer_constant_tree(this->val_, type); + Numeric_constant nc; + nc.set_int(resolved_type, this->val_); + Bexpression* ret = + Expression::backend_numeric_constant_expression(context, &nc); + return expr_to_tree(ret); } // Write VAL to export data. @@ -2286,24 +2245,32 @@ Float_expression::do_check_types(Gogo*) tree Float_expression::do_get_tree(Translate_context* context) { - Gogo* gogo = context->gogo(); - tree type; + Type* resolved_type; if (this->type_ != NULL && !this->type_->is_abstract()) - type = type_to_tree(this->type_->get_backend(gogo)); + resolved_type = this->type_; else if (this->type_ != NULL && this->type_->integer_type() != NULL) { // We have an abstract integer type. We just hope for the best. - type = type_to_tree(Type::lookup_integer_type("int")->get_backend(gogo)); + resolved_type = Type::lookup_integer_type("int"); + } + else if (this->type_ != NULL && this->type_->complex_type() != NULL) + { + // We are converting to an abstract complex type. + resolved_type = Type::lookup_complex_type("complex128"); } else { // If we still have an abstract type here, then this is being // used in a constant expression which didn't get reduced. We // just use float64 and hope for the best. - Type* ft = Type::lookup_float_type("float64"); - type = type_to_tree(ft->get_backend(gogo)); + resolved_type = Type::lookup_float_type("float64"); } - return Expression::float_constant_tree(this->val_, type); + + Numeric_constant nc; + nc.set_float(resolved_type, this->val_); + Bexpression* ret = + Expression::backend_numeric_constant_expression(context, &nc); + return expr_to_tree(ret); } // Write a floating point number to a string dump. @@ -2463,19 +2430,32 @@ Complex_expression::do_check_types(Gogo* tree Complex_expression::do_get_tree(Translate_context* context) { - Gogo* gogo = context->gogo(); - tree type; + Type* resolved_type; if (this->type_ != NULL && !this->type_->is_abstract()) - type = type_to_tree(this->type_->get_backend(gogo)); + resolved_type = this->type_; + else if (this->type_ != NULL && this->type_->integer_type() != NULL) + { + // We are converting to an abstract integer type. + resolved_type = Type::lookup_integer_type("int"); + } + else if (this->type_ != NULL && this->type_->float_type() != NULL) + { + // We are converting to an abstract float type. + resolved_type = Type::lookup_float_type("float64"); + } else { // If we still have an abstract type here, this this is being // used in a constant expression which didn't get reduced. We // just use complex128 and hope for the best. - Type* ct = Type::lookup_complex_type("complex128"); - type = type_to_tree(ct->get_backend(gogo)); + resolved_type = Type::lookup_complex_type("complex128"); } - return Expression::complex_constant_tree(this->real_, this->imag_, type); + + Numeric_constant nc; + nc.set_complex(resolved_type, this->real_, this->imag_); + Bexpression* ret = + Expression::backend_numeric_constant_expression(context, &nc); + return expr_to_tree(ret); } // Write REAL/IMAG to export data. Index: gcc/go/gofrontend/expressions.h =================================================================== --- gcc/go/gofrontend/expressions.h (revision 203039) +++ gcc/go/gofrontend/expressions.h (working copy) @@ -652,17 +652,10 @@ class Expression Type* left_type, tree left_tree, Type* right_type, tree right_tree, Location); - // Return a tree for the multi-precision integer VAL in TYPE. - static tree - integer_constant_tree(mpz_t val, tree type); - - // Return a tree for the floating point value VAL in TYPE. - static tree - float_constant_tree(mpfr_t val, tree type); - - // Return a tree for the complex value REAL/IMAG in TYPE. - static tree - complex_constant_tree(mpfr_t real, mpfr_t imag, tree type); + // Return the backend expression for the numeric constant VAL. + static Bexpression* + backend_numeric_constant_expression(Translate_context*, + Numeric_constant* val); // Export the expression. This is only used for constants. It will // be used for things like values of named constants and sizes of Index: gcc/go/gofrontend/backend.h =================================================================== --- gcc/go/gofrontend/backend.h (revision 203039) +++ gcc/go/gofrontend/backend.h (working copy) @@ -7,6 +7,9 @@ #ifndef GO_BACKEND_H #define GO_BACKEND_H +#include +#include + // Pointers to these types are created by the backend, passed to the // frontend, and passed back to the backend. The types must be // defined by the backend using these names. @@ -247,6 +250,18 @@ class Backend virtual Bexpression* indirect_expression(Bexpression* expr, bool known_valid, Location) = 0; + // Return an expression for the multi-precision integer VAL in BTYPE. + virtual Bexpression* + integer_constant_expression(Btype* btype, mpz_t val) = 0; + + // Return an expression for the floating point value VAL in BTYPE. + virtual Bexpression* + float_constant_expression(Btype* btype, mpfr_t val) = 0; + + // Return an expression for the complex value REAL/IMAG in BTYPE. + virtual Bexpression* + complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag) = 0; + // Statements. // Create an error statement. This is used for cases which should Index: gcc/go/gofrontend/types.cc =================================================================== --- gcc/go/gofrontend/types.cc (revision 203039) +++ gcc/go/gofrontend/types.cc (working copy) @@ -5665,8 +5665,10 @@ Array_type::get_length_tree(Gogo* gogo) t = Type::lookup_integer_type("int"); else if (t->is_abstract()) t = t->make_non_abstract_type(); - tree tt = type_to_tree(t->get_backend(gogo)); - this->length_tree_ = Expression::integer_constant_tree(val, tt); + Btype* btype = t->get_backend(gogo); + Bexpression* iexpr = + gogo->backend()->integer_constant_expression(btype, val); + this->length_tree_ = expr_to_tree(iexpr); mpz_clear(val); } else Index: gcc/go/go-gcc.cc =================================================================== --- gcc/go/go-gcc.cc (revision 203039) +++ gcc/go/go-gcc.cc (working copy) @@ -29,6 +29,8 @@ #include "gimple.h" #include "toplev.h" #include "output.h" +#include "real.h" +#include "realmpfr.h" #include "go-c.h" @@ -218,6 +220,15 @@ class Gcc_backend : public Backend Bexpression* indirect_expression(Bexpression* expr, bool known_valid, Location); + Bexpression* + integer_constant_expression(Btype* btype, mpz_t val); + + Bexpression* + float_constant_expression(Btype* btype, mpfr_t val); + + Bexpression* + complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag); + // Statements. Bstatement* @@ -882,6 +893,62 @@ Gcc_backend::indirect_expression(Bexpres return tree_to_expr(ret); } +// Return a typed value as a constant integer. + +Bexpression* +Gcc_backend::integer_constant_expression(Btype* btype, mpz_t val) +{ + tree t = btype->get_tree(); + if (t == error_mark_node) + return this->error_expression(); + + tree ret = double_int_to_tree(t, mpz_get_double_int(t, val, true)); + return tree_to_expr(ret); +} + +// Return a typed value as a constant floating-point number. + +Bexpression* +Gcc_backend::float_constant_expression(Btype* btype, mpfr_t val) +{ + tree t = btype->get_tree(); + tree ret; + if (t == error_mark_node) + return this->error_expression(); + + REAL_VALUE_TYPE r1; + real_from_mpfr(&r1, val, t, GMP_RNDN); + REAL_VALUE_TYPE r2; + real_convert(&r2, TYPE_MODE(t), &r1); + ret = build_real(t, r2); + return tree_to_expr(ret); +} + +// Return a typed real and imaginary value as a constant complex number. + +Bexpression* +Gcc_backend::complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag) +{ + tree t = btype->get_tree(); + tree ret; + if (t == error_mark_node) + return this->error_expression(); + + REAL_VALUE_TYPE r1; + real_from_mpfr(&r1, real, TREE_TYPE(t), GMP_RNDN); + REAL_VALUE_TYPE r2; + real_convert(&r2, TYPE_MODE(TREE_TYPE(t)), &r1); + + REAL_VALUE_TYPE r3; + real_from_mpfr(&r3, imag, TREE_TYPE(t), GMP_RNDN); + REAL_VALUE_TYPE r4; + real_convert(&r4, TYPE_MODE(TREE_TYPE(t)), &r3); + + ret = build_complex(t, build_real(TREE_TYPE(t), r2), + build_real(TREE_TYPE(t), r4)); + return tree_to_expr(ret); +} + // An expression as a statement. Bstatement*