This patch from Chris Manghane changes the Go frontend to use the backend interface for global constants. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian 2014-04-17 Chris Manghane <cm...@google.com> * go-gcc.cc (Gcc_backend::named_constant_expression): New function.
Index: gcc/go/go-gcc.cc =================================================================== --- gcc/go/go-gcc.cc (revision 209494) +++ gcc/go/go-gcc.cc (revision 209495) @@ -227,6 +227,10 @@ class Gcc_backend : public Backend indirect_expression(Bexpression* expr, bool known_valid, Location); Bexpression* + named_constant_expression(Btype* btype, const std::string& name, + Bexpression* val, Location); + + Bexpression* integer_constant_expression(Btype* btype, mpz_t val); Bexpression* @@ -962,6 +966,29 @@ Gcc_backend::indirect_expression(Bexpres return tree_to_expr(ret); } +// Return an expression that declares a constant named NAME with the +// constant value VAL in BTYPE. + +Bexpression* +Gcc_backend::named_constant_expression(Btype* btype, const std::string& name, + Bexpression* val, Location location) +{ + tree type_tree = btype->get_tree(); + tree const_val = val->get_tree(); + if (type_tree == error_mark_node || const_val == error_mark_node) + return this->error_expression(); + + tree name_tree = get_identifier_from_string(name); + tree decl = build_decl(location.gcc_location(), CONST_DECL, name_tree, + type_tree); + DECL_INITIAL(decl) = const_val; + TREE_CONSTANT(decl) = 1; + TREE_READONLY(decl) = 1; + + go_preserve_from_gc(decl); + return this->make_expression(decl); +} + // Return a typed value as a constant integer. Bexpression* Index: gcc/go/gofrontend/gogo-tree.cc =================================================================== --- gcc/go/gofrontend/gogo-tree.cc (revision 209494) +++ gcc/go/gofrontend/gogo-tree.cc (revision 209495) @@ -1015,44 +1015,22 @@ Named_object::get_tree(Gogo* gogo, Named { case NAMED_OBJECT_CONST: { - Named_constant* named_constant = this->u_.const_value; Translate_context subcontext(gogo, function, NULL, NULL); - tree expr_tree = named_constant->expr()->get_tree(&subcontext); - if (expr_tree == error_mark_node) - decl = error_mark_node; - else + Type* type = this->u_.const_value->type(); + Location loc = this->location(); + + Expression* const_ref = Expression::make_const_reference(this, loc); + Bexpression* const_decl = + tree_to_expr(const_ref->get_tree(&subcontext)); + if (type != NULL && type->is_numeric_type()) { - Type* type = named_constant->type(); - if (type != NULL && !type->is_abstract()) - { - if (type->is_error()) - expr_tree = error_mark_node; - else - { - Btype* btype = type->get_backend(gogo); - expr_tree = fold_convert(type_to_tree(btype), expr_tree); - } - } - if (expr_tree == error_mark_node) - decl = error_mark_node; - else if (INTEGRAL_TYPE_P(TREE_TYPE(expr_tree))) - { - tree name = get_identifier_from_string(this->get_id(gogo)); - decl = build_decl(named_constant->location().gcc_location(), - CONST_DECL, name, TREE_TYPE(expr_tree)); - DECL_INITIAL(decl) = expr_tree; - TREE_CONSTANT(decl) = 1; - TREE_READONLY(decl) = 1; - } - else - { - // A CONST_DECL is only for an enum constant, so we - // shouldn't use for non-integral types. Instead we - // just return the constant itself, rather than a - // decl. - decl = expr_tree; - } + Btype* btype = type->get_backend(gogo); + std::string name = this->get_id(gogo); + const_decl = + gogo->backend()->named_constant_expression(btype, name, + const_decl, loc); } + decl = expr_to_tree(const_decl); } break; Index: gcc/go/gofrontend/backend.h =================================================================== --- gcc/go/gofrontend/backend.h (revision 209494) +++ gcc/go/gofrontend/backend.h (revision 209495) @@ -257,6 +257,12 @@ class Backend virtual Bexpression* indirect_expression(Bexpression* expr, bool known_valid, Location) = 0; + // Return an expression that declares a constant named NAME with the + // constant value VAL in BTYPE. + virtual Bexpression* + named_constant_expression(Btype* btype, const std::string& name, + Bexpression* val, Location) = 0; + // Return an expression for the multi-precision integer VAL in BTYPE. virtual Bexpression* integer_constant_expression(Btype* btype, mpz_t val) = 0; Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 209494) +++ gcc/go/gofrontend/expressions.cc (revision 209495) @@ -2792,12 +2792,12 @@ Const_expression::do_get_tree(Translate_ // If the type has been set for this expression, but the underlying // object is an abstract int or float, we try to get the abstract // value. Otherwise we may lose something in the conversion. + Expression* expr = this->constant_->const_value()->expr(); if (this->type_ != NULL && this->type_->is_numeric_type() && (this->constant_->const_value()->type() == NULL || this->constant_->const_value()->type()->is_abstract())) { - Expression* expr = this->constant_->const_value()->expr(); Numeric_constant nc; if (expr->numeric_constant_value(&nc) && nc.set_type(this->type_, false, this->location())) @@ -2807,15 +2807,9 @@ Const_expression::do_get_tree(Translate_ } } - Gogo* gogo = context->gogo(); - Bexpression* ret = - tree_to_expr(this->constant_->get_tree(gogo, context->function())); if (this->type_ != NULL) - { - Btype* btype = this->type_->get_backend(gogo); - ret = gogo->backend()->convert_expression(btype, ret, this->location()); - } - return expr_to_tree(ret); + expr = Expression::make_cast(this->type_, expr, this->location()); + return expr->get_tree(context); } // Dump ast representation for constant expression.