Commit 002ee4d1 by Chris Manghane Committed by Ian Lance Taylor

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
parent 99206ca9
2013-10-02 Chris Manghane <cmang@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.
2013-09-30 Chris Manghane <cmang@google.com> 2013-09-30 Chris Manghane <cmang@google.com>
* go-gcc.cc (Backend::error_expression): New function. * go-gcc.cc (Backend::error_expression): New function.
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "gimple.h" #include "gimple.h"
#include "toplev.h" #include "toplev.h"
#include "output.h" #include "output.h"
#include "real.h"
#include "realmpfr.h"
#include "go-c.h" #include "go-c.h"
...@@ -218,6 +220,15 @@ class Gcc_backend : public Backend ...@@ -218,6 +220,15 @@ class Gcc_backend : public Backend
Bexpression* Bexpression*
indirect_expression(Bexpression* expr, bool known_valid, Location); 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. // Statements.
Bstatement* Bstatement*
...@@ -882,6 +893,62 @@ Gcc_backend::indirect_expression(Bexpression* expr, bool known_valid, ...@@ -882,6 +893,62 @@ Gcc_backend::indirect_expression(Bexpression* expr, bool known_valid,
return tree_to_expr(ret); 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. // An expression as a statement.
Bstatement* Bstatement*
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#ifndef GO_BACKEND_H #ifndef GO_BACKEND_H
#define 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 // Pointers to these types are created by the backend, passed to the
// frontend, and passed back to the backend. The types must be // frontend, and passed back to the backend. The types must be
// defined by the backend using these names. // defined by the backend using these names.
...@@ -247,6 +250,18 @@ class Backend ...@@ -247,6 +250,18 @@ class Backend
virtual Bexpression* virtual Bexpression*
indirect_expression(Bexpression* expr, bool known_valid, Location) = 0; 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. // Statements.
// Create an error statement. This is used for cases which should // Create an error statement. This is used for cases which should
......
...@@ -610,102 +610,57 @@ Expression::get_tree(Translate_context* context) ...@@ -610,102 +610,57 @@ Expression::get_tree(Translate_context* context)
return this->do_get_tree(context); return this->do_get_tree(context);
} }
// Return a tree for VAL in TYPE. // Return a backend expression for VAL.
Bexpression*
tree Expression::backend_numeric_constant_expression(Translate_context* context,
Expression::integer_constant_tree(mpz_t val, tree type) Numeric_constant* val)
{ {
if (type == error_mark_node) Gogo* gogo = context->gogo();
return error_mark_node; Type* type = val->type();
else if (TREE_CODE(type) == INTEGER_TYPE) if (type == NULL)
return double_int_to_tree(type, return gogo->backend()->error_expression();
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.
tree Btype* btype = type->get_backend(gogo);
Expression::float_constant_tree(mpfr_t val, tree type) Bexpression* ret;
{ if (type->integer_type() != NULL)
if (type == error_mark_node)
return error_mark_node;
else if (TREE_CODE(type) == INTEGER_TYPE)
{ {
mpz_t ival; mpz_t ival;
mpz_init(ival); if (!val->to_int(&ival))
mpfr_get_z(ival, val, GMP_RNDN); {
tree ret = Expression::integer_constant_tree(ival, type); go_assert(saw_errors());
return gogo->backend()->error_expression();
}
ret = gogo->backend()->integer_constant_expression(btype, ival);
mpz_clear(ival); mpz_clear(ival);
return ret;
} }
else if (TREE_CODE(type) == REAL_TYPE) else if (type->float_type() != NULL)
{ {
REAL_VALUE_TYPE r1; mpfr_t fval;
real_from_mpfr(&r1, val, type, GMP_RNDN); if (!val->to_float(&fval))
REAL_VALUE_TYPE r2; {
real_convert(&r2, TYPE_MODE(type), &r1); go_assert(saw_errors());
return build_real(type, r2); 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; mpfr_t real;
real_from_mpfr(&r1, val, TREE_TYPE(type), GMP_RNDN); mpfr_t imag;
REAL_VALUE_TYPE r2; if (!val->to_complex(&real, &imag))
real_convert(&r2, TYPE_MODE(TREE_TYPE(type)), &r1); {
tree imag = build_real_from_int_cst(TREE_TYPE(type), go_assert(saw_errors());
integer_zero_node); return gogo->backend()->error_expression();
return build_complex(type, build_real(TREE_TYPE(type), r2), imag); }
ret = gogo->backend()->complex_constant_expression(btype, real, imag);
mpfr_clear(real);
mpfr_clear(imag);
} }
else else
go_unreachable(); go_unreachable();
}
// Return a tree for REAL/IMAG in TYPE. return ret;
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 a tree which evaluates to true if VAL, of arbitrary integer // Return a tree which evaluates to true if VAL, of arbitrary integer
...@@ -1998,21 +1953,18 @@ Integer_expression::do_check_types(Gogo*) ...@@ -1998,21 +1953,18 @@ Integer_expression::do_check_types(Gogo*)
tree tree
Integer_expression::do_get_tree(Translate_context* context) Integer_expression::do_get_tree(Translate_context* context)
{ {
Gogo* gogo = context->gogo(); Type* resolved_type = NULL;
tree type;
if (this->type_ != NULL && !this->type_->is_abstract()) 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) else if (this->type_ != NULL && this->type_->float_type() != NULL)
{ {
// We are converting to an abstract floating point type. // We are converting to an abstract floating point type.
Type* ftype = Type::lookup_float_type("float64"); resolved_type = Type::lookup_float_type("float64");
type = type_to_tree(ftype->get_backend(gogo));
} }
else if (this->type_ != NULL && this->type_->complex_type() != NULL) else if (this->type_ != NULL && this->type_->complex_type() != NULL)
{ {
// We are converting to an abstract complex type. // We are converting to an abstract complex type.
Type* ctype = Type::lookup_complex_type("complex128"); resolved_type = Type::lookup_complex_type("complex128");
type = type_to_tree(ctype->get_backend(gogo));
} }
else else
{ {
...@@ -2023,16 +1975,23 @@ Integer_expression::do_get_tree(Translate_context* context) ...@@ -2023,16 +1975,23 @@ Integer_expression::do_get_tree(Translate_context* context)
int bits = mpz_sizeinbase(this->val_, 2); int bits = mpz_sizeinbase(this->val_, 2);
Type* int_type = Type::lookup_integer_type("int"); Type* int_type = Type::lookup_integer_type("int");
if (bits < int_type->integer_type()->bits()) if (bits < int_type->integer_type()->bits())
type = type_to_tree(int_type->get_backend(gogo)); resolved_type = int_type;
else if (bits < 64) else if (bits < 64)
{ resolved_type = Type::lookup_integer_type("int64");
Type* t = Type::lookup_integer_type("int64");
type = type_to_tree(t->get_backend(gogo));
}
else 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. // Write VAL to export data.
...@@ -2286,24 +2245,32 @@ Float_expression::do_check_types(Gogo*) ...@@ -2286,24 +2245,32 @@ Float_expression::do_check_types(Gogo*)
tree tree
Float_expression::do_get_tree(Translate_context* context) Float_expression::do_get_tree(Translate_context* context)
{ {
Gogo* gogo = context->gogo(); Type* resolved_type;
tree type;
if (this->type_ != NULL && !this->type_->is_abstract()) 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) else if (this->type_ != NULL && this->type_->integer_type() != NULL)
{ {
// We have an abstract integer type. We just hope for the best. // 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 else
{ {
// If we still have an abstract type here, then this is being // If we still have an abstract type here, then this is being
// used in a constant expression which didn't get reduced. We // used in a constant expression which didn't get reduced. We
// just use float64 and hope for the best. // just use float64 and hope for the best.
Type* ft = Type::lookup_float_type("float64"); resolved_type = Type::lookup_float_type("float64");
type = type_to_tree(ft->get_backend(gogo));
} }
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. // Write a floating point number to a string dump.
...@@ -2463,19 +2430,32 @@ Complex_expression::do_check_types(Gogo*) ...@@ -2463,19 +2430,32 @@ Complex_expression::do_check_types(Gogo*)
tree tree
Complex_expression::do_get_tree(Translate_context* context) Complex_expression::do_get_tree(Translate_context* context)
{ {
Gogo* gogo = context->gogo(); Type* resolved_type;
tree type;
if (this->type_ != NULL && !this->type_->is_abstract()) 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 else
{ {
// If we still have an abstract type here, this this is being // If we still have an abstract type here, this this is being
// used in a constant expression which didn't get reduced. We // used in a constant expression which didn't get reduced. We
// just use complex128 and hope for the best. // just use complex128 and hope for the best.
Type* ct = Type::lookup_complex_type("complex128"); resolved_type = Type::lookup_complex_type("complex128");
type = type_to_tree(ct->get_backend(gogo));
} }
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. // Write REAL/IMAG to export data.
......
...@@ -652,17 +652,10 @@ class Expression ...@@ -652,17 +652,10 @@ class Expression
Type* left_type, tree left_tree, Type* right_type, Type* left_type, tree left_tree, Type* right_type,
tree right_tree, Location); tree right_tree, Location);
// Return a tree for the multi-precision integer VAL in TYPE. // Return the backend expression for the numeric constant VAL.
static tree static Bexpression*
integer_constant_tree(mpz_t val, tree type); backend_numeric_constant_expression(Translate_context*,
Numeric_constant* val);
// 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);
// Export the expression. This is only used for constants. It will // Export the expression. This is only used for constants. It will
// be used for things like values of named constants and sizes of // be used for things like values of named constants and sizes of
......
...@@ -5665,8 +5665,10 @@ Array_type::get_length_tree(Gogo* gogo) ...@@ -5665,8 +5665,10 @@ Array_type::get_length_tree(Gogo* gogo)
t = Type::lookup_integer_type("int"); t = Type::lookup_integer_type("int");
else if (t->is_abstract()) else if (t->is_abstract())
t = t->make_non_abstract_type(); t = t->make_non_abstract_type();
tree tt = type_to_tree(t->get_backend(gogo)); Btype* btype = t->get_backend(gogo);
this->length_tree_ = Expression::integer_constant_tree(val, tt); Bexpression* iexpr =
gogo->backend()->integer_constant_expression(btype, val);
this->length_tree_ = expr_to_tree(iexpr);
mpz_clear(val); mpz_clear(val);
} }
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment