From d56e667993d46456e38c70d7e36c9be3c4dbf37f Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 5 Apr 2011 05:57:39 +0000 Subject: [PATCH] Use backend interface for labels and goto statements. * go-gcc.c (class Blabel): Define. (Gcc_backend::make_expression): New function. (get_identifier_from_string): New function. (Gcc_backend::label): New function. (Gcc_backend::label_definition_statement): New function. (Gcc_backend::goto_statement): New function. (Gcc_backend::label_address): New function. (expression_to_tree): New function. * Make-lang.in (go/expressions.o): Depend on go/gofrontend/backend.h. (go/gogo.o): Likewise. From-SVN: r171968 --- gcc/go/ChangeLog | 14 +++++ gcc/go/Make-lang.in | 4 +- gcc/go/go-gcc.cc | 94 +++++++++++++++++++++++++++++++- gcc/go/gofrontend/backend.h | 28 ++++++++++ gcc/go/gofrontend/expressions.cc | 8 ++- gcc/go/gofrontend/gogo-tree.cc | 56 ------------------- gcc/go/gofrontend/gogo.cc | 64 ++++++++++++++++++++++ gcc/go/gofrontend/gogo.h | 43 ++++++++------- gcc/go/gofrontend/statements.cc | 55 +++++++++++++------ 9 files changed, 267 insertions(+), 99 deletions(-) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index b8a11f6d5d1..657091a2449 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,17 @@ +2011-04-04 Ian Lance Taylor + + * go-gcc.c (class Blabel): Define. + (Gcc_backend::make_expression): New function. + (get_identifier_from_string): New function. + (Gcc_backend::label): New function. + (Gcc_backend::label_definition_statement): New function. + (Gcc_backend::goto_statement): New function. + (Gcc_backend::label_address): New function. + (expression_to_tree): New function. + * Make-lang.in (go/expressions.o): Depend on + go/gofrontend/backend.h. + (go/gogo.o): Likewise. + 2011-04-04 Ian Lance Taylor * go-gcc.cc: #include "tree-iterator.h", "gimple.h", and "gogo.h". diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in index 67900d77497..0dc8942061a 100644 --- a/gcc/go/Make-lang.in +++ b/gcc/go/Make-lang.in @@ -252,7 +252,7 @@ go/expressions.o: go/gofrontend/expressions.cc $(GO_SYSTEM_H) $(TOPLEV_H) \ intl.h $(TREE_H) $(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) \ realmpfr.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \ go/gofrontend/export.h $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \ - $(GO_EXPRESSIONS_H) + go/gofrontend/backend.h $(GO_EXPRESSIONS_H) go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) \ $(GO_PARSE_H) go/gofrontend/backend.h $(GO_GOGO_H) go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \ @@ -264,7 +264,7 @@ go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \ go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \ go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \ $(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_IMPORT_H) \ - go/gofrontend/export.h $(GO_GOGO_H) + go/gofrontend/export.h go/gofrontend/backend.h $(GO_GOGO_H) go/import.o: go/gofrontend/import.cc $(GO_SYSTEM_H) \ $(srcdir)/../include/filenames.h $(srcdir)/../include/simple-object.h \ $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) go/gofrontend/export.h \ diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 2785bf296dc..ee100c6e915 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -90,6 +90,14 @@ class Bfunction : public Gcc_tree { } }; +class Blabel : public Gcc_tree +{ + public: + Blabel(tree t) + : Gcc_tree(t) + { } +}; + // This file implements the interface between the Go frontend proper // and the gcc IR. This implements specific instantiations of // abstract classes defined by the Go frontend proper. The Go @@ -158,22 +166,46 @@ class Gcc_backend : public Backend // Statements. - // Create an assignment statement. Bstatement* assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location); - // Create a return statement. Bstatement* return_statement(Bfunction*, const std::vector&, source_location); + // Labels. + + Blabel* + label(Bfunction*, const std::string& name, source_location); + + Bstatement* + label_definition_statement(Blabel*); + + Bstatement* + goto_statement(Blabel*, source_location); + + Bexpression* + label_address(Blabel*, source_location); + private: + // Make a Bexpression from a tree. + Bexpression* + make_expression(tree t) + { return new Bexpression(t); } + // Make a Bstatement from a tree. Bstatement* make_statement(tree t) { return new Bstatement(t); } }; +// A helper function. + +static inline tree +get_identifier_from_string(const std::string& str) +{ + return get_identifier_with_length(str.data(), str.length()); +} // Assignment. Bstatement* @@ -249,6 +281,58 @@ Gcc_backend::return_statement(Bfunction* bfunction, return this->make_statement(ret); } +// Make a label. + +Blabel* +Gcc_backend::label(Bfunction* function, const std::string& name, + source_location location) +{ + tree decl; + if (name.empty()) + decl = create_artificial_label(location); + else + { + tree id = get_identifier_from_string(name); + decl = build_decl(location, LABEL_DECL, id, void_type_node); + DECL_CONTEXT(decl) = function->get_tree(); + } + return new Blabel(decl); +} + +// Make a statement which defines a label. + +Bstatement* +Gcc_backend::label_definition_statement(Blabel* label) +{ + tree lab = label->get_tree(); + tree ret = fold_build1_loc(DECL_SOURCE_LOCATION(lab), LABEL_EXPR, + void_type_node, lab); + return this->make_statement(ret); +} + +// Make a goto statement. + +Bstatement* +Gcc_backend::goto_statement(Blabel* label, source_location location) +{ + tree lab = label->get_tree(); + tree ret = fold_build1_loc(location, GOTO_EXPR, void_type_node, lab); + return this->make_statement(ret); +} + +// Get the address of a label. + +Bexpression* +Gcc_backend::label_address(Blabel* label, source_location location) +{ + tree lab = label->get_tree(); + TREE_USED(lab) = 1; + TREE_ADDRESSABLE(lab) = 1; + tree ret = fold_convert_loc(location, ptr_type_node, + build_fold_addr_expr_loc(location, lab)); + return this->make_expression(ret); +} + // The single backend. static Gcc_backend gcc_backend; @@ -276,6 +360,12 @@ tree_to_function(tree t) return new Bfunction(t); } +tree +expression_to_tree(Bexpression* be) +{ + return be->get_tree(); +} + tree statement_to_tree(Bstatement* bs) { diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index 959fc7862c0..814263edc22 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -27,6 +27,9 @@ class Bstatement; // The backend representation of a function definition. class Bfunction; +// The backend representation of a label. +class Blabel; + // A list of backend types. typedef std::vector Btypes; @@ -114,6 +117,30 @@ class Backend virtual Bstatement* return_statement(Bfunction*, const std::vector&, source_location) = 0; + + // Labels. + + // Create a new label. NAME will be empty if this is a label + // created by the frontend for a loop construct. The location is + // where the the label is defined. + virtual Blabel* + label(Bfunction*, const std::string& name, source_location) = 0; + + // Create a statement which defines a label. This statement will be + // put into the codestream at the point where the label should be + // defined. + virtual Bstatement* + label_definition_statement(Blabel*) = 0; + + // Create a goto statement to a label. + virtual Bstatement* + goto_statement(Blabel*, source_location) = 0; + + // Create an expression for the address of a label. This is used to + // get the return address of a deferred function which may call + // recover. + virtual Bexpression* + label_address(Blabel*, source_location) = 0; }; // The backend interface has to define this function. @@ -125,6 +152,7 @@ extern Backend* go_get_backend(); extern Bexpression* tree_to_expr(tree); extern Bfunction* tree_to_function(tree); +extern tree expression_to_tree(Bexpression*); extern tree statement_to_tree(Bstatement*); #endif // !defined(GO_BACKEND_H) diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index a0cfcfcdf74..afd2191e857 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -33,6 +33,7 @@ extern "C" #include "import.h" #include "statements.h" #include "lex.h" +#include "backend.h" #include "expressions.h" // Class Expression. @@ -12595,8 +12596,11 @@ class Label_addr_expression : public Expression { return new Label_addr_expression(this->label_, this->location()); } tree - do_get_tree(Translate_context*) - { return this->label_->get_addr(this->location()); } + do_get_tree(Translate_context* context) + { + return expression_to_tree(this->label_->get_addr(context, + this->location())); + } private: // The label whose address we are taking. diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc index bd5945bd7ba..53e43c7b519 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -1915,62 +1915,6 @@ Block::get_tree(Translate_context* context) return bind; } -// Get the LABEL_DECL for a label. - -tree -Label::get_decl() -{ - if (this->decl_ == NULL) - { - tree id = get_identifier_from_string(this->name_); - this->decl_ = build_decl(this->location_, LABEL_DECL, id, void_type_node); - DECL_CONTEXT(this->decl_) = current_function_decl; - } - return this->decl_; -} - -// Return an expression for the address of this label. - -tree -Label::get_addr(source_location location) -{ - tree decl = this->get_decl(); - TREE_USED(decl) = 1; - TREE_ADDRESSABLE(decl) = 1; - return fold_convert_loc(location, ptr_type_node, - build_fold_addr_expr_loc(location, decl)); -} - -// Get the LABEL_DECL for an unnamed label. - -tree -Unnamed_label::get_decl() -{ - if (this->decl_ == NULL) - this->decl_ = create_artificial_label(this->location_); - return this->decl_; -} - -// Get the LABEL_EXPR for an unnamed label. - -tree -Unnamed_label::get_definition() -{ - tree t = build1(LABEL_EXPR, void_type_node, this->get_decl()); - SET_EXPR_LOCATION(t, this->location_); - return t; -} - -// Return a goto to this label. - -tree -Unnamed_label::get_goto(source_location location) -{ - tree t = build1(GOTO_EXPR, void_type_node, this->get_decl()); - SET_EXPR_LOCATION(t, location); - return t; -} - // Return the integer type to use for a size. GO_EXTERN_C diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 5b3ac8cd9c2..31549ac233a 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -15,6 +15,7 @@ #include "dataflow.h" #include "import.h" #include "export.h" +#include "backend.h" #include "gogo.h" // Class Gogo. @@ -4430,6 +4431,69 @@ Bindings::traverse(Traverse* traverse, bool is_global) return TRAVERSE_CONTINUE; } +// Class Label. + +// Get the backend representation for a label. + +Blabel* +Label::get_backend_label(Translate_context* context) +{ + if (this->blabel_ == NULL) + { + Function* function = context->function()->func_value(); + tree fndecl = function->get_decl(); + Bfunction* bfunction = tree_to_function(fndecl); + this->blabel_ = context->backend()->label(bfunction, this->name_, + this->location_); + } + return this->blabel_; +} + +// Return an expression for the address of this label. + +Bexpression* +Label::get_addr(Translate_context* context, source_location location) +{ + Blabel* label = this->get_backend_label(context); + return context->backend()->label_address(label, location); +} + +// Class Unnamed_label. + +// Get the backend representation for an unnamed label. + +Blabel* +Unnamed_label::get_blabel(Translate_context* context) +{ + if (this->blabel_ == NULL) + { + Function* function = context->function()->func_value(); + tree fndecl = function->get_decl(); + Bfunction* bfunction = tree_to_function(fndecl); + this->blabel_ = context->backend()->label(bfunction, "", + this->location_); + } + return this->blabel_; +} + +// Return a statement which defines this unnamed label. + +Bstatement* +Unnamed_label::get_definition(Translate_context* context) +{ + Blabel* blabel = this->get_blabel(context); + return context->backend()->label_definition_statement(blabel); +} + +// Return a goto statement to this unnamed label. + +Bstatement* +Unnamed_label::get_goto(Translate_context* context, source_location location) +{ + Blabel* blabel = this->get_blabel(context); + return context->backend()->goto_statement(blabel, location); +} + // Class Package. Package::Package(const std::string& name, const std::string& unique_prefix, diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 87e2da6890b..cf126cdc282 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -40,6 +40,9 @@ class Translate_context; class Backend; class Export; class Import; +class Bexpression; +class Bstatement; +class Blabel; // This file declares the basic classes used to hold the internal // representation of Go which is built by the parser. @@ -2115,7 +2118,7 @@ class Label { public: Label(const std::string& name) - : name_(name), location_(0), is_used_(false), decl_(NULL) + : name_(name), location_(0), is_used_(false), blabel_(NULL) { } // Return the label's name. @@ -2151,13 +2154,15 @@ class Label this->location_ = location; } - // Return the LABEL_DECL for this decl. - tree - get_decl(); + // Return the backend representation for this label. + Blabel* + get_backend_label(Translate_context*); - // Return an expression for the address of this label. - tree - get_addr(source_location location); + // Return an expression for the address of this label. This is used + // to get the return address of a deferred function to see whether + // the function may call recover. + Bexpression* + get_addr(Translate_context*, source_location location); private: // The name of the label. @@ -2167,8 +2172,8 @@ class Label source_location location_; // Whether the label has been used. bool is_used_; - // The LABEL_DECL. - tree decl_; + // The backend representation. + Blabel* blabel_; }; // An unnamed label. These are used when lowering loops. @@ -2177,7 +2182,7 @@ class Unnamed_label { public: Unnamed_label(source_location location) - : location_(location), decl_(NULL) + : location_(location), blabel_(NULL) { } // Get the location where the label is defined. @@ -2191,22 +2196,22 @@ class Unnamed_label { this->location_ = location; } // Return a statement which defines this label. - tree - get_definition(); + Bstatement* + get_definition(Translate_context*); // Return a goto to this label from LOCATION. - tree - get_goto(source_location location); + Bstatement* + get_goto(Translate_context*, source_location location); private: - // Return the LABEL_DECL to use with GOTO_EXPR. - tree - get_decl(); + // Return the backend representation. + Blabel* + get_blabel(Translate_context*); // The location where the label is defined. source_location location_; - // The LABEL_DECL. - tree decl_; + // The backend representation of this label. + Blabel* blabel_; }; // An imported package. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 3783fb83a51..854b329d9ec 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -2619,8 +2619,11 @@ class Bc_statement : public Statement { return false; } tree - do_get_tree(Translate_context*) - { return this->label_->get_goto(this->location()); } + do_get_tree(Translate_context* context) + { + return statement_to_tree(this->label_->get_goto(context, + this->location())); + } private: // The label that this branches to. @@ -2692,9 +2695,12 @@ Goto_statement::do_check_types(Gogo*) // Return the tree for the goto statement. tree -Goto_statement::do_get_tree(Translate_context*) +Goto_statement::do_get_tree(Translate_context* context) { - return this->build_stmt_1(GOTO_EXPR, this->label_->get_decl()); + Blabel* blabel = this->label_->get_backend_label(context); + Bstatement* statement = context->backend()->goto_statement(blabel, + this->location()); + return statement_to_tree(statement); } // Make a goto statement. @@ -2725,8 +2731,11 @@ class Goto_unnamed_statement : public Statement { return false; } tree - do_get_tree(Translate_context*) - { return this->label_->get_goto(this->location()); } + do_get_tree(Translate_context* context) + { + return statement_to_tree(this->label_->get_goto(context, + this->location())); + } private: Unnamed_label* label_; @@ -2754,9 +2763,12 @@ Label_statement::do_traverse(Traverse*) // Return a tree defining this label. tree -Label_statement::do_get_tree(Translate_context*) +Label_statement::do_get_tree(Translate_context* context) { - return this->build_stmt_1(LABEL_EXPR, this->label_->get_decl()); + Blabel* blabel = this->label_->get_backend_label(context); + Bstatement* statement; + statement = context->backend()->label_definition_statement(blabel); + return statement_to_tree(statement); } // Make a label statement. @@ -2783,8 +2795,8 @@ class Unnamed_label_statement : public Statement { return TRAVERSE_CONTINUE; } tree - do_get_tree(Translate_context*) - { return this->label_->get_definition(); } + do_get_tree(Translate_context* context) + { return statement_to_tree(this->label_->get_definition(context)); } private: // The label. @@ -3134,7 +3146,10 @@ Case_clauses::Case_clause::get_constant_tree(Translate_context* context, } if (!this->is_fallthrough_) - append_to_statement_list(break_label->get_goto(this->location_), stmt_list); + { + Bstatement* g = break_label->get_goto(context, this->location_); + append_to_statement_list(statement_to_tree(g), stmt_list); + } } // Class Case_clauses. @@ -3387,7 +3402,8 @@ Constant_switch_statement::do_get_tree(Translate_context* context) SET_EXPR_LOCATION(s, this->location()); append_to_statement_list(s, &stmt_list); - append_to_statement_list(break_label->get_definition(), &stmt_list); + Bstatement* ldef = break_label->get_definition(context); + append_to_statement_list(statement_to_tree(ldef), &stmt_list); return stmt_list; } @@ -4245,7 +4261,8 @@ Select_clauses::get_tree(Translate_context* context, tree stmt_list = NULL_TREE; append_to_statement_list(default_clause->get_statements_tree(context), &stmt_list); - append_to_statement_list(break_label->get_definition(), &stmt_list); + Bstatement* ldef = break_label->get_definition(context); + append_to_statement_list(statement_to_tree(ldef), &stmt_list); return stmt_list; } @@ -4336,7 +4353,8 @@ Select_clauses::get_tree(Translate_context* context, } } - append_to_statement_list(break_label->get_definition(), &stmt_list); + Bstatement* ldef = break_label->get_definition(context); + append_to_statement_list(statement_to_tree(ldef), &stmt_list); tree switch_stmt = build3(SWITCH_EXPR, sizetype, call, stmt_list, NULL_TREE); SET_EXPR_LOCATION(switch_stmt, location); @@ -4358,10 +4376,11 @@ Select_clauses::add_clause_tree(Translate_context* context, int case_index, NULL_TREE, label), stmt_list); append_to_statement_list(clause->get_statements_tree(context), stmt_list); - tree g = bottom_label->get_goto(clause->statements() == NULL - ? clause->location() - : clause->statements()->end_location()); - append_to_statement_list(g, stmt_list); + source_location gloc = (clause->statements() == NULL + ? clause->location() + : clause->statements()->end_location()); + Bstatement* g = bottom_label->get_goto(context, gloc); + append_to_statement_list(statement_to_tree(g), stmt_list); } // Class Select_statement. -- 2.30.2