aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/go-gcc.cc
diff options
context:
space:
mode:
authorChris Manghane <cmang@google.com>2014-04-14 22:43:47 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-04-14 22:43:47 +0000
commit7035307e8f5291aa613c07f49f899444b9e65c80 (patch)
treeb131f3f58afbe5406406926c7d499bebab24fdf2 /gcc/go/go-gcc.cc
parent88f592e3f4117e5da3da84f9bd2b1da8c4bc9a99 (diff)
downloadgcc-7035307e8f5291aa613c07f49f899444b9e65c80.zip
gcc-7035307e8f5291aa613c07f49f899444b9e65c80.tar.gz
gcc-7035307e8f5291aa613c07f49f899444b9e65c80.tar.bz2
Sync to current external repository.
user: Ian Lance Taylor <iant@golang.org> date: Thu Apr 10 09:25:24 2014 -0700 files: go/expressions.cc description: compiler: add checks for constant overflow Prevent extremely large constants from eating all of memory. user: Chris Manghane <cmang@golang.org> date: Mon Apr 07 16:57:09 2014 -0700 files: go/gogo-tree.cc go/gogo.cc go/gogo.h go/statements.cc description: compiler: Use backend interface for variable initialization. user: Chris Manghane <cmang@golang.org> date: Thu Apr 03 19:56:05 2014 -0700 files: go/backend.h go/gogo-tree.cc go/gogo.cc go/gogo.h description: compiler: Use backend interface to build function code. changeset: 1269:6e30875d539e user: Chris Manghane <cmang@golang.org> date: Wed Apr 02 13:16:00 2014 -0700 files: go/backend.h go/gogo-tree.cc go/gogo.cc go/gogo.h description: compiler: Use backend interface for building function defer wrappers. user: Chris Manghane <cmang@golang.org> date: Mon Mar 31 12:42:49 2014 -0700 files: go/expressions.cc go/gogo-tree.cc go/gogo.cc go/gogo.h description: compiler: Use backend interface for memory allocation. user: Chris Manghane <cmang@golang.org> date: Thu Mar 27 14:22:49 2014 -0700 files: go/backend.h go/expressions.cc go/expressions.h description: compiler: Use backend interface for fixed array construction. user: Chris Manghane <cmang@golang.org> date: Mon Mar 17 21:25:04 2014 -0700 files: go/expressions.cc description: compiler: Check for loops in self-referential array types. Fixes issue 7525. user: Chris Manghane <cmang@golang.org> date: Mon Mar 17 14:31:59 2014 -0700 files: go/gogo.cc go/parse.cc description: compiler: Don't declare blank labels. Fixes issue 7539. user: Chris Manghane <cmang@golang.org> date: Mon Mar 17 13:12:32 2014 -0700 files: go/backend.h go/expressions.cc go/expressions.h go/runtime.def description: compiler: Use backend interface for call expressions. user: Chris Manghane <cmang@golang.org> date: Wed Mar 12 13:34:27 2014 -0700 files: go/expressions.cc go/expressions.h go/gogo-tree.cc go/statements.cc description: compiler: Use backend interface map construction. user: Chris Manghane <cmang@golang.org> date: Tue Mar 11 12:53:06 2014 -0700 files: go/backend.h go/expressions.cc go/gogo-tree.cc go/gogo.h description: compiler: Use backend interface for string expressions. user: Chris Manghane <cmang@golang.org> date: Sat Mar 08 15:56:59 2014 -0800 files: go/backend.h go/expressions.cc go/expressions.h description: compiler: Use backend interface for array and string indexing. user: Chris Manghane <cmang@golang.org> date: Fri Mar 07 16:02:18 2014 -0800 files: go/expressions.cc description: compiler: Use backend interface for constant expressions. user: Chris Manghane <cmang@golang.org> date: Thu Mar 06 16:00:18 2014 -0800 files: go/expressions.cc description: compiler: Use backend interface for struct construction. user: Chris Manghane <cmang@golang.org> date: Wed Mar 05 13:09:37 2014 -0800 files: go/expressions.cc description: compiler: Use backend interface for type conversions. user: Chris Manghane <cmang@golang.org> date: Tue Mar 04 07:03:47 2014 -0800 files: go/expressions.cc go/expressions.h go/gogo-tree.cc go/gogo.h go/runtime.def libgo/runtime/chan.c description: compiler: Use backend interface for channel receive. user: Chris Manghane <cmang@golang.org> date: Mon Mar 03 15:18:57 2014 -0800 files: go/backend.h go/expressions.cc go/runtime.def description: compiler: Use backend interface for builtin calls. user: Chris Manghane <cmang@golang.org> date: Mon Mar 03 07:44:35 2014 -0800 files: go/expressions.cc go/expressions.h go/types.cc go/types.h description: compiler: Use backend interface for string info. user: Chris Manghane <cmang@golang.org> date: Fri Feb 28 10:45:55 2014 -0800 files: go/expressions.cc go/expressions.h go/gogo-tree.cc go/statements.cc description: compiler: Use backend interface for map indexing. user: Chris Manghane <cmang@golang.org> date: Wed Feb 26 14:13:10 2014 -0800 files: go/expressions.cc go/expressions.h description: compiler: Use backend interface for slice value expressions. user: Chris Manghane <cmang@golang.org> date: Wed Feb 26 13:12:19 2014 -0800 files: go/backend.h go/expressions.cc go/expressions.h go/gogo-tree.cc go/runtime.def go/statements.cc description: compiler: Use backend interface for interface values. user: Chris Manghane <cmang@golang.org> date: Mon Feb 24 12:30:13 2014 -0800 files: go/expressions.cc go/expressions.h go/parse.cc go/statements.cc description: compiler: Change Heap_composite_expression to Heap_expression. user: Chris Manghane <cmang@golang.org> date: Thu Feb 20 19:47:06 2014 -0800 files: go/expressions.cc go/expressions.h go/gogo-tree.cc go/gogo.cc go/gogo.h go/types.cc go/types.h description: compiler: Use backend interface for interface method table expressions. user: Chris Manghane <cmang@golang.org> date: Mon Feb 03 14:36:20 2014 -0800 files: go/expressions.cc go/expressions.h description: compiler: Add compound expressions to the frontend. * go-gcc.cc: Include "convert.h". (Gcc_backend::string_constant_expression): New function. (Gcc_backend::real_part_expression): Likewise. (Gcc_backend::imag_part_expression): Likewise. (Gcc_backend::complex_expression): Likewise. (Gcc_backend::constructor_expression): Likewise. (Gcc_backend::array_constructor_expression): Likewise. (Gcc_backend::pointer_offset_expression): Likewise. (Gcc_backend::array_index_expression): Likewise. (Gcc_backend::call_expression): Likewise. (Gcc_backend::exception_handler_statement): Likewise. (Gcc_backend::function_defer_statement): Likewise. (Gcc_backend::function_set_parameters): Likewise. (Gcc_backend::function_set_body): Likewise. (Gcc_backend::convert_expression): Handle various type conversions. From-SVN: r209393
Diffstat (limited to 'gcc/go/go-gcc.cc')
-rw-r--r--gcc/go/go-gcc.cc447
1 files changed, 443 insertions, 4 deletions
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 6aec287..3abefae 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -29,6 +29,7 @@
#include "stor-layout.h"
#include "varasm.h"
#include "tree-iterator.h"
+#include "convert.h"
#include "basic-block.h"
#include "gimple-expr.h"
#include "toplev.h"
@@ -235,6 +236,18 @@ class Gcc_backend : public Backend
complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag);
Bexpression*
+ string_constant_expression(const std::string& val);
+
+ Bexpression*
+ real_part_expression(Bexpression* bcomplex, Location);
+
+ Bexpression*
+ imag_part_expression(Bexpression* bcomplex, Location);
+
+ Bexpression*
+ complex_expression(Bexpression* breal, Bexpression* bimag, Location);
+
+ Bexpression*
convert_expression(Btype* type, Bexpression* expr, Location);
Bexpression*
@@ -259,6 +272,23 @@ class Gcc_backend : public Backend
Bexpression*
binary_expression(Operator, Bexpression*, Bexpression*, Location);
+ Bexpression*
+ constructor_expression(Btype*, const std::vector<Bexpression*>&, Location);
+
+ Bexpression*
+ array_constructor_expression(Btype*, const std::vector<unsigned long>&,
+ const std::vector<Bexpression*>&, Location);
+
+ Bexpression*
+ pointer_offset_expression(Bexpression* base, Bexpression* offset, Location);
+
+ Bexpression*
+ array_index_expression(Bexpression* array, Bexpression* index, Location);
+
+ Bexpression*
+ call_expression(Bexpression* fn, const std::vector<Bexpression*>& args,
+ Location);
+
// Statements.
Bstatement*
@@ -294,6 +324,10 @@ class Gcc_backend : public Backend
Bstatement*
statement_list(const std::vector<Bstatement*>&);
+ Bstatement*
+ exception_handler_statement(Bstatement* bstat, Bstatement* except_stmt,
+ Bstatement* finally_stmt, Location);
+
// Blocks.
Bblock*
@@ -372,6 +406,16 @@ class Gcc_backend : public Backend
bool is_visible, bool is_declaration, bool is_inlinable,
bool disable_split_stack, bool in_unique_section, Location);
+ Bstatement*
+ function_defer_statement(Bfunction* function, Bexpression* undefer,
+ Bexpression* defer, Location);
+
+ bool
+ function_set_parameters(Bfunction* function, const std::vector<Bvariable*>&);
+
+ bool
+ function_set_body(Bfunction* function, Bstatement* code_stmt);
+
private:
// Make a Bexpression from a tree.
Bexpression*
@@ -974,18 +1018,108 @@ Gcc_backend::complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag)
return tree_to_expr(ret);
}
+// Make a constant string expression.
+
+Bexpression*
+Gcc_backend::string_constant_expression(const std::string& val)
+{
+ tree index_type = build_index_type(size_int(val.length()));
+ tree const_char_type = build_qualified_type(unsigned_char_type_node,
+ TYPE_QUAL_CONST);
+ tree string_type = build_array_type(const_char_type, index_type);
+ string_type = build_variant_type_copy(string_type);
+ TYPE_STRING_FLAG(string_type) = 1;
+ tree string_val = build_string(val.length(), val.data());
+ TREE_TYPE(string_val) = string_type;
+
+ return this->make_expression(string_val);
+}
+
+// Return the real part of a complex expression.
+
+Bexpression*
+Gcc_backend::real_part_expression(Bexpression* bcomplex, Location location)
+{
+ tree complex_tree = bcomplex->get_tree();
+ if (complex_tree == error_mark_node)
+ return this->error_expression();
+ gcc_assert(COMPLEX_FLOAT_TYPE_P(TREE_TYPE(complex_tree)));
+ tree ret = fold_build1_loc(location.gcc_location(), REALPART_EXPR,
+ TREE_TYPE(TREE_TYPE(complex_tree)),
+ complex_tree);
+ return this->make_expression(ret);
+}
+
+// Return the imaginary part of a complex expression.
+
+Bexpression*
+Gcc_backend::imag_part_expression(Bexpression* bcomplex, Location location)
+{
+ tree complex_tree = bcomplex->get_tree();
+ if (complex_tree == error_mark_node)
+ return this->error_expression();
+ gcc_assert(COMPLEX_FLOAT_TYPE_P(TREE_TYPE(complex_tree)));
+ tree ret = fold_build1_loc(location.gcc_location(), IMAGPART_EXPR,
+ TREE_TYPE(TREE_TYPE(complex_tree)),
+ complex_tree);
+ return this->make_expression(ret);
+}
+
+// Make a complex expression given its real and imaginary parts.
+
+Bexpression*
+Gcc_backend::complex_expression(Bexpression* breal, Bexpression* bimag,
+ Location location)
+{
+ tree real_tree = breal->get_tree();
+ tree imag_tree = bimag->get_tree();
+ if (real_tree == error_mark_node || imag_tree == error_mark_node)
+ return this->error_expression();
+ gcc_assert(TYPE_MAIN_VARIANT(TREE_TYPE(real_tree))
+ == TYPE_MAIN_VARIANT(TREE_TYPE(imag_tree)));
+ gcc_assert(SCALAR_FLOAT_TYPE_P(TREE_TYPE(real_tree)));
+ tree ret = fold_build2_loc(location.gcc_location(), COMPLEX_EXPR,
+ build_complex_type(TREE_TYPE(real_tree)),
+ real_tree, imag_tree);
+ return this->make_expression(ret);
+}
+
// An expression that converts an expression to a different type.
Bexpression*
-Gcc_backend::convert_expression(Btype* type, Bexpression* expr, Location)
+Gcc_backend::convert_expression(Btype* type, Bexpression* expr,
+ Location location)
{
tree type_tree = type->get_tree();
tree expr_tree = expr->get_tree();
- if (type_tree == error_mark_node || expr_tree == error_mark_node)
+ if (type_tree == error_mark_node
+ || expr_tree == error_mark_node
+ || TREE_TYPE(expr_tree) == error_mark_node)
return this->error_expression();
- tree ret = fold_convert(type_tree, expr_tree);
- return tree_to_expr(ret);
+ tree ret;
+ if (this->type_size(type) == 0)
+ {
+ // Do not convert zero-sized types.
+ ret = expr_tree;
+ }
+ else if (TREE_CODE(type_tree) == INTEGER_TYPE)
+ ret = fold(convert_to_integer(type_tree, expr_tree));
+ else if (TREE_CODE(type_tree) == REAL_TYPE)
+ ret = fold(convert_to_real(type_tree, expr_tree));
+ else if (TREE_CODE(type_tree) == COMPLEX_TYPE)
+ ret = fold(convert_to_complex(type_tree, expr_tree));
+ else if (TREE_CODE(type_tree) == POINTER_TYPE
+ && TREE_CODE(TREE_TYPE(expr_tree)) == INTEGER_TYPE)
+ ret = fold(convert_to_pointer(type_tree, expr_tree));
+ else if (TREE_CODE(type_tree) == RECORD_TYPE
+ || TREE_CODE(type_tree) == ARRAY_TYPE)
+ ret = fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR,
+ type_tree, expr_tree);
+ else
+ ret = fold_convert_loc(location.gcc_location(), type_tree, expr_tree);
+
+ return this->make_expression(ret);
}
// Get the address of a function.
@@ -1243,6 +1377,205 @@ Gcc_backend::binary_expression(Operator op, Bexpression* left,
return this->make_expression(ret);
}
+// Return an expression that constructs BTYPE with VALS.
+
+Bexpression*
+Gcc_backend::constructor_expression(Btype* btype,
+ const std::vector<Bexpression*>& vals,
+ Location location)
+{
+ tree type_tree = btype->get_tree();
+ if (type_tree == error_mark_node)
+ return this->error_expression();
+
+ vec<constructor_elt, va_gc> *init;
+ vec_alloc(init, vals.size());
+
+ bool is_constant = true;
+ tree field = TYPE_FIELDS(type_tree);
+ for (std::vector<Bexpression*>::const_iterator p = vals.begin();
+ p != vals.end();
+ ++p, field = DECL_CHAIN(field))
+ {
+ gcc_assert(field != NULL_TREE);
+ tree val = (*p)->get_tree();
+ if (TREE_TYPE(field) == error_mark_node
+ || val == error_mark_node
+ || TREE_TYPE(val) == error_mark_node)
+ return this->error_expression();
+
+ constructor_elt empty = {NULL, NULL};
+ constructor_elt* elt = init->quick_push(empty);
+ elt->index = field;
+ elt->value = fold_convert_loc(location.gcc_location(), TREE_TYPE(field),
+ val);
+ if (!TREE_CONSTANT(elt->value))
+ is_constant = false;
+ }
+ gcc_assert(field == NULL_TREE);
+ tree ret = build_constructor(type_tree, init);
+ if (is_constant)
+ TREE_CONSTANT(ret) = 1;
+
+ return this->make_expression(ret);
+}
+
+Bexpression*
+Gcc_backend::array_constructor_expression(
+ Btype* array_btype, const std::vector<unsigned long>& indexes,
+ const std::vector<Bexpression*>& vals, Location)
+{
+ tree type_tree = array_btype->get_tree();
+ if (type_tree == error_mark_node)
+ return this->error_expression();
+
+ gcc_assert(indexes.size() == vals.size());
+ vec<constructor_elt, va_gc> *init;
+ vec_alloc(init, vals.size());
+
+ bool is_constant = true;
+ for (size_t i = 0; i < vals.size(); ++i)
+ {
+ tree index = size_int(indexes[i]);
+ tree val = (vals[i])->get_tree();
+
+ if (index == error_mark_node
+ || val == error_mark_node)
+ return this->error_expression();
+
+ if (!TREE_CONSTANT(val))
+ is_constant = false;
+
+ constructor_elt empty = {NULL, NULL};
+ constructor_elt* elt = init->quick_push(empty);
+ elt->index = index;
+ elt->value = val;
+ }
+
+ tree ret = build_constructor(type_tree, init);
+ if (is_constant)
+ TREE_CONSTANT(ret) = 1;
+ return this->make_expression(ret);
+}
+
+// Return an expression for the address of BASE[INDEX].
+
+Bexpression*
+Gcc_backend::pointer_offset_expression(Bexpression* base, Bexpression* index,
+ Location location)
+{
+ tree base_tree = base->get_tree();
+ tree index_tree = index->get_tree();
+ tree element_type_tree = TREE_TYPE(TREE_TYPE(base_tree));
+ if (base_tree == error_mark_node
+ || TREE_TYPE(base_tree) == error_mark_node
+ || index_tree == error_mark_node
+ || element_type_tree == error_mark_node)
+ return this->error_expression();
+
+ tree element_size = TYPE_SIZE_UNIT(element_type_tree);
+ index_tree = fold_convert_loc(location.gcc_location(), sizetype, index_tree);
+ tree offset = fold_build2_loc(location.gcc_location(), MULT_EXPR, sizetype,
+ index_tree, element_size);
+ tree ptr = fold_build2_loc(location.gcc_location(), POINTER_PLUS_EXPR,
+ TREE_TYPE(base_tree), base_tree, offset);
+ return this->make_expression(ptr);
+}
+
+// Return an expression representing ARRAY[INDEX]
+
+Bexpression*
+Gcc_backend::array_index_expression(Bexpression* array, Bexpression* index,
+ Location location)
+{
+ tree array_tree = array->get_tree();
+ tree index_tree = index->get_tree();
+ if (array_tree == error_mark_node
+ || TREE_TYPE(array_tree) == error_mark_node
+ || index_tree == error_mark_node)
+ return this->error_expression();
+
+ tree ret = build4_loc(location.gcc_location(), ARRAY_REF,
+ TREE_TYPE(TREE_TYPE(array_tree)), array_tree,
+ index_tree, NULL_TREE, NULL_TREE);
+ return this->make_expression(ret);
+}
+
+// Create an expression for a call to FN_EXPR with FN_ARGS.
+Bexpression*
+Gcc_backend::call_expression(Bexpression* fn_expr,
+ const std::vector<Bexpression*>& fn_args,
+ Location location)
+{
+ tree fn = fn_expr->get_tree();
+ if (fn == error_mark_node || TREE_TYPE(fn) == error_mark_node)
+ return this->error_expression();
+
+ gcc_assert(FUNCTION_POINTER_TYPE_P(TREE_TYPE(fn)));
+ tree rettype = TREE_TYPE(TREE_TYPE(TREE_TYPE(fn)));
+
+ size_t nargs = fn_args.size();
+ tree* args = nargs == 0 ? NULL : new tree[nargs];
+ for (size_t i = 0; i < nargs; ++i)
+ {
+ args[i] = fn_args.at(i)->get_tree();
+ if (args[i] == error_mark_node)
+ return this->error_expression();
+ }
+
+ tree fndecl = fn;
+ if (TREE_CODE(fndecl) == ADDR_EXPR)
+ fndecl = TREE_OPERAND(fndecl, 0);
+
+ // This is to support builtin math functions when using 80387 math.
+ tree excess_type = NULL_TREE;
+ if (optimize
+ && TREE_CODE(fndecl) == FUNCTION_DECL
+ && DECL_IS_BUILTIN(fndecl)
+ && DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_NORMAL
+ && nargs > 0
+ && ((SCALAR_FLOAT_TYPE_P(rettype)
+ && SCALAR_FLOAT_TYPE_P(TREE_TYPE(args[0])))
+ || (COMPLEX_FLOAT_TYPE_P(rettype)
+ && COMPLEX_FLOAT_TYPE_P(TREE_TYPE(args[0])))))
+ {
+ excess_type = excess_precision_type(TREE_TYPE(args[0]));
+ if (excess_type != NULL_TREE)
+ {
+ tree excess_fndecl = mathfn_built_in(excess_type,
+ DECL_FUNCTION_CODE(fndecl));
+ if (excess_fndecl == NULL_TREE)
+ excess_type = NULL_TREE;
+ else
+ {
+ fn = build_fold_addr_expr_loc(location.gcc_location(),
+ excess_fndecl);
+ for (size_t i = 0; i < nargs; ++i)
+ {
+ if (SCALAR_FLOAT_TYPE_P(TREE_TYPE(args[i]))
+ || COMPLEX_FLOAT_TYPE_P(TREE_TYPE(args[i])))
+ args[i] = ::convert(excess_type, args[i]);
+ }
+ }
+ }
+ }
+
+ tree ret =
+ build_call_array_loc(location.gcc_location(),
+ excess_type != NULL_TREE ? excess_type : rettype,
+ fn, nargs, args);
+
+ if (excess_type != NULL_TREE)
+ {
+ // Calling convert here can undo our excess precision change.
+ // That may or may not be a bug in convert_to_real.
+ ret = build1_loc(location.gcc_location(), NOP_EXPR, rettype, ret);
+ }
+
+ delete[] args;
+ return this->make_expression(ret);
+}
+
// An expression as a statement.
Bstatement*
@@ -1402,6 +1735,40 @@ Gcc_backend::return_statement(Bfunction* bfunction,
return this->make_statement(ret);
}
+// Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an
+// error occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and if not
+// NULL, it will always be executed. This is used for handling defers in Go
+// functions. In C++, the resulting code is of this form:
+// try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; }
+
+Bstatement*
+Gcc_backend::exception_handler_statement(Bstatement* bstat,
+ Bstatement* except_stmt,
+ Bstatement* finally_stmt,
+ Location location)
+{
+ tree stat_tree = bstat->get_tree();
+ tree except_tree = except_stmt == NULL ? NULL_TREE : except_stmt->get_tree();
+ tree finally_tree = finally_stmt == NULL
+ ? NULL_TREE
+ : finally_stmt->get_tree();
+
+ if (stat_tree == error_mark_node
+ || except_tree == error_mark_node
+ || finally_tree == error_mark_node)
+ return this->error_statement();
+
+ if (except_tree != NULL_TREE)
+ stat_tree = build2_loc(location.gcc_location(), TRY_CATCH_EXPR,
+ void_type_node, stat_tree,
+ build2_loc(location.gcc_location(), CATCH_EXPR,
+ void_type_node, NULL, except_tree));
+ if (finally_tree != NULL_TREE)
+ stat_tree = build2_loc(location.gcc_location(), TRY_FINALLY_EXPR,
+ void_type_node, stat_tree, finally_tree);
+ return this->make_statement(stat_tree);
+}
+
// If.
Bstatement*
@@ -2070,6 +2437,78 @@ Gcc_backend::function(Btype* fntype, const std::string& name,
return new Bfunction(decl);
}
+// Create a statement that runs all deferred calls for FUNCTION. This should
+// be a statement that looks like this in C++:
+// finish:
+// try { UNDEFER; } catch { CHECK_DEFER; goto finish; }
+
+Bstatement*
+Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer,
+ Bexpression* defer, Location location)
+{
+ tree undefer_tree = undefer->get_tree();
+ tree defer_tree = defer->get_tree();
+
+ if (undefer_tree == error_mark_node
+ || defer_tree == error_mark_node)
+ return this->error_statement();
+
+ tree stmt_list = NULL;
+ Blabel* blabel = this->label(function, "", location);
+ Bstatement* label_def = this->label_definition_statement(blabel);
+ append_to_statement_list(label_def->get_tree(), &stmt_list);
+
+ Bstatement* jump_stmt = this->goto_statement(blabel, location);
+ tree jump = jump_stmt->get_tree();
+ tree catch_body = build2(COMPOUND_EXPR, void_type_node, defer_tree, jump);
+ catch_body = build2(CATCH_EXPR, void_type_node, NULL, catch_body);
+ tree try_catch =
+ build2(TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body);
+ append_to_statement_list(try_catch, &stmt_list);
+
+ return this->make_statement(stmt_list);
+}
+
+// Record PARAM_VARS as the variables to use for the parameters of FUNCTION.
+// This will only be called for a function definition.
+
+bool
+Gcc_backend::function_set_parameters(Bfunction* function,
+ const std::vector<Bvariable*>& param_vars)
+{
+ tree func_tree = function->get_tree();
+ if (func_tree == error_mark_node)
+ return false;
+
+ tree params = NULL_TREE;
+ tree *pp = &params;
+ for (std::vector<Bvariable*>::const_iterator pv = param_vars.begin();
+ pv != param_vars.end();
+ ++pv)
+ {
+ *pp = (*pv)->get_tree();
+ gcc_assert(*pp != error_mark_node);
+ pp = &DECL_CHAIN(*pp);
+ }
+ *pp = NULL_TREE;
+ DECL_ARGUMENTS(func_tree) = params;
+ return true;
+}
+
+// Set the function body for FUNCTION using the code in CODE_BLOCK.
+
+bool
+Gcc_backend::function_set_body(Bfunction* function, Bstatement* code_stmt)
+{
+ tree func_tree = function->get_tree();
+ tree code = code_stmt->get_tree();
+
+ if (func_tree == error_mark_node || code == error_mark_node)
+ return false;
+ DECL_SAVED_TREE(func_tree) = code;
+ return true;
+}
+
// The single backend.
static Gcc_backend gcc_backend;