ROSE Compiler Framework/Program Translation

From Wikibooks, open books for an open world
Jump to: navigation, search

With its high level intermediate representation, ROSE is suitable for building source-to-source translators. This is achieved by re-structuring the AST of the input source code, then unparsing the transformed AST to the output source code.

Documentation[edit]

Official tutorial: Chapter 32 AST Construction of [ROSE Tutorial http://rosecompiler.org/ROSE_Tutorial/ROSE-Tutorial.pdf]

Many beginners' questions should be readily answered after reading this chapter.

Expected behavior of a ROSE Translator[edit]

A translator built using ROSE is designed to act like a compiler (gcc, g++,gfortran ,etc depending on the input file types).

So users of the translator only need to change the build system for the input files to use the translator instead of the original compiler.

SageBuilder and SageInterface[edit]

The official guide for restructuring/constructing AST highly recommends using helper functions from SageBuilder and SageInterface namespaces to create AST pieces and moving them around. These helper functions try to be stable across low-level changes and be smart enough to transparently set many edges and maintain symbol tables.

Users who want to have lower level control may want to directly invoke the member functions of AST nodes and symbol tables to explicitly manipulate edges and symbols in the AST. But this process is very tedious and error-prone.

It is possible that some builder functions are not yet provided, especially for C++ constructs like template declaration etc. We are actively working on this. In the meantime, you can directly use new operators and other member functions as a workaround.

Steps for writing translators[edit]

Generic steps:

  • prepare a simplest source file (a.c) as an example input of your translator
    • avoid including any system headers so you can visualize the whole AST
    • use ROSE_INSTALLATION_TREE/bin/dotGeneratorWholeASTGraph to generate a whole AST for a.c
  • prepare another simplest source file (b.c) as an example output of your translator
    • again, avoid including any system headers
    • use ROSE_INSTALLATION_TREE/bin/dotGeneratorWholeASTGraph to generate a whole AST for b.c
  • compare the two dot graphs side by side
  • use SageInterface or SageBuilder functions to restruct the source AST graph to be the AST graph you want to generate
    • if there is no SageBuilder function to create what you want. You may have to use new operator to create the nodes and take care of edges, symbols yourself.

More details, see How to create a translator

Order to traverse AST[edit]

Naive pre-order traversal is not suitable for building a translator since the translator may change the nodes the traversal is expected to visit later on. Conceptually, this is essentially a similar problem to C++ iterator invalidation.

To safely transform AST, it is recommended to use a reverse iterator of the statement list generated by a preorder traversal. This is different from a list generated from a post order traversal.

For example, assuming we have a subtree of : parent <child 1, child 2>,

  • Pre order traversal will generate a list: parent, child 1, child2
  • Post order traversal will generate a list: child 1, child2, parent.
  • Reverse iterator of the pre order will give you : child2, child 1, and parent. Transforming using this order is the safest based on our experiences.

Example translators[edit]

There are many test translators under https://github.com/rose-compiler/rose/tree/master/tests/roseTests/astInterfaceTests

  • buildForStmt.C
  • buildFunctionCalls.C
  • buildPragmaDeclaration.C
  • and so on

Other examples:

  • Split one complex statement into multiple simpler statements: ROSE/projects/backstroke/ExtractFunctionArguments.C

Trouble shooting[edit]

Assertion failed: (expr->get_startOfConstruct() != NULL)[edit]

Assertion failed: (expr->get_startOfConstruct() != NULL), function unparseExpression, file ../../../ROSE/src/backend/unparser/languageIndependenceSupport/unparseLanguageIndependentConstructs.C, line 812.

void visitorTraversal::visit(SgNode* sgn){
    
        SageBuilder::pushScopeStack(body);
        SgAssignOp* sao = isSgAssignOp(sgn);
        if(!sao)
            return;
    
        SgVarRefExp* svr = SageBuilder::buildVarRefExp("mami");
        SgIntVal* siv =  SageBuilder::buildIntVal(33);
    
        SgAssignOp* newsao = new SgAssignOp(svr, siv, NULL);
        SageInterface::replaceWithPattern(sao, newsao);
        SageBuilder::popScopeStack();     
    }

The cause is: SgAssignOp* newsao = new SgAssignOp(svr, siv, NULL);

expr->get_startOfConstruct() != NULL says there is no start file position. There is an existing SageBuilder function to build Assign Op and take care of lots of details, including file info objects. Otherwise you have to maintain these details by yourself if you use raw new operators.