123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- // 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 <iostream>
- #include <fstream>
- #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_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(std::ostream* out /* = NULL */,
- bool dump_subblocks /* = true */)
- : indent_(0), dump_subblocks_(dump_subblocks), ostream_(out), gogo_(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->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.
- if (this->gogo_ != NULL)
- 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,
- bool as_pairs /* = false */)
- {
- if (el == NULL)
- return;
- for (std::vector<Expression*>::const_iterator it = el->begin();
- it != el->end();
- it++)
- {
- if ( it != el->begin())
- this->ostream() << ",";
- if (*it != NULL)
- (*it)->dump_expression(this);
- else
- this->ostream() << "NULL";
- if (as_pairs)
- {
- this->ostream() << ":";
- ++it;
- (*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_OR:
- 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_flag.is_enabled())
- {
- Ast_dump_context adc;
- adc.dump(this, basename);
- }
- }
- // Implementation of String_dump interface.
- void
- Ast_dump_context::write_c_string(const char* s)
- {
- this->ostream() << s;
- }
- void
- Ast_dump_context::write_string(const std::string& s)
- {
- this->ostream() << s;
- }
- // Dump statment to stream.
- void
- Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
- {
- Ast_dump_context adc(out, false);
- stm->dump_statement(&adc);
- }
- // Dump expression to stream.
- void
- Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
- {
- Ast_dump_context adc(out, false);
- expr->dump_expression(&adc);
- }
|