aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/go-gcc.cc
diff options
context:
space:
mode:
authorChris Manghane <cmang@google.com>2014-04-26 03:38:34 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-04-26 03:38:34 +0000
commit036165d8116610b18861941fed4080a93783f954 (patch)
tree93a36b3f34bf901b1b63907441f2986c34fe7d4e /gcc/go/go-gcc.cc
parent10695c6a1da3fef02b6842f10b8586ad38a94763 (diff)
downloadgcc-036165d8116610b18861941fed4080a93783f954.zip
gcc-036165d8116610b18861941fed4080a93783f954.tar.gz
gcc-036165d8116610b18861941fed4080a93783f954.tar.bz2
compiler: Use backend interface for defining global declarations.
* go-gcc.cc: Include "cgraph.h" and "gimplify.h". (Gcc_backend::return_statement): Push and pop function. (Gcc_backend::label): Likewise. (Gcc_backend::function_defer_statement): Likewise. (Gcc_backend::switch_statement): Add function parameter. (Gcc_backend::block): Don't permit function to be NULL. (Gcc_backend::temporary_variable): Change go_assert to gcc_assert. (Gcc_backend::gc_root_variable): New function. (Gcc_backend::write_global_definitions): New function. From-SVN: r209819
Diffstat (limited to 'gcc/go/go-gcc.cc')
-rw-r--r--gcc/go/go-gcc.cc168
1 files changed, 155 insertions, 13 deletions
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 376e4dc..499b670 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -29,9 +29,11 @@
#include "stor-layout.h"
#include "varasm.h"
#include "tree-iterator.h"
+#include "cgraph.h"
#include "convert.h"
#include "basic-block.h"
#include "gimple-expr.h"
+#include "gimplify.h"
#include "toplev.h"
#include "output.h"
#include "real.h"
@@ -317,7 +319,7 @@ class Gcc_backend : public Backend
Location);
Bstatement*
- switch_statement(Bexpression* value,
+ switch_statement(Bfunction* function, Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
Location);
@@ -376,6 +378,9 @@ class Gcc_backend : public Backend
Location, Bstatement**);
Bvariable*
+ gc_root_variable(Btype*, Bexpression*);
+
+ Bvariable*
immutable_struct(const std::string&, bool, bool, Btype*, Location);
void
@@ -420,6 +425,12 @@ class Gcc_backend : public Backend
bool
function_set_body(Bfunction* function, Bstatement* code_stmt);
+ void
+ write_global_definitions(const std::vector<Btype*>&,
+ const std::vector<Bexpression*>&,
+ const std::vector<Bfunction*>&,
+ const std::vector<Bvariable*>&);
+
private:
// Make a Bexpression from a tree.
Bexpression*
@@ -1709,6 +1720,7 @@ Gcc_backend::return_statement(Bfunction* bfunction,
tree result = DECL_RESULT(fntree);
if (result == error_mark_node)
return this->error_statement();
+
tree ret;
if (vals.empty())
ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, void_type_node,
@@ -1732,7 +1744,14 @@ Gcc_backend::return_statement(Bfunction* bfunction,
// statement.
tree stmt_list = NULL_TREE;
tree rettype = TREE_TYPE(result);
+
+ if (DECL_STRUCT_FUNCTION(fntree) == NULL)
+ push_struct_function(fntree);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(fntree));
tree rettmp = create_tmp_var(rettype, "RESULT");
+ pop_cfun();
+
tree field = TYPE_FIELDS(rettype);
for (std::vector<Bexpression*>::const_iterator p = vals.begin();
p != vals.end();
@@ -1818,6 +1837,7 @@ Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
Bstatement*
Gcc_backend::switch_statement(
+ Bfunction* function,
Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
@@ -1825,6 +1845,12 @@ Gcc_backend::switch_statement(
{
gcc_assert(cases.size() == statements.size());
+ tree decl = function->get_tree();
+ if (DECL_STRUCT_FUNCTION(decl) == NULL)
+ push_struct_function(decl);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(decl));
+
tree stmt_list = NULL_TREE;
std::vector<std::vector<Bexpression*> >::const_iterator pc = cases.begin();
for (std::vector<Bstatement*>::const_iterator ps = statements.begin();
@@ -1864,6 +1890,7 @@ Gcc_backend::switch_statement(
append_to_statement_list(t, &stmt_list);
}
}
+ pop_cfun();
tree tv = value->get_tree();
if (tv == error_mark_node)
@@ -1922,13 +1949,7 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing,
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();
+ tree fndecl = function->get_tree();
gcc_assert(fndecl != NULL_TREE);
// We may have already created a block for local variables when
@@ -1982,7 +2003,6 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing,
void_type_node, BLOCK_VARS(block_tree),
NULL_TREE, block_tree);
TREE_SIDE_EFFECTS(bind_tree) = 1;
-
return new Bblock(bind_tree);
}
@@ -2214,7 +2234,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
return this->error_variable();
}
- go_assert(function != NULL);
+ gcc_assert(function != NULL);
tree decl = function->get_tree();
tree var;
@@ -2263,6 +2283,28 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
return new Bvariable(var);
}
+// Make a GC root variable.
+
+Bvariable*
+Gcc_backend::gc_root_variable(Btype* type, Bexpression* init)
+{
+ tree type_tree = type->get_tree();
+ tree init_tree = init->get_tree();
+ if (type_tree == error_mark_node || init_tree == error_mark_node)
+ return this->error_variable();
+
+ tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
+ create_tmp_var_name("gc"), type_tree);
+ DECL_EXTERNAL(decl) = 0;
+ TREE_PUBLIC(decl) = 0;
+ TREE_STATIC(decl) = 1;
+ DECL_ARTIFICIAL(decl) = 1;
+ DECL_INITIAL(decl) = init_tree;
+ rest_of_decl_compilation(decl, 1, 0);
+
+ return new Bvariable(decl);
+}
+
// Create a named immutable initialized data structure.
Bvariable*
@@ -2277,9 +2319,9 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
get_identifier_from_string(name),
build_qualified_type(type_tree, TYPE_QUAL_CONST));
TREE_STATIC(decl) = 1;
+ TREE_USED(decl) = 1;
TREE_READONLY(decl) = 1;
TREE_CONSTANT(decl) = 1;
- TREE_USED(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
if (!is_hidden)
TREE_PUBLIC(decl) = 1;
@@ -2369,7 +2411,17 @@ Gcc_backend::label(Bfunction* function, const std::string& name,
{
tree decl;
if (name.empty())
- decl = create_artificial_label(location.gcc_location());
+ {
+ tree func_tree = function->get_tree();
+ if (DECL_STRUCT_FUNCTION(func_tree) == NULL)
+ push_struct_function(func_tree);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(func_tree));
+
+ decl = create_artificial_label(location.gcc_location());
+
+ pop_cfun();
+ }
else
{
tree id = get_identifier_from_string(name);
@@ -2477,11 +2529,18 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer,
{
tree undefer_tree = undefer->get_tree();
tree defer_tree = defer->get_tree();
+ tree fntree = function->get_tree();
if (undefer_tree == error_mark_node
- || defer_tree == error_mark_node)
+ || defer_tree == error_mark_node
+ || fntree == error_mark_node)
return this->error_statement();
+ if (DECL_STRUCT_FUNCTION(fntree) == NULL)
+ push_struct_function(fntree);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(fntree));
+
tree stmt_list = NULL;
Blabel* blabel = this->label(function, "", location);
Bstatement* label_def = this->label_definition_statement(blabel);
@@ -2494,6 +2553,7 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer,
tree try_catch =
build2(TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body);
append_to_statement_list(try_catch, &stmt_list);
+ pop_cfun();
return this->make_statement(stmt_list);
}
@@ -2538,6 +2598,88 @@ Gcc_backend::function_set_body(Bfunction* function, Bstatement* code_stmt)
return true;
}
+// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
+// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
+
+void
+Gcc_backend::write_global_definitions(
+ const std::vector<Btype*>& type_decls,
+ const std::vector<Bexpression*>& constant_decls,
+ const std::vector<Bfunction*>& function_decls,
+ const std::vector<Bvariable*>& variable_decls)
+{
+ size_t count_definitions = type_decls.size() + constant_decls.size()
+ + function_decls.size() + variable_decls.size();
+
+ tree* defs = new tree[count_definitions];
+
+ // Convert all non-erroneous declarations into Gimple form.
+ size_t i = 0;
+ for (std::vector<Bvariable*>::const_iterator p = variable_decls.begin();
+ p != variable_decls.end();
+ ++p)
+ {
+ if ((*p)->get_tree() != error_mark_node)
+ {
+ defs[i] = (*p)->get_tree();
+ go_preserve_from_gc(defs[i]);
+ ++i;
+ }
+ }
+
+ for (std::vector<Btype*>::const_iterator p = type_decls.begin();
+ p != type_decls.end();
+ ++p)
+ {
+ tree type_tree = (*p)->get_tree();
+ if (type_tree != error_mark_node
+ && IS_TYPE_OR_DECL_P(type_tree))
+ {
+ defs[i] = TYPE_NAME(type_tree);
+ gcc_assert(defs[i] != NULL);
+ go_preserve_from_gc(defs[i]);
+ ++i;
+ }
+ }
+ for (std::vector<Bexpression*>::const_iterator p = constant_decls.begin();
+ p != constant_decls.end();
+ ++p)
+ {
+ if ((*p)->get_tree() != error_mark_node)
+ {
+ defs[i] = (*p)->get_tree();
+ go_preserve_from_gc(defs[i]);
+ ++i;
+ }
+ }
+ for (std::vector<Bfunction*>::const_iterator p = function_decls.begin();
+ p != function_decls.end();
+ ++p)
+ {
+ tree decl = (*p)->get_tree();
+ if (decl != error_mark_node)
+ {
+ go_preserve_from_gc(decl);
+ gimplify_function_tree(decl);
+ cgraph_finalize_function(decl, true);
+
+ defs[i] = decl;
+ ++i;
+ }
+ }
+
+ // Pass everything back to the middle-end.
+
+ wrapup_global_declarations(defs, i);
+
+ finalize_compilation_unit();
+
+ check_global_declarations(defs, i);
+ emit_debug_global_declarations(defs, i);
+
+ delete[] defs;
+}
+
// The single backend.
static Gcc_backend gcc_backend;