ROSE Compiler Framework/transformation tracking
An experimental feature to keep track of transformation
Design
editThe transformation tracking or IR mapping information
- each AST node is assigned a unique integer ID, based on a preorder traversal of the AST.
- a transformation generated node (affected node) is connected with one or more input nodes.
- stored in std::map<AST_NODE_ID, std::set<AST_NODE_ID> > , map from an affected node to its input node sets
This is a rarely used feature. To avoid memory/computation overhead, we store information in separated memory , not directly extending AST node's members.
The tracking is based on unique IDs of AST nodes. To disable memory reuse of deleted AST nodes, it is recommended to configure ROSE with
- --enable-memory-pool-no-reuse Enable special memory pool model: no reuse of deleted memory (default is to reuse memory)
APIs
editThe source code and API functions are defined in https://github.com/rose-compiler/rose-develop/tree/master/src/midend/programTransformation/transformationTracking
From
//! Assign Ids and save current File Info. void registerAstSubtreeIds (SgNode* root); // get unique ID AST_NODE_ID getId (SgNode* ); // check if a node has been assigned a unique ID bool hasId (SgNode* n); //Obtain the SgNode from an ID SgNode* getNode (AST_NODE_ID id); // the input AST node IDs for a transformation generated node. extern std::map<AST_NODE_ID, std::set<AST_NODE_ID> > inputIDs; // This should be called after the transformation is completed and all IDs are assigned. void addInputNode(SgNode* affected_node, SgNode* inputnode);
from transformationTracking.cpp: internal two maps/tables store IDs and memory addresses
// the following data structures are for internal use only std::map <SgNode*, unsigned int > AstToIdTable; // reverse lookup , oops, if they are one-to-one mapping, how a single node obtains multiple IDs? std::map <unsigned int, SgNode*> IdToAstTable;
example use
edit// Assign portable and unique IDs for all located nodes in AST TransformationTracking::registerAstSubtreeIds (project); // Dump AST dotgraph with unique IDs , for debugging purpose // Test unique ID assignment and dot graph generation TransformationTracking::registerAstSubtreeIds (sageProject); generateWholeGraphOfAST("wholeAST-v1"); AstDOTGeneration astdotgen; astdotgen.generate(sageProject,AstDOTGeneration::TOPDOWNBOTTOMUP, "v1"); // record the input node of an affected node after some transformation // patch up IDs for the changed subtree TransformationTracking::registerAstSubtreeIds (orig_scope); std::vector <SgVariableDeclaration*>::iterator iter; for (iter = newly_inserted_copied_decls.begin(); iter!= newly_inserted_copied_decls.end(); iter++) { //TransformationTracking::addInputNode (affected_node, input_node) TransformationTracking::addInputNode (*iter, decl); } // retrieve stored mapping information std::map<AST_NODE_ID, std::set<AST_NODE_ID> >::iterator iter; for (iter = TransformationTracking::inputIDs.begin(); iterĀ != TransformationTracking::inputIDs.end(); iter++) { std::set<AST_NODE_ID> ids = (*iter).second; if (ids.size()>0) { string src_comment = "Transformation generated based on "; cout<<"Found a node with IR mapping info"<<endl; SgNode* affected_node = TransformationTracking::getNode((*iter).first); cout<<isSgLocatedNode(affected_node)->unparseToString()<<endl; cout<<"-- with input nodes ----------"<<endl; std::set<AST_NODE_ID>::iterator iditer; for(iditer = ids.begin(); iditerĀ != ids.end(); iditer ++) { SgNode* input_node = TransformationTracking::getNode((*iditer)); SgLocatedNode* lnode = isSgLocatedNode(input_node); cout<<lnode->unparseToString()<<endl; cout<<"//Transformation generated based on line #"<< lnode->get_file_info()->get_line() <<endl; src_comment += " line # " + StringUtility::numberToString(lnode->get_file_info()->get_line()); } src_comment +="\n"; SgStatement* enclosing_stmt = getEnclosingStatement(affected_node); attachComment (enclosing_stmt, src_comment); } // end if ids.size() >0 } // end for inputIDs