#include <gmp.h>
-#ifndef ENABLE_BUILD_WITH_CXX
-extern "C"
-{
-#endif
-
-#include "intl.h"
-#include "tree.h"
-#include "gimple.h"
-#include "convert.h"
-#include "tree-iterator.h"
-#include "tree-flow.h"
-#include "real.h"
-
-#ifndef ENABLE_BUILD_WITH_CXX
-}
-#endif
-
#include "go-c.h"
#include "types.h"
#include "expressions.h"
return ret;
}
-// Get a tree for a Statement. This is really done by the child
-// class.
+// Convert a Statement to the backend representation. This is really
+// done by the child class.
Bstatement*
Statement::get_backend(Translate_context* context)
return this->do_get_backend(context);
}
-// Build tree nodes and set locations.
-
-tree
-Statement::build_stmt_1(int tree_code_value, tree node)
-{
- tree ret = build1(static_cast<tree_code>(tree_code_value),
- void_type_node, node);
- SET_EXPR_LOCATION(ret, this->location_);
- return ret;
-}
-
// Note that this statement is erroneous. This is called by children
// when they discover an error.
return true;
}
-// Return the tree for a variable declaration.
+// Convert a variable declaration to the backend representation.
Bstatement*
Variable_declaration_statement::do_get_backend(Translate_context* context)
Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
context->function());
tree init = var->get_init_tree(context->gogo(), context->function());
- Bexpression* binit = init == NULL_TREE ? NULL : tree_to_expr(init);
+ Bexpression* binit = init == NULL ? NULL : tree_to_expr(init);
+
if (!var->is_in_heap())
{
gcc_assert(binit != NULL);
return context->backend()->init_statement(bvar, binit);
}
- else
+
+ // Something takes the address of this variable, so the value is
+ // stored in the heap. Initialize it to newly allocated memory
+ // space, and assign the initial value to the new space.
+ source_location loc = this->location();
+ Named_object* newfn = context->gogo()->lookup_global("new");
+ gcc_assert(newfn != NULL && newfn->is_function_declaration());
+ Expression* func = Expression::make_func_reference(newfn, NULL, loc);
+ Expression_list* params = new Expression_list();
+ params->push_back(Expression::make_type(var->type(), loc));
+ Expression* call = Expression::make_call(func, params, false, loc);
+ context->gogo()->lower_expression(context->function(), &call);
+ Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
+ Bstatement* btemp = temp->get_backend(context);
+
+ Bstatement* set = NULL;
+ if (binit != NULL)
{
- // Something takes the address of this variable, so the value is
- // stored in the heap. Initialize it to newly allocated memory
- // space, and assign the initial value to the new space.
- source_location loc = this->location();
- tree decl = var_to_tree(bvar);
- tree decl_type = TREE_TYPE(decl);
- gcc_assert(POINTER_TYPE_P(decl_type));
- tree size = TYPE_SIZE_UNIT(TREE_TYPE(decl_type));
- tree space = context->gogo()->allocate_memory(var->type(), size, loc);
- if (binit != NULL)
- space = save_expr(space);
- space = fold_convert_loc(loc, decl_type, space);
- Bstatement* s1 = context->backend()->init_statement(bvar,
- tree_to_expr(space));
- if (binit == NULL)
- return s1;
- else
- {
- tree indir = build_fold_indirect_ref_loc(loc, space);
- Bexpression* bindir = tree_to_expr(indir);
- Bstatement* s2 = context->backend()->assignment_statement(bindir,
- binit,
- loc);
- return context->backend()->compound_statement(s1, s2);
- }
+ Expression* e = Expression::make_temporary_reference(temp, loc);
+ e = Expression::make_unary(OPERATOR_MULT, e, loc);
+ Bexpression* be = tree_to_expr(e->get_tree(context));
+ set = context->backend()->assignment_statement(be, binit, loc);
}
+
+ Expression* ref = Expression::make_temporary_reference(temp, loc);
+ Bexpression* bref = tree_to_expr(ref->get_tree(context));
+ Bstatement* sinit = context->backend()->init_statement(bvar, bref);
+
+ std::vector<Bstatement*> stats;
+ stats.reserve(3);
+ stats.push_back(btemp);
+ if (set != NULL)
+ stats.push_back(set);
+ stats.push_back(sinit);
+ return context->backend()->statement_list(stats);
}
// Make a variable declaration.
}
}
-// Return a tree.
+// Convert to backend representation.
Bstatement*
Temporary_statement::do_get_backend(Translate_context* context)
this->set_is_error();
}
-// Build a tree for an assignment statement.
+// Convert an assignment statement to the backend representation.
Bstatement*
Assignment_statement::do_get_backend(Translate_context* context)
{
tree rhs_tree = this->rhs_->get_tree(context);
- if (rhs_tree == error_mark_node)
- return context->backend()->error_statement();
-
if (this->lhs_->is_sink_expression())
return context->backend()->expression_statement(tree_to_expr(rhs_tree));
-
tree lhs_tree = this->lhs_->get_tree(context);
-
- if (lhs_tree == error_mark_node)
- return context->backend()->error_statement();
-
rhs_tree = Expression::convert_for_assignment(context, this->lhs_->type(),
this->rhs_->type(), rhs_tree,
this->location());
- if (rhs_tree == error_mark_node)
- return context->backend()->error_statement();
-
return context->backend()->assignment_statement(tree_to_expr(lhs_tree),
tree_to_expr(rhs_tree),
this->location());
gogo->finish_function(location);
}
-// Get the function and argument trees.
+// Get the function and argument expressions.
bool
Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
}
}
-// Return the tree for the goto statement.
+// Convert the goto statement to the backend representation.
Bstatement*
Goto_statement::do_get_backend(Translate_context* context)
return TRAVERSE_CONTINUE;
}
-// Return a tree defining this label.
+// Return the backend representation of the statement defining this
+// label.
Bstatement*
Label_statement::do_get_backend(Translate_context* context)
|| this->else_block_->may_fall_through());
}
-// Get tree.
+// Get the backend representation.
Bstatement*
If_statement::do_get_backend(Translate_context* context)
}
}
-// Get a tree for a send statement.
+// Convert a send statement to the backend representation.
Bstatement*
Send_statement::do_get_backend(Translate_context* context)
return this->statements_->may_fall_through();
}
-// Return a tree for the statements to execute.
+// Return the backend representation for the statements to execute.
Bstatement*
Select_clauses::Select_clause::get_statements_backend(
return context->backend()->statement_list(statements);
}
-// Add the tree for CLAUSE to STMT_LIST.
+// Add CLAUSE to CASES/CLAUSES at INDEX.
void
Select_clauses::add_clause_backend(
return Statement::make_block_statement(b, this->location());
}
-// Return the tree for a select statement.
+// Return the backend representation for a select statement.
Bstatement*
Select_statement::do_get_backend(Translate_context* context)
int
traverse_type(Traverse*, Type*);
- // Build a tree node with one operand, setting the location. The
- // first operand really has type "enum tree_code", but that enum is
- // not defined here.
- tree
- build_stmt_1(int tree_code_value, tree);
-
// For children to call when they detect that they are in error.
void
set_is_error();
bool
may_fall_through() const;
- // Return a tree for the statements to execute.
+ // Convert the statements to the backend representation.
Bstatement*
get_statements_backend(Translate_context*);
void
do_check_types(Gogo*);
- // Return the function and argument trees for the call.
+ // Return the function and argument for the call.
bool
get_fn_and_arg(Expression** pfn, Expression** parg);
std::vector<Bstatement*>* all_statements) const;
private:
- // For a constant tree we need to keep a record of constants we have
- // already seen. Note that INTEGER_CST trees are interned.
+ // For a constant switch we need to keep a record of constants we
+ // have already seen.
class Hash_integer_value;
class Eq_integer_value;
typedef Unordered_set_hash(Expression*, Hash_integer_value,
{ gcc_unreachable(); }
private:
- // Get the type descriptor.
- tree
- get_type_descriptor(Translate_context*, Type*, tree);
-
// The variable holding the value we are switching on.
Named_object* var_;
// The expression we are switching on if there is no variable.