int main( int argc, char * argv[] ) { // If we want this translator to take specific options (beyond those defined // by ROSE) then insert command line processing for new options here. // To better support the stencil specification that might benifit from constant // folding, I have turned this ON is hte frontend. By default it is OFF so that // we can preserve source code as much as possible (original expression trees). // The Stencil DSL can be made to work in eithr setting, but this make sure that // dimension dependent processing of the stencil coeficients will be evaluated // to constants. I will turn this off (and thus use a less blunt axe) when the new // constant expression evaluation in ROSE is fixed to support more general types // than integer expresion (should be done by JP later today). // bool frontendConstantFolding = true; bool frontendConstantFolding = false; // Generate the ROSE AST. SgProject* project = frontend(argc,argv,frontendConstantFolding); ROSE_ASSERT(project != NULL); #if DEBUG_USING_DOT_GRAPHS // generateDOTforMultipleFile(*project); generateDOT(*project,"_before_transformation"); #endif #if DEBUG_USING_DOT_GRAPHS && 1 const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 12000; #endif #if DEBUG_USING_DOT_GRAPHS && 1 // Output an optional graph of the AST (the whole graph, of bounded complexity, when active) generateAstGraph(project,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH,"_before"); #endif // Build the inherited attribute Detection_InheritedAttribute inheritedAttribute; // Define the traversal DetectionTraversal shiftCalculus_DetectionTraversal; #if 0 printf ("Call the Detection traversal starting at the project (root) node of the AST \n"); #endif // Call the traversal starting at the project (root) node of the AST Detection_SynthesizedAttribute result = shiftCalculus_DetectionTraversal.traverse(project,inheritedAttribute); #if 0 printf ("Stencil Operator was transformed: %s \n",result.get_stencilOperatorTransformed() ? "true" : "false"); #endif ROSE_ASSERT(result.get_stencilOperatorTransformed() == false); #if 0 printf ("DONE: Call the Detection traversal starting at the project (root) node of the AST \n"); #endif // Build the inherited attribute StencilEvaluation_InheritedAttribute inheritedAttribute_stencilEval; // Define the traversal StencilEvaluationTraversal shiftCalculus_StencilEvaluationTraversal(shiftCalculus_DetectionTraversal); #if 0 printf ("Call the StencilEvaluation traversal starting at the project (root) node of the AST \n"); #endif // Call the traversal starting at the project (root) node of the AST StencilEvaluation_SynthesizedAttribute result_stencilEval = shiftCalculus_StencilEvaluationTraversal.traverse(project,inheritedAttribute_stencilEval); #if 0 printf ("Stencil Evaluation was transformed: %s \n",result_stencilEval.get_stencilOperatorTransformed() ? "true" : "false"); #endif ROSE_ASSERT(result_stencilEval.get_stencilOperatorTransformed() == false); #if 0 printf ("DONE: Call the StencilEvaluation traversal starting at the project (root) node of the AST \n"); #endif shiftCalculus_StencilEvaluationTraversal.displayStencil("After evaluation of stencil"); #if 1 printf ("Call generateStencilCode to generate example code \n"); #endif // Generate code from stencil data structure. bool generateLowlevelCode = true; generateStencilCode(shiftCalculus_StencilEvaluationTraversal,generateLowlevelCode); #if 1 printf ("DONE: Call generateStencilCode to generate example code \n"); #endif // AST consistency tests (optional for users, but this enforces more of our tests) AstTests::runAllTests(project); #if DEBUG_USING_DOT_GRAPHS printf ("Write out the DOT file after the transformation \n"); // generateDOTforMultipleFile(*project,"after_transformation"); generateDOT(*project,"_after_transformation"); printf ("DONE: Write out the DOT file after the transformation \n"); #endif #if DEBUG_USING_DOT_GRAPHS && 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 = 10000; generateAstGraph(project,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH,"_after"); #endif // Regenerate the source code but skip the call the to the vendor compiler. return backend(project); }
int main (int argc, char* argv[]) { // Main Function for default example ROSE Preprocessor // This is an example of a preprocessor that can be built with ROSE // Build the project object (AST) which we will fill up with multiple files and use as a // handle for all processing of the AST(s) associated with one or more source files. SgProject* sageProject = frontend(argc,argv); // DQ (7/20/2004): Added internal consistancy tests on AST AstTests::runAllTests(sageProject); // This is not needed here // FixSgProject(sageProject); bool changed = true; int count = 0; /* Inline one call at a time until all have been inlined. Loops on recursive code. */ while (changed) { changed = false; calls_to_inline.clear(); FindCallsVisitor().traverseInputFiles(sageProject, preorder); for (std::vector<SgFunctionCallExp*>::iterator i = calls_to_inline.begin(); i != calls_to_inline.end(); ++i) { // cout << (*i)->unparseToString() << endl; // generateAstGraph(sageProject, 400000); if (doInline(*i)) { changed = true; // AstTests::runAllTests(sageProject); break; } } ++count; #if 0 sageProject.unparse(); #endif // To prevent infinite loops if (count == 10) { break; } } #if 1 // Rename each variable declaration renameVariables(sageProject); #if 1 // Fold up blocks flattenBlocks(sageProject); // Clean up inliner-generated code cleanupInlinedCode(sageProject); #endif // Change members to public changeAllMembersToPublic(sageProject); // AstPDFGeneration().generateInputFiles(sageProject); // AstDOTGeneration().generateInputFiles(sageProject); #endif AstTests::runAllTests(sageProject); #if 0 // Output an optional graph of the AST (just the tree, when active) printf ("Generating a dot file... (ROSE Release Note: turn off output of dot files before committing code) \n"); generateDOT (*sageProject ); // generateAstGraph(project, 2000); #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(sageProject,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif return backend(sageProject); }
//! This removes the original expression tree from value expressions where it has been constant folded by EDG. void resetConstantFoldedValues( SgNode* node ) { // This is the initial default, it will be changed later to be an optional behavior. // Note that all unparsing will use the original expression tree and is verified to generate // correct for all of the regression tests in C and C++. The original expression trees are // saved in ROSE as part of supporting source to source work. One could conclude that the // original expression tree should always of never used as part of analysis, but not both // the constant folded value AND the original expression tree. // This is a temporary option, if false then we pass all tests and are consistent with historical configurations // of the ROSE AST, but it is inconsistent so we want to fix that (because it causes control flow problems). #if 1 // DQ (11/5/2012): Original value bool makeASTConstantFoldingExpressionConsistant = true; #else // DQ (11/5/2012): An experimental value while I play with the original expression trees. bool makeASTConstantFoldingExpressionConsistant = false; #endif #if 1 // This should be turned on except for internal testing. ROSE_ASSERT(makeASTConstantFoldingExpressionConsistant == true); #else printf ("WARNING: INTERNAL TESTING MODE: In resetConstantFoldedValues() \n"); ROSE_ASSERT(makeASTConstantFoldingExpressionConsistant == false); #endif // This will become an input option in the near future. Once they can be supported through all of the test codes. // The default is to use the original expression trees and replace the saved constant folded values in the AST. // Note that having both can lead to some confusion (e.g. in the control flow graph and analysis, so we select one // (no constant folded values) and make it an option to have the other (using constant folded values)). Note also // This this is EDG's definition of constant folding which is fairly aggressive. bool makeASTConstantFoldingExpressionConsistant_useOriginalExpressionTrees = true; // Constant folding is optional and can be specified as an optional parameter to "frontend()" function. // If set it sets a flag in the SgProject IR node. SgProject* project = isSgProject(node); if (project != NULL) { // Read the optional setting for constant folding in the frontend (only applied to C/C++ when using EDG). makeASTConstantFoldingExpressionConsistant_useOriginalExpressionTrees = (project->get_frontendConstantFolding() == false); } // ROSE_ASSERT(project != NULL); // printf ("project->get_frontendConstantFolding() = %s \n",(project->get_frontendConstantFolding() == true) ? "true" : "false"); #if 0 // SgProject* project = isSgProject(node); // 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; ROSE_ASSERT(project != NULL); if (project != NULL) { printf ("OUTPUT A GRAPH BEFORE CONSTANT FOLDING \n"); generateAstGraph(project,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH,"_before_constantfolding"); } #endif // printf ("In resetConstantFoldedValues(): makeASTConstantFoldingExpressionConsistant = %s \n",makeASTConstantFoldingExpressionConsistant ? "true" : "false"); if (makeASTConstantFoldingExpressionConsistant == true) { // printf ("In resetConstantFoldedValues(): makeASTConstantFoldingExpressionConsistant_useOriginalExpressionTrees = %s \n",makeASTConstantFoldingExpressionConsistant_useOriginalExpressionTrees ? "true" : "false"); if (makeASTConstantFoldingExpressionConsistant_useOriginalExpressionTrees == true) { // We want this to be the default for ROSE, since it matches what is output by the unparser and thus what // is required to pass all of the tests codes. // DQ (9/17/2011): This case fails dozens of test codes! // However, this case fails lot of tests codes due to the verification of all OriginalExpressionTree pointer // to be NULL and the name qualification tests (which fail as a result of the transformations to eliminate the // constant folded expressions and instead use the original expression trees). // printf ("WARNING: Testing current default to replace constant folded value with the original expression tree (future default setting for ROSE). \n"); // This replaces the constant folded value with the saved original expression tree (default). // This fails for test2011_113.C since we don't handle expressions in array types that contain // original expression trees. The reason is that original expression tree is not used to replace // the constant folded value and then (because of recent changes to the AST traversal) the variables // in the array types index expression is not processed for name qualification. // We need to either: // 1) uniformly define the how constants are replaced (everywhere) with their original expressions, or // 2) fix the name qualification to look into the original expression trees explicitly. // or both. // Note: If we fix #1 then we will not have to worry about #2, also I think that #1 defines a consistent // AST, where as #2 pushes the name qualification to simple work on the non-consistent AST. removeConstantFoldedValue(node); } else { // DQ (9/17/2011): This case fails only 2 test codes. Where the constant folded expression is unparsed but // does not generate the correct code. This may be a separate issue to investigate after we get the original // expression trees to be used (and the constant folding overridden; the other face below). // DQ (9/18/2011): Leave this warning message in place for now (we will likely remove it later). printf ("WARNING: Current default is to reset constant folding by removing the original expression tree. \n"); // This removes the original expression tree leaving the constant folded values (optional; not the default). // This fails for test2006_112.C (fails to compile unparsed code because the original expression is correct // code (if unparsed) while the constant folded expression is not correct code (if unparsed). In this case // the constant folded values are mostly useful for purposes of analysis. removeOriginalExpressionTrees(node); } // DQ (11/5/2012): I think this should be here rather than outside of this (put it back the way it was). // verifyOriginalExpressionTreesSetToNull(node); // DQ (4/26/2013): Moved here to permit makeASTConstantFoldingExpressionConsistant == false for debugging. // DQ (11/5/2012): Moved to inside of conditional (put this back the way it was). // verifyOriginalExpressionTreesSetToNull(node); } else { // DQ (4/26/2013): Added warning to support debugging of default argument handling in function call arguments. printf ("WARNING: makeASTConstantFoldingExpressionConsistant == false (temporary state for debugging mixed AST with constants and their original expression trees). \n"); } // DQ (4/26/2013): Commented out (see comment above). // DQ (11/5/2012): Moved to inside of conditional (put this back the way it was). verifyOriginalExpressionTreesSetToNull(node); }
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); }