void postProcessingSupport (SgNode* node) { // DQ (5/24/2006): Added this test to figue out where Symbol parent pointers are being reset to NULL // TestParentPointersOfSymbols::test(); // DQ (7/25/2005): It is presently an error to call this function with a SgProject // or SgDirectory, since there is no way to compute the SgFile from such IR nodes // (could be multiply defined). // ROSE_ASSERT(isSgProject(node) == NULL && isSgDirectory(node) == NULL); // GB (8/19/2009): Removed the assertion against calling this function on // SgProject and SgDirectory nodes. Nothing below needs to compute a // SgFile, as far as I can tell; also, calling the AstPostProcessing just // once on an entire project is more efficient than calling it once per // file. // JJW (12/5/2008): Turn off C and C++ postprocessing steps when the new EDG // interface is being used (it should produce correct, complete ASTs on its // own and do its own fixups) #ifdef ROSE_USE_NEW_EDG_INTERFACE // Only do AST post-processing for C/C++ bool doPostprocessing = (SageInterface::is_Fortran_language() == true) || (SageInterface::is_PHP_language() == true) || (SageInterface::is_Python_language() == true); // If this is C or C++ then we are using the new EDG translation and althrough fewer // fixups should be required, some are still required. if (doPostprocessing == false) { #ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION printf ("Postprocessing AST build using new EDG/Sage Translation Interface. \n"); #endif #if 0 // DQ (4/26/2013): Debugging code. printf ("In postProcessingSupport: Test 1: Calling postProcessingTestFunctionCallArguments() \n"); postProcessingTestFunctionCallArguments(node); #endif #ifndef ROSE_USE_CLANG_FRONTEND // DQ (10/31/2012): Added fixup for EDG bug which drops variable declarations of some source sequence lists. fixupEdgBugDuplicateVariablesInAST(); #endif // DQ (5/1/2012): After EDG/ROSE translation, there should be no IR nodes marked as transformations. // Liao 11/21/2012. AstPostProcessing() is called within both Frontend and Midend // so we have to detect the mode first before asserting no transformation generated file info objects if (SageBuilder::SourcePositionClassificationMode != SageBuilder::e_sourcePositionTransformation) detectTransformations(node); // DQ (8/12/2012): reset all of the type references (to intermediately generated types). fixupTypeReferences(); // Reset and test and parent pointers so that it matches our definition // of the AST (as defined by the AST traversal mechanism). topLevelResetParentPointer(node); // DQ (8/23/2012): Modified to take a SgNode so that we could compute the global scope for use in setting // parents of template instantiations that have not be placed into the AST but exist in the memory pool. // Another 2nd step to make sure that parents of even IR nodes not traversed can be set properly. // resetParentPointersInMemoryPool(); resetParentPointersInMemoryPool(node); // DQ (6/27/2005): fixup the defining and non-defining declarations referenced at each SgDeclarationStatement // This is a more sophisticated fixup than that done by fixupDeclarations. See test2009_09.C for an example // of a non-defining declaration appearing before a defining declaration and requiring a fixup of the // non-defining declaration reference to the defining declaration. fixupAstDefiningAndNondefiningDeclarations(node); // DQ (6/11/2013): This corrects where EDG can set the scope of a friend declaration to be different from the defining declaration. // We need it to be a rule in ROSE that the scope of the declarations are consistant between defining and all non-defining declaration). fixupAstDeclarationScope(node); // Fixup the symbol tables (in each scope) and the global function type // symbol table. This is less important for C, but required for C++. // But since the new EDG interface has to handle C and C++ we don't // setup the global function type table there to be uniform. fixupAstSymbolTables(node); // DQ (4/14/2010): Added support for symbol aliases for C++ // This is the support for C++ "using declarations" which uses symbol aliases in the symbol table to provide // correct visability of symbols included from alternative scopes (e.g. namespaces). fixupAstSymbolTablesToSupportAliasedSymbols(node); // DQ (2/12/2012): Added support for this, since AST_consistancy expects get_nameResetFromMangledForm() == true. resetTemplateNames(node); // ********************************************************************** // DQ (4/29/2012): Added some of the template fixup support for EDG 4.3 work. // DQ (6/21/2005): This function now only marks the subtrees of all appropriate declarations as compiler generated. // DQ (5/27/2005): mark all template instantiations (which we generate as template specializations) as compiler generated. // This is required to make them pass the unparser and the phase where comments are attached. Some fixup of filenames // and line numbers might also be required. fixupTemplateInstantiations(node); #if 0 // DQ (4/26/2013): Debugging code. printf ("In postProcessingSupport: Test 2: Calling postProcessingTestFunctionCallArguments() \n"); postProcessingTestFunctionCallArguments(node); #endif // DQ (8/19/2005): Mark any template specialization (C++ specializations are template instantiations // that are explicit in the source code). Such template specializations are marked for output only // if they are present in the source file. This detail could effect handling of header files later on. // Have this phase preceed the markTemplateInstantiationsForOutput() since all specializations should // be searched for uses of (references to) instantiated template functions and member functions. markTemplateSpecializationsForOutput(node); // DQ (6/21/2005): This function marks template declarations for output by the unparser (it is part of a // fixed point iteration over the AST to force find all templates that are required (EDG at the moment // outputs only though template functions that are required, but this function solves the more general // problem of instantiation of both function and member function templates (and static data, later)). markTemplateInstantiationsForOutput(node); // DQ (10/21/2007): Friend template functions were previously not properly marked which caused their generated template // symbols to be added to the wrong symbol tables. This is a cause of numerous symbol table problems. fixupFriendTemplateDeclarations(); // DQ (4/29/2012): End of new template fixup support for EDG 4.3 work. // ********************************************************************** // DQ (5/14/2012): Fixup source code position information for the end of functions to match the largest values in their subtree. // DQ (10/27/2007): Setup any endOfConstruct Sg_File_Info objects (report on where they occur) fixupSourcePositionConstructs(); #if 0 // DQ (4/26/2013): Debugging code. printf ("In postProcessingSupport: Test 3: Calling postProcessingTestFunctionCallArguments() \n"); postProcessingTestFunctionCallArguments(node); #endif // DQ (2/12/2012): This is a problem for test2004_35.C (debugging this issue). // printf ("Exiting after calling resetTemplateNames() \n"); // ROSE_ASSERT(false); // DQ (10/4/2012): Added this pass to support command line option to control use of constant folding // (fixes bug pointed out by Liao). // DQ (9/14/2011): Process the AST to remove constant folded values held in the expression trees. // This step defines a consistent AST more suitable for analysis since only the constant folded // values will be visited. However, the default should be to save the original expression trees // and remove the constant folded values since this represents the original code. #if 1 resetConstantFoldedValues(node); #else // DQ (10/11/2012): This is helpful to allow us to see both expression trees in the AST for debugging. printf ("Skipping AST Postprocessing resetConstantFoldedValues() \n"); #endif #if 0 // DQ (4/26/2013): Debugging code. printf ("In postProcessingSupport: Test 4: Calling postProcessingTestFunctionCallArguments() \n"); postProcessingTestFunctionCallArguments(node); #endif // DQ (10/5/2012): Fixup known macros that might expand into a recursive mess in the unparsed code. fixupSelfReferentialMacrosInAST(node); // Make sure that frontend-specific and compiler-generated AST nodes are marked as such. These two must run in this // order since checkIsCompilerGenerated depends on correct values of compiler-generated flags. checkIsFrontendSpecificFlag(node); checkIsCompilerGeneratedFlag(node); // This resets the isModified flag on each IR node so that we can record // where transformations are done in the AST. If any transformations on // the AST are done, even just building it, this step should be the final // step. checkIsModifiedFlag(node); // DQ (5/2/2012): After EDG/ROSE translation, there should be no IR nodes marked as transformations. // Liao 11/21/2012. AstPostProcessing() is called within both Frontend and Midend // so we have to detect the mode first before asserting no transformation generated file info objects if (SageBuilder::SourcePositionClassificationMode !=SageBuilder::e_sourcePositionTransformation) detectTransformations(node); #if 0 // DQ (4/26/2013): Debugging code. printf ("In postProcessingSupport: Test 10: Calling postProcessingTestFunctionCallArguments() \n"); postProcessingTestFunctionCallArguments(node); #endif // DQ (4/24/2013): Detect the correct function declaration to declare the use of default arguments. // This can only be a single function and it can't be any function (this is a moderately complex issue). fixupFunctionDefaultArguments(node); // DQ (12/20/2012): We now store the logical and physical source position information. // Although they are frequently the same, the use of #line directives causes them to be different. // This is part of debugging the physical source position information which is used in the weaving // of the comments and CPP directives into the AST. For this the consistancy check is more helpful // if done befor it is used (here), instead of after the comment and CPP directive insertion in the // AST Consistancy tests. checkPhysicalSourcePosition(node); #ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION printf ("DONE: Postprocessing AST build using new EDG/Sage Translation Interface. \n"); #endif return; } #endif // ROSE_USE_NEW_EDG_INTERFACE -- do postprocessing unconditionally when the old EDG interface is used // DQ (7/7/2005): Introduce tracking of performance of ROSE. // TimingPerformance timer ("AST Fixup: time (sec) = "); if ( SgProject::get_verbose() >= AST_POST_PROCESSING_VERBOSE_LEVEL ) cout << "/* AST Postprocessing started. */" << endl; ROSE_ASSERT(node != NULL); // DQ (7/19/2005): Moved to after parent pointer fixup! // subTemporaryAstFixes(node); // DQ (3/11/2006): Fixup NULL pointers left by users when building the AST // (note that the AST translation fixes these directly). This step is // provided as a way to make the AST build by users consistant with what // is built elsewhere within ROSE. fixupNullPointersInAST(node); // DQ (8/9/2005): Some function definitions in Boost are build without // a body (example in test2005_102.C, but it appears to work fine). fixupFunctionDefinitions(node); // DQ (8/10/2005): correct any template declarations mistakenly marked as compiler-generated fixupTemplateDeclarations(node); // Output progress comments for these relatively expensive operations on the AST if ( SgProject::get_verbose() >= AST_POST_PROCESSING_VERBOSE_LEVEL ) cout << "/* AST Postprocessing reset parent pointers */" << endl; topLevelResetParentPointer (node); // DQ (6/10/2007): This is called later, but call it now to reset the parents in SgTemplateInstantiationDecl // This is required (I think) so that resetTemplateNames() can compute template argument name qualification correctly. // See test2005_28.C for where this is required. // resetParentPointersInMemoryPool(); resetParentPointersInMemoryPool(node); // Output progress comments for these relatively expensive operations on the AST if ( SgProject::get_verbose() >= AST_POST_PROCESSING_VERBOSE_LEVEL ) cout << "/* AST Postprocessing reset parent pointers (done) */" << endl; // DQ (7/19/2005): Moved to after parent pointer fixup! // subTemporaryAstFixes(node); removeInitializedNamePtr(node); // DQ (3/17/2007): This should be empty ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // DQ (12/1/2004): This should be done before the reset of template names (since that operation requires valid scopes!) // DQ (11/29/2004): Added to support new explicit scope information on IR nodes // initializeExplicitScopeData(node); initializeExplicitScopes(node); // DQ (5/28/2006): Fixup names in declarations that are inconsistent (e.g. where more than one non-defining declaration exists) resetNamesInAST(); // DQ (3/17/2007): This should be empty ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // Output progress comments for these relatively expensive operations on the AST if ( SgProject::get_verbose() >= AST_POST_PROCESSING_VERBOSE_LEVEL ) cout << "/* AST Postprocessing reset template names */" << endl; #if 0 // DQ (5/15/2011): I don't feel comfortable with this being called before the AST is finied being post processed. // This used to be called in the unparser, but that is after resetTemplateNames() below and that is a problem // because template names have already been generated. void newBuildHiddenTypeAndDeclarationLists( SgNode* node ); printf ("Developing a new implementation of the name qualification support. \n"); newBuildHiddenTypeAndDeclarationLists(node); printf ("DONE: new name qualification support built. \n"); printf ("Calling SgNode::clearGlobalMangledNameMap() \n"); SgNode::clearGlobalMangledNameMap(); #endif // DQ (5/15/2011): This causes template names to be computed as strings and and without name qualification // if we don't call the name qualification before here. Or we reset the template names after we do the // analysis to support the name qualification. // reset the names of template class declarations resetTemplateNames(node); // DQ (2/12/2012): This is a problem for test2004_35.C (debugging this issue). // printf ("Exiting after calling resetTemplateNames() \n"); // ROSE_ASSERT(false); // DQ (3/17/2007): This should be empty ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // Output progress comments for these relatively expensive operations on the AST if ( SgProject::get_verbose() >= AST_POST_PROCESSING_VERBOSE_LEVEL ) cout << "/* AST Postprocessing reset template names (done) */" << endl; // DQ (6/26/2007): Enum values used before they are defined in a class can have NULL declaration pointers. This // fixup handles this case and traverses just the SgEnumVal objects. fixupEnumValues(); // DQ (4/7/2010): This was commented out to modify Fortran code, but I think it should NOT modify Fortran code. // DQ (5/21/2008): This only make since for C and C++ (Error, this DOES apply to Fortran where the "parameter" attribute is used!) if (SageInterface::is_Fortran_language() == false && SageInterface::is_Java_language() == false) { // DQ (3/20/2005): Fixup AST so that GNU g++ compile-able code will be generated fixupInClassDataInitialization(node); } // DQ (3/24/2005): Fixup AST to generate code that works around GNU g++ bugs fixupforGnuBackendCompiler(node); // DQ (4/19/2005): fixup all definingDeclaration and NondefiningDeclaration pointers in SgDeclarationStatement IR nodes // fixupDeclarations(node); // DQ (5/20/2005): make the non-defining (forward) declarations added by EDG for static template // specializations added under the "--instantiation local" option match the defining declarations. fixupStorageAccessOfForwardTemplateDeclarations(node); #if 0 // DQ (6/27/2005): fixup the defining and non-defining declarations referenced at each SgDeclarationStatement fixupAstDefiningAndNondefiningDeclarations(node); #endif // DQ (6/21/2005): This function now only marks the subtrees of all appropriate declarations as compiler generated. // DQ (5/27/2005): mark all template instantiations (which we generate as template specializations) as compiler generated. // This is required to make them pass the unparser and the phase where comments are attached. Some fixup of filenames // and line numbers might also be required. fixupTemplateInstantiations(node); // DQ (8/19/2005): Mark any template specialization (C++ specializations are template instantiations // that are explicit in the source code). Such template specializations are marked for output only // if they are present in the source file. This detail could effect handling of header files later on. // Have this phase preceed the markTemplateInstantiationsForOutput() since all specializations should // be searched for uses of (references to) instantiated template functions and member functions. markTemplateSpecializationsForOutput(node); // DQ (6/21/2005): This function marks template declarations for output by the unparser (it is part of a // fixed point iteration over the AST to force find all templates that are required (EDG at the moment // outputs only though template functions that are required, but this function solves the more general // problem of instantiation of both function and member function templates (and static data, later)). markTemplateInstantiationsForOutput(node); // DQ (3/17/2007): This should be empty ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // DQ (3/16/2006): fixup any newly added declarations (see if we can eliminate the first place where this is called, above) // fixup all definingDeclaration and NondefiningDeclaration pointers in SgDeclarationStatement IR nodes // driscoll6 (6/10/11): this traversal sets p_firstNondefiningDeclaration for defining declarations, which // causes justifiable failures in AstConsistencyTests. Until this is resolved, skip this test for Python. if (SageInterface::is_Python_language()) { //cerr << "warning: python. Skipping fixupDeclarations() in astPostProcessing.C" << endl; } else { fixupDeclarations(node); } // DQ (3/17/2007): This should be empty ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // DQ (2/12/2006): Moved to trail marking templates (as a test) // DQ (6/27/2005): fixup the defining and non-defining declarations referenced at each SgDeclarationStatement // This is a more sophisticated fixup than that done by fixupDeclarations. fixupAstDefiningAndNondefiningDeclarations(node); #if 0 ROSE_ASSERT(saved_declaration != NULL); printf ("saved_declaration = %p saved_declaration->get_definingDeclaration() = %p saved_declaration->get_firstNondefiningDeclaration() = %p \n", saved_declaration,saved_declaration->get_definingDeclaration(),saved_declaration->get_firstNondefiningDeclaration()); ROSE_ASSERT(saved_declaration->get_definingDeclaration() != saved_declaration->get_firstNondefiningDeclaration()); #endif // DQ (10/21/2007): Friend template functions were previously not properly marked which caused their generated template // symbols to be added to the wrong symbol tables. This is a cause of numerous symbol table problems. fixupFriendTemplateDeclarations(); // DQ (3/17/2007): This should be the last point at which the globalMangledNameMap is empty // The fixupAstSymbolTables will generate calls to function types that will be placed into // the globalMangledNameMap. ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // DQ (6/26/2005): The global function type symbol table should be rebuilt (since the names of templates // used in qualified names of types have been reset (in post processing). Other local symbol tables should // be initalized and constructed for any empty scopes (for consistancy, we want all scopes to have a valid // symbol table pointer). fixupAstSymbolTables(node); // DQ (3/17/2007): At this point the globalMangledNameMap has been used in the symbol table construction. OK. // ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // DQ (8/20/2005): Handle backend vendor specific template handling options // (e.g. g++ options: -fno-implicit-templates and -fno-implicit-inline-templates) processTemplateHandlingOptions(node); // DQ (5/22/2005): relocate compiler generated forward template instantiation declarations to appear // after the template declarations and before first use. // relocateCompilerGeneratedTemplateInstantiationDeclarationsInAST(node); // DQ (8/27/2005): This disables output of some template instantiations that would result in // "ambiguous template specialization" in g++ (version 3.3.x, 3.4.x, and 4.x). See test2005_150.C // for more detail. markOverloadedTemplateInstantiations(node); // DQ (9/5/2005): Need to mark all nodes in any subtree marked as a transformation markTransformationsForOutput(node); // DQ (3/5/2006): Mark functions that are provided for backend compatability as compiler generated by ROSE #if 1 markBackendSpecificFunctionsAsCompilerGenerated(node); #else printf ("Warning: Skipped marking of backend specific functions ... \n"); #endif // DQ (5/24/2006): Added this test to figure out where Symbol parent pointers are being reset to NULL // TestParentPointersOfSymbols::test(); // DQ (5/24/2006): reset the remaining parents in IR nodes missed by the AST based traversals // resetParentPointersInMemoryPool(); resetParentPointersInMemoryPool(node); // DQ (3/17/2007): This should be empty // ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // DQ (5/29/2006): Fixup types in declarations that are not shared (e.g. where more than one non-defining declaration exists) resetTypesInAST(); // DQ (3/17/2007): This should be empty // ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // DQ (3/10/2007): fixup name of any template classes that have been copied incorrectly into SgInitializedName // list in base class constructor preinitialization lists (see test2004_156.C for an example). resetContructorInitilizerLists(); // DQ (10/27/2007): Setup any endOfConstruct Sg_File_Info objects (report on where they occur) fixupSourcePositionConstructs(); // DQ (1/19/2008): This can be called at nearly any point in the ast fixup. markLhsValues(node); #ifndef ROSE_USE_CLANG_FRONTEND // DQ (2/21/2010): This normalizes an EDG trick (well documented) that replaces "__PRETTY_FUNCTION__" variable // references with variable given the name of the function where the "__PRETTY_FUNCTION__" variable references // was found. This is only seen when compiling ROSE using ROSE and was a mysterious property of ROSE for a long // time until it was identified. This fixup traversal changes the name back to "__PRETTY_FUNCTION__" to make // the code generated using ROSE when compiling ROSE source code the same as if GNU processed it (e.g. using CPP). if (SageInterface::is_Java_language() == false) { fixupPrettyFunctionVariables(node); } #endif #if 0 // DQ (1/22/2008): Use this for the Fortran code to get more accurate source position information. // DQ (4/16/2007): comment out to test how function declaration prototypes are reset or set wrong. // DQ (11/1/2006): fixup source code position information for AST IR nodes. fixupSourcePositionInformation(node); #endif #if 0 // DQ (11/10/2007): Moved computation of hidden list from astPostProcessing.C to unparseFile so that // it will be called AFTER any transformations and immediately before code generation where it is // really required. This part of a fix for Liao's outliner, but should be useful for numerous // transformations. // DQ (8/6/2007): Only compute the hidden lists if working with C++ code! if (SageInterface::is_Cxx_language() == true) { // DQ (5/22/2007): Moved from SgProject::parse() function to here so that propagateHiddenListData() could be called afterward. // DQ (5/8/2007): Now build the hidden lists for types and declarations (Robert Preissl's work) Hidden_List_Computation::buildHiddenTypeAndDeclarationLists(node); // DQ (6/5/2007): We actually need this now since the hidden lists are not pushed to lower scopes where they are required. // DQ (5/22/2007): Added support for passing hidden list information about types, declarations and elaborated types to child scopes. propagateHiddenListData(node); } #endif // DQ (11/24/2007): Support for Fortran resolution of array vs. function references. if (SageInterface::is_Fortran_language() == true) { // I think this is not used since I can always figure out if something is an // array reference or a function call. fixupFortranReferences(node); // DQ (10/3/2008): This bug in OFP is now fixed so no fixup is required. // This is the most reliable way to introduce the Fortran "contains" statement. // insertFortranContainsStatement(node); } // DQ (9/26/2008): fixup the handling of use declarations (SgUseStatement). // This also will fixup C++ using declarations. fixupFortranUseDeclarations(node); #if 0 ROSE_MemoryUsage memoryUsage1; printf ("Test 1: memory_usage = %f \n",memoryUsage1.getMemoryUsageMegabytes()); #endif // DQ (4/14/2010): Added support for symbol aliases for C++ // This is the support for C++ "using declarations" which uses symbol aliases in the symbol table to provide // correct visability of symbols included from alternative scopes (e.g. namespaces). fixupAstSymbolTablesToSupportAliasedSymbols(node); #if 0 ROSE_MemoryUsage memoryUsage2; printf ("Test 2: memory_usage = %f \n",memoryUsage2.getMemoryUsageMegabytes()); #endif // DQ (6/24/2010): To support merge, we want to normalize the typedef lists for each type so that // the names of the types will evaluate to be the same (and merge appropriately). normalizeTypedefSequenceLists(); #if 0 ROSE_MemoryUsage memoryUsage3; printf ("Test 3: memory_usage = %f \n",memoryUsage3.getMemoryUsageMegabytes()); #endif // DQ (3/7/2010): Identify the fragments of the AST that are disconnected. // Moved from astConsistancy tests (since it deletes nodes not connected to the AST). // TestForDisconnectedAST::test(node); // DQ (9/14/2011): Process the AST to remove constant folded values held in the expression trees. // This step defines a consistant AST more suitable for analysis since only the constant folded // values will be visited. However, the default should be to save the original expression trees // and remove the constant folded values since this represents the original code. This mechanism // will provide a default when it is more fully implemented. resetConstantFoldedValues(node); // Make sure that compiler-generated AST nodes are marked for Sg_File_Info::isCompilerGenerated(). checkIsCompilerGeneratedFlag(node); // DQ (5/22/2005): Nearly all AST fixup should be done before this closing step // QY: check the isModified flag // CheckIsModifiedFlagSupport(node); checkIsModifiedFlag(node); #if 0 ROSE_MemoryUsage memoryUsage4; printf ("Test 4: memory_usage = %f \n",memoryUsage4.getMemoryUsageMegabytes()); #endif // ROSE_ASSERT(saved_declaration->get_definingDeclaration() != saved_declaration->get_firstNondefiningDeclaration()); // DQ (3/17/2007): This should be empty // ROSE_ASSERT(SgNode::get_globalMangledNameMap().size() == 0); // This is used for both of the fillowing tests. SgSourceFile* sourceFile = isSgSourceFile(node); #if 1 // DQ (9/11/2009): Added support for numbering of statements required to support name qualification. if (sourceFile != NULL) { // DQ (9/11/2009): Added support for numbering of statements required to support name qualification. // sourceFile->buildStatementNumbering(); SgGlobal* globalScope = sourceFile->get_globalScope(); ROSE_ASSERT(globalScope != NULL); globalScope->buildStatementNumbering(); } else { if (SgProject* project = isSgProject(node)) { SgFilePtrList &files = project->get_fileList(); for (SgFilePtrList::iterator fileI = files.begin(); fileI != files.end(); ++fileI) { if ( (sourceFile = isSgSourceFile(*fileI)) ) { SgGlobal* globalScope = sourceFile->get_globalScope(); ROSE_ASSERT(globalScope != NULL); globalScope->buildStatementNumbering(); } } } } #endif // DQ (4/4/2010): check that the global scope has statements. // This was an error for Fortran and it appeared that everything // was working when it was not. It appeared because of a strange // error between versions of the OFP support files. So as a // way to avoid this in the future, we issue a warning for Fortran // code that has no statements in the global scope. It can still // be a valid Fortran code (containing only comments). but this // should help avoid our test codes appearing to work when they // don't (in the future). For C/C++ files there should always be // something in the global scope (because or ROSE defined functions), // so this test should not be a problem. if (sourceFile != NULL) { SgGlobal* globalScope = sourceFile->get_globalScope(); ROSE_ASSERT(globalScope != NULL); if (globalScope->get_declarations().empty() == true) { printf ("WARNING: no statements in global scope for file = %s \n",sourceFile->getFileName().c_str()); } } else { if (SgProject* project = isSgProject(node)) { SgFilePtrList &files = project->get_fileList(); for (SgFilePtrList::iterator fileI = files.begin(); fileI != files.end(); ++fileI) { if ( (sourceFile = isSgSourceFile(*fileI)) ) { SgGlobal* globalScope = sourceFile->get_globalScope(); ROSE_ASSERT(globalScope != NULL); if (globalScope->get_declarations().empty() == true) { printf ("WARNING: no statements in global scope for file = %s \n",(*fileI)->getFileName().c_str()); } } } } } if ( SgProject::get_verbose() >= AST_POST_PROCESSING_VERBOSE_LEVEL ) cout << "/* AST Postprocessing finished */" << endl; // DQ (5/3/2010): Added support for binary analysis specific post-processing. SgProject* project = isSgProject(node); if (project != NULL) { #if 0 // printf ("In postProcessingSupport(): project->get_exit_after_parser() = %s \n",project->get_exit_after_parser() ? "true" : "false"); // printf ("In postProcessingSupport(): project->get_binary_only() = %s \n",project->get_binary_only() ? "true" : "false"); if (project->get_binary_only() == true) { printf ("Inside of postProcessingSupport(): Processing binary project \n"); // ROSE_ASSERT(false); // addEdgesInAST(); } #endif } }
int main( int argc, char *argv[] ) { if( argc < 2 ) { cout << "./amos: no input files " << endl; cout << " " << endl; cout << "Hi, this is Amos! " << endl; cout << "It's my pleasure to serve you. " << endl; cout << " " << endl; cout << "Please type option '--help' to see guide " << endl; cout << " " << endl; return 0; } cout << "*************************************************************" << endl; cout << "** **" << endl; cout << "** Welcome to use OpenMP task validation system! **" << endl; cout << "** **" << endl; cout << "** editor: Amos Wang **" << endl; cout << "*************************************************************\n" << endl; vector<string> argvList( argv, argv+argc ); vector<string> argvList0( argv, argv+argc ); // keep original argv and argc command_processing( argvList ); if( !parse_OmpTask( argvList ) ) { cout << "\nAmos says: I am sorry that I could not find any OpenMP task !" << endl << endl; return 0; } // for time counter long t_start; long t_end; double time_program = 0.0; t_start = usecs(); // for time counter transform_Task2Loop( argvList ); SgProject *project = frontend(argvList); ROSE_ASSERT( project != NULL ); #if 1 VariantVector vv( V_SgForStatement ); Rose_STL_Container<SgNode*> loops = NodeQuery::queryMemoryPool(vv); for( Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgForStatement* cur_loop = isSgForStatement(*iter); ROSE_ASSERT(cur_loop); SageInterface::normalizeForLoopInitDeclaration(cur_loop); } #endif //initialize_analysis( project, false ); initialize_analysis( project, false ); //For each source file in the project SgFilePtrList &ptr_list = project->get_fileList(); cout << "\n**** Amos' validation system running ****\n" << endl; for( SgFilePtrList::iterator iter = ptr_list.begin(); iter != ptr_list.end(); iter++ ) { cout << "temp source code: " << (*iter)->get_file_info()->get_filename() << endl << endl; SgFile *sageFile = (*iter); SgSourceFile *sfile = isSgSourceFile(sageFile); ROSE_ASSERT(sfile); SgGlobal *root = sfile->get_globalScope(); SgDeclarationStatementPtrList& declList = root->get_declarations (); //cout << "Check point 2" << endl; //For each function body in the scope for( SgDeclarationStatementPtrList::iterator p = declList.begin(); p != declList.end(); ++p ) { SgFunctionDeclaration *func = isSgFunctionDeclaration(*p); if ( func == 0 ) continue; SgFunctionDefinition *defn = func->get_definition(); if ( defn == 0 ) continue; //ignore functions in system headers, Can keep them to test robustness if ( defn->get_file_info()->get_filename() != sageFile->get_file_info()->get_filename() ) continue; SgBasicBlock *body = defn->get_body(); // For each loop Rose_STL_Container<SgNode*> loops = NodeQuery::querySubTree( defn, V_SgForStatement ); if( loops.size() == 0 ) continue; // X. Replace operators with their equivalent counterparts defined // in "inline" annotations AstInterfaceImpl faImpl_1( body ); CPPAstInterface fa_body( &faImpl_1 ); OperatorInlineRewrite()( fa_body, AstNodePtrImpl(body) ); // Pass annotations to arrayInterface and use them to collect // alias info. function info etc. ArrayAnnotation* annot = ArrayAnnotation::get_inst(); ArrayInterface array_interface( *annot ); array_interface.initialize( fa_body, AstNodePtrImpl(defn) ); array_interface.observe( fa_body ); // X. Loop normalization for all loops within body NormalizeForLoop(fa_body, AstNodePtrImpl(body)); //cout << "Check point 3" << endl; for ( Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgNode* current_loop = *iter; SgInitializedName* invarname = getLoopInvariant( current_loop ); if( invarname != NULL ) { if( invarname->get_name().getString().compare("__Amos_Wang__") == 0 ) { //cout << "It's __Amos_Wang__." << endl; //replace "for(__Amos_Wang__ = 0;__Amos_Wang__ <= 1 - 1;__Amos_Wang__ += 1)" //to "#pragma omp task" std::string strtemp = current_loop->unparseToString(); strtemp.replace( 0, 64, "#pragma omp task" ); cout << "task position at: " << current_loop->get_file_info()->get_line() << ", " << current_loop->get_file_info()->get_col() << endl; cout << "context: " << strtemp.c_str() << endl; TaskValidation( current_loop ); cout << "TaskValidation done...\n" << endl; } else continue; } }// end for loops }//end loop for each function body cout << "--------------------------------------------" << endl; }//end loop for each source file release_analysis(); //generateDOT( *project ); backend( project ); //generate final file with correct directive amos_filter( argvList0 ); // for time counter t_end = usecs(); time_program = ((double)(t_end - t_start))/1000000; cout << "analysis time: " << time_program << " sec" << endl; // cout << endl << "***** Thank you for using Amos' compiler ! *****\n" << endl; return 0; }
void POETAstInterface::unparse(POETCode_ext* n, std::ostream& out, int align) { static SgUnparse_Info info; static Unparser* roseUnparser = 0; static POETCode* linebreak=ASTFactory::inst()->new_string("\n"); static POETCode* comma=ASTFactory::inst()->new_string(","); static bool template_only=false; static POETCode* left_over = 0; SgNode * input = (SgNode*)n->get_content(); POETCode* res = POETAstInterface::find_Ast2POET(input); if (res == n) { if (template_only && input->variantT() == V_SgFunctionDeclaration) { left_over = LIST(n,left_over); } else { std::string res = input->unparseToCompleteString(); out << res; } } else { if (roseUnparser == 0) { /* QY/2013: copied from the global unparseFile to use a different ostream and delegate*/ bool UseAutoKeyword = false; bool generateLineDirectives = true; bool useOverloadedOperators = false; bool num = false; bool _this = true; bool caststring = false; bool _debug = false; bool _class = false; bool _forced_transformation_format = false; bool _unparse_includes = false; Unparser_Opt roseOptions( UseAutoKeyword, generateLineDirectives, useOverloadedOperators, num, _this, caststring, _debug, _class, _forced_transformation_format, _unparse_includes ); roseUnparser = new Unparser(&out, "", roseOptions); } switch (input->variantT()) { case V_SgSourceFile: { SgSourceFile* f = isSgSourceFile(input); info.set_current_scope(f->get_globalScope()); template_only = true; code_gen(out, n->get_children(), 0, 0, align); template_only = false; if (left_over != 0) { code_gen(out, left_over, 0, 0, align); left_over = 0; } break; } case V_SgFunctionDeclaration: if (template_only) { left_over = LIST(n, left_over); break; } case V_SgTemplateInstantiationFunctionDecl: { SgFunctionDeclaration* d = isSgFunctionDeclaration(input); roseUnparser->u_exprStmt->unparseAttachedPreprocessingInfo(d,info,PreprocessingInfo::before); POETCode_ext_delegate repl(n, out); roseUnparser->repl = &repl; roseUnparser->u_exprStmt->unparseFuncDeclStmt(d, info); break; } case V_SgFunctionDefinition: { SgStatement* d = isSgStatement(input); POETCode_ext_delegate repl(n, out); roseUnparser->repl = &repl; roseUnparser->u_exprStmt->unparseStatement(d, info); assert(n->get_children() != n); out << "{"; code_gen(out, linebreak, 0, 0, align + 2); code_gen(out, n->get_children(), 0, linebreak, align+2); code_gen(out, linebreak, 0, 0, align); out << "}"; break; } case V_SgPragmaDeclaration: { out << "#pragma "; POETTuple* c = dynamic_cast<POETTuple*>(n->get_children()); assert(c != 0); code_gen(out, c->get_entry(0)); roseUnparser->cur << " "; roseUnparser->cur.insert_newline(1,align); code_gen(out, c->get_entry(1), 0, 0, align); break; } case V_SgForStatement: { out << "for (" ; POETTuple* c = dynamic_cast<POETTuple*>(n->get_children()); assert(c != 0); code_gen(out, c->get_entry(0)); code_gen(out, c->get_entry(1)); out << ";"; code_gen(out, c->get_entry(2)); out << ")"; break; } case V_SgExprStatement: code_gen(out, n->get_children(), 0, 0, align); out << ";"; break; case V_SgTemplateInstantiationMemberFunctionDecl: break; default: std::cerr << "Unsupported unparsing for : " << input->class_name() << input->unparseToString() << "\n"; //assert(0); } } }
int main ( int argc, char * argv[] ) { //init_poet(); // initialize poet if (argc <= 1) { PrintUsage(argv[0]); return -1; } #ifdef USE_OMEGA std::stringstream buffer; buffer << argv[argc-1] << std::endl; DepStats.SetFileName(buffer.str()); #endif vector<string> argvList(argv, argv + argc); CmdOptions::GetInstance()->SetOptions(argvList); ArrayAnnotation* array_annot = ArrayAnnotation::get_inst(); array_annot->register_annot(); //OperatorSideEffectAnnotation* funcAnnot=OperatorSideEffectAnnotation::get_inst(); //funcAnnot->register_annot(); LoopTransformInterface::set_sideEffectInfo(array_annot); ArrayInterface anal(*array_annot); LoopTransformInterface::set_arrayInfo(&anal); ReadAnnotation::get_inst()->read(); if (DebugAnnot()) { // funcAnnot->Dump(); array_annot->Dump(); } AssumeNoAlias aliasInfo; LoopTransformInterface::set_aliasInfo(&aliasInfo); LoopTransformInterface::cmdline_configure(argvList); SgProject *sageProject = new SgProject ( argvList); FixFileInfo(sageProject); // DQ (11/19/2013): Added AST consistency tests. AstTests::runAllTests(sageProject); int filenum = sageProject->numberOfFiles(); for (int i = 0; i < filenum; ++i) { // DQ (11/19/2013): Added AST consistency tests. AstTests::runAllTests(sageProject); SgSourceFile* sageFile = isSgSourceFile(sageProject->get_fileList()[i]); ROSE_ASSERT(sageFile != NULL); std::string fname = sageFile->get_file_info()->get_raw_filename(); fname=fname.substr(fname.find_last_of('/')+1); AutoTuningInterface tuning(fname); LoopTransformInterface::set_tuningInterface(&tuning); SgGlobal *root = sageFile->get_globalScope(); ROSE_ASSERT(root != NULL); SgDeclarationStatementPtrList declList = root->get_declarations (); // DQ (11/19/2013): Added AST consistency tests. AstTests::runAllTests(sageProject); for (SgDeclarationStatementPtrList::iterator p = declList.begin(); p != declList.end(); ++p) { SgFunctionDeclaration *func = isSgFunctionDeclaration(*p); if (func == 0) continue; SgFunctionDefinition *defn = func->get_definition(); if (defn == 0) continue; SgBasicBlock *stmts = defn->get_body(); AstInterfaceImpl scope(stmts); // DQ (11/19/2013): Added AST consistency tests. AstTests::runAllTests(sageProject); // DQ (11/19/2013): Added AST consistency tests. AstTests::runAllTests(sageProject); LoopTransformInterface::TransformTraverse(scope,AstNodePtrImpl(stmts)); #if 0 // DQ (11/19/2013): Added AST consistency tests (this fails). AstTests::runAllTests(sageProject); #endif } tuning.GenOutput(); #if 0 // DQ (11/19/2013): Added AST consistency tests (this fails). AstTests::runAllTests(sageProject); #endif } // if (CmdOptions::GetInstance()->HasOption("-fd")) { // simpleIndexFiniteDifferencing(sageProject); // } // if (CmdOptions::GetInstance()->HasOption("-pre")) { // partialRedundancyElimination(sageProject); // } #if 0 // DQ (11/19/2013): Added AST consistency tests (this fails). AstTests::runAllTests(sageProject); #endif unparseProject(sageProject); //backend(sageProject); #ifdef USE_OMEGA DepStats.SetDepChoice(0x1 | 0x2 | 0x4); DepStats.PrintResults(); #endif return 0; }
int clang_main(int argc, char ** argv, SgSourceFile& sageFile) { // 0 - Analyse Cmd Line std::vector<std::string> inc_dirs_list; std::vector<std::string> define_list; std::vector<std::string> inc_list; std::string input_file; for (int i = 0; i < argc; i++) { std::string current_arg(argv[i]); if (current_arg.find("-I") == 0) { if (current_arg.length() > 2) { inc_dirs_list.push_back(current_arg.substr(2)); } else { i++; if (i < argc) inc_dirs_list.push_back(current_arg); else break; } } else if (current_arg.find("-D") == 0) { if (current_arg.length() > 2) { define_list.push_back(current_arg.substr(2)); } else { i++; if (i < argc) define_list.push_back(current_arg); else break; } } else if (current_arg.find("-c") == 0) {} else if (current_arg.find("-o") == 0) { if (current_arg.length() == 2) { i++; if (i >= argc) break; } } else { // TODO -include #if DEBUG_ARGS std::cerr << "argv[" << i << "] = " << current_arg << " is neither define or include dir. Use it as input file." << std::endl; #endif input_file = current_arg; } } ClangToSageTranslator::Language language = ClangToSageTranslator::unknown; size_t last_period = input_file.find_last_of("."); std::string extention(input_file.substr(last_period + 1)); if (extention == "c") { language = ClangToSageTranslator::C; } else if (extention == "C" || extention == "cxx" || extention == "cpp" || extention == "cc") { language = ClangToSageTranslator::CPLUSPLUS; } else if (extention == "objc") { language = ClangToSageTranslator::OBJC; } else if (extention == "cu") { language = ClangToSageTranslator::CUDA; } else if (extention == "ocl" || extention == "cl") { language = ClangToSageTranslator::OPENCL; } ROSE_ASSERT(language != ClangToSageTranslator::unknown); const char * cxx_config_include_dirs_array [] = CXX_INCLUDE_STRING; const char * c_config_include_dirs_array [] = C_INCLUDE_STRING; std::vector<std::string> cxx_config_include_dirs ( cxx_config_include_dirs_array, cxx_config_include_dirs_array + sizeof(cxx_config_include_dirs_array) / sizeof(const char*) ); std::vector<std::string> c_config_include_dirs ( c_config_include_dirs_array, c_config_include_dirs_array + sizeof(c_config_include_dirs_array) / sizeof(const char*) ); std::string rose_include_path; bool in_install_tree = roseInstallPrefix(rose_include_path); if (in_install_tree) { rose_include_path += "/include-staging/"; } else { rose_include_path = std::string(ROSE_AUTOMAKE_TOP_BUILDDIR) + "/include-staging/"; } std::vector<std::string>::iterator it; for (it = c_config_include_dirs.begin(); it != c_config_include_dirs.end(); it++) if (it->length() > 0 && (*it)[0] != '/') *it = rose_include_path + *it; for (it = cxx_config_include_dirs.begin(); it != cxx_config_include_dirs.end(); it++) if (it->length() > 0 && (*it)[0] != '/') *it = rose_include_path + *it; inc_dirs_list.push_back(rose_include_path + "clang/"); // FIXME add ROSE path to gcc headers... switch (language) { case ClangToSageTranslator::C: inc_dirs_list.insert(inc_dirs_list.begin(), c_config_include_dirs.begin(), c_config_include_dirs.end()); inc_list.push_back("clang-builtin-c.h"); break; case ClangToSageTranslator::CPLUSPLUS: inc_dirs_list.insert(inc_dirs_list.begin(), cxx_config_include_dirs.begin(), cxx_config_include_dirs.end()); inc_list.push_back("clang-builtin-cpp.hpp"); break; case ClangToSageTranslator::CUDA: inc_dirs_list.insert(inc_dirs_list.begin(), cxx_config_include_dirs.begin(), cxx_config_include_dirs.end()); inc_list.push_back("clang-builtin-cuda.hpp"); break; case ClangToSageTranslator::OPENCL: // inc_dirs_list.insert(inc_dirs_list.begin(), c_config_include_dirs.begin(), c_config_include_dirs.end()); // FIXME get the path right inc_list.push_back("clang-builtin-opencl.h"); break; case ClangToSageTranslator::OBJC: default: ROSE_ASSERT(false); } // FIXME should be handle by Clang ? define_list.push_back("__I__=_Complex_I"); unsigned cnt = define_list.size() + inc_dirs_list.size() + inc_list.size(); char ** args = new char*[cnt]; std::vector<std::string>::iterator it_str; unsigned i = 0; for (it_str = define_list.begin(); it_str != define_list.end(); it_str++) { args[i] = new char[it_str->size() + 3]; args[i][0] = '-'; args[i][1] = 'D'; strcpy(&(args[i][2]), it_str->c_str()); #if DEBUG_ARGS std::cerr << "args[" << i << "] = " << args[i] << std::endl; #endif i++; } for (it_str = inc_dirs_list.begin(); it_str != inc_dirs_list.end(); it_str++) { args[i] = new char[it_str->size() + 3]; args[i][0] = '-'; args[i][1] = 'I'; strcpy(&(args[i][2]), it_str->c_str()); #if DEBUG_ARGS std::cerr << "args[" << i << "] = " << args[i] << std::endl; #endif i++; } for (it_str = inc_list.begin(); it_str != inc_list.end(); it_str++) { args[i] = new char[it_str->size() + 9]; args[i][0] = '-'; args[i][1] = 'i'; args[i][2] = 'n'; args[i][3] = 'c'; args[i][4] = 'l'; args[i][5] = 'u'; args[i][6] = 'd'; args[i][7] = 'e'; strcpy(&(args[i][8]), it_str->c_str()); #if DEBUG_ARGS std::cerr << "args[" << i << "] = " << args[i] << std::endl; #endif i++; } // 2 - Create a compiler instance clang::CompilerInstance * compiler_instance = new clang::CompilerInstance(); clang::TextDiagnosticPrinter * diag_printer = new clang::TextDiagnosticPrinter(llvm::errs(), clang::DiagnosticOptions()); compiler_instance->createDiagnostics(argc, argv, diag_printer, true, false); clang::CompilerInvocation * invocation = new clang::CompilerInvocation(); clang::CompilerInvocation::CreateFromArgs(*invocation, args, &(args[cnt]), compiler_instance->getDiagnostics()); compiler_instance->setInvocation(invocation); clang::LangOptions & lang_opts = compiler_instance->getLangOpts(); switch (language) { case ClangToSageTranslator::C: // compiler_instance->getInvocation().setLangDefaults(lang_opts, clang::IK_C, ); break; case ClangToSageTranslator::CPLUSPLUS: lang_opts.CPlusPlus = 1; // compiler_instance->getInvocation().setLangDefaults(lang_opts, clang::IK_CXX, ); break; case ClangToSageTranslator::CUDA: lang_opts.CUDA = 1; // lang_opts.CPlusPlus = 1; // compiler_instance->getInvocation().setLangDefaults(lang_opts, clang::IK_CUDA, clang::LangStandard::lang_cuda); break; case ClangToSageTranslator::OPENCL: lang_opts.OpenCL = 1; // compiler_instance->getInvocation().setLangDefaults(lang_opts, clang::IK_OpenCL, clang::LangStandard::lang_opencl); break; case ClangToSageTranslator::OBJC: ROSE_ASSERT(!"Objective-C is not supported by ROSE Compiler."); // compiler_instance->getInvocation().setLangDefaults(lang_opts, clang::IK_, ); default: ROSE_ASSERT(false); } clang::TargetOptions target_options; target_options.Triple = llvm::sys::getHostTriple(); clang::TargetInfo * target_info = clang::TargetInfo::CreateTargetInfo(compiler_instance->getDiagnostics(), target_options); compiler_instance->setTarget(target_info); compiler_instance->createFileManager(); compiler_instance->createSourceManager(compiler_instance->getFileManager()); const clang::FileEntry * input_file_entry = compiler_instance->getFileManager().getFile(input_file); compiler_instance->getSourceManager().createMainFileID(input_file_entry); if (!compiler_instance->hasPreprocessor()) compiler_instance->createPreprocessor(); if (!compiler_instance->hasASTContext()) compiler_instance->createASTContext(); ClangToSageTranslator translator(compiler_instance, language); compiler_instance->setASTConsumer(&translator); if (!compiler_instance->hasSema()) compiler_instance->createSema(clang::TU_Complete, NULL); ROSE_ASSERT (compiler_instance->hasDiagnostics()); ROSE_ASSERT (compiler_instance->hasTarget()); ROSE_ASSERT (compiler_instance->hasFileManager()); ROSE_ASSERT (compiler_instance->hasSourceManager()); ROSE_ASSERT (compiler_instance->hasPreprocessor()); ROSE_ASSERT (compiler_instance->hasASTContext()); ROSE_ASSERT (compiler_instance->hasSema()); // 3 - Translate compiler_instance->getDiagnosticClient().BeginSourceFile(compiler_instance->getLangOpts(), &(compiler_instance->getPreprocessor())); clang::ParseAST(compiler_instance->getPreprocessor(), &translator, compiler_instance->getASTContext()); compiler_instance->getDiagnosticClient().EndSourceFile(); SgGlobal * global_scope = translator.getGlobalScope(); // 4 - Attach to the file if (sageFile.get_globalScope() != NULL) SageInterface::deleteAST(sageFile.get_globalScope()); sageFile.set_globalScope(global_scope); global_scope->set_parent(&sageFile); std::string file_name(input_file); Sg_File_Info * start_fi = new Sg_File_Info(file_name, 0, 0); Sg_File_Info * end_fi = new Sg_File_Info(file_name, 0, 0); global_scope->set_startOfConstruct(start_fi); global_scope->set_endOfConstruct(end_fi); // 5 - Finish the AST (fixup phase) finishSageAST(translator); return 1; }
POETCode* POETAstInterface::Ast2POET(const Ast& n) { static SgTemplateInstantiationFunctionDecl* tmp=0; SgNode* input = (SgNode*) n; if (input == 0) return EMPTY; POETCode* res = POETAstInterface::find_Ast2POET(input); if (res != 0) return res; { SgProject* sageProject=isSgProject(input); if (sageProject != 0) { int filenum = sageProject->numberOfFiles(); for (int i = 0; i < filenum; ++i) { SgSourceFile* sageFile = isSgSourceFile(sageProject->get_fileList()[i]); SgGlobal *root = sageFile->get_globalScope(); SgDeclarationStatementPtrList declList = root->get_declarations (); POETCode* curfile = ROSE_2_POET_list(declList, 0, tmp); curfile = new POETCode_ext(sageFile, curfile); POETAstInterface::set_Ast2POET(sageFile, curfile); res=LIST(curfile, res); } POETAstInterface::set_Ast2POET(sageProject,res); return res; } } { SgBasicBlock* block = isSgBasicBlock(input); if (block != 0) { res=ROSE_2_POET_list(block->get_statements(), res, tmp); POETAstInterface::set_Ast2POET(block, res); return res; } } { SgExprListExp* block = isSgExprListExp(input); if (block != 0) { res=ROSE_2_POET_list(block->get_expressions(), 0, tmp); POETAstInterface::set_Ast2POET(block, res); return res; } } { SgForStatement *f = isSgForStatement(input); if (f != 0) { POETCode* init = ROSE_2_POET_list(f->get_for_init_stmt()->get_init_stmt(),0, tmp); POETCode* ctrl = new POETCode_ext(f, TUPLE3(init,Ast2POET(f->get_test_expr()), Ast2POET(f->get_increment()))); res = CODE_ACC("Nest", PAIR(ctrl,Ast2POET(f->get_loop_body()))); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgVarRefExp * v = isSgVarRefExp(input); if (v != 0) { res = STRING(v->get_symbol()->get_name().str()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgMemberFunctionRefExp * v = isSgMemberFunctionRefExp(input); if (v != 0) { res = STRING(v->get_symbol()->get_name().str()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgIntVal * v = isSgIntVal(input); if (v != 0) { res = ICONST(v->get_value()); POETAstInterface::set_Ast2POET(input, res); return res; } } { SgInitializedName* var = isSgInitializedName(input); if (var != 0) { POETCode* name = STRING(var->get_name().str()); POETCode* init = Ast2POET(var->get_initializer()); res = new POETCode_ext(var, PAIR(name,init)); POETAstInterface::set_Ast2POET(input, res); return res; } } /* { std::string fname; AstInterface::AstList params; AstNodeType returnType; AstNodePtr body; if (AstInterface :: IsFunctionDefinition( input, &fname, ¶ms, (AstInterface::AstList*)0, &body, (AstInterface::AstTypeList*)0, &returnType)) { if (body != AST_NULL) std::cerr << "body not empty:" << fname << "\n"; POETCode* c = TUPLE4(STRING(fname), ROSE_2_POET_list(0,params,0), STRING(AstInterface::GetTypeName(returnType)), Ast2POET(body.get_ptr())); res = new POETCode_ext(input, c); POETAstInterface::set_Ast2POET(input,res); return res; } } */ AstInterface::AstList c = AstInterface::GetChildrenList(input); switch (input->variantT()) { case V_SgCastExp: case V_SgAssignInitializer: res = Ast2POET(c[0]); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgDotExp: { POETCode* v1 = Ast2POET(c[1]); if (dynamic_cast<POETString*>(v1)->get_content() == "operator()") return Ast2POET(c[0]); res = CODE_ACC("Bop",TUPLE3(STRING("."), Ast2POET(c[0]), v1)); return res; } case V_SgLessThanOp: res = CODE_ACC("Bop",TUPLE3(STRING("<"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgSubtractOp: res = CODE_ACC("Bop",TUPLE3(STRING("-"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgAddOp: res = CODE_ACC("Bop",TUPLE3(STRING("+"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgMultiplyOp: res = CODE_ACC("Bop",TUPLE3(STRING("*"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgDivideOp: res = CODE_ACC("Bop",TUPLE3(STRING("/"),Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgAssignOp: res = CODE_ACC("Assign",PAIR(Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; case V_SgFunctionCallExp: res = CODE_ACC("FunctionCall",PAIR(Ast2POET(c[0]), Ast2POET(c[1]))); POETAstInterface::set_Ast2POET(input, res); return res; } POETCode * c2 = 0; if (tmp == 0) tmp=isSgTemplateInstantiationFunctionDecl(input); switch (c.size()) { case 0: break; case 1: c2 = Ast2POET(c[0]); break; case 2: c2 = PAIR(Ast2POET(c[0]),Ast2POET(c[1])); break; case 3: c2 = TUPLE3(Ast2POET(c[0]),Ast2POET(c[1]),Ast2POET(c[2])); break; case 4: c2 = TUPLE4(Ast2POET(c[0]),Ast2POET(c[1]),Ast2POET(c[2]),Ast2POET(c[3])); break; default: //std::cerr << "too many children: " << c.size() << ":" << input->unparseToString() << "\n"; c2 = EMPTY; } if (tmp == input) tmp = 0; res = new POETCode_ext(input, c2); POETAstInterface::set_Ast2POET(input,res); return res; }
int main (int argc, char *argv[]) { vector<string> argvList(argv, argv+argc); //Processing debugging and annotation options // autopar_command_processing(argvList); argvList = commandline_processing (argvList); // enable parsing user-defined pragma if enable_diff is true // -rose:openmp:parse_only if (enable_diff) argvList.push_back("-rose:openmp:parse_only"); SgProject *project = frontend (argvList); ROSE_ASSERT (project != NULL); // register midend signal handling function if (KEEP_GOING_CAUGHT_MIDEND_SIGNAL) { std::cout << "[WARN] " << "Configured to keep going after catching a " << "signal in AutoPar" << std::endl; Rose::KeepGoing::setMidendErrorCode (project, 100); goto label_end; } // create a block to avoid jump crosses initialization of candidateFuncDefs etc. { std::vector<SgFunctionDefinition* > candidateFuncDefs; findCandidateFunctionDefinitions (project, candidateFuncDefs); normalizeLoops (candidateFuncDefs); //Prepare liveness analysis etc. //Too much output for analysis debugging info. //initialize_analysis (project,enable_debug); initialize_analysis (project, false); // This is a bit redundant with findCandidateFunctionDefinitions () // But we do need the per file control to decide if omp.h is needed for each file // // For each source file in the project SgFilePtrList & ptr_list = project->get_fileList(); for (SgFilePtrList::iterator iter = ptr_list.begin(); iter!=ptr_list.end(); iter++) { SgFile* sageFile = (*iter); SgSourceFile * sfile = isSgSourceFile(sageFile); ROSE_ASSERT(sfile); SgGlobal *root = sfile->get_globalScope(); Rose_STL_Container<SgNode*> defList = NodeQuery::querySubTree(sfile, V_SgFunctionDefinition); bool hasOpenMP= false; // flag to indicate if omp.h is needed in this file //For each function body in the scope //for (SgDeclarationStatementPtrList::iterator p = declList.begin(); p != declList.end(); ++p) for (Rose_STL_Container<SgNode*>::iterator p = defList.begin(); p != defList.end(); ++p) { // cout<<"\t loop at:"<< cur_loop->get_file_info()->get_line() <<endl; SgFunctionDefinition *defn = isSgFunctionDefinition(*p); ROSE_ASSERT (defn != NULL); SgFunctionDeclaration *func = defn->get_declaration(); ROSE_ASSERT (func != NULL); //ignore functions in system headers, Can keep them to test robustness if (defn->get_file_info()->get_filename()!=sageFile->get_file_info()->get_filename()) { continue; } SgBasicBlock *body = defn->get_body(); // For each loop Rose_STL_Container<SgNode*> loops = NodeQuery::querySubTree(defn,V_SgForStatement); if (loops.size()==0) { if (enable_debug) cout<<"\t skipped since no for loops are found in this function"<<endl; continue; } #if 0 // Moved to be executed before running liveness analysis. // normalize C99 style for (int i= x, ...) to C89 style: int i; (i=x, ...) // Liao, 10/22/2009. Thank Jeff Keasler for spotting this bug for (Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgForStatement* cur_loop = isSgForStatement(*iter); ROSE_ASSERT(cur_loop); SageInterface::normalizeForLoopInitDeclaration(cur_loop); } #endif // X. Replace operators with their equivalent counterparts defined // in "inline" annotations AstInterfaceImpl faImpl_1(body); CPPAstInterface fa_body(&faImpl_1); OperatorInlineRewrite()( fa_body, AstNodePtrImpl(body)); // Pass annotations to arrayInterface and use them to collect // alias info. function info etc. ArrayAnnotation* annot = ArrayAnnotation::get_inst(); ArrayInterface array_interface(*annot); array_interface.initialize(fa_body, AstNodePtrImpl(defn)); array_interface.observe(fa_body); //FR(06/07/2011): aliasinfo was not set which caused segfault LoopTransformInterface::set_aliasInfo(&array_interface); for (Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgNode* current_loop = *iter; if (enable_debug) { SgForStatement * fl = isSgForStatement(current_loop); cout<<"\t\t Considering loop at "<< fl->get_file_info()->get_line()<<endl; } //X. Parallelize loop one by one // getLoopInvariant() will actually check if the loop has canonical forms // which can be handled by dependence analysis SgInitializedName* invarname = getLoopInvariant(current_loop); if (invarname != NULL) { bool ret = ParallelizeOutermostLoop(current_loop, &array_interface, annot); if (ret) // if at least one loop is parallelized, we set hasOpenMP to be true for the entire file. hasOpenMP = true; } else // cannot grab loop index from a non-conforming loop, skip parallelization { if (enable_debug) cout<<"Skipping a non-canonical loop at line:"<<current_loop->get_file_info()->get_line()<<"..."<<endl; // We should not reset it to false. The last loop may not be parallelizable. But a previous one may be. //hasOpenMP = false; } }// end for loops } // end for-loop for declarations // insert omp.h if needed if (hasOpenMP && !enable_diff) { SageInterface::insertHeader("omp.h",PreprocessingInfo::after,false,root); if (enable_patch) generatePatchFile(sfile); } // compare user-defined and compiler-generated OmpAttributes if (enable_diff) diffUserDefinedAndCompilerGeneratedOpenMP(sfile); } //end for-loop of files #if 1 // undo loop normalization std::map <SgForStatement* , bool >::iterator iter = trans_records.forLoopInitNormalizationTable.begin(); for (; iter!= trans_records.forLoopInitNormalizationTable.end(); iter ++) { SgForStatement* for_loop = (*iter).first; unnormalizeForLoopInitDeclaration (for_loop); } #endif // Qing's loop normalization is not robust enough to pass all tests //AstTests::runAllTests(project); // clean up resources for analyses release_analysis(); } label_end: // Report errors if (keep_going) { std::vector<std::string> orig_rose_cmdline(argv, argv+argc); Rose::KeepGoing::generate_reports (project, orig_rose_cmdline); } //project->unparse(); return backend (project); }
int main(int argc, char** argv) { std::string binaryFilename = (argc >= 1 ? argv[argc-1] : "" ); std::vector<std::string> newArgv(argv,argv+argc); newArgv.push_back("-rose:output"); newArgv.push_back(binaryFilename+"-binarySemantics.C"); SgProject* proj = frontend(newArgv); ROSE_ASSERT (proj); SgSourceFile* newFile = isSgSourceFile(proj->get_fileList().front()); ROSE_ASSERT(newFile != NULL); SgGlobal* g = newFile->get_globalScope(); ROSE_ASSERT (g); //I am doing some experimental work to enable functions in the C representation //Set this flag to true in order to enable that work bool enable_functions = true; //Jeremiah did some work to enable a simplification and normalization of the //C representation. Enable this work by setting this flag to true. bool enable_normalizations = false; vector<SgNode*> asmFiles = NodeQuery::querySubTree(proj, V_SgAsmGenericFile); ROSE_ASSERT (asmFiles.size() == 1); if( enable_functions == false) { //Representation of C normalizations withotu functions SgFunctionDeclaration* decl = buildDefiningFunctionDeclaration("run", SgTypeVoid::createType(), buildFunctionParameterList(), g); appendStatement(decl, g); SgBasicBlock* body = decl->get_definition()->get_body(); // ROSE_ASSERT(isSgAsmFile(asmFiles[0])); // X86CTranslationPolicy policy(newFile, isSgAsmFile(asmFiles[0])); X86CTranslationPolicy policy(newFile, isSgAsmGenericFile(asmFiles[0])); ROSE_ASSERT( isSgAsmGenericFile(asmFiles[0]) != NULL); policy.switchBody = buildBasicBlock(); removeDeadStores(policy.switchBody,policy); SgSwitchStatement* sw = buildSwitchStatement(buildVarRefExp(policy.ipSym), policy.switchBody); ROSE_ASSERT(isSgBasicBlock(sw->get_body())); SgWhileStmt* whileStmt = buildWhileStmt(buildBoolValExp(true), sw); appendStatement(whileStmt, body); policy.whileBody = sw; X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression> t(policy); //AS FIXME: This query gets noting in the form in the repository. Doing this hack since we only //have one binary file anyways. //vector<SgNode*> instructions = NodeQuery::querySubTree(asmFiles[0], V_SgAsmX86Instruction); vector<SgNode*> instructions = NodeQuery::querySubTree(proj, V_SgAsmX86Instruction); std::cout << "Instruction\n"; for (size_t i = 0; i < instructions.size(); ++i) { SgAsmX86Instruction* insn = isSgAsmX86Instruction(instructions[i]); ROSE_ASSERT (insn); try { t.processInstruction(insn); } catch (const X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression>::Exception &e) { std::cout <<e.mesg <<": " <<unparseInstructionWithAddress(e.insn) <<"\n"; } } if ( enable_normalizations == true ) { //Enable normalizations of C representation //This is done heuristically where some steps //are repeated. It is not clear which order is //the best { plugInAllConstVarDefs(policy.switchBody,policy) ; simplifyAllExpressions(policy.switchBody); removeIfConstants(policy.switchBody); removeDeadStores(policy.switchBody,policy); removeUnusedVariables(policy.switchBody); } { plugInAllConstVarDefs(policy.switchBody,policy) ; simplifyAllExpressions(policy.switchBody); removeIfConstants(policy.switchBody); removeDeadStores(policy.switchBody,policy); } removeUnusedVariables(policy.switchBody); } }else{ //Experimental changes to introduce functions into the C representation //When trying to add function I get that symbols are not defined //Iterate over the functions separately vector<SgNode*> asmFunctions = NodeQuery::querySubTree(proj, V_SgAsmFunction); for(size_t j = 0; j < asmFunctions.size(); j++ ) { SgAsmFunction* binFunc = isSgAsmFunction( asmFunctions[j] ); // Some functions (probably just one) are generated to hold basic blocks that could not // be assigned to a particular function. This happens when the Disassembler is overzealous // and the Partitioner cannot statically determine where the block belongs. The name of // one such function is "***uncategorized blocks***". [matzke 2010-06-29] if ((binFunc->get_reason() & SgAsmFunction::FUNC_LEFTOVERS)) continue; //Some functions may be unnamed so we need to generate a name for those std::string funcName; if (binFunc->get_name().size()==0) { char addr_str[64]; sprintf(addr_str, "0x%"PRIx64, binFunc->get_statementList()[0]->get_address()); funcName = std::string("my_") + addr_str;; } else { funcName = "my" + binFunc->get_name(); } //Functions can have illegal characters in their name. Need to replace those characters for ( int i = 0 ; i < funcName.size(); i++ ) { char& currentCharacter = funcName.at(i); if ( currentCharacter == '.' ) currentCharacter = '_'; } SgFunctionDeclaration* decl = buildDefiningFunctionDeclaration(funcName, SgTypeVoid::createType(), buildFunctionParameterList(), g); appendStatement(decl, g); SgBasicBlock* body = decl->get_definition()->get_body(); X86CTranslationPolicy policy(newFile, isSgAsmGenericFile(asmFiles[0])); ROSE_ASSERT( isSgAsmGenericFile(asmFiles[0]) != NULL); policy.switchBody = buildBasicBlock(); SgSwitchStatement* sw = buildSwitchStatement(buildVarRefExp(policy.ipSym), policy.switchBody); SgWhileStmt* whileStmt = buildWhileStmt(buildBoolValExp(true), sw); appendStatement(whileStmt, body); policy.whileBody = sw; X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression> t(policy); vector<SgNode*> instructions = NodeQuery::querySubTree(binFunc, V_SgAsmX86Instruction); for (size_t i = 0; i < instructions.size(); ++i) { SgAsmX86Instruction* insn = isSgAsmX86Instruction(instructions[i]); if( insn->get_kind() == x86_nop ) continue; ROSE_ASSERT (insn); try { t.processInstruction(insn); } catch (const X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression>::Exception &e) { std::cout <<e.mesg <<": " <<unparseInstructionWithAddress(e.insn) <<"\n"; } } } //addDirectJumpsToSwitchCases(policy); } proj->get_fileList().erase(proj->get_fileList().end() - 1); // Remove binary file before calling backend // AstTests::runAllTests(proj); //Compile the resulting project return backend(proj); }
void TransformationSupport::getTransformationOptions ( SgNode* astNode, list<OptionDeclaration> & generatedList, string identifingTypeName ) { // This function searches for variables of type ScopeBasedTransformationOptimization. Variables // of type ScopeBasedTransformationOptimization are used to communicate optimizations from the // application to the preprocessor. If called from a project or file object it traverses down to // the global scope of the file and searches only the global scope, if called from and other // location within the AST it searches the current scope and then traverses the parent nodes to // find all enclosing scopes until in reaches the global scope. At each scope it searches for // variables of type ScopeBasedTransformationOptimization. // printf ("######################### START OF TRANSFORMATION OPTION QUERY ######################## \n"); ROSE_ASSERT (astNode != NULL); ROSE_ASSERT (identifingTypeName.c_str() != NULL); #if 0 printf ("In getTransformationOptions(): astNode->sage_class_name() = %s generatedList.size() = %d \n", astNode->sage_class_name(),generatedList.size()); SgLocatedNode* locatedNode = isSgLocatedNode(astNode); if (locatedNode != NULL) { printf (" locatedNode->get_file_info()->get_filename() = %s \n",locatedNode->get_file_info()->get_filename()); printf (" locatedNode->get_file_info()->get_line() = %d \n",locatedNode->get_file_info()->get_line()); } #endif switch (astNode->variant()) { case ProjectTag: { SgProject* project = isSgProject(astNode); ROSE_ASSERT (project != NULL); //! Loop through all the files in the project and call the mainTransform function for each file int i = 0; for (i=0; i < project->numberOfFiles(); i++) { SgFile* file = &(project->get_file(i)); // printf ("Calling Query::traverse(SgFile,QueryFunctionType,QueryAssemblyFunctionType) \n"); getTransformationOptions ( file, generatedList, identifingTypeName ); } break; } case SourceFileTag: { SgSourceFile* file = isSgSourceFile(astNode); ROSE_ASSERT (file != NULL); SgGlobal* globalScope = file->get_globalScope(); ROSE_ASSERT (globalScope != NULL); ROSE_ASSERT (isSgGlobal(globalScope) != NULL); getTransformationOptions ( globalScope, generatedList, identifingTypeName ); break; } // Global Scope case GLOBAL_STMT: { SgGlobal* globalScope = isSgGlobal(astNode); ROSE_ASSERT (globalScope != NULL); SgSymbolTable* symbolTable = globalScope->get_symbol_table(); ROSE_ASSERT (symbolTable != NULL); getTransformationOptions ( symbolTable, generatedList, identifingTypeName ); // printf ("Processed global scope, exiting .. \n"); // ROSE_ABORT(); break; } case SymbolTableTag: { // List the variable in each scope // printf ("List all the variables in this symbol table! \n"); SgSymbolTable* symbolTable = isSgSymbolTable(astNode); ROSE_ASSERT (symbolTable != NULL); bool foundTransformationOptimizationSpecifier = false; // printf ("Now print out the information in the symbol table for this scope: \n"); // symbolTable->print(); #if 0 // I don't know when a SymbolTable is given a name! printf ("SymbolTable has a name = %s \n", (symbolTable->get_no_name()) ? "NO: it has no name" : "YES: it does have a name"); if (!symbolTable->get_no_name()) printf ("SymbolTable name = %s \n",symbolTable->get_name().str()); else ROSE_ASSERT (symbolTable->get_name().str() == NULL); #endif if (symbolTable->get_table() != NULL) { SgSymbolTable::hash_iterator i = symbolTable->get_table()->begin(); int counter = 0; while (i != symbolTable->get_table()->end()) { ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL ); // printf ("Initial info: number: %d pair.first (SgName) = %s pair.second (SgSymbol) sage_class_name() = %s \n", // counter,(*i).first.str(),(*i).second->sage_class_name()); SgSymbol* symbol = isSgSymbol((*i).second); ROSE_ASSERT ( symbol != NULL ); SgType* type = symbol->get_type(); ROSE_ASSERT ( type != NULL ); SgNamedType* namedType = isSgNamedType(type); string typeName; if (namedType != NULL) { SgName n = namedType->get_name(); typeName = namedType->get_name().str(); // char* nameString = namedType->get_name().str(); // printf ("Type is: (named type) = %s \n",nameString); ROSE_ASSERT (identifingTypeName.c_str() != NULL); // ROSE_ASSERT (typeName != NULL); // printf ("In getTransformationOptions(): typeName = %s identifingTypeName = %s \n",typeName.c_str(),identifingTypeName.c_str()); // if ( (typeName != NULL) && ( typeName == identifingTypeName) ) if ( typeName == identifingTypeName ) { // Now look at the parameter list to the constructor and save the // values into the list. // printf ("Now save the constructor arguments! \n"); SgVariableSymbol* variableSymbol = isSgVariableSymbol(symbol); if ( variableSymbol != NULL ) { SgInitializedName* initializedNameDeclaration = variableSymbol->get_declaration(); ROSE_ASSERT (initializedNameDeclaration != NULL); SgDeclarationStatement* declarationStatement = initializedNameDeclaration->get_declaration(); ROSE_ASSERT (declarationStatement != NULL); SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(declarationStatement); ROSE_ASSERT (variableDeclaration != NULL); getTransformationOptionsFromVariableDeclarationConstructorArguments(variableDeclaration,generatedList); foundTransformationOptimizationSpecifier = true; // printf ("Exiting after saving the constructor arguments! \n"); // ROSE_ABORT(); } else { #if 0 printf ("Not a SgVariableSymbol: symbol->sage_class_name() = %s \n", symbol->sage_class_name()); #endif } } else { #if 0 printf ("typeName != identifingTypeName : symbol->sage_class_name() = %s \n", symbol->sage_class_name()); #endif #if 0 // I don't think this should ever be NULL (but it is sometimes) if (typeName != NULL) printf ("typeName == NULL \n"); #endif } } else { typeName = (char *)type->sage_class_name(); } // printf ("In while loop at the base: counter = %d \n",counter); i++; counter++; } } else { // printf ("Pointer to symbol table is NULL \n"); } // printf ("foundTransformationOptimizationSpecifier = %s \n",foundTransformationOptimizationSpecifier ? "true" : "false"); // SgSymbolTable objects don't have a parent node (specifically they lack a get_parent // member function in the interface)! break; } case BASIC_BLOCK_STMT: { // List the variable in each scope // printf ("List all the variables in this scope! \n"); SgBasicBlock* basicBlock = isSgBasicBlock(astNode); ROSE_ASSERT (basicBlock != NULL); SgSymbolTable* symbolTable = basicBlock->get_symbol_table(); ROSE_ASSERT (symbolTable != NULL); getTransformationOptions ( symbolTable, generatedList, identifingTypeName ); // Next go (fall through this case) to the default case so that we traverse the parent // of the SgBasicBlock. // break; } default: // Most cases will be the default (this is by design) // printf ("default in switch found in globalQueryGetListOperandStringFunction() (sage_class_name = %s) \n",astNode->sage_class_name()); // Need to recursively backtrack through the parents until we reach the SgGlobal (global scope) SgStatement* statement = isSgStatement(astNode); if (statement != NULL) { SgNode* parentNode = statement->get_parent(); ROSE_ASSERT (parentNode != NULL); // printf ("parent = %p parentNode->sage_class_name() = %s \n",parentNode,parentNode->sage_class_name()); SgStatement* parentStatement = isSgStatement(parentNode); if (parentStatement == NULL) { printf ("parentStatement == NULL: statement (%p) is a %s \n",statement,statement->sage_class_name()); printf ("parentStatement == NULL: statement->get_file_info()->get_filename() = %s \n",statement->get_file_info()->get_filename()); printf ("parentStatement == NULL: statement->get_file_info()->get_line() = %d \n",statement->get_file_info()->get_line()); } ROSE_ASSERT (parentStatement != NULL); // Call this function recursively (directly rather than through the query mechanism) getTransformationOptions ( parentStatement, generatedList, identifingTypeName ); } else { // printf ("astNode is not a SgStatement! \n"); } break; } #if 0 printf ("At BASE of getTransformationOptions(): astNode->sage_class_name() = %s size of generatedList = %d \n", astNode->sage_class_name(),generatedList.size()); #endif // printf ("######################### END OF TRANSFORMATION OPTION QUERY ######################## \n"); }
int main (int argc, char *argv[]) { vector<string> argvList(argv, argv+argc); //Processing debugging and annotation options autopar_command_processing(argvList); // enable parsing user-defined pragma if enable_diff is true // -rose:openmp:parse_only if (enable_diff) argvList.push_back("-rose:openmp:parse_only"); SgProject *project = frontend (argvList); ROSE_ASSERT (project != NULL); #if 1 // This has to happen before analyses are called. // For each loop VariantVector vv (V_SgForStatement); Rose_STL_Container<SgNode*> loops = NodeQuery::queryMemoryPool(vv); // normalize C99 style for (int i= x, ...) to C89 style: int i; (i=x, ...) // Liao, 10/22/2009. Thank Jeff Keasler for spotting this bug for (Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgForStatement* cur_loop = isSgForStatement(*iter); ROSE_ASSERT(cur_loop); SageInterface::normalizeForLoopInitDeclaration(cur_loop); } #endif //Prepare liveness analysis etc. initialize_analysis (project,false); // For each source file in the project SgFilePtrList & ptr_list = project->get_fileList(); for (SgFilePtrList::iterator iter = ptr_list.begin(); iter!=ptr_list.end(); iter++) { SgFile* sageFile = (*iter); SgSourceFile * sfile = isSgSourceFile(sageFile); ROSE_ASSERT(sfile); SgGlobal *root = sfile->get_globalScope(); SgDeclarationStatementPtrList& declList = root->get_declarations (); bool hasOpenMP= false; // flag to indicate if omp.h is needed in this file //For each function body in the scope for (SgDeclarationStatementPtrList::iterator p = declList.begin(); p != declList.end(); ++p) { SgFunctionDeclaration *func = isSgFunctionDeclaration(*p); if (func == 0) continue; SgFunctionDefinition *defn = func->get_definition(); if (defn == 0) continue; //ignore functions in system headers, Can keep them to test robustness if (defn->get_file_info()->get_filename()!=sageFile->get_file_info()->get_filename()) continue; SgBasicBlock *body = defn->get_body(); // For each loop Rose_STL_Container<SgNode*> loops = NodeQuery::querySubTree(defn,V_SgForStatement); if (loops.size()==0) continue; #if 0 // Moved to be executed before running liveness analysis. // normalize C99 style for (int i= x, ...) to C89 style: int i; (i=x, ...) // Liao, 10/22/2009. Thank Jeff Keasler for spotting this bug for (Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgForStatement* cur_loop = isSgForStatement(*iter); ROSE_ASSERT(cur_loop); SageInterface::normalizeForLoopInitDeclaration(cur_loop); } #endif // X. Replace operators with their equivalent counterparts defined // in "inline" annotations AstInterfaceImpl faImpl_1(body); CPPAstInterface fa_body(&faImpl_1); OperatorInlineRewrite()( fa_body, AstNodePtrImpl(body)); // Pass annotations to arrayInterface and use them to collect // alias info. function info etc. ArrayAnnotation* annot = ArrayAnnotation::get_inst(); ArrayInterface array_interface(*annot); array_interface.initialize(fa_body, AstNodePtrImpl(defn)); array_interface.observe(fa_body); //FR(06/07/2011): aliasinfo was not set which caused segfault LoopTransformInterface::set_aliasInfo(&array_interface); // X. Loop normalization for all loops within body NormalizeForLoop(fa_body, AstNodePtrImpl(body)); for (Rose_STL_Container<SgNode*>::iterator iter = loops.begin(); iter!= loops.end(); iter++ ) { SgNode* current_loop = *iter; //X. Parallelize loop one by one // getLoopInvariant() will actually check if the loop has canonical forms // which can be handled by dependence analysis SgInitializedName* invarname = getLoopInvariant(current_loop); if (invarname != NULL) { hasOpenMP = ParallelizeOutermostLoop(current_loop, &array_interface, annot); } else // cannot grab loop index from a non-conforming loop, skip parallelization { if (enable_debug) cout<<"Skipping a non-canonical loop at line:"<<current_loop->get_file_info()->get_line()<<"..."<<endl; hasOpenMP = false; } }// end for loops } // end for-loop for declarations // insert omp.h if needed if (hasOpenMP && !enable_diff) { SageInterface::insertHeader("omp.h",PreprocessingInfo::after,false,root); if (enable_patch) generatePatchFile(sfile); } // compare user-defined and compiler-generated OmpAttributes if (enable_diff) diffUserDefinedAndCompilerGeneratedOpenMP(sfile); } //end for-loop of files // Qing's loop normalization is not robust enough to pass all tests //AstTests::runAllTests(project); release_analysis(); //project->unparse(); return backend (project); }
int main( int argc, char* argv[] ) { // Initialize and check compatibility. See rose::initialize ROSE_INITIALIZE; SgProject* project = frontend(argc,argv); AstTests::runAllTests(project); #if 0 // Output the graph so that we can see the whole AST graph, for debugging. generateAstGraph(project, 4000); #endif #if 1 printf ("Generate the dot output of the SAGE III AST \n"); generateDOT ( *project ); printf ("DONE: Generate the dot output of the SAGE III AST \n"); #endif // There are lots of way to write this, this is one simple approach; get all the function calls. std::vector<SgNode*> functionCalls = NodeQuery::querySubTree (project,V_SgFunctionCallExp); // Find the SgFunctionSymbol for snprintf so that we can reset references to "sprintf" to "snprintf" instead. // SgGlobal* globalScope = (*project)[0]->get_globalScope(); SgSourceFile* sourceFile = isSgSourceFile(project->get_fileList()[0]); ROSE_ASSERT(sourceFile != NULL); SgGlobal* globalScope = sourceFile->get_globalScope(); SgFunctionSymbol* snprintf_functionSymbol = globalScope->lookup_function_symbol("snprintf"); ROSE_ASSERT(snprintf_functionSymbol != NULL); // Iterate over the function calls to find the calls to "sprintf" for (unsigned long i = 0; i < functionCalls.size(); i++) { SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(functionCalls[i]); ROSE_ASSERT(functionCallExp != NULL); SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); if (functionSymbol != NULL) { SgName functionName = functionSymbol->get_name(); // printf ("Function being called: %s \n",functionName.str()); if (functionName == "sprintf") { // Now we have something to do! functionRefExp->set_symbol(snprintf_functionSymbol); // Now add the "n" argument SgExprListExp* functionArguments = functionCallExp->get_args(); SgExpressionPtrList & functionArgumentList = functionArguments->get_expressions(); // "sprintf" shuld have exactly 2 arguments (I guess the "..." don't count) printf ("functionArgumentList.size() = %zu \n",functionArgumentList.size()); // ROSE_ASSERT(functionArgumentList.size() == 2); SgExpressionPtrList::iterator i = functionArgumentList.begin(); // printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str()); SgVarRefExp* variableRefExp = isSgVarRefExp(*i); ROSE_ASSERT(variableRefExp != NULL); // printf ("variableRefExp->get_type() = %p = %s = %s \n",variableRefExp->get_type(),variableRefExp->get_type()->class_name().c_str(),SageInterface::get_name(variableRefExp->get_type()).c_str()); SgType* bufferType = variableRefExp->get_type(); SgExpression* bufferLengthExpression = NULL; switch(bufferType->variantT()) { case V_SgArrayType: { SgArrayType* arrayType = isSgArrayType(bufferType); bufferLengthExpression = arrayType->get_index(); break; } case V_SgPointerType: { // SgPointerType* pointerType = isSgPointerType(bufferType); SgInitializedName* variableDeclaration = variableRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(variableDeclaration != NULL); SgExpression* initializer = variableDeclaration->get_initializer(); if (initializer != NULL) { SgAssignInitializer* assignmentInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignmentInitializer != NULL); // This is the rhs of the initialization of the pointer (likely a malloc through a cast). // This assumes: buffer = (char*) malloc(bufferLengthExpression); SgExpression* initializationExpression = assignmentInitializer->get_operand(); ROSE_ASSERT(initializationExpression != NULL); SgCastExp* castExp = isSgCastExp(initializationExpression); ROSE_ASSERT(castExp != NULL); SgFunctionCallExp* functionCall = isSgFunctionCallExp(castExp->get_operand()); ROSE_ASSERT(functionCall != NULL); SgExprListExp* functionArguments = isSgExprListExp(functionCall->get_args()); bufferLengthExpression = functionArguments->get_expressions()[0]; ROSE_ASSERT(bufferLengthExpression != NULL); } else { printf ("Initializer not found, so no value for n in snprintf can be computed currently \n"); } break; } default: { printf ("Error: default reached in evaluation of buffer type = %p = %s \n",bufferType,bufferType->class_name().c_str()); ROSE_ASSERT(false); } } ROSE_ASSERT(bufferLengthExpression != NULL); // printf ("bufferLengthExpression = %p = %s = %s \n",bufferLengthExpression,bufferLengthExpression->class_name().c_str(),SageInterface::get_name(bufferLengthExpression).c_str()); // Jump over the first argument, the "n" is defined to be the 2nd argument (the rest are shifted one position). i++; // Build a deep copy of the expression used to define the static buffer (could be any complex expression). SgTreeCopy copy_help; SgExpression* bufferLengthExpression_copy = isSgExpression(bufferLengthExpression->copy(copy_help)); // Insert the "n" for the parameter list to work with "snprintf" instead of "sprintf" functionArgumentList.insert(i,bufferLengthExpression_copy); } } } } return backend(project); }