class Gogo;
class Traverse;
+class Statement_inserter;
class Block;
class Function;
class Unnamed_label;
class Type_case_clauses;
class Select_clauses;
class Typed_identifier_list;
+class Bexpression;
+class Bstatement;
+class Bvariable;
+class Ast_dump_context;
// This class is used to traverse assignments made by a statement
// which makes assignments.
// Make a return statement.
static Statement*
- make_return_statement(const Typed_identifier_list*, Expression_list*,
- source_location);
+ make_return_statement(Expression_list*, source_location);
// Make a break statement.
static Statement*
// simplify statements for further processing. It returns the same
// Statement or a new one. FUNCTION is the function containing this
// statement. BLOCK is the block containing this statement.
+ // INSERTER can be used to insert new statements before this one.
Statement*
- lower(Gogo* gogo, Named_object* function, Block* block)
- { return this->do_lower(gogo, function, block); }
+ lower(Gogo* gogo, Named_object* function, Block* block,
+ Statement_inserter* inserter)
+ { return this->do_lower(gogo, function, block, inserter); }
// Set type information for unnamed constants.
void
may_fall_through() const
{ return this->do_may_fall_through(); }
- // Return the tree for a statement. BLOCK is the enclosing block.
- tree
- get_tree(Translate_context*);
+ // Convert the statement to the backend representation.
+ Bstatement*
+ get_backend(Translate_context*);
+
+ // Dump AST representation of a statement to a dump context.
+ void
+ dump_statement(Ast_dump_context*) const;
protected:
// Implemented by child class: traverse the tree.
// Implemented by the child class: lower this statement to a simpler
// one.
virtual Statement*
- do_lower(Gogo*, Named_object*, Block*)
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
{ return this; }
// Implemented by child class: set type information for unnamed
do_may_fall_through() const
{ return true; }
- // Implemented by child class: return a tree.
- virtual tree
- do_get_tree(Translate_context*) = 0;
+ // Implemented by child class: convert to backend representation.
+ virtual Bstatement*
+ do_get_backend(Translate_context*) = 0;
+
+ // Implemented by child class: dump ast representation.
+ virtual void
+ do_dump_statement(Ast_dump_context*) const = 0;
// Traverse an expression in a statement.
int
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();
public:
Temporary_statement(Type* type, Expression* init, source_location location)
: Statement(STATEMENT_TEMPORARY, location),
- type_(type), init_(init), decl_(NULL), is_address_taken_(false)
+ type_(type), init_(init), bvariable_(NULL), is_address_taken_(false)
{ }
// Return the type of the temporary variable.
Type*
type() const;
- // Return the initialization expression.
- Expression*
- init() const
- { return this->init_; }
-
// Record that something takes the address of this temporary
// variable.
void
set_is_address_taken()
{ this->is_address_taken_ = true; }
- // Return the tree for the temporary variable itself. This should
- // not be called until after the statement itself has been expanded.
- tree
- get_decl() const;
+ // Return the temporary variable. This should not be called until
+ // after the statement itself has been converted.
+ Bvariable*
+ get_backend_variable(Translate_context*) const;
protected:
int
void
do_check_types(Gogo*);
- tree
- do_get_tree(Translate_context*);
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
// The type of the temporary variable.
Type* type_;
// The initial value of the temporary variable. This may be NULL.
Expression* init_;
- // The DECL for the temporary variable.
- tree decl_;
+ // The backend representation of the temporary variable.
+ Bvariable* bvariable_;
// True if something takes the address of this temporary variable.
bool is_address_taken_;
};
bool
do_traverse_assignments(Traverse_assignments*);
- tree
- do_get_tree(Translate_context*);
+ Statement*
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
+
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
Named_object* var_;
class Return_statement : public Statement
{
public:
- Return_statement(const Typed_identifier_list* results, Expression_list* vals,
- source_location location)
+ Return_statement(Expression_list* vals, source_location location)
: Statement(STATEMENT_RETURN, location),
- results_(results), vals_(vals)
+ vals_(vals), is_lowered_(false)
{ }
// The list of values being returned. This may be NULL.
do_traverse_assignments(Traverse_assignments*);
Statement*
- do_lower(Gogo*, Named_object*, Block*);
-
- void
- do_determine_types();
-
- void
- do_check_types(Gogo*);
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
bool
do_may_fall_through() const
{ return false; }
- tree
- do_get_tree(Translate_context*);
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
- // The result types of the function we are returning from. This is
- // here because in some of the traversals it is inconvenient to get
- // it.
- const Typed_identifier_list* results_;
// Return values. This may be NULL.
Expression_list* vals_;
+ // True if this statement has been lowered.
+ bool is_lowered_;
};
// A send statement.
void
do_check_types(Gogo*);
- tree
- do_get_tree(Translate_context*);
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
// The channel on which to send the value.
bool
may_fall_through() const;
- // Return a tree implementing the select statement.
- tree
- get_tree(Translate_context*, Unnamed_label* break_label, source_location);
+ // Convert to the backend representation.
+ Bstatement*
+ get_backend(Translate_context*, Unnamed_label* break_label, source_location);
+
+ // Dump AST representation.
+ void
+ dump_clauses(Ast_dump_context*) const;
private:
// A single clause.
: channel_(channel), val_(val), closed_(closed), var_(var),
closedvar_(closedvar), statements_(statements), location_(location),
is_send_(is_send), is_default_(is_default), is_lowered_(false)
- { gcc_assert(is_default ? channel == NULL : channel != NULL); }
+ { go_assert(is_default ? channel == NULL : channel != NULL); }
// Traverse the select clause.
int
bool
is_send() const
{
- gcc_assert(!this->is_default_);
+ go_assert(!this->is_default_);
return this->is_send_;
}
bool
may_fall_through() const;
- // Return a tree for the statements to execute.
- tree
- get_statements_tree(Translate_context*);
+ // Convert the statements to the backend representation.
+ Bstatement*
+ get_statements_backend(Translate_context*);
+
+ // Dump AST representation.
+ void
+ dump_clause(Ast_dump_context*) const;
private:
// The channel.
};
void
- add_clause_tree(Translate_context*, int, Select_clause*, Unnamed_label*,
- tree*);
+ add_clause_backend(Translate_context*, source_location, int index,
+ int case_value, Select_clause*, Unnamed_label*,
+ std::vector<std::vector<Bexpression*> >* cases,
+ std::vector<Bstatement*>* clauses);
typedef std::vector<Select_clause> Clauses;
void
add_clauses(Select_clauses* clauses)
{
- gcc_assert(this->clauses_ == NULL);
+ go_assert(this->clauses_ == NULL);
this->clauses_ = clauses;
}
{ return this->clauses_->traverse(traverse); }
Statement*
- do_lower(Gogo*, Named_object*, Block*);
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
void
do_determine_types()
do_may_fall_through() const
{ return this->clauses_->may_fall_through(); }
- tree
- do_get_tree(Translate_context*);
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
// The select clauses.
// Return the call expression.
Expression*
- call()
+ call() const
{ return this->call_; }
// Simplify a go or defer statement so that it only uses a single
// parameter.
bool
- simplify_statement(Gogo*, Block*);
+ simplify_statement(Gogo*, Named_object*, Block*);
protected:
int
void
do_check_types(Gogo*);
- // Return the function and argument trees for the call.
- void
- get_fn_and_arg(Translate_context*, tree* pfn, tree* parg);
+ // Return the function and argument for the call.
+ bool
+ get_fn_and_arg(Expression** pfn, Expression** parg);
private:
// Return whether this is a simple go statement.
bool
is_simple(Function_type*) const;
+ // Return whether the thunk function is a constant.
+ bool
+ is_constant_function() const;
+
// Build the struct to use for a complex case.
Struct_type*
build_struct(Function_type* fntype);
// Build the thunk.
void
- build_thunk(Gogo*, const std::string&, Function_type* fntype);
-
- // The field name used in the thunk structure for the function
- // pointer.
- static const char* const thunk_field_fn;
-
- // The field name used in the thunk structure for the receiver, if
- // there is one.
- static const char* const thunk_field_receiver;
+ build_thunk(Gogo*, const std::string&);
// Set the name to use for thunk field N.
void
{ }
protected:
- tree
- do_get_tree(Translate_context*);
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
};
// A defer statement.
{ }
protected:
- tree
- do_get_tree(Translate_context*);
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
};
// A label statement.
int
do_traverse(Traverse*);
- tree
- do_get_tree(Translate_context*);
+ Bstatement*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
// The label.
void
add_statements(Block* statements)
{
- gcc_assert(this->statements_ == NULL);
+ go_assert(this->statements_ == NULL);
this->statements_ = statements;
}
bool
do_traverse_assignments(Traverse_assignments*)
- { gcc_unreachable(); }
+ { go_unreachable(); }
Statement*
- do_lower(Gogo*, Named_object*, Block*);
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
- tree
- do_get_tree(Translate_context*)
- { gcc_unreachable(); }
+ Bstatement*
+ do_get_backend(Translate_context*)
+ { go_unreachable(); }
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
// The initialization statements. This may be NULL.
void
add_statements(Block* statements)
{
- gcc_assert(this->statements_ == NULL);
+ go_assert(this->statements_ == NULL);
this->statements_ = statements;
}
bool
do_traverse_assignments(Traverse_assignments*)
- { gcc_unreachable(); }
+ { go_unreachable(); }
Statement*
- do_lower(Gogo*, Named_object*, Block*);
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
- tree
- do_get_tree(Translate_context*)
- { gcc_unreachable(); }
+ Bstatement*
+ do_get_backend(Translate_context*)
+ { go_unreachable(); }
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
Expression*
// Return the body of a SWITCH_EXPR when all the clauses are
// constants.
- tree
- get_constant_tree(Translate_context*, Unnamed_label* break_label) const;
+ void
+ get_backend(Translate_context*, Unnamed_label* break_label,
+ std::vector<std::vector<Bexpression*> >* all_cases,
+ std::vector<Bstatement*>* all_statements) const;
+ // Dump the AST representation to a dump context.
+ void
+ dump_clauses(Ast_dump_context*) 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.
- typedef Unordered_set(tree) Case_constants;
+ // 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,
+ Eq_integer_value) Case_constants;
// One case clause.
class Case_clause
bool
may_fall_through() const;
- // Build up the body of a SWITCH_EXPR when the case expressions
- // are constant.
- void
- get_constant_tree(Translate_context*, Unnamed_label* break_label,
- Case_constants* case_constants, tree* stmt_list) const;
+ // Convert the case values and statements to the backend
+ // representation.
+ Bstatement*
+ get_backend(Translate_context*, Unnamed_label* break_label,
+ Case_constants*, std::vector<Bexpression*>* cases) const;
+ // Dump the AST representation to a dump context.
+ void
+ dump_clause(Ast_dump_context*) const;
+
private:
// The list of case expressions.
Expression_list* cases_;
void
add_clauses(Case_clauses* clauses)
{
- gcc_assert(this->clauses_ == NULL);
+ go_assert(this->clauses_ == NULL);
this->clauses_ = clauses;
}
do_traverse(Traverse*);
Statement*
- do_lower(Gogo*, Named_object*, Block*);
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
+
+ Bstatement*
+ do_get_backend(Translate_context*)
+ { go_unreachable(); }
- tree
- do_get_tree(Translate_context*)
- { gcc_unreachable(); }
+ void
+ do_dump_statement(Ast_dump_context*) const;
private:
// The value to switch on. This may be NULL.
lower(Block*, Temporary_statement* descriptor_temp,
Unnamed_label* break_label) const;
+ // Dump the AST representation to a dump context.
+ void
+ dump_clauses(Ast_dump_context*) const;
+
private:
// One type case clause.
class Type_case_clause
lower(Block*, Temporary_statement* descriptor_temp,
Unnamed_label* break_label, Unnamed_label** stmts_label) const;
+ // Dump the AST representation to a dump context.
+ void
+ dump_clause(Ast_dump_context*) const;
+
private:
// The type for this type clause.
Type* type_;
source_location location)
: Statement(STATEMENT_TYPE_SWITCH, location),
var_(var), expr_(expr), clauses_(NULL), break_label_(NULL)
- { gcc_assert(var == NULL || expr == NULL); }
+ { go_assert(var == NULL || expr == NULL); }
// Add the clauses.
void
add_clauses(Type_case_clauses* clauses)
{
- gcc_assert(this->clauses_ == NULL);
+ go_assert(this->clauses_ == NULL);
this->clauses_ = clauses;
}
do_traverse(Traverse*);
Statement*
- do_lower(Gogo*, Named_object*, Block*);
+ do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
- tree
- do_get_tree(Translate_context*)
- { gcc_unreachable(); }
+ Bstatement*
+ do_get_backend(Translate_context*)
+ { go_unreachable(); }
- private:
- // Get the type descriptor.
- tree
- get_type_descriptor(Translate_context*, Type*, tree);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+ private:
// The variable holding the value we are switching on.
Named_object* var_;
// The expression we are switching on if there is no variable.