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>
* go-gcc.cc (Backend::error_expression): New function.
......
......@@ -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*
......
......@@ -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
......
......@@ -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.
......
......@@ -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
......
......@@ -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
......
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