* Add TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV target macro.
[official-gcc.git] / gcc / go / gofrontend / ast-dump.cc
blob850e31a81e5329569c9804eca11149bc8d77cff7
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"
20 // The -fgo-dump-ast flag to activate AST dumps.
22 Go_dump ast_dump_flag("ast");
24 // This class is used to traverse the tree to look for blocks and
25 // function headers.
27 class Ast_dump_traverse_blocks_and_functions : public Traverse
29 public:
30 Ast_dump_traverse_blocks_and_functions(Ast_dump_context* ast_dump_context)
31 : Traverse(traverse_blocks | traverse_functions),
32 ast_dump_context_(ast_dump_context)
33 { }
35 protected:
36 int
37 block(Block*);
39 int
40 function(Named_object*);
42 private:
43 Ast_dump_context* ast_dump_context_;
46 // This class is used to traverse the tree to look for statements.
48 class Ast_dump_traverse_statements : public Traverse
50 public:
51 Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context)
52 : Traverse(traverse_statements),
53 ast_dump_context_(ast_dump_context)
54 { }
56 protected:
57 int
58 statement(Block*, size_t* pindex, Statement*);
60 private:
61 Ast_dump_context* ast_dump_context_;
64 // For each block we enclose it in brackets.
66 int Ast_dump_traverse_blocks_and_functions::block(Block * block)
68 this->ast_dump_context_->print_indent();
69 this->ast_dump_context_->ostream() << "{" << std::endl;
70 this->ast_dump_context_->indent();
72 // Dump statememts.
73 Ast_dump_traverse_statements adts(this->ast_dump_context_);
74 block->traverse(&adts);
76 this->ast_dump_context_->unindent();
77 this->ast_dump_context_->print_indent();
78 this->ast_dump_context_->ostream() << "}" << std::endl;
80 return TRAVERSE_SKIP_COMPONENTS;
83 // Dump each traversed statement.
85 int
86 Ast_dump_traverse_statements::statement(Block* block, size_t* pindex,
87 Statement* statement)
89 statement->dump_statement(this->ast_dump_context_);
91 if (statement->is_block_statement())
93 Ast_dump_traverse_blocks_and_functions adtbf(this->ast_dump_context_);
94 statement->traverse(block, pindex, &adtbf);
97 return TRAVERSE_SKIP_COMPONENTS;
100 // Dump the function header.
103 Ast_dump_traverse_blocks_and_functions::function(Named_object* no)
105 this->ast_dump_context_->ostream() << no->name();
107 go_assert(no->is_function());
108 Function* func = no->func_value();
110 this->ast_dump_context_->ostream() << "(";
111 this->ast_dump_context_->dump_typed_identifier_list(
112 func->type()->parameters());
114 this->ast_dump_context_->ostream() << ")";
116 Function::Results* res = func->result_variables();
117 if (res != NULL && !res->empty())
119 this->ast_dump_context_->ostream() << " (";
121 for (Function::Results::const_iterator it = res->begin();
122 it != res->end();
123 it++)
125 if (it != res->begin())
126 this->ast_dump_context_->ostream() << ",";
127 Named_object* no = (*it);
129 this->ast_dump_context_->ostream() << no->name() << " ";
130 go_assert(no->is_result_variable());
131 Result_variable* resvar = no->result_var_value();
133 this->ast_dump_context_->dump_type(resvar->type());
136 this->ast_dump_context_->ostream() << ")";
139 this->ast_dump_context_->ostream() << " : ";
140 this->ast_dump_context_->dump_type(func->type());
141 this->ast_dump_context_->ostream() << std::endl;
143 return TRAVERSE_CONTINUE;
146 // Class Ast_dump_context.
148 Ast_dump_context::Ast_dump_context(std::ostream* out /* = NULL */,
149 bool dump_subblocks /* = true */)
150 : indent_(0), dump_subblocks_(dump_subblocks), ostream_(out), gogo_(NULL)
154 // Dump files will be named %basename%.dump.ast
156 const char* kAstDumpFileExtension = ".dump.ast";
158 // Dump the internal representation.
160 void
161 Ast_dump_context::dump(Gogo* gogo, const char* basename)
163 std::ofstream* out = new std::ofstream();
164 std::string dumpname(basename);
165 dumpname += ".dump.ast";
166 out->open(dumpname.c_str());
168 if (out->fail())
170 error("cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str());
171 return;
174 this->gogo_ = gogo;
175 this->ostream_ = out;
177 Ast_dump_traverse_blocks_and_functions adtbf(this);
178 gogo->traverse(&adtbf);
180 out->close();
183 // Dump a textual representation of a type to the
184 // the dump file.
186 void
187 Ast_dump_context::dump_type(const Type* t)
189 if (t == NULL)
190 this->ostream() << "(nil type)";
191 else
192 // FIXME: write a type pretty printer instead of
193 // using mangled names.
194 if (this->gogo_ != NULL)
195 this->ostream() << "(" << t->mangled_name(this->gogo_) << ")";
198 // Dump a textual representation of a block to the
199 // the dump file.
201 void
202 Ast_dump_context::dump_block(Block* b)
204 Ast_dump_traverse_blocks_and_functions adtbf(this);
205 b->traverse(&adtbf);
208 // Dump a textual representation of an expression to the
209 // the dump file.
211 void
212 Ast_dump_context::dump_expression(const Expression* e)
214 e->dump_expression(this);
217 // Dump a textual representation of an expression list to the
218 // the dump file.
220 void
221 Ast_dump_context::dump_expression_list(const Expression_list* el,
222 bool as_pairs /* = false */)
224 if (el == NULL)
225 return;
227 for (std::vector<Expression*>::const_iterator it = el->begin();
228 it != el->end();
229 it++)
231 if ( it != el->begin())
232 this->ostream() << ",";
233 if (*it != NULL)
234 (*it)->dump_expression(this);
235 else
236 this->ostream() << "NULL";
237 if (as_pairs)
239 this->ostream() << ":";
240 ++it;
241 (*it)->dump_expression(this);
246 // Dump a textual representation of a typed identifier to the
247 // the dump file.
249 void
250 Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
252 this->ostream() << ti->name() << " ";
253 this->dump_type(ti->type());
256 // Dump a textual representation of a typed identifier list to the
257 // the dump file.
259 void
260 Ast_dump_context::dump_typed_identifier_list(
261 const Typed_identifier_list* ti_list)
263 if (ti_list == NULL)
264 return;
266 for (Typed_identifier_list::const_iterator it = ti_list->begin();
267 it != ti_list->end();
268 it++)
270 if (it != ti_list->begin())
271 this->ostream() << ",";
272 this->dump_typed_identifier(&(*it));
276 // Dump a textual representation of a temporary variable to the
277 // the dump file.
279 void
280 Ast_dump_context::dump_temp_variable_name(const Statement* s)
282 go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
283 // Use the statement address as part of the name for the temporary variable.
284 this->ostream() << "tmp." << (uintptr_t) s;
287 // Dump a textual representation of a label to the
288 // the dump file.
290 void
291 Ast_dump_context::dump_label_name(const Unnamed_label* l)
293 // Use the unnamed label address as part of the name for the temporary
294 // variable.
295 this->ostream() << "label." << (uintptr_t) l;
298 // Produce a textual representation of an operator symbol.
300 static const char*
301 op_string(Operator op)
303 // FIXME: This should be in line with symbols that are parsed,
304 // exported and/or imported.
305 switch (op)
307 case OPERATOR_PLUS:
308 return "+";
309 case OPERATOR_MINUS:
310 return "-";
311 case OPERATOR_NOT:
312 return "!";
313 case OPERATOR_XOR:
314 return "^";
315 case OPERATOR_OR:
316 return "|";
317 case OPERATOR_AND:
318 return "&";
319 case OPERATOR_MULT:
320 return "*";
321 case OPERATOR_OROR:
322 return "||";
323 case OPERATOR_ANDAND:
324 return "&&";
325 case OPERATOR_EQEQ:
326 return "==";
327 case OPERATOR_NOTEQ:
328 return "!=";
329 case OPERATOR_LT:
330 return "<";
331 case OPERATOR_LE:
332 return "<=";
333 case OPERATOR_GT:
334 return ">";
335 case OPERATOR_GE:
336 return ">=";
337 case OPERATOR_DIV:
338 return "/";
339 case OPERATOR_MOD:
340 return "%";
341 case OPERATOR_LSHIFT:
342 return "<<";
343 case OPERATOR_RSHIFT:
344 return "//";
345 case OPERATOR_BITCLEAR:
346 return "&^";
347 case OPERATOR_CHANOP:
348 return "<-";
349 case OPERATOR_PLUSEQ:
350 return "+=";
351 case OPERATOR_MINUSEQ:
352 return "-=";
353 case OPERATOR_OREQ:
354 return "|=";
355 case OPERATOR_XOREQ:
356 return "^=";
357 case OPERATOR_MULTEQ:
358 return "*=";
359 case OPERATOR_DIVEQ:
360 return "/=";
361 case OPERATOR_MODEQ:
362 return "%=";
363 case OPERATOR_LSHIFTEQ:
364 return "<<=";
365 case OPERATOR_RSHIFTEQ:
366 return ">>=";
367 case OPERATOR_ANDEQ:
368 return "&=";
369 case OPERATOR_BITCLEAREQ:
370 return "&^=";
371 case OPERATOR_PLUSPLUS:
372 return "++";
373 case OPERATOR_MINUSMINUS:
374 return "--";
375 case OPERATOR_COLON:
376 return ":";
377 case OPERATOR_COLONEQ:
378 return ":=";
379 case OPERATOR_SEMICOLON:
380 return ";";
381 case OPERATOR_DOT:
382 return ".";
383 case OPERATOR_ELLIPSIS:
384 return "...";
385 case OPERATOR_COMMA:
386 return ",";
387 case OPERATOR_LPAREN:
388 return "(";
389 case OPERATOR_RPAREN:
390 return ")";
391 case OPERATOR_LCURLY:
392 return "{";
393 case OPERATOR_RCURLY:
394 return "}";
395 case OPERATOR_LSQUARE:
396 return "[";
397 case OPERATOR_RSQUARE:
398 return "]";
399 default:
400 go_unreachable();
402 return NULL;
405 // Dump a textual representation of an operator to the
406 // the dump file.
408 void
409 Ast_dump_context::dump_operator(Operator op)
411 this->ostream() << op_string(op);
414 // Size of a single indent.
416 const int Ast_dump_context::offset_ = 2;
418 // Print indenting spaces to dump file.
420 void
421 Ast_dump_context::print_indent()
423 for (int i = 0; i < this->indent_ * this->offset_; i++)
424 this->ostream() << " ";
427 // Dump a textual representation of the ast to the
428 // the dump file.
430 void Gogo::dump_ast(const char* basename)
432 if (::ast_dump_flag.is_enabled())
434 Ast_dump_context adc;
435 adc.dump(this, basename);
439 // Implementation of String_dump interface.
441 void
442 Ast_dump_context::write_c_string(const char* s)
444 this->ostream() << s;
447 void
448 Ast_dump_context::write_string(const std::string& s)
450 this->ostream() << s;
453 // Dump statment to stream.
455 void
456 Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
458 Ast_dump_context adc(out, false);
459 stm->dump_statement(&adc);
462 // Dump expression to stream.
464 void
465 Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
467 Ast_dump_context adc(out, false);
468 expr->dump_expression(&adc);