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.
14 #include "expressions.h"
15 #include "statements.h"
20 #include "go-diagnostics.h"
22 // The -fgo-dump-ast flag to activate AST dumps.
24 Go_dump
ast_dump_flag("ast");
26 // This class is used to traverse the tree to look for blocks and
29 class Ast_dump_traverse_blocks_and_functions
: public Traverse
32 Ast_dump_traverse_blocks_and_functions(Ast_dump_context
* ast_dump_context
)
33 : Traverse(traverse_blocks
| traverse_functions
| traverse_variables
),
34 ast_dump_context_(ast_dump_context
)
42 function(Named_object
*);
45 variable(Named_object
*);
48 Ast_dump_context
* ast_dump_context_
;
51 // This class is used to traverse the tree to look for statements.
53 class Ast_dump_traverse_statements
: public Traverse
56 Ast_dump_traverse_statements(Ast_dump_context
* ast_dump_context
)
57 : Traverse(traverse_statements
),
58 ast_dump_context_(ast_dump_context
)
63 statement(Block
*, size_t* pindex
, Statement
*);
66 Ast_dump_context
* ast_dump_context_
;
69 // For each block we enclose it in brackets.
71 int Ast_dump_traverse_blocks_and_functions::block(Block
* block
)
75 this->ast_dump_context_
->ostream() << std::endl
;
79 this->ast_dump_context_
->print_indent();
80 this->ast_dump_context_
->ostream() << "{" << std::endl
;
81 this->ast_dump_context_
->indent();
84 Ast_dump_traverse_statements
adts(this->ast_dump_context_
);
85 block
->traverse(&adts
);
87 this->ast_dump_context_
->unindent();
88 this->ast_dump_context_
->print_indent();
89 this->ast_dump_context_
->ostream() << "}" << std::endl
;
91 return TRAVERSE_SKIP_COMPONENTS
;
94 // Dump each traversed statement.
97 Ast_dump_traverse_statements::statement(Block
* block
, size_t* pindex
,
100 statement
->dump_statement(this->ast_dump_context_
);
102 if (statement
->is_block_statement())
104 Ast_dump_traverse_blocks_and_functions
adtbf(this->ast_dump_context_
);
105 statement
->traverse(block
, pindex
, &adtbf
);
108 return TRAVERSE_SKIP_COMPONENTS
;
111 // Dump the function header.
114 Ast_dump_traverse_blocks_and_functions::function(Named_object
* no
)
116 this->ast_dump_context_
->ostream() << no
->name();
118 go_assert(no
->is_function());
119 Function
* func
= no
->func_value();
121 this->ast_dump_context_
->ostream() << "(";
122 this->ast_dump_context_
->dump_typed_identifier_list(
123 func
->type()->parameters());
125 this->ast_dump_context_
->ostream() << ")";
127 Function::Results
* res
= func
->result_variables();
128 if (res
!= NULL
&& !res
->empty())
130 this->ast_dump_context_
->ostream() << " (";
132 for (Function::Results::const_iterator it
= res
->begin();
136 if (it
!= res
->begin())
137 this->ast_dump_context_
->ostream() << ",";
138 Named_object
* rno
= (*it
);
140 this->ast_dump_context_
->ostream() << rno
->name() << " ";
141 go_assert(rno
->is_result_variable());
142 Result_variable
* resvar
= rno
->result_var_value();
144 this->ast_dump_context_
->dump_type(resvar
->type());
147 this->ast_dump_context_
->ostream() << ")";
150 this->ast_dump_context_
->ostream() << " : ";
151 this->ast_dump_context_
->dump_type(func
->type());
152 this->ast_dump_context_
->ostream() << std::endl
;
154 return TRAVERSE_CONTINUE
;
157 // Dump variable preinits
160 Ast_dump_traverse_blocks_and_functions::variable(Named_object
* no
)
162 if (!no
->is_variable())
163 return TRAVERSE_CONTINUE
;
165 Variable
* var
= no
->var_value();
166 if (var
->has_pre_init())
168 this->ast_dump_context_
->ostream() << "// preinit block for var "
169 << no
->message_name() << "\n";
170 var
->preinit()->traverse(this);
173 return TRAVERSE_CONTINUE
;
178 // Class Ast_dump_context.
180 Ast_dump_context::Ast_dump_context(std::ostream
* out
/* = NULL */,
181 bool dump_subblocks
/* = true */)
182 : indent_(0), dump_subblocks_(dump_subblocks
), ostream_(out
), gogo_(NULL
)
186 // Dump files will be named %basename%.dump.ast
188 const char* kAstDumpFileExtension
= ".dump.ast";
190 // Dump the internal representation.
193 Ast_dump_context::dump(Gogo
* gogo
, const char* basename
)
196 std::string
dumpname(basename
);
197 dumpname
+= ".dump.ast";
198 out
.open(dumpname
.c_str());
202 go_error_at(Linemap::unknown_location(),
203 "cannot open %s:%m; %<-fgo-dump-ast%> ignored",
209 this->ostream_
= &out
;
211 Ast_dump_traverse_blocks_and_functions
adtbf(this);
212 gogo
->traverse(&adtbf
);
217 // Dump a textual representation of a type to the
221 Ast_dump_context::dump_type(const Type
* t
)
224 this->ostream() << "(nil type)";
226 // FIXME: write a type pretty printer instead of
227 // using mangled names.
228 if (this->gogo_
!= NULL
)
231 t
->backend_name(this->gogo_
, &bname
);
232 this->ostream() << "(" << bname
.name() << ")";
236 // Dump a textual representation of a block to the
240 Ast_dump_context::dump_block(Block
* b
)
242 Ast_dump_traverse_blocks_and_functions
adtbf(this);
246 // Dump a textual representation of an expression to the
250 Ast_dump_context::dump_expression(const Expression
* e
)
252 e
->dump_expression(this);
255 // Dump a textual representation of an expression list to the
259 Ast_dump_context::dump_expression_list(const Expression_list
* el
,
260 bool as_pairs
/* = false */)
265 for (std::vector
<Expression
*>::const_iterator it
= el
->begin();
269 if ( it
!= el
->begin())
270 this->ostream() << ",";
272 (*it
)->dump_expression(this);
274 this->ostream() << "NULL";
277 this->ostream() << ":";
279 (*it
)->dump_expression(this);
284 // Dump a textual representation of a typed identifier to the
288 Ast_dump_context::dump_typed_identifier(const Typed_identifier
* ti
)
290 this->ostream() << ti
->name() << " ";
291 this->dump_type(ti
->type());
294 // Dump a textual representation of a typed identifier list to the
298 Ast_dump_context::dump_typed_identifier_list(
299 const Typed_identifier_list
* ti_list
)
304 for (Typed_identifier_list::const_iterator it
= ti_list
->begin();
305 it
!= ti_list
->end();
308 if (it
!= ti_list
->begin())
309 this->ostream() << ",";
310 this->dump_typed_identifier(&(*it
));
314 // Dump a textual representation of a temporary variable to the
318 Ast_dump_context::dump_temp_variable_name(const Statement
* s
)
320 go_assert(s
->classification() == Statement::STATEMENT_TEMPORARY
);
321 // Use the statement address as part of the name for the temporary variable.
322 this->ostream() << "tmp." << (uintptr_t) s
;
325 // Dump a textual representation of a label to the
329 Ast_dump_context::dump_label_name(const Unnamed_label
* l
)
331 // Use the unnamed label address as part of the name for the temporary
333 this->ostream() << "label." << (uintptr_t) l
;
336 // Produce a textual representation of an operator symbol.
339 op_string(Operator op
)
341 // FIXME: This should be in line with symbols that are parsed,
342 // exported and/or imported.
361 case OPERATOR_ANDAND
:
379 case OPERATOR_LSHIFT
:
381 case OPERATOR_RSHIFT
:
383 case OPERATOR_BITCLEAR
:
385 case OPERATOR_CHANOP
:
387 case OPERATOR_PLUSEQ
:
389 case OPERATOR_MINUSEQ
:
395 case OPERATOR_MULTEQ
:
401 case OPERATOR_LSHIFTEQ
:
403 case OPERATOR_RSHIFTEQ
:
407 case OPERATOR_BITCLEAREQ
:
409 case OPERATOR_PLUSPLUS
:
411 case OPERATOR_MINUSMINUS
:
415 case OPERATOR_COLONEQ
:
417 case OPERATOR_SEMICOLON
:
421 case OPERATOR_ELLIPSIS
:
425 case OPERATOR_LPAREN
:
427 case OPERATOR_RPAREN
:
429 case OPERATOR_LCURLY
:
431 case OPERATOR_RCURLY
:
433 case OPERATOR_LSQUARE
:
435 case OPERATOR_RSQUARE
:
443 // Dump a textual representation of an operator to the
447 Ast_dump_context::dump_operator(Operator op
)
449 this->ostream() << op_string(op
);
452 // Size of a single indent.
454 const int Ast_dump_context::offset_
= 2;
456 // Print indenting spaces to dump file.
459 Ast_dump_context::print_indent()
461 for (int i
= 0; i
< this->indent_
* this->offset_
; i
++)
462 this->ostream() << " ";
465 // Dump a textual representation of the ast to the
468 void Gogo::dump_ast(const char* basename
)
470 if (::ast_dump_flag
.is_enabled())
472 Ast_dump_context adc
;
473 adc
.dump(this, basename
);
477 // Implementation of String_dump interface.
480 Ast_dump_context::write_c_string(const char* s
)
482 this->ostream() << s
;
486 Ast_dump_context::write_string(const std::string
& s
)
488 this->ostream() << s
;
491 // Dump statement to stream.
494 Ast_dump_context::dump_to_stream(const Statement
* stm
, std::ostream
* out
)
496 Ast_dump_context
adc(out
, false);
497 stm
->dump_statement(&adc
);
500 // Dump expression to stream.
503 Ast_dump_context::dump_to_stream(const Expression
* expr
, std::ostream
* out
)
505 Ast_dump_context
adc(out
, false);
506 expr
->dump_expression(&adc
);
509 // Dump an expression to std::cerr. This is intended to be used
510 // from within a debugging session.
513 debug_go_expression(const Expression
* expr
)
516 std::cerr
<< "<null>";
519 Ast_dump_context::dump_to_stream(expr
, &std::cerr
);
520 std::string lstr
= Linemap::location_to_string(expr
->location());
521 std::cerr
<< " // loc " << lstr
<< std::endl
;
525 // Shallow dump of stmt to std::cerr. This is intended to be used
526 // from within a debugging session.
529 debug_go_statement(const Statement
* stmt
)
532 std::cerr
<< "<null>\n";
535 std::string lstr
= Linemap::location_to_string(stmt
->location());
536 Statement
*ncstmt
= const_cast<Statement
*>(stmt
);
537 Block_statement
* bs
= ncstmt
->block_statement();
539 std::cerr
<< "Block " << bs
->block()
540 << " // location: " << lstr
<< std::endl
;
542 Ast_dump_context::dump_to_stream(stmt
, &std::cerr
);
546 // Deep dump of statement to std::cerr. This is intended to be used
547 // from within a debugging session.
550 debug_go_statement_deep(const Statement
* statement
)
552 Ast_dump_context
adc(&std::cerr
, true);
553 statement
->dump_statement(&adc
);
556 // Shallow dump of a block to std::cerr. This is intended to be used
557 // from within a debugging session.
560 debug_go_block(const Block
* block
)
563 std::cerr
<< "<null>";
566 std::cerr
<< "Block " << block
567 << " (enclosing " << block
->enclosing() << "):\n";
568 const std::vector
<Statement
*>* stmts
= block
->statements();
571 for (size_t i
= 0; i
< stmts
->size(); ++i
)
573 debug_go_statement(stmts
->at(i
));
579 // Deep dump of a block to std:cerr. This is intended to be used
580 // from within a debugging session.
583 debug_go_block_deep(const Block
* block
)
585 Ast_dump_context
adc(&std::cerr
, true);
586 Block
* ncblock
= const_cast<Block
*>(block
);
587 adc
.dump_block(ncblock
);
592 typedef Unordered_map(const Type
*, unsigned) idx_map
;
594 Type_dumper(const Type
* type
)
595 : top_(type
), ntypes_(0)
597 this->worklist_
.push_back(type
);
602 std::string
stringResult() { return ss_
.str(); }
605 void emitpre(unsigned tag
, const Type
* addr
);
606 void typeref(const char*, const Type
*, const char *);
607 void visit_forward_declaration_type(const Forward_declaration_type
* fdt
);
608 void visit_function_type(const Function_type
* ft
);
609 void visit_struct_type(const Struct_type
* st
);
610 void visit_array_type(const Array_type
* at
);
611 void visit_map_type(const Map_type
* mt
);
612 void visit_channel_type(const Channel_type
* mt
);
613 void visit_interface_type(const Interface_type
* mt
);
614 void visit_methods(const Typed_identifier_list
* methods
,
616 std::pair
<bool, unsigned> lookup(const Type
*);
618 static const unsigned notag
= 0xffffffff;
624 std::list
<const Type
*> worklist_
;
625 std::ostringstream ss_
;
628 // Look up a type, installing it in 'types_'. Return is <found, N>
629 // where 'found' is true if type had been previously recorded, and N
630 // is the index/tag assigned to N. The input argument is appended to
631 // the work list if this is the first time we've seen it.
633 std::pair
<bool, unsigned> Type_dumper::lookup(const Type
* t
)
635 std::pair
<const Type
*, unsigned> entry
= std::make_pair(t
, this->ntypes_
);
636 std::pair
<idx_map::iterator
, bool> ins
= this->types_
.insert(entry
);
641 this->worklist_
.push_back(t
);
643 return std::make_pair(ins
.second
, ins
.first
->second
);
646 // Emit preamble prior to dumping a type, including the type
647 // pointer itself and the tag we've assigned it. If no
648 // tag is specified (via special "notag" value) and/or the
649 // pointer is null, then just emit an equivalent amount
652 void Type_dumper::emitpre(unsigned tag
, const Type
* ptr
)
654 char tbuf
[50], pbuf
[50], buf
[200];
658 snprintf(tbuf
, sizeof tbuf
, "T%u", tag
);
662 snprintf(pbuf
, sizeof pbuf
, "%p", (const void*) ptr
);
664 snprintf(buf
, sizeof buf
, "%8s %16s ", tbuf
, pbuf
);
668 // Emit a reference to a type into the dump buffer. In most cases this means
669 // just the type tag, but for named types we also emit the name, and for
670 // simple/primitive types (ex: int64) we emit the type itself. If "pref" is
671 // non-NULL, emit the string prior to the reference, and if "suf" is non-NULL,
672 // emit it following the reference.
674 void Type_dumper::typeref(const char* pref
, const Type
* t
, const char* suf
)
678 std::pair
<bool, unsigned> p
= this->lookup(t
);
679 unsigned tag
= p
.second
;
680 switch (t
->classification())
682 case Type::TYPE_NAMED
:
684 const Named_type
* nt
= t
->named_type();
685 const Named_object
* no
= nt
->named_object();
686 this->ss_
<< "'" << no
->message_name() << "' -> ";
687 const Type
* underlying
= nt
->real_type();
688 this->typeref(NULL
, underlying
, NULL
);
691 case Type::TYPE_POINTER
:
692 this->typeref("*", t
->points_to(), NULL
);
694 case Type::TYPE_ERROR
:
695 this->ss_
<< "error_type";
697 case Type::TYPE_INTEGER
:
699 const Integer_type
* it
= t
->integer_type();
700 if (it
->is_abstract())
701 this->ss_
<< "abstract_int";
703 this->ss_
<< (it
->is_unsigned() ? "u" : "") << "int" << it
->bits();
706 case Type::TYPE_FLOAT
:
708 const Float_type
* ft
= t
->float_type();
709 if (ft
->is_abstract())
710 this->ss_
<< "abstract_float";
712 this->ss_
<< "float" << ft
->bits();
715 case Type::TYPE_COMPLEX
:
717 const Complex_type
* ct
= t
->complex_type();
718 if (ct
->is_abstract())
719 this->ss_
<< "abstract_complex";
721 this->ss_
<< "complex" << ct
->bits();
724 case Type::TYPE_BOOLEAN
:
727 case Type::TYPE_STRING
:
728 this->ss_
<< "string";
731 this->ss_
<< "nil_type";
733 case Type::TYPE_VOID
:
734 this->ss_
<< "void_type";
736 case Type::TYPE_FUNCTION
:
737 case Type::TYPE_STRUCT
:
738 case Type::TYPE_ARRAY
:
740 case Type::TYPE_CHANNEL
:
741 case Type::TYPE_FORWARD
:
742 case Type::TYPE_INTERFACE
:
743 this->ss_
<< "T" << tag
;
747 // This is a debugging routine, so instead of a go_unreachable()
748 // issue a warning/error, to allow for the possibility that the
749 // compiler we're debugging is in a bad state.
750 this->ss_
<< "<??? " << ((unsigned)t
->classification()) << "> "
757 void Type_dumper::visit_forward_declaration_type(const Forward_declaration_type
* fdt
)
759 this->ss_
<< "forward_declaration_type ";
760 if (fdt
->is_defined())
761 this->typeref("-> ", fdt
->real_type(), NULL
);
763 this->ss_
<< "'" << fdt
->name() << "'";
767 void Type_dumper::visit_function_type(const Function_type
* ft
)
769 this->ss_
<< "function\n";
770 const Typed_identifier
* rec
= ft
->receiver();
773 this->emitpre(notag
, NULL
);
774 this->typeref("receiver ", rec
->type(), "\n");
776 const Typed_identifier_list
* parameters
= ft
->parameters();
777 if (parameters
!= NULL
)
779 for (Typed_identifier_list::const_iterator p
= parameters
->begin();
780 p
!= parameters
->end();
783 this->emitpre(notag
, NULL
);
784 this->typeref(" param ", p
->type(), "\n");
787 const Typed_identifier_list
* results
= ft
->results();
790 for (Typed_identifier_list::const_iterator p
= results
->begin();
794 this->emitpre(notag
, NULL
);
795 this->typeref(" result ", p
->type(), "\n");
800 void Type_dumper::visit_struct_type(const Struct_type
* st
)
802 this->ss_
<< "struct\n";
803 const Struct_field_list
* fields
= st
->fields();
806 for (Struct_field_list::const_iterator p
= fields
->begin();
810 this->emitpre(notag
, NULL
);
811 this->typeref(" field ", p
->type(), "\n");
816 void Type_dumper::visit_array_type(const Array_type
* at
)
818 this->ss_
<< "array [";
819 if (at
->length() != NULL
)
822 if (at
->int_length(&len
))
825 this->typeref("] ", at
->element_type(), "\n");
828 void Type_dumper::visit_map_type(const Map_type
* mt
)
830 this->ss_
<< "map [";
831 this->typeref(NULL
, mt
->key_type(), NULL
);
832 this->typeref("] ", mt
->val_type(), "\n");
835 void Type_dumper::visit_methods(const Typed_identifier_list
* methods
,
840 this->emitpre(notag
, NULL
);
841 this->ss_
<< tag
<< "\n";
843 for (Typed_identifier_list::const_iterator p
= methods
->begin();
847 this->emitpre(notag
, NULL
);
848 if (p
->name().empty())
849 this->typeref(" embedded method ", p
->type(), "\n");
852 this->ss_
<< " method '" << p
->name() << "' ";
853 this->typeref(NULL
, p
->type(), "\n");
858 void Type_dumper::visit_interface_type(const Interface_type
* it
)
860 const Typed_identifier_list
* methods
=
861 (it
->methods_are_finalized() ? it
->methods() : it
->local_methods());
864 this->ss_
<< "empty_interface\n";
867 this->ss_
<< "interface";
868 if (! it
->methods_are_finalized())
870 this->ss_
<< " [unfinalized]\n";
871 visit_methods(it
->local_methods(), NULL
);
876 visit_methods(it
->local_methods(), "[parse_methods]");
877 visit_methods(it
->methods(), "[all_methods]");
881 void Type_dumper::visit_channel_type(const Channel_type
* ct
)
883 this->ss_
<< "channel {";
885 this->ss_
<< " send";
886 if (ct
->may_receive())
887 this->ss_
<< " receive";
888 this->typeref(" } ", ct
->element_type(), "\n");
891 void Type_dumper::visit()
893 while (! this->worklist_
.empty()) {
894 const Type
* t
= this->worklist_
.front();
895 this->worklist_
.pop_front();
897 std::pair
<bool, unsigned> p
= this->lookup(t
);
898 unsigned tag
= p
.second
;
899 this->emitpre(tag
, t
);
901 switch(t
->classification())
903 case Type::TYPE_ERROR
:
904 case Type::TYPE_INTEGER
:
905 case Type::TYPE_FLOAT
:
906 case Type::TYPE_COMPLEX
:
907 case Type::TYPE_BOOLEAN
:
908 case Type::TYPE_STRING
:
909 case Type::TYPE_VOID
:
910 case Type::TYPE_POINTER
:
912 case Type::TYPE_NAMED
:
913 this->typeref(NULL
, t
, "\n");
915 case Type::TYPE_FORWARD
:
916 this->visit_forward_declaration_type(t
->forward_declaration_type());
919 case Type::TYPE_FUNCTION
:
920 this->visit_function_type(t
->function_type());
922 case Type::TYPE_STRUCT
:
923 this->visit_struct_type(t
->struct_type());
925 case Type::TYPE_ARRAY
:
926 this->visit_array_type(t
->array_type());
929 this->visit_map_type(t
->map_type());
931 case Type::TYPE_CHANNEL
:
932 this->visit_channel_type(t
->channel_type());
934 case Type::TYPE_INTERFACE
:
935 this->visit_interface_type(t
->interface_type());
938 // This is a debugging routine, so instead of a go_unreachable()
939 // issue a warning/error, to allow for the possibility that the
940 // compiler we're debugging is in a bad state.
941 this->ss_
<< "<unknown/unrecognized classification "
942 << ((unsigned)t
->classification()) << ">\n";
947 // Dump a Go type for debugging purposes. This is a deep as opposed
948 // to shallow dump; all of the types reachable from the specified
949 // type will be dumped in addition to the type itself.
951 void debug_go_type(const Type
* type
)
955 std::cerr
<< "<NULL type>\n";
958 Type_dumper
dumper(type
);
960 std::cerr
<< dumper
.stringResult();
963 void debug_go_type(Type
* type
)
965 const Type
* ctype
= type
;
966 debug_go_type(ctype
);