From: Roberto Lublinerman Date: Wed, 3 Aug 2011 00:37:26 +0000 (+0000) Subject: gccgo: Added code to dump the AST tree. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=16c57fe28099740e06cb761b928b62a5a028bf66;p=gcc.git gccgo: Added code to dump the AST tree. gccgo: Added code to dump the AST tree. The AST dump is activated with -fgo-dump-ast. Initial version, it only dumps (most) constructs that are expected after the lowering transformation. * Make-lang.in (GO_OBJS): Add go/ast-dump.o. (go/ast-dump.o): New target. (go/expressions.o): Depend on go/gofrontend/ast-dump.h. (go/statements.o): Likewise. From-SVN: r177225 --- diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index fb26cabfc31..dcf420e364c 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,10 @@ +2011-08-02 Roberto Lublinerman + + * Make-lang.in (GO_OBJS): Add go/ast-dump.o. + (go/ast-dump.o): New target. + (go/expressions.o): Depend on go/gofrontend/ast-dump.h. + (go/statements.o): Likewise. + 2011-07-06 Richard Guenther * go-lang.c (go_langhook_init): diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in index 26c16194d7f..40fa30ceb98 100644 --- a/gcc/go/Make-lang.in +++ b/gcc/go/Make-lang.in @@ -45,6 +45,7 @@ gccgo$(exeext): $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) go-warn = $(STRICT_WARN) GO_OBJS = \ + go/ast-dump.o \ go/dataflow.o \ go/export.o \ go/expressions.o \ @@ -247,6 +248,9 @@ go/go-gcc.o: go/go-gcc.cc $(GO_SYSTEM_H) $(TREE_H) tree-iterator.h \ go/%.o: go/gofrontend/%.cc $(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION) +go/ast-dump.o: go/gofrontend/ast-dump.cc $(GO_SYSTME_H) $(GO_GOGO_H) \ + $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_TYPES_H) \ + go/gofrontend/ast-dump.h $(GO_C_H) go/gofrontend/go-dump.h go/dataflow.o: go/gofrontend/dataflow.cc $(GO_SYSTEM_H) $(GO_GOGO_H) \ $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) go/gofrontend/dataflow.h go/export.o: go/gofrontend/export.cc $(GO_SYSTEM_H) \ @@ -256,7 +260,8 @@ go/expressions.o: go/gofrontend/expressions.cc $(GO_SYSTEM_H) $(TOPLEV_H) \ intl.h $(TREE_H) $(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) \ realmpfr.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \ go/gofrontend/export.h $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \ - $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_EXPRESSIONS_H) + $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_EXPRESSIONS_H) \ + go/gofrontend/ast-dump.h go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) \ $(GO_PARSE_H) go/gofrontend/backend.h $(GO_GOGO_H) go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \ @@ -285,7 +290,8 @@ go/runtime.o: go/gofrontend/runtime.cc $(GO_SYSTEM_H) $(GO_GOGO_H) \ go/gofrontend/runtime.def go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) \ $(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) \ - $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_STATEMENTS_H) + $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_STATEMENTS_H) \ + go/gofrontend/ast-dump.h go/types.o: go/gofrontend/types.cc $(GO_SYSTEM_H) $(TOPLEV_H) intl.h $(TREE_H) \ $(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \ go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) \ diff --git a/gcc/go/gofrontend/ast-dump.cc b/gcc/go/gofrontend/ast-dump.cc new file mode 100644 index 00000000000..d52d3676481 --- /dev/null +++ b/gcc/go/gofrontend/ast-dump.cc @@ -0,0 +1,423 @@ +// ast-dump.cc -- AST debug dump. -*- C++ -*- + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "go-system.h" + +#include +#include + +#include "gogo.h" +#include "expressions.h" +#include "statements.h" +#include "types.h" +#include "ast-dump.h" +#include "go-c.h" +#include "go-dump.h" + +// The -fgo-dump-ast flag to activate AST dumps. + +Go_dump ast_dump_context_flag("ast"); + +// This class is used to traverse the tree to look for blocks and +// function headers. + +class Ast_dump_traverse_blocks_and_functions : public Traverse +{ + public: + Ast_dump_traverse_blocks_and_functions(Ast_dump_context* ast_dump_context) + : Traverse(traverse_blocks | traverse_functions), + ast_dump_context_(ast_dump_context) + { } + + protected: + int + block(Block*); + + int + function(Named_object*); + + private: + Ast_dump_context* ast_dump_context_; +}; + +// This class is used to traverse the tree to look for statements. + +class Ast_dump_traverse_statements : public Traverse +{ + public: + Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context) + : Traverse(traverse_statements), + ast_dump_context_(ast_dump_context) + { } + + protected: + int + statement(Block*, size_t* pindex, Statement*); + + private: + Ast_dump_context* ast_dump_context_; +}; + +// For each block we enclose it in brackets. + +int Ast_dump_traverse_blocks_and_functions::block(Block * block) +{ + this->ast_dump_context_->print_indent(); + this->ast_dump_context_->ostream() << "{" << std::endl; + this->ast_dump_context_->indent(); + + // Dump statememts. + Ast_dump_traverse_statements adts(this->ast_dump_context_); + block->traverse(&adts); + + this->ast_dump_context_->unindent(); + this->ast_dump_context_->print_indent(); + this->ast_dump_context_->ostream() << "}" << std::endl; + + return TRAVERSE_SKIP_COMPONENTS; +} + +// Dump each traversed statement. + +int +Ast_dump_traverse_statements::statement(Block* block, size_t* pindex, + Statement* statement) +{ + statement->dump_statement(this->ast_dump_context_); + + if (statement->is_block_statement()) + { + Ast_dump_traverse_blocks_and_functions adtbf(this->ast_dump_context_); + statement->traverse(block, pindex, &adtbf); + } + + return TRAVERSE_SKIP_COMPONENTS; +} + +// Dump the function header. + +int +Ast_dump_traverse_blocks_and_functions::function(Named_object* no) +{ + this->ast_dump_context_->ostream() << no->name(); + + go_assert(no->is_function()); + Function* func = no->func_value(); + + this->ast_dump_context_->ostream() << "("; + this->ast_dump_context_->dump_typed_identifier_list( + func->type()->parameters()); + + this->ast_dump_context_->ostream() << ")"; + + Function::Results* res = func->result_variables(); + if (res != NULL && !res->empty()) + { + this->ast_dump_context_->ostream() << " ("; + + for (Function::Results::const_iterator it = res->begin(); + it != res->end(); + it++) + { + if (it != res->begin()) + this->ast_dump_context_->ostream() << ","; + Named_object* no = (*it); + + this->ast_dump_context_->ostream() << no->name() << " "; + go_assert(no->is_result_variable()); + Result_variable* resvar = no->result_var_value(); + + this->ast_dump_context_->dump_type(resvar->type()); + + } + this->ast_dump_context_->ostream() << ")"; + } + + this->ast_dump_context_->ostream() << " : "; + this->ast_dump_context_->dump_type(func->type()); + this->ast_dump_context_->ostream() << std::endl; + + return TRAVERSE_CONTINUE; +} + +// Class Ast_dump_context. + +Ast_dump_context::Ast_dump_context() : ostream_(NULL) +{ +} + +// Dump files will be named %basename%.dump.ast + +const char* kAstDumpFileExtension = ".dump.ast"; + +// Dump the internal representation. + +void +Ast_dump_context::dump(Gogo* gogo, const char* basename) +{ + std::ofstream* out = new std::ofstream(); + std::string dumpname(basename); + dumpname += ".dump.ast"; + out->open(dumpname.c_str()); + + if (out->fail()) + { + error("cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str()); + return; + } + + this->indent_ = 0; + this->gogo_ = gogo; + this->ostream_ = out; + + Ast_dump_traverse_blocks_and_functions adtbf(this); + gogo->traverse(&adtbf); + + out->close(); +} + +// Dump a textual representation of a type to the +// the dump file. + +void +Ast_dump_context::dump_type(const Type* t) +{ + if (t == NULL) + this->ostream() << "(nil type)"; + else + // FIXME: write a type pretty printer instead of + // using mangled names. + this->ostream() << "(" << t->mangled_name(this->gogo_) << ")"; +} + +// Dump a textual representation of a block to the +// the dump file. + +void +Ast_dump_context::dump_block(Block* b) +{ + Ast_dump_traverse_blocks_and_functions adtbf(this); + b->traverse(&adtbf); +} + +// Dump a textual representation of an expression to the +// the dump file. + +void +Ast_dump_context::dump_expression(const Expression* e) +{ + e->dump_expression(this); +} + +// Dump a textual representation of an expression list to the +// the dump file. + +void +Ast_dump_context::dump_expression_list(const Expression_list* el) +{ + if (el == NULL) + return; + + for (std::vector::const_iterator it = el->begin(); + it != el->end(); + it++) + { + if ( it != el->begin()) + this->ostream() << ","; + (*it)->dump_expression(this); + } +} + +// Dump a textual representation of a typed identifier to the +// the dump file. + +void +Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti) +{ + this->ostream() << ti->name() << " "; + this->dump_type(ti->type()); +} + +// Dump a textual representation of a typed identifier list to the +// the dump file. + +void +Ast_dump_context::dump_typed_identifier_list( + const Typed_identifier_list* ti_list) +{ + if (ti_list == NULL) + return; + + for (Typed_identifier_list::const_iterator it = ti_list->begin(); + it != ti_list->end(); + it++) + { + if (it != ti_list->begin()) + this->ostream() << ","; + this->dump_typed_identifier(&(*it)); + } +} + +// Dump a textual representation of a temporary variable to the +// the dump file. + +void +Ast_dump_context::dump_temp_variable_name(const Statement* s) +{ + go_assert(s->classification() == Statement::STATEMENT_TEMPORARY); + // Use the statement address as part of the name for the temporary variable. + this->ostream() << "tmp." << (uintptr_t) s; +} + +// Dump a textual representation of a label to the +// the dump file. + +void +Ast_dump_context::dump_label_name(const Unnamed_label* l) +{ + // Use the unnamed label address as part of the name for the temporary + // variable. + this->ostream() << "label." << (uintptr_t) l; +} + +// Produce a textual representation of an operator symbol. + +static const char* +op_string(Operator op) +{ +// FIXME: This should be in line with symbols that are parsed, +// exported and/or imported. + switch (op) + { + case OPERATOR_PLUS: + return "+"; + case OPERATOR_MINUS: + return "-"; + case OPERATOR_NOT: + return "!"; + case OPERATOR_XOR: + return "^"; + case OPERATOR_AND: + return "&"; + case OPERATOR_MULT: + return "*"; + case OPERATOR_OROR: + return "||"; + case OPERATOR_ANDAND: + return "&&"; + case OPERATOR_EQEQ: + return "=="; + case OPERATOR_NOTEQ: + return "!="; + case OPERATOR_LT: + return "<"; + case OPERATOR_LE: + return "<="; + case OPERATOR_GT: + return ">"; + case OPERATOR_GE: + return ">="; + case OPERATOR_DIV: + return "/"; + case OPERATOR_MOD: + return "%"; + case OPERATOR_LSHIFT: + return "<<"; + case OPERATOR_RSHIFT: + return "//"; + case OPERATOR_BITCLEAR: + return "&^"; + case OPERATOR_CHANOP: + return "<-"; + case OPERATOR_PLUSEQ: + return "+="; + case OPERATOR_MINUSEQ: + return "-="; + case OPERATOR_OREQ: + return "|="; + case OPERATOR_XOREQ: + return "^="; + case OPERATOR_MULTEQ: + return "*="; + case OPERATOR_DIVEQ: + return "/="; + case OPERATOR_MODEQ: + return "%="; + case OPERATOR_LSHIFTEQ: + return "<<="; + case OPERATOR_RSHIFTEQ: + return ">>="; + case OPERATOR_ANDEQ: + return "&="; + case OPERATOR_BITCLEAREQ: + return "&^="; + case OPERATOR_PLUSPLUS: + return "++"; + case OPERATOR_MINUSMINUS: + return "--"; + case OPERATOR_COLON: + return ":"; + case OPERATOR_COLONEQ: + return ":="; + case OPERATOR_SEMICOLON: + return ";"; + case OPERATOR_DOT: + return "."; + case OPERATOR_ELLIPSIS: + return "..."; + case OPERATOR_COMMA: + return ","; + case OPERATOR_LPAREN: + return "("; + case OPERATOR_RPAREN: + return ")"; + case OPERATOR_LCURLY: + return "{"; + case OPERATOR_RCURLY: + return "}"; + case OPERATOR_LSQUARE: + return "["; + case OPERATOR_RSQUARE: + return "]"; + default: + go_unreachable(); + } + return NULL; +} + +// Dump a textual representation of an operator to the +// the dump file. + +void +Ast_dump_context::dump_operator(Operator op) +{ + this->ostream() << op_string(op); +} + +// Size of a single indent. + +const int Ast_dump_context::offset_ = 2; + +// Print indenting spaces to dump file. + +void +Ast_dump_context::print_indent() +{ + for (int i = 0; i < this->indent_ * this->offset_; i++) + this->ostream() << " "; +} + +// Dump a textual representation of the ast to the +// the dump file. + +void Gogo::dump_ast(const char* basename) +{ + if (ast_dump_context_flag.is_enabled()) + { + Ast_dump_context adc; + adc.dump(this, basename); + } +} diff --git a/gcc/go/gofrontend/ast-dump.h b/gcc/go/gofrontend/ast-dump.h new file mode 100644 index 00000000000..92a4915e625 --- /dev/null +++ b/gcc/go/gofrontend/ast-dump.h @@ -0,0 +1,96 @@ +// ast-dump.h -- AST debug dump. -*- C++ -*- + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#ifndef GO_AST_DUMP_H +#define GO_AST_DUMP_H + +class Expression; +class Expression_list; +class Named_object; +class Statement; +class Gogo; + +// This class implements fgo-dump-ast. the +// Abstract syntax tree dump of the Go program. + +class Ast_dump_context +{ + public: + Ast_dump_context(); + + // Initialize the dump context. + void + dump(Gogo*, const char* basename); + + // Dump spaces to dumpfile as indentation. + void + print_indent(); + + // Increase current indentation for print_indent(). + void + indent() + { ++this->indent_;} + + // Decrease current indentation for print_indent(). + void + unindent() + { --this->indent_;} + + // Get dump output stream. + std::ostream& + ostream() + { return *this->ostream_;} + + // Dump a Block to dump file. + void + dump_block(Block*); + + // Dump a type to dump file. + void + dump_type(const Type*); + + // Dump an expression to dump file. + void + dump_expression(const Expression*); + + // Dump an expression list to dump file. + void + dump_expression_list(const Expression_list*); + + // Dump a typed identifier to dump file. + void + dump_typed_identifier(const Typed_identifier*); + + // Dump a typed identifier list to dump file. + void + dump_typed_identifier_list(const Typed_identifier_list*); + + // Dump temporary variable name to dump file. + void + dump_temp_variable_name(const Statement*); + + // Dump unamed lable name to dump file. + void + dump_label_name(const Unnamed_label*); + + // Dump operator symbol to dump file. + void + dump_operator(Operator); + + private: + // Current indent level. + int indent_; + + // Indentation offset. + static const int offset_; + + // Stream on output dump file. + std::ostream* ostream_; + + Gogo* gogo_; +}; + +#endif // GO_AST_DUMP_H diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 433a6d7d431..fbd716ab8e9 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -36,6 +36,7 @@ extern "C" #include "runtime.h" #include "backend.h" #include "expressions.h" +#include "ast-dump.h" // Class Expression. @@ -790,6 +791,12 @@ Expression::check_bounds(tree val, tree bound_type, tree sofar, sofar, ret); } +void +Expression::dump_expression(Ast_dump_context* ast_dump_context) const +{ + this->do_dump_expression(ast_dump_context); +} + // Error expressions. This are used to avoid cascading errors. class Error_expression : public Expression @@ -849,8 +856,19 @@ class Error_expression : public Expression tree do_get_tree(Translate_context*) { return error_mark_node; } + + void + do_dump_expression(Ast_dump_context*) const; }; +// Dump the ast representation for an error expression to a dump context. + +void +Error_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "_Error_" ; +} + Expression* Expression::make_error(source_location location) { @@ -894,11 +912,19 @@ Type_expression : public Expression do_get_tree(Translate_context*) { go_unreachable(); } + void do_dump_expression(Ast_dump_context*) const; + private: // The type which we are representing as an expression. Type* type_; }; +void +Type_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->dump_type(this->type_); +} + Expression* Expression::make_type(Type* type, source_location location) { @@ -1018,6 +1044,14 @@ Var_expression::do_get_tree(Translate_context* context) return ret; } +// Ast dump for variable expression. + +void +Var_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << this->variable_->name() ; +} + // Make a reference to a variable in an expression. Expression* @@ -1076,6 +1110,15 @@ Temporary_reference_expression::do_get_tree(Translate_context* context) return ret; } +// Ast dump for temporary reference. + +void +Temporary_reference_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->dump_temp_variable_name(this->statement_); +} + // Make a reference to a temporary variable. Temporary_reference_expression* @@ -1113,6 +1156,9 @@ class Sink_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The type of this sink variable. Type* type_; @@ -1154,6 +1200,14 @@ Sink_expression::do_get_tree(Translate_context* context) return this->var_; } +// Ast dump for sink expression. + +void +Sink_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "_" ; +} + // Make a sink expression. Expression* @@ -1286,6 +1340,14 @@ Func_expression::do_get_tree(Translate_context* context) return gogo->make_trampoline(fnaddr, closure_tree, this->location()); } +// Ast dump for function. + +void +Func_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << this->function_->name() ; +} + // Make a reference to a function in an expression. Expression* @@ -1354,6 +1416,16 @@ Unknown_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int) } } +// Dump the ast representation for an unknown expression to a dump context. + +void +Unknown_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "_Unknown_(" << this->named_object_->name() + << ")"; + +} + // Make a reference to an unknown name. Expression* @@ -1399,6 +1471,10 @@ class Boolean_expression : public Expression do_export(Export* exp) const { exp->write_c_string(this->val_ ? "true" : "false"); } + void + do_dump_expression(Ast_dump_context* ast_dump_context) const + { ast_dump_context->ostream() << (this->val_ ? "true" : "false"); } + private: // The constant. bool val_; @@ -1566,6 +1642,15 @@ String_expression::do_import(Import* imp) return Expression::make_string(val, imp->location()); } +// Ast dump for string expression. + +void +String_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + // FIXME: Do proper backshlash quoting for this->val_ + ast_dump_context->ostream() << "\"" << this->val_ << "\""; +} + // Make a string expression. Expression* @@ -1595,6 +1680,10 @@ class Integer_expression : public Expression static void export_integer(Export* exp, const mpz_t val); + // Write VAL to dump context. + static void + dump_integer(Ast_dump_context* ast_dump_context, const mpz_t val); + protected: bool do_is_constant() const @@ -1623,6 +1712,9 @@ class Integer_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The integer value. mpz_t val_; @@ -1871,6 +1963,28 @@ Integer_expression::do_import(Import* imp) } } +// Write integer to dump context. + +void +Integer_expression::dump_integer(Ast_dump_context* ast_dump_context, + const mpz_t val) +{ + // FIXME: refactor this code so that is used both by dump and export. Extract + // a common interface for Ast_dump_context and Export. + char* s = mpz_get_str(NULL, 10, val); + ast_dump_context->ostream() << s ; + free(s); +} + + +// Ast dump for integer expression. + +void +Integer_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + Integer_expression::dump_integer(ast_dump_context, this->val_); +} + // Build a new integer value. Expression* @@ -1903,6 +2017,10 @@ class Float_expression : public Expression // Write VAL to export data. static void export_float(Export* exp, const mpfr_t val); + + // Write VAL to dump file. + static void + dump_float(Ast_dump_context* ast_dump_context, const mpfr_t val); protected: bool @@ -1932,6 +2050,9 @@ class Float_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The floating point value. mpfr_t val_; @@ -2109,6 +2230,35 @@ Float_expression::do_export(Export* exp) const exp->write_c_string(" "); } +// Write a floating point number to a dump context. + +void +Float_expression::dump_float(Ast_dump_context* ast_dump_context, + const mpfr_t val) +{ + // FIXME: this code should be refactored so that the same code is used here + // and in export_float. + + mp_exp_t exponent; + char* s = mpfr_get_str(NULL, &exponent, 10, 0, val, GMP_RNDN); + if (*s == '-') + ast_dump_context->ostream() << "-"; + ast_dump_context->ostream() << "0."; + ast_dump_context->ostream() << (*s == '-' ? s + 1 : s); + mpfr_free_str(s); + char buf[30]; + snprintf(buf, sizeof buf, "E%ld", exponent); + ast_dump_context->ostream() << buf; +} + +// Dump a floating point number to the dump file. + +void +Float_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + Float_expression::dump_float(ast_dump_context, this->val_); +} + // Make a float expression. Expression* @@ -2143,6 +2293,11 @@ class Complex_expression : public Expression static void export_complex(Export* exp, const mpfr_t real, const mpfr_t val); + // Write REAL/IMAG to dump context. + static void + dump_complex(Ast_dump_context* ast_dump_context, + const mpfr_t real, const mpfr_t val); + protected: bool do_is_constant() const @@ -2173,6 +2328,9 @@ class Complex_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The real part. mpfr_t real_; @@ -2342,6 +2500,34 @@ Complex_expression::do_export(Export* exp) const exp->write_c_string(" "); } +// Write a complex number to a dump context. + +void +Complex_expression::dump_complex(Ast_dump_context* ast_dump_context, + const mpfr_t real, const mpfr_t imag) +{ + // FIXME: this code should be refactored so that it is used both here + // and by export _complex + if (!mpfr_zero_p(real)) + { + Float_expression::dump_float(ast_dump_context, real); + if (mpfr_sgn(imag) > 0) + ast_dump_context->ostream() << "+"; + } + Float_expression::dump_float(ast_dump_context, imag); + ast_dump_context->ostream() << "i"; +} + +// Dump a complex expression to the dump file. + +void +Complex_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + Complex_expression::dump_complex(ast_dump_context, + this->real_, + this->imag_); +} + // Make a complex expression. Expression* @@ -2443,6 +2629,9 @@ class Const_expression : public Expression do_export(Export* exp) const { this->constant_->const_value()->expr()->export_expression(exp); } + void + do_dump_expression(Ast_dump_context*) const; + private: // The constant. Named_object* constant_; @@ -2824,6 +3013,14 @@ Const_expression::do_get_tree(Translate_context* context) return ret; } +// Dump ast representation for constant expression. + +void +Const_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << this->constant_->name(); +} + // Make a reference to a constant in an expression. Expression* @@ -2905,6 +3102,10 @@ class Nil_expression : public Expression void do_export(Export* exp) const { exp->write_c_string("nil"); } + + void + do_dump_expression(Ast_dump_context* ast_dump_context) const + { ast_dump_context->ostream() << "nil"; } }; // Import a nil expression. @@ -2945,6 +3146,10 @@ class Iota_expression : public Parser_expression Expression* do_copy() { go_unreachable(); } + + void + do_dump_expression(Ast_dump_context* ast_dump_context) const + { ast_dump_context->ostream() << "iota"; } }; // Make an iota expression. This is only called for one case: the @@ -3040,6 +3245,9 @@ class Type_conversion_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The type to convert to. Type* type_; @@ -3570,6 +3778,18 @@ Type_conversion_expression::do_import(Import* imp) return Expression::make_cast(type, val, imp->location()); } +// Dump ast representation for a type conversion expression. + +void +Type_conversion_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << "("; + ast_dump_context->dump_expression(this->expr_); + ast_dump_context->ostream() << ") "; +} + // Make a type cast expression. Expression* @@ -3614,6 +3834,9 @@ class Unsafe_type_conversion_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The type to convert to. Type* type_; @@ -3698,6 +3921,18 @@ Unsafe_type_conversion_expression::do_get_tree(Translate_context* context) return fold_convert_loc(loc, type_tree, expr_tree); } +// Dump ast representation for an unsafe type conversion expression. + +void +Unsafe_type_conversion_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << "("; + ast_dump_context->dump_expression(this->expr_); + ast_dump_context->ostream() << ") "; +} + // Make an unsafe type conversion expression. Expression* @@ -3801,6 +4036,9 @@ class Unary_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The unary operator to apply. Operator op_; @@ -4412,6 +4650,17 @@ Unary_expression::do_import(Import* imp) return Expression::make_unary(op, expr, imp->location()); } +// Dump ast representation of an unary expression. + +void +Unary_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->dump_operator(this->op_); + ast_dump_context->ostream() << "("; + ast_dump_context->dump_expression(this->expr_); + ast_dump_context->ostream() << ") "; +} + // Make a unary expression. Expression* @@ -6311,6 +6560,20 @@ Binary_expression::do_import(Import* imp) return Expression::make_binary(op, left, right, imp->location()); } +// Dump ast representation of a binary expression. + +void +Binary_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "("; + ast_dump_context->dump_expression(this->left_); + ast_dump_context->ostream() << " "; + ast_dump_context->dump_operator(this->op_); + ast_dump_context->ostream() << " "; + ast_dump_context->dump_expression(this->right_); + ast_dump_context->ostream() << ") "; +} + // Make a binary expression. Expression* @@ -6643,6 +6906,26 @@ Bound_method_expression::do_get_tree(Translate_context*) return error_mark_node; } +// Dump ast representation of a bound method expression. + +void +Bound_method_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + if (this->expr_type_ != NULL) + ast_dump_context->ostream() << "("; + ast_dump_context->dump_expression(this->expr_); + if (this->expr_type_ != NULL) + { + ast_dump_context->ostream() << ":"; + ast_dump_context->dump_type(this->expr_type_); + ast_dump_context->ostream() << ")"; + } + + ast_dump_context->ostream() << "."; + ast_dump_context->dump_expression(method_); +} + // Make a method expression. Bound_method_expression* @@ -9298,6 +9581,19 @@ Call_expression::set_results(Translate_context* context, tree call_tree) return save_expr(stmt_list); } +// Dump ast representation for a call expressin. + +void +Call_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + this->fn_->dump_expression(ast_dump_context); + ast_dump_context->ostream() << "("; + if (args_ != NULL) + ast_dump_context->dump_expression_list(this->args_); + + ast_dump_context->ostream() << ") "; +} + // Make a call expression. Call_expression* @@ -9344,6 +9640,9 @@ class Call_result_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The underlying call expression. Expression* call_; @@ -9443,6 +9742,19 @@ Call_result_expression::do_get_tree(Translate_context* context) return ref->get_tree(context); } +// Dump ast representation for a call result expression. + +void +Call_result_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + // FIXME: Wouldn't it be better if the call is assigned to a temporary + // (struct) and the fields are referenced instead. + ast_dump_context->ostream() << this->index_ << "@("; + ast_dump_context->dump_expression(this->call_); + ast_dump_context->ostream() << ")"; +} + // Make a reference to a single result of a call which returns // multiple results. @@ -9519,6 +9831,36 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int) } } +// Write an indexed expression (expr[expr:expr] or expr[expr]) to a +// dump context + +void +Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context, + const Expression* expr, + const Expression* start, + const Expression* end) +{ + expr->dump_expression(ast_dump_context); + ast_dump_context->ostream() << "["; + start->dump_expression(ast_dump_context); + if (end != NULL) + { + ast_dump_context->ostream() << ":"; + end->dump_expression(ast_dump_context); + } + ast_dump_context->ostream() << "]"; +} + +// Dump ast representation for an index expression. + +void +Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + Index_expression::dump_index_expression(ast_dump_context, this->left_, + this->start_, this->end_); +} + // Make an index expression. Expression* @@ -9573,6 +9915,9 @@ class Array_index_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The array we are getting a value from. Expression* array_; @@ -9922,6 +10267,16 @@ Array_index_expression::do_get_tree(Translate_context* context) constructor); } +// Dump ast representation for an array index expression. + +void +Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + Index_expression::dump_index_expression(ast_dump_context, this->array_, + this->start_, this->end_); +} + // Make an array index expression. END may be NULL. Expression* @@ -9976,6 +10331,9 @@ class String_index_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The string we are getting a value from. Expression* string_; @@ -10176,6 +10534,16 @@ String_index_expression::do_get_tree(Translate_context* context) } } +// Dump ast representation for a string index expression. + +void +String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + Index_expression::dump_index_expression(ast_dump_context, this->string_, + this->start_, this->end_); +} + // Make a string index expression. END may be NULL. Expression* @@ -10390,6 +10758,16 @@ Map_index_expression::get_value_pointer(Translate_context* context, return ret; } +// Dump ast representation for a map index expression + +void +Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + Index_expression::dump_index_expression(ast_dump_context, + this->map_, this->index_, NULL); +} + // Make a map index expression. Map_index_expression* @@ -10456,6 +10834,16 @@ Field_reference_expression::do_get_tree(Translate_context* context) NULL_TREE); } +// Dump ast representation for a field reference expression. + +void +Field_reference_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + this->expr_->dump_expression(ast_dump_context); + ast_dump_context->ostream() << "." << this->field_index_; +} + // Make a reference to a qualified identifier in an expression. Field_reference_expression* @@ -10602,6 +10990,16 @@ Interface_field_reference_expression::do_get_tree(Translate_context*) go_unreachable(); } +// Dump ast representation for an interface field reference. + +void +Interface_field_reference_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + this->expr_->dump_expression(ast_dump_context); + ast_dump_context->ostream() << "." << this->name_; +} + // Make a reference to a field in an interface. Expression* @@ -10639,6 +11037,9 @@ class Selector_expression : public Parser_expression this->location()); } + void + do_dump_expression(Ast_dump_context* ast_dump_context) const; + private: Expression* lower_method_expression(Gogo*); @@ -10859,6 +11260,17 @@ Selector_expression::lower_method_expression(Gogo* gogo) return Expression::make_func_reference(no, NULL, location); } +// Dump the ast for a selector expression. + +void +Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->dump_expression(this->left_); + ast_dump_context->ostream() << "."; + ast_dump_context->ostream() << this->name_; +} + // Make a selector expression. Expression* @@ -10898,6 +11310,9 @@ class Allocation_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The type we are allocating. Type* type_; @@ -10919,6 +11334,17 @@ Allocation_expression::do_get_tree(Translate_context* context) return fold_convert(build_pointer_type(type_tree), space); } +// Dump ast representation for an allocation expression. + +void +Allocation_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->ostream() << "new("; + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << ")"; +} + // Make an allocation expression. Expression* @@ -10973,6 +11399,9 @@ class Struct_construction_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The type of the struct to construct. Type* type_; @@ -11185,6 +11614,19 @@ Struct_construction_expression::do_export(Export* exp) const exp->write_c_string(")"); } +// Dump ast representation of a struct construction expression. + +void +Struct_construction_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << "{"; + ast_dump_context->dump_expression_list(this->vals_); + ast_dump_context->ostream() << "}"; +} + // Make a struct composite literal. This used by the thunk code. Expression* @@ -11249,6 +11691,9 @@ protected: tree get_constructor_tree(Translate_context* context, tree type_tree); + void + do_dump_expression(Ast_dump_context*) const; + private: // The type of the array to construct. Type* type_; @@ -11422,6 +11867,19 @@ Array_construction_expression::do_export(Export* exp) const exp->write_c_string(")"); } +// Dump ast representation of an array construction expressin. + +void +Array_construction_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << "{" ; + ast_dump_context->dump_expression_list(this->vals_); + ast_dump_context->ostream() << "}" ; + +} + // Construct a fixed array. class Fixed_array_construction_expression : @@ -11688,6 +12146,9 @@ class Map_construction_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The type of the map to construct. Type* type_; @@ -11941,6 +12402,18 @@ Map_construction_expression::do_export(Export* exp) const exp->write_c_string(")"); } +// Dump ast representation for a map construction expression. + +void +Map_construction_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + // FIXME: We should print key:value pairs here. + ast_dump_context->ostream() << "{" ; + ast_dump_context->dump_expression_list(this->vals_); + ast_dump_context->ostream() << "}"; +} + // A general composite literal. This is lowered to a type specific // version. @@ -11971,6 +12444,9 @@ class Composite_literal_expression : public Parser_expression this->location()); } + void + do_dump_expression(Ast_dump_context*) const; + private: Expression* lower_struct(Gogo*, Type*); @@ -12382,6 +12858,20 @@ Composite_literal_expression::lower_map(Gogo* gogo, Named_object* function, return new Map_construction_expression(type, this->vals_, location); } +// Dump ast representation for a composite literal expression. + +void +Composite_literal_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + // FIXME: We should print colons if this->has_keys_ is true + ast_dump_context->ostream() << "composite_literal(" ; + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << ", {"; + ast_dump_context->dump_expression_list(this->vals_); + ast_dump_context->ostream() << "})"; +} + // Make a composite literal expression. Expression* @@ -12556,6 +13046,17 @@ Type_guard_expression::do_get_tree(Translate_context* context) this->location()); } +// Dump ast representation for a type guard expression. + +void +Type_guard_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + this->expr_->dump_expression(ast_dump_context); + ast_dump_context->ostream() << "."; + ast_dump_context->dump_type(this->type_); +} + // Make a type guard expression. Expression* @@ -12607,6 +13108,9 @@ class Heap_composite_expression : public Expression do_export(Export*) const { go_unreachable(); } + void + do_dump_expression(Ast_dump_context*) const; + private: // The composite literal which is being put on the heap. Expression* expr_; @@ -12635,6 +13139,17 @@ Heap_composite_expression::do_get_tree(Translate_context* context) return ret; } +// Dump ast representation for a heap composite expression. + +void +Heap_composite_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "&("; + ast_dump_context->dump_expression(this->expr_); + ast_dump_context->ostream() << ")"; +} + // Allocate a composite literal on the heap. Expression* @@ -12702,6 +13217,15 @@ Receive_expression::do_get_tree(Translate_context* context) this->for_select_, this->location()); } +// Dump ast representation for a receive expression. + +void +Receive_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << " <- " ; + ast_dump_context->dump_expression(channel_); +} + // Make a receive expression. Receive_expression* @@ -12741,11 +13265,23 @@ class Type_descriptor_expression : public Expression this->location()); } + void + do_dump_expression(Ast_dump_context*) const; + private: // The type for which this is the descriptor. Type* type_; }; +// Dump ast representation for a type descriptor expression. + +void +Type_descriptor_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->dump_type(this->type_); +} + // Make a type descriptor expression. Expression* @@ -12783,6 +13319,9 @@ class Type_info_expression : public Expression tree do_get_tree(Translate_context* context); + void + do_dump_expression(Ast_dump_context*) const; + private: // The type for which we are getting information. Type* type_; @@ -12834,6 +13373,23 @@ Type_info_expression::do_get_tree(Translate_context* context) } } +// Dump ast representation for a type info expression. + +void +Type_info_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "typeinfo("; + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << ","; + ast_dump_context->ostream() << + (this->type_info_ == TYPE_INFO_ALIGNMENT ? "alignment" + : this->type_info_ == TYPE_INFO_FIELD_ALIGNMENT ? "field alignment" + : this->type_info_ == TYPE_INFO_SIZE ? "size " + : "unknown"); + ast_dump_context->ostream() << ")"; +} + // Make a type info expression. Expression* @@ -12870,6 +13426,9 @@ class Struct_field_offset_expression : public Expression tree do_get_tree(Translate_context* context); + void + do_dump_expression(Ast_dump_context*) const; + private: // The type of the struct. Struct_type* type_; @@ -12906,6 +13465,17 @@ Struct_field_offset_expression::do_get_tree(Translate_context* context) byte_position(struct_field_tree)); } +// Dump ast representation for a struct field offset expression. + +void +Struct_field_offset_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "unsafe.Offsetof("; + ast_dump_context->ostream() << this->field_->field_name(); + ast_dump_context->ostream() << ")"; +} + // Make an expression for a struct field offset. Expression* @@ -12946,11 +13516,25 @@ class Map_descriptor_expression : public Expression this->location()); } + void + do_dump_expression(Ast_dump_context*) const; + private: // The type for which this is the descriptor. Map_type* type_; }; +// Dump ast representation for a map descriptor expression. + +void +Map_descriptor_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "map_descriptor("; + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << ")"; +} + // Make a map descriptor expression. Expression* @@ -12988,6 +13572,10 @@ class Label_addr_expression : public Expression return expr_to_tree(this->label_->get_addr(context, this->location())); } + void + do_dump_expression(Ast_dump_context* ast_dump_context) const + { ast_dump_context->ostream() << this->label_->name(); } + private: // The label whose address we are taking. Label* label_; diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index da31f149ae0..6f74f73eb1a 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -42,6 +42,7 @@ class Export; class Import; class Temporary_statement; class Label; +class Ast_dump_context; // The base class for all expressions. @@ -635,6 +636,10 @@ class Expression static tree check_bounds(tree val, tree bound_type, tree sofar, source_location); + // Dump an expression to a dump constext. + void + dump_expression(Ast_dump_context*) const; + protected: // May be implemented by child class: traverse the expressions. virtual int @@ -731,6 +736,10 @@ class Expression void report_error(const char*); + // Child class implements dumping to a dump context. + virtual void + do_dump_expression(Ast_dump_context*) const = 0; + private: // Convert to the desired statement classification, or return NULL. // This is a controlled dynamic cast. @@ -934,6 +943,9 @@ class Var_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The variable we are referencing. Named_object* variable_; @@ -978,6 +990,9 @@ class Temporary_reference_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The statement where the temporary variable is defined. Temporary_statement* statement_; @@ -1031,6 +1046,9 @@ class String_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The string value. This is immutable. const std::string val_; @@ -1154,6 +1172,9 @@ class Binary_expression : public Expression void do_export(Export*) const; + void + do_dump_expression(Ast_dump_context*) const; + private: // The binary operator to apply. Operator op_; @@ -1290,6 +1311,9 @@ class Call_expression : public Expression bool determining_types(); + void + do_dump_expression(Ast_dump_context*) const; + private: bool check_argument_type(int, const Type*, const Type*, source_location, bool); @@ -1384,6 +1408,9 @@ class Func_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The function itself. Named_object* function_; @@ -1432,6 +1459,9 @@ class Unknown_expression : public Parser_expression do_copy() { return new Unknown_expression(this->named_object_, this->location()); } + void + do_dump_expression(Ast_dump_context*) const; + private: // The unknown name. Named_object* named_object_; @@ -1456,6 +1486,12 @@ class Index_expression : public Parser_expression set_is_lvalue() { this->is_lvalue_ = true; } + // Dump an index expression, i.e. an expression of the form + // expr[expr] or expr[expr:expr], to a dump context. + static void + dump_index_expression(Ast_dump_context*, const Expression* expr, + const Expression* start, const Expression* end); + protected: int do_traverse(Traverse*); @@ -1473,6 +1509,9 @@ class Index_expression : public Parser_expression this->location()); } + void + do_dump_expression(Ast_dump_context*) const; + private: // The expression being indexed. Expression* left_; @@ -1572,6 +1611,9 @@ class Map_index_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The map we are looking into. Expression* map_; @@ -1641,6 +1683,9 @@ class Bound_method_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The object used to find the method. This is passed to the method // as the first argument. @@ -1712,6 +1757,9 @@ class Field_reference_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The expression we are looking into. This should have a type of // struct. @@ -1777,6 +1825,9 @@ class Interface_field_reference_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The expression for the interface object. This should have a type // of interface or pointer to interface. @@ -1830,6 +1881,9 @@ class Type_guard_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The expression to convert. Expression* expr_; @@ -1889,6 +1943,9 @@ class Receive_expression : public Expression tree do_get_tree(Translate_context*); + void + do_dump_expression(Ast_dump_context*) const; + private: // The channel from which we are receiving. Expression* channel_; diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc index 3dc34402765..4ab0f8ee7cf 100644 --- a/gcc/go/gofrontend/go.cc +++ b/gcc/go/gofrontend/go.cc @@ -133,6 +133,9 @@ go_parse_input_files(const char** filenames, unsigned int filename_count, // Convert complicated go and defer statements into simpler ones. ::gogo->simplify_thunk_statements(); + + // Dump ast, use filename[0] as the base name + ::gogo->dump_ast(filenames[0]); } // Write out globals. diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index c9d2971daf5..dae22f51c05 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -422,6 +422,10 @@ class Gogo void simplify_thunk_statements(); + // Dump AST if -fgo-dump-ast is set + void + dump_ast(const char* basename); + // Convert named types to the backend representation. void convert_named_types(); @@ -512,7 +516,6 @@ class Gogo receive_as_64bit_integer(tree type, tree channel, bool blocking, bool for_select); - // Make a trampoline which calls FNADDR passing CLOSURE. tree make_trampoline(tree fnaddr, tree closure, source_location); diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index dd2aef6f10a..c6d2ace91f8 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -15,6 +15,7 @@ #include "runtime.h" #include "backend.h" #include "statements.h" +#include "ast-dump.h" // Class Statement. @@ -142,6 +143,14 @@ Statement::get_backend(Translate_context* context) return this->do_get_backend(context); } +// Dump AST representation for a statement to a dump context. + +void +Statement::dump_statement(Ast_dump_context* ast_dump_context) const +{ + this->do_dump_statement(ast_dump_context); +} + // Note that this statement is erroneous. This is called by children // when they discover an error. @@ -178,8 +187,20 @@ class Error_statement : public Statement Bstatement* do_get_backend(Translate_context*) { go_unreachable(); } + + void + do_dump_statement(Ast_dump_context*) const; }; +// Dump the AST representation for an error statement. + +void +Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "Error statement" << std::endl; +} + // Make an error statement. Statement* @@ -280,6 +301,30 @@ Variable_declaration_statement::do_get_backend(Translate_context* context) return context->backend()->statement_list(stats); } +// Dump the AST representation for a variable declaration. + +void +Variable_declaration_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + + go_assert(var_->is_variable()); + ast_dump_context->ostream() << "var " << this->var_->name() << " "; + Variable* var = this->var_->var_value(); + if (var->has_type()) + { + ast_dump_context->dump_type(var->type()); + ast_dump_context->ostream() << " "; + } + if (var->init() != NULL) + { + ast_dump_context->ostream() << "= "; + ast_dump_context->dump_expression(var->init()); + } + ast_dump_context->ostream() << std::endl; +} + // Make a variable declaration. Statement* @@ -422,6 +467,27 @@ Temporary_statement::get_backend_variable(Translate_context* context) const return this->bvariable_; } +// Dump the AST represemtation for a temporary statement + +void +Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_temp_variable_name(this); + if (this->type_ != NULL) + { + ast_dump_context->ostream() << " "; + ast_dump_context->dump_type(this->type_); + + } + if (this->init_ != NULL) + { + ast_dump_context->ostream() << " = "; + ast_dump_context->dump_expression(this->init_); + } + ast_dump_context->ostream() << std::endl; +} + // Make and initialize a temporary variable in BLOCK. Temporary_statement* @@ -458,6 +524,9 @@ class Assignment_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: // Left hand side--the lvalue. Expression* lhs_; @@ -542,6 +611,19 @@ Assignment_statement::do_get_backend(Translate_context* context) this->location()); } +// Dump the AST representation for an assignment statement. + +void +Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(this->lhs_); + ast_dump_context->ostream() << " = " ; + ast_dump_context->dump_expression(this->rhs_); + ast_dump_context->ostream() << std::endl; +} + // Make an assignment statement. Statement* @@ -614,6 +696,9 @@ class Assignment_operation_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // The operator (OPERATOR_PLUSEQ, etc.). Operator op_; @@ -704,6 +789,19 @@ Assignment_operation_statement::do_lower(Gogo*, Named_object*, } } +// Dump the AST representation for an assignment operation statement + +void +Assignment_operation_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(this->lhs_); + ast_dump_context->dump_operator(this->op_); + ast_dump_context->dump_expression(this->rhs_); + ast_dump_context->ostream() << std::endl; +} + // Make an assignment operation statement. Statement* @@ -741,6 +839,9 @@ class Tuple_assignment_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // Left hand side--a list of lvalues. Expression_list* lhs_; @@ -768,7 +869,7 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, source_location loc = this->location(); Block* b = new Block(enclosing, loc); - + // First move out any subexpressions on the left hand side. The // right hand side will be evaluated in the required order anyhow. Move_ordered_evals moe(b); @@ -832,6 +933,19 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, return Statement::make_block_statement(b, loc); } +// Dump the AST representation for a tuple assignment statement. + +void +Tuple_assignment_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression_list(this->lhs_); + ast_dump_context->ostream() << " = "; + ast_dump_context->dump_expression_list(this->rhs_); + ast_dump_context->ostream() << std::endl; +} + // Make a tuple assignment statement. Statement* @@ -869,6 +983,9 @@ public: do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // Lvalue which receives the value from the map. Expression* val_; @@ -960,6 +1077,21 @@ Tuple_map_assignment_statement::do_lower(Gogo*, Named_object*, return Statement::make_block_statement(b, loc); } +// Dump the AST representation for a tuple map assignment statement. + +void +Tuple_map_assignment_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(this->val_); + ast_dump_context->ostream() << ", "; + ast_dump_context->dump_expression(this->present_); + ast_dump_context->ostream() << " = "; + ast_dump_context->dump_expression(this->map_index_); + ast_dump_context->ostream() << std::endl; +} + // Make a map assignment statement which returns a pair of values. Statement* @@ -998,6 +1130,9 @@ class Map_assignment_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // A reference to the map index which should be set or deleted. Expression* map_index_; @@ -1076,6 +1211,21 @@ Map_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, return Statement::make_block_statement(b, loc); } +// Dump the AST representation for a map assignment statement. + +void +Map_assignment_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(this->map_index_); + ast_dump_context->ostream() << " = "; + ast_dump_context->dump_expression(this->val_); + ast_dump_context->ostream() << ", "; + ast_dump_context->dump_expression(this->should_set_); + ast_dump_context->ostream() << std::endl; +} + // Make a statement which assigns a pair of entries to a map. Statement* @@ -1113,6 +1263,9 @@ class Tuple_receive_assignment_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // Lvalue which receives the value from the channel. Expression* val_; @@ -1200,6 +1353,21 @@ Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*, return Statement::make_block_statement(b, loc); } +// Dump the AST representation for a tuple receive statement. + +void +Tuple_receive_assignment_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(this->val_); + ast_dump_context->ostream() << ", "; + ast_dump_context->dump_expression(this->closed_); + ast_dump_context->ostream() << " <- "; + ast_dump_context->dump_expression(this->channel_); + ast_dump_context->ostream() << std::endl; +} + // Make a nonblocking receive statement. Statement* @@ -1240,6 +1408,9 @@ class Tuple_type_guard_assignment_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: Call_expression* lower_to_type(Runtime::Function); @@ -1375,6 +1546,23 @@ Tuple_type_guard_assignment_statement::lower_to_object_type( b->add_statement(s); } +// Dump the AST representation for a tuple type guard statement. + +void +Tuple_type_guard_assignment_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(this->val_); + ast_dump_context->ostream() << ", "; + ast_dump_context->dump_expression(this->ok_); + ast_dump_context->ostream() << " = "; + ast_dump_context->dump_expression(this->expr_); + ast_dump_context->ostream() << " . "; + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << std::endl; +} + // Make an assignment from a type guard to a pair of variables. Statement* @@ -1415,6 +1603,9 @@ class Expression_statement : public Statement Bstatement* do_get_backend(Translate_context* context); + void + do_dump_statement(Ast_dump_context*) const; + private: Expression* expr_; }; @@ -1459,6 +1650,17 @@ Expression_statement::do_get_backend(Translate_context* context) return context->backend()->expression_statement(tree_to_expr(expr_tree)); } +// Dump the AST representation for an expression statement + +void +Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(expr_); + ast_dump_context->ostream() << std::endl; +} + // Make an expression statement from an Expression. Statement* @@ -1494,6 +1696,9 @@ class Block_statement : public Statement Bstatement* do_get_backend(Translate_context* context); + void + do_dump_statement(Ast_dump_context*) const; + private: Block* block_; }; @@ -1507,6 +1712,14 @@ Block_statement::do_get_backend(Translate_context* context) return context->backend()->block_statement(bblock); } +// Dump the AST for a block statement + +void +Block_statement::do_dump_statement(Ast_dump_context*) const +{ + // block statement braces are dumped when traversing. +} + // Make a block statement. Statement* @@ -1541,6 +1754,9 @@ class Inc_dec_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // The l-value to increment or decrement. Expression* expr_; @@ -1564,6 +1780,16 @@ Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*) return Statement::make_assignment_operation(op, this->expr_, oexpr, loc); } +// Dump the AST representation for a inc/dec statement. + +void +Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(expr_); + ast_dump_context->ostream() << (is_inc_? "++": "--") << std::endl; +} + // Make an increment statement. Statement* @@ -2233,6 +2459,17 @@ Go_statement::do_get_backend(Translate_context* context) return context->backend()->expression_statement(call_bexpr); } +// Dump the AST representation for go statement. + +void +Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "go "; + ast_dump_context->dump_expression(this->call()); + ast_dump_context->ostream() << std::endl; +} + // Make a go statement. Statement* @@ -2261,6 +2498,17 @@ Defer_statement::do_get_backend(Translate_context* context) return context->backend()->expression_statement(call_bexpr); } +// Dump the AST representation for defer statement. + +void +Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "defer "; + ast_dump_context->dump_expression(this->call()); + ast_dump_context->ostream() << std::endl; +} + // Make a defer statement. Statement* @@ -2445,6 +2693,17 @@ Return_statement::do_get_backend(Translate_context* context) retvals, loc); } +// Dump the AST representation for a return statement. + +void +Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "return " ; + ast_dump_context->dump_expression_list(this->vals_); + ast_dump_context->ostream() << std::endl; +} + // Make a return statement. Statement* @@ -2481,6 +2740,9 @@ class Bc_statement : public Statement do_get_backend(Translate_context* context) { return this->label_->get_goto(context, this->location()); } + void + do_dump_statement(Ast_dump_context*) const; + private: // The label that this branches to. Unnamed_label* label_; @@ -2488,6 +2750,21 @@ class Bc_statement : public Statement bool is_break_; }; +// Dump the AST representation for a break/continue statement + +void +Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue"); + if (this->label_ != NULL) + { + ast_dump_context->ostream() << " "; + ast_dump_context->dump_label_name(this->label_); + } + ast_dump_context->ostream() << std::endl; +} + // Make a break statement. Statement* @@ -2530,6 +2807,9 @@ class Goto_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: Label* label_; }; @@ -2557,6 +2837,15 @@ Goto_statement::do_get_backend(Translate_context* context) return context->backend()->goto_statement(blabel, this->location()); } +// Dump the AST representation for a goto statement. + +void +Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "goto " << this->label_->name() << std::endl; +} + // Make a goto statement. Statement* @@ -2588,10 +2877,25 @@ class Goto_unnamed_statement : public Statement do_get_backend(Translate_context* context) { return this->label_->get_goto(context, this->location()); } + void + do_dump_statement(Ast_dump_context*) const; + private: Unnamed_label* label_; }; +// Dump the AST representation for an unnamed goto statement + +void +Goto_unnamed_statement::do_dump_statement( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "goto "; + ast_dump_context->dump_label_name(this->label_); + ast_dump_context->ostream() << std::endl; +} + // Make a goto statement to an unnamed label. Statement* @@ -2621,6 +2925,15 @@ Label_statement::do_get_backend(Translate_context* context) return context->backend()->label_definition_statement(blabel); } +// Dump the AST for a label definition statement. + +void +Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << this->label_->name() << ":" << std::endl; +} + // Make a label statement. Statement* @@ -2648,11 +2961,25 @@ class Unnamed_label_statement : public Statement do_get_backend(Translate_context* context) { return this->label_->get_definition(context); } + void + do_dump_statement(Ast_dump_context*) const; + private: // The label. Unnamed_label* label_; }; +// Dump the AST representation for an unnamed label definition statement. + +void +Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_label_name(this->label_); + ast_dump_context->ostream() << ":" << std::endl; +} + // Make an unnamed label statement. Statement* @@ -2688,6 +3015,9 @@ class If_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: Expression* cond_; Block* then_block_; @@ -2759,6 +3089,24 @@ If_statement::do_get_backend(Translate_context* context) else_block, this->location()); } +// Dump the AST representation for an if statement + +void +If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "if "; + ast_dump_context->dump_expression(this->cond_); + ast_dump_context->ostream() << std::endl; + ast_dump_context->dump_block(this->then_block_); + if (this->else_block_ != NULL) + { + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "else" << std::endl; + ast_dump_context->dump_block(this->else_block_); + } +} + // Make an if statement. Statement* @@ -3050,6 +3398,31 @@ Case_clauses::Case_clause::get_backend(Translate_context* context, return context->backend()->compound_statement(statements, break_stat); } +// Dump the AST representation for a case clause + +void +Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->print_indent(); + if (this->is_default_) + { + ast_dump_context->ostream() << "default:"; + } + else + { + ast_dump_context->ostream() << "case "; + ast_dump_context->dump_expression_list(this->cases_); + ast_dump_context->ostream() << ":" ; + } + ast_dump_context->dump_block(this->statements_); + if (this->is_fallthrough_) + { + ast_dump_context->print_indent(); + ast_dump_context->ostream() << " (fallthrough)" << std::endl; + } +} + // Class Case_clauses. // Traversal. @@ -3212,6 +3585,17 @@ Case_clauses::get_backend(Translate_context* context, } } +// Dump the AST representation for case clauses (from a switch statement) + +void +Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const +{ + for (Clauses::const_iterator p = this->clauses_.begin(); + p != this->clauses_.end(); + ++p) + p->dump_clause(ast_dump_context); +} + // A constant switch statement. A Switch_statement is lowered to this // when all the cases are constants. @@ -3241,6 +3625,9 @@ class Constant_switch_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: // The value to switch on. Expression* val_; @@ -3320,6 +3707,20 @@ Constant_switch_statement::do_get_backend(Translate_context* context) return context->backend()->compound_statement(switch_statement, ldef); } +// Dump the AST representation for a constant switch statement. + +void +Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "switch "; + ast_dump_context->dump_expression(this->val_); + ast_dump_context->ostream() << " {" << std::endl; + this->clauses_->dump_clauses(ast_dump_context); + ast_dump_context->ostream() << "}" << std::endl; +} + // Class Switch_statement. // Traversal. @@ -3395,6 +3796,24 @@ Switch_statement::break_label() return this->break_label_; } +// Dump the AST representation for a switch statement. + +void +Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "switch "; + if (this->val_ != NULL) + { + ast_dump_context->dump_expression(this->val_); + ast_dump_context->ostream() << " "; + } + ast_dump_context->ostream() << "{" << std::endl; + this->clauses_->dump_clauses(ast_dump_context); + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "}" << std::endl; +} + // Make a switch statement. Switch_statement* @@ -3519,6 +3938,31 @@ Type_case_clauses::Type_case_clause::lower(Block* b, } } +// Dump the AST representation for a type case clause + +void +Type_case_clauses::Type_case_clause::dump_clause( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + if (this->is_default_) + { + ast_dump_context->ostream() << "default:"; + } + else + { + ast_dump_context->ostream() << "case "; + ast_dump_context->dump_type(this->type_); + ast_dump_context->ostream() << ":" ; + } + ast_dump_context->dump_block(this->statements_); + if (this->is_fallthrough_) + { + ast_dump_context->print_indent(); + ast_dump_context->ostream() << " (fallthrough)" << std::endl; + } +} + // Class Type_case_clauses. // Traversal. @@ -3589,6 +4033,17 @@ Type_case_clauses::lower(Block* b, Temporary_statement* descriptor_temp, default_case->lower(b, descriptor_temp, break_label, NULL); } +// Dump the AST representation for case clauses (from a switch statement) + +void +Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const +{ + for (Type_clauses::const_iterator p = this->clauses_.begin(); + p != this->clauses_.end(); + ++p) + p->dump_clause(ast_dump_context); +} + // Class Type_switch_statement. // Traversal. @@ -3692,6 +4147,20 @@ Type_switch_statement::break_label() return this->break_label_; } +// Dump the AST representation for a type switch statement + +void +Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "switch " << this->var_->name() << " = "; + ast_dump_context->dump_expression(this->expr_); + ast_dump_context->ostream() << " .(type) {" << std::endl; + this->clauses_->dump_clauses(ast_dump_context); + ast_dump_context->ostream() << "}" << std::endl; +} + // Make a type switch statement. Type_switch_statement* @@ -3862,6 +4331,18 @@ Send_statement::do_get_backend(Translate_context* context) return context->backend()->compound_statement(btemp, s); } +// Dump the AST representation for a send statement + +void +Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->dump_expression(this->channel_); + ast_dump_context->ostream() << " <- "; + ast_dump_context->dump_expression(this->val_); + ast_dump_context->ostream() << std::endl; +} + // Make a send statement. Send_statement* @@ -4053,6 +4534,48 @@ Select_clauses::Select_clause::get_statements_backend( return context->backend()->block_statement(bblock); } +// Dump the AST representation for a select case clause + +void +Select_clauses::Select_clause::dump_clause( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + if (this->is_default_) + { + ast_dump_context->ostream() << "default:"; + } + else + { + ast_dump_context->ostream() << "case " ; + if (this->is_send_) + { + ast_dump_context->dump_expression(this->channel_); + ast_dump_context->ostream() << " <- " ; + ast_dump_context->dump_expression(this->val_); + } + else + { + if (this->val_ != NULL) + ast_dump_context->dump_expression(this->val_); + if (this->closed_ != NULL) + { + // FIXME: can val_ == NULL and closed_ ! = NULL? + ast_dump_context->ostream() << " , " ; + ast_dump_context->dump_expression(this->closed_); + } + if (this->closedvar_ != NULL || + this->var_ != NULL) + ast_dump_context->ostream() << " := " ; + + ast_dump_context->ostream() << " <- " ; + ast_dump_context->dump_expression(this->channel_); + } + ast_dump_context->ostream() << ":" ; + } + ast_dump_context->dump_block(this->statements_); +} + // Class Select_clauses. // Traversal. @@ -4326,6 +4849,17 @@ Select_clauses::add_clause_backend( (*clauses)[index] = context->backend()->compound_statement(s, g); } +// Dump the AST representation for select clauses. + +void +Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const +{ + for (Clauses::const_iterator p = this->clauses_.begin(); + p != this->clauses_.end(); + ++p) + p->dump_clause(ast_dump_context); +} + // Class Select_statement. // Return the break label for this switch statement, creating it if @@ -4366,6 +4900,17 @@ Select_statement::do_get_backend(Translate_context* context) this->location()); } +// Dump the AST representation for a select statement. + +void +Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "select {" << std::endl; + this->clauses_->dump_clauses(ast_dump_context); + ast_dump_context->ostream() << "}" << std::endl; +} + // Make a select statement. Select_statement* @@ -4501,6 +5046,38 @@ For_statement::set_break_continue_labels(Unnamed_label* break_label, this->continue_label_ = continue_label; } +// Dump the AST representation for a for statement. + +void +For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + if (this->init_ != NULL) + { + ast_dump_context->print_indent(); + ast_dump_context->indent(); + ast_dump_context->ostream() << "// INIT " << std::endl; + ast_dump_context->dump_block(this->init_); + ast_dump_context->unindent(); + } + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "for "; + if (this->cond_ != NULL) + ast_dump_context->dump_expression(this->cond_); + ast_dump_context->ostream() << " {" << std::endl; + ast_dump_context->indent(); + + ast_dump_context->dump_block(this->statements_); + if (this->init_ != NULL) + { + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "// POST " << std::endl; + ast_dump_context->dump_block(this->post_); + } + ast_dump_context->unindent(); + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "}" << std::endl; +} + // Make a for statement. For_statement* @@ -5119,6 +5696,33 @@ For_range_statement::continue_label() return this->continue_label_; } +// Dump the AST representation for a for range statement. + +void +For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const +{ + + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "for "; + ast_dump_context->dump_expression(this->index_var_); + if (this->value_var_ != NULL) + { + ast_dump_context->ostream() << ", "; + ast_dump_context->dump_expression(this->value_var_); + } + + ast_dump_context->ostream() << " = range "; + ast_dump_context->dump_expression(this->range_); + ast_dump_context->ostream() << " {" << std::endl; + ast_dump_context->indent(); + + ast_dump_context->dump_block(this->statements_); + + ast_dump_context->unindent(); + ast_dump_context->print_indent(); + ast_dump_context->ostream() << "}" << std::endl; +} + // Make a for statement with a range clause. For_range_statement* diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 44241ab1152..8b5263bb820 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -43,6 +43,7 @@ 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. @@ -374,6 +375,10 @@ class Statement 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. virtual int @@ -414,6 +419,10 @@ class Statement 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 traverse_expression(Traverse*, Expression**); @@ -507,6 +516,9 @@ class Temporary_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: // The type of the temporary variable. Type* type_; @@ -544,6 +556,9 @@ class Variable_declaration_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: Named_object* var_; }; @@ -581,6 +596,9 @@ class Return_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: // Return values. This may be NULL. Expression_list* vals_; @@ -617,6 +635,9 @@ class Send_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: // The channel on which to send the value. Expression* channel_; @@ -678,6 +699,10 @@ class Select_clauses 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. class Select_clause @@ -748,6 +773,10 @@ class Select_clauses Bstatement* get_statements_backend(Translate_context*); + // Dump AST representation. + void + dump_clause(Ast_dump_context*) const; + private: // The channel. Expression* channel_; @@ -825,6 +854,9 @@ class Select_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: // The select clauses. Select_clauses* clauses_; @@ -844,7 +876,7 @@ class Thunk_statement : public Statement // Return the call expression. Expression* - call() + call() const { return this->call_; } // Simplify a go or defer statement so that it only uses a single @@ -914,6 +946,9 @@ class Go_statement : public Thunk_statement protected: Bstatement* do_get_backend(Translate_context*); + + void + do_dump_statement(Ast_dump_context*) const; }; // A defer statement. @@ -928,6 +963,9 @@ class Defer_statement : public Thunk_statement protected: Bstatement* do_get_backend(Translate_context*); + + void + do_dump_statement(Ast_dump_context*) const; }; // A label statement. @@ -952,6 +990,9 @@ class Label_statement : public Statement Bstatement* do_get_backend(Translate_context*); + void + do_dump_statement(Ast_dump_context*) const; + private: // The label. Label* label_; @@ -1005,6 +1046,9 @@ class For_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // The initialization statements. This may be NULL. Block* init_; @@ -1063,6 +1107,9 @@ class For_range_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: Expression* make_range_ref(Named_object*, Temporary_statement*, source_location); @@ -1167,6 +1214,10 @@ class Case_clauses std::vector >* all_cases, std::vector* all_statements) const; + // Dump the AST representation to a dump context. + void + dump_clauses(Ast_dump_context*) const; + private: // For a constant switch we need to keep a record of constants we // have already seen. @@ -1237,6 +1288,10 @@ class Case_clauses get_backend(Translate_context*, Unnamed_label* break_label, Case_constants*, std::vector* 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_; @@ -1292,6 +1347,9 @@ class Switch_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // The value to switch on. This may be NULL. Expression* val_; @@ -1342,6 +1400,10 @@ class Type_case_clauses 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 @@ -1382,6 +1444,10 @@ class Type_case_clauses 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_; @@ -1438,6 +1504,9 @@ class Type_switch_statement : public Statement do_get_backend(Translate_context*) { go_unreachable(); } + void + do_dump_statement(Ast_dump_context*) const; + private: // The variable holding the value we are switching on. Named_object* var_;