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; }