Example #1
0
SgSourceFile*
FortranModuleInfo::createSgSourceFile(string modName)
   {
     int errorCode = 0;
     vector<string> argv;

  // DQ (11/12/2008): Modified to force filename to lower case.
#if 0
     printf ("In FortranModuleInfo::createSgSourceFile(): generating a module file %s using module name = %s \n",StringUtility::convertToLowerCase(modName).c_str(),modName.c_str());
#endif
  // modName = StringUtility::convertToLowerCase(modName);

  // current directory
     string rmodFileName = modName + MOD_FILE_SUFFIX;

#if 0
     printf ("In FortranModuleInfo::createSgSourceFile(): Searching for file rmodFileName = %s \n",rmodFileName.c_str());
     printf ("In FortranModuleInfo::createSgSourceFile(): boost::filesystem::exists(rmodFileName.c_str()) = %s \n",boost::filesystem::exists(rmodFileName.c_str()) ? "true" : "false");
#endif

     if (boost::filesystem::exists(rmodFileName.c_str()) == false)
        {
          printf ("File rmodFileName = %s NOT FOUND (expected to be present) \n",rmodFileName.c_str());
          return NULL;
        }

     argv.push_back(SKIP_SYNTAX_CHECK);
     argv.push_back(rmodFileName);

     nestedSgFile++;

     if (SgProject::get_verbose() > 1)
          printf ("START FortranModuleInfo::createSgSourceFile(%s): nestedSgFile = %d \n",rmodFileName.c_str(),nestedSgFile);

     SgProject*  project = getCurrentProject();

     SgSourceFile* newFile = isSgSourceFile(determineFileType(argv,errorCode,project));
  // SgSourceFile* newFile =  new SgSourceFile (argv, errorCode, 0, project);
     ROSE_ASSERT(newFile != NULL);

#if 0
     printf ("In FortranModuleInfo::createSgSourceFile(): Calling the fronend explicitly! \n");
#endif

   // DQ (6/13/2013): Since we seperated the construction of the SgFile IR nodes from the invocation of the frontend, we have to call the frontend explicitly.
     newFile->runFrontend(errorCode);

  // DQ (6/13/2013): At least report that the error code is not checked, this is just something that I noticed but don't want to modify just now.
  // I guess that the point is that it should compile since the module compiled previously, but it should still be enforced to be zero.
     if (errorCode != 0)
        {
          printf ("In FortranModuleInfo::createSgSourceFile(): errorCode != 0 is not checked \n");
          ROSE_ASSERT(errorCode == 0);
        }

     ROSE_ASSERT (newFile != NULL);
     ROSE_ASSERT (newFile->get_startOfConstruct() != NULL);

  // Set the project as the  parent 
     newFile->set_parent(project);

  // DQ (11/12/2008): This rmod file should be explicitly marked to not be compiled.
  // printf ("Marking the new module file to not be compiled \n");
     newFile->set_skipfinalCompileStep(true);
     newFile->set_skip_unparse(true);

     project->set_file(*newFile);

     if (SgProject::get_verbose() > 1)
          printf ("END FortranModuleInfo::createSgSourceFile(%s): nestedSgFile = %d \n",rmodFileName.c_str(),nestedSgFile);

     nestedSgFile--;

     return newFile;
   }
