PrefixSynthesizedAttribute PrefixSuffixGenerationTraversal::evaluateSynthesizedAttribute ( SgNode* astNode, PrefixInheritedAttribute inputInheritedAttribute, SynthesizedAttributesList inputSynthesizedAttributeList ) { #if 0 printf ("@@@ In evaluateSynthesizedAttribute: astNode = %s \n",astNode->sage_class_name()); printf (" inputSynthesizedAttributeList.size() = %zu \n",inputSynthesizedAttributeList.size()); #endif return PrefixSynthesizedAttribute(); }
SynthesizedAttribute Traversal::evaluateSynthesizedAttribute ( SgNode* astNode, InheritedAttribute inheritedAttribute, SynthesizedAttributesList childAttributes ) { SynthesizedAttribute localResult; // printf ("evaluateSynthesizedAttribute(): astNode = %p = %s inheritedAttribute.isFirstFile = %s \n",astNode,astNode->class_name().c_str(),inheritedAttribute.isFirstFile ? "true" : "false"); // Accumulate any valid pointer to main on a child node and pass it to the local synthesized attribute. for (size_t i = 0; i < childAttributes.size(); i++) { if (childAttributes[i].main_function != NULL) { localResult.main_function = childAttributes[i].main_function; } } if (inheritedAttribute.isFirstFile == true) { SgGlobal* globalScope = isSgGlobal(astNode); if (globalScope != NULL) { // Gather all of the functions in global scope of the first file. vector<SgDeclarationStatement*> globalScopeDeclarationsToMove = globalScope->get_declarations(); inheritedAttribute.statements_from_first_file = globalScopeDeclarationsToMove; // printf ("evaluateSynthesizedAttribute(): Gather all of the functions in global scope of the first file inheritedAttribute.statements_from_first_file.size() = %zu \n",inheritedAttribute.statements_from_first_file.size()); // Erase the declarations in the global scope of the first file. globalScope->get_declarations().clear(); } SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(astNode); if (declarationStatement != NULL && isSgGlobal(declarationStatement->get_parent()) != NULL) { // Mark as a transformation (recursively mark the whole subtree). // printf ("*** Mark as a transformation: declarationStatement = %p \n",declarationStatement); markAsTransformation(declarationStatement); if (declarationStatement->get_firstNondefiningDeclaration() != NULL) markAsTransformation(declarationStatement->get_firstNondefiningDeclaration()); } } else { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(astNode); if (functionDeclaration != NULL && functionDeclaration->get_name() == "main") { // Save the pointer to the main function (in the second file). localResult.main_function = functionDeclaration; // printf ("Found the main function ...(saved pointer) inheritedAttribute.main_function = %p \n",localResult.main_function); } // printf ("evaluateSynthesizedAttribute(): localResult.main_function = %p \n",localResult.main_function); // Test for the selected insertion point in the 2nd file for the declarations gathered from the first file. SgGlobal* globalScope = isSgGlobal(astNode); if (globalScope != NULL && localResult.main_function != NULL) { printf ("evaluateSynthesizedAttribute(): Found the main function ...\n"); vector<SgDeclarationStatement*>::iterator i = find(globalScope->get_declarations().begin(),globalScope->get_declarations().end(),localResult.main_function); globalScope->get_declarations().insert(i,inheritedAttribute.statements_from_first_file.begin(),inheritedAttribute.statements_from_first_file.end()); #if 0 // Set the parents of each declaration to match the new location (avoids warning that might later be an error). for (size_t i = 0; i < inheritedAttribute.statements_from_first_file.size(); i++) { inheritedAttribute.statements_from_first_file[i]->set_parent(globalScope); } #endif } } return localResult; }
ChildUses DefsAndUsesTraversal::evaluateSynthesizedAttribute(SgNode* node, SynthesizedAttributesList attrs) { if (StaticSingleAssignment::getDebug()) { cout << "---------<" << node->class_name() << node << ">-------" << node << endl; } //We want to propagate the def/use information up from the varRefs to the higher expressions. if (SgInitializedName * initName = isSgInitializedName(node)) { VarUniqueName * uName = StaticSingleAssignment::getUniqueName(node); ROSE_ASSERT(uName); //Add this as a def, unless this initialized name is a preinitialization of a parent class. For example, //in the base of B : A(3) { ... } where A is a superclass of B, an initialized name for A appears. //Clearly, the initialized name for the parent class is not a real variable if (initName->get_preinitialization() != SgInitializedName::e_virtual_base_class && initName->get_preinitialization() != SgInitializedName::e_nonvirtual_base_class) { ssa->getOriginalDefTable()[node].insert(uName->getKey()); if (StaticSingleAssignment::getDebug()) { cout << "Defined " << uName->getNameString() << endl; } } return ChildUses(); } //Variable references are where all uses originate else if (isSgVarRefExp(node)) { //Get the unique name of the def. VarUniqueName * uName = StaticSingleAssignment::getUniqueName(node); //In some cases, a varRef isn't actually part of a variable name. For example, //foo().x where foo returns a structure. x is an SgVarRefExp, but is not part of a variable name. if (uName == NULL) { return ChildUses(); } //Add this as a use. If it's not a use (e.g. target of an assignment), we'll fix it up later. ssa->getLocalUsesTable()[node].insert(uName->getKey()); if (StaticSingleAssignment::getDebug()) { cout << "Found use for " << uName->getNameString() << " at " << node->cfgForBeginning().toStringForDebugging() << endl; } //This varref is both the only use in the subtree and the current variable return ChildUses(node, isSgVarRefExp(node)); } //Catch all types of Binary Operations else if (SgBinaryOp * binaryOp = isSgBinaryOp(node)) { ROSE_ASSERT(attrs.size() == 2 && "Error: BinaryOp without exactly 2 children."); ChildUses& lhs = attrs[0]; ChildUses& rhs = attrs[1]; //If we have an assigning operation, we want to list everything on the LHS as being defined //Otherwise, everything is being used. vector<SgNode*> uses; switch (binaryOp->variantT()) { //All the binary ops that define the LHS 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_SgPointerAssignOp: case V_SgRshiftAssignOp: case V_SgXorAssignOp: case V_SgAssignOp: { //All the uses from the RHS are propagated uses.insert(uses.end(), rhs.getUses().begin(), rhs.getUses().end()); //All the uses from the LHS are propagated, unless we're an assign op uses.insert(uses.end(), lhs.getUses().begin(), lhs.getUses().end()); SgVarRefExp* currentVar = lhs.getCurrentVar(); if (currentVar != NULL) { vector<SgNode*>::iterator currVarUse = find(uses.begin(), uses.end(), currentVar); //An assign op doesn't use the var it's defining. So, remove that var from the uses if (isSgAssignOp(binaryOp)) { if (currVarUse != uses.end()) { uses.erase(currVarUse); } //Also remove the use from the varRef node, because it's not really a use. ssa->getLocalUsesTable()[currentVar].clear(); } //All the other ops always use the var they're defining (+=, -=, /=, etc) else { if (currVarUse == uses.end()) { uses.push_back(currentVar); } } } //Set all the uses as being used at this node addUsesToNode(binaryOp, uses); //Set the current var as being defined here //It's possible that the LHS has no variable references. For example, //foo() = 3, where foo() returns a reference if (currentVar != NULL) { addDefForVarAtNode(currentVar, binaryOp); } return ChildUses(uses, currentVar); } //Otherwise cover all the non-defining Ops default: { //We want to set all the varRefs as being used here std::vector<SgNode*> uses; uses.insert(uses.end(), lhs.getUses().begin(), lhs.getUses().end()); uses.insert(uses.end(), rhs.getUses().begin(), rhs.getUses().end()); //Set all the uses as being used here. addUsesToNode(binaryOp, uses); //Propagate the current variable up. The rhs variable is the one that could be potentially defined up the tree return ChildUses(uses, rhs.getCurrentVar()); } } } //Catch all unary operations here. else if (isSgUnaryOp(node)) { SgUnaryOp* unaryOp = isSgUnaryOp(node); //Now handle the uses. All unary operators use everything in their operand std::vector<SgNode*> uses; if (isSgAddressOfOp(unaryOp) && isSgPointerMemberType(unaryOp->get_type())) { //SgAddressOfOp is special; it's not always a use of its operand. When creating a reference to a member variable, //we create reference without providing a variable instance. For example, // struct foo { int bar; }; // // void test() // { // int foo::*v = &foo::bar; <---- There is no use of foo.bar on this line // foo b; // b.*v = 3; // } //In this case, there are no uses in the operand. We also want to delete any uses for the children vector<SgNode*> successors = SageInterface::querySubTree<SgNode > (unaryOp); foreach(SgNode* successor, successors) { ssa->getLocalUsesTable()[successor].clear(); } } else { //Guard against unary ops that have no children (exception rethrow statement) if (attrs.size() > 0)