Daily bump.
[official-gcc.git] / gcc / go / gofrontend / ast-dump.cc
blob1fbc890f53ee8f0fdbfc52c165a040772a557682
1 // ast-dump.cc -- AST debug dump. -*- C++ -*-
3 // Copyright 2011 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 #include "go-system.h"
9 #include <iostream>
10 #include <fstream>
12 #include "gogo.h"
13 #include "expressions.h"
14 #include "statements.h"
15 #include "types.h"
16 #include "ast-dump.h"
17 #include "go-c.h"
18 #include "go-dump.h"
19 #include "go-diagnostics.h"
21 // The -fgo-dump-ast flag to activate AST dumps.
23 Go_dump ast_dump_flag("ast");
25 // This class is used to traverse the tree to look for blocks and
26 // function headers.
28 class Ast_dump_traverse_blocks_and_functions : public Traverse
30 public:
31 Ast_dump_traverse_blocks_and_functions(Ast_dump_context* ast_dump_context)
32 : Traverse(traverse_blocks | traverse_functions | traverse_variables),
33 ast_dump_context_(ast_dump_context)
34 { }
36 protected:
37 int
38 block(Block*);
40 int
41 function(Named_object*);
43 int
44 variable(Named_object*);
46 private:
47 Ast_dump_context* ast_dump_context_;
50 // This class is used to traverse the tree to look for statements.
52 class Ast_dump_traverse_statements : public Traverse
54 public:
55 Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context)
56 : Traverse(traverse_statements),
57 ast_dump_context_(ast_dump_context)
58 { }
60 protected:
61 int
62 statement(Block*, size_t* pindex, Statement*);
64 private:
65 Ast_dump_context* ast_dump_context_;
68 // For each block we enclose it in brackets.
70 int Ast_dump_traverse_blocks_and_functions::block(Block * block)
72 if (block == NULL)
74 this->ast_dump_context_->ostream() << std::endl;
75 return TRAVERSE_EXIT;
78 this->ast_dump_context_->print_indent();
79 this->ast_dump_context_->ostream() << "{" << std::endl;
80 this->ast_dump_context_->indent();
82 // Dump statememts.
83 Ast_dump_traverse_statements adts(this->ast_dump_context_);
84 block->traverse(&adts);
86 this->ast_dump_context_->unindent();
87 this->ast_dump_context_->print_indent();
88 this->ast_dump_context_->ostream() << "}" << std::endl;
90 return TRAVERSE_SKIP_COMPONENTS;
93 // Dump each traversed statement.
95 int
96 Ast_dump_traverse_statements::statement(Block* block, size_t* pindex,
97 Statement* statement)
99 statement->dump_statement(this->ast_dump_context_);
101 if (statement->is_block_statement())
103 Ast_dump_traverse_blocks_and_functions adtbf(this->ast_dump_context_);
104 statement->traverse(block, pindex, &adtbf);
107 return TRAVERSE_SKIP_COMPONENTS;
110 // Dump the function header.
113 Ast_dump_traverse_blocks_and_functions::function(Named_object* no)
115 this->ast_dump_context_->ostream() << no->name();
117 go_assert(no->is_function());
118 Function* func = no->func_value();
120 this->ast_dump_context_->ostream() << "(";
121 this->ast_dump_context_->dump_typed_identifier_list(
122 func->type()->parameters());
124 this->ast_dump_context_->ostream() << ")";
126 Function::Results* res = func->result_variables();
127 if (res != NULL && !res->empty())
129 this->ast_dump_context_->ostream() << " (";
131 for (Function::Results::const_iterator it = res->begin();
132 it != res->end();
133 it++)
135 if (it != res->begin())
136 this->ast_dump_context_->ostream() << ",";
137 Named_object* no = (*it);
139 this->ast_dump_context_->ostream() << no->name() << " ";
140 go_assert(no->is_result_variable());
141 Result_variable* resvar = no->result_var_value();
143 this->ast_dump_context_->dump_type(resvar->type());
146 this->ast_dump_context_->ostream() << ")";
149 this->ast_dump_context_->ostream() << " : ";
150 this->ast_dump_context_->dump_type(func->type());
151 this->ast_dump_context_->ostream() << std::endl;
153 return TRAVERSE_CONTINUE;
156 // Dump variable preinits
159 Ast_dump_traverse_blocks_and_functions::variable(Named_object* no)
161 if (!no->is_variable())
162 return TRAVERSE_CONTINUE;
164 Variable* var = no->var_value();
165 if (var->has_pre_init())
167 this->ast_dump_context_->ostream() << "// preinit block for var "
168 << no->message_name() << "\n";
169 var->preinit()->traverse(this);
172 return TRAVERSE_CONTINUE;
177 // Class Ast_dump_context.
179 Ast_dump_context::Ast_dump_context(std::ostream* out /* = NULL */,
180 bool dump_subblocks /* = true */)
181 : indent_(0), dump_subblocks_(dump_subblocks), ostream_(out), gogo_(NULL)
185 // Dump files will be named %basename%.dump.ast
187 const char* kAstDumpFileExtension = ".dump.ast";
189 // Dump the internal representation.
191 void
192 Ast_dump_context::dump(Gogo* gogo, const char* basename)
194 std::ofstream out;
195 std::string dumpname(basename);
196 dumpname += ".dump.ast";
197 out.open(dumpname.c_str());
199 if (out.fail())
201 go_error_at(Linemap::unknown_location(),
202 "cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str());
203 return;
206 this->gogo_ = gogo;
207 this->ostream_ = &out;
209 Ast_dump_traverse_blocks_and_functions adtbf(this);
210 gogo->traverse(&adtbf);
212 out.close();
215 // Dump a textual representation of a type to the
216 // the dump file.
218 void
219 Ast_dump_context::dump_type(const Type* t)
221 if (t == NULL)
222 this->ostream() << "(nil type)";
223 else
224 // FIXME: write a type pretty printer instead of
225 // using mangled names.
226 if (this->gogo_ != NULL)
227 this->ostream() << "(" << t->mangled_name(this->gogo_) << ")";
230 // Dump a textual representation of a block to the
231 // the dump file.
233 void
234 Ast_dump_context::dump_block(Block* b)
236 Ast_dump_traverse_blocks_and_functions adtbf(this);
237 b->traverse(&adtbf);
240 // Dump a textual representation of an expression to the
241 // the dump file.
243 void
244 Ast_dump_context::dump_expression(const Expression* e)
246 e->dump_expression(this);
249 // Dump a textual representation of an expression list to the
250 // the dump file.
252 void
253 Ast_dump_context::dump_expression_list(const Expression_list* el,
254 bool as_pairs /* = false */)
256 if (el == NULL)
257 return;
259 for (std::vector<Expression*>::const_iterator it = el->begin();
260 it != el->end();
261 it++)
263 if ( it != el->begin())
264 this->ostream() << ",";
265 if (*it != NULL)
266 (*it)->dump_expression(this);
267 else
268 this->ostream() << "NULL";
269 if (as_pairs)
271 this->ostream() << ":";
272 ++it;
273 (*it)->dump_expression(this);
278 // Dump a textual representation of a typed identifier to the
279 // the dump file.
281 void
282 Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
284 this->ostream() << ti->name() << " ";
285 this->dump_type(ti->type());
288 // Dump a textual representation of a typed identifier list to the
289 // the dump file.
291 void
292 Ast_dump_context::dump_typed_identifier_list(
293 const Typed_identifier_list* ti_list)
295 if (ti_list == NULL)
296 return;
298 for (Typed_identifier_list::const_iterator it = ti_list->begin();
299 it != ti_list->end();
300 it++)
302 if (it != ti_list->begin())
303 this->ostream() << ",";
304 this->dump_typed_identifier(&(*it));
308 // Dump a textual representation of a temporary variable to the
309 // the dump file.
311 void
312 Ast_dump_context::dump_temp_variable_name(const Statement* s)
314 go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
315 // Use the statement address as part of the name for the temporary variable.
316 this->ostream() << "tmp." << (uintptr_t) s;
319 // Dump a textual representation of a label to the
320 // the dump file.
322 void
323 Ast_dump_context::dump_label_name(const Unnamed_label* l)
325 // Use the unnamed label address as part of the name for the temporary
326 // variable.
327 this->ostream() << "label." << (uintptr_t) l;
330 // Produce a textual representation of an operator symbol.
332 static const char*
333 op_string(Operator op)
335 // FIXME: This should be in line with symbols that are parsed,
336 // exported and/or imported.
337 switch (op)
339 case OPERATOR_PLUS:
340 return "+";
341 case OPERATOR_MINUS:
342 return "-";
343 case OPERATOR_NOT:
344 return "!";
345 case OPERATOR_XOR:
346 return "^";
347 case OPERATOR_OR:
348 return "|";
349 case OPERATOR_AND:
350 return "&";
351 case OPERATOR_MULT:
352 return "*";
353 case OPERATOR_OROR:
354 return "||";
355 case OPERATOR_ANDAND:
356 return "&&";
357 case OPERATOR_EQEQ:
358 return "==";
359 case OPERATOR_NOTEQ:
360 return "!=";
361 case OPERATOR_LT:
362 return "<";
363 case OPERATOR_LE:
364 return "<=";
365 case OPERATOR_GT:
366 return ">";
367 case OPERATOR_GE:
368 return ">=";
369 case OPERATOR_DIV:
370 return "/";
371 case OPERATOR_MOD:
372 return "%";
373 case OPERATOR_LSHIFT:
374 return "<<";
375 case OPERATOR_RSHIFT:
376 return "//";
377 case OPERATOR_BITCLEAR:
378 return "&^";
379 case OPERATOR_CHANOP:
380 return "<-";
381 case OPERATOR_PLUSEQ:
382 return "+=";
383 case OPERATOR_MINUSEQ:
384 return "-=";
385 case OPERATOR_OREQ:
386 return "|=";
387 case OPERATOR_XOREQ:
388 return "^=";
389 case OPERATOR_MULTEQ:
390 return "*=";
391 case OPERATOR_DIVEQ:
392 return "/=";
393 case OPERATOR_MODEQ:
394 return "%=";
395 case OPERATOR_LSHIFTEQ:
396 return "<<=";
397 case OPERATOR_RSHIFTEQ:
398 return ">>=";
399 case OPERATOR_ANDEQ:
400 return "&=";
401 case OPERATOR_BITCLEAREQ:
402 return "&^=";
403 case OPERATOR_PLUSPLUS:
404 return "++";
405 case OPERATOR_MINUSMINUS:
406 return "--";
407 case OPERATOR_COLON:
408 return ":";
409 case OPERATOR_COLONEQ:
410 return ":=";
411 case OPERATOR_SEMICOLON:
412 return ";";
413 case OPERATOR_DOT:
414 return ".";
415 case OPERATOR_ELLIPSIS:
416 return "...";
417 case OPERATOR_COMMA:
418 return ",";
419 case OPERATOR_LPAREN:
420 return "(";
421 case OPERATOR_RPAREN:
422 return ")";
423 case OPERATOR_LCURLY:
424 return "{";
425 case OPERATOR_RCURLY:
426 return "}";
427 case OPERATOR_LSQUARE:
428 return "[";
429 case OPERATOR_RSQUARE:
430 return "]";
431 default:
432 go_unreachable();
434 return NULL;
437 // Dump a textual representation of an operator to the
438 // the dump file.
440 void
441 Ast_dump_context::dump_operator(Operator op)
443 this->ostream() << op_string(op);
446 // Size of a single indent.
448 const int Ast_dump_context::offset_ = 2;
450 // Print indenting spaces to dump file.
452 void
453 Ast_dump_context::print_indent()
455 for (int i = 0; i < this->indent_ * this->offset_; i++)
456 this->ostream() << " ";
459 // Dump a textual representation of the ast to the
460 // the dump file.
462 void Gogo::dump_ast(const char* basename)
464 if (::ast_dump_flag.is_enabled())
466 Ast_dump_context adc;
467 adc.dump(this, basename);
471 // Implementation of String_dump interface.
473 void
474 Ast_dump_context::write_c_string(const char* s)
476 this->ostream() << s;
479 void
480 Ast_dump_context::write_string(const std::string& s)
482 this->ostream() << s;
485 // Dump statment to stream.
487 void
488 Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
490 Ast_dump_context adc(out, false);
491 stm->dump_statement(&adc);
494 // Dump expression to stream.
496 void
497 Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
499 Ast_dump_context adc(out, false);
500 expr->dump_expression(&adc);