int
main ( int argc, char * argv[] )
   {
  // DQ (2/26/2010): Use the last name as the output file name for the generated AST (written back out).
     ROSE_ASSERT(argc > 1);
     if (argc <= 1)
        {
          printf ("Error: This AST file reader requires the name of a binary AST file AND the output filename for the merged binary AST file. \n");
          ROSE_ASSERT(false);
        }

#if 0
  // DQ (2/23/2010): This can't be called since it will generate a SgFunctionTypeTable and the memory pools must be empty.
     printf ("Before reading AST files: SgNode::get_globalFunctionTypeTable() = %p \n",SgNode::get_globalFunctionTypeTable());
  // ROSE_ASSERT(isSgFunctionTypeTable(SgNode::get_globalFunctionTypeTable()) != NULL);
#endif

  // Internal debugging support (e.g. new and delete operators).
  // ROSE_DEBUG = 2;

     int numFiles = argc - 2;
     vector<std::string> fileNames;
     for (int i= 0; i < numFiles; ++i)
        {
       // Detect options starting with "-"; not allowed.
          if (argv[i+1][0] == '-')
             {
               printf ("Skipping %s \n",argv[i+1]);

               printf ("Error can't handle common ROSE options on command line! \n");
               ROSE_ASSERT(false);
             }

          fileNames.push_back(argv[i+1]);
        }

     string outputFileName = argv[argc-1];
     printf ("Number of file = %zu Output filename = %s \n",fileNames.size(),outputFileName.c_str());

  // Reset numFiles to only count valid input files.
  // numFiles = fileNames.size();

#if 0
     printf ("Exiting after test of output name specification. \n");
     ROSE_ASSERT(false);
#endif

#if 0
     cout << "################ In astFileRead.C ############## " << endl;
     cout << "#  Going to read " << numFiles << " files  " << endl;
     cout << "################################################ " << endl;
#endif

  // We should be built into a data structure to hold this sepeaate file by file AST information.
  // Static data structures in ROSE that require special handling when reading more than one AST from a file.
     vector<SgFunctionTypeTable*> functionTableArray;
  // vector<map<int, std::string> > fileidtoname_mapArray;
  // vector<map<std::string, int> > nametofileid_mapArray;

  // This uses the new data structure to hold all the required information for each 
  // AST file so that we can do a merge of the static information of the AST.
     vector<AstFileSpecificInfo*> AstFileInfoArray;

     size_t currentNumberOfNodes  = 0;
     size_t previousNumberOfNodes = 0;

  // DQ (6/5/2010): Trigger debugging output!
  // ROSE_DEBUG = 2;
  // SgProject::set_verbose(3);

  // cout  << endl << "Here we call the AST_FILE_IO :: readASTFromFile ..." << endl;
     SgProject* tmp_previous_globalProject = NULL;
     for (int i= 0; i < numFiles; ++i)
        {
       // cout  << "Here we will read .... " << fileNames[i] << endl;
          AST_FILE_IO :: readASTFromFile ( fileNames[i] + ".binary" );
       // cout  << "Here we just read .... " << fileNames[i] << endl;

          AstData* tmp_ast = AST_FILE_IO::getAst(i);
          SgProject* tmp_globalProject = tmp_ast->getRootOfAst();
          ROSE_ASSERT(tmp_globalProject->get_freepointer() == AST_FileIO::IS_VALID_POINTER());
          if (tmp_previous_globalProject != NULL)
             {
               ROSE_ASSERT(tmp_previous_globalProject->get_freepointer() == AST_FileIO::IS_VALID_POINTER());
             }
          tmp_previous_globalProject = tmp_globalProject;
          

          currentNumberOfNodes = Sg_File_Info::numberOfNodes();

       // printf ("SgProject* tmp_globalProject = %p \n",tmp_globalProject);
          printf ("file #%5d = %20s AST size = %12zu IR nodes  memory usage = %12zu bytes  Sg_File_Info::numberOfNodes() = %12zu \n",i,fileNames[i].c_str(),numberOfNodes(),memoryUsage(),currentNumberOfNodes);

       // TestFreepointerInMemoryPool::test();

#if 0
       // DQ (2/24/2010): This is a significant bottleneck to the performance on large codes since it is n^2 in the size of the AST.
          AstTests::runAllTests(ast->getRootOfAst());
#endif
#if 0
          printf ("In loop reading AST files: SgNode::get_globalFunctionTypeTable() = %p \n",SgNode::get_globalFunctionTypeTable());
          printf ("file #%d AST Sg_File_Info::numberOfNodes() = %d \n",i,currentNumberOfNodes);
#endif
       // Some of this information has to be setup after we call AST_FILE_IO::setStaticDataOfAst() for each AST.
       // AstFileSpecificInfo* astFileSpecificInformation = new AstFileSpecificInfo(SgNode::get_globalFunctionTypeTable(),previousNumberOfNodes,currentNumberOfNodes,Sg_File_Info::get_fileidtoname_map(),Sg_File_Info::get_nametofileid_map());
          AstFileSpecificInfo* astFileSpecificInformation = new AstFileSpecificInfo(previousNumberOfNodes,currentNumberOfNodes-1);
          ROSE_ASSERT(astFileSpecificInformation != NULL);  
          AstFileInfoArray.push_back(astFileSpecificInformation);

       // Track the positions of the base and bound of the Sg_File_Info list in the memory pool.
          previousNumberOfNodes = currentNumberOfNodes;

       // printf ("At base of loop over the input files... i = %d \n",i);
        }
#if 1
     cout  << endl << "AST_FILE_IO :: readASTFromFile done ... " << endl;
#endif

  // SgFunctionTypeTable* globalFunctionTypeTable = NULL;
     SgProject*           globalProject                 = NULL;

     ROSE_ASSERT(AstFileInfoArray.size() == (size_t)numFiles);

  // DQ (6/5/2010): Trigger debugging output!
  // ROSE_DEBUG = 2;

     AstData* ast = NULL;
     for (int i= 0; i < numFiles; ++i)
        {
#if 0
          printf ("Processing file #%d \n",i);
#endif
          ast = AST_FILE_IO::getAst(i);
#if 0
       // DQ (6/6/2010): Turned off to limit output in debugging...
       // DQ (6/5/2010): Unclear if I can use this test here!
          printf ("Running AstTests::runAllTests() BEFORE calling AST_FILE_IO::setStaticDataOfAst(ast)\n");
          AstTests::runAllTests(ast->getRootOfAst());
          printf ("DONE: Running AstTests::runAllTests() BEFORE calling AST_FILE_IO::setStaticDataOfAst(ast)\n");
#endif

       // This sets static data to be consistant within each AST, but not across the single merged AST (from multiple files).
          AST_FILE_IO::setStaticDataOfAst(ast);

       // TestFreepointerInMemoryPool::test();

#if 0
          printf ("In loop reading AST files: SgNode::get_globalFunctionTypeTable() = %p \n",SgNode::get_globalFunctionTypeTable());
          printf ("In loop reading AST files: Sg_File_Info::get_fileidtoname_map() = %p size() = %zu \n",&Sg_File_Info::get_fileidtoname_map(),Sg_File_Info::get_fileidtoname_map().size());
          printf ("In loop reading AST files: Sg_File_Info::get_nametofileid_map() = %p size() = %zu \n",&Sg_File_Info::get_nametofileid_map(),Sg_File_Info::get_nametofileid_map().size());
          printf ("Sg_File_Info::numberOfNodes() = %d \n",Sg_File_Info::numberOfNodes());
#endif
          ROSE_ASSERT(Sg_File_Info::get_fileidtoname_map().size() == Sg_File_Info::get_nametofileid_map().size());

       // We need to make a second call to fixup the information in the AstFileSpecificInfo objects once we have called AST_FILE_IO::setStaticDataOfAst() for each AST.
          AstFileInfoArray[i]->fixupAstFileSpecificInfo(SgNode::get_globalFunctionTypeTable(),Sg_File_Info::get_fileidtoname_map(),Sg_File_Info::get_nametofileid_map());

       // printf ("DONE with call to AstFileInfoArray[%d]->fixupAstFileSpecificInfo() \n",i);

       // Save references to all the function type tables.
          functionTableArray.push_back(SgNode::get_globalFunctionTypeTable());

       // Save copies of all the filename maps (copies because they are not implemented via a static pointer).
       // fileidtoname_mapArray.push_back(Sg_File_Info::get_fileidtoname_map());
       // nametofileid_mapArray.push_back(Sg_File_Info::get_nametofileid_map());

       // testAST(ast->getRootOfAst());


       // DQ (6/21/2010): Fixup the support for builtin types stored as static data in the SgType derived classes.
       // FixupbuiltinTypes(AST_FILE_IO::getAst(i),AST_FILE_IO::getAst(i));
       // printf ("In loop reading AST files: SgTypeUnsignedInt::p_builtin_type = %p \n",SgTypeUnsignedInt::createType());

#if 0
       // TestFreepointerInMemoryPool::test();

          printf ("Call to AstTests::runAllTests() ast->getRootOfAst() = %p = %s \n",ast->getRootOfAst(),ast->getRootOfAst()->class_name().c_str());
          SgProject* temp_project = ast->getRootOfAst();
       // ROSE_ASSERT(temp_project->numberOfFiles() == 1);
          ROSE_ASSERT(temp_project->numberOfDirectories() == 0);
          SgFile* temp_file = (*temp_project)[0];
          printf ("temp_file->get_filename() = %s \n",temp_file->getFileName().c_str());

       // DQ (6/5/2010): Turn on to support debugging...
       // DQ (2/24/2010): This is a significant bottleneck to the performance on large codes since it is n^2 in the size of the AST.
       // AstTests::runAllTests(ast->getRootOfAst());

          printf ("DONE with call to AstTests::runAllTests() \n");
#endif
#if 0
       // To read and merge the separate AST files, we don't have to call the backend.
          backend(ast->getRootOfAst());
#endif

       // printf ("globalProject = %p \n",globalProject);

          if (globalProject == NULL)
             {
               globalProject = ast->getRootOfAst();
               ROSE_ASSERT(globalProject->get_freepointer() == AST_FileIO::IS_VALID_POINTER());
             }
            else
             {
               SgProject* localProject = ast->getRootOfAst();
               SgFile*    localFile    = (*localProject)[0];

            // DQ (3/1/2010): Merged files that are reread will have more than one SgFile object.
            // ROSE_ASSERT(localProject->numberOfFiles() == 1);

            // Add the file to the global project. This also sets the parent of the input file. Is this a side-effect that we want?
               globalProject->set_file(*localFile);
#if 0
               printf ("globalProject = %p numberOfFiles() = %d \n",globalProject,globalProject->numberOfFiles());
#endif
               ROSE_ASSERT(globalProject->get_freepointer() == AST_FileIO::IS_VALID_POINTER());
//             delete localProject;
             }
        }

     printf ("Size of AST = %zu (globalProject = %p)\n",numberOfNodes(),globalProject);

#if 0
     for (int i= 0; i < numFiles; ++i)
        {
          AstFileInfoArray[i]->display("static AST file information");
        }
#endif

#if 0
  // DQ (3/7/2010): It may be that we have to process the merged static data before we can expect 
  // to pass this test.
  // DQ (2/24/2010): Better to run this once at the end to avoid a significant bottleneck to the 
  // performance on large codes (it is n^2 in the size of the AST if run for each file separately).
     //AstTests::runAllTests(ast->getRootOfAst());
#endif

  // Merge the function tables from each AST.
  // SgFunctionTypeTable* globalFunctionTypeTable = mergeFunctionTypeSymbolTables (functionTableArray);
  // ROSE_ASSERT(globalFunctionTypeTable != NULL);

  // It is required to merge the static information in the AST, to get a valid AST, even if no other merging is done.
     printf ("\n\nCalling mergeStaticASTFileInformation() \n");
     mergeStaticASTFileInformation(AstFileInfoArray);
     printf ("Size of AST (after merge of static data) = %zu \n",numberOfNodes());

  // DQ (7/10/2010): This is now called from within the AST merge mechanism.
  // printf ("Normalize the SgTypedefSeq IR nodes to be consistant across the union of ASTs. \n");
  // normalizeTypedefSequenceLists();
  // printf ("DONE: Normalize the SgTypedefSeq IR nodes to be consistant across the union of ASTs. \n");

#if 1
  // DQ (6/7/2010): Now call the AST merge that will detect redundant (or repeated) parts 
  // of the AST and force sharing of these pieces and delete the redundany copies.
     printf ("\n\nCalling AstMergeSupport() \n");
  // int mergeErrorCode = AstMergeSupport(globalProject);
  // bool skipFrontendSpecificIRnodes = true;
  // SgProject::set_verbose(3);
     bool skipFrontendSpecificIRnodes = false;
     mergeAST(globalProject,skipFrontendSpecificIRnodes);
  // ROSE_ASSERT(mergeErrorCode == 0);
  // SgProject::set_verbose(0);
#else
     printf ("Skipping call to mergeAST() \n");
#endif

     printf ("Size of AST (after final merge to eliminate redundancy) = %zu \n",numberOfNodes());

#if 1
  // DQ (2/24/2010): Better to run this once at the end to avoid a significant bottleneck to the 
  // performance on large codes (it is n^2 in the size of the AST if run for each file separately).
  // AstTests::runAllTests(ast->getRootOfAst());
     printf ("\n\nRunning AST consistancy tests on merged AST \n");
     AstTests::runAllTests(globalProject);
     printf ("DONE: Running AST consistancy tests on merged AST \n");
#endif

#if 0
  // Output an example of the value of p_freepointer.
     printf ("AST_FILE_IO::areFreepointersContainingGlobalIndices() = %s \n",AST_FILE_IO::areFreepointersContainingGlobalIndices() ? "true" : "false");
     printf ("BEFORE resetValidAstAfterWriting(): globalProject = %p globalProject->get_freepointer() = %p \n",globalProject,globalProject->get_freepointer());
  // AST_FILE_IO :: resetValidAstAfterWriting();
     printf ("AFTER resetValidAstAfterWriting(): globalProject = %p globalProject->get_freepointer() = %p \n",globalProject,globalProject->get_freepointer());

  // Initialization for file I/O.
  // AST_FILE_IO::clearAllMemoryPools();
#endif

  // DQ (6/6/2010): New test that detects fundamental problem. The extention of the memory pools triggered by
  // reading in a second file causes the SgProject IR node from the reading of the first file to be set to
  // the next node to be used (the SgProject for the second file.  It is not reset when reading the 
  // second file's SgProject and so remains.  
  //    1) Why do we have to extend the memory pool? Wouldn't this happen naturally via the new operator?
  //       ANSWER: We need to compute the address of future IR nodes from the global index numbers. So
  //               they all need to be pre-allocated!!!
     ROSE_ASSERT(globalProject->get_freepointer() == AST_FileIO::IS_VALID_POINTER());

  // Custom test of AST (for problems that appears to be specific to writing out the merged AST).
  // testAST(globalProject);

#if 1
  // Output an optional graph of the AST (just the tree, when active). Note that we need to multiple file version 
  // of this with includes so that we can present a single SgProject rooted AST with multiple SgFile objects.
  // generateDOT ( *globalProject );
     printf ("\n\nGenerating a dot file of the AST (could be very large) \n");
     generateDOT_withIncludes ( *globalProject, "aggregatedAST.dot" );
     printf ("DONE: Generating a dot file of the AST \n");
#endif

#if 1
  // Output an optional graph of the AST (the whole graph, of bounded complexity, when active)
     const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 8000;
     generateAstGraph(globalProject,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH);
#endif

#if 1
  // DQ (2/26/2010): Output an example of the value of p_freepointer for debugging.
  // printf ("globalProject->get_freepointer()  = %p \n",globalProject->get_freepointer());
  // printf ("AST_FILE_IO::vectorOfASTs.size() = %zu \n",AST_FILE_IO::vectorOfASTs.size());
  // AST_FILE_IO::display("Before writing the merged AST (before resetValidAstAfterWriting())");
  // string mergedFileName = "mergedFile.C";

     string mergedFileName = outputFileName;
     printf ("mergedFileName = %s numberOfNodes() = %zu \n",(mergedFileName + ".binary").c_str(),numberOfNodes());

     printf ("Calling AST_FILE_IO::reset() \n");
     AST_FILE_IO::reset();

  // printf ("Calling AST_FILE_IO::resetValidAstAfterWriting() \n");
  // AST_FILE_IO::resetValidAstAfterWriting();
  // AST_FILE_IO::display("Before writing the merged AST");

  // Now write out the merged AST.
     printf ("Calling AST_FILE_IO::startUp()... \n");
     AST_FILE_IO::startUp(globalProject);

     printf ("Writing the AST to disk... \n");
     AST_FILE_IO::writeASTToFile ( mergedFileName + ".binary" );
#endif

  // printf ("Before processing via DOT: globalProject = %p numberOfFiles() = %d \n",globalProject,globalProject->numberOfFiles());

#if 0
  // Output an optional graph of the AST (just the tree, when active). Note that we need to multiple file version 
  // of this with includes so that we can present a single SgProject rooted AST with multiple SgFile objects.
  // generateDOT ( *globalProject );
     generateDOT_withIncludes ( *globalProject, "aggregatedAST.dot" );
#endif

#if 0
  // Output an optional graph of the AST (the whole graph, of bounded complexity, when active)
     const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 8000;
     generateAstGraph(globalProject,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH);
#endif

     printf ("Program Terminated Normally! \n");

     return 0;
   }