diff options
author | Ian Lance Taylor <iant@google.com> | 2011-04-04 23:19:09 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-04-04 23:19:09 +0000 |
commit | 9403944776d0a804dbb1253430633d04aef74c51 (patch) | |
tree | 8d44210d8783d83e459d812c1f0df7bd37abb3c8 /gcc/go/go-gcc.cc | |
parent | 69387b92c18aa7fe8d29aa7788ae838a027b5d48 (diff) | |
download | gcc-9403944776d0a804dbb1253430633d04aef74c51.zip gcc-9403944776d0a804dbb1253430633d04aef74c51.tar.gz gcc-9403944776d0a804dbb1253430633d04aef74c51.tar.bz2 |
Use backend interface for return statements.
* go-gcc.cc: #include "tree-iterator.h", "gimple.h", and "gogo.h".
(class Bfunction): Define.
(Gcc_backend::assignment_statement): Rename from assignment.
Check for errors.
(Gcc_backend::return_statement): New function.
(tree_to_function): New function.
* Make-lang.in (go/go-gcc.o): Depend on tree-iterator.h,
$(GIMPLE_H), and $(GO_GOGO_H).
From-SVN: r171959
Diffstat (limited to 'gcc/go/go-gcc.cc')
-rw-r--r-- | gcc/go/go-gcc.cc | 96 |
1 files changed, 90 insertions, 6 deletions
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index ca2d63b..2785bf2 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -30,11 +30,14 @@ extern "C" #endif #include "tree.h" +#include "tree-iterator.h" +#include "gimple.h" #ifndef ENABLE_BUILD_WITH_CXX } #endif +#include "gogo.h" #include "backend.h" // A class wrapping a tree. @@ -79,6 +82,14 @@ class Bstatement : public Gcc_tree { } }; +class Bfunction : public Gcc_tree +{ + public: + Bfunction(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 @@ -149,8 +160,12 @@ class Gcc_backend : public Backend // Create an assignment statement. Bstatement* - assignment(Bexpression* lhs, Bexpression* rhs, - source_location location); + assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location); + + // Create a return statement. + Bstatement* + return_statement(Bfunction*, const std::vector<Bexpression*>&, + source_location); private: // Make a Bstatement from a tree. @@ -162,13 +177,76 @@ class Gcc_backend : public Backend // Assignment. Bstatement* -Gcc_backend::assignment(Bexpression* lhs, Bexpression* rhs, - source_location location) +Gcc_backend::assignment_statement(Bexpression* lhs, Bexpression* rhs, + source_location location) { + tree lhs_tree = lhs->get_tree(); + tree rhs_tree = rhs->get_tree(); + if (lhs_tree == error_mark_node || rhs_tree == error_mark_node) + return this->make_statement(error_mark_node); return this->make_statement(fold_build2_loc(location, MODIFY_EXPR, void_type_node, - lhs->get_tree(), - rhs->get_tree())); + lhs_tree, rhs_tree)); +} + +// Return. + +Bstatement* +Gcc_backend::return_statement(Bfunction* bfunction, + const std::vector<Bexpression*>& vals, + source_location location) +{ + tree fntree = bfunction->get_tree(); + if (fntree == error_mark_node) + return this->make_statement(error_mark_node); + tree result = DECL_RESULT(fntree); + if (result == error_mark_node) + return this->make_statement(error_mark_node); + tree ret; + if (vals.empty()) + ret = fold_build1_loc(location, RETURN_EXPR, void_type_node, NULL_TREE); + else if (vals.size() == 1) + { + tree val = vals.front()->get_tree(); + if (val == error_mark_node) + return this->make_statement(error_mark_node); + tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node, + result, vals.front()->get_tree()); + ret = fold_build1_loc(location, RETURN_EXPR, void_type_node, set); + } + else + { + // To return multiple values, copy the values into a temporary + // variable of the right structure type, and then assign the + // temporary variable to the DECL_RESULT in the return + // statement. + tree stmt_list = NULL_TREE; + tree rettype = TREE_TYPE(result); + tree rettmp = create_tmp_var(rettype, "RESULT"); + tree field = TYPE_FIELDS(rettype); + for (std::vector<Bexpression*>::const_iterator p = vals.begin(); + p != vals.end(); + p++, field = DECL_CHAIN(field)) + { + gcc_assert(field != NULL_TREE); + tree ref = fold_build3_loc(location, COMPONENT_REF, TREE_TYPE(field), + rettmp, field, NULL_TREE); + tree val = (*p)->get_tree(); + if (val == error_mark_node) + return this->make_statement(error_mark_node); + tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node, + ref, (*p)->get_tree()); + append_to_statement_list(set, &stmt_list); + } + gcc_assert(field == NULL_TREE); + tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node, + result, rettmp); + tree ret_expr = fold_build1_loc(location, RETURN_EXPR, void_type_node, + set); + append_to_statement_list(ret_expr, &stmt_list); + ret = stmt_list; + } + return this->make_statement(ret); } // The single backend. @@ -192,6 +270,12 @@ tree_to_expr(tree t) return new Bexpression(t); } +Bfunction* +tree_to_function(tree t) +{ + return new Bfunction(t); +} + tree statement_to_tree(Bstatement* bs) { |