From: Chris Manghane Date: Wed, 2 Oct 2013 19:22:07 +0000 (+0000) Subject: compiler: Use backend interface for numeric expressions. X-Git-Tag: releases/gcc-4.9.0~3744 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=002ee4d12f56b0164ef224cc8c6fad347b8d95c6;p=thirdparty%2Fgcc.git compiler: Use backend interface for numeric expressions. * 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. From-SVN: r203127 --- diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 8c3a3bda041a..0c9340600b03 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,10 @@ +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. + 2013-09-30 Chris Manghane * go-gcc.cc (Backend::error_expression): New function. diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index df8c4fc6d943..55b60ade21d4 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -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(Bexpression* expr, bool known_valid, 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* diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index 18a594736c48..d0abdd7f7989 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -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 diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 430422c38763..67bec710df5e 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -610,102 +610,57 @@ Expression::get_tree(Translate_context* 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) - { - mpfr_t fval; - mpfr_init_set_z(fval, val, GMP_RNDN); - tree ret = Expression::float_constant_tree(fval, type); - mpfr_clear(fval); - return ret; - } - else if (TREE_CODE(type) == COMPLEX_TYPE) - { - mpfr_t fval; - mpfr_init_set_z(fval, val, GMP_RNDN); - tree real = Expression::float_constant_tree(fval, TREE_TYPE(type)); - 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. + Gogo* gogo = context->gogo(); + Type* type = val->type(); + if (type == NULL) + return gogo->backend()->error_expression(); -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) + Btype* btype = type->get_backend(gogo); + Bexpression* ret; + if (type->integer_type() != NULL) { mpz_t ival; - mpz_init(ival); - mpfr_get_z(ival, val, GMP_RNDN); - tree ret = Expression::integer_constant_tree(ival, type); + 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); - return ret; } - else if (TREE_CODE(type) == REAL_TYPE) + else if (type->float_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); + mpfr_t fval; + 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); } - else if (TREE_CODE(type) == COMPLEX_TYPE) + else if (type->complex_type() != NULL) { - 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(Translate_context* context) 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. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 95584f2748ba..b4cca5453b08 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -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 diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index a4a60706b7af..e1d68e743455 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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