comparison gcc/go/gofrontend/ast-dump.cc @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
6 6
7 #include "go-system.h" 7 #include "go-system.h"
8 8
9 #include <iostream> 9 #include <iostream>
10 #include <fstream> 10 #include <fstream>
11 #include <sstream>
11 12
12 #include "gogo.h" 13 #include "gogo.h"
13 #include "expressions.h" 14 #include "expressions.h"
14 #include "statements.h" 15 #include "statements.h"
15 #include "types.h" 16 #include "types.h"
132 it != res->end(); 133 it != res->end();
133 it++) 134 it++)
134 { 135 {
135 if (it != res->begin()) 136 if (it != res->begin())
136 this->ast_dump_context_->ostream() << ","; 137 this->ast_dump_context_->ostream() << ",";
137 Named_object* no = (*it); 138 Named_object* rno = (*it);
138 139
139 this->ast_dump_context_->ostream() << no->name() << " "; 140 this->ast_dump_context_->ostream() << rno->name() << " ";
140 go_assert(no->is_result_variable()); 141 go_assert(rno->is_result_variable());
141 Result_variable* resvar = no->result_var_value(); 142 Result_variable* resvar = rno->result_var_value();
142 143
143 this->ast_dump_context_->dump_type(resvar->type()); 144 this->ast_dump_context_->dump_type(resvar->type());
144 145
145 } 146 }
146 this->ast_dump_context_->ostream() << ")"; 147 this->ast_dump_context_->ostream() << ")";
197 out.open(dumpname.c_str()); 198 out.open(dumpname.c_str());
198 199
199 if (out.fail()) 200 if (out.fail())
200 { 201 {
201 go_error_at(Linemap::unknown_location(), 202 go_error_at(Linemap::unknown_location(),
202 "cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str()); 203 "cannot open %s:%m; %<-fgo-dump-ast%> ignored",
204 dumpname.c_str());
203 return; 205 return;
204 } 206 }
205 207
206 this->gogo_ = gogo; 208 this->gogo_ = gogo;
207 this->ostream_ = &out; 209 this->ostream_ = &out;
480 Ast_dump_context::write_string(const std::string& s) 482 Ast_dump_context::write_string(const std::string& s)
481 { 483 {
482 this->ostream() << s; 484 this->ostream() << s;
483 } 485 }
484 486
485 // Dump statment to stream. 487 // Dump statement to stream.
486 488
487 void 489 void
488 Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out) 490 Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
489 { 491 {
490 Ast_dump_context adc(out, false); 492 Ast_dump_context adc(out, false);
497 Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out) 499 Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
498 { 500 {
499 Ast_dump_context adc(out, false); 501 Ast_dump_context adc(out, false);
500 expr->dump_expression(&adc); 502 expr->dump_expression(&adc);
501 } 503 }
504
505 // Dump an expression to std::cerr. This is intended to be used
506 // from within a debugging session.
507
508 void
509 debug_go_expression(const Expression* expr)
510 {
511 if (expr == NULL)
512 std::cerr << "<null>";
513 else
514 {
515 Ast_dump_context::dump_to_stream(expr, &std::cerr);
516 std::string lstr = Linemap::location_to_string(expr->location());
517 std::cerr << " // loc " << lstr << std::endl;
518 }
519 }
520
521 // Shallow dump of stmt to std::cerr. This is intended to be used
522 // from within a debugging session.
523
524 void
525 debug_go_statement(const Statement* stmt)
526 {
527 if (stmt == NULL)
528 std::cerr << "<null>\n";
529 else
530 {
531 std::string lstr = Linemap::location_to_string(stmt->location());
532 Statement *ncstmt = const_cast<Statement*>(stmt);
533 Block_statement* bs = ncstmt->block_statement();
534 if (bs != NULL)
535 std::cerr << "Block " << bs->block()
536 << " // location: " << lstr << std::endl;
537 else
538 Ast_dump_context::dump_to_stream(stmt, &std::cerr);
539 }
540 }
541
542 // Deep dump of statement to std::cerr. This is intended to be used
543 // from within a debugging session.
544
545 void
546 debug_go_statement_deep(const Statement* statement)
547 {
548 Ast_dump_context adc(&std::cerr, true);
549 statement->dump_statement(&adc);
550 }
551
552 // Shallow dump of a block to std::cerr. This is intended to be used
553 // from within a debugging session.
554
555 void
556 debug_go_block(const Block* block)
557 {
558 if (block == NULL)
559 std::cerr << "<null>";
560 else
561 {
562 std::cerr << "Block " << block
563 << " (enclosing " << block->enclosing() << "):\n";
564 const std::vector<Statement*>* stmts = block->statements();
565 if (stmts != NULL)
566 {
567 for (size_t i = 0; i < stmts->size(); ++i)
568 {
569 debug_go_statement(stmts->at(i));
570 }
571 }
572 }
573 }
574
575 // Deep dump of a block to std:cerr. This is intended to be used
576 // from within a debugging session.
577
578 void
579 debug_go_block_deep(const Block* block)
580 {
581 Ast_dump_context adc(&std::cerr, true);
582 Block* ncblock = const_cast<Block*>(block);
583 adc.dump_block(ncblock);
584 }
585
586 class Type_dumper
587 {
588 typedef Unordered_map(const Type*, unsigned) idx_map;
589 public:
590 Type_dumper(const Type* type)
591 : top_(type), ntypes_(0)
592 {
593 this->worklist_.push_back(type);
594 }
595
596 void visit();
597
598 std::string stringResult() { return ss_.str(); }
599
600 private:
601 void emitpre(unsigned tag, const Type* addr);
602 void typeref(const char*, const Type*, const char *);
603 void visit_forward_declaration_type(const Forward_declaration_type* fdt);
604 void visit_function_type(const Function_type* ft);
605 void visit_struct_type(const Struct_type* st);
606 void visit_array_type(const Array_type* at);
607 void visit_map_type(const Map_type* mt);
608 void visit_channel_type(const Channel_type* mt);
609 void visit_interface_type(const Interface_type* mt);
610 void visit_methods(const Typed_identifier_list* methods,
611 const char *tag);
612 std::pair<bool, unsigned> lookup(const Type*);
613
614 static const unsigned notag = 0xffffffff;
615
616 private:
617 const Type* top_;
618 idx_map types_;
619 unsigned ntypes_;
620 std::list<const Type*> worklist_;
621 std::ostringstream ss_;
622 };
623
624 // Look up a type, installing it in 'types_'. Return is <found, N>
625 // where 'found' is true if type had been previously recorded, and N
626 // is the index/tag assigned to N. The input argument is appended to
627 // the work list if this is the first time we've seen it.
628
629 std::pair<bool, unsigned> Type_dumper::lookup(const Type* t)
630 {
631 std::pair<const Type*, unsigned> entry = std::make_pair(t, this->ntypes_);
632 std::pair<idx_map::iterator, bool> ins = this->types_.insert(entry);
633 if (ins.second)
634 {
635 this->ntypes_++;
636 if (t != this->top_)
637 this->worklist_.push_back(t);
638 }
639 return std::make_pair(ins.second, ins.first->second);
640 }
641
642 // Emit preamble prior to dumping a type, including the type
643 // pointer itself and the tag we've assigned it. If no
644 // tag is specified (via special "notag" value) and/or the
645 // pointer is null, then just emit an equivalent amount
646 // of spaces.
647
648 void Type_dumper::emitpre(unsigned tag, const Type* ptr)
649 {
650 char tbuf[50], pbuf[50], buf[200];
651
652 tbuf[0] = '\0';
653 if (tag != notag)
654 snprintf(tbuf, sizeof tbuf, "T%u", tag);
655
656 pbuf[0] = '\0';
657 if (ptr != NULL)
658 snprintf(pbuf, sizeof pbuf, "%p", (const void*) ptr);
659
660 snprintf(buf, sizeof buf, "%8s %16s ", tbuf, pbuf);
661 this->ss_ << buf;
662 }
663
664 // Emit a reference to a type into the dump buffer. In most cases this means
665 // just the type tag, but for named types we also emit the name, and for
666 // simple/primitive types (ex: int64) we emit the type itself. If "pref" is
667 // non-NULL, emit the string prior to the reference, and if "suf" is non-NULL,
668 // emit it following the reference.
669
670 void Type_dumper::typeref(const char* pref, const Type* t, const char* suf)
671 {
672 if (pref != NULL)
673 this->ss_ << pref;
674 std::pair<bool, unsigned> p = this->lookup(t);
675 unsigned tag = p.second;
676 switch (t->classification())
677 {
678 case Type::TYPE_NAMED:
679 {
680 const Named_type* nt = t->named_type();
681 const Named_object* no = nt->named_object();
682 this->ss_ << "'" << no->message_name() << "' -> ";
683 const Type* underlying = nt->real_type();
684 this->typeref(NULL, underlying, NULL);
685 break;
686 }
687 case Type::TYPE_POINTER:
688 this->typeref("*", t->points_to(), NULL);
689 break;
690 case Type::TYPE_ERROR:
691 this->ss_ << "error_type";
692 break;
693 case Type::TYPE_INTEGER:
694 {
695 const Integer_type* it = t->integer_type();
696 if (it->is_abstract())
697 this->ss_ << "abstract_int";
698 else
699 this->ss_ << (it->is_unsigned() ? "u" : "") << "int" << it->bits();
700 break;
701 }
702 case Type::TYPE_FLOAT:
703 {
704 const Float_type* ft = t->float_type();
705 if (ft->is_abstract())
706 this->ss_ << "abstract_float";
707 else
708 this->ss_ << "float" << ft->bits();
709 break;
710 }
711 case Type::TYPE_COMPLEX:
712 {
713 const Complex_type* ct = t->complex_type();
714 if (ct->is_abstract())
715 this->ss_ << "abstract_complex";
716 else
717 this->ss_ << "complex" << ct->bits();
718 break;
719 }
720 case Type::TYPE_BOOLEAN:
721 this->ss_ << "bool";
722 break;
723 case Type::TYPE_STRING:
724 this->ss_ << "string";
725 break;
726 case Type::TYPE_NIL:
727 this->ss_ << "nil_type";
728 break;
729 case Type::TYPE_VOID:
730 this->ss_ << "void_type";
731 break;
732 case Type::TYPE_FUNCTION:
733 case Type::TYPE_STRUCT:
734 case Type::TYPE_ARRAY:
735 case Type::TYPE_MAP:
736 case Type::TYPE_CHANNEL:
737 case Type::TYPE_FORWARD:
738 case Type::TYPE_INTERFACE:
739 this->ss_ << "T" << tag;
740 break;
741
742 default:
743 // This is a debugging routine, so instead of a go_unreachable()
744 // issue a warning/error, to allow for the possibility that the
745 // compiler we're debugging is in a bad state.
746 this->ss_ << "<??? " << ((unsigned)t->classification()) << "> "
747 << "T" << tag;
748 }
749 if (suf != NULL)
750 this->ss_ << suf;
751 }
752
753 void Type_dumper::visit_forward_declaration_type(const Forward_declaration_type* fdt)
754 {
755 this->ss_ << "forward_declaration_type ";
756 if (fdt->is_defined())
757 this->typeref("-> ", fdt->real_type(), NULL);
758 else
759 this->ss_ << "'" << fdt->name() << "'";
760 this->ss_ << "\n";
761 }
762
763 void Type_dumper::visit_function_type(const Function_type* ft)
764 {
765 this->ss_ << "function\n";
766 const Typed_identifier* rec = ft->receiver();
767 if (rec != NULL)
768 {
769 this->emitpre(notag, NULL);
770 this->typeref("receiver ", rec->type(), "\n");
771 }
772 const Typed_identifier_list* parameters = ft->parameters();
773 if (parameters != NULL)
774 {
775 for (Typed_identifier_list::const_iterator p = parameters->begin();
776 p != parameters->end();
777 ++p)
778 {
779 this->emitpre(notag, NULL);
780 this->typeref(" param ", p->type(), "\n");
781 }
782 }
783 const Typed_identifier_list* results = ft->results();
784 if (results != NULL)
785 {
786 for (Typed_identifier_list::const_iterator p = results->begin();
787 p != results->end();
788 ++p)
789 {
790 this->emitpre(notag, NULL);
791 this->typeref(" result ", p->type(), "\n");
792 }
793 }
794 }
795
796 void Type_dumper::visit_struct_type(const Struct_type* st)
797 {
798 this->ss_ << "struct\n";
799 const Struct_field_list* fields = st->fields();
800 if (fields != NULL)
801 {
802 for (Struct_field_list::const_iterator p = fields->begin();
803 p != fields->end();
804 ++p)
805 {
806 this->emitpre(notag, NULL);
807 this->typeref(" field ", p->type(), "\n");
808 }
809 }
810 }
811
812 void Type_dumper::visit_array_type(const Array_type* at)
813 {
814 this->ss_ << "array [";
815 if (at->length() != NULL)
816 {
817 int64_t len = 0;
818 if (at->int_length(&len))
819 this->ss_ << len;
820 }
821 this->typeref("] ", at->element_type(), "\n");
822 }
823
824 void Type_dumper::visit_map_type(const Map_type* mt)
825 {
826 this->ss_ << "map [";
827 this->typeref(NULL, mt->key_type(), NULL);
828 this->typeref("] ", mt->val_type(), "\n");
829 }
830
831 void Type_dumper::visit_methods(const Typed_identifier_list* methods,
832 const char *tag)
833 {
834 if (tag != NULL)
835 {
836 this->emitpre(notag, NULL);
837 this->ss_ << tag << "\n";
838 }
839 for (Typed_identifier_list::const_iterator p = methods->begin();
840 p != methods->end();
841 ++p)
842 {
843 this->emitpre(notag, NULL);
844 if (p->name().empty())
845 this->typeref(" embedded method ", p->type(), "\n");
846 else
847 {
848 this->ss_ << " method '" << p->name() << "' ";
849 this->typeref(NULL, p->type(), "\n");
850 }
851 }
852 }
853
854 void Type_dumper::visit_interface_type(const Interface_type* it)
855 {
856 const Typed_identifier_list* methods =
857 (it->methods_are_finalized() ? it->methods() : it->local_methods());
858 if (methods == NULL)
859 {
860 this->ss_ << "empty_interface\n";
861 return;
862 }
863 this->ss_ << "interface";
864 if (! it->methods_are_finalized())
865 {
866 this->ss_ << " [unfinalized]\n";
867 visit_methods(it->local_methods(), NULL);
868 }
869 else
870 {
871 this->ss_ << "\n";
872 visit_methods(it->local_methods(), "[parse_methods]");
873 visit_methods(it->methods(), "[all_methods]");
874 }
875 }
876
877 void Type_dumper::visit_channel_type(const Channel_type* ct)
878 {
879 this->ss_ << "channel {";
880 if (ct->may_send())
881 this->ss_ << " send";
882 if (ct->may_receive())
883 this->ss_ << " receive";
884 this->typeref(" } ", ct->element_type(), "\n");
885 }
886
887 void Type_dumper::visit()
888 {
889 while (! this->worklist_.empty()) {
890 const Type* t = this->worklist_.front();
891 this->worklist_.pop_front();
892
893 std::pair<bool, unsigned> p = this->lookup(t);
894 unsigned tag = p.second;
895 this->emitpre(tag, t);
896
897 switch(t->classification())
898 {
899 case Type::TYPE_ERROR:
900 case Type::TYPE_INTEGER:
901 case Type::TYPE_FLOAT:
902 case Type::TYPE_COMPLEX:
903 case Type::TYPE_BOOLEAN:
904 case Type::TYPE_STRING:
905 case Type::TYPE_VOID:
906 case Type::TYPE_POINTER:
907 case Type::TYPE_NIL:
908 case Type::TYPE_NAMED:
909 this->typeref(NULL, t, "\n");
910 break;
911 case Type::TYPE_FORWARD:
912 this->visit_forward_declaration_type(t->forward_declaration_type());
913 break;
914
915 case Type::TYPE_FUNCTION:
916 this->visit_function_type(t->function_type());
917 break;
918 case Type::TYPE_STRUCT:
919 this->visit_struct_type(t->struct_type());
920 break;
921 case Type::TYPE_ARRAY:
922 this->visit_array_type(t->array_type());
923 break;
924 case Type::TYPE_MAP:
925 this->visit_map_type(t->map_type());
926 break;
927 case Type::TYPE_CHANNEL:
928 this->visit_channel_type(t->channel_type());
929 break;
930 case Type::TYPE_INTERFACE:
931 this->visit_interface_type(t->interface_type());
932 break;
933 default:
934 // This is a debugging routine, so instead of a go_unreachable()
935 // issue a warning/error, to allow for the possibility that the
936 // compiler we're debugging is in a bad state.
937 this->ss_ << "<unknown/unrecognized classification "
938 << ((unsigned)t->classification()) << ">\n";
939 }
940 }
941 }
942
943 // Dump a Go type for debugging purposes. This is a deep as opposed
944 // to shallow dump; all of the types reachable from the specified
945 // type will be dumped in addition to the type itself.
946
947 void debug_go_type(const Type* type)
948 {
949 if (type == NULL)
950 {
951 std::cerr << "<NULL type>\n";
952 return;
953 }
954 Type_dumper dumper(type);
955 dumper.visit();
956 std::cerr << dumper.stringResult();
957 }
958
959 void debug_go_type(Type* type)
960 {
961 const Type* ctype = type;
962 debug_go_type(ctype);
963 }