ROSE Compiler Framework/transformation tracking

An experimental feature to keep track of transformation

Design edit

The 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 edit

The source code and API functions are defined in


 //! 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);

    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<<"-- 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<<"//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