LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - ast-dump.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 0.6 % 514 3
Test Date: 2024-04-13 14:00:49 Functions: 2.4 % 42 1
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                 :           0 : }
      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                 :           0 :     }
     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                 :           0 : }
     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                 :           0 :     this->ostream() << "(" << t->message_name() << ")";
     227                 :           0 : }
     228                 :             : 
     229                 :             : // Dump a textual representation of a block to the
     230                 :             : // the dump file.
     231                 :             : 
     232                 :             : void
     233                 :           0 : Ast_dump_context::dump_block(Block* b)
     234                 :             : {
     235                 :           0 :   Ast_dump_traverse_blocks_and_functions adtbf(this);
     236                 :           0 :   b->traverse(&adtbf);
     237                 :           0 : }
     238                 :             : 
     239                 :             : // Dump a textual representation of an expression to the
     240                 :             : // the dump file.
     241                 :             : 
     242                 :             : void
     243                 :           0 : Ast_dump_context::dump_expression(const Expression* e)
     244                 :             : {
     245                 :           0 :   e->dump_expression(this);
     246                 :           0 : }
     247                 :             : 
     248                 :             : // Dump a textual representation of an expression list to the
     249                 :             : // the dump file.
     250                 :             : 
     251                 :             : void
     252                 :           0 : Ast_dump_context::dump_expression_list(const Expression_list* el,
     253                 :             :                                        bool as_pairs /* = false */)
     254                 :             : {
     255                 :           0 :   if (el == NULL)
     256                 :             :     return;
     257                 :             : 
     258                 :           0 :   for (std::vector<Expression*>::const_iterator it = el->begin();
     259                 :           0 :        it != el->end();
     260                 :           0 :        it++)
     261                 :             :     {
     262                 :           0 :       if ( it != el->begin())
     263                 :           0 :         this->ostream() << ",";
     264                 :           0 :       if (*it != NULL)
     265                 :           0 :         (*it)->dump_expression(this);
     266                 :             :       else
     267                 :           0 :         this->ostream() << "NULL";
     268                 :           0 :       if (as_pairs)
     269                 :             :         {
     270                 :           0 :           this->ostream() << ":";
     271                 :           0 :           ++it;
     272                 :           0 :           (*it)->dump_expression(this);
     273                 :             :         }
     274                 :             :     }
     275                 :             : }
     276                 :             : 
     277                 :             : // Dump a textual representation of a typed identifier to the
     278                 :             : // the dump file.
     279                 :             : 
     280                 :             : void
     281                 :           0 : Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
     282                 :             : {
     283                 :           0 :   this->ostream() << ti->name() << " ";
     284                 :           0 :   this->dump_type(ti->type());
     285                 :           0 : }
     286                 :             : 
     287                 :             : // Dump a textual representation of a typed identifier list to the
     288                 :             : // the dump file.
     289                 :             : 
     290                 :             : void
     291                 :           0 : Ast_dump_context::dump_typed_identifier_list(
     292                 :             :     const Typed_identifier_list* ti_list)
     293                 :             : {
     294                 :           0 :   if (ti_list == NULL)
     295                 :             :     return;
     296                 :             : 
     297                 :           0 :   for (Typed_identifier_list::const_iterator it = ti_list->begin();
     298                 :           0 :        it != ti_list->end();
     299                 :           0 :        it++)
     300                 :             :     {
     301                 :           0 :       if (it != ti_list->begin())
     302                 :           0 :         this->ostream() << ",";
     303                 :           0 :       this->dump_typed_identifier(&(*it));
     304                 :             :     }
     305                 :             : }
     306                 :             : 
     307                 :             : // Dump a textual representation of a temporary variable to the
     308                 :             : // the dump file.
     309                 :             : 
     310                 :             : void
     311                 :           0 : Ast_dump_context::dump_temp_variable_name(const Statement* s)
     312                 :             : {
     313                 :           0 :   go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
     314                 :             :   // Use the statement address as part of the name for the temporary variable.
     315                 :           0 :   this->ostream() << "tmp." << (uintptr_t) s;
     316                 :           0 : }
     317                 :             : 
     318                 :             : // Dump a textual representation of a label to the
     319                 :             : // the dump file.
     320                 :             : 
     321                 :             : void
     322                 :           0 : Ast_dump_context::dump_label_name(const Unnamed_label* l)
     323                 :             : {
     324                 :             :   // Use the unnamed label address as part of the name for the temporary
     325                 :             :   // variable.
     326                 :           0 :   this->ostream() << "label." << (uintptr_t) l;
     327                 :           0 : }
     328                 :             : 
     329                 :             : // Produce a textual representation of an operator symbol.
     330                 :             : 
     331                 :             : static const char*
     332                 :           0 : op_string(Operator op)
     333                 :             : {
     334                 :             : // FIXME: This should be in line with symbols that are parsed,
     335                 :             : // exported and/or imported.
     336                 :           0 :   switch (op)
     337                 :             :     {
     338                 :             :     case OPERATOR_PLUS:
     339                 :             :       return "+";
     340                 :           0 :     case OPERATOR_MINUS:
     341                 :           0 :       return "-";
     342                 :           0 :     case OPERATOR_NOT:
     343                 :           0 :       return "!";
     344                 :           0 :     case OPERATOR_XOR:
     345                 :           0 :       return "^";
     346                 :           0 :     case OPERATOR_OR:
     347                 :           0 :       return "|";
     348                 :           0 :     case OPERATOR_AND:
     349                 :           0 :       return "&";
     350                 :           0 :     case OPERATOR_MULT:
     351                 :           0 :       return "*";
     352                 :           0 :     case OPERATOR_OROR:
     353                 :           0 :       return "||";
     354                 :           0 :     case OPERATOR_ANDAND:
     355                 :           0 :       return "&&";
     356                 :           0 :     case OPERATOR_EQEQ:
     357                 :           0 :       return "==";
     358                 :           0 :     case OPERATOR_NOTEQ:
     359                 :           0 :       return "!=";
     360                 :           0 :     case OPERATOR_LT:
     361                 :           0 :       return "<";
     362                 :           0 :     case OPERATOR_LE:
     363                 :           0 :       return "<=";
     364                 :           0 :     case OPERATOR_GT:
     365                 :           0 :       return ">";
     366                 :           0 :     case OPERATOR_GE:
     367                 :           0 :       return ">=";
     368                 :           0 :     case OPERATOR_DIV:
     369                 :           0 :       return "/";
     370                 :           0 :     case OPERATOR_MOD:
     371                 :           0 :       return "%";
     372                 :           0 :     case OPERATOR_LSHIFT:
     373                 :           0 :       return "<<";
     374                 :           0 :     case OPERATOR_RSHIFT:
     375                 :           0 :       return "//";
     376                 :           0 :     case OPERATOR_BITCLEAR:
     377                 :           0 :       return "&^";
     378                 :           0 :     case OPERATOR_CHANOP:
     379                 :           0 :       return "<-";
     380                 :           0 :     case OPERATOR_PLUSEQ:
     381                 :           0 :       return "+=";
     382                 :           0 :     case OPERATOR_MINUSEQ:
     383                 :           0 :       return "-=";
     384                 :           0 :     case OPERATOR_OREQ:
     385                 :           0 :       return "|=";
     386                 :           0 :     case OPERATOR_XOREQ:
     387                 :           0 :       return "^=";
     388                 :           0 :     case OPERATOR_MULTEQ:
     389                 :           0 :       return "*=";
     390                 :           0 :     case OPERATOR_DIVEQ:
     391                 :           0 :       return "/=";
     392                 :           0 :     case OPERATOR_MODEQ:
     393                 :           0 :       return "%=";
     394                 :           0 :     case OPERATOR_LSHIFTEQ:
     395                 :           0 :       return "<<=";
     396                 :           0 :     case OPERATOR_RSHIFTEQ:
     397                 :           0 :       return ">>=";
     398                 :           0 :     case OPERATOR_ANDEQ:
     399                 :           0 :       return "&=";
     400                 :           0 :     case OPERATOR_BITCLEAREQ:
     401                 :           0 :       return "&^=";
     402                 :           0 :     case OPERATOR_PLUSPLUS:
     403                 :           0 :       return "++";
     404                 :           0 :     case OPERATOR_MINUSMINUS:
     405                 :           0 :       return "--";
     406                 :           0 :     case OPERATOR_COLON:
     407                 :           0 :       return ":";
     408                 :           0 :     case OPERATOR_COLONEQ:
     409                 :           0 :       return ":=";
     410                 :           0 :     case OPERATOR_SEMICOLON:
     411                 :           0 :       return ";";
     412                 :           0 :     case OPERATOR_DOT:
     413                 :           0 :       return ".";
     414                 :           0 :     case OPERATOR_ELLIPSIS:
     415                 :           0 :       return "...";
     416                 :           0 :     case OPERATOR_COMMA:
     417                 :           0 :       return ",";
     418                 :           0 :     case OPERATOR_LPAREN:
     419                 :           0 :       return "(";
     420                 :           0 :     case OPERATOR_RPAREN:
     421                 :           0 :       return ")";
     422                 :           0 :     case OPERATOR_LCURLY:
     423                 :           0 :       return "{";
     424                 :           0 :     case OPERATOR_RCURLY:
     425                 :           0 :       return "}";
     426                 :           0 :     case OPERATOR_LSQUARE:
     427                 :           0 :       return "[";
     428                 :           0 :     case OPERATOR_RSQUARE:
     429                 :           0 :       return "]";
     430                 :           0 :     default:
     431                 :           0 :       go_unreachable();
     432                 :             :     }
     433                 :             :   return NULL;
     434                 :             : }
     435                 :             : 
     436                 :             : // Dump a textual representation of an operator to the
     437                 :             : // the dump file.
     438                 :             : 
     439                 :             : void
     440                 :           0 : Ast_dump_context::dump_operator(Operator op)
     441                 :             : {
     442                 :           0 :   this->ostream() << op_string(op);
     443                 :           0 : }
     444                 :             : 
     445                 :             : // Size of a single indent.
     446                 :             : 
     447                 :             : const int Ast_dump_context::offset_ = 2;
     448                 :             : 
     449                 :             : // Print indenting spaces to dump file.
     450                 :             : 
     451                 :             : void
     452                 :           0 : Ast_dump_context::print_indent()
     453                 :             : {
     454                 :           0 :   for (int i = 0; i < this->indent_ * this->offset_; i++)
     455                 :           0 :     this->ostream() << " ";
     456                 :           0 : }
     457                 :             : 
     458                 :             : // Dump a textual representation of the ast to the
     459                 :             : // the dump file.
     460                 :             : 
     461                 :        4642 : void Gogo::dump_ast(const char* basename)
     462                 :             : {
     463                 :        4642 :   if (::ast_dump_flag.is_enabled())
     464                 :             :     {
     465                 :           0 :       Ast_dump_context adc;
     466                 :           0 :       adc.dump(this, basename);
     467                 :             :     }
     468                 :        4642 : }
     469                 :             : 
     470                 :             : // Implementation of String_dump interface.
     471                 :             : 
     472                 :             : void
     473                 :           0 : Ast_dump_context::write_c_string(const char* s)
     474                 :             : {
     475                 :           0 :   this->ostream() << s;
     476                 :           0 : }
     477                 :             : 
     478                 :             : void
     479                 :           0 : Ast_dump_context::write_string(const std::string& s)
     480                 :             : {
     481                 :           0 :   this->ostream() << s;
     482                 :           0 : }
     483                 :             : 
     484                 :             : // Dump statement to stream.
     485                 :             : 
     486                 :             : void
     487                 :           0 : Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
     488                 :             : {
     489                 :           0 :   Ast_dump_context adc(out, false);
     490                 :           0 :   stm->dump_statement(&adc);
     491                 :           0 : }
     492                 :             : 
     493                 :             : // Dump expression to stream.
     494                 :             : 
     495                 :             : void
     496                 :           0 : Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
     497                 :             : {
     498                 :           0 :   Ast_dump_context adc(out, false);
     499                 :           0 :   expr->dump_expression(&adc);
     500                 :           0 : }
     501                 :             : 
     502                 :             : // Dump an expression to std::cerr. This is intended to be used
     503                 :             : // from within a debugging session.
     504                 :             : 
     505                 :             : void
     506                 :           0 : debug_go_expression(const Expression* expr)
     507                 :             : {
     508                 :           0 :   if (expr == NULL)
     509                 :           0 :     std::cerr << "<null>";
     510                 :             :   else
     511                 :             :     {
     512                 :           0 :       Ast_dump_context::dump_to_stream(expr, &std::cerr);
     513                 :           0 :       std::string lstr = Linemap::location_to_string(expr->location());
     514                 :           0 :       std::cerr << " // loc " << lstr << std::endl;
     515                 :           0 :     }
     516                 :           0 : }
     517                 :             : 
     518                 :             : // Shallow dump of stmt to std::cerr. This is intended to be used
     519                 :             : // from within a debugging session.
     520                 :             : 
     521                 :             : void
     522                 :           0 : debug_go_statement(const Statement* stmt)
     523                 :             : {
     524                 :           0 :   if (stmt == NULL)
     525                 :           0 :     std::cerr << "<null>\n";
     526                 :             :   else
     527                 :             :     {
     528                 :           0 :       std::string lstr = Linemap::location_to_string(stmt->location());
     529                 :           0 :       Statement *ncstmt = const_cast<Statement*>(stmt);
     530                 :           0 :       Block_statement* bs = ncstmt->block_statement();
     531                 :           0 :       if (bs != NULL)
     532                 :           0 :         std::cerr << "Block " << bs->block()
     533                 :           0 :                   << " // location: " << lstr << std::endl;
     534                 :             :       else
     535                 :           0 :         Ast_dump_context::dump_to_stream(stmt, &std::cerr);
     536                 :           0 :     }
     537                 :           0 : }
     538                 :             : 
     539                 :             : // Deep dump of statement to std::cerr. This is intended to be used
     540                 :             : // from within a debugging session.
     541                 :             : 
     542                 :             : void
     543                 :           0 : debug_go_statement_deep(const Statement* statement)
     544                 :             : {
     545                 :           0 :   Ast_dump_context adc(&std::cerr, true);
     546                 :           0 :   statement->dump_statement(&adc);
     547                 :           0 : }
     548                 :             : 
     549                 :             : // Shallow dump of a block to std::cerr. This is intended to be used
     550                 :             : // from within a debugging session.
     551                 :             : 
     552                 :             : void
     553                 :           0 : debug_go_block(const Block* block)
     554                 :             : {
     555                 :           0 :   if (block == NULL)
     556                 :           0 :     std::cerr << "<null>";
     557                 :             :   else
     558                 :             :     {
     559                 :           0 :       std::cerr << "Block " << block
     560                 :           0 :                 << " (enclosing " << block->enclosing() << "):\n";
     561                 :           0 :       const std::vector<Statement*>* stmts = block->statements();
     562                 :           0 :       if (stmts != NULL)
     563                 :             :         {
     564                 :           0 :           for (size_t i = 0; i < stmts->size(); ++i)
     565                 :             :             {
     566                 :           0 :               debug_go_statement(stmts->at(i));
     567                 :             :             }
     568                 :             :         }
     569                 :             :     }
     570                 :           0 : }
     571                 :             : 
     572                 :             : // Deep dump of a block to std:cerr. This is intended to be used
     573                 :             : // from within a debugging session.
     574                 :             : 
     575                 :             : void
     576                 :           0 : debug_go_block_deep(const Block* block)
     577                 :             : {
     578                 :           0 :   Ast_dump_context adc(&std::cerr, true);
     579                 :           0 :   Block* ncblock = const_cast<Block*>(block);
     580                 :           0 :   adc.dump_block(ncblock);
     581                 :           0 : }
     582                 :             : 
     583                 :             : class Type_dumper
     584                 :             : {
     585                 :             :   typedef Unordered_map(const Type*, unsigned) idx_map;
     586                 :             :  public:
     587                 :           0 :   Type_dumper(const Type* type)
     588                 :           0 :       : top_(type), ntypes_(0)
     589                 :             :   {
     590                 :           0 :     this->worklist_.push_back(type);
     591                 :           0 :   }
     592                 :             : 
     593                 :             :   void visit();
     594                 :             : 
     595                 :           0 :   std::string stringResult() { return ss_.str(); }
     596                 :             : 
     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*);
     610                 :             : 
     611                 :             :   static const unsigned notag = 0xffffffff;
     612                 :             : 
     613                 :             :  private:
     614                 :             :   const Type* top_;
     615                 :             :   idx_map types_;
     616                 :             :   unsigned ntypes_;
     617                 :             :   std::list<const Type*> worklist_;
     618                 :             :   std::ostringstream ss_;
     619                 :             : };
     620                 :             : 
     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.
     625                 :             : 
     626                 :           0 : std::pair<bool, unsigned> Type_dumper::lookup(const Type* t)
     627                 :             : {
     628                 :           0 :   std::pair<const Type*, unsigned> entry = std::make_pair(t, this->ntypes_);
     629                 :           0 :   std::pair<idx_map::iterator, bool> ins = this->types_.insert(entry);
     630                 :           0 :   if (ins.second)
     631                 :             :     {
     632                 :           0 :       this->ntypes_++;
     633                 :           0 :       if (t != this->top_)
     634                 :           0 :         this->worklist_.push_back(t);
     635                 :             :     }
     636                 :           0 :   return std::make_pair(ins.second, ins.first->second);
     637                 :             : }
     638                 :             : 
     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.
     644                 :             : 
     645                 :           0 : void Type_dumper::emitpre(unsigned tag, const Type* ptr)
     646                 :             : {
     647                 :           0 :   char tbuf[50], pbuf[50], buf[200];
     648                 :             : 
     649                 :           0 :   tbuf[0] = '\0';
     650                 :           0 :   if (tag != notag)
     651                 :           0 :     snprintf(tbuf, sizeof tbuf, "T%u", tag);
     652                 :             : 
     653                 :           0 :   pbuf[0] = '\0';
     654                 :           0 :   if (ptr != NULL)
     655                 :           0 :     snprintf(pbuf, sizeof pbuf, "%p", (const void*) ptr);
     656                 :             : 
     657                 :           0 :   snprintf(buf, sizeof buf, "%8s %16s  ", tbuf, pbuf);
     658                 :           0 :   this->ss_ << buf;
     659                 :           0 : }
     660                 :             : 
     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.
     666                 :             : 
     667                 :           0 : void Type_dumper::typeref(const char* pref, const Type* t, const char* suf)
     668                 :             : {
     669                 :           0 :   if (pref != NULL)
     670                 :           0 :     this->ss_ << pref;
     671                 :           0 :   std::pair<bool, unsigned> p = this->lookup(t);
     672                 :           0 :   unsigned tag = p.second;
     673                 :           0 :   switch (t->classification())
     674                 :             :     {
     675                 :           0 :       case Type::TYPE_NAMED:
     676                 :           0 :         {
     677                 :           0 :           const Named_type* nt = t->named_type();
     678                 :           0 :           const Named_object* no = nt->named_object();
     679                 :           0 :           this->ss_ << "'" << no->message_name() << "' -> ";
     680                 :           0 :           const Type* underlying = nt->real_type();
     681                 :           0 :           this->typeref(NULL, underlying, NULL);
     682                 :           0 :           break;
     683                 :             :         }
     684                 :           0 :       case Type::TYPE_POINTER:
     685                 :           0 :         this->typeref("*", t->points_to(), NULL);
     686                 :           0 :         break;
     687                 :           0 :       case Type::TYPE_ERROR:
     688                 :           0 :         this->ss_ << "error_type";
     689                 :           0 :         break;
     690                 :           0 :       case Type::TYPE_INTEGER:
     691                 :           0 :         {
     692                 :           0 :           const Integer_type* it = t->integer_type();
     693                 :           0 :           if (it->is_abstract())
     694                 :           0 :             this->ss_ << "abstract_int";
     695                 :             :           else
     696                 :           0 :             this->ss_ << (it->is_unsigned() ? "u" : "") << "int" << it->bits();
     697                 :             :           break;
     698                 :             :         }
     699                 :           0 :       case Type::TYPE_FLOAT:
     700                 :           0 :         {
     701                 :           0 :           const Float_type* ft = t->float_type();
     702                 :           0 :           if (ft->is_abstract())
     703                 :           0 :             this->ss_ << "abstract_float";
     704                 :             :           else
     705                 :           0 :             this->ss_ << "float" << ft->bits();
     706                 :             :           break;
     707                 :             :         }
     708                 :           0 :       case Type::TYPE_COMPLEX:
     709                 :           0 :         {
     710                 :           0 :           const Complex_type* ct = t->complex_type();
     711                 :           0 :           if (ct->is_abstract())
     712                 :           0 :             this->ss_ << "abstract_complex";
     713                 :             :           else
     714                 :           0 :             this->ss_ << "complex" << ct->bits();
     715                 :             :           break;
     716                 :             :         }
     717                 :           0 :       case Type::TYPE_BOOLEAN:
     718                 :           0 :         this->ss_ << "bool";
     719                 :           0 :         break;
     720                 :           0 :       case Type::TYPE_STRING:
     721                 :           0 :         this->ss_ << "string";
     722                 :           0 :         break;
     723                 :           0 :       case Type::TYPE_NIL:
     724                 :           0 :         this->ss_ << "nil_type";
     725                 :           0 :         break;
     726                 :           0 :     case Type::TYPE_VOID:
     727                 :           0 :         this->ss_ << "void_type";
     728                 :           0 :         break;
     729                 :           0 :     case Type::TYPE_FUNCTION:
     730                 :           0 :     case Type::TYPE_STRUCT:
     731                 :           0 :     case Type::TYPE_ARRAY:
     732                 :           0 :     case Type::TYPE_MAP:
     733                 :           0 :     case Type::TYPE_CHANNEL:
     734                 :           0 :     case Type::TYPE_FORWARD:
     735                 :           0 :     case Type::TYPE_INTERFACE:
     736                 :           0 :       this->ss_ << "T" << tag;
     737                 :           0 :       break;
     738                 :             : 
     739                 :           0 :     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                 :           0 :       this->ss_ << "<??? " << ((unsigned)t->classification()) << "> "
     744                 :           0 :                 << "T" << tag;
     745                 :             :     }
     746                 :           0 :   if (suf != NULL)
     747                 :           0 :     this->ss_ << suf;
     748                 :           0 : }
     749                 :             : 
     750                 :           0 : void Type_dumper::visit_forward_declaration_type(const Forward_declaration_type* fdt)
     751                 :             : {
     752                 :           0 :   this->ss_ << "forward_declaration_type ";
     753                 :           0 :   if (fdt->is_defined())
     754                 :           0 :     this->typeref("-> ", fdt->real_type(), NULL);
     755                 :             :   else
     756                 :           0 :     this->ss_ << "'" << fdt->name() << "'";
     757                 :           0 :   this->ss_ << "\n";
     758                 :           0 : }
     759                 :             : 
     760                 :           0 : void Type_dumper::visit_function_type(const Function_type* ft)
     761                 :             : {
     762                 :           0 :   this->ss_ << "function\n";
     763                 :           0 :   const Typed_identifier* rec = ft->receiver();
     764                 :           0 :   if (rec != NULL)
     765                 :             :     {
     766                 :           0 :       this->emitpre(notag, NULL);
     767                 :           0 :       this->typeref("receiver ", rec->type(), "\n");
     768                 :             :     }
     769                 :           0 :   const Typed_identifier_list* parameters = ft->parameters();
     770                 :           0 :   if (parameters != NULL)
     771                 :             :     {
     772                 :           0 :       for (Typed_identifier_list::const_iterator p = parameters->begin();
     773                 :           0 :            p != parameters->end();
     774                 :           0 :            ++p)
     775                 :             :         {
     776                 :           0 :           this->emitpre(notag, NULL);
     777                 :           0 :           this->typeref(" param ", p->type(), "\n");
     778                 :             :         }
     779                 :             :     }
     780                 :           0 :   const Typed_identifier_list* results = ft->results();
     781                 :           0 :   if (results != NULL)
     782                 :             :     {
     783                 :           0 :       for (Typed_identifier_list::const_iterator p = results->begin();
     784                 :           0 :            p != results->end();
     785                 :           0 :            ++p)
     786                 :             :         {
     787                 :           0 :           this->emitpre(notag, NULL);
     788                 :           0 :           this->typeref(" result ", p->type(), "\n");
     789                 :             :         }
     790                 :             :     }
     791                 :           0 : }
     792                 :             : 
     793                 :           0 : void Type_dumper::visit_struct_type(const Struct_type* st)
     794                 :             : {
     795                 :           0 :   this->ss_ << "struct\n";
     796                 :           0 :   const Struct_field_list* fields = st->fields();
     797                 :           0 :   if (fields != NULL)
     798                 :             :     {
     799                 :           0 :       for (Struct_field_list::const_iterator p = fields->begin();
     800                 :           0 :            p != fields->end();
     801                 :           0 :            ++p)
     802                 :             :         {
     803                 :           0 :           this->emitpre(notag, NULL);
     804                 :           0 :           this->typeref(" field ", p->type(), "\n");
     805                 :             :         }
     806                 :             :     }
     807                 :           0 : }
     808                 :             : 
     809                 :           0 : void Type_dumper::visit_array_type(const Array_type* at)
     810                 :             : {
     811                 :           0 :   this->ss_ << "array [";
     812                 :           0 :   if (at->length() != NULL)
     813                 :             :     {
     814                 :           0 :       int64_t len = 0;
     815                 :           0 :       if (at->int_length(&len))
     816                 :           0 :         this->ss_ << len;
     817                 :             :     }
     818                 :           0 :   this->typeref("] ", at->element_type(), "\n");
     819                 :           0 : }
     820                 :             : 
     821                 :           0 : void Type_dumper::visit_map_type(const Map_type* mt)
     822                 :             : {
     823                 :           0 :   this->ss_ << "map [";
     824                 :           0 :   this->typeref(NULL, mt->key_type(), NULL);
     825                 :           0 :   this->typeref("] ", mt->val_type(), "\n");
     826                 :           0 : }
     827                 :             : 
     828                 :           0 : void Type_dumper::visit_methods(const Typed_identifier_list* methods,
     829                 :             :                                 const char *tag)
     830                 :             : {
     831                 :           0 :   if (tag != NULL)
     832                 :             :     {
     833                 :           0 :       this->emitpre(notag, NULL);
     834                 :           0 :       this->ss_ << tag << "\n";
     835                 :             :     }
     836                 :           0 :   for (Typed_identifier_list::const_iterator p = methods->begin();
     837                 :           0 :        p != methods->end();
     838                 :           0 :        ++p)
     839                 :             :     {
     840                 :           0 :       this->emitpre(notag, NULL);
     841                 :           0 :       if (p->name().empty())
     842                 :           0 :         this->typeref("  embedded method ", p->type(), "\n");
     843                 :             :       else
     844                 :             :         {
     845                 :           0 :           this->ss_ << "  method '" << p->name() << "' ";
     846                 :           0 :           this->typeref(NULL, p->type(), "\n");
     847                 :             :         }
     848                 :             :     }
     849                 :           0 : }
     850                 :             : 
     851                 :           0 : void Type_dumper::visit_interface_type(const Interface_type* it)
     852                 :             : {
     853                 :           0 :   const Typed_identifier_list* methods =
     854                 :           0 :       (it->methods_are_finalized() ? it->methods() : it->local_methods());
     855                 :           0 :   if (methods == NULL)
     856                 :             :     {
     857                 :           0 :       this->ss_ << "empty_interface\n";
     858                 :           0 :       return;
     859                 :             :     }
     860                 :           0 :   this->ss_ << "interface";
     861                 :           0 :   if (! it->methods_are_finalized())
     862                 :             :     {
     863                 :           0 :       this->ss_ << " [unfinalized]\n";
     864                 :           0 :       visit_methods(it->local_methods(), NULL);
     865                 :             :     }
     866                 :             :   else
     867                 :             :     {
     868                 :           0 :       this->ss_ << "\n";
     869                 :           0 :       visit_methods(it->local_methods(), "[parse_methods]");
     870                 :           0 :       visit_methods(it->methods(), "[all_methods]");
     871                 :             :     }
     872                 :             : }
     873                 :             : 
     874                 :           0 : void Type_dumper::visit_channel_type(const Channel_type* ct)
     875                 :             : {
     876                 :           0 :   this->ss_ << "channel {";
     877                 :           0 :   if (ct->may_send())
     878                 :           0 :     this->ss_ << " send";
     879                 :           0 :   if (ct->may_receive())
     880                 :           0 :     this->ss_ << " receive";
     881                 :           0 :   this->typeref(" } ", ct->element_type(), "\n");
     882                 :           0 : }
     883                 :             : 
     884                 :           0 : void Type_dumper::visit()
     885                 :             : {
     886                 :           0 :   while (! this->worklist_.empty()) {
     887                 :           0 :     const Type* t = this->worklist_.front();
     888                 :           0 :     this->worklist_.pop_front();
     889                 :             : 
     890                 :           0 :     std::pair<bool, unsigned> p = this->lookup(t);
     891                 :           0 :     unsigned tag = p.second;
     892                 :           0 :     this->emitpre(tag, t);
     893                 :             : 
     894                 :           0 :     switch(t->classification())
     895                 :             :       {
     896                 :           0 :         case Type::TYPE_ERROR:
     897                 :           0 :         case Type::TYPE_INTEGER:
     898                 :           0 :         case Type::TYPE_FLOAT:
     899                 :           0 :         case Type::TYPE_COMPLEX:
     900                 :           0 :         case Type::TYPE_BOOLEAN:
     901                 :           0 :         case Type::TYPE_STRING:
     902                 :           0 :         case Type::TYPE_VOID:
     903                 :           0 :         case Type::TYPE_POINTER:
     904                 :           0 :         case Type::TYPE_NIL:
     905                 :           0 :         case Type::TYPE_NAMED:
     906                 :           0 :           this->typeref(NULL, t, "\n");
     907                 :           0 :           break;
     908                 :           0 :         case Type::TYPE_FORWARD:
     909                 :           0 :           this->visit_forward_declaration_type(t->forward_declaration_type());
     910                 :           0 :           break;
     911                 :             : 
     912                 :           0 :         case Type::TYPE_FUNCTION:
     913                 :           0 :           this->visit_function_type(t->function_type());
     914                 :           0 :           break;
     915                 :           0 :         case Type::TYPE_STRUCT:
     916                 :           0 :           this->visit_struct_type(t->struct_type());
     917                 :           0 :           break;
     918                 :           0 :         case Type::TYPE_ARRAY:
     919                 :           0 :           this->visit_array_type(t->array_type());
     920                 :           0 :           break;
     921                 :           0 :         case Type::TYPE_MAP:
     922                 :           0 :           this->visit_map_type(t->map_type());
     923                 :           0 :           break;
     924                 :           0 :         case Type::TYPE_CHANNEL:
     925                 :           0 :           this->visit_channel_type(t->channel_type());
     926                 :           0 :           break;
     927                 :           0 :         case Type::TYPE_INTERFACE:
     928                 :           0 :           this->visit_interface_type(t->interface_type());
     929                 :           0 :           break;
     930                 :           0 :         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                 :           0 :           this->ss_ << "<unknown/unrecognized classification "
     935                 :           0 :                     << ((unsigned)t->classification()) << ">\n";
     936                 :             :       }
     937                 :             :   }
     938                 :           0 : }
     939                 :             : 
     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.
     943                 :             : 
     944                 :           0 : void debug_go_type(const Type* type)
     945                 :             : {
     946                 :           0 :   if (type == NULL)
     947                 :             :     {
     948                 :           0 :       std::cerr << "<NULL type>\n";
     949                 :           0 :       return;
     950                 :             :     }
     951                 :           0 :   Type_dumper dumper(type);
     952                 :           0 :   dumper.visit();
     953                 :           0 :   std::cerr << dumper.stringResult();
     954                 :           0 : }
     955                 :             : 
     956                 :           0 : void debug_go_type(Type* type)
     957                 :             : {
     958                 :           0 :   const Type* ctype = type;
     959                 :           0 :   debug_go_type(ctype);
     960                 :           0 : }
        

Generated by: LCOV version 2.1-beta

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,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.