aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/go-gcc.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2011-04-19 18:20:05 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-04-19 18:20:05 +0000
commit5ad7db5fa38f86e095645296a5c1832fa088aa84 (patch)
treebd78a56617f782bc1b6bc7acb061e27f107b8285 /gcc/go/go-gcc.cc
parentf7d2e5d418d88cccfd1d54daebd57de464d9bd92 (diff)
downloadgcc-5ad7db5fa38f86e095645296a5c1832fa088aa84.zip
gcc-5ad7db5fa38f86e095645296a5c1832fa088aa84.tar.gz
gcc-5ad7db5fa38f86e095645296a5c1832fa088aa84.tar.bz2
Use backend interface for blocks.
* go-gcc.cc (class Bblock): Define. (Gcc_backend::if_statement): Change then_block and else_block to Bblock*. (Gcc_backend::block): New function. (Gcc_backend::block_add_statements): New function. (Gcc_backend::block_statement): New function. (tree_to_block, block_to_tree): New functions. From-SVN: r172731
Diffstat (limited to 'gcc/go/go-gcc.cc')
-rw-r--r--gcc/go/go-gcc.cc149
1 files changed, 145 insertions, 4 deletions
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index e4f4cfc..46c149c 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -92,6 +92,14 @@ class Bfunction : public Gcc_tree
{ }
};
+class Bblock : public Gcc_tree
+{
+ public:
+ Bblock(tree t)
+ : Gcc_tree(t)
+ { }
+};
+
class Bvariable : public Gcc_tree
{
public:
@@ -194,8 +202,8 @@ class Gcc_backend : public Backend
source_location);
Bstatement*
- if_statement(Bexpression* condition, Bstatement* then_block,
- Bstatement* else_block, source_location);
+ if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
+ source_location);
Bstatement*
switch_statement(Bexpression* value,
@@ -209,6 +217,18 @@ class Gcc_backend : public Backend
Bstatement*
statement_list(const std::vector<Bstatement*>&);
+ // Blocks.
+
+ Bblock*
+ block(Bfunction*, Bblock*, const std::vector<Bvariable*>&,
+ source_location, source_location);
+
+ void
+ block_add_statements(Bblock*, const std::vector<Bstatement*>&);
+
+ Bstatement*
+ block_statement(Bblock*);
+
// Variables.
Bvariable*
@@ -370,8 +390,8 @@ Gcc_backend::return_statement(Bfunction* bfunction,
// If.
Bstatement*
-Gcc_backend::if_statement(Bexpression* condition, Bstatement* then_block,
- Bstatement* else_block, source_location location)
+Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
+ Bblock* else_block, source_location location)
{
tree cond_tree = condition->get_tree();
tree then_tree = then_block->get_tree();
@@ -481,6 +501,114 @@ Gcc_backend::statement_list(const std::vector<Bstatement*>& statements)
return this->make_statement(stmt_list);
}
+// Make a block. For some reason gcc uses a dual structure for
+// blocks: BLOCK tree nodes and BIND_EXPR tree nodes. Since the
+// BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in
+// the Bblock.
+
+Bblock*
+Gcc_backend::block(Bfunction* function, Bblock* enclosing,
+ const std::vector<Bvariable*>& vars,
+ source_location start_location,
+ source_location)
+{
+ tree block_tree = make_node(BLOCK);
+ if (enclosing == NULL)
+ {
+ // FIXME: Permitting FUNCTION to be NULL is a temporary measure
+ // until we have a proper representation of the init function.
+ tree fndecl;
+ if (function == NULL)
+ fndecl = current_function_decl;
+ else
+ fndecl = function->get_tree();
+ gcc_assert(fndecl != NULL_TREE);
+
+ // We may have already created a block for local variables when
+ // we take the address of a parameter.
+ if (DECL_INITIAL(fndecl) == NULL_TREE)
+ {
+ BLOCK_SUPERCONTEXT(block_tree) = fndecl;
+ DECL_INITIAL(fndecl) = block_tree;
+ }
+ else
+ {
+ tree superblock_tree = DECL_INITIAL(fndecl);
+ BLOCK_SUPERCONTEXT(block_tree) = superblock_tree;
+ tree* pp;
+ for (pp = &BLOCK_SUBBLOCKS(superblock_tree);
+ *pp != NULL_TREE;
+ pp = &BLOCK_CHAIN(*pp))
+ ;
+ *pp = block_tree;
+ }
+ }
+ else
+ {
+ tree superbind_tree = enclosing->get_tree();
+ tree superblock_tree = BIND_EXPR_BLOCK(superbind_tree);
+ gcc_assert(TREE_CODE(superblock_tree) == BLOCK);
+
+ BLOCK_SUPERCONTEXT(block_tree) = superblock_tree;
+ tree* pp;
+ for (pp = &BLOCK_SUBBLOCKS(superblock_tree);
+ *pp != NULL_TREE;
+ pp = &BLOCK_CHAIN(*pp))
+ ;
+ *pp = block_tree;
+ }
+
+ tree* pp = &BLOCK_VARS(block_tree);
+ for (std::vector<Bvariable*>::const_iterator pv = vars.begin();
+ pv != vars.end();
+ ++pv)
+ {
+ *pp = (*pv)->get_tree();
+ if (*pp != error_mark_node)
+ pp = &DECL_CHAIN(*pp);
+ }
+ *pp = NULL_TREE;
+
+ TREE_USED(block_tree) = 1;
+
+ tree bind_tree = build3_loc(start_location, BIND_EXPR, void_type_node,
+ BLOCK_VARS(block_tree), NULL_TREE, block_tree);
+ TREE_SIDE_EFFECTS(bind_tree) = 1;
+
+ return new Bblock(bind_tree);
+}
+
+// Add statements to a block.
+
+void
+Gcc_backend::block_add_statements(Bblock* bblock,
+ const std::vector<Bstatement*>& statements)
+{
+ tree stmt_list = NULL_TREE;
+ for (std::vector<Bstatement*>::const_iterator p = statements.begin();
+ p != statements.end();
+ ++p)
+ {
+ tree s = (*p)->get_tree();
+ if (s != error_mark_node)
+ append_to_statement_list(s, &stmt_list);
+ }
+
+ tree bind_tree = bblock->get_tree();
+ gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR);
+ BIND_EXPR_BODY(bind_tree) = stmt_list;
+}
+
+// Return a block as a statement.
+
+Bstatement*
+Gcc_backend::block_statement(Bblock* bblock)
+{
+ tree bind_tree = bblock->get_tree();
+ gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR);
+ return this->make_statement(bind_tree);
+}
+
// Make a global variable.
Bvariable*
@@ -665,6 +793,13 @@ tree_to_function(tree t)
return new Bfunction(t);
}
+Bblock*
+tree_to_block(tree t)
+{
+ gcc_assert(TREE_CODE(t) == BIND_EXPR);
+ return new Bblock(t);
+}
+
tree
expr_to_tree(Bexpression* be)
{
@@ -678,6 +813,12 @@ stat_to_tree(Bstatement* bs)
}
tree
+block_to_tree(Bblock* bb)
+{
+ return bb->get_tree();
+}
+
+tree
var_to_tree(Bvariable* bv)
{
return bv->get_tree();