ROSE Compiler Framework/Program Translation

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

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

List of translation

edit

List

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.

Processing pragmas

edit

Main article at ROSE Compiler Framework/Processing Pragmas

It is often useful to use pragmas to guide a translator.

A set of parser building functions are provided to help create recursive descent parsers:

Once you include the header AstFromString.h (located in src/frontend/SageIII/astFromString), you can access the variables and functions defined in the namespace.

There is an example project doing pragma parsing and saving the results into AST attributes. https://github.com/rose-compiler/rose-develop/tree/master/projects/pragmaParsing

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

Prepare the output of your translator

  • prepare a simplest source file (b.c) as an example output of your translator
    • avoid including any system headers
    • use ROSE_INSTALLATION_TREE/bin/dotGeneratorWholeASTGraph to generate a whole AST for b.c , more details for visualize AST are available at How to visualize AST.
  • study the dot graph for AST node types and their parent-child relations.
  • 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

Other examples:

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

Transformation Tracking

edit

See Transformation tracking

Abstract Handles

edit

strings used to pinpoint source code constructs. Useful to pass loops, functions etc. to a translator for processing, more at

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.