2023-09-14 19:43:13 +03:00
# include "fix_common_blocks.h"
using std : : vector ;
using std : : map ;
using std : : set ;
using std : : string ;
using std : : to_string ;
using std : : pair ;
using std : : make_pair ;
using std : : stack ;
using std : : deque ;
using std : : reverse ;
using std : : tuple ;
//// main function --> fixCommonBlocks
////// step1: build union for each common block
/// main function:
// renew unions for all common blocks in the file
static void BuildNewCommDecls ( SgFile * file , const map < string , CommonBlock * > allCommonBlocks ,
map < string , deque < CommConstraint > > & newCommonDecls , map < string , map < string , deque < CommConstraint > > > & commDecls ,
set < string > & badCommon , map < string , set < string > > & notUsedVars , vector < SgStatement * > & programUnits ) ;
// get names of variables and array elements, which were referenced in programm unit
static set < string > getUses ( SgStatement * firstSt , const set < string > & commonVarNames ) ;
static void getUsesFromExpr ( SgExpression * expr , const set < string > & commonVarNames , set < string > & used ) ;
// splits arrays into elements and replaces not used vars with empty constraints
static bool splitType ( deque < CommConstraint > & d , bool check_use , const set < string > & namesOfUsedVars ) ;
// create constraits set
static deque < CommConstraint > makeConstraints ( deque < CommConstraint > & constraints , const set < string > & namesOfUsedVars , set < string > & notUsedVars ) ;
// build union
static bool buildConstraintsUnion ( deque < CommConstraint > & U , deque < CommConstraint > B , const set < string > & namesOfUsedVars , pair < CommConstraint , CommConstraint > & problemConstraints ) ;
static bool docheckUnequalConstraints ( deque < CommConstraint > & U , deque < CommConstraint > & B , deque < CommConstraint > & newU , pair < CommConstraint , CommConstraint > & problemConstraints ) ;
static bool check ( deque < CommConstraint > & A , deque < CommConstraint > & B , pair < CommConstraint , CommConstraint > & problemConstraints ) ;
/// small help functions:
static string getParentName ( const string & name ) ;
static bool equalDims ( const CommConstraint & a , const CommConstraint & b ) ;
static bool equalConstraints ( const CommConstraint & a , const CommConstraint & b ) ;
static void addElem ( deque < CommConstraint > & comm , const CommConstraint & elem ) ;
//////
// change names of variables in 'constraints'
static void fixNames ( deque < CommConstraint > & constraints , const string & commName ) ;
////// step2: transformation
/// main function
// peform transformation on every program unit in the file
static void fixFunctions ( SgFile * file , vector < SgStatement * > programUnits , map < string , deque < CommConstraint > > & newCommonDecls ,
map < string , map < string , deque < CommConstraint > > > & commDecls , const set < string > & badCommon , map < string , set < string > > & notUsedVars ) ;
// get pairs of names (namesOldToNew) for renaming
static bool getNamesOldToNew ( deque < CommConstraint > newDecl , deque < CommConstraint > oldDecl , map < string , string > & namesOldToNew ) ;
// create new symbols for new variables in new common declaration (constraints)
static void makeCommVarSymbs ( const deque < CommConstraint > & constraints , SgFile * file , SgStatement * func , string commName ,
map < string , SgSymbol * > & symbs , vector < SgSymbol * > & needNewDecl ) ;
// delete from program unit all references to names in commVarNames
static void deleteOldVars ( SgStatement * firstSt , const set < string > & commVarNames ) ;
// calls fixExpression for each statement, replaces names in data statement
static void renameVariables ( SgStatement * firstSt , const map < string , SgSymbol * > & newVarSymbs , const map < string , string > & namesOldToNew ) ;
// replacing variables or array elements in expression expr if their names are in namesOldToNew
static SgExpression * fixExpression ( SgExpression * expr , const map < string , SgSymbol * > & newSymbs , const map < string , string > & namesOldToNew ) ;
// make new exprList exprssion for new declaration decl with symbols from newSymbs
static SgExpression * makeExprListForCommon ( const deque < CommConstraint > & decl , const map < string , SgSymbol * > & newSymbs ,
SgFile * file , SgStatement * firstSt ) ;
// replace old common declarations with new ones
static void rewriteCommon ( SgStatement * firstSt , map < string , SgExpression * > & commListExprs ) ;
/// help functions:
static SgExpression * makeIdxFromStr ( const string & str ) ;
// make new expression of array element
static SgExpression * newArrElemExpr ( const string & newName , const map < string , SgSymbol * > & newSymbs ) ;
static bool variablePositionComp ( const Variable * lhs , const Variable * rhs ) ;
//////
CommConstraint : : CommConstraint ( const Variable * var , bool u , const string & funcName , const string & fileName )
{
used = u ;
for ( const auto & use : var - > getAllUse ( ) )
{
if ( use . getFunctionName ( ) = = funcName )
{
SgSymbol * symb = use . getUseS ( ) ;
identifier = symb - > identifier ( ) ;
DeclInfo dInfo = DeclInfo ( identifier , fileName , use . getDeclaratedPlace ( ) - > lineNumber ( ) ) ;
uses . push_back ( dInfo ) ;
if ( ( symb - > attributes ( ) & DATA_BIT ) ! = 0 )
used = true ;
type = symb - > type ( ) ;
typeVariant = type - > variant ( ) ;
vector < SgStatement * > decls ;
declaratedInStmt ( symb , & decls , false ) ;
Distribution : : Array * arr = NULL ;
for ( auto decl : decls )
{
arr = getArrayFromDeclarated ( decl , identifier ) ;
// TODO: for arrays located in the same place in common, with the same names, the same structure will be given,
// even if they have DIFFERENT dimensions (should be different structures)
if ( arr ! = NULL )
break ;
}
if ( arr ! = NULL )
{
arrayInfo = arr ;
size = arr - > GetTypeSize ( ) ;
for ( auto x : arr - > GetSizes ( ) )
size * = x . second - x . first + 1 ;
SgArrayType * arrType = isSgArrayType ( type ) ;
if ( arrType ! = NULL )
typeVariant = arrType - > baseType ( ) - > variant ( ) ;
else
__spf_print ( 1 , " ! array with no array type! \n " ) ;
}
else
size = getSizeOfType ( type ) ;
}
}
}
CommConstraint : : CommConstraint ( const string & name , SgType * t , bool u ) : used ( u ) , type ( t ) , identifier ( name )
{
typeVariant = type - > variant ( ) ;
size = getSizeOfType ( type ) ;
}
CommConstraint : : CommConstraint ( const string & name , SgType * t , bool u , vector < DeclInfo > & us ) : used ( u ) , type ( t ) , identifier ( name ) , uses ( us )
{
typeVariant = type - > variant ( ) ;
size = getSizeOfType ( type ) ;
}
string getParentName ( const string & name )
{
size_t len = name . find ( " % " ) ;
size_t posB = name . find ( " ( " ) ;
if ( len = = string : : npos )
if ( posB = = string : : npos )
return name ;
else
len = posB ;
else if ( posB ! = string : : npos & & posB < len )
len = posB ;
return name . substr ( 0 , len ) ;
}
void getUsesFromExpr ( SgExpression * expr , const set < string > & commonVarNames , set < string > & used )
{
if ( expr = = NULL )
return ;
if ( expr - > variant ( ) = = VAR_REF | | expr - > variant ( ) = = ARRAY_REF )
{
string name = expr - > symbol ( ) - > identifier ( ) ;
if ( commonVarNames . find ( getParentName ( name ) ) ! = commonVarNames . end ( ) )
{
if ( expr - > variant ( ) = = VAR_REF )
used . insert ( name ) ;
else if ( expr - > variant ( ) = = ARRAY_REF )
{
SgArrayRefExp * arrExpr = ( SgArrayRefExp * ) expr ;
if ( arrExpr - > lhs ( ) = = NULL )
used . insert ( name ) ;
else // it's array element
{
SgExpression * exprList = arrExpr - > lhs ( ) ;
bool ok = true ;
int x ;
while ( exprList ! = NULL & & ok ) // TODO: evaluate indexes of elements if they are written using loop variable
{
if ( - 1 = = CalculateInteger ( exprList - > lhs ( ) , x ) )
ok = false ;
exprList = exprList - > rhs ( ) ;
}
if ( ok )
used . insert ( expr - > sunparse ( ) ) ;
else
used . insert ( name ) ;
}
}
}
}
getUsesFromExpr ( expr - > lhs ( ) , commonVarNames , used ) ;
getUsesFromExpr ( expr - > rhs ( ) , commonVarNames , used ) ;
}
set < string > getUses ( SgStatement * firstSt , const set < string > & commonVarNames )
{
set < string > used ;
SgStatement * lastSt = firstSt - > lastNodeOfStmt ( ) ;
for ( SgStatement * curSt = firstSt ; curSt ! = lastSt ; curSt = curSt - > lexNext ( ) )
{
int var = curSt - > variant ( ) ;
if ( var ! = COMM_STAT & & var ! = VAR_DECL & & var ! = VAR_DECL_90 & & var ! = DIM_STAT ) //
{
for ( int i = 0 ; i < 3 ; i + + )
if ( curSt - > expr ( i ) ! = NULL )
getUsesFromExpr ( curSt - > expr ( i ) , commonVarNames , used ) ;
}
}
return used ;
}
bool equalDims ( const CommConstraint & a , const CommConstraint & b )
{
const vector < pair < int , int > > & adim = a . arrayInfo - > GetSizes ( ) ;
const vector < pair < int , int > > & bdim = b . arrayInfo - > GetSizes ( ) ;
if ( adim . size ( ) ! = bdim . size ( ) )
return false ;
for ( int i = 0 ; i < adim . size ( ) ; i + + )
{
if ( adim [ i ] . second - adim [ i ] . first ! = bdim [ i ] . second - bdim [ i ] . first )
return false ;
}
2026-02-18 23:20:58 +03:00
return true ;
2023-09-14 19:43:13 +03:00
}
// TODO: add attributes to CommConstraints, check if a and b have equal attributes
bool equalConstraints ( const CommConstraint & a , const CommConstraint & b )
{
if ( ( a . arrayInfo ! = NULL & & b . arrayInfo = = NULL ) | | ( ( a . arrayInfo = = NULL & & b . arrayInfo ! = NULL ) ) )
return false ;
if ( a . typeVariant ! = b . typeVariant | | a . size ! = b . size )
return false ;
if ( a . arrayInfo ! = NULL )
return a . arrayInfo - > GetTypeSize ( ) = = b . arrayInfo - > GetTypeSize ( ) & & equalDims ( a , b ) ;
return true ;
}
void addElem ( deque < CommConstraint > & comm , const CommConstraint & elem )
{
if ( elem . typeVariant = = 0 & & ! comm . empty ( ) & & comm . back ( ) . typeVariant = = 0 )
comm . back ( ) . size + = elem . size ;
else
comm . push_back ( elem ) ;
}
// TODO: check attributes: do not split arrays with pointer or target attributes if check_use == true
bool splitType ( deque < CommConstraint > & d , bool check_use , const set < string > & namesOfUsedVars = { } )
{
CommConstraint var = d . front ( ) ;
string name = var . identifier ;
if ( var . typeVariant = = 0 | | ( check_use & & var . used ) )
return false ;
if ( var . arrayInfo ! = NULL ) // TODO: arrays can be split not only into individual elements, but also into smaller arrays
{
d . pop_front ( ) ;
const auto dims = var . arrayInfo - > GetSizes ( ) ;
int numOfDims = dims . size ( ) ;
SgType * elemType = new SgType ( var . typeVariant ) ;
int elemNum = var . size / var . arrayInfo - > GetTypeSize ( ) ;
for ( int k = elemNum - 1 ; k > = 0 ; k - - )
{
string newName = name + " ( " ;
int ind = k ;
for ( int i = 0 ; i < numOfDims ; i + + )
{
auto d = dims [ i ] ;
int dimLen = d . second - d . first + 1 ;
newName + = to_string ( ind % dimLen + d . first ) ;
if ( i < numOfDims - 1 )
newName + = " , " ;
ind = ind / dimLen ;
}
newName + = " ) " ;
CommConstraint newVar = CommConstraint ( newName , elemType , var . used , var . uses ) ;
if ( check_use & & ! newVar . used & & namesOfUsedVars . find ( newName ) ! = namesOfUsedVars . end ( ) )
newVar . used = true ;
d . push_front ( newVar ) ;
}
return true ;
}
else
{
if ( check_use & & ( var . used = = false ) )
{
d . pop_front ( ) ;
CommConstraint newVar = CommConstraint ( var . identifier , var . size ) ;
d . push_front ( newVar ) ;
return true ;
}
else
return false ;
}
}
deque < CommConstraint > makeConstraints ( deque < CommConstraint > & constraints , const set < string > & namesOfUsedVars , set < string > & notUsedVars )
{
deque < CommConstraint > res ;
while ( ! constraints . empty ( ) )
{
string curName = constraints . front ( ) . identifier ;
if ( ! splitType ( constraints , true , namesOfUsedVars ) )
{
addElem ( res , constraints . front ( ) ) ;
constraints . pop_front ( ) ;
}
else
notUsedVars . insert ( curName ) ;
}
return res ;
}
bool check ( deque < CommConstraint > & A , deque < CommConstraint > & B , pair < CommConstraint , CommConstraint > & problemConstraints )
{
while ( ! A . empty ( ) & & ! B . empty ( ) )
{
if ( B . front ( ) . size > A . front ( ) . size )
{
if ( ! splitType ( B , false ) )
{
problemConstraints . second = A . front ( ) ;
return false ;
}
}
else if ( B . front ( ) . size < A . front ( ) . size )
{
if ( A . front ( ) . typeVariant = = 0 )
{
A . front ( ) . size - = B . front ( ) . size ;
B . pop_front ( ) ;
}
else
{
problemConstraints . second = A . front ( ) ;
return false ;
}
}
else
{
if ( A . front ( ) . typeVariant ! = 0 & & B . front ( ) . typeVariant ! = 0 & & ! equalConstraints ( A . front ( ) , B . front ( ) ) )
{
problemConstraints . second = A . front ( ) ;
return false ;
}
B . pop_front ( ) ;
A . pop_front ( ) ;
}
}
return true ;
}
bool docheckUnequalConstraints ( deque < CommConstraint > & U , deque < CommConstraint > & B , deque < CommConstraint > & newU , pair < CommConstraint , CommConstraint > & problemConstraints )
{
if ( U . front ( ) . typeVariant = = 0 )
{
addElem ( newU , B . front ( ) ) ;
U . front ( ) . size - = B . front ( ) . size ;
B . pop_front ( ) ;
}
else
{
deque < CommConstraint > temp ;
temp . push_front ( U . front ( ) ) ;
if ( ! check ( B , temp , problemConstraints ) )
{
problemConstraints . first = U . front ( ) ;
return false ;
}
addElem ( newU , U . front ( ) ) ;
U . pop_front ( ) ;
}
return true ;
}
bool buildConstraintsUnion ( deque < CommConstraint > & U , deque < CommConstraint > B , const set < string > & namesOfUsedVars , pair < CommConstraint , CommConstraint > & problemConstraints )
{
deque < CommConstraint > newU ;
while ( ! U . empty ( ) & & ! B . empty ( ) )
{
if ( U . front ( ) . size < B . front ( ) . size )
{
if ( ! docheckUnequalConstraints ( B , U , newU , problemConstraints ) )
return false ;
}
else if ( U . front ( ) . size > B . front ( ) . size )
{
if ( ! docheckUnequalConstraints ( U , B , newU , problemConstraints ) )
return false ;
}
else
{
if ( U . front ( ) . typeVariant = = 0 | | B . front ( ) . typeVariant = = 0
| | equalConstraints ( U . front ( ) , B . front ( ) ) )
{
if ( U . front ( ) . typeVariant = = 0 )
addElem ( newU , B . front ( ) ) ;
else if ( B . front ( ) . typeVariant = = 0 )
addElem ( newU , U . front ( ) ) ;
else
{
U . front ( ) . uses . insert ( U . front ( ) . uses . end ( ) , B . front ( ) . uses . begin ( ) , B . front ( ) . uses . end ( ) ) ; // adding to funcs
addElem ( newU , U . front ( ) ) ;
}
U . pop_front ( ) ;
B . pop_front ( ) ;
}
else
{
problemConstraints = make_pair ( B . front ( ) , U . front ( ) ) ;
return false ;
}
}
}
while ( ! B . empty ( ) )
{
addElem ( newU , B . front ( ) ) ;
B . pop_front ( ) ;
}
while ( ! U . empty ( ) )
{
addElem ( newU , U . front ( ) ) ;
U . pop_front ( ) ;
}
if ( ! newU . empty ( ) & & newU . back ( ) . typeVariant = = 0 )
newU . pop_back ( ) ;
U = newU ;
return true ;
}
bool getNamesOldToNew ( deque < CommConstraint > newDecl , deque < CommConstraint > oldDecl , map < string , string > & namesOldToNew )
{
bool needChange = false ;
map < string , string > rename ;
while ( ! oldDecl . empty ( ) & & ! newDecl . empty ( ) )
{
if ( newDecl . front ( ) . typeVariant = = 0 ) // => oldDecl.front().typeVariant == 0
{
if ( oldDecl . front ( ) . size > newDecl . front ( ) . size )
{
oldDecl . front ( ) . size - = newDecl . front ( ) . size ;
needChange = true ;
}
else
oldDecl . pop_front ( ) ;
newDecl . pop_front ( ) ;
}
else if ( newDecl . front ( ) . size > oldDecl . front ( ) . size )
{
needChange = true ;
deque < CommConstraint > tmp ;
tmp . push_front ( newDecl . front ( ) ) ;
splitType ( tmp , false ) ;
while ( ! tmp . empty ( ) & & ! oldDecl . empty ( ) )
{
if ( oldDecl . front ( ) . typeVariant = = 0 )
{
if ( oldDecl . front ( ) . size > tmp . front ( ) . size )
oldDecl . front ( ) . size - = tmp . front ( ) . size ;
else
oldDecl . pop_front ( ) ;
}
else
{
rename [ oldDecl . front ( ) . identifier ] = tmp . front ( ) . identifier ;
oldDecl . pop_front ( ) ;
}
tmp . pop_front ( ) ;
}
newDecl . pop_front ( ) ;
}
else if ( oldDecl . front ( ) . size > newDecl . front ( ) . size ) // => oldDecl.front().typeVariant == 0
{
needChange = true ;
oldDecl . front ( ) . size - = newDecl . front ( ) . size ;
newDecl . pop_front ( ) ;
}
else // == and newDecl.front().typeVariant != 0
{
if ( oldDecl . front ( ) . typeVariant = = 0 )
needChange = true ;
else
{
if ( oldDecl . front ( ) . identifier . find ( ' ( ' ) ! = string : : npos )
{
needChange = true ;
rename [ oldDecl . front ( ) . identifier ] = newDecl . front ( ) . identifier ;
}
else
rename [ oldDecl . front ( ) . identifier ] = newDecl . front ( ) . identifier ;
}
oldDecl . pop_front ( ) ;
newDecl . pop_front ( ) ;
}
}
if ( ! oldDecl . empty ( ) | | ! newDecl . empty ( ) )
needChange = true ;
if ( needChange )
namesOldToNew . insert ( rename . begin ( ) , rename . end ( ) ) ;
return needChange ;
}
void makeCommVarSymbs ( const deque < CommConstraint > & constraints , SgFile * file , SgStatement * func , string commName ,
map < string , SgSymbol * > & symbs , vector < SgSymbol * > & needNewDecl )
{
for ( const CommConstraint & var : constraints )
{
if ( var . typeVariant ! = 0 )
{
SgSymbol * symb = findSymbolOrCreate ( file , var . identifier , var . type - > copyPtr ( ) , func ) ;
symbs [ var . identifier ] = symb ;
needNewDecl . push_back ( symb ) ;
}
}
}
void deleteOldVars ( SgStatement * firstSt , const set < string > & commVarNames )
{
SgStatement * lastSt = firstSt - > lastNodeOfStmt ( ) ;
vector < SgStatement * > stmtsToDelete ;
for ( SgStatement * curSt = firstSt ; curSt ! = lastSt ; curSt = curSt - > lexNext ( ) )
{
if ( curSt - > variant ( ) = = VAR_DECL | | curSt - > variant ( ) = = VAR_DECL_90 )
{
SgVarDeclStmt * varDeclSt = ( SgVarDeclStmt * ) curSt ;
vector < SgExpression * > varsToDelete ;
for ( int i = 0 ; i < varDeclSt - > numberOfVars ( ) ; i + + )
{
SgExpression * var = varDeclSt - > var ( i ) ;
string varName = " " ;
if ( var - > variant ( ) = = ASSGN_OP )
varName = var - > lhs ( ) - > symbol ( ) - > identifier ( ) ;
else
varName = var - > symbol ( ) - > identifier ( ) ;
if ( commVarNames . find ( varName ) ! = commVarNames . end ( ) )
varsToDelete . push_back ( var ) ;
}
if ( varDeclSt - > numberOfVars ( ) = = varsToDelete . size ( ) )
stmtsToDelete . push_back ( curSt ) ;
else
for ( SgExpression * var : varsToDelete )
varDeclSt - > deleteTheVar ( * var ) ;
}
else if ( curSt - > variant ( ) = = DIM_STAT )
{
SgExpression * ex = curSt - > expr ( 0 ) ;
bool first = true ;
vector < SgExpression * > leftExprs ;
while ( ex ! = NULL )
{
string name = ex - > lhs ( ) - > symbol ( ) - > identifier ( ) ;
if ( commVarNames . find ( name ) = = commVarNames . end ( ) )
leftExprs . push_back ( ex - > lhs ( ) ) ;
ex = ex - > rhs ( ) ;
}
if ( leftExprs . empty ( ) )
stmtsToDelete . push_back ( curSt ) ;
else
curSt - > setExpression ( 0 , makeExprList ( leftExprs ) ) ;
}
// TODO: delete common variables form attributes statements (like DIM_STAT)
}
for ( SgStatement * st : stmtsToDelete )
st - > deleteStmt ( ) ;
}
SgExpression * makeIdxFromStr ( const string & str )
{
vector < SgExpression * > items ;
int num = 0 ;
for ( char c : str )
{
if ( ' 0 ' < = c & & c < = ' 9 ' )
num = num * 10 + ( c - ' 0 ' ) ;
else if ( c = = ' , ' | | c = = ' ) ' )
{
SgExpression * ex = new SgValueExp ( num ) ;
items . push_back ( ex ) ;
num = 0 ;
}
}
reverse ( items . begin ( ) , items . end ( ) ) ;
SgExpression * exprList = makeExprList ( items , false ) ;
return exprList ;
}
SgExpression * newArrElemExpr ( const string & newName , const map < string , SgSymbol * > & newSymbs )
{
size_t pos = newName . find ( ' ( ' ) ;
SgExpression * newExpr = new SgArrayRefExp ( * newSymbs . at ( newName . substr ( 0 , pos ) ) ) ;
newExpr - > setLhs ( makeIdxFromStr ( newName . substr ( pos ) ) ) ;
return newExpr ;
}
SgExpression * fixExpression ( SgExpression * expr , const map < string , SgSymbol * > & newSymbs , const map < string , string > & namesOldToNew )
{
if ( expr = = NULL )
return NULL ;
if ( expr - > variant ( ) = = VAR_REF | | expr - > variant ( ) = = ARRAY_REF )
{
string name = expr - > symbol ( ) - > identifier ( ) ;
auto nameIt = namesOldToNew . find ( name ) ;
if ( nameIt ! = namesOldToNew . end ( ) )
{
string newName = nameIt - > second ;
auto symbIt = newSymbs . find ( newName ) ;
if ( symbIt = = newSymbs . end ( ) ) // variable -> array element
return newArrElemExpr ( newName , newSymbs ) ;
else // variable -> variable or array name -> array name
{
SgSymbol * newSymb = symbIt - > second ;
expr - > setSymbol ( newSymb ) ;
}
}
else
{
string fullName = expr - > sunparse ( ) ;
auto fullNameIt = namesOldToNew . find ( fullName ) ;
if ( fullNameIt ! = namesOldToNew . end ( ) )
{
string newName = fullNameIt - > second ;
auto symbIt = newSymbs . find ( newName ) ;
if ( symbIt = = newSymbs . end ( ) ) // array element -> array element
return newArrElemExpr ( newName , newSymbs ) ;
else // array element -> variable
{
SgVariableSymb * varSymb = ( SgVariableSymb * ) symbIt - > second ;
SgExpression * newExpr = new SgVarRefExp ( * varSymb ) ;
return newExpr ;
}
}
}
}
SgExpression * lhs = fixExpression ( expr - > lhs ( ) , newSymbs , namesOldToNew ) ;
if ( lhs ! = NULL )
expr - > setLhs ( lhs ) ;
SgExpression * rhs = fixExpression ( expr - > rhs ( ) , newSymbs , namesOldToNew ) ;
if ( rhs ! = NULL )
expr - > setRhs ( rhs ) ;
return NULL ;
}
void renameVariables ( SgStatement * firstSt , const map < string , SgSymbol * > & newVarSymbs , const map < string , string > & namesOldToNew )
{
SgStatement * lastSt = firstSt - > lastNodeOfStmt ( ) ;
for ( SgStatement * curSt = firstSt ; curSt ! = NULL & & curSt ! = lastSt ; curSt = curSt - > lexNext ( ) )
{
if ( curSt - > variant ( ) = = DATA_DECL )
{
SgValueExp * dataExpr = ( SgValueExp * ) curSt - > expr ( 0 ) ;
map < string , string > data = splitData ( { dataExpr } ) ;
string newDataStr = " data " ;
bool needChange = false ;
int left = data . size ( ) ;
for ( pair < const string , string > & item : data )
{
auto nameIt = namesOldToNew . find ( item . first ) ;
if ( nameIt ! = namesOldToNew . end ( ) )
{
newDataStr + = nameIt - > second + " / " + item . second + " / " ;
needChange = true ;
}
else
newDataStr + = item . first + " / " + item . second + " / " ;
left - - ;
if ( left ! = 0 )
newDataStr + = " , " ;
}
if ( needChange )
{
SgExpression * es = new SgExpression ( STMT_STR ) ;
char * value = ( char * ) malloc ( newDataStr . size ( ) + 1 ) ;
value [ newDataStr . size ( ) ] = ' \0 ' ;
memcpy ( value , newDataStr . c_str ( ) , sizeof ( char ) * newDataStr . size ( ) ) ;
es - > thellnd - > entry . string_val = value ;
curSt - > setExpression ( 0 , es ) ;
}
}
else if ( isSgExecutableStatement ( curSt ) | | curSt - > variant ( ) = = EQUI_STAT )
{
for ( int i = 0 ; i < 3 ; i + + )
{
SgExpression * expr = fixExpression ( curSt - > expr ( i ) , newVarSymbs , namesOldToNew ) ;
if ( expr ! = NULL )
curSt - > setExpression ( i , expr ) ;
}
}
}
}
SgExpression * makeExprListForCommon ( const deque < CommConstraint > & decl , const map < string , SgSymbol * > & newSymbs ,
SgFile * file , SgStatement * firstSt )
{
vector < SgExpression * > items ;
for ( auto it = decl . rbegin ( ) ; it ! = decl . rend ( ) ; it + + )
{
if ( it - > typeVariant = = 0 )
continue ;
SgSymbol * symb = NULL ;
bool old = false ;
auto symbIt = newSymbs . find ( it - > identifier ) ;
if ( symbIt ! = newSymbs . end ( ) )
symb = symbIt - > second ;
else
{
symb = findSymbolOrCreate ( file , it - > identifier , it - > type , firstSt ) ;
old = true ;
}
SgVariableSymb * varSymb = isSgVariableSymb ( symb ) ;
if ( varSymb - > type ( ) - > variant ( ) = = T_ARRAY )
{
SgExpression * newExpr = new SgArrayRefExp ( * varSymb ) ;
items . push_back ( newExpr ) ;
}
else
{
SgExpression * newExpr = new SgVarRefExp ( symb ) ;
items . push_back ( newExpr ) ;
}
}
SgExpression * exprList = makeExprList ( items , false ) ;
return exprList ;
}
void rewriteCommon ( SgStatement * firstSt , map < string , SgExpression * > & commListExprs )
{
vector < SgStatement * > commonStmtsToDelete ;
for ( SgStatement * st = firstSt ; st ! = firstSt - > lastDeclaration ( ) - > lexNext ( ) ; st = st - > lexNext ( ) )
{
if ( st - > variant ( ) = = COMM_STAT )
{
SgExpression * ex = st - > expr ( 0 ) ;
bool first = true ;
SgExpression * prev = NULL ;
while ( ex ! = NULL )
{
string commName = " " ;
SgSymbol * s = ex - > symbol ( ) ;
if ( s = = NULL )
commName = " spf_unnamed " ;
else
commName = s - > identifier ( ) ;
auto commIt = commListExprs . find ( commName ) ;
if ( commIt ! = commListExprs . end ( ) )
{
if ( commIt - > second ! = NULL )
{
ex - > setLhs ( commIt - > second ) ;
commIt - > second = NULL ;
if ( first )
first = false ;
prev = ex ;
ex = ex - > rhs ( ) ;
}
else
{
if ( first )
{
st - > setExpression ( 0 , ex - > rhs ( ) ) ;
ex = st - > expr ( 0 ) ;
}
else
{
prev - > setRhs ( ex - > rhs ( ) ) ;
ex = prev - > rhs ( ) ;
}
}
}
else
ex = ex - > rhs ( ) ;
}
if ( st - > expr ( 0 ) = = NULL )
commonStmtsToDelete . push_back ( st ) ;
}
}
for ( SgStatement * st : commonStmtsToDelete )
st - > deleteStmt ( ) ;
}
void fixNames ( deque < CommConstraint > & constraints , const string & commName )
{
for ( auto & var : constraints )
{
for ( char & c : var . identifier )
{
if ( c = = ' ) ' | | c = = ' ( ' )
c = ' l ' ;
if ( c = = ' , ' )
c = ' _ ' ;
}
var . identifier = commName + " _ " + var . identifier ;
}
}
bool variablePositionComp ( const Variable * lhs , const Variable * rhs )
{
return lhs - > getPosition ( ) < rhs - > getPosition ( ) ;
}
void fixFunctions ( SgFile * file , vector < SgStatement * > programUnits , map < string , deque < CommConstraint > > & newCommonDecls ,
map < string , map < string , deque < CommConstraint > > > & commDecls , const set < string > & badCommon , map < string , set < string > > & notUsedVars )
{
for ( SgStatement * unitSt : programUnits )
{
string funcName = unitSt - > symbol ( ) - > identifier ( ) ;
if ( commDecls . find ( funcName ) = = commDecls . end ( ) )
continue ;
SgStatement * firstSt = unitSt ;
map < string , SgExpression * > commListExprs ;
map < string , SgSymbol * > newVarSymbs ; // new symbols for new variables
map < string , string > namesOldToNew ; // for ranaming: old name -> new name
vector < SgSymbol * > needNewDecl ;
for ( auto & common : commDecls [ funcName ] )
{
string commName = common . first ;
if ( badCommon . find ( commName ) ! = badCommon . end ( ) )
continue ;
const deque < CommConstraint > & newDecl = newCommonDecls . at ( commName ) ;
vector < CommConstraint > varsNeedNewSymb ;
bool needChange = getNamesOldToNew ( newDecl , common . second , namesOldToNew ) ;
if ( ! needChange )
continue ;
makeCommVarSymbs ( newDecl , file , firstSt , commName , newVarSymbs , needNewDecl ) ;
commListExprs [ commName ] = makeExprListForCommon ( newDecl , newVarSymbs , file , firstSt ) ;
}
if ( ! commListExprs . empty ( ) )
{
for ( const auto & item : commListExprs )
for ( const auto & x : commDecls [ funcName ] [ item . first ] )
notUsedVars [ funcName ] . insert ( x . identifier ) ;
deleteOldVars ( unitSt , notUsedVars [ funcName ] ) ;
renameVariables ( unitSt , newVarSymbs , namesOldToNew ) ;
makeDeclaration ( needNewDecl , unitSt ) ;
rewriteCommon ( firstSt , commListExprs ) ;
}
}
}
void BuildNewCommDecls ( SgFile * file , const map < string , CommonBlock * > allCommonBlocks ,
map < string , deque < CommConstraint > > & newCommonDecls , map < string , map < string , deque < CommConstraint > > > & commDecls ,
set < string > & badCommon , map < string , set < string > > & notUsedVars , vector < SgStatement * > & programUnits )
{
string fileName = file - > filename ( ) ;
SgStatement * curSt = file - > firstStatement ( ) ;
while ( curSt ! = NULL )
{
if ( curSt - > variant ( ) = = PROG_HEDR | | curSt - > variant ( ) = = PROC_HEDR | | curSt - > variant ( ) = = FUNC_HEDR | | curSt - > variant ( ) = = BLOCK_DATA | | curSt - > variant ( ) = = MODULE_STMT )
{
programUnits . push_back ( curSt ) ;
string funcName = curSt - > symbol ( ) - > identifier ( ) ;
for ( auto item : allCommonBlocks )
{
string commName = item . first ;
if ( badCommon . find ( commName ) ! = badCommon . end ( ) )
continue ;
CommonBlock * commonBlock = item . second ;
vector < const Variable * > vars = commonBlock - > getVariables ( fileName , funcName ) ;
if ( vars . size ( ) = = 0 )
continue ;
sort ( vars . begin ( ) , vars . end ( ) , variablePositionComp ) ;
set < string > varNames ;
for ( const Variable * var : vars )
varNames . insert ( var - > getName ( ) ) ;
set < string > namesOfUsedVars = getUses ( curSt , varNames ) ;
bool hasChar = false ;
bool hasNotChar = false ;
deque < CommConstraint > constraints ;
for ( const Variable * var : vars )
{
CommConstraint newConstr = CommConstraint ( var , false , funcName , fileName ) ;
if ( newConstr . typeVariant = = T_STRING | | newConstr . typeVariant = = T_ARRAY ) // ignore common blocks with strings
hasChar = true ;
else
hasNotChar = true ;
if ( namesOfUsedVars . find ( newConstr . identifier ) ! = namesOfUsedVars . end ( ) )
newConstr . used = true ;
constraints . push_back ( newConstr ) ;
}
if ( hasChar & & hasNotChar ) // TDOO: make proper warning message or separate such common blocks
__spf_print ( 1 , " common block '%s' ('%s':%d) contains variables of symbolic and numeric types. It is required to divide \n " , commName . c_str ( ) , fileName . c_str ( ) , constraints . back ( ) . uses . back ( ) . lineNum ) ;
if ( hasChar )
{
badCommon . insert ( commName ) ;
continue ;
}
deque < CommConstraint > curComm = makeConstraints ( constraints , namesOfUsedVars , notUsedVars [ funcName ] ) ;
commDecls [ funcName ] [ commName ] = curComm ;
bool res ;
pair < CommConstraint , CommConstraint > problemConstraints ;
res = buildConstraintsUnion ( newCommonDecls [ commName ] , curComm , namesOfUsedVars , problemConstraints ) ;
if ( ! res )
{
badCommon . insert ( commName ) ;
for ( auto x : problemConstraints . first . uses ) // TODO: make proper warning message
for ( auto y : problemConstraints . second . uses )
__spf_print ( 1 , " variables '%s' and '%s' in one storage association (common block '%s') have different types (files - %s:%d and %s:%d) \n " ,
x . varName . c_str ( ) , y . varName . c_str ( ) , commName . c_str ( ) , x . fileName . c_str ( ) , x . lineNum , y . fileName . c_str ( ) , y . lineNum ) ;
}
}
curSt = curSt - > lastNodeOfStmt ( ) ;
}
else
curSt = curSt - > lexNext ( ) ;
}
}
// main function
void fixCommonBlocks ( const map < string , vector < FuncInfo * > > allFuncInfo , const map < string , CommonBlock * > allCommonBlocks , SgProject * project ) // TODO: separate into 2 steps?
{
int filesNum = project - > numberOfFiles ( ) ;
map < string , map < string , map < string , deque < CommConstraint > > > > commDecls ; // file_name -> function_name -> common block name -> old declaration of common block
map < string , deque < CommConstraint > > newCommonDecls ; // name of common block -> cur builded declaration
map < string , set < string > > notUsedVars ;
map < string , vector < SgStatement * > > programUnitsInFile ;
set < string > badCommon ;
for ( int i = 0 ; i < filesNum ; i + + ) // first step
{
SgFile * file = & project - > file ( i ) ;
string fileName = file - > filename ( ) ;
file - > switchToFile ( fileName ) ;
BuildNewCommDecls ( file , allCommonBlocks , newCommonDecls , commDecls [ fileName ] , badCommon , notUsedVars , programUnitsInFile [ fileName ] ) ;
}
for ( auto & elem : newCommonDecls )
fixNames ( elem . second , elem . first ) ;
for ( int i = 0 ; i < filesNum ; i + + ) // second step
{
SgFile * file = & project - > file ( i ) ;
string fileName = file - > filename ( ) ;
file - > switchToFile ( fileName ) ;
fixFunctions ( file , programUnitsInFile [ fileName ] , newCommonDecls , commDecls [ fileName ] , badCommon , notUsedVars ) ;
}
}