void replaceExps(SgExpression* exp, SgVariableDeclaration* vardecl) { if (isSgVarRefExp(exp)) { return; } else if (isSgUnaryOp(exp)) { if (isSgMinusMinusOp(exp) || isSgPlusPlusOp(exp)) { SgExpression* operand = (isSgUnaryOp(exp))->get_operand(); SgExpression* operand_cpy = SageInterface::copyExpression(operand); std::cout << "operand: " << operand->class_name() << std::endl; SageInterface::replaceExpression(exp,operand_cpy); } return; } else if (isSgBinaryOp(exp)) { replaceExps(isSgBinaryOp(exp)->get_lhs_operand(), vardecl); replaceExps(isSgBinaryOp(exp)->get_rhs_operand(), vardecl); return; } else { return; } return; }
int main(int argc, char** argv) { SgProject* proj = frontend(argc,argv); SgFunctionDeclaration* mainDecl = SageInterface::findMain(proj); SgFunctionDefinition* mainDef = mainDecl->get_definition(); std::vector<SgNode*> ifExps; ifExps = NodeQuery::querySubTree(mainDef, V_SgIfStmt); for (int i = 0; i < ifExps.size(); i++) { getIfConds(isSgIfStmt(ifExps[i]), isSgScopeStatement(mainDef)); } std::vector<SgNode*> assignNodes = NodeQuery::querySubTree(mainDef, V_SgVariableDeclaration); std::cout << assignNodes.size() << " nodes found" << std::endl; std::vector<SgBinaryOp*> bin_ops; std::vector<SgUnaryOp*> un_ops; std::vector<SgNode*> other; std::vector<SgExpression*> results; for (std::vector<SgNode*>::iterator i = assignNodes.begin(); i != assignNodes.end(); i++) { SgVariableDeclaration* vdecl = isSgVariableDeclaration(*i); SgInitializedNamePtrList vlst = vdecl->get_variables(); SgInitializedName* initName = isSgInitializedName((*(vlst.begin()))); SgExpression* exp = isSgAssignInitializer(initName->get_initializer())->get_operand(); std::cout << exp->class_name() << std::endl; if (!isSgFunctionCallExp(exp)) { getExps(exp, isSgInitializedName(*i), results, 0); std::cout << "prefixes" << std::endl; for (int j = 0; j < prefixes.size(); j++) { SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(prefixes[j]); SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,true); std::cout << prefixes[j]->class_name() << std::endl; } std::cout << "results" << std::endl; for (int j = 0; j < results.size(); j++) { std::cout << results[j]->class_name() << std::endl; } std::cout << "postfixes" << std::endl; for (int j = 0; j < postfixes.size(); j++) { SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(postfixes[j]); SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,false); std::cout << postfixes[j]->class_name() << std::endl; } replaceExps(exp,vdecl); simplifyExps(exp); } } backend(proj); return 0; }
void instrumentRead(SgVarRefExp *varRef) { SgExpression *parent = isSgExpression(varRef->get_parent()); assert(parent != NULL); Sg_File_Info * file_info = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); SgCommaOpExp *commaOp = new SgCommaOpExp(file_info, beforeRead.getCallExp(), varRef, varRef->get_type()); SgUnaryOp *uOp = isSgUnaryOp(parent); if (uOp != NULL) { uOp->set_operand(commaOp); } else { SgBinaryOp *bOp = isSgBinaryOp(parent); if (bOp != NULL) { if (bOp->get_lhs_operand() == varRef) { bOp->set_lhs_operand(commaOp); } else { assert(bOp->get_rhs_operand() == varRef); bOp->set_rhs_operand(commaOp); } } else { SgExprListExp *expList = isSgExprListExp(parent); if (expList != NULL) { SgExpressionPtrList& expressions = expList->get_expressions(); for (SgExpressionPtrList::iterator iter = expressions.begin(); ; iter++) { assert (iter != expressions.end()); //element must be in the list! if (*iter == varRef) { //insert commaOp instead of varRef expressions.insert(expressions.erase(iter), commaOp); break; } } } else { //SgClassNameRefExp //SgConditionalExp //SgDeleteExp //go on implementing other cases cerr<<"unexpected parent expression: "<<parent->class_name()<<endl; assert (false); } } } }
void deleteOriginalExpressionTree(SgExpression* exp) { // This function deleted the existing original expression tree for an expression. SgExpression* originalExpressionTree = exp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 printf ("Removing the original expression tree from keyExpression = %p = %s originalExpressionTree = %p = %s \n", exp,exp->class_name().c_str(),originalExpressionTree,originalExpressionTree->class_name().c_str()); #endif // Remove the original expression tree... // delete value->get_originalExpressionTree(); // SageInterface::deleteAST(originalExpressionTree); SageInterface::deleteExpressionTreeWithOriginalExpressionSubtrees(originalExpressionTree); // Set the pointer to the original expression tree to NULL. exp->set_originalExpressionTree(NULL); } }
StencilEvaluation_InheritedAttribute StencilEvaluationTraversal::evaluateInheritedAttribute (SgNode* astNode, StencilEvaluation_InheritedAttribute inheritedAttribute ) { #if 0 printf ("In evaluateInheritedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif bool foundPairShiftDoubleConstructor = false; // This is for stencil specifications using vectors of points to represent offsets (not finished). // bool foundVariableDeclarationForStencilInput = false; double stencilCoeficientValue = 0.0; // StencilOffsetFSM offset; StencilOffsetFSM* stencilOffsetFSM = NULL; // We want to interogate the SgAssignInitializer, but we need to generality in the refactored function to use any SgInitializer (e.g. SgConstructorInitializer, etc.). SgInitializedName* initializedName = detectVariableDeclarationOfSpecificType (astNode,"Point"); if (initializedName != NULL) { // This is the code that is specific to the DSL (e.g. the semantics of getZeros() and getUnitv() functions). // So this may be the limit of what can be refactored to common DSL support code. // Or I can maybe do a second pass at atempting to refactor more code later. string name = initializedName->get_name(); SgInitializer* initializer = initializedName->get_initptr(); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); if (assignInitializer != NULL) { SgExpression* exp = assignInitializer->get_operand(); ROSE_ASSERT(exp != NULL); SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(exp); if (functionCallExp != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); string functionName = functionSymbol->get_name(); #if 0 printf ("functionName = %s \n",functionName.c_str()); #endif if (functionName == "getZeros") { // We leverage the semantics of known functions used to initialize "Point" objects ("getZeros" initialized the Point object to be all zeros). // In a stencil this will be the center point from which all other points will have non-zero offsets. // For a common centered difference discretization this will be the center point of the stencil. #if 0 printf ("Identified and interpreting the semantics of getZeros() function \n"); #endif stencilOffsetFSM = new StencilOffsetFSM(0,0,0); ROSE_ASSERT(stencilOffsetFSM != NULL); } if (functionName == "getUnitv") { // We leverage the semantics of known functions used to initialize "Point" objects // ("getUnitv" initializes the Point object to be a unit vector for a specific input dimention). // In a stencil this will be an ofset from the center point. #if 0 printf ("Identified and interpreting the semantics of getUnitv() function \n"); #endif // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); // ROSE_ASSERT(intVal != NULL); if (intVal != NULL) { int value = intVal->get_value(); #if 0 printf ("value = %d \n",value); #endif switch(value) { case 0: stencilOffsetFSM = new StencilOffsetFSM(1,0,0); break; case 1: stencilOffsetFSM = new StencilOffsetFSM(0,1,0); break; case 2: stencilOffsetFSM = new StencilOffsetFSM(0,0,1); break; default: { printf ("Error: default reached in switch: value = %d (for be value of 0, 1, or 2) \n",value); ROSE_ASSERT(false); } } ROSE_ASSERT(stencilOffsetFSM != NULL); // End of test for intVal != NULL } else { #if 0 printf ("functionArg = %p = %s \n",functionArg,functionArg->class_name().c_str()); #endif } } // ROSE_ASSERT(stencilOffsetFSM != NULL); } } } if (stencilOffsetFSM != NULL) { // Put the FSM into the map. #if 0 printf ("Put the stencilOffsetFSM = %p into the StencilOffsetMap using key = %s \n",stencilOffsetFSM,name.c_str()); #endif ROSE_ASSERT(StencilOffsetMap.find(name) == StencilOffsetMap.end()); // We have a choice of syntax to add the element to the map. // StencilOffsetMap.insert(pair<string,StencilOffsetFSM*>(name,stencilOffsetFSM)); StencilOffsetMap[name] = stencilOffsetFSM; } // new StencilOffsetFSM(); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Recognize member function calls on "Point" objects so that we can trigger events on those associated finite state machines. bool isTemplateClass = false; bool isTemplateFunctionInstantiation = false; SgInitializedName* initializedNameUsedToCallMemberFunction = NULL; SgFunctionCallExp* functionCallExp = detectMemberFunctionOfSpecificClassType(astNode,initializedNameUsedToCallMemberFunction,"Point",isTemplateClass,"operator*=",isTemplateFunctionInstantiation); if (functionCallExp != NULL) { // This is the DSL specific part (capturing the semantics of operator*= with specific integer values). // The name of the variable off of which the member function is called (variable has type "Point"). ROSE_ASSERT(initializedNameUsedToCallMemberFunction != NULL); string name = initializedNameUsedToCallMemberFunction->get_name(); // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); bool usingUnaryMinus = false; if (intVal == NULL) { SgMinusOp* minusOp = isSgMinusOp(functionArg); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; intVal = isSgIntVal(minusOp->get_operand()); } } ROSE_ASSERT(intVal != NULL); int value = intVal->get_value(); if (usingUnaryMinus == true) { value *= -1; } #if 0 printf ("value = %d \n",value); #endif // Look up the stencil offset finite state machine ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 stencilOffsetFSM->display("before multiply event"); #endif if (value == -1) { // Execute the event on the finte state machine to accumulate the state. stencilOffsetFSM->operator*=(-1); } else { printf ("Error: constant value other than -1 are not supported \n"); ROSE_ASSERT(false); } #if 0 stencilOffsetFSM->display("after multiply event"); #endif } // Detection of "pair<Shift,double>(xdir,ident)" defined as an event in the stencil finite machine model. // Actually, it is the Stencil that is create using the "pair<Shift,double>(xdir,ident)" that should be the // event so we first detect the SgConstructorInitializer. There is not other code similar to this which // has to test for the template arguments, so this has not yet refactored into the dslSupport.C file. // I will do this later since this is general support that could be resused in other DSL compilers. SgConstructorInitializer* constructorInitializer = isSgConstructorInitializer(astNode); if (constructorInitializer != NULL) { // DQ (10/20/2014): This can sometimes be NULL. // ROSE_ASSERT(constructorInitializer->get_class_decl() != NULL); SgClassDeclaration* classDeclaration = constructorInitializer->get_class_decl(); // ROSE_ASSERT(classDeclaration != NULL); if (classDeclaration != NULL) { #if 0 printf ("constructorInitializer = %p class name = %s \n",constructorInitializer,classDeclaration->get_name().str()); #endif SgTemplateInstantiationDecl* templateInstantiationDecl = isSgTemplateInstantiationDecl(classDeclaration); // ROSE_ASSERT(templateInstantiationDecl != NULL); #if 0 if (templateInstantiationDecl != NULL) { printf ("constructorInitializer = %p name = %s template name = %s \n",constructorInitializer,templateInstantiationDecl->get_name().str(),templateInstantiationDecl->get_templateName().str()); } #endif // if (classDeclaration->get_name() == "pair") if (templateInstantiationDecl != NULL && templateInstantiationDecl->get_templateName() == "pair") { // Look at the template parameters. #if 0 printf ("Found template instantiation for pair \n"); #endif SgTemplateArgumentPtrList & templateArgs = templateInstantiationDecl->get_templateArguments(); if (templateArgs.size() == 2) { // Now look at the template arguments and check that they represent the pattern that we are looking for in the AST. // It is not clear now flexible we should be, at present shift/coeficent pairs must be specified exactly one way. SgType* type_0 = templateArgs[0]->get_type(); SgType* type_1 = templateArgs[1]->get_type(); if ( type_0 != NULL && type_1 != NULL) { SgClassType* classType_0 = isSgClassType(type_0); // ROSE_ASSERT(classType_0 != NULL); if (classType_0 != NULL) { SgClassDeclaration* classDeclarationType_0 = isSgClassDeclaration(classType_0->get_declaration()); ROSE_ASSERT(classDeclarationType_0 != NULL); #if 0 printf ("templateArgs[0]->get_name() = %s \n",classDeclarationType_0->get_name().str()); printf ("templateArgs[1]->get_type()->class_name() = %s \n",type_1->class_name().c_str()); #endif bool foundShiftExpression = false; bool foundStencilCoeficient = false; // We might want to be more flexiable about the type of the 2nd parameter (allow SgTypeFloat, SgTypeComplex, etc.). if (classDeclarationType_0->get_name() == "Shift" && type_1->variant() == V_SgTypeDouble) { // Found a pair<Shift,double> input for a stencil. #if 0 printf ("##### Found a pair<Shift,double>() input for a stencil input \n"); #endif // ***************************************************************************************************** // Look at the first parameter to the pair<Shift,double>() constructor. // ***************************************************************************************************** SgExpression* stencilOffset = constructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(stencilOffset != NULL); #if 0 printf ("stencilOffset = %p = %s \n",stencilOffset,stencilOffset->class_name().c_str()); #endif SgConstructorInitializer* stencilOffsetConstructorInitializer = isSgConstructorInitializer(stencilOffset); if (stencilOffsetConstructorInitializer != NULL) { // This is the case of a Shift being constructed implicitly from a Point (doing so more directly would be easier to make sense of in the AST). #if 0 printf ("!!!!! Looking for the stencil offset \n"); #endif ROSE_ASSERT(stencilOffsetConstructorInitializer->get_class_decl() != NULL); SgClassDeclaration* stencilOffsetClassDeclaration = stencilOffsetConstructorInitializer->get_class_decl(); ROSE_ASSERT(stencilOffsetClassDeclaration != NULL); #if 0 printf ("stencilOffsetConstructorInitializer = %p class name = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration->get_name().str()); printf ("stencilOffsetConstructorInitializer = %p class = %p = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration,stencilOffsetClassDeclaration->class_name().c_str()); #endif // This should not be a template instantiation (the Shift is defined to be a noo-template class declaration, not a template class declaration). SgTemplateInstantiationDecl* stencilOffsetTemplateInstantiationDecl = isSgTemplateInstantiationDecl(stencilOffsetClassDeclaration); ROSE_ASSERT(stencilOffsetTemplateInstantiationDecl == NULL); if (stencilOffsetClassDeclaration != NULL && stencilOffsetClassDeclaration->get_name() == "Shift") { // Now we know that the type associated with the first template parameter is associated with the class "Shift". // But we need so also now what the first parametr is associate with the constructor initializer, since it will // be the name of the variable used to interprete the stencil offset (and the name of the variable will be the // key into the map of finite machine models used to accumulate the state of the stencil offsets that we accumulate // to build the stencil. // Now we need the value of the input (computed using it's fine state machine). SgExpression* inputToShiftConstructor = stencilOffsetConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToShiftConstructor != NULL); SgConstructorInitializer* inputToShiftConstructorInitializer = isSgConstructorInitializer(inputToShiftConstructor); if (stencilOffsetConstructorInitializer != NULL) { SgExpression* inputToPointConstructor = inputToShiftConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToPointConstructor != NULL); // This should be a SgVarRefExp (if we strictly follow the stencil specification rules (which are not written down yet). SgVarRefExp* inputToPointVarRefExp = isSgVarRefExp(inputToPointConstructor); if (inputToPointVarRefExp != NULL) { #if 0 printf ("Found varRefExp in bottom of chain of constructors \n"); #endif SgVariableSymbol* variableSymbolForOffset = isSgVariableSymbol(inputToPointVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForOffset != NULL); SgInitializedName* initializedNameForOffset = variableSymbolForOffset->get_declaration(); ROSE_ASSERT(initializedNameForOffset != NULL); SgInitializer* initializer = initializedNameForOffset->get_initptr(); ROSE_ASSERT(initializer != NULL); #if 0 printf ("Found initializedName: name = %s in bottom of chain of constructors: initializer = %p = %s \n",initializedNameForOffset->get_name().str(),initializer,initializer->class_name().c_str()); #endif // Record the name to be used as a key into the map of "StencilOffset" finite state machines. SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); string name = initializedNameForOffset->get_name(); // Look up the current state in the finite state machine for the "Point". // Check that this is a previously defined stencil offset. ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); // StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { printf ("What is this expression: inputToPointConstructor = %p = %s \n",inputToPointConstructor,inputToPointConstructor->class_name().c_str()); ROSE_ASSERT(false); } } #if 0 printf ("Found Shift type \n"); #endif foundShiftExpression = true; } #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { // This case for the specification of a Shift in the first argument is not yet supported (need an example of this). printf ("This case of using a shift is not a part of what is supported \n"); } // ***************************************************************************************************** // Look at the second parameter to the pair<Shift,double>(first_parameter,second_parameter) constructor. // ***************************************************************************************************** SgExpression* stencilCoeficent = constructorInitializer->get_args()->get_expressions()[1]; ROSE_ASSERT(stencilCoeficent != NULL); SgVarRefExp* stencilCoeficentVarRefExp = isSgVarRefExp(stencilCoeficent); if (stencilCoeficentVarRefExp != NULL) { // Handle the case where this is a constant SgVarRefExp and the value is available in the declaration. SgVariableSymbol* variableSymbolForConstant = isSgVariableSymbol(stencilCoeficentVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForConstant != NULL); SgInitializedName* initializedNameForConstant = variableSymbolForConstant->get_declaration(); ROSE_ASSERT(initializedNameForConstant != NULL); SgInitializer* initializer = initializedNameForConstant->get_initptr(); ROSE_ASSERT(initializer != NULL); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); SgValueExp* valueExp = isSgValueExp(assignInitializer->get_operand()); bool usingUnaryMinus = false; // ROSE_ASSERT(valueExp != NULL); if (valueExp == NULL) { SgExpression* operand = assignInitializer->get_operand(); SgMinusOp* minusOp = isSgMinusOp(operand); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; valueExp = isSgValueExp(minusOp->get_operand()); } } SgDoubleVal* doubleVal = isSgDoubleVal(valueExp); // ROSE_ASSERT(doubleVal != NULL); double value = 0.0; if (doubleVal == NULL) { // Call JP's function to evaluate the constant expression. ROSE_ASSERT(valueExp == NULL); ROSE_ASSERT(stencilCoeficent != NULL); DSL_Support::const_numeric_expr_t const_expression = DSL_Support::evaluateConstNumericExpression(stencilCoeficent); if (const_expression.hasValue_ == true) { ROSE_ASSERT(const_expression.isIntOnly_ == false); value = const_expression.value_; printf ("const expression evaluated to value = %4.2f \n",value); } else { printf ("constnat value expression could not be evaluated to a constant \n"); ROSE_ASSERT(false); } } else { #if 1 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif value = (usingUnaryMinus == false) ? doubleVal->get_value() : -(doubleVal->get_value()); } #if 1 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { // When we turn on constant folding in the frontend we eveluate directly to a SgDoubleVal. SgDoubleVal* doubleVal = isSgDoubleVal(stencilCoeficent); if (doubleVal != NULL) { ROSE_ASSERT(doubleVal != NULL); #if 0 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif double value = doubleVal->get_value(); #if 0 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { printf ("Error: second parameter in pair for stencil is not a SgVarRefExp (might be explicit value not yet supported) \n"); printf (" --- stencilCoeficent = %p = %s \n",stencilCoeficent,stencilCoeficent->class_name().c_str()); ROSE_ASSERT(false); } } } #if 0 printf ("foundShiftExpression = %s \n",foundShiftExpression ? "true" : "false"); printf ("foundStencilCoeficient = %s \n",foundStencilCoeficient ? "true" : "false"); #endif if (foundShiftExpression == true && foundStencilCoeficient == true) { #if 0 printf ("Found pair<Shift,double>() constructor expression! \n"); #endif foundPairShiftDoubleConstructor = true; } // End of test for classType_0 != NULL } } } } else { #if 0 printf ("This is not a SgConstructorInitializer for the pair templated class \n"); #endif } // End of test for classDeclaration != NULL } } #if 0 printf ("foundPairShiftDoubleConstructor = %s \n",foundPairShiftDoubleConstructor ? "true" : "false"); #endif if (foundPairShiftDoubleConstructor == true) { // This is the recognition of an event for one of the finite state machines we implement to evaluate the stencil at compile time. #if 0 printf ("In evaluateInheritedAttribute(): found pair<Shift,double>() constructor expression! \n"); printf (" --- stencilOffsetFSM = %p \n",stencilOffsetFSM); printf (" --- stencilCoeficientValue = %f \n",stencilCoeficientValue); #endif ROSE_ASSERT(stencilOffsetFSM != NULL); inheritedAttribute.stencilOffsetFSM = stencilOffsetFSM; inheritedAttribute.stencilCoeficientValue = stencilCoeficientValue; #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Construct the return attribute from the modified input attribute. return StencilEvaluation_InheritedAttribute(inheritedAttribute); }
InheritedAttribute visitorTraversal::evaluateInheritedAttribute(SgNode* n, InheritedAttribute inheritedAttribute) { Sg_File_Info* s = n->get_startOfConstruct(); Sg_File_Info* e = n->get_endOfConstruct(); Sg_File_Info* f = n->get_file_info(); for(int x=0; x < inheritedAttribute.depth; ++x) { printf(" "); } if(s != NULL && e != NULL && !isSgLabelStatement(n)) { printf ("%s (%d, %d, %d)->(%d, %d): %s",n->sage_class_name(),s->get_file_id()+1,s->get_raw_line(),s->get_raw_col(),e->get_raw_line(),e->get_raw_col(), verbose ? n->unparseToString().c_str() : "" ); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } SgExprStatement * exprStmt = isSgExprStatement(n); if(exprStmt != NULL) { printf(" [expr type: %s]", exprStmt->get_expression()->sage_class_name()); SgFunctionCallExp * fcall = isSgFunctionCallExp(exprStmt->get_expression()); if(fcall != NULL) { SgExpression * funcExpr = fcall->get_function(); if(funcExpr != NULL) { printf(" [function expr: %s]", funcExpr->class_name().c_str()); } SgFunctionDeclaration * fdecl = fcall->getAssociatedFunctionDeclaration(); if(fdecl != NULL) { printf(" [called function: %s]", fdecl->get_name().str()); } } } if(isSgFunctionDeclaration(n)) { printf(" [declares function: %s]", isSgFunctionDeclaration(n)->get_name().str()); } SgStatement * sgStmt = isSgStatement(n); if(sgStmt != NULL) { printf(" [scope: %s, %p]", sgStmt->get_scope()->sage_class_name(), sgStmt->get_scope()); } //SgLabelStatement * lblStmt = isSgLabelStatement(n); //if(lblStmt != NULL) { // SgStatement * lblStmt2 = lblStmt->get_statement(); //} } else if (f != NULL) { SgInitializedName * iname = isSgInitializedName(n); if(iname != NULL) { SgType* inameType = iname->get_type(); printf("%s (%d, %d, %d): %s [type: %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(),n->unparseToString().c_str(),inameType->class_name().c_str()); SgDeclarationStatement * ds = isSgDeclarationStatement(iname->get_parent()); if(ds != NULL) { if(ds->get_declarationModifier().get_storageModifier().isStatic()) { printf(" static"); } } SgArrayType * art = isSgArrayType(iname->get_type()); if(art != NULL) { printf(" %d", art->get_rank()); } printf("]"); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } else { printf("%s (%d, %d, %d): %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(), verbose ? n->unparseToString().c_str() : ""); } } else { printf("%s : %s", n->sage_class_name(), verbose ? n->unparseToString().c_str() : ""); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } printf(" succ# %lu", n->get_numberOfTraversalSuccessors()); printf("\n"); return InheritedAttribute(inheritedAttribute.depth+1); }
void VerifyOriginalExpressionTreesSetToNull::visit ( SgNode* node ) { // This traversal is used to verify that all of the original expression trees in the AST have // been either deleted (optional) or used to replace the constant folded values (the default // for the ROSE AST so that we can preserve the greatest amount of source-to-source detail). // Note that it can detect problems that are due to orphaned expressions in the AST. // An example is test2011_138.C where the multidimensional array indexing causes and orphaned // expression to be created and it has a original expression tree. Since the orphaned expression // can't be reached we can eliminate the original expression tree. The bug in ROSE is that there // is an orphaned expression tree not that there is a remaining original expression tree. // We need a mechanism to detect nodes that exist in the AST and are not pointed to by any other // IR node (and then we have to decide if parent pointers count). ROSE_ASSERT(node != NULL); // printf ("In VerifyOriginalExpressionTreesSetToNull::visit(): node = %s \n",node->class_name().c_str()); SgExpression* exp = isSgExpression(node); if (exp != NULL) { SgExpression* originalExpressionTree = exp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION printf ("Error: there is a valid originalExpressionTree = %p = %s on node = %p = %s \n",originalExpressionTree,originalExpressionTree->class_name().c_str(),exp,exp->class_name().c_str()); #endif } #if 0 // Liao debugging 11/13/2012 ROSE_ASSERT(originalExpressionTree == NULL); #endif // Allow us to ignore the cases of originalExpressionTrees hidden in array types. // I want to narrow down the failing tests codes to eliminate this case which is handled separately. if (originalExpressionTree != NULL) { #if 0 SgNode* parent = exp; // Note that test2011_121.C fails to be either a SgArrayType or a SgVariableDefinition (failing in some part of "complex" header file). // test2005_203.C demonstrates the use of constant folding in bitfield specifications. // while (parent != NULL && isSgArrayType(parent) == NULL) while (parent != NULL && isSgArrayType(parent) == NULL && isSgVariableDefinition(parent) == NULL) { parent = parent->get_parent(); } if (isSgArrayType(parent) == NULL) { printf ("So what is the parent: parent = %p = %s \n",parent, (parent != NULL) ? parent->class_name().c_str() : "NULL"); } ROSE_ASSERT(isSgArrayType(parent) != NULL || isSgVariableDefinition(parent) != NULL); #else #ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION printf ("In VerifyOriginalExpressionTreesSetToNull(): originalExpressionTree = %p = %s on node = %p = %s Ingoring originalExpressionTree != NULL \n", originalExpressionTree,originalExpressionTree->class_name().c_str(),exp,exp->class_name().c_str()); #endif #endif } } }
void DetectOriginalExpressionTreeTraversal::visit ( SgNode* node ) { // This is used to operate on the AST and on subtree that are hidden in SgArrayType and bitfile expressions. ROSE_ASSERT(node != NULL); // printf ("In DetectOriginalExpressionTreeTraversal::visit(): node = %s \n",node->class_name().c_str()); SgExpression* exp = isSgExpression(node); if (exp != NULL) { SgExpression* originalExpressionTree = exp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { printf ("Error: DetectOriginalExpressionTreeTraversal::visit() -- there is a valid originalExpressionTree = %p = %s on node = %p = %s \n",originalExpressionTree,originalExpressionTree->class_name().c_str(),exp,exp->class_name().c_str()); ROSE_ASSERT(originalExpressionTree->get_startOfConstruct() != NULL); originalExpressionTree->get_startOfConstruct()->display("Error: DetectOriginalExpressionTreeTraversal::visit()"); } // DQ (6/12/2013): Commented out as part of EDG 4.7 testing. #if 0 ROSE_ASSERT(originalExpressionTree == NULL); #endif } }
void fixupReferencesToGlobalVariables ( Rose_STL_Container<SgVarRefExp*> & variableReferenceList, SgVariableSymbol* globalClassVariableSymbol) { // Now fixup the SgVarRefExp to reference the global variables through a struct for (Rose_STL_Container<SgVarRefExp*>::iterator var = variableReferenceList.begin(); var != variableReferenceList.end(); var++) { assert(*var != NULL); // printf ("Variable reference for %s \n",(*var)->get_symbol()->get_declaration()->get_name().str()); SgNode* parent = (*var)->get_parent(); assert(parent != NULL); // If this is not an expression then is likely a meaningless statement such as ("x;") SgExpression* parentExpression = isSgExpression(parent); assert(parentExpression != NULL); // Build the reference through the global class variable ("x" --> "AMPI_globals.x") // Build source position informaiton (marked as transformation) Sg_File_Info* fileInfo = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); assert(fileInfo != NULL); // Build "AMPI_globals" SgExpression* lhs = new SgVarRefExp(fileInfo,globalClassVariableSymbol); assert(lhs != NULL); // Build "AMPI_globals.x" from "x" SgDotExp* globalVariableReference = new SgDotExp(fileInfo,lhs,*var); assert(globalVariableReference != NULL); if (parentExpression != NULL) { // Introduce reference to *var through the data structure // case of binary operator SgUnaryOp* unaryOperator = isSgUnaryOp(parentExpression); if (unaryOperator != NULL) { unaryOperator->set_operand(globalVariableReference); } else { // case of binary operator SgBinaryOp* binaryOperator = isSgBinaryOp(parentExpression); if (binaryOperator != NULL) { // figure out if the *var is on the lhs or the rhs if (binaryOperator->get_lhs_operand() == *var) { binaryOperator->set_lhs_operand(globalVariableReference); } else { assert(binaryOperator->get_rhs_operand() == *var); binaryOperator->set_rhs_operand(globalVariableReference); } } else { // ignore these cases for now! switch(parentExpression->variantT()) { // Where the variable appers in the function argument list the parent is a SgExprListExp case V_SgExprListExp: { printf ("Sorry not implemented, case of global variable in function argument list ... \n"); assert(false); break; } case V_SgInitializer: case V_SgRefExp: case V_SgVarArgOp: default: { printf ("Error: default reached in switch parentExpression = %p = %s \n",parentExpression,parentExpression->class_name().c_str()); assert(false); } } } } } } }
void RemoveConstantFoldedValue::handleTheSynthesizedAttribute( SgNode* node, const RemoveConstantFoldedValueSynthesizedAttribute & i ) { SgExpression* value = isSgExpression(i.node); if (value != NULL) { SgExpression* originalExpressionTree = value->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 printf ("Found an originalExpressionTree = %p = %s \n",originalExpressionTree,originalExpressionTree->class_name().c_str()); #endif if (node == value->get_parent()) { // What kind of IR node are we at presently? Replace the expression representing the SgValueExp with the Expression representing the original subtree. #if 0 printf ("Current IR node with SgExpression child = %p = %s originalExpressionTree = %p = %s \n",node,node->class_name().c_str(),originalExpressionTree,originalExpressionTree->class_name().c_str()); #endif bool traceReplacement = true; ConstantFoldedValueReplacer r(traceReplacement, value); node->processDataMemberReferenceToPointers(&r); } else { printf ("*** Strange case of child attribute not having the current node as a parent child = %p = %s originalExpressionTree = %p = %s \n",node,node->class_name().c_str(),originalExpressionTree,originalExpressionTree->class_name().c_str()); } } } }
void ConstantFoldedValueReplacer::operator()(SgNode*& key, const SgName & debugStringName, bool /* traverse */ traceReplacement) { // This function is used to replace the expression in an AST node and avoids explicitly handling all of the cases // of where an IR node can exist in the AST (in this case expressions containing an opriginal expression tree could // be in a lot of locations). // Note that the key will be a reference to the pointer for each data member of the IR node where: // node->processDataMemberReferenceToPointers(&r); // is called. #if 0 printf ("Inside of ConstantFoldedValueReplacer::operator() key = %p = %s = %s node = %p = %s = %s \n", key,(key != NULL) ? key->class_name().c_str() : "NULL",(key != NULL) ? SageInterface::get_name(key).c_str() : "NULL", targetNode,(targetNode != NULL) ? targetNode->class_name().c_str() : "NULL",(targetNode != NULL) ? SageInterface::get_name(targetNode).c_str() : "NULL"); #endif if (key != NULL) { // Now reset the pointer to the subtree identified as redundent with a // subtree in the original AST to the subtree in the original (merged) AST. // Note: targetNode is the IR node to be replaced (set in the ConstantFoldedValueReplacer constructor call). if (key == targetNode) { #if 0 printf ("Note that key == originalNode \n"); #endif SgExpression* keyExpression = isSgExpression(key); // DQ (9/17/2011): We don't want to eliminate references to enum values (see test2005_194.C). // Though I wonder if it could be that we are not distinguishing the enum value and the // values of the enum variables (the order of the fields in the enum declaration). if (isSgEnumVal(keyExpression) == NULL) { if (keyExpression != NULL) { #if 0 printf ("Note that key is a valid expression keyExpression->get_originalExpressionTree() = %p \n",keyExpression->get_originalExpressionTree()); #endif if (keyExpression->get_originalExpressionTree() != NULL) { #if 0 printf ("key contains a originalExpressionTree = %p = %s \n",keyExpression->get_originalExpressionTree(),keyExpression->get_originalExpressionTree()->class_name().c_str()); #endif // DQ (10/8/2011): Added support for chains of expression trees. // while (keyExpression->get_originalExpressionTree()->get_originalExpressionTree() != NULL) while (keyExpression->get_originalExpressionTree()->get_originalExpressionTree() != NULL && isSgEnumVal(keyExpression->get_originalExpressionTree()) == NULL) { SgExpression* nestedOriginalExpressionTree = keyExpression->get_originalExpressionTree(); ROSE_ASSERT(nestedOriginalExpressionTree != NULL); #if 0 printf ("Found a chain of original expression trees (iterate to find the end of the chain: keyExpression = %p = %s keyExpression->get_originalExpressionTree() = %p = %s \n", keyExpression,keyExpression->class_name().c_str(),nestedOriginalExpressionTree,nestedOriginalExpressionTree->class_name().c_str()); #endif keyExpression = nestedOriginalExpressionTree; } // If this is an enum value, then we don't want the original expression tree (which // will otherwise be substituted into such places as SgCaseOptionStmt nodes, etc.). SgEnumVal* enumValue = isSgEnumVal(keyExpression->get_originalExpressionTree()); if (enumValue != NULL) { #if 0 printf ("Detected case of enumValue = %p \n",enumValue); #endif if (enumValue->get_originalExpressionTree()) { #if 0 printf ("Deleting the original expression in the nested enumValue \n"); #endif deleteOriginalExpressionTree(enumValue->get_originalExpressionTree()); enumValue->set_originalExpressionTree(NULL); } } ROSE_ASSERT(keyExpression->get_originalExpressionTree() != NULL); key = keyExpression->get_originalExpressionTree(); ROSE_ASSERT(key != NULL); // Set the parent node ROSE_ASSERT(keyExpression->get_originalExpressionTree() != NULL); keyExpression->get_originalExpressionTree()->set_parent(targetNode->get_parent()); SgExpression* targetExpression = isSgExpression(targetNode); // Clear the originalExpressionTree targetExpression->set_originalExpressionTree(NULL); ROSE_ASSERT(targetExpression->get_originalExpressionTree() == NULL); targetExpression->set_parent(NULL); // DQ (9/24/2011): This can be an expression tree (more than just a single IR node (see test2011_140.C). // delete targetNode; SageInterface::deleteAST(targetExpression); // Reset the pointer to avoid any dangling pointer problems. targetNode = NULL; } } else { #if 0 printf ("key is not a SgExpression \n"); #endif } } else { // For the case of a SgEnumVal, don't use the original expression tree (see test2005_194.C) // The original expression tree holds the value used for the enum field, instead of the // reference to the correct enum field). #if 0 printf ("ENUM VALUE special handling: we call deleteOriginalExpressionTree(keyExpression = %p) \n",keyExpression); #endif deleteOriginalExpressionTree(keyExpression); } } else { #if 0 printf ("key != originalNode \n"); #endif } } else { #if 0 printf ("key == NULL \n"); #endif } #if 0 printf ("Leaving ConstantFoldedValueReplacer::operator() new reset key = %p = %s \n",key,(key != NULL) ? key->class_name().c_str() : "NULL"); #endif }
void visitorTraversal::visit(SgNode* n) { SgFile* file = isSgFile(n); if (file != NULL) { filename = file->get_sourceFileNameWithPath(); } // On each statement node and output it's position. SgStatement* statement = isSgStatement(n); bool outputStatement = (statement != NULL) ? true : false; // Check for the statement to exist in the input source file outputStatement = outputStatement && (statement->get_file_info()->get_filenameString() == filename); // Skip SgGlobal IR nodes outputStatement = outputStatement && (isSgGlobal(statement) == NULL); if (outputStatement == true) { AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo(); if (comments != NULL) { // printf ("Found attached comments (to IR node at %p of type: %s): \n",statement,statement->class_name().c_str()); // int counter = 0; AttachedPreprocessingInfoType::iterator i; for (i = comments->begin(); i != comments->end(); i++) { #if 0 printf (" Attached Comment #%d in file %s (relativePosition=%s): classification %s :\n%s\n", counter++,(*i)->get_file_info()->get_filenameString().c_str(), ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after", PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective()).c_str(), (*i)->getString().c_str()); #endif // Mark comments and CPP directives a few different colors. int startingLineNumber = (*i)->get_file_info()->get_line(); int startingColumnNumber = (*i)->get_file_info()->get_col(); // Subtract 1 from number of lines to avoid over counting the current line. int endingLineNumber = startingLineNumber + ((*i)->getNumberOfLines() - 1); int endingColumnNumber = (*i)->getColumnNumberOfEndOfString(); string color = directiveTypeColor((*i)->getTypeOfDirective()); #if 0 printf ("%d,%d,%s,%d,%d\n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } } else { // printf ("No attached comments (at %p of type: %s): \n",statement,statement->sage_class_name()); } ROSE_ASSERT(statement->get_startOfConstruct() != NULL); int startingLineNumber = statement->get_startOfConstruct()->get_line(); int startingColumnNumber = statement->get_startOfConstruct()->get_col(); if (statement->get_endOfConstruct() == NULL) { printf ("Error: statement->get_endOfConstruct() == NULL (statement = %p = %s) \n",statement,statement->class_name().c_str()); } ROSE_ASSERT(statement->get_endOfConstruct() != NULL); int endingLineNumber = statement->get_endOfConstruct()->get_line(); int endingColumnNumber = statement->get_endOfConstruct()->get_col(); // Catch errors (likely compiler generate IR node or NULL file) if (endingLineNumber == 0) { endingLineNumber = startingLineNumber; endingColumnNumber = startingColumnNumber; } #if 0 // Mark all statements blue string color = "blue"; if (isSgScopeStatement(statement) != NULL) color = "red"; #else string color = nodeColor(statement); #endif #if 0 printf ("%d,%d,%s,%d,%d %s = %p \n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber,statement->class_name().c_str(),statement); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } // On each statement node and output it's position. SgExpression* expression = isSgExpression(n); bool outputExpression = (expression != NULL) ? true : false; // Check for the statement to exist in the input source file outputExpression = outputExpression && (expression->get_file_info()->get_filenameString() == filename); if (outputExpression == true) { // Currently we don't attach comments to expressions (as I recall). AttachedPreprocessingInfoType* comments = expression->getAttachedPreprocessingInfo(); ROSE_ASSERT(comments == NULL); ROSE_ASSERT(expression->get_startOfConstruct() != NULL); int startingLineNumber = expression->get_startOfConstruct()->get_line(); int startingColumnNumber = expression->get_startOfConstruct()->get_col(); // For expressions I would like to be a bit more tollerant of a few mistakes. if (expression->get_endOfConstruct() == NULL) { printf ("Error: expression->get_endOfConstruct() == NULL (expression = %p = %s) \n",expression,expression->class_name().c_str()); } // ROSE_ASSERT(expression->get_endOfConstruct() != NULL); int endingLineNumber = startingLineNumber; int endingColumnNumber = startingColumnNumber; if (expression->get_endOfConstruct() != NULL) { endingLineNumber = expression->get_endOfConstruct()->get_line(); endingColumnNumber = expression->get_endOfConstruct()->get_col(); } // Catch errors (likely compiler generate IR node or NULL file) if (endingLineNumber == 0) { endingLineNumber = startingLineNumber; endingColumnNumber = startingColumnNumber; } string color = nodeColor(expression); #if 0 printf ("%d,%d,%s,%d,%d %s = %p \n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber,expression->class_name().c_str(),expression); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } // On each statement node and output it's position. SgInitializedName* initializedName = isSgInitializedName(n); bool outputInitializedName = (initializedName != NULL) ? true : false; // Check for the statement to exist in the input source file outputInitializedName = outputInitializedName && (initializedName->get_file_info()->get_filenameString() == filename); if (outputInitializedName == true) { // Currently we don't attach comments to SgInitializedName IR nodes (as I recall). // AttachedPreprocessingInfoType* comments = initializedName->getAttachedPreprocessingInfo(); // ROSE_ASSERT(comments == NULL); ROSE_ASSERT(initializedName->get_startOfConstruct() != NULL); int startingLineNumber = initializedName->get_startOfConstruct()->get_line(); int startingColumnNumber = initializedName->get_startOfConstruct()->get_col(); #if 0 // For SgInitializedName I would like to be a bit more tollerant of a few mistakes. if (initializedName->get_endOfConstruct() == NULL) { printf ("Note: initializedName->get_endOfConstruct() == NULL is OK (initializedName = %p = %s) \n",initializedName,initializedName->class_name().c_str()); } // ROSE_ASSERT(initializedName->get_endOfConstruct() != NULL); #endif int endingLineNumber = startingLineNumber; int endingColumnNumber = startingColumnNumber; if (initializedName->get_endOfConstruct() != NULL) { endingLineNumber = initializedName->get_endOfConstruct()->get_line(); endingColumnNumber = initializedName->get_endOfConstruct()->get_col(); } // Catch errors (likely compiler generate IR node or NULL file) if (endingLineNumber == 0) { endingLineNumber = startingLineNumber; endingColumnNumber = startingColumnNumber; } string color = nodeColor(initializedName); #if 0 // This is redundant I/O for debugging. printf ("%d,%d,%s,%d,%d %s = %p \n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber,initializedName->class_name().c_str(),initializedName); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } }
// Do finite differencing on one expression within one context. The expression // must be defined and valid within the entire body of root. The rewrite rules // are used to simplify expressions. When a variable var is updated from // old_value to new_value, an expression of the form (var, (old_value, // new_value)) is created and rewritten. The rewrite rules may either produce // an arbitrary expression (which will be used as-is) or one of the form (var, // (something, value)) (which will be changed to (var = value)). void doFiniteDifferencingOne(SgExpression* e, SgBasicBlock* root, RewriteRule* rules) { SgStatementPtrList& root_stmts = root->get_statements(); SgStatementPtrList::iterator i; for (i = root_stmts.begin(); i != root_stmts.end(); ++i) { if (expressionComputedIn(e, *i)) break; } if (i == root_stmts.end()) return; // Expression is not used within root, so quit vector<SgVariableSymbol*> used_symbols = SageInterface::getSymbolsUsedInExpression(e); SgName cachename = "cache_fd__"; cachename << ++SageInterface::gensym_counter; SgVariableDeclaration* cachedecl = new SgVariableDeclaration(SgNULL_FILE, cachename, e->get_type(),0 /* new SgAssignInitializer(SgNULL_FILE, e) */); SgInitializedName* cachevar = cachedecl->get_variables().back(); ROSE_ASSERT (cachevar); root->get_statements().insert(i, cachedecl); cachedecl->set_parent(root); cachedecl->set_definingDeclaration(cachedecl); cachevar->set_scope(root); SgVariableSymbol* sym = new SgVariableSymbol(cachevar); root->insert_symbol(cachename, sym); SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, sym); vr->set_endOfConstruct(SgNULL_FILE); replaceCopiesOfExpression(e, vr, root); vector<SgExpression*> modifications_to_used_symbols; FdFindModifyingStatementsVisitor(used_symbols, modifications_to_used_symbols).go(root); cachedecl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,(string("// Finite differencing: ") + cachename.str() + " is a cache of " + e->unparseToString()).c_str(),"Compiler-Generated in Finite Differencing",0, 0, 0, PreprocessingInfo::before)); if (modifications_to_used_symbols.size() == 0) { SgInitializer* cacheinit = new SgAssignInitializer(SgNULL_FILE, e); e->set_parent(cacheinit); cachevar->set_initializer(cacheinit); cacheinit->set_parent(cachevar); } else { for (unsigned int i = 0; i < modifications_to_used_symbols.size(); ++i) { SgExpression* modstmt = modifications_to_used_symbols[i]; #ifdef FD_DEBUG cout << "Updating cache after " << modstmt->unparseToString() << endl; #endif SgExpression* updateCache = 0; SgVarRefExp* varref = new SgVarRefExp(SgNULL_FILE, sym); varref->set_endOfConstruct(SgNULL_FILE); SgTreeCopy tc; SgExpression* eCopy = isSgExpression(e->copy(tc)); switch (modstmt->variantT()) { case V_SgAssignOp: { SgAssignOp* assignment = isSgAssignOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); replaceCopiesOfExpression(lhs, rhs, eCopy); } break; case V_SgPlusAssignOp: case V_SgMinusAssignOp: case V_SgAndAssignOp: case V_SgIorAssignOp: case V_SgMultAssignOp: case V_SgDivAssignOp: case V_SgModAssignOp: case V_SgXorAssignOp: case V_SgLshiftAssignOp: case V_SgRshiftAssignOp: { SgBinaryOp* assignment = isSgBinaryOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); SgTreeCopy tc; SgExpression* rhsCopy = isSgExpression(rhs->copy(tc)); SgExpression* newval = 0; switch (modstmt->variantT()) { #define DO_OP(op, nonassignment) \ case V_##op: { \ newval = new nonassignment(SgNULL_FILE, lhs, rhsCopy); \ newval->set_endOfConstruct(SgNULL_FILE); \ } \ break DO_OP(SgPlusAssignOp, SgAddOp); DO_OP(SgMinusAssignOp, SgSubtractOp); DO_OP(SgAndAssignOp, SgBitAndOp); DO_OP(SgIorAssignOp, SgBitOrOp); DO_OP(SgMultAssignOp, SgMultiplyOp); DO_OP(SgDivAssignOp, SgDivideOp); DO_OP(SgModAssignOp, SgModOp); DO_OP(SgXorAssignOp, SgBitXorOp); DO_OP(SgLshiftAssignOp, SgLshiftOp); DO_OP(SgRshiftAssignOp, SgRshiftOp); #undef DO_OP default: break; } assert (newval); replaceCopiesOfExpression(lhs, newval, eCopy); } break; case V_SgPlusPlusOp: { SgExpression* lhs = isSgPlusPlusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgAddOp* add = new SgAddOp(SgNULL_FILE, lhs, one); add->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(add); one->set_parent(add); replaceCopiesOfExpression(lhs,add,eCopy); } break; case V_SgMinusMinusOp: { SgExpression* lhs = isSgMinusMinusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgSubtractOp* sub = new SgSubtractOp(SgNULL_FILE, lhs, one); sub->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(sub); one->set_parent(sub); replaceCopiesOfExpression(lhs,sub,eCopy); } break; default: cerr << modstmt->sage_class_name() << endl; assert (false); break; } #ifdef FD_DEBUG cout << "e is " << e->unparseToString() << endl; cout << "eCopy is " << eCopy->unparseToString() << endl; #endif updateCache = doFdVariableUpdate(rules, varref, e, eCopy); #ifdef FD_DEBUG cout << "updateCache is " << updateCache->unparseToString() << endl; #endif if (updateCache) { ROSE_ASSERT(modstmt != NULL); SgNode* ifp = modstmt->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, updateCache, modstmt); modstmt->set_parent(comma); updateCache->set_parent(comma); if (ifp == NULL) { printf ("modstmt->get_parent() == NULL modstmt = %p = %s \n",modstmt,modstmt->class_name().c_str()); modstmt->get_startOfConstruct()->display("modstmt->get_parent() == NULL: debug"); } ROSE_ASSERT(ifp != NULL); #ifdef FD_DEBUG cout << "New expression is " << comma->unparseToString() << endl; cout << "IFP is " << ifp->sage_class_name() << ": " << ifp->unparseToString() << endl; #endif if (isSgExpression(ifp)) { isSgExpression(ifp)->replace_expression(modstmt, comma); comma->set_parent(ifp); } else { // DQ (12/16/2006): Need to handle cases that are not SgExpression (now that SgExpressionRoot is not used!) // cerr << ifp->sage_class_name() << endl; // assert (!"Bad parent type for inserting comma expression"); SgStatement* statement = isSgStatement(ifp); if (statement != NULL) { #ifdef FD_DEBUG printf ("Before statement->replace_expression(): statement = %p = %s modstmt = %p = %s \n",statement,statement->class_name().c_str(),modstmt,modstmt->class_name().c_str()); SgExprStatement* expresionStatement = isSgExprStatement(statement); if (expresionStatement != NULL) { SgExpression* expression = expresionStatement->get_expression(); printf ("expressionStatement expression = %p = %s \n",expression,expression->class_name().c_str()); } #endif statement->replace_expression(modstmt, comma); comma->set_parent(statement); } else { ROSE_ASSERT(ifp != NULL); printf ("Error: parent is neither a SgExpression nor a SgStatement ifp = %p = %s \n",ifp,ifp->class_name().c_str()); ROSE_ASSERT(false); } } #ifdef FD_DEBUG cout << "IFP is now " << ifp->unparseToString() << endl; #endif } } } }
// Do partial redundancy elimination, looking for copies of one expression expr // within the basic block root. A control flow graph for root must be provided // in cfg, with a map from nodes to their statements in node_statements, a map // from edges to their CFG edge types in edge_type, and a map from edges to // their insertion points in edge_insertion_point. The algorithm used is that // of Paleri, Srikant, and Shankar ("Partial redundancy elimination: a simple, // pragmatic, and provably correct algorithm", Science of Computer Programming // 48 (2003) 1--20). void PRE::partialRedundancyEliminationOne( SgExpression* expr, SgBasicBlock* root, const myControlFlowGraph& cfg) { // SgBasicBlock* myFunctionBody = getFunctionDefinition(expr)->get_body(); // DQ (3/16/2006): Added assertions ROSE_ASSERT(expr != NULL); ROSE_ASSERT(root != NULL); vector<SgVariableSymbol*> symbols_in_expression = SageInterface::getSymbolsUsedInExpression(expr); if (anyOfListPotentiallyModifiedIn(symbols_in_expression, expr)) { // This expression updates its own arguments, and so is not idempotent // Return immediately return; } // Simple or not user-definable expressions if (isSgVarRefExp(expr)) return; if (isSgValueExp(expr)) return; if (isSgFunctionRefExp(expr)) return; if (isSgExprListExp(expr)) return; if (isSgInitializer(expr)) return; #if 0 if ( (isSgAddOp(expr) || isSgSubtractOp(expr)) && (isSgVarRefExp(isSgBinaryOp(expr)->get_lhs_operand()) || isSgValueExp(isSgBinaryOp(expr)->get_lhs_operand())) && (isSgVarRefExp(isSgBinaryOp(expr)->get_rhs_operand()) || isSgValueExp(isSgBinaryOp(expr)->get_rhs_operand()))) return; #endif // Expressions which do not keep a consistent value each time they are used if (!expressionTreeEqual(expr, expr)) return; // cerr << "Trying to do PRE using expression " << expr->unparseToString() << " whose type is " << expr->sage_class_name() << endl; VertexIter i = cfg.graph.vertices().begin(), end = cfg.graph.vertices().end(); // cerr << "CFG has " << distance(i, end) << " nodes" << endl; bool needToMakeCachevar = false; set<SgNode*> replacements; vector<pair<SgNode*, bool /* before */> > insertions; vector<bool> transp(cfg.graph.vertices().size()), comp(cfg.graph.vertices().size()), antloc(cfg.graph.vertices().size()); vector<SgNode*> first_computation(cfg.graph.vertices().size()), last_computation(cfg.graph.vertices().size()); // Set values of local node properties for (i = cfg.graph.vertices().begin(); i != end; ++i) { const vector<SgNode*>& stmts = cfg.node_statements[*i]; // Precompute test values for each statement vector<bool> argumentsModifiedInStatement(stmts.size()); vector<int> expressionComputedInStatement(stmts.size()); for (unsigned int j = 0; j < stmts.size(); ++j) { if (anyOfListPotentiallyModifiedIn(symbols_in_expression, stmts[j])) argumentsModifiedInStatement[j] = true; expressionComputedInStatement[j] = countComputationsOfExpressionIn(expr, stmts[j]); } // Compute transp transp[*i] = true; for (unsigned int j = 0; j < stmts.size(); ++j) if (argumentsModifiedInStatement[j]) transp[*i] = false; // Compute comp and do local redundancy elimination comp[*i] = false; SgNode* firstComputationInChain = 0; bool needToInsertComputation = false; bool computationInsertedOrUsed = false; // cout << "In node " << *i << endl; for (unsigned int j = 0; j < stmts.size(); ++j) { // cout << "In stmt " << j << ", expressionComputedInStatement = " << expressionComputedInStatement[j] // << ", argumentsModifiedInStatement = " << argumentsModifiedInStatement[j] << endl; if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j] && comp[*i] /* from last iter */) { // Do local redundancy elimination if (firstComputationInChain && needToInsertComputation) { insertions.push_back(make_pair(firstComputationInChain, true)); replacements.insert(firstComputationInChain); needToInsertComputation = false; } replacements.insert(stmts[j]); computationInsertedOrUsed = true; needToMakeCachevar = true; } if (expressionComputedInStatement[j]) { comp[*i] = true; if (!firstComputationInChain) { firstComputationInChain = stmts[j]; needToInsertComputation = true; if (expressionComputedInStatement[j] >= 2) { insertions.push_back(make_pair(stmts[j], true)); needToMakeCachevar = true; needToInsertComputation = false; computationInsertedOrUsed = true; replacements.insert(stmts[j]); } } last_computation[*i] = stmts[j]; } if (argumentsModifiedInStatement[j]) { comp[*i] = false; // Must come after expressionComputedInStatement check firstComputationInChain = 0; needToInsertComputation = false; } } assert (!computationInsertedOrUsed || needToMakeCachevar); // Compute antloc antloc[*i] = false; for (unsigned int j = 0; j < stmts.size(); ++j) { if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j]) { antloc[*i] = true; first_computation[*i] = stmts[j]; break; } if (argumentsModifiedInStatement[j]) { antloc[*i] = false; break; } } } // #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl; #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl; PRINT_PROPERTY(transp); PRINT_PROPERTY(comp); PRINT_PROPERTY(antloc); int (simpleGraph::*source_ptr)(int) const = &simpleGraph::source; int (simpleGraph::*target_ptr)(int) const = &simpleGraph::target; vector<bool> avin(cfg.graph.vertices().size(), true); vector<bool> avout(cfg.graph.vertices().size(), true); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(avin, cfg); FIXPOINT_OUTPUT_BEGIN(avout, cfg); avin[v] = accumulate_neighbors(cfg, v, avout,cfg.graph.in_edges(v),&simpleGraph::source, logical_and<bool>(), true, false); avout[v] = comp[v] || (avin[v] && transp[v]); FIXPOINT_OUTPUT_END(avout, <=, cfg); FIXPOINT_OUTPUT_END(avin, <=, cfg); FIXPOINT_END(cfg, out_edges, OutEdgeIter) PRINT_PROPERTY(avin); PRINT_PROPERTY(avout); vector<bool> antin(cfg.graph.vertices().size(), true); vector<bool> antout(cfg.graph.vertices().size(), true); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(antin, cfg); FIXPOINT_OUTPUT_BEGIN(antout, cfg); antout[v] = accumulate_neighbors(cfg, v, antin, cfg.graph.out_edges(v), target_ptr, logical_and<bool>(), true, false); antin[v] = antloc[v] || (antout[v] && transp[v]); FIXPOINT_OUTPUT_END(antout, <=, cfg); FIXPOINT_OUTPUT_END(antin, <=, cfg); FIXPOINT_END(cfg, in_edges, InEdgeIter) PRINT_PROPERTY(antin); PRINT_PROPERTY(antout); vector<bool> safein(cfg.graph.vertices().size()), safeout(cfg.graph.vertices().size()); for (i = cfg.graph.vertices().begin(); i != end; ++i) { safein[*i] = avin[*i] || antin[*i]; safeout[*i] = avout[*i] || antout[*i]; } PRINT_PROPERTY(safein); PRINT_PROPERTY(safeout); vector<bool> spavin(cfg.graph.vertices().size(), false); vector<bool> spavout(cfg.graph.vertices().size(), false); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(spavin, cfg); FIXPOINT_OUTPUT_BEGIN(spavout, cfg); spavin[v] = safein[v] && accumulate_neighbors(cfg, v, spavout, cfg.graph.in_edges(v), source_ptr, logical_or<bool>(), false, false); spavout[v] = safeout[v] && (comp[v] || (spavin[v] && transp[v])); FIXPOINT_OUTPUT_END(spavout, >=, cfg); FIXPOINT_OUTPUT_END(spavin, >=, cfg); FIXPOINT_END(cfg, out_edges, OutEdgeIter) PRINT_PROPERTY(spavin); PRINT_PROPERTY(spavout); vector<bool> spantin(cfg.graph.vertices().size(), false); vector<bool> spantout(cfg.graph.vertices().size(), false); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(spantin, cfg); FIXPOINT_OUTPUT_BEGIN(spantout, cfg); spantout[v] = safeout[v] && accumulate_neighbors(cfg, v, spantin, cfg.graph.out_edges(v), target_ptr, logical_or<bool>(), false, false); spantin[v] = safein[v] && (antloc[v] || (spantout[v] && transp[v])); FIXPOINT_OUTPUT_END(spantout, >=, cfg); FIXPOINT_OUTPUT_END(spantin, >=, cfg); FIXPOINT_END(cfg, in_edges, InEdgeIter) PRINT_PROPERTY(spantin); PRINT_PROPERTY(spantout); #undef PRINT_PROPERTY vector<bool> node_insert(cfg.graph.vertices().size()); vector<bool> replacef(cfg.graph.vertices().size()); vector<bool> replacel(cfg.graph.vertices().size()); // printf ("Intermediate test 1: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); for (i = cfg.graph.vertices().begin(); i != end; ++i) { node_insert[*i] = comp[*i] && spantout[*i] && (!transp[*i] || !spavin[*i]); replacef[*i] = antloc[*i] && (spavin[*i] || (transp[*i] && spantout[*i])); replacel[*i] = comp[*i] && (spantout[*i] || (transp[*i] && spavin[*i])); if (node_insert[*i]) { needToMakeCachevar = true; insertions.push_back(make_pair(last_computation[*i], true)); // cerr << "Insert computation of " << expr->unparseToString() << " just before last computation in " << *i << endl; } if (replacef[*i]) { needToMakeCachevar = true; replacements.insert(first_computation[*i]); // cerr << "Replace first computation of " << *i << endl; } if (replacel[*i]) { needToMakeCachevar = true; replacements.insert(last_computation[*i]); // cerr << "Replace last computation of " << *i << endl; } } vector<bool> edge_insert(cfg.graph.edges().size()); // printf ("Intermediate test 2: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); EdgeIter j = cfg.graph.edges().begin(), jend = cfg.graph.edges().end(); for (; j != jend; ++j) { edge_insert[*j] = !spavout[cfg.graph.source(*j)] && spavin[cfg.graph.target(*j)] && spantin[cfg.graph.target(*j)]; // printf ("edge_insert[*j] = %s \n",edge_insert[*j] ? "true" : "false"); if (edge_insert[*j]) { needToMakeCachevar = true; // cerr << "Insert computation of " << expr->unparseToString() << " on edge from " // << cfg.graph.source(*j) << " to " << cfg.graph.target(*j) << endl; } } // printf ("Before final test: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); // Add cache variable if necessary SgVarRefExp* cachevar = 0; if (needToMakeCachevar) { SgName cachevarname = "cachevar__"; cachevarname << ++SageInterface::gensym_counter; // printf ("Building variable name = %s \n",cachevarname.str()); SgType* type = expr->get_type(); if (isSgArrayType(type)) type = new SgPointerType(isSgArrayType(type)->get_base_type()); assert (SageInterface::isDefaultConstructible(type)); // FIXME: assert (isAssignable(type)); SgVariableDeclaration* decl = new SgVariableDeclaration(SgNULL_FILE, cachevarname, type, NULL); decl->set_definingDeclaration(decl); SgInitializedName* initname = decl->get_variables().back(); // DQ (10/5/2007): Added an assertion. ROSE_ASSERT(initname != NULL); decl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment, (string("// Partial redundancy elimination: ") + cachevarname.str() + " is a cache of " + expr->unparseToString()).c_str(), "Compiler-Generated in PRE", 0, 0, 0, PreprocessingInfo::before)); SgVariableSymbol* cachevarsym = new SgVariableSymbol(initname); decl->set_parent(root); // DQ (10/5/2007): Added scope (suggested by Jeremiah). initname->set_scope(root); root->get_statements().insert(root->get_statements().begin(),decl); root->insert_symbol(cachevarname, cachevarsym); cachevar = new SgVarRefExp(SgNULL_FILE, cachevarsym); cachevar->set_endOfConstruct(SgNULL_FILE); } // Do expression computation replacements for (set<SgNode*>::iterator i = replacements.begin(); i != replacements.end(); ++i) { ReplaceExpressionWithVarrefVisitor(expr, cachevar).traverse(*i, postorder); } // Do edge insertions // int count = 0; bool failAtEndOfFunction = false; for (j = cfg.graph.edges().begin(); j != jend; ++j) { // printf ("Build the insertion list! count = %d \n",count++); if (edge_insert[*j]) { #if 0 // DQ (3/13/2006): Compiler warns that "src" is unused, so I have commented it out! Vertex src = cfg.graph.source(*j), tgt = cfg.graph.target(*j); cerr << "Doing insertion between " << src << " and " << tgt << endl; #endif pair<SgNode*, bool> insert_point = cfg.edge_insertion_point[*j]; if (insert_point.first) { insertions.push_back(insert_point); } else { // DQ (3/16/2006): This is a visited when we fixup the NULL pointer to the initializer in a SgForStatment. cerr << "Warning: no insertion point found" << endl; //FIXME was assert printf ("Need to figure out what to do here! cfg.edge_insertion_point[*j] = %p \n",&(cfg.edge_insertion_point[*j])); failAtEndOfFunction = true; ROSE_ASSERT(false); } } } // Do within-node insertions // printf ("At start of loop: insertions.size() = %zu \n",insertions.size()); for (vector<pair<SgNode*, bool> >::iterator i = insertions.begin(); i != insertions.end(); ++i) { SgTreeCopy tc1, tc2; SgVarRefExp* cachevarCopy = isSgVarRefExp(cachevar->copy(tc1)); ROSE_ASSERT (cachevarCopy); cachevarCopy->set_lvalue(true); SgExpression* operation = new SgAssignOp(SgNULL_FILE, cachevarCopy, isSgExpression(expr->copy(tc2))); #if 0 printf ("Inside of loop: insertions.size() = %zu \n",insertions.size()); printf ("\n\ni->first = %p = %s = %s \n",i->first,i->first->class_name().c_str(),i->first->unparseToString().c_str()); printf ("operation = %p = %s = %s \n",operation,operation->class_name().c_str(),operation->unparseToString().c_str()); #endif if (isSgExpression(i->first) && !i->second) { SgNode* ifp = i->first->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, isSgExpression(i->first), operation); operation->set_parent(comma); comma->set_parent(ifp); i->first->set_parent(comma); if (isSgForStatement(ifp)) { isSgForStatement(ifp)->set_increment(comma); } else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_lhs_operand() == i->first) { isSgBinaryOp(ifp)->set_lhs_operand(comma); } else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_rhs_operand() == i->first) { isSgBinaryOp(ifp)->set_rhs_operand(comma); } else if (isSgUnaryOp(ifp) && isSgUnaryOp(ifp)->get_operand() == i->first) { isSgUnaryOp(ifp)->set_operand(comma); } else { cerr << ifp->sage_class_name() << endl; assert (!"Bad parent type for inserting comma expression"); } } else { SgStatement* the_computation = new SgExprStatement(SgNULL_FILE, operation); operation->set_parent(the_computation); // printf ("In pre.C: the_computation = %p = %s \n",the_computation,the_computation->class_name().c_str()); if (isSgBasicBlock(i->first) && i->second) { isSgBasicBlock(i->first)->get_statements().insert(isSgBasicBlock(i->first)->get_statements().begin(),the_computation); the_computation->set_parent(i->first); } else { #if 0 // DQ (3/14/2006): Bug here when SgExprStatement from SgForStatement test is used here! printf ("Bug here when SgExprStatement from SgForStatement test is used: i->first = %s \n",i->first->class_name().c_str()); i->first->get_file_info()->display("Location i->first"); printf ("Bug here when SgExprStatement from SgForStatement test is used: TransformationSupport::getStatement(i->first) = %s \n", TransformationSupport::getStatement(i->first)->class_name().c_str()); printf ("Bug here when SgExprStatement from SgForStatement test is used: the_computation = %s \n",the_computation->class_name().c_str()); the_computation->get_file_info()->display("Location the_computation: debug"); ROSE_ASSERT(i->first != NULL); ROSE_ASSERT(i->first->get_parent() != NULL); printf ("i->first->get_parent() = %s \n",i->first->get_parent()->class_name().c_str()); i->first->get_file_info()->display("Location i->first: debug"); #endif SgForStatement* forStatement = isSgForStatement(i->first->get_parent()); if (forStatement != NULL) { // Make sure that both pointers are not equal because they are both NULL! ROSE_ASSERT(forStatement->get_test() != NULL); SgExprStatement* possibleTest = isSgExprStatement(i->first); if ( forStatement->get_test() == possibleTest ) { // This is a special case of a SgExpressionStatement as a target in a SgForStatement // printf ("Found special case of target being the test of a SgForStatement \n"); forStatement->set_test(the_computation); the_computation->set_parent(forStatement); } } else { SgForInitStatement* forInitStatement = isSgForInitStatement(i->first->get_parent()); if (forInitStatement != NULL) { // printf ("Found the SgForInitStatement \n"); SgVariableDeclaration* possibleVariable = isSgVariableDeclaration(i->first); SgExprStatement* possibleExpression = isSgExprStatement(i->first); SgStatementPtrList & statementList = forInitStatement->get_init_stmt(); SgStatementPtrList::iterator i = statementList.begin(); bool addToForInitList = false; while ( (addToForInitList == false) && (i != statementList.end()) ) { // if ( *i == possibleVariable ) if ( *i == possibleVariable || *i == possibleExpression ) { // This is a special case of a SgExpressionStatement as a target in a SgForStatement // printf ("Found special case of SgForInitStatement transformation \n"); addToForInitList = true; } i++; } // Only modify the STL list outside of the loop over the list to avoid interator invalidation if (addToForInitList == true) { // Add the the_computation statment to the list in the SgForInitStatement. // Later if we abandon the SgForInitStatement then we would have to add it to // the list of SgInitializedName objects in the SgVariableDeclaration OR modify // the expression list to handle the extra expression (but I think this case in // handled above). // printf ("Adding the_computation to the list in the SgForInitStatement \n"); statementList.push_back(the_computation); the_computation->set_parent(forInitStatement); } } else { myStatementInsert(TransformationSupport::getStatement(i->first),the_computation,i->second,true); the_computation->set_parent(TransformationSupport::getStatement(i->first)); } } } } } // DQ (3/16/2006): debugging code to force failure at inspection point if (failAtEndOfFunction == true) { printf ("Error: internal error detected \n"); ROSE_ASSERT(false); } }
void RemoveConstantFoldedValueViaParent::visit ( SgNode* node ) { // This is an alternative implementation that allows us to handle expression that are not // traversed in the AST (e.g. types like SgArrayType which can contain expressions). ROSE_ASSERT(node != NULL); // DQ (3/11/2006): Set NULL pointers where we would like to have none. #if 0 printf ("In RemoveConstantFoldedValueViaParent::visit(): node = %p = %s \n",node,node->class_name().c_str()); #endif // DQ (10/12/2012): Turn this on so that we can detect failing IR nodes (failing later) that have valid originalExpressionTrees. // DQ (10/12/2012): Turn this back off because it appears to fail... #if 0 SgExpression* exp = isSgExpression(node); if (exp != NULL) { SgExpression* originalExpressionTree = exp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { SgNode* parent = exp->get_parent(); if (parent != NULL) { printf ("Current IR node with SgExpression parent = %p = %s child = %p = %s originalExpressionTree = %p = %s \n",parent,parent->class_name().c_str(),node,node->class_name().c_str(),originalExpressionTree,originalExpressionTree->class_name().c_str()); bool traceReplacement = true; ConstantFoldedValueReplacer r(traceReplacement, exp); parent->processDataMemberReferenceToPointers(&r); // node->processDataMemberReferenceToPointers(&r); } // Set the originalExpressionTree to NULL. exp->set_originalExpressionTree(NULL); // Set the parent of originalExpressionTree to be the parent of exp. originalExpressionTree->set_parent(parent); // And then delete the folded constant. SageInterface::deleteAST(exp); } } #endif SgArrayType* arrayType = isSgArrayType(node); if (arrayType != NULL) { #if 0 printf ("Found an array type arrayType = %p arrayType->get_index() = %p \n",arrayType,arrayType->get_index()); #endif SgExpression* index = arrayType->get_index(); if (index != NULL) { #if 0 printf ("Fixup array index = %p = %s (traverse index AST subtree) \n",index,index->class_name().c_str()); #endif RemoveConstantFoldedValue astFixupTraversal; astFixupTraversal.traverse(index); #if 0 printf ("DONE: Fixup array index = %p (traverse index AST) \n\n\n\n",index); #endif #if 0 printf ("Found an array index = %p (fixup index directly) \n",index); #endif // Handle the case where the original expression tree is at the root of the subtree. SgExpression* originalExpressionTree = index->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 printf ("Found an originalExpressionTree in the array index originalExpressionTree = %p \n",originalExpressionTree); #endif // DQ (6/12/2013): This appears to be a problem in EDG 4.7 (see test2011_117.C). std::vector<SgExpression*> redundantChainOfOriginalExpressionTrees; if (originalExpressionTree->get_originalExpressionTree() != NULL) { #if 0 printf ("Detected originalExpressionTree nested directly within the originalExpressionTree \n", originalExpressionTree,originalExpressionTree->class_name().c_str(), originalExpressionTree->get_originalExpressionTree(),originalExpressionTree->get_originalExpressionTree()->class_name().c_str()); #endif // Loop to the end of the chain of original expressions (which EDG 4.7 should never have constructed). while (originalExpressionTree->get_originalExpressionTree() != NULL) { #if 0 printf ("Looping through a chain of originalExpressionTrees \n"); #endif // Save the list of redundnat nodes so that we can delete them properly. redundantChainOfOriginalExpressionTrees.push_back(originalExpressionTree); originalExpressionTree = originalExpressionTree->get_originalExpressionTree(); } #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } arrayType->set_index(originalExpressionTree); originalExpressionTree->set_parent(arrayType); index->set_originalExpressionTree(NULL); // printf ("DEBUGING: skip delete of index in array type \n"); delete index; // DQ (6/12/2013): Delete the nodes that we had to skip over (caused by chain of redundant entries from EDG 4.7). std::vector<SgExpression*>::iterator i = redundantChainOfOriginalExpressionTrees.begin(); while (i != redundantChainOfOriginalExpressionTrees.end()) { #if 0 printf ("deleting the redundnat originalExpressionTree chain caused by EDG 4.7 (delete %p = %s) \n",*i,(*i)->class_name().c_str()); #endif delete *i; i++; } index = NULL; } } } SgVariableDefinition* variableDefinition = isSgVariableDefinition(node); if (variableDefinition != NULL) { #if 0 printf ("Found a SgVariableDefinition \n"); #endif SgExpression* bitfieldExp = variableDefinition->get_bitfield(); if (bitfieldExp != NULL) { #if 0 printf ("Fixup bitfieldExp = %p (traverse bitfieldExp AST subtree) \n",bitfieldExp); #endif RemoveConstantFoldedValue astFixupTraversal; astFixupTraversal.traverse(bitfieldExp); // Handle the case where the original expression tree is at the root of the subtree. SgExpression* originalExpressionTree = bitfieldExp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 // DQ (9/18/2011): This code will not work since the bitfile data member in SgVariableDefinition is a SgUnsignedLongVal instead of a SgExpression. variableDefinition->set_bitfield(originalExpressionTree); originalExpressionTree->set_parent(variableDefinition); bitfieldExp->set_originalExpressionTree(NULL); delete bitfieldExp; bitfieldExp = NULL; #else // The ROSE AST needs to be fixed to handle more general expressions for bitfield widths (this does not effect the CFG). // TODO: Change the data type of the bitfield data member in SgVariableDefinition. // DQ (1/20/2014): This has been done now. // printf ("Member data bitfield widths need to be changed (in the ROSE IR) to support more general expressions (can't fix this original expression tree) \n"); #endif #if 0 // This case is not handled yet! printf ("Found an original expression tree in a bitfield expression \n"); ROSE_ASSERT(false); #endif } } } }
void MarkLhsValues::visit(SgNode* node) { // DQ (1/19/2008): Fixup the get_lvalue() member function which is common on expressions. // printf ("In TestLValueExpressions::visit(): node = %s \n",node->class_name().c_str()); ROSE_ASSERT(node != NULL); #if 0 Sg_File_Info* fileInfo = node->get_file_info(); printf ("In MarkLhsValues::visit(): node = %s fileInfo = %p \n",node->class_name().c_str(),fileInfo); if (fileInfo != NULL) { bool isCompilerGenerated = fileInfo->isCompilerGenerated(); std::string filename = fileInfo->get_filenameString(); int line_number = fileInfo->get_line(); int column_number = fileInfo->get_line(); printf ("--- isCompilerGenerated = %s position = %d:%d filename = %s \n",isCompilerGenerated ? "true" : "false",line_number,column_number,filename.c_str()); } #endif // This function most often sets the SgVarRefExp which appears as an lhs operand in a limited set of binary operators. SgExpression* expression = isSgExpression(node); if (expression != NULL) { #if 0 printf ("MarkLhsValues::visit(): calling expression->get_lvalue() on expression = %p = %s \n",expression,expression->class_name().c_str()); #endif SgBinaryOp* binaryOperator = isSgBinaryOp(expression); if (binaryOperator != NULL) { switch (expression->variantT()) { // IR nodes that have an l-value (required by C/C++/Fortran standard) case V_SgAssignOp: case V_SgAndAssignOp: case V_SgDivAssignOp: case V_SgIorAssignOp: case V_SgLshiftAssignOp: case V_SgMinusAssignOp: case V_SgModAssignOp: case V_SgMultAssignOp: case V_SgPlusAssignOp: case V_SgRshiftAssignOp: case V_SgXorAssignOp: { SgExpression* lhs = binaryOperator->get_lhs_operand(); ROSE_ASSERT(lhs != NULL); SgExpression* rhs = binaryOperator->get_rhs_operand(); ROSE_ASSERT(rhs != NULL); // This is violated by the ROSE/tests/nonsmoke/functional/roseTests/astInliningTests/pass16.C test code! // ROSE_ASSERT(lhs->get_lvalue() == true); // This is a value that I know has to be set, the AST generation in EDG/Sage and OFP/Sage // sets this properly, but some transformations of the AST do not, so we fix it up here. lhs->set_lvalue(true); rhs->set_lvalue(false); break; } // These cases are less clear so don't explicitly mark it as an l-value! case V_SgDotExp: case V_SgArrowExp: { SgExpression* lhs = binaryOperator->get_lhs_operand(); ROSE_ASSERT(lhs != NULL); #if WARN_ABOUT_ATYPICAL_LVALUES printf ("L-value test for SgBinaryOp = %s: not clear how to assert value -- lhs->get_lvalue() = %s \n",binaryOperator->class_name().c_str(),lhs->get_lvalue() ? "true" : "false"); #endif // ROSE_ASSERT(lhs->get_lvalue() == true); break; } // DQ (10/9/2008): For the Fortran user defined operator, the lhs is not an L-value. // This represents my understanding, because assignment is explicitly handled separately. case V_SgUserDefinedBinaryOp: { SgExpression* lhs = binaryOperator->get_lhs_operand(); ROSE_ASSERT(lhs != NULL); SgExpression* rhs = binaryOperator->get_rhs_operand(); ROSE_ASSERT(rhs != NULL); // This is a value that I know has to be set, the AST generation in EDG/Sage and OFP/Sage // sets this properly, but some transformations of the AST do not, so we fix it up here. lhs->set_lvalue(false); rhs->set_lvalue(false); break; } default: { // Make sure that the lhs is not an L-value SgExpression* lhs = binaryOperator->get_lhs_operand(); ROSE_ASSERT(lhs != NULL); #if WARN_ABOUT_ATYPICAL_LVALUES if (lhs->get_lvalue() == true) { printf ("Error for lhs = %p = %s = %s in binary expression = %s \n", lhs,lhs->class_name().c_str(),SageInterface::get_name(lhs).c_str(),expression->class_name().c_str()); binaryOperator->get_startOfConstruct()->display("Error for lhs: lhs->get_lvalue() == true: debug"); } #endif // ROSE_ASSERT(lhs->get_lvalue() == false); } } //SgExpression* rhs = binaryOperator->get_rhs_operand(); // Liao 3/14/2011. This function is called by builders for binary expressions. // These builders can accept empty right hand operands. // ROSE_ASSERT(rhs != NULL); #if WARN_ABOUT_ATYPICAL_LVALUES if (rhs != NULL) if (rhs->get_lvalue() == true) { printf ("Error for rhs = %p = %s = %s in binary expression = %s \n", rhs,rhs->class_name().c_str(),SageInterface::get_name(rhs).c_str(),expression->class_name().c_str()); binaryOperator->get_startOfConstruct()->display("Error for rhs: rhs->get_lvalue() == true: debug"); } #endif // ROSE_ASSERT(rhs->get_lvalue() == false); } SgUnaryOp* unaryOperator = isSgUnaryOp(expression); if (unaryOperator != NULL) { switch (expression->variantT()) { // IR nodes that should have a valid lvalue // What about SgAddressOfOp? case V_SgAddressOfOp: break; // JJW 1/31/2008 case V_SgMinusMinusOp: case V_SgPlusPlusOp: { SgExpression* operand = unaryOperator->get_operand(); ROSE_ASSERT(operand != NULL); #if WARN_ABOUT_ATYPICAL_LVALUES // if (operand->get_lvalue() == true) if (operand->get_lvalue() == false) { printf ("Error for operand = %p = %s = %s in unary expression (SgMinusMinusOp or SgPlusPlusOp) = %s \n", operand,operand->class_name().c_str(),SageInterface::get_name(operand).c_str(),expression->class_name().c_str()); unaryOperator->get_startOfConstruct()->display("Error for operand: operand->get_lvalue() == true: debug"); } #endif // ROSE_ASSERT(operand->get_lvalue() == false); operand->set_lvalue(true); // ROSE_ASSERT(operand->get_lvalue() == true); break; } case V_SgThrowOp: { #if WARN_ABOUT_ATYPICAL_LVALUES // Note that the gnu " __throw_exception_again;" can cause a SgThrowOp to now have an operand! SgExpression* operand = unaryOperator->get_operand(); if (operand == NULL) { printf ("Warning: operand == NULL in SgUnaryOp = %s (likely caused by __throw_exception_again) \n",expression->class_name().c_str()); // unaryOperator->get_startOfConstruct()->display("Error: operand == NULL in SgUnaryOp: debug"); } #endif // ROSE_ASSERT(operand != NULL); break; } // DQ (10/9/2008): For the Fortran user defined operator, the operand is not an L-value. // This represents my understanding, because assignment is explicitly handled separately. case V_SgUserDefinedUnaryOp: { SgExpression* operand = unaryOperator->get_operand(); ROSE_ASSERT(operand != NULL); operand->set_lvalue(false); } // Added to address problem on Qing's machine using g++ 4.0.2 case V_SgNotOp: // These are where some error occur. I want to isolate then so that I know the current status of where lvalues are not marked correctly! case V_SgPointerDerefExp: case V_SgCastExp: case V_SgMinusOp: case V_SgBitComplementOp: // case V_SgPlusOp: { SgExpression* operand = unaryOperator->get_operand(); ROSE_ASSERT(operand != NULL); #if WARN_ABOUT_ATYPICAL_LVALUES // Most of the time this is false, we only want to know when it is true if (operand->get_lvalue() == true) { printf ("L-value test for SgUnaryOp = %s: not clear how to assert value -- operand->get_lvalue() = %s \n",unaryOperator->class_name().c_str(),operand->get_lvalue() ? "true" : "false"); // unaryOperator->get_startOfConstruct()->display("L-value test for SgUnaryOp: operand->get_lvalue() == true: debug"); } #endif // ROSE_ASSERT(operand->get_lvalue() == false); break; } default: { SgExpression* operand = unaryOperator->get_operand(); ROSE_ASSERT(operand != NULL); #if WARN_ABOUT_ATYPICAL_LVALUES if (operand->get_lvalue() == true) { printf ("Error for operand = %p = %s = %s in unary expression = %s \n", operand,operand->class_name().c_str(),SageInterface::get_name(operand).c_str(),expression->class_name().c_str()); unaryOperator->get_startOfConstruct()->display("Error for operand: operand->get_lvalue() == true: debug"); } #endif // DQ (10/9/2008): What is the date and author for this comment? Is it fixed now? Was it made into a test code? // Note that this fails for line 206 of file: include/g++_HEADERS/hdrs1/ext/mt_allocator.h ROSE_ASSERT(operand->get_lvalue() == false); } } } } }
void SimpleInstrumentation::visit ( SgNode* astNode ) { switch(astNode->variantT()) { case V_SgFunctionCallExp: { SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(astNode); SgExpression *function = functionCallExp->get_function(); ROSE_ASSERT(function); switch (function->variantT()) { case V_SgFunctionRefExp: { SgFunctionRefExp *functionRefExp = isSgFunctionRefExp(function); SgFunctionSymbol *symbol = functionRefExp->get_symbol(); ROSE_ASSERT(symbol != NULL); SgFunctionDeclaration *functionDeclaration = symbol->get_declaration(); ROSE_ASSERT(functionDeclaration != NULL); if (symbol == functionSymbol) { // Now we know that we have found the correct function call // (even in the presence of overloading or other forms of hidding) // Now fixup the symbol and type of the SgFunctionRefExp object to // reflect the new function to be called (after this we still have to // fixup the argument list in the SgFunctionCallExp. // We only want to build the decalration once (and insert it into the global scope) // after that we save the symbol and reuse it. if (newFunctionSymbol == NULL) { SgFunctionType* originalFunctionType = isSgFunctionType(functionSymbol->get_type()); ROSE_ASSERT(originalFunctionType != NULL); newFunctionSymbol = buildNewFunctionDeclaration (TransformationSupport::getStatement(astNode),originalFunctionType); } ROSE_ASSERT(newFunctionSymbol != NULL); ROSE_ASSERT(newFunctionSymbol->get_type() != NULL); functionRefExp->set_symbol(newFunctionSymbol); } break; } default: cerr<<"warning: unrecognized variant: "<<function->class_name(); } break; } case V_SgFunctionDeclaration: { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(astNode); string functionName = functionDeclaration->get_name().str(); if (functionName == "send") { SgFunctionType *functionType = functionDeclaration->get_type(); ROSE_ASSERT(functionType != NULL); bool foundFunction = false; if (functionType->get_return_type()->unparseToString() == "ssize_t") { SgTypePtrList & argumentList = functionType->get_arguments(); SgTypePtrList::iterator i = argumentList.begin(); if ( (*i++)->unparseToString() == "int" ) if ( (*i++)->unparseToString() == "const void *" ) if ( (*i++)->unparseToString() == "size_t" ) if ( (*i++)->unparseToString() == "int" ) foundFunction = true; } if (foundFunction == true) { // Now get the sysmbol using functionType SgScopeStatement *scope = functionDeclaration->get_scope(); ROSE_ASSERT(scope != NULL); functionSymbol = scope->lookup_function_symbol (functionName,functionType); } } break; } default: { // No other special cases } } }