Assignment Insertion in ROSE compiler after AssignOp

147 views Asked by At

Lately I've been working with the ROSE compiler and I was able to apply a few insertions of code into C source and get a successful output. However, I haven't been able to insert an assignment statement when visiting SgAssignOps. This is a simplified version of my code to show the problem:

#include "rose.h"
#include <iostream>
#include <transformationSupport.h>
using namespace SageInterface;
using namespace SageBuilder;
using namespace std;

int main (int argc, char *argv[])
{
    SgProject *project = frontend (argc, argv);

    // Find all Assignment operations
    std::vector<SgNode* > assignOpList = NodeQuery::querySubTree (project, V_SgAssignOp);

    std::vector<SgNode*>::iterator iter;

    for (iter = assignOpList.begin(); iter!= assignOpList.end(); iter++) { 

        SgNode * node = (*iter);

        SgStatement * asmStmt = TransformationSupport::getStatement(node);

        //ADD PRAGMA STATEMENT BEFORE       
        ostringstream osPragma;
        osPragma << "example statement";
        SgPragmaDeclaration* pragmaDecl = buildPragmaDeclaration(osPragma.str());
        insertStatementBefore(asmStmt, pragmaDecl);

        //ADD ASSIGNMENT STATEMENT AFTER
        SgExprStatement* newAsmt = buildAssignStatement(buildVarRefExp("a"),buildIntVal(9));
        insertStatementAfter(asmStmt,newAsmt);
    }

    AstTests::runAllTests(project); 
    // Translation only
    project->unparse();
}

A simple input code:

int main(int argc, char* argv[])
{
    int a;

    a = 3;

    return a;

}

The code compiles. However..

When applied to the input code I get a segmentation fault, no error messages.

If I remove the assignment statement insertion, the pragma insertion works.

If I remove the call to runAllTests() I get the following error message when unparsing:

test: /mnt/DATA/rose/src/backend/unparser/nameQualificationSupport.C:4986: virtual NameQualificationInheritedAttribute NameQualificationTraversal::evaluateInheritedAttribute(SgNode*, NameQualificationInheritedAttribute): Assertion `initializedName->get_parent() != __null' failed.
Aborted (core dumped)

Notice I'm using "a" in this example and in the input code, so the variable is already declared.

What would be the right way to make an assignment insertion like that?

The provided example in the tutorial uses the scope on the main function body and inserts it at the end, I need it to happen after another assignment. Do I need to push the Scope on the node to the ScopeStack? And if so, how would that be expressed? I'm not very familiar with the push and pop scope stack methods.

2

There are 2 answers

0
joseppinilla On

OK... while writing my questions I realized I had to give the scope methods another chance.

I found that setting the scope to the function worked, therefore:

    pushScopeStack (TransformationSupport::getFunctionDeclaration(node)->get_scope());
    SgExprStatement* newAsmt = buildAssignStatement(buildVarRefExp("a"),buildIntVal(9));        
    insertStatementAfter(asmStmt,newAsmt);
    popScopeStack();

I feel like this is the right way to do it, but I still feel there's documentation missing about the use of these methods and the ScopeStack in general.

0
Cole Nelson On

This is old, but answering for people with this problem in the future.

The error actually comes from when you are calling buildVarRefExp and buildPragmaDeclaration. As can bee seen through doxygen, they take an optional parameter for SgScopeStatement. This scope statement is where SageBuilder finds the variable referenced (github source). If it is not given, it takes it from the ScopeStack. However, when you haven't pushed anything onto the ScopeStack and call these functions without the optional parameter, it does not know where to look.

So, your two solutions are:

  1. Use the ScopeStack for storing the SgScopeStatement (eg pushScopeStack)
  2. Pass the SgScopeStatement into buildVarRefExp and buildPragmaDeclaration as an argument.

In your case specifically, you could do:

SgScopeStatement scope = TransformationSupport::getFunctionDeclaration(node)->get_scope();

And replace your SageBuilder statements with:

buildPragmaDeclaration(osPragma.str(), scope);
buildVarRefExp("a", scope);