i386: Fix up spaceship expanders for -mtune=i[45]86 [PR117053]
[official-gcc.git] / gcc / go / gofrontend / ast-dump.cc
blob12f49e68700529e21cc3fe01c54edb49877874fb
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>
11 #include <sstream>
13 #include "gogo.h"
14 #include "expressions.h"
15 #include "statements.h"
16 #include "types.h"
17 #include "ast-dump.h"
18 #include "go-c.h"
19 #include "go-dump.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
27 // function headers.
29 class Ast_dump_traverse_blocks_and_functions : public Traverse
31 public:
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)
35 { }
37 protected:
38 int
39 block(Block*);
41 int
42 function(Named_object*);
44 int
45 variable(Named_object*);
47 private:
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
55 public:
56 Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context)
57 : Traverse(traverse_statements),
58 ast_dump_context_(ast_dump_context)
59 { }
61 protected:
62 int
63 statement(Block*, size_t* pindex, Statement*);
65 private:
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)
73 if (block == NULL)
75 this->ast_dump_context_->ostream() << std::endl;
76 return TRAVERSE_EXIT;
79 this->ast_dump_context_->print_indent();
80 this->ast_dump_context_->ostream() << "{" << std::endl;
81 this->ast_dump_context_->indent();
83 // Dump statememts.
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.
96 int
97 Ast_dump_traverse_statements::statement(Block* block, size_t* pindex,
98 Statement* statement)
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();
133 it != res->end();
134 it++)
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.
192 void
193 Ast_dump_context::dump(Gogo* gogo, const char* basename)
195 std::ofstream out;
196 std::string dumpname(basename);
197 dumpname += ".dump.ast";
198 out.open(dumpname.c_str());
200 if (out.fail())
202 go_error_at(Linemap::unknown_location(),
203 "cannot open %s:%m; %<-fgo-dump-ast%> ignored",
204 dumpname.c_str());
205 return;
208 this->gogo_ = gogo;
209 this->ostream_ = &out;
211 Ast_dump_traverse_blocks_and_functions adtbf(this);
212 gogo->traverse(&adtbf);
214 out.close();
217 // Dump a textual representation of a type to the
218 // the dump file.
220 void
221 Ast_dump_context::dump_type(const Type* t)
223 if (t == NULL)
224 this->ostream() << "(nil type)";
225 else
226 this->ostream() << "(" << t->message_name() << ")";
229 // Dump a textual representation of a block to the
230 // the dump file.
232 void
233 Ast_dump_context::dump_block(Block* b)
235 Ast_dump_traverse_blocks_and_functions adtbf(this);
236 b->traverse(&adtbf);
239 // Dump a textual representation of an expression to the
240 // the dump file.
242 void
243 Ast_dump_context::dump_expression(const Expression* e)
245 e->dump_expression(this);
248 // Dump a textual representation of an expression list to the
249 // the dump file.
251 void
252 Ast_dump_context::dump_expression_list(const Expression_list* el,
253 bool as_pairs /* = false */)
255 if (el == NULL)
256 return;
258 for (std::vector<Expression*>::const_iterator it = el->begin();
259 it != el->end();
260 it++)
262 if ( it != el->begin())
263 this->ostream() << ",";
264 if (*it != NULL)
265 (*it)->dump_expression(this);
266 else
267 this->ostream() << "NULL";
268 if (as_pairs)
270 this->ostream() << ":";
271 ++it;
272 (*it)->dump_expression(this);
277 // Dump a textual representation of a typed identifier to the
278 // the dump file.
280 void
281 Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
283 this->ostream() << ti->name() << " ";
284 this->dump_type(ti->type());
287 // Dump a textual representation of a typed identifier list to the
288 // the dump file.
290 void
291 Ast_dump_context::dump_typed_identifier_list(
292 const Typed_identifier_list* ti_list)
294 if (ti_list == NULL)
295 return;
297 for (Typed_identifier_list::const_iterator it = ti_list->begin();
298 it != ti_list->end();
299 it++)
301 if (it != ti_list->begin())
302 this->ostream() << ",";
303 this->dump_typed_identifier(&(*it));
307 // Dump a textual representation of a temporary variable to the
308 // the dump file.
310 void
311 Ast_dump_context::dump_temp_variable_name(const Statement* s)
313 go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
314 // Use the statement address as part of the name for the temporary variable.
315 this->ostream() << "tmp." << (uintptr_t) s;
318 // Dump a textual representation of a label to the
319 // the dump file.
321 void
322 Ast_dump_context::dump_label_name(const Unnamed_label* l)
324 // Use the unnamed label address as part of the name for the temporary
325 // variable.
326 this->ostream() << "label." << (uintptr_t) l;
329 // Produce a textual representation of an operator symbol.
331 static const char*
332 op_string(Operator op)
334 // FIXME: This should be in line with symbols that are parsed,
335 // exported and/or imported.
336 switch (op)
338 case OPERATOR_PLUS:
339 return "+";
340 case OPERATOR_MINUS:
341 return "-";
342 case OPERATOR_NOT:
343 return "!";
344 case OPERATOR_XOR:
345 return "^";
346 case OPERATOR_OR:
347 return "|";
348 case OPERATOR_AND:
349 return "&";
350 case OPERATOR_MULT:
351 return "*";
352 case OPERATOR_OROR:
353 return "||";
354 case OPERATOR_ANDAND:
355 return "&&";
356 case OPERATOR_EQEQ:
357 return "==";
358 case OPERATOR_NOTEQ:
359 return "!=";
360 case OPERATOR_LT:
361 return "<";
362 case OPERATOR_LE:
363 return "<=";
364 case OPERATOR_GT:
365 return ">";
366 case OPERATOR_GE:
367 return ">=";
368 case OPERATOR_DIV:
369 return "/";
370 case OPERATOR_MOD:
371 return "%";
372 case OPERATOR_LSHIFT:
373 return "<<";
374 case OPERATOR_RSHIFT:
375 return "//";
376 case OPERATOR_BITCLEAR:
377 return "&^";
378 case OPERATOR_CHANOP:
379 return "<-";
380 case OPERATOR_PLUSEQ:
381 return "+=";
382 case OPERATOR_MINUSEQ:
383 return "-=";
384 case OPERATOR_OREQ:
385 return "|=";
386 case OPERATOR_XOREQ:
387 return "^=";
388 case OPERATOR_MULTEQ:
389 return "*=";
390 case OPERATOR_DIVEQ:
391 return "/=";
392 case OPERATOR_MODEQ:
393 return "%=";
394 case OPERATOR_LSHIFTEQ:
395 return "<<=";
396 case OPERATOR_RSHIFTEQ:
397 return ">>=";
398 case OPERATOR_ANDEQ:
399 return "&=";
400 case OPERATOR_BITCLEAREQ:
401 return "&^=";
402 case OPERATOR_PLUSPLUS:
403 return "++";
404 case OPERATOR_MINUSMINUS:
405 return "--";
406 case OPERATOR_COLON:
407 return ":";
408 case OPERATOR_COLONEQ:
409 return ":=";
410 case OPERATOR_SEMICOLON:
411 return ";";
412 case OPERATOR_DOT:
413 return ".";
414 case OPERATOR_ELLIPSIS:
415 return "...";
416 case OPERATOR_COMMA:
417 return ",";
418 case OPERATOR_LPAREN:
419 return "(";
420 case OPERATOR_RPAREN:
421 return ")";
422 case OPERATOR_LCURLY:
423 return "{";
424 case OPERATOR_RCURLY:
425 return "}";
426 case OPERATOR_LSQUARE:
427 return "[";
428 case OPERATOR_RSQUARE:
429 return "]";
430 default:
431 go_unreachable();
433 return NULL;
436 // Dump a textual representation of an operator to the
437 // the dump file.
439 void
440 Ast_dump_context::dump_operator(Operator op)
442 this->ostream() << op_string(op);
445 // Size of a single indent.
447 const int Ast_dump_context::offset_ = 2;
449 // Print indenting spaces to dump file.
451 void
452 Ast_dump_context::print_indent()
454 for (int i = 0; i < this->indent_ * this->offset_; i++)
455 this->ostream() << " ";
458 // Dump a textual representation of the ast to the
459 // the dump file.
461 void Gogo::dump_ast(const char* basename)
463 if (::ast_dump_flag.is_enabled())
465 Ast_dump_context adc;
466 adc.dump(this, basename);
470 // Implementation of String_dump interface.
472 void
473 Ast_dump_context::write_c_string(const char* s)
475 this->ostream() << s;
478 void
479 Ast_dump_context::write_string(const std::string& s)
481 this->ostream() << s;
484 // Dump statement to stream.
486 void
487 Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
489 Ast_dump_context adc(out, false);
490 stm->dump_statement(&adc);
493 // Dump expression to stream.
495 void
496 Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
498 Ast_dump_context adc(out, false);
499 expr->dump_expression(&adc);
502 // Dump an expression to std::cerr. This is intended to be used
503 // from within a debugging session.
505 void
506 debug_go_expression(const Expression* expr)
508 if (expr == NULL)
509 std::cerr << "<null>";
510 else
512 Ast_dump_context::dump_to_stream(expr, &std::cerr);
513 std::string lstr = Linemap::location_to_string(expr->location());
514 std::cerr << " // loc " << lstr << std::endl;
518 // Shallow dump of stmt to std::cerr. This is intended to be used
519 // from within a debugging session.
521 void
522 debug_go_statement(const Statement* stmt)
524 if (stmt == NULL)
525 std::cerr << "<null>\n";
526 else
528 std::string lstr = Linemap::location_to_string(stmt->location());
529 Statement *ncstmt = const_cast<Statement*>(stmt);
530 Block_statement* bs = ncstmt->block_statement();
531 if (bs != NULL)
532 std::cerr << "Block " << bs->block()
533 << " // location: " << lstr << std::endl;
534 else
535 Ast_dump_context::dump_to_stream(stmt, &std::cerr);
539 // Deep dump of statement to std::cerr. This is intended to be used
540 // from within a debugging session.
542 void
543 debug_go_statement_deep(const Statement* statement)
545 Ast_dump_context adc(&std::cerr, true);
546 statement->dump_statement(&adc);
549 // Shallow dump of a block to std::cerr. This is intended to be used
550 // from within a debugging session.
552 void
553 debug_go_block(const Block* block)
555 if (block == NULL)
556 std::cerr << "<null>";
557 else
559 std::cerr << "Block " << block
560 << " (enclosing " << block->enclosing() << "):\n";
561 const std::vector<Statement*>* stmts = block->statements();
562 if (stmts != NULL)
564 for (size_t i = 0; i < stmts->size(); ++i)
566 debug_go_statement(stmts->at(i));
572 // Deep dump of a block to std:cerr. This is intended to be used
573 // from within a debugging session.
575 void
576 debug_go_block_deep(const Block* block)
578 Ast_dump_context adc(&std::cerr, true);
579 Block* ncblock = const_cast<Block*>(block);
580 adc.dump_block(ncblock);
583 class Type_dumper
585 typedef Unordered_map(const Type*, unsigned) idx_map;
586 public:
587 Type_dumper(const Type* type)
588 : top_(type), ntypes_(0)
590 this->worklist_.push_back(type);
593 void visit();
595 std::string stringResult() { return ss_.str(); }
597 private:
598 void emitpre(unsigned tag, const Type* addr);
599 void typeref(const char*, const Type*, const char *);
600 void visit_forward_declaration_type(const Forward_declaration_type* fdt);
601 void visit_function_type(const Function_type* ft);
602 void visit_struct_type(const Struct_type* st);
603 void visit_array_type(const Array_type* at);
604 void visit_map_type(const Map_type* mt);
605 void visit_channel_type(const Channel_type* mt);
606 void visit_interface_type(const Interface_type* mt);
607 void visit_methods(const Typed_identifier_list* methods,
608 const char *tag);
609 std::pair<bool, unsigned> lookup(const Type*);
611 static const unsigned notag = 0xffffffff;
613 private:
614 const Type* top_;
615 idx_map types_;
616 unsigned ntypes_;
617 std::list<const Type*> worklist_;
618 std::ostringstream ss_;
621 // Look up a type, installing it in 'types_'. Return is <found, N>
622 // where 'found' is true if type had been previously recorded, and N
623 // is the index/tag assigned to N. The input argument is appended to
624 // the work list if this is the first time we've seen it.
626 std::pair<bool, unsigned> Type_dumper::lookup(const Type* t)
628 std::pair<const Type*, unsigned> entry = std::make_pair(t, this->ntypes_);
629 std::pair<idx_map::iterator, bool> ins = this->types_.insert(entry);
630 if (ins.second)
632 this->ntypes_++;
633 if (t != this->top_)
634 this->worklist_.push_back(t);
636 return std::make_pair(ins.second, ins.first->second);
639 // Emit preamble prior to dumping a type, including the type
640 // pointer itself and the tag we've assigned it. If no
641 // tag is specified (via special "notag" value) and/or the
642 // pointer is null, then just emit an equivalent amount
643 // of spaces.
645 void Type_dumper::emitpre(unsigned tag, const Type* ptr)
647 char tbuf[50], pbuf[50], buf[200];
649 tbuf[0] = '\0';
650 if (tag != notag)
651 snprintf(tbuf, sizeof tbuf, "T%u", tag);
653 pbuf[0] = '\0';
654 if (ptr != NULL)
655 snprintf(pbuf, sizeof pbuf, "%p", (const void*) ptr);
657 snprintf(buf, sizeof buf, "%8s %16s ", tbuf, pbuf);
658 this->ss_ << buf;
661 // Emit a reference to a type into the dump buffer. In most cases this means
662 // just the type tag, but for named types we also emit the name, and for
663 // simple/primitive types (ex: int64) we emit the type itself. If "pref" is
664 // non-NULL, emit the string prior to the reference, and if "suf" is non-NULL,
665 // emit it following the reference.
667 void Type_dumper::typeref(const char* pref, const Type* t, const char* suf)
669 if (pref != NULL)
670 this->ss_ << pref;
671 std::pair<bool, unsigned> p = this->lookup(t);
672 unsigned tag = p.second;
673 switch (t->classification())
675 case Type::TYPE_NAMED:
677 const Named_type* nt = t->named_type();
678 const Named_object* no = nt->named_object();
679 this->ss_ << "'" << no->message_name() << "' -> ";
680 const Type* underlying = nt->real_type();
681 this->typeref(NULL, underlying, NULL);
682 break;
684 case Type::TYPE_POINTER:
685 this->typeref("*", t->points_to(), NULL);
686 break;
687 case Type::TYPE_ERROR:
688 this->ss_ << "error_type";
689 break;
690 case Type::TYPE_INTEGER:
692 const Integer_type* it = t->integer_type();
693 if (it->is_abstract())
694 this->ss_ << "abstract_int";
695 else
696 this->ss_ << (it->is_unsigned() ? "u" : "") << "int" << it->bits();
697 break;
699 case Type::TYPE_FLOAT:
701 const Float_type* ft = t->float_type();
702 if (ft->is_abstract())
703 this->ss_ << "abstract_float";
704 else
705 this->ss_ << "float" << ft->bits();
706 break;
708 case Type::TYPE_COMPLEX:
710 const Complex_type* ct = t->complex_type();
711 if (ct->is_abstract())
712 this->ss_ << "abstract_complex";
713 else
714 this->ss_ << "complex" << ct->bits();
715 break;
717 case Type::TYPE_BOOLEAN:
718 this->ss_ << "bool";
719 break;
720 case Type::TYPE_STRING:
721 this->ss_ << "string";
722 break;
723 case Type::TYPE_NIL:
724 this->ss_ << "nil_type";
725 break;
726 case Type::TYPE_VOID:
727 this->ss_ << "void_type";
728 break;
729 case Type::TYPE_FUNCTION:
730 case Type::TYPE_STRUCT:
731 case Type::TYPE_ARRAY:
732 case Type::TYPE_MAP:
733 case Type::TYPE_CHANNEL:
734 case Type::TYPE_FORWARD:
735 case Type::TYPE_INTERFACE:
736 this->ss_ << "T" << tag;
737 break;
739 default:
740 // This is a debugging routine, so instead of a go_unreachable()
741 // issue a warning/error, to allow for the possibility that the
742 // compiler we're debugging is in a bad state.
743 this->ss_ << "<??? " << ((unsigned)t->classification()) << "> "
744 << "T" << tag;
746 if (suf != NULL)
747 this->ss_ << suf;
750 void Type_dumper::visit_forward_declaration_type(const Forward_declaration_type* fdt)
752 this->ss_ << "forward_declaration_type ";
753 if (fdt->is_defined())
754 this->typeref("-> ", fdt->real_type(), NULL);
755 else
756 this->ss_ << "'" << fdt->name() << "'";
757 this->ss_ << "\n";
760 void Type_dumper::visit_function_type(const Function_type* ft)
762 this->ss_ << "function\n";
763 const Typed_identifier* rec = ft->receiver();
764 if (rec != NULL)
766 this->emitpre(notag, NULL);
767 this->typeref("receiver ", rec->type(), "\n");
769 const Typed_identifier_list* parameters = ft->parameters();
770 if (parameters != NULL)
772 for (Typed_identifier_list::const_iterator p = parameters->begin();
773 p != parameters->end();
774 ++p)
776 this->emitpre(notag, NULL);
777 this->typeref(" param ", p->type(), "\n");
780 const Typed_identifier_list* results = ft->results();
781 if (results != NULL)
783 for (Typed_identifier_list::const_iterator p = results->begin();
784 p != results->end();
785 ++p)
787 this->emitpre(notag, NULL);
788 this->typeref(" result ", p->type(), "\n");
793 void Type_dumper::visit_struct_type(const Struct_type* st)
795 this->ss_ << "struct\n";
796 const Struct_field_list* fields = st->fields();
797 if (fields != NULL)
799 for (Struct_field_list::const_iterator p = fields->begin();
800 p != fields->end();
801 ++p)
803 this->emitpre(notag, NULL);
804 this->typeref(" field ", p->type(), "\n");
809 void Type_dumper::visit_array_type(const Array_type* at)
811 this->ss_ << "array [";
812 if (at->length() != NULL)
814 int64_t len = 0;
815 if (at->int_length(&len))
816 this->ss_ << len;
818 this->typeref("] ", at->element_type(), "\n");
821 void Type_dumper::visit_map_type(const Map_type* mt)
823 this->ss_ << "map [";
824 this->typeref(NULL, mt->key_type(), NULL);
825 this->typeref("] ", mt->val_type(), "\n");
828 void Type_dumper::visit_methods(const Typed_identifier_list* methods,
829 const char *tag)
831 if (tag != NULL)
833 this->emitpre(notag, NULL);
834 this->ss_ << tag << "\n";
836 for (Typed_identifier_list::const_iterator p = methods->begin();
837 p != methods->end();
838 ++p)
840 this->emitpre(notag, NULL);
841 if (p->name().empty())
842 this->typeref(" embedded method ", p->type(), "\n");
843 else
845 this->ss_ << " method '" << p->name() << "' ";
846 this->typeref(NULL, p->type(), "\n");
851 void Type_dumper::visit_interface_type(const Interface_type* it)
853 const Typed_identifier_list* methods =
854 (it->methods_are_finalized() ? it->methods() : it->local_methods());
855 if (methods == NULL)
857 this->ss_ << "empty_interface\n";
858 return;
860 this->ss_ << "interface";
861 if (! it->methods_are_finalized())
863 this->ss_ << " [unfinalized]\n";
864 visit_methods(it->local_methods(), NULL);
866 else
868 this->ss_ << "\n";
869 visit_methods(it->local_methods(), "[parse_methods]");
870 visit_methods(it->methods(), "[all_methods]");
874 void Type_dumper::visit_channel_type(const Channel_type* ct)
876 this->ss_ << "channel {";
877 if (ct->may_send())
878 this->ss_ << " send";
879 if (ct->may_receive())
880 this->ss_ << " receive";
881 this->typeref(" } ", ct->element_type(), "\n");
884 void Type_dumper::visit()
886 while (! this->worklist_.empty()) {
887 const Type* t = this->worklist_.front();
888 this->worklist_.pop_front();
890 std::pair<bool, unsigned> p = this->lookup(t);
891 unsigned tag = p.second;
892 this->emitpre(tag, t);
894 switch(t->classification())
896 case Type::TYPE_ERROR:
897 case Type::TYPE_INTEGER:
898 case Type::TYPE_FLOAT:
899 case Type::TYPE_COMPLEX:
900 case Type::TYPE_BOOLEAN:
901 case Type::TYPE_STRING:
902 case Type::TYPE_VOID:
903 case Type::TYPE_POINTER:
904 case Type::TYPE_NIL:
905 case Type::TYPE_NAMED:
906 this->typeref(NULL, t, "\n");
907 break;
908 case Type::TYPE_FORWARD:
909 this->visit_forward_declaration_type(t->forward_declaration_type());
910 break;
912 case Type::TYPE_FUNCTION:
913 this->visit_function_type(t->function_type());
914 break;
915 case Type::TYPE_STRUCT:
916 this->visit_struct_type(t->struct_type());
917 break;
918 case Type::TYPE_ARRAY:
919 this->visit_array_type(t->array_type());
920 break;
921 case Type::TYPE_MAP:
922 this->visit_map_type(t->map_type());
923 break;
924 case Type::TYPE_CHANNEL:
925 this->visit_channel_type(t->channel_type());
926 break;
927 case Type::TYPE_INTERFACE:
928 this->visit_interface_type(t->interface_type());
929 break;
930 default:
931 // This is a debugging routine, so instead of a go_unreachable()
932 // issue a warning/error, to allow for the possibility that the
933 // compiler we're debugging is in a bad state.
934 this->ss_ << "<unknown/unrecognized classification "
935 << ((unsigned)t->classification()) << ">\n";
940 // Dump a Go type for debugging purposes. This is a deep as opposed
941 // to shallow dump; all of the types reachable from the specified
942 // type will be dumped in addition to the type itself.
944 void debug_go_type(const Type* type)
946 if (type == NULL)
948 std::cerr << "<NULL type>\n";
949 return;
951 Type_dumper dumper(type);
952 dumper.visit();
953 std::cerr << dumper.stringResult();
956 void debug_go_type(Type* type)
958 const Type* ctype = type;
959 debug_go_type(ctype);