/* * Fix OP function calls and inject debug names */ void OPSource::fixOpStructs(SgNode *n) { SgInitializedName* initname = isSgInitializedName(n); if(initname) { string var_name = initname->get_name().getString(); SgConstructorInitializer *initer = isSgConstructorInitializer(initname->get_initializer()); if(initer) { string class_name = initer->get_class_decl()->get_name().getString(); if(class_name.find("op_dat") != string::npos || class_name.find("op_dat_gbl") != string::npos || class_name.compare("_op_ptr") == 0 || class_name.compare("_op_set") == 0 || class_name.compare("_op_dat_const") == 0) { cout << "---Injecting Debug Name: " << var_name << "---" << endl; SgExprListExp* list = initer->get_args(); SgExpressionPtrList &exprs = list->get_expressions(); if( isSgStringVal(exprs.back()) == NULL ) { list->append_expression(buildStringVal(var_name)); } } } } }
void interleaveAcrossArraysCheck::storeArrayReference(SgInitializedName* var, string variableName, string type) { // Check if variable is present in transformation if(!transformation->containsInput(variableName)) return; SgConstructorInitializer* constInit = isSgConstructorInitializer(var->get_initializer()); ROSE_ASSERT (constInit != NULL); string dimensions = constInit->get_args()->unparseToString(); ArrayRef arrayRef(variableName, type, dimensions); for(vector<ArrayRef>::iterator iter = arrayRefList.begin(); iter!=arrayRefList.end() ; iter ++) { ArrayRef curArrayRef = *iter; // Case 3 if( curArrayRef.dimensions != dimensions ) { cout << " ERROR: Variable Dimensions: " << dimensions << " for variable: " << variableName << " does not match with other dimensions: " << curArrayRef.dimensions << endl; ROSE_ABORT(); } // Case 4 if( curArrayRef.type != type ) { cout << " ERROR: Variable Type: " << type << " for variable: " << variableName << " does not match with other types: " << curArrayRef.type << endl; ROSE_ABORT(); } // Case 5 if(curArrayRef.name == variableName && curArrayRef.type == type) { cout << " ERROR: Variable Name: " << variableName << " Type: " << type << " duplicate entry found " << endl; ROSE_ABORT(); } } arrayRefList.push_back(arrayRef); // Set at the start of first declaration and until last declaration if(!isContigousDecl && arrayRefList.size() != transformation->getInput().size()) isContigousDecl = true; if(arrayRefList.size() == transformation->getInput().size()) isContigousDecl = false; return; }
std::set<varID> BasicProgmemTransform::getVarsInUnsafeConstructors() { std::set<varID> results; Rose_STL_Container<SgNode *> constructors = NodeQuery::querySubTree(project, V_SgConstructorInitializer); for(auto& cons: constructors) { SgConstructorInitializer *consInit = isSgConstructorInitializer(cons); SgClassDeclaration *classDecl = consInit->get_class_decl(); if(classDecl == NULL || isArduinoStringType(classDecl->get_type()) == false) { SgExpressionPtrList exprs = consInit->get_args()->get_expressions(); for(auto &exp: exprs) { SgVarRefExp* var = isSgVarRefExp(exp); if(var == NULL) { continue ;} std::set<varID> aliases = aliasAnalysis->getAliasesForVariableAtNode(var, SgExpr2Var(var)); results.insert(aliases.begin(), aliases.end()); } } } return results; }
void BasicProgmemTransform::transformStringConstructors(SgFunctionDeclaration *func) { Rose_STL_Container<SgNode *> constructors = NodeQuery::querySubTree(func, V_SgConstructorInitializer); for(auto &cons: constructors) { SgConstructorInitializer *consInit = isSgConstructorInitializer(cons); SgClassDeclaration *classDecl = consInit->get_class_decl(); if(classDecl != NULL && isArduinoStringType(classDecl->get_type())) { SgExpressionPtrList exprs = consInit->get_args()->get_expressions(); for(auto &exp: exprs) { SgVarRefExp* var = isSgVarRefExp(exp); if(var == NULL) { continue ;} // SgInitializedName *initName = var->get_symbol()->get_declaration(); if(isVarDeclToRemove(var)) { castProgmemParams(var); } } } } }
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); }
void TransformationSupport::getTransformationOptionsFromVariableDeclarationConstructorArguments ( SgVariableDeclaration* variableDeclaration, list<OptionDeclaration> & returnEnumValueList ) { ROSE_ASSERT (variableDeclaration != NULL); SgInitializedNamePtrList & variableList = variableDeclaration->get_variables(); printf ("Inside of getTransformationOptionsFromVariableDeclarationConstructorArguments() \n"); for (SgInitializedNamePtrList::iterator i = variableList.begin(); i != variableList.end(); i++) { // We don't care about the name // SgName & name = (*i).get_name(); ROSE_ASSERT ((*i) != NULL); // QY 11/10/04 removed named_item in SgInitializedName // printf ("Processing a variable in the list \n"); // if ((*i)->get_named_item() != NULL) // { // ROSE_ASSERT ((*i)->get_named_item() != NULL); // SgInitializer *initializerOther = (*i)->get_named_item()->get_initializer(); SgInitializer *initializerOther = (*i)->get_initializer(); // This is not always a valid pointer // ROSE_ASSERT (initializerOther != NULL); // printf ("Test for initialized in variable \n"); if (initializerOther != NULL) { // There are other things we could ask of the initializer ROSE_ASSERT (initializerOther != NULL); // printf ("Found a valid initialized in variable \n"); SgConstructorInitializer* constructorInitializer = isSgConstructorInitializer(initializerOther); ROSE_ASSERT (constructorInitializer != NULL); SgExprListExp* argumentList = constructorInitializer->get_args(); ROSE_ASSERT (argumentList != NULL); SgExpressionPtrList & expressionPtrList = argumentList->get_expressions(); ROSE_ASSERT(expressionPtrList.empty() == false); SgExpressionPtrList::iterator i = expressionPtrList.begin(); ROSE_ASSERT (*i != NULL); // First value is a char* identifying the option SgStringVal* charString = isSgStringVal(*i); ROSE_ASSERT (charString != NULL); #if 1 string optionString; string valueString; int counter = 0; while (i != expressionPtrList.end()) { // printf ("Expression List Element #%d of %d (total) (*i)->sage_class_name() = %s \n", // counter,expressionPtrList.size(),(*i)->sage_class_name()); switch ( (*i)->variant() ) { case ENUM_VAL: { SgEnumVal* enumVal = isSgEnumVal(*i); ROSE_ASSERT (enumVal != NULL); // int enumValue = enumVal->get_value(); SgName enumName = enumVal->get_name(); // printf ("Name = %s value = %d \n",enumName.str(),enumValue); // printf ("Name = %s \n",enumName.str()); string name = enumName.str(); // char* name = rose::stringDuplicate( enumName.str() ); // Put the value at the start of the list so that the list can be processed in // consecutive order to establish options for consecutive scopes (root to // child scope). Order is not important if we are only ORing the operands! // returnEnumValueList.push_front (name); // returnEnumValueList.push_front (enumValue); ROSE_ASSERT (counter == 0); break; } case STRING_VAL: { // ROSE_ASSERT (counter == 1); // printf ("Found a SgStringVal expression! \n"); SgStringVal* stringVal = isSgStringVal(*i); ROSE_ASSERT (stringVal != NULL); if (counter == 0) { optionString = stringVal->get_value(); valueString = ""; // printf ("optionString = %s \n",optionString); } if (counter == 1) { valueString = stringVal->get_value(); // printf ("valueString = %s \n",valueString); } break; } case DOUBLE_VAL: { ROSE_ASSERT (counter == 1); // printf ("Found a SgStringVal expression! \n"); SgDoubleVal* doubleVal = isSgDoubleVal(*i); ROSE_ASSERT (doubleVal != NULL); valueString = StringUtility::numberToString(doubleVal->get_value()).c_str(); // printf ("valueString = %s \n",valueString); break; } default: { printf ("Default reached in switch in getTransformationOptionsFromVariableDeclarationConstructorArguments() (*i)->sage_class_name() = %s \n",(*i)->sage_class_name()); ROSE_ABORT(); break; } } i++; counter++; } // printf ("optionString = %s valueString = %s \n",optionString,valueString); OptionDeclaration optionSpecification(optionString.c_str(),valueString.c_str()); returnEnumValueList.push_front (optionSpecification); #endif } else { // printf ("Valid initializer not found in variable \n"); } /* } else { // printf ("Warning: In getTransformationOptionsFromVariableDeclarationConstructorArguments(): (*i).get_named_item() = NULL \n"); } */ } }
void ProcTraversal::visit(SgNode *node) { if (isSgFunctionDeclaration(node)) { SgFunctionDeclaration *decl = isSgFunctionDeclaration(node); if (decl->get_definition() != NULL) { /* collect statistics */ //AstNumberOfNodesStatistics anons; //anons.traverse(decl, postorder); //original_ast_nodes += anons.get_numberofnodes(); //original_ast_statements += anons.get_numberofstatements(); /* do the real work */ Procedure *proc = new Procedure(); proc->procnum = procnum++; proc->decl = decl; proc->funcsym = isSgFunctionSymbol(decl->get_symbol_from_symbol_table()); if (proc->funcsym == NULL) { #if 0 std::cout << std::endl << "*** NULL function symbol for declaration " << decl->unparseToString() << std::endl << "symbol: " << (void *) decl->get_symbol_from_symbol_table() << (decl->get_symbol_from_symbol_table() != NULL ? decl->get_symbol_from_symbol_table()->class_name() : "") << std::endl << "first nondef decl: " << (void *) decl->get_firstNondefiningDeclaration() << " sym: " << (decl->get_firstNondefiningDeclaration() != NULL ? (void *) decl->get_firstNondefiningDeclaration() ->get_symbol_from_symbol_table() : (void *) NULL) << std::endl; #endif if (decl->get_firstNondefiningDeclaration() != NULL) { proc->funcsym = isSgFunctionSymbol(decl ->get_firstNondefiningDeclaration() ->get_symbol_from_symbol_table()); } } assert(proc->funcsym != NULL); // GB (2008-05-14): We need two parameter lists: One for the names of the // variables inside the function definition, which is // decl->get_parameterList(), and one that contains any default arguments // the function might have. The default arguments are supposedly // associated with the first nondefining declaration. proc->params = decl->get_parameterList(); SgDeclarationStatement *fndstmt = decl->get_firstNondefiningDeclaration(); SgFunctionDeclaration *fnd = isSgFunctionDeclaration(fndstmt); if (fnd != NULL && fnd != decl) proc->default_params = fnd->get_parameterList(); else proc->default_params = proc->params; SgMemberFunctionDeclaration *mdecl = isSgMemberFunctionDeclaration(decl); if (mdecl) { proc->class_type = isSgClassDefinition(mdecl->get_scope()); std::string name = proc->class_type->get_mangled_name().str(); name += "::"; name += decl->get_name().str(); std::string mname = proc->class_type->get_mangled_name().str(); mname += "::"; mname += decl->get_mangled_name().str(); proc->memberf_name = name; proc->mangled_memberf_name = mname; proc->name = decl->get_name().str(); proc->mangled_name = decl->get_mangled_name().str(); // GB (2008-05-26): Computing a single this symbol for each // procedure. Thus, this symbol can also be compared by pointer // equality (as is the case for all other symbols). While we're at it, // we also build a VarRefExp for this which can be used everywhere the // this pointer occurs. proc->this_type = Ir::createPointerType( proc->class_type->get_declaration()->get_type()); proc->this_sym = Ir::createVariableSymbol("this", proc->this_type); proc->this_exp = Ir::createVarRefExp(proc->this_sym); } else { proc->name = decl->get_name().str(); proc->mangled_name = decl->get_mangled_name().str(); proc->class_type = NULL; proc->memberf_name = proc->mangled_memberf_name = ""; proc->this_type = NULL; proc->this_sym = NULL; proc->this_exp = NULL; // GB (2008-07-01): Better resolution of calls to static functions. // This only makes sense for non-member functions. SgStorageModifier &sm = (fnd != NULL ? fnd : decl)->get_declarationModifier().get_storageModifier(); proc->isStatic = sm.isStatic(); // Note that we query the first nondefining declaration for the // static modifier, but we save the file of the *defining* // declaration. This is because the first declaration might be in // some header file, but for call resolution, the actual source // file with the definition is relevant. // Trace back to the enclosing file node. The definition might be // included in foo.c from bar.c, in which case the Sg_File_Info // would refer to bar.c; but for function call resolution, foo.c is // the relevant file. SgNode *p = decl->get_parent(); while (p != NULL && !isSgFile(p)) p = p->get_parent(); proc->containingFile = isSgFile(p); } proc_map.insert(std::make_pair(proc->name, proc)); mangled_proc_map.insert(std::make_pair(proc->mangled_name, proc)); std::vector<SgVariableSymbol* >* arglist = new std::vector<SgVariableSymbol* >(); SgVariableSymbol *this_var = NULL, *this_temp_var = NULL; if (mdecl || decl->get_parameterList() != NULL && !decl->get_parameterList()->get_args().empty()) { proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum); if (mdecl) { // GB (2008-05-26): We now compute the this pointer right at the // beginning of building the procedure. // this_var = Ir::createVariableSymbol("this", this_type); this_var = proc->this_sym; // std::string varname // = std::string("$") + proc->name + "$this"; // this_temp_var = Ir::createVariableSymbol(varname, proc->this_type); this_temp_var = global_this_variable_symbol; ParamAssignment* paramAssignment = Ir::createParamAssignment(this_var, this_temp_var); proc->arg_block->statements.push_back(paramAssignment); arglist->push_back(this_var); if (proc->name.find('~') != std::string::npos) { arglist->push_back(this_temp_var); } } SgInitializedNamePtrList params = proc->params->get_args(); SgInitializedNamePtrList::const_iterator i; #if 0 int parnum = 0; for (i = params.begin(); i != params.end(); ++i) { SgVariableSymbol *i_var = Ir::createVariableSymbol(*i); std::stringstream varname; // varname << "$" << proc->name << "$arg_" << parnum++; SgVariableSymbol* var = Ir::createVariableSymbol(varname.str(),(*i)->get_type()); proc->arg_block->statements.push_back(Ir::createParamAssignment(i_var, var)); arglist->push_back(i_var); } #else // GB (2008-06-23): Trying to replace all procedure-specific argument // variables by a global list of argument variables. This means that at // this point, we do not necessarily need to build a complete list but // only add to the CFG's argument list if it is not long enough. size_t func_params = params.size(); size_t global_args = global_argument_variable_symbols.size(); std::stringstream varname; while (global_args < func_params) { varname.str(""); varname << "$tmpvar$arg_" << global_args++; SgVariableSymbol *var = Ir::createVariableSymbol(varname.str(), global_unknown_type); program->global_map[varname.str()] = std::make_pair(var, var->get_declaration()); global_argument_variable_symbols.push_back(var); } // now create the param assignments size_t j = 0; for (i = params.begin(); i != params.end(); ++i) { SgVariableSymbol *i_var = Ir::createVariableSymbol(params[j]); SgVariableSymbol *var = global_argument_variable_symbols[j]; j++; proc->arg_block->statements.push_back( Ir::createParamAssignment(i_var, var)); arglist->push_back(i_var); } #if 0 // replace the arglist allocated above by the new one; this must be // fixed for this pointers! delete arglist; arglist = &global_argument_variable_symbols; #endif #endif } else { proc->arg_block = NULL; } /* If this is a constructor, call default constructors * of all base classes. If base class constructors are * called manually, these calls will be removed later. */ if (mdecl && strcmp(mdecl->get_name().str(), proc->class_type->get_declaration()->get_name().str()) == 0 && proc->class_type != NULL) { SgBaseClassPtrList::iterator base; for (base = proc->class_type->get_inheritances().begin(); base != proc->class_type->get_inheritances().end(); ++base) { SgClassDeclaration* baseclass = (*base)->get_base_class(); SgVariableSymbol *lhs = Ir::createVariableSymbol("$tmpvar$" + baseclass->get_name(), baseclass->get_type()); program->global_map["$tmpvar$" + baseclass->get_name()] = std::make_pair(lhs, lhs->get_declaration()); SgMemberFunctionDeclaration* fd=get_default_constructor(baseclass); assert(fd); SgType* basetype=baseclass->get_type(); assert(basetype); SgConstructorInitializer *sci = Ir::createConstructorInitializer(fd,basetype); ArgumentAssignment* a = Ir::createArgumentAssignment(lhs, sci); proc->arg_block->statements.push_back(a); // std::string this_called_varname // = std::string("$") + baseclass->get_name() + "$this"; SgVariableSymbol *this_called_var // = Ir::createVariableSymbol(this_called_varname, // baseclass->get_type()); = global_this_variable_symbol; ReturnAssignment* this_ass = Ir::createReturnAssignment(this_var, this_called_var); proc->arg_block->statements.push_back(this_ass); } } if (mdecl && mdecl->get_CtorInitializerList() != NULL && !mdecl->get_CtorInitializerList()->get_ctors().empty()) { SgInitializedNamePtrList cis = mdecl->get_CtorInitializerList()->get_ctors(); SgInitializedNamePtrList::const_iterator i; if (proc->arg_block == NULL) { proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum); } for (i = cis.begin(); i != cis.end(); ++i) { SgVariableSymbol* lhs = Ir::createVariableSymbol(*i); SgAssignInitializer *ai = isSgAssignInitializer((*i)->get_initializer()); SgConstructorInitializer *ci = isSgConstructorInitializer((*i)->get_initializer()); /* TODO: other types of initializers */ if (ai) { SgClassDeclaration *class_decl = proc->class_type->get_declaration(); // GB (2008-05-26): We now compute the this pointer right at the // beginning of building the procedure. // SgVarRefExp* this_ref // = Ir::createVarRefExp("this", // Ir::createPointerType(class_decl->get_type())); SgVarRefExp* this_ref = proc->this_exp; SgArrowExp* arrowExp = Ir::createArrowExp(this_ref,Ir::createVarRefExp(lhs)); // GB (2008-03-17): We need to handle function calls in // initializers. In order to be able to build an argument // assignment, we need to know the function's return variable, so // the expression labeler must be called on it. The expression // number is irrelevant, however, as it does not appear in the // return variable. if (isSgFunctionCallExp(ai->get_operand_i())) { #if 0 ExprLabeler el(0 /*expnum*/); el.traverse(ai->get_operand_i(), preorder); // expnum = el.get_expnum(); #endif // GB (2008-06-25): There is now a single global return // variable. This may or may not mean that we can simply ignore // the code above. I don't quite understand why this labeling // couldn't be done later on, and where its result was used. } ArgumentAssignment* argumentAssignment = Ir::createArgumentAssignment(arrowExp,ai->get_operand_i()); proc->arg_block->statements.push_back(argumentAssignment); } else if (ci) { /* if this is a call to a base class's * constructor, remove the call we generated * before */ SgStatement* this_a = NULL; SgClassDeclaration* cd = ci->get_class_decl(); std::deque<SgStatement *>::iterator i; for (i = proc->arg_block->statements.begin(); i != proc->arg_block->statements.end(); ++i) { ArgumentAssignment* a = dynamic_cast<ArgumentAssignment *>(*i); if (a && isSgConstructorInitializer(a->get_rhs())) { SgConstructorInitializer* c = isSgConstructorInitializer(a->get_rhs()); std::string c_decl_name = c->get_class_decl()->get_name().str(); std::string cd_name = cd->get_name().str(); // if (c->get_class_decl()->get_name() == cd->get_name()) { if (c_decl_name == cd_name) { #if 0 // erase the following assignment // of the this pointer as well this_a = *proc->arg_block->statements.erase(i+1); proc->arg_block->statements.erase(i); #endif // GB (2008-03-28): That's an interesting piece of code, but // it might be very mean to iterators. At least it is hard to // see whether it is correct. So let's try it like this: // erase i; we get an iterator back, which refers to the next // element. Save that element as this_a, and then erase. std::deque<SgStatement *>::iterator this_pos; this_pos = proc->arg_block->statements.erase(i); this_a = *this_pos; proc->arg_block->statements.erase(this_pos); // Good. Looks like this fixed a very obscure bug. break; } } } /* now add the initialization */ proc->arg_block->statements.push_back(Ir::createArgumentAssignment(lhs, ci)); if (this_a != NULL) proc->arg_block->statements.push_back(this_a); } } } proc->entry = new CallBlock(node_id++, START, proc->procnum, new std::vector<SgVariableSymbol *>(*arglist), (proc->memberf_name != "" ? proc->memberf_name : proc->name)); proc->exit = new CallBlock(node_id++, END, proc->procnum, new std::vector<SgVariableSymbol *>(*arglist), (proc->memberf_name != "" ? proc->memberf_name : proc->name)); proc->entry->partner = proc->exit; proc->exit->partner = proc->entry; proc->entry->call_target = Ir::createFunctionRefExp(proc->funcsym); proc->exit->call_target = Ir::createFunctionRefExp(proc->funcsym); /* In constructors, insert an assignment $A$this = this * at the end to make sure that the 'this' pointer can be * passed back to the calling function uncobbled. */ proc->this_assignment = NULL; if (mdecl) { SgMemberFunctionDeclaration* cmdecl = isSgMemberFunctionDeclaration(mdecl->get_firstNondefiningDeclaration()); // if (cmdecl && cmdecl->get_specialFunctionModifier().isConstructor()) { proc->this_assignment = new BasicBlock(node_id++, INNER, proc->procnum); ReturnAssignment* returnAssignment = Ir::createReturnAssignment(this_temp_var, this_var); proc->this_assignment->statements.push_back(returnAssignment); add_link(proc->this_assignment, proc->exit, NORMAL_EDGE); // } } std::stringstream varname; // varname << "$" << proc->name << "$return"; // proc->returnvar = Ir::createVariableSymbol(varname.str(), // decl->get_type()->get_return_type()); proc->returnvar = global_return_variable_symbol; procedures->push_back(proc); if(getPrintCollectedFunctionNames()) { std::cout << (proc->memberf_name != "" ? proc->memberf_name : proc->name) << " " /*<< proc->decl << std::endl*/; } if (proc->arg_block != NULL) { proc->arg_block->call_target = Ir::createFunctionRefExp(proc->funcsym); } // delete arglist; } } }