LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - ast-dump.cc (source / functions) Hit Total Coverage
Test: gcc.info Lines: 3 508 0.6 %
Date: 2020-03-28 11:57:23 Functions: 1 42 2.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // ast-dump.cc -- AST debug dump.    -*- C++ -*-
       2                 :            : 
       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.
       6                 :            : 
       7                 :            : #include "go-system.h"
       8                 :            : 
       9                 :            : #include <iostream>
      10                 :            : #include <fstream>
      11                 :            : #include <sstream>
      12                 :            : 
      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"
      21                 :            : 
      22                 :            : // The -fgo-dump-ast flag to activate AST dumps.
      23                 :            : 
      24                 :            : Go_dump ast_dump_flag("ast");
      25                 :            : 
      26                 :            : // This class is used to traverse the tree to look for blocks and
      27                 :            : // function headers.
      28                 :            : 
      29                 :          0 : class Ast_dump_traverse_blocks_and_functions : public Traverse
      30                 :            : {
      31                 :            :  public:
      32                 :          0 :   Ast_dump_traverse_blocks_and_functions(Ast_dump_context* ast_dump_context)
      33                 :          0 :       : Traverse(traverse_blocks | traverse_functions | traverse_variables),
      34                 :          0 :       ast_dump_context_(ast_dump_context)
      35                 :            :   { }
      36                 :            : 
      37                 :            :  protected:
      38                 :            :   int
      39                 :            :   block(Block*);
      40                 :            : 
      41                 :            :   int
      42                 :            :   function(Named_object*);
      43                 :            : 
      44                 :            :   int
      45                 :            :   variable(Named_object*);
      46                 :            : 
      47                 :            :  private:
      48                 :            :   Ast_dump_context* ast_dump_context_;
      49                 :            : };
      50                 :            : 
      51                 :            : // This class is used to traverse the tree to look for statements.
      52                 :            : 
      53                 :          0 : class Ast_dump_traverse_statements : public Traverse
      54                 :            : {
      55                 :            :  public:
      56                 :          0 :   Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context)
      57                 :          0 :       : Traverse(traverse_statements),
      58                 :          0 :       ast_dump_context_(ast_dump_context)
      59                 :            :   { }
      60                 :            : 
      61                 :            :  protected:
      62                 :            :   int
      63                 :            :   statement(Block*, size_t* pindex, Statement*);
      64                 :            : 
      65                 :            :  private:
      66                 :            :   Ast_dump_context* ast_dump_context_;
      67                 :            : };
      68                 :            : 
      69                 :            : // For each block we enclose it in brackets.
      70                 :            : 
      71                 :          0 : int Ast_dump_traverse_blocks_and_functions::block(Block * block)
      72                 :            : {
      73                 :          0 :   if (block == NULL)
      74                 :            :     {
      75                 :          0 :       this->ast_dump_context_->ostream() << std::endl;
      76                 :          0 :       return TRAVERSE_EXIT;
      77                 :            :     }
      78                 :            : 
      79                 :          0 :   this->ast_dump_context_->print_indent();
      80                 :          0 :   this->ast_dump_context_->ostream() << "{" << std::endl;
      81                 :          0 :   this->ast_dump_context_->indent();
      82                 :            : 
      83                 :            :   // Dump statememts.
      84                 :          0 :   Ast_dump_traverse_statements adts(this->ast_dump_context_);
      85                 :          0 :   block->traverse(&adts);
      86                 :            : 
      87                 :          0 :   this->ast_dump_context_->unindent();
      88                 :          0 :   this->ast_dump_context_->print_indent();
      89                 :          0 :   this->ast_dump_context_->ostream() << "}" << std::endl;
      90                 :            : 
      91                 :          0 :   return TRAVERSE_SKIP_COMPONENTS;
      92                 :            : }
      93                 :            : 
      94                 :            : // Dump each traversed statement.
      95                 :            : 
      96                 :            : int
      97                 :          0 : Ast_dump_traverse_statements::statement(Block* block, size_t* pindex,
      98                 :            :                                         Statement* statement)
      99                 :            : {
     100                 :          0 :   statement->dump_statement(this->ast_dump_context_);
     101                 :            : 
     102                 :          0 :   if (statement->is_block_statement())
     103                 :            :     {
     104                 :          0 :       Ast_dump_traverse_blocks_and_functions adtbf(this->ast_dump_context_);
     105                 :          0 :       statement->traverse(block, pindex, &adtbf);
     106                 :            :     }
     107                 :            : 
     108                 :          0 :   return TRAVERSE_SKIP_COMPONENTS;
     109                 :            : }
     110                 :            : 
     111                 :            : // Dump the function header.
     112                 :            : 
     113                 :            : int
     114                 :          0 : Ast_dump_traverse_blocks_and_functions::function(Named_object* no)
     115                 :            : {
     116                 :          0 :   this->ast_dump_context_->ostream() << no->name();
     117                 :            : 
     118                 :          0 :   go_assert(no->is_function());
     119                 :          0 :   Function* func = no->func_value();
     120                 :            : 
     121                 :          0 :   this->ast_dump_context_->ostream() << "(";
     122                 :          0 :   this->ast_dump_context_->dump_typed_identifier_list(
     123                 :            :                               func->type()->parameters());
     124                 :            : 
     125                 :          0 :   this->ast_dump_context_->ostream() << ")";
     126                 :            : 
     127                 :          0 :   Function::Results* res = func->result_variables();
     128                 :          0 :   if (res != NULL && !res->empty())
     129                 :            :     {
     130                 :          0 :       this->ast_dump_context_->ostream() << " (";
     131                 :            : 
     132                 :          0 :       for (Function::Results::const_iterator it = res->begin();
     133                 :          0 :           it != res->end();
     134                 :          0 :           it++)
     135                 :            :         {
     136                 :          0 :           if (it != res->begin())
     137                 :          0 :             this->ast_dump_context_->ostream() << ",";
     138                 :          0 :           Named_object* rno = (*it);
     139                 :            : 
     140                 :          0 :           this->ast_dump_context_->ostream() << rno->name() << " ";
     141                 :          0 :           go_assert(rno->is_result_variable());
     142                 :          0 :           Result_variable* resvar = rno->result_var_value();
     143                 :            : 
     144                 :          0 :           this->ast_dump_context_->dump_type(resvar->type());
     145                 :            : 
     146                 :            :         }
     147                 :          0 :       this->ast_dump_context_->ostream() << ")";
     148                 :            :     }
     149                 :            : 
     150                 :          0 :   this->ast_dump_context_->ostream() << " : ";
     151                 :          0 :   this->ast_dump_context_->dump_type(func->type());
     152                 :          0 :   this->ast_dump_context_->ostream() << std::endl;
     153                 :            : 
     154                 :          0 :   return TRAVERSE_CONTINUE;
     155                 :            : }
     156                 :            : 
     157                 :            : // Dump variable preinits
     158                 :            : 
     159                 :            : int
     160                 :          0 : Ast_dump_traverse_blocks_and_functions::variable(Named_object* no)
     161                 :            : {
     162                 :          0 :   if (!no->is_variable())
     163                 :            :     return TRAVERSE_CONTINUE;
     164                 :            : 
     165                 :          0 :   Variable* var = no->var_value();
     166                 :          0 :   if (var->has_pre_init())
     167                 :            :     {
     168                 :          0 :       this->ast_dump_context_->ostream() << "// preinit block for var "
     169                 :          0 :                                          << no->message_name() << "\n";
     170                 :          0 :       var->preinit()->traverse(this);
     171                 :            :     }
     172                 :            : 
     173                 :            :   return TRAVERSE_CONTINUE;
     174                 :            : }
     175                 :            : 
     176                 :            : 
     177                 :            : 
     178                 :            : // Class Ast_dump_context.
     179                 :            : 
     180                 :          0 : Ast_dump_context::Ast_dump_context(std::ostream* out /* = NULL */,
     181                 :          0 :                                    bool dump_subblocks /* = true */)
     182                 :          0 :   :  indent_(0), dump_subblocks_(dump_subblocks), ostream_(out), gogo_(NULL)
     183                 :            : {
     184                 :          0 : }
     185                 :            : 
     186                 :            : // Dump files will be named %basename%.dump.ast
     187                 :            : 
     188                 :            : const char* kAstDumpFileExtension = ".dump.ast";
     189                 :            : 
     190                 :            : // Dump the internal representation.
     191                 :            : 
     192                 :            : void
     193                 :          0 : Ast_dump_context::dump(Gogo* gogo, const char* basename)
     194                 :            : {
     195                 :          0 :   std::ofstream out;
     196                 :          0 :   std::string dumpname(basename);
     197                 :          0 :   dumpname += ".dump.ast";
     198                 :          0 :   out.open(dumpname.c_str());
     199                 :            : 
     200                 :          0 :   if (out.fail())
     201                 :            :     {
     202                 :          0 :       go_error_at(Linemap::unknown_location(),
     203                 :            :                   "cannot open %s:%m; %<-fgo-dump-ast%> ignored",
     204                 :            :                   dumpname.c_str());
     205                 :          0 :       return;
     206                 :            :     }
     207                 :            : 
     208                 :          0 :   this->gogo_ = gogo;
     209                 :          0 :   this->ostream_ = &out;
     210                 :            : 
     211                 :          0 :   Ast_dump_traverse_blocks_and_functions adtbf(this);
     212                 :          0 :   gogo->traverse(&adtbf);
     213                 :            : 
     214                 :          0 :   out.close();
     215                 :            : }
     216                 :            : 
     217                 :            : // Dump a textual representation of a type to the
     218                 :            : // the dump file.
     219                 :            : 
     220                 :            : void
     221                 :          0 : Ast_dump_context::dump_type(const Type* t)
     222                 :            : {
     223                 :          0 :   if (t == NULL)
     224                 :          0 :     this->ostream() << "(nil type)";
     225                 :            :   else
     226                 :            :     // FIXME: write a type pretty printer instead of
     227                 :            :     // using mangled names.
     228                 :          0 :     if (this->gogo_ != NULL)
     229                 :          0 :       this->ostream() << "(" << t->mangled_name(this->gogo_) <<  ")";
     230                 :          0 : }
     231                 :            : 
     232                 :            : // Dump a textual representation of a block to the
     233                 :            : // the dump file.
     234                 :            : 
     235                 :            : void
     236                 :          0 : Ast_dump_context::dump_block(Block* b)
     237                 :            : {
     238                 :          0 :   Ast_dump_traverse_blocks_and_functions adtbf(this);
     239                 :          0 :   b->traverse(&adtbf);
     240                 :          0 : }
     241                 :            : 
     242                 :            : // Dump a textual representation of an expression to the
     243                 :            : // the dump file.
     244                 :            : 
     245                 :            : void
     246                 :          0 : Ast_dump_context::dump_expression(const Expression* e)
     247                 :            : {
     248                 :          0 :   e->dump_expression(this);
     249                 :          0 : }
     250                 :            : 
     251                 :            : // Dump a textual representation of an expression list to the
     252                 :            : // the dump file.
     253                 :            : 
     254                 :            : void
     255                 :          0 : Ast_dump_context::dump_expression_list(const Expression_list* el,
     256                 :            :                                        bool as_pairs /* = false */)
     257                 :            : {
     258                 :          0 :   if (el == NULL)
     259                 :            :     return;
     260                 :            : 
     261                 :          0 :   for (std::vector<Expression*>::const_iterator it = el->begin();
     262                 :          0 :        it != el->end();
     263                 :          0 :        it++)
     264                 :            :     {
     265                 :          0 :       if ( it != el->begin())
     266                 :          0 :         this->ostream() << ",";
     267                 :          0 :       if (*it != NULL)
     268                 :          0 :         (*it)->dump_expression(this);
     269                 :            :       else
     270                 :          0 :         this->ostream() << "NULL";
     271                 :          0 :       if (as_pairs)
     272                 :            :         {
     273                 :          0 :           this->ostream() << ":";
     274                 :          0 :           ++it;
     275                 :          0 :           (*it)->dump_expression(this);
     276                 :            :         }
     277                 :            :     }
     278                 :            : }
     279                 :            : 
     280                 :            : // Dump a textual representation of a typed identifier to the
     281                 :            : // the dump file.
     282                 :            : 
     283                 :            : void
     284                 :          0 : Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
     285                 :            : {
     286                 :          0 :   this->ostream() << ti->name() << " ";
     287                 :          0 :   this->dump_type(ti->type());
     288                 :          0 : }
     289                 :            : 
     290                 :            : // Dump a textual representation of a typed identifier list to the
     291                 :            : // the dump file.
     292                 :            : 
     293                 :            : void
     294                 :          0 : Ast_dump_context::dump_typed_identifier_list(
     295                 :            :     const Typed_identifier_list* ti_list)
     296                 :            : {
     297                 :          0 :   if (ti_list == NULL)
     298                 :            :     return;
     299                 :            : 
     300                 :          0 :   for (Typed_identifier_list::const_iterator it = ti_list->begin();
     301                 :          0 :        it != ti_list->end();
     302                 :          0 :        it++)
     303                 :            :     {
     304                 :          0 :       if (it != ti_list->begin())
     305                 :          0 :         this->ostream() << ",";
     306                 :          0 :       this->dump_typed_identifier(&(*it));
     307                 :            :     }
     308                 :            : }
     309                 :            : 
     310                 :            : // Dump a textual representation of a temporary variable to the
     311                 :            : // the dump file.
     312                 :            : 
     313                 :            : void
     314                 :          0 : Ast_dump_context::dump_temp_variable_name(const Statement* s)
     315                 :            : {
     316                 :          0 :   go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
     317                 :            :   // Use the statement address as part of the name for the temporary variable.
     318                 :          0 :   this->ostream() << "tmp." << (uintptr_t) s;
     319                 :          0 : }
     320                 :            : 
     321                 :            : // Dump a textual representation of a label to the
     322                 :            : // the dump file.
     323                 :            : 
     324                 :            : void
     325                 :          0 : Ast_dump_context::dump_label_name(const Unnamed_label* l)
     326                 :            : {
     327                 :            :   // Use the unnamed label address as part of the name for the temporary
     328                 :            :   // variable.
     329                 :          0 :   this->ostream() << "label." << (uintptr_t) l;
     330                 :          0 : }
     331                 :            : 
     332                 :            : // Produce a textual representation of an operator symbol.
     333                 :            : 
     334                 :            : static const char*
     335                 :          0 : op_string(Operator op)
     336                 :            : {
     337                 :            : // FIXME: This should be in line with symbols that are parsed,
     338                 :            : // exported and/or imported.
     339                 :          0 :   switch (op)
     340                 :            :     {
     341                 :            :     case OPERATOR_PLUS:
     342                 :            :       return "+";
     343                 :          0 :     case OPERATOR_MINUS:
     344                 :          0 :       return "-";
     345                 :          0 :     case OPERATOR_NOT:
     346                 :          0 :       return "!";
     347                 :          0 :     case OPERATOR_XOR:
     348                 :          0 :       return "^";
     349                 :          0 :     case OPERATOR_OR:
     350                 :          0 :       return "|";
     351                 :          0 :     case OPERATOR_AND:
     352                 :          0 :       return "&";
     353                 :          0 :     case OPERATOR_MULT:
     354                 :          0 :       return "*";
     355                 :          0 :     case OPERATOR_OROR:
     356                 :          0 :       return "||";
     357                 :          0 :     case OPERATOR_ANDAND:
     358                 :          0 :       return "&&";
     359                 :          0 :     case OPERATOR_EQEQ:
     360                 :          0 :       return "==";
     361                 :          0 :     case OPERATOR_NOTEQ:
     362                 :          0 :       return "!=";
     363                 :          0 :     case OPERATOR_LT:
     364                 :          0 :       return "<";
     365                 :          0 :     case OPERATOR_LE:
     366                 :          0 :       return "<=";
     367                 :          0 :     case OPERATOR_GT:
     368                 :          0 :       return ">";
     369                 :          0 :     case OPERATOR_GE:
     370                 :          0 :       return ">=";
     371                 :          0 :     case OPERATOR_DIV:
     372                 :          0 :       return "/";
     373                 :          0 :     case OPERATOR_MOD:
     374                 :          0 :       return "%";
     375                 :          0 :     case OPERATOR_LSHIFT:
     376                 :          0 :       return "<<";
     377                 :          0 :     case OPERATOR_RSHIFT:
     378                 :          0 :       return "//";
     379                 :          0 :     case OPERATOR_BITCLEAR:
     380                 :          0 :       return "&^";
     381                 :          0 :     case OPERATOR_CHANOP:
     382                 :          0 :       return "<-";
     383                 :          0 :     case OPERATOR_PLUSEQ:
     384                 :          0 :       return "+=";
     385                 :          0 :     case OPERATOR_MINUSEQ:
     386                 :          0 :       return "-=";
     387                 :          0 :     case OPERATOR_OREQ:
     388                 :          0 :       return "|=";
     389                 :          0 :     case OPERATOR_XOREQ:
     390                 :          0 :       return "^=";
     391                 :          0 :     case OPERATOR_MULTEQ:
     392                 :          0 :       return "*=";
     393                 :          0 :     case OPERATOR_DIVEQ:
     394                 :          0 :       return "/=";
     395                 :          0 :     case OPERATOR_MODEQ:
     396                 :          0 :       return "%=";
     397                 :          0 :     case OPERATOR_LSHIFTEQ:
     398                 :          0 :       return "<<=";
     399                 :          0 :     case OPERATOR_RSHIFTEQ:
     400                 :          0 :       return ">>=";
     401                 :          0 :     case OPERATOR_ANDEQ:
     402                 :          0 :       return "&=";
     403                 :          0 :     case OPERATOR_BITCLEAREQ:
     404                 :          0 :       return "&^=";
     405                 :          0 :     case OPERATOR_PLUSPLUS:
     406                 :          0 :       return "++";
     407                 :          0 :     case OPERATOR_MINUSMINUS:
     408                 :          0 :       return "--";
     409                 :          0 :     case OPERATOR_COLON:
     410                 :          0 :       return ":";
     411                 :          0 :     case OPERATOR_COLONEQ:
     412                 :          0 :       return ":=";
     413                 :          0 :     case OPERATOR_SEMICOLON:
     414                 :          0 :       return ";";
     415                 :          0 :     case OPERATOR_DOT:
     416                 :          0 :       return ".";
     417                 :          0 :     case OPERATOR_ELLIPSIS:
     418                 :          0 :       return "...";
     419                 :          0 :     case OPERATOR_COMMA:
     420                 :          0 :       return ",";
     421                 :          0 :     case OPERATOR_LPAREN:
     422                 :          0 :       return "(";
     423                 :          0 :     case OPERATOR_RPAREN:
     424                 :          0 :       return ")";
     425                 :          0 :     case OPERATOR_LCURLY:
     426                 :          0 :       return "{";
     427                 :          0 :     case OPERATOR_RCURLY:
     428                 :          0 :       return "}";
     429                 :          0 :     case OPERATOR_LSQUARE:
     430                 :          0 :       return "[";
     431                 :          0 :     case OPERATOR_RSQUARE:
     432                 :          0 :       return "]";
     433                 :          0 :     default:
     434                 :          0 :       go_unreachable();
     435                 :            :     }
     436                 :            :   return NULL;
     437                 :            : }
     438                 :            : 
     439                 :            : // Dump a textual representation of an operator to the
     440                 :            : // the dump file.
     441                 :            : 
     442                 :            : void
     443                 :          0 : Ast_dump_context::dump_operator(Operator op)
     444                 :            : {
     445                 :          0 :   this->ostream() << op_string(op);
     446                 :          0 : }
     447                 :            : 
     448                 :            : // Size of a single indent.
     449                 :            : 
     450                 :            : const int Ast_dump_context::offset_ = 2;
     451                 :            : 
     452                 :            : // Print indenting spaces to dump file.
     453                 :            : 
     454                 :            : void
     455                 :          0 : Ast_dump_context::print_indent()
     456                 :            : {
     457                 :          0 :   for (int i = 0; i < this->indent_ * this->offset_; i++)
     458                 :          0 :     this->ostream() << " ";
     459                 :          0 : }
     460                 :            : 
     461                 :            : // Dump a textual representation of the ast to the
     462                 :            : // the dump file.
     463                 :            : 
     464                 :       3372 : void Gogo::dump_ast(const char* basename)
     465                 :            : {
     466                 :       3372 :   if (::ast_dump_flag.is_enabled())
     467                 :            :     {
     468                 :          0 :       Ast_dump_context adc;
     469                 :          0 :       adc.dump(this, basename);
     470                 :            :     }
     471                 :       3372 : }
     472                 :            : 
     473                 :            : // Implementation of String_dump interface.
     474                 :            : 
     475                 :            : void
     476                 :          0 : Ast_dump_context::write_c_string(const char* s)
     477                 :            : {
     478                 :          0 :   this->ostream() << s;
     479                 :          0 : }
     480                 :            : 
     481                 :            : void
     482                 :          0 : Ast_dump_context::write_string(const std::string& s)
     483                 :            : {
     484                 :          0 :   this->ostream() << s;
     485                 :          0 : }
     486                 :            : 
     487                 :            : // Dump statement to stream.
     488                 :            : 
     489                 :            : void
     490                 :          0 : Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
     491                 :            : {
     492                 :          0 :   Ast_dump_context adc(out, false);
     493                 :          0 :   stm->dump_statement(&adc);
     494                 :          0 : }
     495                 :            : 
     496                 :            : // Dump expression to stream.
     497                 :            : 
     498                 :            : void
     499                 :          0 : Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
     500                 :            : {
     501                 :          0 :   Ast_dump_context adc(out, false);
     502                 :          0 :   expr->dump_expression(&adc);
     503                 :          0 : }
     504                 :            : 
     505                 :            : // Dump an expression to std::cerr. This is intended to be used
     506                 :            : // from within a debugging session.
     507                 :            : 
     508                 :            : void
     509                 :          0 : debug_go_expression(const Expression* expr)
     510                 :            : {
     511                 :          0 :   if (expr == NULL)
     512                 :          0 :     std::cerr << "<null>";
     513                 :            :   else
     514                 :            :     {
     515                 :          0 :       Ast_dump_context::dump_to_stream(expr, &std::cerr);
     516                 :          0 :       std::string lstr = Linemap::location_to_string(expr->location());
     517                 :          0 :       std::cerr << " // loc " << lstr << std::endl;
     518                 :            :     }
     519                 :          0 : }
     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                 :          0 : debug_go_statement(const Statement* stmt)
     526                 :            : {
     527                 :          0 :   if (stmt == NULL)
     528                 :          0 :     std::cerr << "<null>\n";
     529                 :            :   else
     530                 :            :     {
     531                 :          0 :       std::string lstr = Linemap::location_to_string(stmt->location());
     532                 :          0 :       Statement *ncstmt = const_cast<Statement*>(stmt);
     533                 :          0 :       Block_statement* bs = ncstmt->block_statement();
     534                 :          0 :       if (bs != NULL)
     535                 :          0 :         std::cerr << "Block " << bs->block()
     536                 :          0 :                   << " // location: " << lstr << std::endl;
     537                 :            :       else
     538                 :          0 :         Ast_dump_context::dump_to_stream(stmt, &std::cerr);
     539                 :            :     }
     540                 :          0 : }
     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                 :          0 : debug_go_statement_deep(const Statement* statement)
     547                 :            : {
     548                 :          0 :   Ast_dump_context adc(&std::cerr, true);
     549                 :          0 :   statement->dump_statement(&adc);
     550                 :          0 : }
     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                 :          0 : debug_go_block(const Block* block)
     557                 :            : {
     558                 :          0 :   if (block == NULL)
     559                 :          0 :     std::cerr << "<null>";
     560                 :            :   else
     561                 :            :     {
     562                 :          0 :       std::cerr << "Block " << block
     563                 :          0 :                 << " (enclosing " << block->enclosing() << "):\n";
     564                 :          0 :       const std::vector<Statement*>* stmts = block->statements();
     565                 :          0 :       if (stmts != NULL)
     566                 :            :         {
     567                 :          0 :           for (size_t i = 0; i < stmts->size(); ++i)
     568                 :            :             {
     569                 :          0 :               debug_go_statement(stmts->at(i));
     570                 :            :             }
     571                 :            :         }
     572                 :            :     }
     573                 :          0 : }
     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                 :          0 : debug_go_block_deep(const Block* block)
     580                 :            : {
     581                 :          0 :   Ast_dump_context adc(&std::cerr, true);
     582                 :          0 :   Block* ncblock = const_cast<Block*>(block);
     583                 :          0 :   adc.dump_block(ncblock);
     584                 :          0 : }
     585                 :            : 
     586                 :            : class Type_dumper
     587                 :            : {
     588                 :            :   typedef Unordered_map(const Type*, unsigned) idx_map;
     589                 :            :  public:
     590                 :          0 :   Type_dumper(const Type* type)
     591                 :          0 :       : top_(type), ntypes_(0)
     592                 :            :   {
     593                 :          0 :     this->worklist_.push_back(type);
     594                 :          0 :   }
     595                 :            : 
     596                 :            :   void visit();
     597                 :            : 
     598                 :          0 :   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                 :          0 : std::pair<bool, unsigned> Type_dumper::lookup(const Type* t)
     630                 :            : {
     631                 :          0 :   std::pair<const Type*, unsigned> entry = std::make_pair(t, this->ntypes_);
     632                 :          0 :   std::pair<idx_map::iterator, bool> ins = this->types_.insert(entry);
     633                 :          0 :   if (ins.second)
     634                 :            :     {
     635                 :          0 :       this->ntypes_++;
     636                 :          0 :       if (t != this->top_)
     637                 :          0 :         this->worklist_.push_back(t);
     638                 :            :     }
     639                 :          0 :   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                 :          0 : void Type_dumper::emitpre(unsigned tag, const Type* ptr)
     649                 :            : {
     650                 :          0 :   char tbuf[50], pbuf[50], buf[200];
     651                 :            : 
     652                 :          0 :   tbuf[0] = '\0';
     653                 :          0 :   if (tag != notag)
     654                 :          0 :     snprintf(tbuf, sizeof tbuf, "T%u", tag);
     655                 :            : 
     656                 :          0 :   pbuf[0] = '\0';
     657                 :          0 :   if (ptr != NULL)
     658                 :          0 :     snprintf(pbuf, sizeof pbuf, "%p", (const void*) ptr);
     659                 :            : 
     660                 :          0 :   snprintf(buf, sizeof buf, "%8s %16s  ", tbuf, pbuf);
     661                 :          0 :   this->ss_ << buf;
     662                 :          0 : }
     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                 :          0 : void Type_dumper::typeref(const char* pref, const Type* t, const char* suf)
     671                 :            : {
     672                 :          0 :   if (pref != NULL)
     673                 :          0 :     this->ss_ << pref;
     674                 :          0 :   std::pair<bool, unsigned> p = this->lookup(t);
     675                 :          0 :   unsigned tag = p.second;
     676                 :          0 :   switch (t->classification())
     677                 :            :     {
     678                 :          0 :       case Type::TYPE_NAMED:
     679                 :          0 :         {
     680                 :          0 :           const Named_type* nt = t->named_type();
     681                 :          0 :           const Named_object* no = nt->named_object();
     682                 :          0 :           this->ss_ << "'" << no->message_name() << "' -> ";
     683                 :          0 :           const Type* underlying = nt->real_type();
     684                 :          0 :           this->typeref(NULL, underlying, NULL);
     685                 :          0 :           break;
     686                 :            :         }
     687                 :          0 :       case Type::TYPE_POINTER:
     688                 :          0 :         this->typeref("*", t->points_to(), NULL);
     689                 :          0 :         break;
     690                 :          0 :       case Type::TYPE_ERROR:
     691                 :          0 :         this->ss_ << "error_type";
     692                 :          0 :         break;
     693                 :          0 :       case Type::TYPE_INTEGER:
     694                 :          0 :         {
     695                 :          0 :           const Integer_type* it = t->integer_type();
     696                 :          0 :           if (it->is_abstract())
     697                 :          0 :             this->ss_ << "abstract_int";
     698                 :            :           else
     699                 :          0 :             this->ss_ << (it->is_unsigned() ? "u" : "") << "int" << it->bits();
     700                 :            :           break;
     701                 :            :         }
     702                 :          0 :       case Type::TYPE_FLOAT:
     703                 :          0 :         {
     704                 :          0 :           const Float_type* ft = t->float_type();
     705                 :          0 :           if (ft->is_abstract())
     706                 :          0 :             this->ss_ << "abstract_float";
     707                 :            :           else
     708                 :          0 :             this->ss_ << "float" << ft->bits();
     709                 :            :           break;
     710                 :            :         }
     711                 :          0 :       case Type::TYPE_COMPLEX:
     712                 :          0 :         {
     713                 :          0 :           const Complex_type* ct = t->complex_type();
     714                 :          0 :           if (ct->is_abstract())
     715                 :          0 :             this->ss_ << "abstract_complex";
     716                 :            :           else
     717                 :          0 :             this->ss_ << "complex" << ct->bits();
     718                 :            :           break;
     719                 :            :         }
     720                 :          0 :       case Type::TYPE_BOOLEAN:
     721                 :          0 :         this->ss_ << "bool";
     722                 :          0 :         break;
     723                 :          0 :       case Type::TYPE_STRING:
     724                 :          0 :         this->ss_ << "string";
     725                 :          0 :         break;
     726                 :          0 :       case Type::TYPE_NIL:
     727                 :          0 :         this->ss_ << "nil_type";
     728                 :          0 :         break;
     729                 :          0 :     case Type::TYPE_VOID:
     730                 :          0 :         this->ss_ << "void_type";
     731                 :          0 :         break;
     732                 :          0 :     case Type::TYPE_FUNCTION:
     733                 :          0 :     case Type::TYPE_STRUCT:
     734                 :          0 :     case Type::TYPE_ARRAY:
     735                 :          0 :     case Type::TYPE_MAP:
     736                 :          0 :     case Type::TYPE_CHANNEL:
     737                 :          0 :     case Type::TYPE_FORWARD:
     738                 :          0 :     case Type::TYPE_INTERFACE:
     739                 :          0 :       this->ss_ << "T" << tag;
     740                 :            :       break;
     741                 :            : 
     742                 :          0 :     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                 :          0 :       this->ss_ << "<??? " << ((unsigned)t->classification()) << "> "
     747                 :          0 :                 << "T" << tag;
     748                 :            :     }
     749                 :          0 :   if (suf != NULL)
     750                 :          0 :     this->ss_ << suf;
     751                 :          0 : }
     752                 :            : 
     753                 :          0 : void Type_dumper::visit_forward_declaration_type(const Forward_declaration_type* fdt)
     754                 :            : {
     755                 :          0 :   this->ss_ << "forward_declaration_type ";
     756                 :          0 :   if (fdt->is_defined())
     757                 :          0 :     this->typeref("-> ", fdt->real_type(), NULL);
     758                 :            :   else
     759                 :          0 :     this->ss_ << "'" << fdt->name() << "'";
     760                 :          0 :   this->ss_ << "\n";
     761                 :          0 : }
     762                 :            : 
     763                 :          0 : void Type_dumper::visit_function_type(const Function_type* ft)
     764                 :            : {
     765                 :          0 :   this->ss_ << "function\n";
     766                 :          0 :   const Typed_identifier* rec = ft->receiver();
     767                 :          0 :   if (rec != NULL)
     768                 :            :     {
     769                 :          0 :       this->emitpre(notag, NULL);
     770                 :          0 :       this->typeref("receiver ", rec->type(), "\n");
     771                 :            :     }
     772                 :          0 :   const Typed_identifier_list* parameters = ft->parameters();
     773                 :          0 :   if (parameters != NULL)
     774                 :            :     {
     775                 :          0 :       for (Typed_identifier_list::const_iterator p = parameters->begin();
     776                 :          0 :            p != parameters->end();
     777                 :          0 :            ++p)
     778                 :            :         {
     779                 :          0 :           this->emitpre(notag, NULL);
     780                 :          0 :           this->typeref(" param ", p->type(), "\n");
     781                 :            :         }
     782                 :            :     }
     783                 :          0 :   const Typed_identifier_list* results = ft->results();
     784                 :          0 :   if (results != NULL)
     785                 :            :     {
     786                 :          0 :       for (Typed_identifier_list::const_iterator p = results->begin();
     787                 :          0 :            p != results->end();
     788                 :          0 :            ++p)
     789                 :            :         {
     790                 :          0 :           this->emitpre(notag, NULL);
     791                 :          0 :           this->typeref(" result ", p->type(), "\n");
     792                 :            :         }
     793                 :            :     }
     794                 :          0 : }
     795                 :            : 
     796                 :          0 : void Type_dumper::visit_struct_type(const Struct_type* st)
     797                 :            : {
     798                 :          0 :   this->ss_ << "struct\n";
     799                 :          0 :   const Struct_field_list* fields = st->fields();
     800                 :          0 :   if (fields != NULL)
     801                 :            :     {
     802                 :          0 :       for (Struct_field_list::const_iterator p = fields->begin();
     803                 :          0 :            p != fields->end();
     804                 :          0 :            ++p)
     805                 :            :         {
     806                 :          0 :           this->emitpre(notag, NULL);
     807                 :          0 :           this->typeref(" field ", p->type(), "\n");
     808                 :            :         }
     809                 :            :     }
     810                 :          0 : }
     811                 :            : 
     812                 :          0 : void Type_dumper::visit_array_type(const Array_type* at)
     813                 :            : {
     814                 :          0 :   this->ss_ << "array [";
     815                 :          0 :   if (at->length() != NULL)
     816                 :            :     {
     817                 :          0 :       int64_t len = 0;
     818                 :          0 :       if (at->int_length(&len))
     819                 :          0 :         this->ss_ << len;
     820                 :            :     }
     821                 :          0 :   this->typeref("] ", at->element_type(), "\n");
     822                 :          0 : }
     823                 :            : 
     824                 :          0 : void Type_dumper::visit_map_type(const Map_type* mt)
     825                 :            : {
     826                 :          0 :   this->ss_ << "map [";
     827                 :          0 :   this->typeref(NULL, mt->key_type(), NULL);
     828                 :          0 :   this->typeref("] ", mt->val_type(), "\n");
     829                 :          0 : }
     830                 :            : 
     831                 :          0 : void Type_dumper::visit_methods(const Typed_identifier_list* methods,
     832                 :            :                                 const char *tag)
     833                 :            : {
     834                 :          0 :   if (tag != NULL)
     835                 :            :     {
     836                 :          0 :       this->emitpre(notag, NULL);
     837                 :          0 :       this->ss_ << tag << "\n";
     838                 :            :     }
     839                 :          0 :   for (Typed_identifier_list::const_iterator p = methods->begin();
     840                 :          0 :        p != methods->end();
     841                 :          0 :        ++p)
     842                 :            :     {
     843                 :          0 :       this->emitpre(notag, NULL);
     844                 :          0 :       if (p->name().empty())
     845                 :          0 :         this->typeref("  embedded method ", p->type(), "\n");
     846                 :            :       else
     847                 :            :         {
     848                 :          0 :           this->ss_ << "  method '" << p->name() << "' ";
     849                 :          0 :           this->typeref(NULL, p->type(), "\n");
     850                 :            :         }
     851                 :            :     }
     852                 :          0 : }
     853                 :            : 
     854                 :          0 : void Type_dumper::visit_interface_type(const Interface_type* it)
     855                 :            : {
     856                 :          0 :   const Typed_identifier_list* methods =
     857                 :          0 :       (it->methods_are_finalized() ? it->methods() : it->local_methods());
     858                 :          0 :   if (methods == NULL)
     859                 :            :     {
     860                 :          0 :       this->ss_ << "empty_interface\n";
     861                 :          0 :       return;
     862                 :            :     }
     863                 :          0 :   this->ss_ << "interface";
     864                 :          0 :   if (! it->methods_are_finalized())
     865                 :            :     {
     866                 :          0 :       this->ss_ << " [unfinalized]\n";
     867                 :          0 :       visit_methods(it->local_methods(), NULL);
     868                 :            :     }
     869                 :            :   else
     870                 :            :     {
     871                 :          0 :       this->ss_ << "\n";
     872                 :          0 :       visit_methods(it->local_methods(), "[parse_methods]");
     873                 :          0 :       visit_methods(it->methods(), "[all_methods]");
     874                 :            :     }
     875                 :            : }
     876                 :            : 
     877                 :          0 : void Type_dumper::visit_channel_type(const Channel_type* ct)
     878                 :            : {
     879                 :          0 :   this->ss_ << "channel {";
     880                 :          0 :   if (ct->may_send())
     881                 :          0 :     this->ss_ << " send";
     882                 :          0 :   if (ct->may_receive())
     883                 :          0 :     this->ss_ << " receive";
     884                 :          0 :   this->typeref(" } ", ct->element_type(), "\n");
     885                 :          0 : }
     886                 :            : 
     887                 :          0 : void Type_dumper::visit()
     888                 :            : {
     889                 :          0 :   while (! this->worklist_.empty()) {
     890                 :          0 :     const Type* t = this->worklist_.front();
     891                 :          0 :     this->worklist_.pop_front();
     892                 :            : 
     893                 :          0 :     std::pair<bool, unsigned> p = this->lookup(t);
     894                 :          0 :     unsigned tag = p.second;
     895                 :          0 :     this->emitpre(tag, t);
     896                 :            : 
     897                 :          0 :     switch(t->classification())
     898                 :            :       {
     899                 :          0 :         case Type::TYPE_ERROR:
     900                 :          0 :         case Type::TYPE_INTEGER:
     901                 :          0 :         case Type::TYPE_FLOAT:
     902                 :          0 :         case Type::TYPE_COMPLEX:
     903                 :          0 :         case Type::TYPE_BOOLEAN:
     904                 :          0 :         case Type::TYPE_STRING:
     905                 :          0 :         case Type::TYPE_VOID:
     906                 :          0 :         case Type::TYPE_POINTER:
     907                 :          0 :         case Type::TYPE_NIL:
     908                 :          0 :         case Type::TYPE_NAMED:
     909                 :          0 :           this->typeref(NULL, t, "\n");
     910                 :          0 :           break;
     911                 :          0 :         case Type::TYPE_FORWARD:
     912                 :          0 :           this->visit_forward_declaration_type(t->forward_declaration_type());
     913                 :          0 :           break;
     914                 :            : 
     915                 :          0 :         case Type::TYPE_FUNCTION:
     916                 :          0 :           this->visit_function_type(t->function_type());
     917                 :          0 :           break;
     918                 :          0 :         case Type::TYPE_STRUCT:
     919                 :          0 :           this->visit_struct_type(t->struct_type());
     920                 :          0 :           break;
     921                 :          0 :         case Type::TYPE_ARRAY:
     922                 :          0 :           this->visit_array_type(t->array_type());
     923                 :          0 :           break;
     924                 :          0 :         case Type::TYPE_MAP:
     925                 :          0 :           this->visit_map_type(t->map_type());
     926                 :          0 :           break;
     927                 :          0 :         case Type::TYPE_CHANNEL:
     928                 :          0 :           this->visit_channel_type(t->channel_type());
     929                 :          0 :           break;
     930                 :          0 :         case Type::TYPE_INTERFACE:
     931                 :          0 :           this->visit_interface_type(t->interface_type());
     932                 :          0 :           break;
     933                 :          0 :         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                 :          0 :           this->ss_ << "<unknown/unrecognized classification "
     938                 :          0 :                     << ((unsigned)t->classification()) << ">\n";
     939                 :            :       }
     940                 :            :   }
     941                 :          0 : }
     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                 :          0 : void debug_go_type(const Type* type)
     948                 :            : {
     949                 :          0 :   if (type == NULL)
     950                 :            :     {
     951                 :          0 :       std::cerr << "<NULL type>\n";
     952                 :          0 :       return;
     953                 :            :     }
     954                 :          0 :   Type_dumper dumper(type);
     955                 :          0 :   dumper.visit();
     956                 :          0 :   std::cerr << dumper.stringResult();
     957                 :            : }
     958                 :            : 
     959                 :          0 : void debug_go_type(Type* type)
     960                 :            : {
     961                 :          0 :   const Type* ctype = type;
     962                 :          0 :   debug_go_type(ctype);
     963                 :          0 : }

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.