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.
13 #include "expressions.h"
14 #include "statements.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
28 class Ast_dump_traverse_blocks_and_functions
: public Traverse
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
)
41 function(Named_object
*);
44 variable(Named_object
*);
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
55 Ast_dump_traverse_statements(Ast_dump_context
* ast_dump_context
)
56 : Traverse(traverse_statements
),
57 ast_dump_context_(ast_dump_context
)
62 statement(Block
*, size_t* pindex
, Statement
*);
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
)
74 this->ast_dump_context_
->ostream() << std::endl
;
78 this->ast_dump_context_
->print_indent();
79 this->ast_dump_context_
->ostream() << "{" << std::endl
;
80 this->ast_dump_context_
->indent();
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.
96 Ast_dump_traverse_statements::statement(Block
* block
, size_t* pindex
,
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();
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.
192 Ast_dump_context::dump(Gogo
* gogo
, const char* basename
)
195 std::string
dumpname(basename
);
196 dumpname
+= ".dump.ast";
197 out
.open(dumpname
.c_str());
201 go_error_at(Linemap::unknown_location(),
202 "cannot open %s:%m, -fgo-dump-ast ignored", dumpname
.c_str());
207 this->ostream_
= &out
;
209 Ast_dump_traverse_blocks_and_functions
adtbf(this);
210 gogo
->traverse(&adtbf
);
215 // Dump a textual representation of a type to the
219 Ast_dump_context::dump_type(const Type
* t
)
222 this->ostream() << "(nil type)";
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
234 Ast_dump_context::dump_block(Block
* b
)
236 Ast_dump_traverse_blocks_and_functions
adtbf(this);
240 // Dump a textual representation of an expression to the
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
253 Ast_dump_context::dump_expression_list(const Expression_list
* el
,
254 bool as_pairs
/* = false */)
259 for (std::vector
<Expression
*>::const_iterator it
= el
->begin();
263 if ( it
!= el
->begin())
264 this->ostream() << ",";
266 (*it
)->dump_expression(this);
268 this->ostream() << "NULL";
271 this->ostream() << ":";
273 (*it
)->dump_expression(this);
278 // Dump a textual representation of a typed identifier to the
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
292 Ast_dump_context::dump_typed_identifier_list(
293 const Typed_identifier_list
* ti_list
)
298 for (Typed_identifier_list::const_iterator it
= ti_list
->begin();
299 it
!= ti_list
->end();
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
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
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
327 this->ostream() << "label." << (uintptr_t) l
;
330 // Produce a textual representation of an operator symbol.
333 op_string(Operator op
)
335 // FIXME: This should be in line with symbols that are parsed,
336 // exported and/or imported.
355 case OPERATOR_ANDAND
:
373 case OPERATOR_LSHIFT
:
375 case OPERATOR_RSHIFT
:
377 case OPERATOR_BITCLEAR
:
379 case OPERATOR_CHANOP
:
381 case OPERATOR_PLUSEQ
:
383 case OPERATOR_MINUSEQ
:
389 case OPERATOR_MULTEQ
:
395 case OPERATOR_LSHIFTEQ
:
397 case OPERATOR_RSHIFTEQ
:
401 case OPERATOR_BITCLEAREQ
:
403 case OPERATOR_PLUSPLUS
:
405 case OPERATOR_MINUSMINUS
:
409 case OPERATOR_COLONEQ
:
411 case OPERATOR_SEMICOLON
:
415 case OPERATOR_ELLIPSIS
:
419 case OPERATOR_LPAREN
:
421 case OPERATOR_RPAREN
:
423 case OPERATOR_LCURLY
:
425 case OPERATOR_RCURLY
:
427 case OPERATOR_LSQUARE
:
429 case OPERATOR_RSQUARE
:
437 // Dump a textual representation of an operator to the
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.
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
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.
474 Ast_dump_context::write_c_string(const char* s
)
476 this->ostream() << s
;
480 Ast_dump_context::write_string(const std::string
& s
)
482 this->ostream() << s
;
485 // Dump statment to stream.
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.
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
);