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 <cm...@google.com> * 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 <gmp.h> +#include <mpfr.h> + // 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*