diff mbox

Go patch committed: Use backend interface for numeric constants

Message ID mcr8uybeauw.fsf@iant-glaptop.roam.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor Oct. 2, 2013, 7:22 p.m. UTC
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  <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.
diff mbox

Patch

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*