2025-06-02 19:08:09 +03:00
# include "leak_detector.h"
2023-09-14 19:43:13 +03:00
# include <cstdio>
# include <cstdlib>
# include <cstring>
# include <cstdint>
# include <map>
# include <vector>
# include <set>
# include <string>
# include <stack>
# include "dvm.h"
# include "graph_calls_func.h"
2024-05-11 15:38:41 +03:00
# include "../CFGraph/CFGraph.h"
# include "../GraphLoop/graph_loops_func.h"
2023-09-14 19:43:13 +03:00
# include "../DirectiveProcessing/directive_parser.h"
# include "../Utils/SgUtils.h"
2025-04-13 17:24:49 +03:00
# include "../Utils/json.hpp"
2023-09-14 19:43:13 +03:00
# include "../ParallelizationRegions/ParRegions_func.h"
# include "../DynamicAnalysis/gCov_parser_func.h"
2025-06-02 19:08:09 +03:00
# include "expr_transform.h"
2023-09-14 19:43:13 +03:00
# include "../LoopAnalyzer/loop_analyzer.h"
# include "../VerificationCode/verifications.h"
using std : : vector ;
using std : : map ;
using std : : set ;
using std : : pair ;
using std : : tuple ;
using std : : string ;
using std : : wstring ;
using std : : make_pair ;
using std : : to_string ;
using std : : cout ;
using std : : endl ;
using std : : stack ;
2025-04-13 17:24:49 +03:00
using json = nlohmann : : json ;
2023-09-14 19:43:13 +03:00
# define DEBUG 0
//TODO: improve parameter checking
2023-11-22 20:21:18 +03:00
void correctNameIfContains ( SgStatement * call , SgExpression * exCall , string & name ,
const vector < SgStatement * > & containsFunctions , const string & prefix )
2023-09-14 19:43:13 +03:00
{
if ( containsFunctions . size ( ) < = 0 )
return ;
if ( call = = NULL & & exCall = = NULL )
return ;
for ( auto & func : containsFunctions )
{
if ( func - > symbol ( ) - > identifier ( ) = = name )
{
int numPar = 0 ;
if ( call & & call - > variant ( ) = = PROC_STAT )
numPar = isSgCallStmt ( call ) - > numberOfArgs ( ) ;
else if ( exCall & & exCall - > variant ( ) = = FUNC_CALL )
numPar = isSgFunctionCallExp ( exCall ) - > numberOfArgs ( ) ;
else
return ;
SgProgHedrStmt * f = ( SgProgHedrStmt * ) func ;
//XXX
if ( f - > numberOfParameters ( ) = = numPar )
name = prefix + name ;
break ;
}
}
}
extern map < tuple < int , string , string > , pair < DIST : : Array * , DIST : : ArrayAccessInfo * > > declaredArrays ;
extern map < SgStatement * , set < tuple < int , string , string > > > declaratedArraysSt ;
extern int getIntrinsicFunctionType ( const char * name ) ;
static parF detectType ( SgType * type )
{
parF retT = UNKNOWN_T ;
int len = getSizeOfType ( type ) ;
int var = type - > variant ( ) ;
switch ( var )
{
case DEFAULT :
break ;
case T_INT :
if ( len = = 0 | | len = = 4 )
retT = SCALAR_INT_T ;
else if ( len = = 8 )
retT = SCALAR_LONG_INT_T ;
else if ( len = = 2 )
retT = SCALAR_SHORT_T ;
break ;
case T_FLOAT :
if ( len = = 0 | | len = = 4 )
retT = SCALAR_FLOAT_T ;
else if ( len = = 8 )
retT = SCALAR_DOUBLE_T ;
break ;
case T_DOUBLE :
if ( len = = 0 | | len = = 8 )
retT = SCALAR_DOUBLE_T ;
break ;
case T_CHAR :
if ( len = = 0 | | len = = 4 )
retT = SCALAR_CHAR_T ;
break ;
case T_BOOL :
if ( len = = 0 | | len = = 4 )
retT = SCALAR_BOOL_T ;
break ;
case T_STRING :
retT = STRING_T ;
break ;
case T_COMPLEX :
if ( len = = 0 | | len = = 4 )
retT = SCALAR_CMPLX_FLOAT_T ;
else if ( len = = 8 )
retT = SCALAR_CMPLX_DOUBLE_T ;
break ;
case T_DCOMPLEX :
if ( len = = 0 | | len = = 8 )
retT = SCALAR_CMPLX_DOUBLE_T ;
break ;
}
return retT ;
}
static void fillParam ( const int i , SgSymbol * parIn , FuncParam & currParams , const map < string , vector < SgExpression * > > & commonBlocks , bool isArrayRef ,
bool isExternal = false )
{
SgSymbol * par = OriginalSymbol ( parIn ) ;
currParams . parametersT [ i ] = UNKNOWN_T ;
if ( ( par - > attributes ( ) & OPTIONAL_BIT ) ! = 0 )
currParams . inout_types [ i ] | = OPTIONAL_BIT ;
if ( ( par - > attributes ( ) & EXTERNAL_BIT ) | | isExternal )
{
currParams . parametersT [ i ] = EXTERNAL_T ;
return ;
}
if ( par - > variant ( ) = = FUNCTION_NAME )
{
if ( isIntrinsicFunctionName ( par - > identifier ( ) ) )
{
const int type = getIntrinsicFunctionType ( par - > identifier ( ) ) ;
if ( type = = T_DOUBLE )
currParams . parametersT [ i ] = SCALAR_DOUBLE_T ;
else if ( type = = T_FLOAT )
currParams . parametersT [ i ] = SCALAR_FLOAT_T ;
}
else
{
SgType * type = par - > type ( ) ;
currParams . parametersT [ i ] = detectType ( type ) ;
}
return ;
}
SgType * type = par - > type ( ) ;
if ( type )
{
const int varT = type - > variant ( ) ;
if ( isArrayType ( type ) )
{
currParams . parametersT [ i ] = ARRAY_T ;
SgStatement * decl = declaratedInStmt ( par ) ;
auto uniqKey = getUniqName ( commonBlocks , decl , par ) ;
auto itArray = declaredArrays . find ( uniqKey ) ;
if ( itArray = = declaredArrays . end ( ) )
{
__spf_print ( 1 , " array was not in declared list: '%s' \n " , par - > identifier ( ) ) ;
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
}
currParams . parameters [ i ] = itArray - > second . first ;
}
else if ( isStringArrayType ( type ) )
{
if ( isArrayRef )
currParams . parametersT [ i ] = STRING_T ;
else
currParams . parametersT [ i ] = STRING_ARRAY_T ;
}
else
currParams . parametersT [ i ] = detectType ( type ) ;
}
else
{
//printf("var = %d %s\n", par->variant(), tag[par->variant()]);
currParams . parametersT [ i ] = UNKNOWN_T ;
}
}
static void fillFuncParams ( FuncInfo * currInfo , const map < string , vector < SgExpression * > > & commonBlocks , SgProgHedrStmt * procHeader )
{
int numOfParams = procHeader - > numberOfParameters ( ) ;
FuncParam & currParams = currInfo - > funcParams ;
currParams . init ( numOfParams ) ;
if ( numOfParams > 0 )
2024-05-11 15:38:41 +03:00
{
2023-09-14 19:43:13 +03:00
for ( int i = 0 ; i < numOfParams ; + + i )
fillParam ( i , procHeader - > parameter ( i ) , currParams , commonBlocks , false ) ;
2024-05-11 15:38:41 +03:00
for ( int i = 0 ; i < procHeader - > numberOfParameters ( ) ; + + i )
{
currInfo - > funcParams . identificators . push_back ( ( procHeader - > parameter ( i ) ) - > identifier ( ) ) ;
currInfo - > isParamUsedAsIndex . push_back ( false ) ;
}
}
2023-09-14 19:43:13 +03:00
}
static void fillFuncParams ( FuncInfo * currInfo , const map < string , vector < SgExpression * > > & commonBlocks , SgStatement * entryHeader )
{
SgExpression * parList = entryHeader - > expr ( 0 ) ;
int numOfParams = 0 ;
for ( SgExpression * p = parList ; p ; p = p - > rhs ( ) )
numOfParams + + ;
FuncParam & currParams = currInfo - > funcParams ;
currParams . init ( numOfParams ) ;
if ( numOfParams > 0 )
{
SgExpression * p = parList ;
for ( int i = 0 ; i < numOfParams ; + + i , p = p - > rhs ( ) )
{
fillParam ( i , p - > lhs ( ) - > symbol ( ) , currParams , commonBlocks , ( p - > lhs ( ) - > lhs ( ) | | p - > lhs ( ) - > rhs ( ) ) ) ;
currInfo - > funcParams . identificators . push_back ( p - > lhs ( ) - > symbol ( ) - > identifier ( ) ) ;
currInfo - > isParamUsedAsIndex . push_back ( false ) ;
}
}
}
static parF detectMaxTypeOfExpression ( SgExpression * ex )
{
if ( ! ex )
return UNKNOWN_T ;
parF res = UNKNOWN_T ;
if ( ex - > variant ( ) = = VAR_REF )
{
if ( ex - > symbol ( ) & & ex - > symbol ( ) - > type ( ) )
res = detectType ( ex - > symbol ( ) - > type ( ) ) ;
}
else if ( isArrayRef ( ex ) )
{
if ( ex - > symbol ( ) & & ex - > symbol ( ) - > type ( ) - > baseType ( ) )
res = detectType ( ex - > symbol ( ) - > type ( ) - > baseType ( ) ) ;
}
else if ( ex - > variant ( ) = = CONST_REF )
{
if ( ex - > type ( ) )
res = detectType ( ex - > type ( ) ) ;
}
else if ( ex - > variant ( ) > = INT_VAL & & ex - > variant ( ) < = STRING_VAL | | ex - > variant ( ) = = COMPLEX_VAL )
{
if ( ex - > type ( ) )
res = detectType ( ex - > type ( ) ) ;
}
else
{
parF lF = UNKNOWN_T , rF = UNKNOWN_T ;
if ( ex - > lhs ( ) )
lF = detectMaxTypeOfExpression ( ex - > lhs ( ) ) ;
if ( ex - > rhs ( ) )
rF = detectMaxTypeOfExpression ( ex - > rhs ( ) ) ;
res = MAX ( res , lF ) ;
res = MAX ( res , rF ) ;
}
return res ;
}
parF detectExpressionType ( SgExpression * exp ) {
const int var = exp - > variant ( ) ;
if ( var = = INT_VAL )
return SCALAR_INT_T ;
else if ( var = = FLOAT_VAL )
return SCALAR_FLOAT_T ;
else if ( var = = DOUBLE_VAL )
return SCALAR_DOUBLE_T ;
else if ( var = = CHAR_VAL )
return SCALAR_CHAR_T ;
else if ( var = = BOOL_VAL )
return SCALAR_BOOL_T ;
else if ( exp - > variant ( ) = = VAR_REF & & exp - > symbol ( ) & & ( exp - > symbol ( ) - > attributes ( ) & EXTERNAL_BIT ) )
return EXTERNAL_T ;
else
{
SgType * type = exp - > type ( ) ;
if ( type )
{
if ( type - > variant ( ) = = DEFAULT )
return detectMaxTypeOfExpression ( exp ) ;
else
return detectType ( type ) ;
}
else
return UNKNOWN_T ;
}
}
//TODO:: add values
static void processActualParams ( SgExpression * parList , const map < string , vector < SgExpression * > > & commonBlocks , FuncParam & currParams ,
const set < string > & externalCall )
{
int numOfPar = 0 ;
for ( SgExpression * ex = parList ; ex ! = NULL ; ex = ex - > rhs ( ) )
numOfPar + + ;
currParams . init ( numOfPar ) ;
if ( numOfPar > 0 )
{
int num = 0 ;
for ( SgExpression * ex = parList ; ex ! = NULL ; ex = ex - > rhs ( ) , + + num )
{
if ( ex - > lhs ( ) & & ex - > lhs ( ) - > lhs ( ) = = NULL & & ex - > lhs ( ) - > rhs ( ) = = NULL )
currParams . identificators . push_back ( string ( ex - > lhs ( ) - > unparse ( ) ) ) ;
else
currParams . identificators . push_back ( " " ) ;
if ( ex - > lhs ( ) - > symbol ( ) )
fillParam ( num , ex - > lhs ( ) - > symbol ( ) , currParams , commonBlocks , ( ex - > lhs ( ) - > lhs ( ) | | ex - > lhs ( ) - > rhs ( ) ) ,
externalCall . find ( ex - > lhs ( ) - > symbol ( ) - > identifier ( ) ) ! = externalCall . end ( ) ) ;
else
{
parF parf = detectExpressionType ( ex - > lhs ( ) ) ;
currParams . parametersT [ num ] = parf ;
if ( parf = = SCALAR_INT_T )
{
2024-04-09 11:51:21 +03:00
SgExpression * result = CalculateInteger ( ex - > lhs ( ) - > copyPtr ( ) ) ;
2023-09-14 19:43:13 +03:00
if ( result ! = ex - > lhs ( ) )
{
currParams . parameters [ num ] = new int [ 1 ] ;
addToCollection ( __LINE__ , __FILE__ , currParams . parameters [ num ] , 2 ) ;
( ( int * ) currParams . parameters [ num ] ) [ 0 ] = result - > valueInteger ( ) ;
}
}
}
}
}
}
2024-05-11 15:38:41 +03:00
static void findFuncCalls ( SgStatement * parent , SgExpression * curr , FuncInfo * procInfo , const int line ,
2023-09-14 19:43:13 +03:00
const map < string , vector < SgExpression * > > & commonBlocks , const set < string > & macroNames ,
const vector < SgStatement * > & containsFunctions , const string & prefix )
{
if ( curr - > variant ( ) = = FUNC_CALL & & macroNames . find ( curr - > symbol ( ) - > identifier ( ) ) = = macroNames . end ( ) )
{
2024-05-11 15:38:41 +03:00
vector < string > nameOfCallFunc ;
nameOfCallFunc . push_back ( curr - > symbol ( ) - > identifier ( ) ) ;
nameOfCallFunc . push_back ( OriginalSymbol ( curr - > symbol ( ) ) - > identifier ( ) ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
for ( auto & elem : nameOfCallFunc )
correctNameIfContains ( NULL , curr , elem , containsFunctions , prefix ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
procInfo - > callsFrom . insert ( nameOfCallFunc . begin ( ) , nameOfCallFunc . end ( ) ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
FuncInfoCallFrom newCall ;
newCall . detailCallsFrom = make_pair ( nameOfCallFunc [ 1 ] , line ) ; // original name of call
newCall . pointerDetailCallsFrom = make_pair ( curr , FUNC_CALL ) ;
newCall . parentForPointer = parent ;
newCall . actualParams = FuncParam ( ) ;
2023-11-05 13:08:57 +03:00
2024-05-11 15:38:41 +03:00
processActualParams ( curr - > lhs ( ) , commonBlocks , newCall . actualParams , procInfo - > externalCalls ) ;
procInfo - > callsFromDetailed . push_back ( newCall ) ;
2023-09-14 19:43:13 +03:00
}
if ( curr - > lhs ( ) )
2024-05-11 15:38:41 +03:00
findFuncCalls ( parent , curr - > lhs ( ) , procInfo , line , commonBlocks , macroNames , containsFunctions , prefix ) ;
2023-09-14 19:43:13 +03:00
if ( curr - > rhs ( ) )
2024-05-11 15:38:41 +03:00
findFuncCalls ( parent , curr - > rhs ( ) , procInfo , line , commonBlocks , macroNames , containsFunctions , prefix ) ;
2023-09-14 19:43:13 +03:00
}
static void findReplaceSymbolByExpression ( SgExpression * parentEx , SgExpression * findIn , int pos ,
const string & symbol , SgExpression * replace ,
vector < tuple < SgExpression * , int , SgExpression * > > & replaces )
{
if ( findIn )
{
if ( findIn - > symbol ( ) )
if ( findIn - > symbol ( ) - > identifier ( ) = = symbol )
replaces . push_back ( std : : make_tuple ( parentEx , pos , replace - > copyPtr ( ) ) ) ;
findReplaceSymbolByExpression ( findIn , findIn - > lhs ( ) , 0 , symbol , replace , replaces ) ;
findReplaceSymbolByExpression ( findIn , findIn - > rhs ( ) , 1 , symbol , replace , replaces ) ;
}
}
static void doMacroExpand ( SgStatement * parent , SgExpression * parentEx , SgExpression * findIn , int pos ,
const map < string , SgStatement * > & macroStats ,
const set < string > & macroNames , bool & needToIterate ,
vector < Messages > & messages )
{
if ( findIn )
{
if ( findIn - > variant ( ) = = FUNC_CALL & & macroNames . find ( string ( findIn - > symbol ( ) - > identifier ( ) ) ) ! = macroNames . end ( ) )
{
const string funcName = string ( findIn - > symbol ( ) - > identifier ( ) ) ;
auto it = macroStats . find ( funcName ) ;
SgStatement * macroStat = it - > second ;
vector < SgExpression * > parameters ;
for ( SgExpression * list = findIn - > lhs ( ) ; list ; list = list - > rhs ( ) )
parameters . push_back ( list - > lhs ( ) - > copyPtr ( ) ) ;
SgExpression * toInsert = macroStat - > expr ( 0 ) - > lhs ( ) - > copyPtr ( ) ;
if ( parentEx = = NULL )
parent - > setExpression ( pos , * toInsert ) ;
else
{
if ( pos = = 0 )
parentEx - > setLhs ( * toInsert ) ;
else if ( pos = = 1 )
parentEx - > setRhs ( * toInsert ) ;
}
SgSymbol * declSymb = macroStat - > expr ( 0 ) - > symbol ( ) ;
int parN = lenghtOfParamList ( declSymb - > thesymb ) ;
vector < tuple < SgExpression * , int , SgExpression * > > replaces ;
for ( int z = 0 ; z < parN ; + + z )
{
SgSymbol * toExpand = SymbMapping ( GetThParam ( declSymb - > thesymb , z ) ) ;
findReplaceSymbolByExpression ( toInsert , toInsert - > lhs ( ) , 0 , toExpand - > identifier ( ) , parameters [ z ] , replaces ) ;
findReplaceSymbolByExpression ( toInsert , toInsert - > rhs ( ) , 1 , toExpand - > identifier ( ) , parameters [ z ] , replaces ) ;
}
for ( auto & repl : replaces )
{
if ( std : : get < 1 > ( repl ) = = 0 )
std : : get < 0 > ( repl ) - > setLhs ( std : : get < 2 > ( repl ) ) ;
else if ( std : : get < 1 > ( repl ) = = 1 )
std : : get < 0 > ( repl ) - > setRhs ( std : : get < 2 > ( repl ) ) ;
}
needToIterate = true ;
wstring messageE , messageR ;
__spf_printToLongBuf ( messageE , L " substitute statement function with name '%s' " , to_wstring ( funcName ) . c_str ( ) ) ;
__spf_printToLongBuf ( messageR , R101 , to_wstring ( funcName ) . c_str ( ) ) ;
messages . push_back ( Messages ( NOTE , parent - > lineNumber ( ) , messageR , messageE , 2006 ) ) ;
}
doMacroExpand ( parent , findIn , findIn - > lhs ( ) , 0 , macroStats , macroNames , needToIterate , messages ) ;
doMacroExpand ( parent , findIn , findIn - > rhs ( ) , 1 , macroStats , macroNames , needToIterate , messages ) ;
}
}
void doMacroExpand ( SgFile * file , vector < Messages > & messages )
{
for ( int i = 0 ; i < file - > numberOfFunctions ( ) ; + + i )
{
SgStatement * st = file - > functions ( i ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
map < string , SgStatement * > macroStats ;
set < string > macroNames ;
while ( st ! = lastNode )
{
if ( st = = NULL )
{
__spf_print ( 1 , " internal error in analysis, parallel directives will not be generated for this file! \n " ) ;
break ;
}
if ( ! isSgExecutableStatement ( st ) )
{
if ( st - > variant ( ) = = STMTFN_STAT )
{
macroStats . insert ( make_pair ( st - > expr ( 0 ) - > symbol ( ) - > identifier ( ) , st ) ) ;
macroNames . insert ( st - > expr ( 0 ) - > symbol ( ) - > identifier ( ) ) ;
}
}
else
break ;
st = st - > lexNext ( ) ;
}
if ( macroStats . size ( ) > 0 )
{
bool needToIterate = true ;
while ( needToIterate )
{
needToIterate = false ;
for ( SgStatement * stat = st ; stat ! = lastNode ; stat = stat - > lexNext ( ) )
for ( int i = 1 ; i < 3 ; + + i )
if ( stat - > expr ( i ) )
doMacroExpand ( stat , NULL , stat - > expr ( i ) , i , macroStats , macroNames , needToIterate , messages ) ;
}
}
}
}
static void findIdxRef ( SgExpression * exp , FuncInfo & currInfo )
{
if ( exp )
{
if ( exp - > variant ( ) = = VAR_REF )
{
for ( int i = 0 ; i < currInfo . funcParams . identificators . size ( ) ; i + + )
{
if ( exp - > symbol ( ) - > identifier ( ) = = currInfo . funcParams . identificators [ i ] )
currInfo . isParamUsedAsIndex [ i ] = true ;
}
}
findIdxRef ( exp - > lhs ( ) , currInfo ) ;
findIdxRef ( exp - > rhs ( ) , currInfo ) ;
}
}
static void findArrayRef ( SgExpression * exp , FuncInfo & currInfo , bool isWrite )
{
if ( exp )
{
if ( isArrayRef ( exp ) )
{
DIST : : Array * arrayRef = NULL ;
SgSymbol * symbS = OriginalSymbol ( exp - > symbol ( ) ) ;
const string symb = symbS - > identifier ( ) ;
if ( symbS )
arrayRef = getArrayFromDeclarated ( declaratedInStmt ( symbS ) , symb ) ;
else
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( arrayRef )
{
// only distributed arrays were added
if ( arrayRef - > IsNotDistribute ( ) = = false )
{
// Through all indexes
for ( SgExpression * ex = exp ; ex ! = NULL ; ex = ex - > rhs ( ) )
findIdxRef ( exp - > lhs ( ) , currInfo ) ;
currInfo . allUsedArrays . insert ( arrayRef ) ;
if ( isWrite )
currInfo . usedArraysWrite . insert ( arrayRef ) ;
}
}
}
else
{
findArrayRef ( exp - > lhs ( ) , currInfo , isWrite ) ;
findArrayRef ( exp - > rhs ( ) , currInfo , isWrite ) ;
}
}
}
static void findParamInParam ( SgExpression * exp , FuncInfo & currInfo )
{
// Searching through expression, which parameter presented with
if ( exp )
{
2025-02-10 12:16:52 +03:00
if ( exp - > variant ( ) = = VAR_REF | | isArrayRef ( exp ) )
2023-09-14 19:43:13 +03:00
{
// check for matching with one of param of func which called this
//cout << "Checking " << exp->symbol()->identifier() << " for match.." << endl;
for ( int i = 0 ; i < currInfo . funcParams . identificators . size ( ) ; i + + )
{
const string & parName = currInfo . funcParams . identificators [ i ] ;
//cout << " with " << parName << ".. ";
if ( exp - > symbol ( ) - > identifier ( ) = = parName )
{
//cout << "Success." << endl;
NestedFuncCall & currNestedFuncCall = currInfo . funcsCalledFromThis . back ( ) ;
currNestedFuncCall . NoOfParamUsedForCall . back ( ) . push_back ( i ) ;
break ;
}
}
}
// do not search further if found, cause VAR_REF is always a leaf
else
{
findParamInParam ( exp - > lhs ( ) , currInfo ) ;
findParamInParam ( exp - > rhs ( ) , currInfo ) ;
}
}
}
static bool hasRecCall ( const FuncInfo * proc , const vector < string > & newNames )
{
bool has = false ;
for ( auto & toAdd : newNames )
if ( proc - > funcName = = toAdd )
has = true ;
return has ;
}
static void findParamUsedInFuncCalls ( SgExpression * exp , FuncInfo & currInfo , const vector < SgStatement * > & containsFunctions , const string & prefix ) ;
static void throughParams ( SgExpression * pars , FuncInfo & currInfo , const vector < SgStatement * > & containsFunctions , const string & prefix )
{
for ( SgExpression * par = pars ; par ! = NULL ; par = par - > rhs ( ) )
{
// initialize vector representing parameter #parNo
NestedFuncCall & currNestedFuncCall = currInfo . funcsCalledFromThis . back ( ) ;
currNestedFuncCall . NoOfParamUsedForCall . push_back ( vector < int > ( ) ) ;
findParamInParam ( par - > lhs ( ) , currInfo ) ;
}
// search another func call, possibly used in parameter
for ( SgExpression * par = pars ; par ! = NULL ; par = par - > rhs ( ) )
findParamUsedInFuncCalls ( pars - > lhs ( ) , currInfo , containsFunctions , prefix ) ;
}
// Takes random expression, finds there func calls and check their parameters
// for using parameters of func where first is called from
static void findParamUsedInFuncCalls ( SgExpression * exp , FuncInfo & currInfo ,
const vector < SgStatement * > & containsFunctions , const string & prefix )
{
if ( exp )
{
if ( exp - > variant ( ) = = FUNC_CALL )
{
vector < string > nameOfCallFunc ;
nameOfCallFunc . push_back ( exp - > symbol ( ) - > identifier ( ) ) ;
nameOfCallFunc . push_back ( OriginalSymbol ( exp - > symbol ( ) ) - > identifier ( ) ) ;
for ( auto & elem : nameOfCallFunc )
correctNameIfContains ( NULL , exp , elem , containsFunctions , prefix ) ;
if ( ! hasRecCall ( & currInfo , nameOfCallFunc ) )
{
// Add func call which we've just found
2025-02-10 12:16:52 +03:00
currInfo . funcsCalledFromThis . push_back ( NestedFuncCall ( nameOfCallFunc [ 1 ] ) ) ;
2023-09-14 19:43:13 +03:00
// For every found func call iterate through pars
//cout << "Through params of the call of " << exp->symbol()->identifier() << endl;
throughParams ( exp - > lhs ( ) , currInfo , containsFunctions , prefix ) ;
}
}
else
{
// If we've not found func call, search further in all branches
findParamUsedInFuncCalls ( exp - > rhs ( ) , currInfo , containsFunctions , prefix ) ;
findParamUsedInFuncCalls ( exp - > lhs ( ) , currInfo , containsFunctions , prefix ) ;
}
}
}
static void printParInfo ( const map < string , vector < FuncInfo * > > & allFuncInfo )
{
cout < < " *********Which parameters of current function are used in func calls inside it********* " < < endl ;
for ( auto & file1 : allFuncInfo )
{
for ( auto & currInfo : file1 . second )
{
cout < < currInfo - > funcName < < " calls to: " < < endl ;
for ( auto & calledFunc : currInfo - > funcsCalledFromThis )
{
cout < < " " < < calledFunc . CalledFuncName < < " with params: " < < endl ;
int parNo = 0 ;
for ( auto & paramOfCalled : calledFunc . NoOfParamUsedForCall )
{
cout < < " " < < parNo < < " : " ;
for ( auto & paramOfCalling : paramOfCalled )
cout < < currInfo - > funcParams . identificators [ paramOfCalling ] < < " " ;
parNo + + ;
cout < < endl ;
}
}
}
}
cout < < endl ;
cout < < " *********Which parameters of current function are used as indices for arrays********* " < < endl ;
for ( auto & file1 : allFuncInfo )
{
for ( auto & currInfo : file1 . second )
{
cout < < currInfo - > funcName < < endl ;
for ( size_t i = 0 ; i < currInfo - > isParamUsedAsIndex . size ( ) ; i + + )
{
cout < < currInfo - > funcParams . identificators [ i ] < < " : " ;
if ( currInfo - > isParamUsedAsIndex [ i ] )
cout < < " used " < < endl ;
else
cout < < " not used " < < endl ;
}
}
}
cout < < endl ;
}
void findContainsFunctions ( SgStatement * st , vector < SgStatement * > & found , const bool searchAll )
{
SgStatement * end = st - > lastNodeOfStmt ( ) ;
bool containsStarted = false ;
for ( ; st ! = end ; st = st - > lexNext ( ) )
{
if ( containsStarted )
{
if ( st - > variant ( ) = = PROC_HEDR | | st - > variant ( ) = = FUNC_HEDR )
{
found . push_back ( st ) ;
st = searchAll ? st : st - > lastNodeOfStmt ( ) ;
}
else if ( ! searchAll & & st - > variant ( ) = = CONTAINS_STMT )
break ;
}
if ( st - > variant ( ) = = CONTAINS_STMT )
containsStarted = true ;
}
}
2025-02-10 12:16:52 +03:00
static void fillIn ( FuncInfo * currF , SgExpression * ex , const map < string , int > & parNames , bool isInFuncPar )
2023-09-14 19:43:13 +03:00
{
if ( ex )
{
2025-02-10 12:16:52 +03:00
if ( ! isInFuncPar & & ( ex - > variant ( ) = = VAR_REF | | isArrayRef ( ex ) ) )
2023-09-14 19:43:13 +03:00
{
const char * name = ex - > symbol ( ) - > identifier ( ) ;
if ( name & & name ! = string ( " " ) )
{
auto it = parNames . find ( name ) ;
if ( it ! = parNames . end ( ) )
currF - > funcParams . inout_types [ it - > second ] | = IN_BIT ;
}
}
2025-02-10 12:16:52 +03:00
if ( ex - > variant ( ) = = FUNC_CALL ) {
SgFunctionCallExp * call = ( SgFunctionCallExp * ) ex ;
for ( int z = 0 ; z < call - > numberOfArgs ( ) ; + + z )
fillIn ( currF , call - > arg ( z ) , parNames , true ) ;
}
else {
fillIn ( currF , ex - > lhs ( ) , parNames , false ) ;
fillIn ( currF , ex - > rhs ( ) , parNames , false ) ;
}
2023-09-14 19:43:13 +03:00
}
}
2024-05-12 13:37:42 +03:00
static void fillType ( FuncInfo * currF , const string & symb , const map < string , int > & parNames , const int type )
2023-09-14 19:43:13 +03:00
{
if ( symb ! = " " )
{
auto it = parNames . find ( symb ) ;
if ( it ! = parNames . end ( ) )
2024-05-12 13:37:42 +03:00
currF - > funcParams . inout_types [ it - > second ] | = type ;
2023-09-14 19:43:13 +03:00
}
}
static void checkSpecList ( SgExpression * pair , FuncInfo * currF , const map < string , int > & parNames , int )
{
auto valExp = isSgKeywordValExp ( pair - > lhs ( ) ) ;
if ( valExp - > value ( ) = = string ( " unit " ) )
if ( pair - > rhs ( ) & & pair - > rhs ( ) - > symbol ( ) )
2024-05-12 13:37:42 +03:00
fillType ( currF , pair - > rhs ( ) - > symbol ( ) - > identifier ( ) , parNames , INOUT_BIT ) ;
2023-09-14 19:43:13 +03:00
}
static void checkSpecList ( SgExpression * spec , FuncInfo * currF , const map < string , int > & parNames )
{
if ( spec - > variant ( ) = = SPEC_PAIR )
checkSpecList ( spec , currF , parNames , 0 ) ;
else
{
while ( spec )
{
if ( spec - > lhs ( ) - > variant ( ) = = SPEC_PAIR )
checkSpecList ( spec - > lhs ( ) , currF , parNames , 0 ) ;
spec = spec - > rhs ( ) ;
}
}
}
2024-05-11 15:38:41 +03:00
static void fillInOut ( FuncInfo * currF , SgStatement * start , SgStatement * last , const set < SgStatement * > & activeOps )
2023-09-14 19:43:13 +03:00
{
if ( currF - > funcParams . countOfPars = = 0 )
return ;
static map < string , vector < int > > supportedKeyWordArg = { { " system_clock " , { OUT_BIT , OUT_BIT , OUT_BIT } } } ;
map < string , int > parNames ;
for ( int i = 0 ; i < currF - > funcParams . identificators . size ( ) ; + + i )
parNames [ currF - > funcParams . identificators [ i ] ] = i ;
for ( auto st = start ; st ! = last ; st = st - > lexNext ( ) )
{
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
if ( st - > variant ( ) = = ENTRY_STAT )
continue ;
if ( isSgExecutableStatement ( st ) = = NULL | | st - > lineNumber ( ) < = 0 )
continue ;
2024-05-11 15:38:41 +03:00
if ( activeOps . size ( ) & & activeOps . find ( st ) = = activeOps . end ( ) )
continue ;
2023-09-14 19:43:13 +03:00
if ( st - > variant ( ) = = ASSIGN_STAT )
{
SgExpression * left = st - > expr ( 0 ) ;
2025-02-10 12:16:52 +03:00
fillIn ( currF , left - > lhs ( ) , parNames , false ) ;
fillIn ( currF , left - > rhs ( ) , parNames , false ) ;
fillIn ( currF , st - > expr ( 1 ) , parNames , false ) ;
2023-09-14 19:43:13 +03:00
string symb = " " ;
if ( left - > symbol ( ) )
symb = left - > symbol ( ) - > identifier ( ) ;
else if ( left - > variant ( ) = = ARRAY_OP )
{
if ( left - > lhs ( ) - > symbol ( ) )
symb = left - > lhs ( ) - > symbol ( ) - > identifier ( ) ;
}
2024-05-12 13:37:42 +03:00
fillType ( currF , symb , parNames , OUT_BIT ) ;
2023-09-14 19:43:13 +03:00
} // TODO: need to extend
else if ( st - > variant ( ) = = READ_STAT )
{
SgInputOutputStmt * read = isSgInputOutputStmt ( st ) ;
if ( read = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
for ( auto ex = read - > itemList ( ) ; ex ; ex = ex - > rhs ( ) )
{
SgExpression * item = ex - > lhs ( ) ;
if ( item - > variant ( ) = = VAR_REF | | isArrayRef ( item ) )
{
string symb = " " ;
if ( item - > symbol ( ) )
symb = item - > symbol ( ) - > identifier ( ) ;
2024-05-12 13:37:42 +03:00
fillType ( currF , symb , parNames , OUT_BIT ) ;
2023-09-14 19:43:13 +03:00
}
else if ( item - > variant ( ) = = IOACCESS )
{
SgExpression * list = item - > lhs ( ) ;
stack < SgExpression * > queue ;
queue . push ( list ) ;
while ( ! queue . empty ( ) )
{
auto item = queue . top ( ) ;
queue . pop ( ) ;
if ( item - > lhs ( ) )
queue . push ( item - > lhs ( ) ) ;
if ( item - > rhs ( ) )
queue . push ( item - > rhs ( ) ) ;
if ( item - > variant ( ) = = VAR_REF | | isArrayRef ( item ) )
{
string symb = " " ;
if ( item - > symbol ( ) )
symb = item - > symbol ( ) - > identifier ( ) ;
2024-05-12 13:37:42 +03:00
fillType ( currF , symb , parNames , OUT_BIT ) ;
2023-09-14 19:43:13 +03:00
}
}
}
}
checkSpecList ( read - > specList ( ) , currF , parNames ) ;
} // TODO: need to extend
else if ( st - > variant ( ) = = WRITE_STAT )
{
SgInputOutputStmt * write = isSgInputOutputStmt ( st ) ;
if ( write = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
checkSpecList ( write - > specList ( ) , currF , parNames ) ;
}
else if ( ! isDVM_stat ( st ) )
{
bool processed = false ;
//TODO: for FUNC_CALL
if ( st - > variant ( ) = = PROC_STAT & & isIntrinsicFunctionName ( st - > symbol ( ) - > identifier ( ) ) )
{
const string name = st - > symbol ( ) - > identifier ( ) ;
if ( supportedKeyWordArg . find ( name ) ! = supportedKeyWordArg . end ( ) )
{
int z = 0 ;
const vector < int > & types = supportedKeyWordArg [ name ] ;
for ( auto ex = st - > expr ( 0 ) ; ex ; ex = ex - > rhs ( ) , + + z )
{
SgExpression * arg = ex - > lhs ( ) ;
if ( arg - > variant ( ) = = KEYWORD_ARG )
{
arg = arg - > rhs ( ) ;
if ( types . size ( ) < = z )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( types [ z ] = = OUT_BIT | | types [ z ] = = INOUT_BIT )
2024-05-12 13:37:42 +03:00
fillType ( currF , arg - > symbol ( ) - > identifier ( ) , parNames , OUT_BIT ) ;
2023-09-14 19:43:13 +03:00
if ( types [ z ] = = IN_BIT | | types [ z ] = = INOUT_BIT )
2025-02-10 12:16:52 +03:00
fillIn ( currF , arg , parNames , false ) ;
2023-09-14 19:43:13 +03:00
}
else
2025-02-10 12:16:52 +03:00
fillIn ( currF , arg , parNames , false ) ;
2023-09-14 19:43:13 +03:00
}
processed = true ;
}
}
2025-02-10 12:16:52 +03:00
if ( ! processed )
{
if ( st - > variant ( ) = = PROC_STAT )
{
SgCallStmt * call = ( SgCallStmt * ) st ;
for ( int z = 0 ; z < call - > numberOfArgs ( ) ; + + z )
fillIn ( currF , call - > arg ( z ) , parNames , true ) ;
}
else
{
for ( int i = 0 ; i < 3 ; + + i )
fillIn ( currF , st - > expr ( i ) , parNames , false ) ;
}
}
2023-09-14 19:43:13 +03:00
}
}
}
//TODO: check common block and module use
2024-05-11 15:38:41 +03:00
static void fillFunctionPureStatus ( SgStatement * header , FuncInfo * currInfo , vector < Messages > & messagesForFile , const set < SgStatement * > & activeOps )
2023-09-14 19:43:13 +03:00
{
if ( ! currInfo - > isMain )
{
set < int > lines ;
2024-05-11 15:38:41 +03:00
bool hasIntent = hasThisIds ( header , lines , { INTENT_STMT } , & activeOps ) ;
2023-09-14 19:43:13 +03:00
bool declaratedAsPure = ( header - > symbol ( ) - > attributes ( ) & PURE_BIT ) ;
if ( declaratedAsPure & & ! hasIntent & & ( ( SgProgHedrStmt * ) header ) - > numberOfParameters ( ) )
{
messagesForFile . push_back ( Messages ( ERROR , header - > lineNumber ( ) , R143 , L " Wrong pure declaration - INTENT mismatch " , 4002 ) ) ;
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
}
if ( currInfo - > commonBlocks . size ( ) = = 0 )
{
lines . clear ( ) ;
2024-02-02 21:02:11 +03:00
bool has = hasThisIds ( header , lines , { DATA_DECL , SAVE_DECL , USE_STMT ,
WRITE_STAT , READ_STAT , OPEN_STAT , CLOSE_STAT ,
2024-05-11 15:38:41 +03:00
PRINT_STAT , STOP_STAT , PAUSE_NODE } ,
& activeOps ) ;
2023-09-14 19:43:13 +03:00
if ( ! has | | declaratedAsPure )
currInfo - > isPure = true ;
else
{
for ( auto & line : lines )
messagesForFile . push_back ( Messages ( WARR , line , R93 , L " Function is impure due to this operator usage " , 1049 ) ) ;
}
}
else if ( declaratedAsPure )
currInfo - > isPure = true ;
}
else
currInfo - > isPure = true ;
}
static void fillCommons ( FuncInfo * currInfo , const map < string , vector < SgExpression * > > & commonBlocks )
{
for ( auto & item : commonBlocks )
{
auto inserted = currInfo - > commonBlocks . insert ( make_pair ( item . first , set < string > ( ) ) ) ;
for ( auto & list : item . second )
{
SgExpression * expr_list = list - > lhs ( ) ;
while ( expr_list ! = NULL )
{
SgExpression * var = expr_list - > lhs ( ) ;
expr_list = expr_list - > rhs ( ) ;
inserted . first - > second . insert ( var - > symbol ( ) - > identifier ( ) ) ;
}
}
}
}
2024-05-25 17:41:28 +03:00
static void printActiveLines ( const set < SgStatement * > & activeOps )
{
set < int > lines ;
for ( auto & st : activeOps )
lines . insert ( st - > lineNumber ( ) ) ;
for ( auto & line : lines )
printf ( " %d \n " , line ) ;
}
2024-05-11 15:38:41 +03:00
static FuncInfo * createNewFuction ( const string & funcName , SgStatement * st , SgStatement * entry ,
vector < Messages > & messagesForFile ,
const map < string , vector < SgExpression * > > & commonBlocks ,
const set < SgStatement * > & activeOps )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
FuncInfo * currInfo = new FuncInfo ( funcName , make_pair ( entry - > lineNumber ( ) , lastNode - > lineNumber ( ) ) , new Statement ( entry ) ) ;
hasThisIds ( st , currInfo - > linesOfIO , { WRITE_STAT , READ_STAT , OPEN_STAT , CLOSE_STAT , PRINT_STAT } , & activeOps ) ;
hasThisIds ( st , currInfo - > linesOfStop , { STOP_STAT , PAUSE_NODE } , & activeOps ) ;
currInfo - > isMain = ( st - > variant ( ) = = PROG_HEDR ) ;
fillCommons ( currInfo , commonBlocks ) ;
fillFunctionPureStatus ( st , currInfo , messagesForFile , activeOps ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( st - > variant ( ) ! = PROG_HEDR )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
SgProgHedrStmt * procFuncHedr = ( ( SgProgHedrStmt * ) st ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( st = = entry )
fillFuncParams ( currInfo , commonBlocks , procFuncHedr ) ;
2023-09-14 19:43:13 +03:00
else
2024-05-11 15:38:41 +03:00
fillFuncParams ( currInfo , commonBlocks , entry ) ;
fillInOut ( currInfo , st , lastNode , activeOps ) ;
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( isSPF_NoInline ( new Statement ( st - > lexNext ( ) ) ) )
{
__spf_print ( 1 , " set NOINLINE attribute for function '%s' \n " , funcName . c_str ( ) ) ;
currInfo - > doNotInline = true ;
}
2025-02-10 12:16:52 +03:00
2024-05-11 15:38:41 +03:00
return currInfo ;
}
2023-09-14 19:43:13 +03:00
2024-05-12 13:37:42 +03:00
static FuncInfo * analyzeFunction ( const string & funcName , const string & containsPrefix ,
SgStatement * function , SgStatement * entry , map < string , vector < FuncInfo * > > & allFuncInfo ,
const map < int , LoopGraph * > & mapLoopGraph , vector < Messages > & messagesForFile ,
vector < SgStatement * > & containsFunctions ,
const set < SgStatement * > & activeOps )
2024-05-11 15:38:41 +03:00
{
SgStatement * st = function ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
const string fileName = function - > fileName ( ) ;
auto it = allFuncInfo . find ( fileName ) ;
if ( it = = allFuncInfo . end ( ) )
it = allFuncInfo . insert ( it , make_pair ( fileName , vector < FuncInfo * > ( ) ) ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
map < string , vector < SgExpression * > > commonBlocks ;
getCommonBlocksRef ( commonBlocks , function , lastNode ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( function - > controlParent ( ) - > variant ( ) = = GLOBAL )
containsFunctions . clear ( ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
findContainsFunctions ( function , containsFunctions ) ;
auto procInfo = createNewFuction ( funcName , function , entry , messagesForFile , commonBlocks , activeOps ) ;
it - > second . push_back ( procInfo ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
vector < SgStatement * > macroStats ;
set < string > macroNames ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
while ( st ! = lastNode )
{
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( st - > variant ( ) = = INTERFACE_STMT )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
st = st - > lexNext ( ) ;
while ( st & & ! ( st - > controlParent ( ) - > variant ( ) = = INTERFACE_STMT & & st - > variant ( ) = = CONTROL_END ) )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
if ( st - > variant ( ) = = PROC_HEDR | | st - > variant ( ) = = FUNC_HEDR )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
procInfo - > interfaceBlocks [ st - > symbol ( ) - > identifier ( ) ] = NULL ;
st = st - > lastNodeOfStmt ( ) ;
2023-09-14 19:43:13 +03:00
}
2024-05-11 15:38:41 +03:00
st = st - > lexNext ( ) ;
2023-09-14 19:43:13 +03:00
}
2024-05-11 15:38:41 +03:00
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( st = = NULL )
{
__spf_print ( 1 , " internal error in analysis, parallel directives will not be generated for this file! \n " ) ;
break ;
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( ! isSgExecutableStatement ( st ) )
{
if ( st - > variant ( ) = = STMTFN_STAT )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
macroStats . push_back ( st ) ;
macroNames . insert ( st - > expr ( 0 ) - > symbol ( ) - > identifier ( ) ) ;
2023-09-14 19:43:13 +03:00
}
}
2024-05-11 15:38:41 +03:00
else
break ;
st = st - > lexNext ( ) ;
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
st = function ;
const string file = st - > fileName ( ) ;
while ( st ! = lastNode )
{
if ( st = = NULL )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
__spf_print ( 1 , " internal error in analysis, parallel directives will not be generated for this file! \n " ) ;
break ;
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( ! __gcov_doesThisLineExecuted ( st - > fileName ( ) , st - > lineNumber ( ) ) | |
st - > variant ( ) = = ENTRY_STAT )
{
st = st - > lexNext ( ) ;
continue ;
}
if ( activeOps . size ( ) )
{
if ( st - > fileName ( ) = = file & &
isSgExecutableStatement ( st ) & &
activeOps . find ( st ) = = activeOps . end ( ) )
2023-09-14 19:43:13 +03:00
{
st = st - > lexNext ( ) ;
continue ;
}
2024-05-11 15:38:41 +03:00
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
// check for external calls
if ( st - > variant ( ) = = EXTERN_STAT )
for ( SgExpression * ex = st - > expr ( 0 ) ; ex ; ex = ex - > rhs ( ) )
if ( ex - > lhs ( ) - > symbol ( ) )
procInfo - > externalCalls . insert ( ex - > lhs ( ) - > symbol ( ) - > identifier ( ) ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
const string prefix = containsPrefix = = " " ? string ( function - > symbol ( ) - > identifier ( ) ) + " . " : containsPrefix ;
//printf("var %d, line %d, file %s\n", st->variant(), st->lineNumber(), st->fileName());
if ( st - > variant ( ) = = PROC_STAT )
{
vector < string > pureNameOfCallFunc ;
pureNameOfCallFunc . push_back ( removeString ( " call " , st - > symbol ( ) - > identifier ( ) ) ) ;
pureNameOfCallFunc . push_back ( removeString ( " call " , OriginalSymbol ( st - > symbol ( ) ) - > identifier ( ) ) ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
for ( auto & elem : pureNameOfCallFunc )
correctNameIfContains ( st , NULL , elem , containsFunctions , prefix ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
if ( hasRecCall ( procInfo , pureNameOfCallFunc ) )
continue ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
procInfo - > callsFrom . insert ( pureNameOfCallFunc . begin ( ) , pureNameOfCallFunc . end ( ) ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
FuncInfoCallFrom newCall ;
newCall . detailCallsFrom = make_pair ( pureNameOfCallFunc [ 1 ] , st - > lineNumber ( ) ) ; // original name of call
newCall . pointerDetailCallsFrom = make_pair ( st , PROC_STAT ) ;
newCall . parentForPointer = st ;
newCall . actualParams = FuncParam ( ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
processActualParams ( st - > expr ( 0 ) , commonBlocks , newCall . actualParams , procInfo - > externalCalls ) ;
procInfo - > callsFromDetailed . push_back ( newCall ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
// Add func call which we've just found
NestedFuncCall funcCall ( pureNameOfCallFunc [ 1 ] ) ;
procInfo - > funcsCalledFromThis . push_back ( funcCall ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
// search for using pars of cur func in pars of called
throughParams ( st - > expr ( 0 ) , * procInfo , containsFunctions , prefix ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
//find external calls
for ( SgExpression * par = st - > expr ( 0 ) ; par ! = NULL ; par = par - > rhs ( ) )
{
SgExpression * curr = par - > lhs ( ) ;
if ( curr )
{
if ( curr - > variant ( ) = = VAR_REF )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
auto s = curr - > symbol ( ) ;
if ( procInfo - > externalCalls . find ( s - > identifier ( ) ) ! = procInfo - > externalCalls . end ( ) | |
( s - > attributes ( ) & EXTERNAL_BIT ) )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
vector < string > nameOfCallFunc ;
nameOfCallFunc . push_back ( s - > identifier ( ) ) ;
nameOfCallFunc . push_back ( OriginalSymbol ( s ) - > identifier ( ) ) ;
for ( auto & elem : nameOfCallFunc )
correctNameIfContains ( NULL , curr , elem , containsFunctions , prefix ) ;
procInfo - > callsFrom . insert ( nameOfCallFunc . begin ( ) , nameOfCallFunc . end ( ) ) ;
FuncInfoCallFrom newCall ;
newCall . detailCallsFrom = make_pair ( nameOfCallFunc [ 1 ] , st - > lineNumber ( ) ) ; // original name of call
newCall . pointerDetailCallsFrom = make_pair ( curr , VAR_REF ) ;
newCall . parentForPointer = st ;
newCall . actualParams = FuncParam ( ) ;
procInfo - > callsFromDetailed . push_back ( newCall ) ;
2023-09-14 19:43:13 +03:00
}
}
}
}
2024-05-11 15:38:41 +03:00
}
else
{
2023-09-14 19:43:13 +03:00
for ( int i = 0 ; i < 3 ; + + i )
if ( st - > expr ( i ) )
2024-05-11 15:38:41 +03:00
findParamUsedInFuncCalls ( st - > expr ( i ) , * procInfo , containsFunctions , prefix ) ;
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
for ( int i = 0 ; i < 3 ; + + i )
if ( st - > expr ( i ) )
findFuncCalls ( st , st - > expr ( i ) , procInfo , st - > lineNumber ( ) , commonBlocks , macroNames , containsFunctions , prefix ) ;
if ( isSgExecutableStatement ( st ) )
{
if ( procInfo - > isParamUsedAsIndex . size ( ) )
for ( int i = 0 ; i < 3 ; i + + )
findArrayRef ( st - > expr ( i ) , * procInfo , st - > variant ( ) = = ASSIGN_STAT & & i = = 0 ) ;
if ( st - > variant ( ) = = FOR_NODE )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
auto itL = mapLoopGraph . find ( st - > lineNumber ( ) ) ;
if ( itL ! = mapLoopGraph . end ( ) )
procInfo - > loopsInFunc . push_back ( itL - > second ) ;
}
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
st = st - > lexNext ( ) ;
}
2024-05-12 13:37:42 +03:00
return procInfo ;
2024-05-11 15:38:41 +03:00
}
2023-09-14 19:43:13 +03:00
2024-05-25 17:41:28 +03:00
static set < SgStatement * > fillActiveOperators ( SgStatement * func , const vector < SAPFOR : : BasicBlock * > & blocks )
2024-05-11 15:38:41 +03:00
{
if ( blocks . size ( ) = = 0 )
return set < SgStatement * > ( ) ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
set < SgStatement * > active ;
set < SAPFOR : : BasicBlock * > activeBlocks ;
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
activeBlocks . insert ( blocks [ 0 ] ) ;
bool added = true ;
while ( added )
{
added = false ;
for ( auto & block : activeBlocks )
{
for ( auto & next : block - > getNext ( ) )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
if ( activeBlocks . find ( next ) = = activeBlocks . end ( ) )
2023-09-14 19:43:13 +03:00
{
2024-05-11 15:38:41 +03:00
activeBlocks . insert ( next ) ;
added = true ;
2023-09-14 19:43:13 +03:00
}
}
2024-05-11 15:38:41 +03:00
}
}
2023-09-14 19:43:13 +03:00
2024-05-11 15:38:41 +03:00
for ( auto & block : activeBlocks )
{
for ( auto & instr : block - > getInstructions ( ) )
{
auto op = instr - > getInstruction ( ) - > getOperator ( ) ;
if ( op )
active . insert ( op ) ;
}
}
2024-05-25 17:41:28 +03:00
//complete blocked statements
for ( auto st = func - > lexNext ( ) ; st ! = func - > lastNodeOfStmt ( ) ; st = st - > lexNext ( ) )
{
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
if ( st - > variant ( ) = = SWITCH_NODE )
{
auto select = isSgSwitchStmt ( st ) ;
int numOfCases = select - > numberOfCaseOptions ( ) ;
for ( int z = 0 ; z < numOfCases ; + + z )
{
auto caseOp = isSgCaseOptionStmt ( select - > caseOption ( z ) ) ;
if ( active . count ( caseOp ) )
{
active . insert ( st ) ;
break ;
}
}
}
}
2024-05-11 15:38:41 +03:00
return active ;
}
//if fullIR not empty -> call this function from CALL_GRAPH2
void functionAnalyzer ( SgFile * file , map < string , vector < FuncInfo * > > & allFuncInfo , const vector < LoopGraph * > & loops , vector < Messages > & messagesForFile ,
map < FuncInfo * , vector < SAPFOR : : BasicBlock * > > & fullIR )
{
map < int , LoopGraph * > mapLoopGraph ;
createMapLoopGraph ( loops , mapLoopGraph ) ;
map < SgStatement * , FuncInfo * > tmpInfoInIR ;
for ( auto & elem : fullIR )
{
SgStatement * func = elem . first - > funcPointer - > GetOriginal ( ) ;
if ( tmpInfoInIR . count ( func ) ! = 0 )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
tmpInfoInIR [ func ] = elem . first ;
}
int funcNum = file - > numberOfFunctions ( ) ;
__spf_print ( DEBUG , " functions num in file = %d \n " , funcNum ) ;
vector < SgStatement * > containsFunctions ;
vector < SgStatement * > functions ;
for ( int i = 0 ; i < funcNum ; + + i )
{
auto func = file - > functions ( i ) ;
functions . push_back ( func ) ;
//find entry points
for ( auto st = func - > lexNext ( ) ; st ! = func - > lastNodeOfStmt ( ) ; st = st - > lexNext ( ) )
{
if ( st - > variant ( ) = = ENTRY_STAT )
functions . push_back ( st ) ;
}
}
2024-05-12 13:37:42 +03:00
FuncInfo * lastNonEntry = NULL ;
2024-05-11 15:38:41 +03:00
for ( auto & function : functions )
{
bool isEntry = ( function - > variant ( ) = = ENTRY_STAT ) ;
const int line = function - > lineNumber ( ) ;
const char * file = function - > fileName ( ) ;
string containsPrefix = " " ;
SgStatement * st_cp = isEntry ? function - > controlParent ( ) - > controlParent ( ) : function - > controlParent ( ) ;
if ( st_cp - > variant ( ) = = PROC_HEDR | | st_cp - > variant ( ) = = PROG_HEDR | | st_cp - > variant ( ) = = FUNC_HEDR )
containsPrefix = st_cp - > symbol ( ) - > identifier ( ) + string ( " . " ) ;
else if ( st_cp - > variant ( ) = = INTERFACE_STMT )
continue ;
string funcName = " " ;
if ( function - > variant ( ) = = PROG_HEDR )
{
SgProgHedrStmt * progH = ( SgProgHedrStmt * ) function ;
funcName = progH - > nameWithContains ( ) ;
__spf_print ( DEBUG , " *** Program <%s> started at line %d / %s \n " , progH - > symbol ( ) - > identifier ( ) , line , file ) ;
}
else if ( function - > variant ( ) = = PROC_HEDR )
{
SgProcHedrStmt * procH = ( SgProcHedrStmt * ) function ;
funcName = procH - > nameWithContains ( ) ;
__spf_print ( DEBUG , " *** Function <%s> started at line %d / %s \n " , procH - > symbol ( ) - > identifier ( ) , line , file ) ;
}
else if ( function - > variant ( ) = = FUNC_HEDR )
{
SgFuncHedrStmt * funcH = ( SgFuncHedrStmt * ) function ;
funcName = funcH - > nameWithContains ( ) ;
__spf_print ( DEBUG , " *** Function <%s> started at line %d / %s \n " , funcH - > symbol ( ) - > identifier ( ) , line , file ) ;
}
else if ( function - > variant ( ) = = ENTRY_STAT )
{
funcName = function - > symbol ( ) - > identifier ( ) ;
__spf_print ( DEBUG , " *** Entry function <%s> started at line %d / %s \n " , funcName . c_str ( ) , line , file ) ;
2023-09-14 19:43:13 +03:00
}
2024-05-11 15:38:41 +03:00
else
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
set < SgStatement * > activeOps ;
if ( fullIR . size ( ) )
{
if ( tmpInfoInIR . count ( function ) = = 0 )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
2024-05-25 17:41:28 +03:00
activeOps = fillActiveOperators ( ( isEntry ? function - > controlParent ( ) : function ) , fullIR [ tmpInfoInIR [ function ] ] ) ;
2024-05-11 15:38:41 +03:00
activeOps . insert ( function ) ;
if ( isEntry )
activeOps . insert ( function - > controlParent ( ) ) ;
}
2024-05-12 13:37:42 +03:00
auto procInfo = analyzeFunction ( funcName , containsPrefix , isEntry ? function - > controlParent ( ) : function , function , allFuncInfo , mapLoopGraph , messagesForFile , containsFunctions , activeOps ) ;
if ( isEntry )
{
if ( ! lastNonEntry )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
lastNonEntry - > entry . push_back ( procInfo ) ;
}
else
lastNonEntry = procInfo ;
2023-09-14 19:43:13 +03:00
}
//fill INTERFACE block from modules
vector < SgStatement * > modules ;
findModulesInFile ( file , modules ) ;
for ( auto & mod : modules )
{
if ( mod - > fileName ( ) ! = string ( file - > filename ( ) ) )
continue ;
const string moduleName = mod - > symbol ( ) - > identifier ( ) ;
for ( auto st = mod - > lexNext ( ) ; st ! = mod - > lastNodeOfStmt ( ) ; st = st - > lexNext ( ) )
{
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
if ( isSgExecutableStatement ( st ) )
break ;
if ( st - > variant ( ) = = INTERFACE_STMT )
{
if ( needToReplaceInterfaceName ( st ) )
{
const string fileName = st - > fileName ( ) ;
auto it = allFuncInfo . find ( fileName ) ;
if ( it = = allFuncInfo . end ( ) )
it = allFuncInfo . insert ( it , make_pair ( fileName , vector < FuncInfo * > ( ) ) ) ;
string currF = st - > symbol ( ) - > identifier ( ) ;
if ( currF . find ( " :: " ) = = string : : npos )
currF = moduleName + " :: " + currF ;
FuncInfo * funcInterface = new FuncInfo ( currF , make_pair ( st - > lineNumber ( ) , st - > lastNodeOfStmt ( ) - > lineNumber ( ) ) , new Statement ( st ) ) ;
funcInterface - > isInterface = true ;
for ( auto st_l = st - > lexNext ( ) ; st_l ! = st - > lastNodeOfStmt ( ) ; st_l = st_l - > lexNext ( ) )
if ( st_l - > variant ( ) = = MODULE_PROC_STMT )
{
auto list = st_l - > expr ( 0 ) ;
for ( auto ex = list ; ex ; ex = ex - > rhs ( ) )
funcInterface - > interfaceSynonims [ moduleName + " :: " + ex - > lhs ( ) - > symbol ( ) - > identifier ( ) ] = NULL ;
}
st = st - > lastNodeOfStmt ( ) ;
it - > second . push_back ( funcInterface ) ;
}
}
}
}
2024-05-11 15:38:41 +03:00
auto it = allFuncInfo . find ( file - > filename ( ) ) ;
if ( it = = allFuncInfo . end ( ) )
return ;
if ( fullIR . size ( ) = = 0 )
return ;
vector < FuncInfo * > toRemove ;
for ( auto & func : it - > second )
{
SgStatement * pointer = func - > funcPointer - > GetOriginal ( ) ;
if ( tmpInfoInIR . find ( pointer ) ! = tmpInfoInIR . end ( ) )
{
auto key = tmpInfoInIR [ pointer ] ;
toRemove . push_back ( key ) ;
fullIR [ func ] = fullIR [ key ] ;
fullIR . erase ( key ) ;
}
}
for ( auto & func : toRemove )
delete func ;
2023-09-14 19:43:13 +03:00
}
static bool findLoopVarInParameter ( SgExpression * ex , const string & loopSymb )
{
bool retVal = false ;
if ( ex )
{
if ( ex - > variant ( ) = = VAR_REF )
{
const string ident ( ex - > symbol ( ) - > identifier ( ) ) ;
if ( ident = = loopSymb )
retVal = true ;
}
}
return retVal ;
}
static int countList ( SgExpression * list )
{
int num = 0 ;
while ( list )
{
num + + ;
list = list - > rhs ( ) ;
}
return num ;
}
static bool matchCallAndDefinition ( const FuncParam & funcParDef , const FuncParam & funcParCall , const string & funcName ,
const string & file , const int line , map < string , vector < Messages > > & messages )
{
bool result = true ;
auto typesDef = funcParDef . parametersT ;
auto typesCall = funcParCall . parametersT ;
if ( typesDef . size ( ) ! = typesCall . size ( ) )
{
wstring bufR , bufE ;
__spf_printToLongBuf ( bufE , L " Function '%s': count of call parameters are not enouth " , to_wstring ( funcName ) . c_str ( ) ) ;
__spf_printToLongBuf ( bufR , R38 , to_wstring ( funcName ) . c_str ( ) ) ;
//if (needToAddErrors)
{
messages [ file ] . push_back ( Messages ( ERROR , line , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Function '%s': count of call parameters are not enouth \n " , funcName . c_str ( ) ) ;
}
result = false ;
}
else
{
for ( int i = 0 ; i < typesDef . size ( ) ; + + i )
{
if ( typesCall [ i ] ! = ARRAY_T )
{
if ( typesCall [ i ] ! = typesDef [ i ] )
{
wstring bufR , bufE ;
__spf_printToLongBuf ( bufE , L " Different type of call (%s : %s) and def (%s : %s) parameter %d for function '%s' " ,
to_wstring ( funcParCall . identificators [ i ] ) . c_str ( ) , to_wstring ( paramNames [ typesCall [ i ] ] ) . c_str ( ) ,
to_wstring ( funcParDef . identificators [ i ] ) . c_str ( ) , to_wstring ( paramNames [ typesDef [ i ] ] ) . c_str ( ) , i + 1 , to_wstring ( funcName ) . c_str ( ) ) ;
__spf_printToLongBuf ( bufR , R39 ,
to_wstring ( funcParCall . identificators [ i ] ) . c_str ( ) , to_wstring ( paramNames [ typesCall [ i ] ] ) . c_str ( ) ,
to_wstring ( funcParDef . identificators [ i ] ) . c_str ( ) , to_wstring ( paramNames [ typesDef [ i ] ] ) . c_str ( ) ,
i + 1 , to_wstring ( funcName ) . c_str ( ) ) ;
//if (needToAddErrors)
{
messages [ file ] . push_back ( Messages ( NOTE , line , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Function '%s': different type of call and def parameter %d \n " , funcName . c_str ( ) , i + 1 ) ;
}
2023-11-05 18:20:31 +03:00
//result = false;
2023-09-14 19:43:13 +03:00
}
}
else //TODO
{
/*if (callArrayRef->numberOfSubscripts() > 0)
{
wstring bufR , bufE ;
__spf_printToLongBuf ( bufE , L " Function '%s' needs to be inlined, only full array passing was supported " , to_wstring ( def - > funcName ) . c_str ( ) ) ;
__spf_printToLongBuf ( bufR , R40 , to_wstring ( def - > funcName ) . c_str ( ) ) ;
//if (needToAddErrors)
{
messages [ file ] . push_back ( Messages ( ERROR , line , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Function '%s' needs to be inlined, only full array passing was supported \n " , def - > funcName . c_str ( ) ) ;
}
result = false ;
} */
}
}
}
return result ;
}
static bool matchCallAndDefinition ( SgProject * proj , const map < string , int > & files ,
map < string , vector < Messages > > & messages , bool needToAddErrors , const map < string , FuncInfo * > & funcByName )
{
int count = 0 ;
for ( auto & func : funcByName )
{
FuncInfo * currF = func . second ;
for ( auto & callsTo : currF - > callsTo )
{
2023-11-05 13:08:57 +03:00
for ( int cf = 0 ; cf < callsTo - > callsFromDetailed . size ( ) ; + + cf )
2023-09-14 19:43:13 +03:00
{
2023-11-05 13:08:57 +03:00
if ( callsTo - > callsFromDetailed [ cf ] . detailCallsFrom . first = = currF - > funcName )
2023-09-14 19:43:13 +03:00
{
2023-11-05 13:08:57 +03:00
auto callInfo = callsTo - > callsFromDetailed [ cf ] . pointerDetailCallsFrom ;
2023-09-14 19:43:13 +03:00
if ( callInfo . second = = VAR_REF ) // external call through proc parameter
continue ;
auto itF = files . find ( callsTo - > fileName ) ;
if ( itF = = files . end ( ) )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
2023-11-05 13:08:57 +03:00
bool localR = matchCallAndDefinition ( currF - > funcParams , callsTo - > callsFromDetailed [ cf ] . actualParams , currF - > funcName ,
callsTo - > fileName , callsTo - > callsFromDetailed [ cf ] . detailCallsFrom . second , messages ) ;
2023-09-14 19:43:13 +03:00
if ( ! localR )
count + + ;
}
}
}
}
return count > 0 ;
}
bool isPassFullArray ( SgExpression * ex )
{
if ( ex - > lhs ( ) = = NULL & & ex - > rhs ( ) = = NULL )
return true ;
else
return false ;
}
static bool hasCuttingDims ( SgExpression * ex )
{
if ( ex - > lhs ( ) )
{
if ( ex - > lhs ( ) - > variant ( ) = = EXPR_LIST )
{
SgExpression * list = ex - > lhs ( ) ;
for ( auto list = ex - > lhs ( ) ; list ; list = list - > rhs ( ) )
{
if ( list - > lhs ( ) & & list - > lhs ( ) - > variant ( ) = = DDOT )
return true ;
}
}
}
return false ;
}
static bool checkDimSizesBetweenParams ( bool type2 , const FuncInfo * func , int parNum , SgStatement * decl , SgSymbol * symb , vector < Messages > & messages , const int & statLine )
{
bool ret = false ;
if ( type2 )
{
DIST : : Array * inFunction = ( DIST : : Array * ) func - > funcParams . parameters [ parNum ] ;
DIST : : Array * mainArray = getArrayFromDeclarated ( decl , symb - > identifier ( ) ) ;
if ( mainArray = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( mainArray - > GetDimSize ( ) ! = inFunction - > GetDimSize ( ) & &
! ( inFunction - > IsNotDistribute ( ) & & ! mainArray - > IsNotDistribute ( ) ) )
{
wstring bufE , bufR ;
__spf_printToLongBuf ( bufE , L " Function '%s' needs to be inlined due to different dimension sizes in formal (size = %d) and actual(size = %d) parameters for array reference '%s' " ,
to_wstring ( func - > funcName ) . c_str ( ) , inFunction - > GetDimSize ( ) , mainArray - > GetDimSize ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) ) ;
__spf_printToLongBuf ( bufR , R43 ,
to_wstring ( func - > funcName ) . c_str ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) , inFunction - > GetDimSize ( ) , mainArray - > GetDimSize ( ) ) ;
messages . push_back ( Messages ( ERROR , statLine , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Function '%s' needs to be inlined due to different dimension sizes in formal (size = %d) and actual(size = %d) parameters for array reference '%s' \n " ,
func - > funcName . c_str ( ) , inFunction - > GetDimSize ( ) , mainArray - > GetDimSize ( ) , symb - > identifier ( ) ) ;
ret = true ;
}
}
else
{
wstring bufE , bufR ;
__spf_printToLongBuf ( bufE , L " Type mismatch in function '%s' in formal and actual parameters for array reference '%s' \n " ,
to_wstring ( func - > funcName ) . c_str ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) ) ;
__spf_printToLongBuf ( bufR , R44 ,
to_wstring ( func - > funcName ) . c_str ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) ) ;
messages . push_back ( Messages ( ERROR , statLine , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Type mismatch in function '%s' in formal and actual parameters for array reference '%s' \n " , func - > funcName . c_str ( ) , symb - > identifier ( ) ) ;
ret = true ;
}
return ret ;
}
static bool checkParameter ( SgExpression * ex , vector < Messages > & messages , const int statLine ,
SgForStmt * loop , bool needToAddErrors , const FuncInfo * func , int parNum ,
const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls )
{
bool ret = false ;
if ( ex )
{
if ( isArrayRef ( ex ) )
{
SgArrayRefExp * arrayRef = isSgArrayRefExp ( ex ) ;
SgType * type = ex - > symbol ( ) - > type ( ) ;
if ( arrayRef & & type & & type - > variant ( ) ! = T_STRING )
{
SgSymbol * symb = OriginalSymbol ( arrayRef - > symbol ( ) ) ;
if ( symb )
{
SgStatement * decl = declaratedInStmt ( symb ) ;
set < string > privatesVars ;
tryToFindPrivateInAttributes ( decl , privatesVars ) ;
fillNonDistrArraysAsPrivate ( decl , declaredArrays , declaratedArraysSt , privatesVars ) ;
if ( privatesVars . find ( symb - > identifier ( ) ) = = privatesVars . end ( ) )
{
bool type1 = ( func - > funcParams . inout_types [ parNum ] & OUT_BIT ) ! = 0 ;
bool type2 = func - > funcParams . parametersT [ parNum ] = = ARRAY_T ;
string add = " " ;
wstring addW = L " " ;
if ( type1 )
{
add + = " (as out argument " ;
addW + = wstring ( L " ( " ) + RR42_1 ;
}
if ( type2 )
{
if ( type1 )
{
add + = " , as array in function) " ;
addW + = L " , " + wstring ( RR42_2 ) + L " ) " ;
}
else
{
add + = " (as array in function) " ;
addW + = L " ( " + wstring ( RR42_2 ) + L " ) " ;
}
}
else
add + = " ) " ;
if ( ! isPassFullArray ( ex ) )
{
bool _hasCuttingDims = hasCuttingDims ( ex ) ;
if ( _hasCuttingDims )
{
if ( needToAddErrors )
{
if ( loop )
{
wstring bufE , bufR ;
__spf_printToLongBuf ( bufE , L " Function '%s' needs to be inlined due to non private array reference '%s' under loop on line %d %s " ,
to_wstring ( func - > funcName ) . c_str ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) , loop - > lineNumber ( ) , to_wstring ( add ) . c_str ( ) ) ;
__spf_printToLongBuf ( bufR , R41 ,
to_wstring ( func - > funcName ) . c_str ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) , loop - > lineNumber ( ) , addW . c_str ( ) ) ;
messages . push_back ( Messages ( ERROR , statLine , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Function '%s' needs to be inlined due to non private array reference '%s' under loop on line %d %s \n " , func - > funcName . c_str ( ) , symb - > identifier ( ) , loop - > lineNumber ( ) , add . c_str ( ) ) ;
}
else
{
wstring bufE , bufR ;
__spf_printToLongBuf ( bufE , L " Function '%s' needs to be inlined due to non private array reference '%s' %s " ,
to_wstring ( func - > funcName ) . c_str ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) , to_wstring ( add ) . c_str ( ) ) ;
__spf_printToLongBuf ( bufR , R42 ,
to_wstring ( func - > funcName ) . c_str ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) , addW . c_str ( ) ) ;
messages . push_back ( Messages ( ERROR , statLine , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Function '%s' needs to be inlined due to non private array reference '%s' %s \n " , func - > funcName . c_str ( ) , symb - > identifier ( ) , add . c_str ( ) ) ;
}
}
ret = true ;
}
else
{
//deprecate N first dims to distribute
if ( type2 )
{
ret = checkDimSizesBetweenParams ( type2 , func , parNum , decl , symb , messages , statLine ) ;
if ( ! ret )
{
DIST : : Array * inFunction = ( DIST : : Array * ) func - > funcParams . parameters [ parNum ] ;
DIST : : Array * mainArray = getArrayFromDeclarated ( decl , symb - > identifier ( ) ) ;
if ( mainArray = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
set < DIST : : Array * > realArrayRefs ;
getRealArrayRefs ( mainArray , mainArray , realArrayRefs , arrayLinksByFuncCalls ) ;
const int toDepDims = inFunction - > GetDimSize ( ) ;
for ( auto & array : realArrayRefs )
for ( int z = 0 ; z < toDepDims ; + + z )
array - > DeprecateDimension ( z ) ;
for ( int z = 0 ; z < toDepDims ; + + z )
mainArray - > DeprecateDimension ( z ) ;
inFunction - > DeprecateAllDims ( ) ;
inFunction - > SetDistributeFlag ( DIST : : NO_DISTR ) ;
wstring bufE , bufR ;
if ( inFunction - > GetDimSize ( ) = = 1 )
__spf_printToLongBuf ( bufE , L " First dimension of array '%s' were deprecated to distributon due to function call '%s' " ,
to_wstring ( symb - > identifier ( ) ) . c_str ( ) , to_wstring ( func - > funcName ) . c_str ( ) ) ;
else
__spf_printToLongBuf ( bufE , L " First %d dimensions of array '%s' were deprecated to distributon due to function call '%s' " ,
inFunction - > GetDimSize ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) , to_wstring ( func - > funcName ) . c_str ( ) ) ;
if ( inFunction - > GetDimSize ( ) = = 1 )
__spf_printToLongBuf ( bufR , R73 ,
to_wstring ( symb - > identifier ( ) ) . c_str ( ) , to_wstring ( func - > funcName ) . c_str ( ) ) ;
else
__spf_printToLongBuf ( bufR , R72 ,
inFunction - > GetDimSize ( ) , to_wstring ( symb - > identifier ( ) ) . c_str ( ) , to_wstring ( func - > funcName ) . c_str ( ) ) ;
messages . push_back ( Messages ( NOTE , statLine , bufR , bufE , 1040 ) ) ;
}
}
}
}
else // check dim sizes between formal and actual parameters
ret = checkDimSizesBetweenParams ( type2 , func , parNum , decl , symb , messages , statLine ) ;
}
}
}
}
if ( ex - > lhs ( ) )
{
bool res = checkParameter ( ex - > lhs ( ) , messages , statLine , loop , needToAddErrors , func , parNum , arrayLinksByFuncCalls ) ;
ret | = res ;
}
if ( ex - > rhs ( ) )
{
bool res = checkParameter ( ex - > rhs ( ) , messages , statLine , loop , needToAddErrors , func , parNum , arrayLinksByFuncCalls ) ;
ret | = res ;
}
}
return ret ;
}
static bool checkParameter ( SgExpression * parList , vector < Messages > & messages , bool needToAddErrors ,
const FuncInfo * func , const int funcOnLine , SgForStmt * loop ,
const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls )
{
int parNum = 0 ;
bool needInsert = false ;
while ( parList )
{
bool res = checkParameter ( parList - > lhs ( ) , messages , funcOnLine , loop , needToAddErrors , func , parNum , arrayLinksByFuncCalls ) ;
needInsert | = res ;
+ + parNum ;
parList = parList - > rhs ( ) ;
}
return needInsert ;
}
static vector < int > findNoOfParWithLoopVar ( SgExpression * pars , const string & loopSymb )
{
vector < int > parsWithLoopSymb ;
int parNo = 0 ;
for ( SgExpression * par = pars ; par ! = NULL ; par = par - > rhs ( ) , parNo + + )
{
if ( findLoopVarInParameter ( par - > lhs ( ) , loopSymb ) )
parsWithLoopSymb . push_back ( parNo ) ;
}
return parsWithLoopSymb ;
}
static bool processParameterList ( SgExpression * parList , SgForStmt * loop , const FuncInfo * func , const int funcOnLine , bool needToAddErrors ,
vector < Messages > & messages , const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls )
{
bool needInsert = false ;
bool hasLoopVar = false ;
if ( loop )
hasLoopVar = findLoopVarInParameter ( parList , loop - > symbol ( ) - > identifier ( ) ) ;
if ( hasLoopVar )
{
const vector < int > parsWithLoopSymb = findNoOfParWithLoopVar ( parList , loop - > symbol ( ) - > identifier ( ) ) ;
int idx = - 1 ;
for ( auto & par : parsWithLoopSymb )
{
if ( func - > isParamUsedAsIndex [ par ] )
{
idx = par + 1 ;
break ;
}
}
if ( idx ! = - 1 )
{
wstring bufE , bufR ;
__spf_printToLongBuf ( bufE , L " Function '%s' needs to be inlined due to use of loop's symbol on line %d as index of an array inside this call, in parameter num %d " ,
to_wstring ( func - > funcName ) . c_str ( ) , loop - > lineNumber ( ) , idx ) ;
__spf_printToLongBuf ( bufR , R45 ,
to_wstring ( func - > funcName ) . c_str ( ) , idx , loop - > lineNumber ( ) ) ;
if ( needToAddErrors )
{
messages . push_back ( Messages ( ERROR , funcOnLine , bufR , bufE , 1013 ) ) ;
__spf_print ( 1 , " Function '%s' needs to be inlined due to use of loop's symbol on line %d as index of an array inside this call, in parameter num %d \n " ,
func - > funcName . c_str ( ) , loop - > lineNumber ( ) , idx ) ;
}
needInsert = true ;
}
else
needInsert = checkParameter ( parList , messages , needToAddErrors , func , funcOnLine , loop , arrayLinksByFuncCalls ) ;
}
else
needInsert = checkParameter ( parList , messages , needToAddErrors , func , funcOnLine , loop , arrayLinksByFuncCalls ) ;
return needInsert ;
}
static bool findFuncCall ( SgExpression * ex , const FuncInfo * func , vector < Messages > & messages , const int statLine , SgForStmt * loop , bool needToAddErrors ,
const map < string , FuncInfo * > & funcByName ,
const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls ,
bool processAll = false , set < string > * funcChecked = NULL , set < string > * needToInsert = NULL )
{
bool ret = false ;
if ( ex )
{
if ( ex - > variant ( ) = = FUNC_CALL )
{
if ( processAll )
{
if ( funcChecked & & needToInsert )
{
const string fName = ex - > symbol ( ) - > identifier ( ) ;
if ( funcChecked - > find ( fName ) = = funcChecked - > end ( ) )
{
funcChecked - > insert ( fName ) ;
auto itF = funcByName . find ( fName ) ;
if ( itF ! = funcByName . end ( ) )
{
ret = processParameterList ( ex - > lhs ( ) , loop , itF - > second , statLine , needToAddErrors , messages , arrayLinksByFuncCalls ) ;
if ( ret )
needToInsert - > insert ( fName ) ;
}
}
}
else
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
}
else
{
if ( ex - > symbol ( ) - > identifier ( ) = = func - > funcName )
{
bool res = processParameterList ( ex - > lhs ( ) , loop , func , statLine , needToAddErrors , messages , arrayLinksByFuncCalls ) ;
ret | = res ;
}
}
}
bool resL = findFuncCall ( ex - > lhs ( ) , func , messages , statLine , loop , needToAddErrors , funcByName , arrayLinksByFuncCalls , processAll , funcChecked , needToInsert ) ;
bool resR = findFuncCall ( ex - > rhs ( ) , func , messages , statLine , loop , needToAddErrors , funcByName , arrayLinksByFuncCalls , processAll , funcChecked , needToInsert ) ;
ret | = resL | | resR ;
}
return ret ;
}
static SgStatement * getStatByLine ( string file , const int line , const map < string , map < int , SgStatement * > > & statByLine )
{
auto itF = statByLine . find ( file ) ;
if ( itF = = statByLine . end ( ) )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
auto itS = itF - > second . find ( line ) ;
if ( itS = = itF - > second . end ( ) )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
SwitchFile ( itS - > second - > getFileId ( ) ) ;
return itS - > second ;
}
static void findInsertedFuncLoopGraph ( const vector < LoopGraph * > & childs , set < string > & needToInsert , SgFile * currF ,
vector < Messages > & messages , bool needToAddErrors , const map < string , FuncInfo * > & funcByName ,
const map < string , map < int , SgStatement * > > & statByLine ,
const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls , set < string > & funcChecked )
{
for ( int k = 0 ; k < ( int ) childs . size ( ) ; + + k )
{
auto stat = getStatByLine ( currF - > filename ( ) , childs [ k ] - > lineNum , statByLine ) ;
if ( stat = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
SgForStmt * loop = isSgForStmt ( stat ) ;
if ( loop = = NULL & & stat - > variant ( ) ! = WHILE_NODE )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( loop & & loop - > lineNumber ( ) ! = childs [ k ] - > lineNum )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
// TODO: find loop variable in common block or module
//dont check loop outside of parallel region and DO_WHILE
if ( childs [ k ] - > region & & loop )
{
for ( int i = 0 ; i < ( int ) childs [ k ] - > calls . size ( ) ; + + i )
{
//dont check call with !$SPF NOINLINE
bool needToCheck = true ;
const string & funcName = childs [ k ] - > calls [ i ] . first ;
funcChecked . insert ( funcName ) ;
auto it = funcByName . find ( funcName ) ;
if ( it ! = funcByName . end ( ) )
needToCheck = ! ( it - > second - > doNotInline = = true ) ;
else // function not found
needToCheck = false ;
if ( ! needToCheck )
continue ;
int funcOnLine = childs [ k ] - > calls [ i ] . second ;
SgStatement * func = getStatByLine ( currF - > filename ( ) , funcOnLine , statByLine ) ;
bool needInsert = false ;
const int var = func - > variant ( ) ;
if ( var = = PROC_STAT )
{
bool res = processParameterList ( func - > expr ( 0 ) , loop , it - > second , funcOnLine , needToAddErrors , messages , arrayLinksByFuncCalls ) ;
needInsert | = res ;
}
else
for ( int z = 0 ; z < 3 ; + + z )
{
bool res = findFuncCall ( func - > expr ( z ) , it - > second , messages , funcOnLine , loop , needToAddErrors , funcByName , arrayLinksByFuncCalls ) ;
needInsert | = res ;
}
if ( needInsert )
needToInsert . insert ( childs [ k ] - > calls [ i ] . first ) ;
}
}
findInsertedFuncLoopGraph ( childs [ k ] - > children , needToInsert , currF , messages , needToAddErrors , funcByName , statByLine , arrayLinksByFuncCalls , funcChecked ) ;
}
}
static bool runCheckOutOfLoop ( SgExpression * parList , const FuncInfo * func , const int lineFromCall , bool needToAddErrors ,
vector < Messages > & messages , const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls )
{
bool needInsert = processParameterList ( parList , NULL , func , lineFromCall , needToAddErrors , messages , arrayLinksByFuncCalls ) ;
return needInsert ;
}
static void findInsertedFuncLoopGraph ( const map < string , vector < LoopGraph * > > & loopGraph , set < string > & needToInsert ,
SgProject * proj , const map < string , int > & files , map < string , vector < Messages > > & allMessages ,
bool needToAddErrors , const map < string , FuncInfo * > & funcByName ,
const map < string , map < int , SgStatement * > > & statByLine ,
const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls , const vector < ParallelRegion * > & regions )
{
set < string > funcChecked ;
for ( auto & loop : loopGraph )
{
const int fileN = files . find ( loop . first ) - > second ;
SgFile * currF = & ( proj - > file ( fileN ) ) ;
SwitchFile ( fileN ) ;
auto itM = allMessages . find ( loop . first ) ;
if ( itM = = allMessages . end ( ) )
itM = allMessages . insert ( itM , make_pair ( loop . first , vector < Messages > ( ) ) ) ;
findInsertedFuncLoopGraph ( loop . second , needToInsert , currF , itM - > second , needToAddErrors , funcByName , statByLine , arrayLinksByFuncCalls , funcChecked ) ;
}
//not checked, out of loops
for ( int f = 0 ; f < proj - > numberOfFiles ( ) ; + + f )
{
SgFile * currF = & ( proj - > file ( f ) ) ;
SwitchFile ( f ) ;
auto itM = allMessages . find ( currF - > filename ( ) ) ;
if ( itM = = allMessages . end ( ) )
itM = allMessages . insert ( itM , make_pair ( currF - > filename ( ) , vector < Messages > ( ) ) ) ;
for ( int z = 0 ; z < currF - > numberOfFunctions ( ) ; + + z )
{
SgStatement * funcInFile = currF - > functions ( z ) ;
for ( SgStatement * st = funcInFile - > lexNext ( ) ; st ! = funcInFile - > lastNodeOfStmt ( ) ; st = st - > lexNext ( ) )
{
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
if ( st - > lineNumber ( ) = = - 1 )
continue ;
if ( ! __gcov_doesThisLineExecuted ( st - > fileName ( ) , st - > lineNumber ( ) ) )
continue ;
set < ParallelRegion * > allRegs = getAllRegionsByLine ( regions , st - > fileName ( ) , st - > lineNumber ( ) ) ;
if ( allRegs . size ( ) = = 0 )
continue ;
if ( isSgExecutableStatement ( st ) )
{
if ( st - > variant ( ) = = PROC_STAT )
{
const string fName = st - > symbol ( ) - > identifier ( ) ;
auto it = funcChecked . find ( fName ) ;
auto itF = funcByName . find ( fName ) ;
if ( it = = funcChecked . end ( ) & & itF ! = funcByName . end ( ) )
{
bool needInsert = runCheckOutOfLoop ( st - > expr ( 0 ) , itF - > second , st - > lineNumber ( ) , needToAddErrors , itM - > second , arrayLinksByFuncCalls ) ;
if ( needInsert )
needToInsert . insert ( fName ) ;
}
}
else
for ( int z = 0 ; z < 3 ; + + z )
findFuncCall ( st - > expr ( z ) , NULL , itM - > second , st - > lineNumber ( ) , NULL , needToAddErrors , funcByName , arrayLinksByFuncCalls , true , & funcChecked , & needToInsert ) ;
}
}
}
}
}
//TODO: 'needToAddErrors' is deprecated and always true
int CheckFunctionsToInline ( SgProject * proj , const map < string , int > & files , const char * fileName , map < string , vector < FuncInfo * > > & funcByFile ,
const map < string , vector < LoopGraph * > > & loopGraph , map < string , vector < Messages > > & allMessages , bool needToAddErrors ,
const map < DIST : : Array * , set < DIST : : Array * > > & arrayLinksByFuncCalls , const vector < ParallelRegion * > & regions )
{
map < string , map < int , SgStatement * > > statByLine ; //file -> map
//build info
for ( int i = 0 ; i < proj - > numberOfFiles ( ) ; + + i )
{
map < int , SgStatement * > toAdd ;
SgFile * file = & ( proj - > file ( i ) ) ;
SwitchFile ( i ) ;
SgStatement * st = file - > firstStatement ( ) ;
string currF = file - > filename ( ) ;
while ( st )
{
if ( st - > lineNumber ( ) ! = 0 & & st - > fileName ( ) = = currF )
toAdd [ st - > lineNumber ( ) ] = st ;
st = st - > lexNext ( ) ;
}
statByLine [ file - > filename ( ) ] = toAdd ;
}
map < string , FuncInfo * > funcByName ;
for ( auto & byFile : funcByFile )
{
for ( int k = 0 ; k < byFile . second . size ( ) ; + + k )
{
string name = byFile . second [ k ] - > funcName ;
auto itF = funcByName . find ( name ) ;
if ( itF = = funcByName . end ( ) )
funcByName . insert ( itF , make_pair ( name , byFile . second [ k ] ) ) ;
else
{
__spf_print ( 1 , " function with name '%s' was found in file '%s' on line %d, current position is file '%s' and line %d \n " ,
name . c_str ( ) , itF - > second - > fileName . c_str ( ) , itF - > second - > linesNum . first , byFile . second [ k ] - > fileName . c_str ( ) , byFile . second [ k ] - > linesNum . first ) ;
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
}
}
}
set < string > needToInsert ;
findInsertedFuncLoopGraph ( loopGraph , needToInsert , proj , files , allMessages , needToAddErrors , funcByName , statByLine , arrayLinksByFuncCalls , regions ) ;
bool err = matchCallAndDefinition ( proj , files , allMessages , needToAddErrors , funcByName ) ;
if ( err )
return - 1 ;
if ( needToInsert . size ( ) > 0 )
{
for ( auto it = needToInsert . begin ( ) ; it ! = needToInsert . end ( ) ; + + it )
{
auto itF = funcByName . find ( * it ) ;
if ( itF ! = funcByName . end ( ) )
itF - > second - > needToInline = true ;
}
}
if ( fileName )
{
FILE * out = fopen ( fileName , " w " ) ;
if ( out = = NULL )
{
__spf_print ( 1 , " can not open file %s \n " , fileName ) ;
throw - 1 ;
}
fprintf ( out , " digraph G{ \n " ) ;
auto it = funcByFile . begin ( ) ;
set < string > noInline ;
int fileNum = 0 ;
while ( it ! = funcByFile . end ( ) )
{
fprintf ( out , " subgraph cluster%d { \n " , fileNum ) ;
const int dimSize = ( int ) it - > second . size ( ) ;
set < string > uniqNames ;
for ( int k = 0 ; k < dimSize ; + + k )
{
const string currfunc = it - > second [ k ] - > funcName ;
if ( it - > second [ k ] - > doNotInline )
noInline . insert ( currfunc ) ;
set < string > : : iterator it = uniqNames . find ( currfunc ) ;
if ( it = = uniqNames . end ( ) )
{
uniqNames . insert ( it , currfunc ) ;
fprintf ( out , " \" %s \" \n " , currfunc . c_str ( ) ) ;
}
}
fprintf ( out , " label = \" file <%s> \" \n " , removeString ( " . \\ " , it - > first ) . c_str ( ) ) ;
fprintf ( out , " } \n " ) ;
fileNum + + ;
it + + ;
}
it = funcByFile . begin ( ) ;
while ( it ! = funcByFile . end ( ) )
{
const char * formatString = " \" %s \" -> \" %s \" [minlen=2.0]; \n " ;
const int dimSize = ( int ) it - > second . size ( ) ;
for ( int k = 0 ; k < dimSize ; + + k )
{
const string callFrom = it - > second [ k ] - > funcName ;
set < string > : : const_iterator i = it - > second [ k ] - > callsFrom . begin ( ) ;
for ( ; i ! = it - > second [ k ] - > callsFrom . end ( ) ; i + + )
fprintf ( out , formatString , callFrom . c_str ( ) , i - > c_str ( ) ) ;
}
it + + ;
}
auto it_set = needToInsert . begin ( ) ;
for ( ; it_set ! = needToInsert . end ( ) ; it_set + + )
{
if ( noInline . find ( * it_set ) = = noInline . end ( ) )
fprintf ( out , " \" %s \" [color=red] \n " , it_set - > c_str ( ) ) ;
}
fprintf ( out , " overlap=false \n " ) ;
fprintf ( out , " } \n " ) ;
fclose ( out ) ;
}
return needToInsert . size ( ) ;
}
static string printChainRec ( const vector < FuncInfo * > & currentChainCalls )
{
string out = " " ;
for ( int i = 0 ; i < currentChainCalls . size ( ) ; + + i )
{
out + = currentChainCalls [ i ] - > funcName ;
if ( i ! = currentChainCalls . size ( ) - 1 )
out + = " -> " ;
}
return out ;
}
static bool hasRecursionChain ( vector < FuncInfo * > currentChainCalls , const FuncInfo * current ,
const map < string , FuncInfo * > & allFuncinfo , vector < Messages > & messagesForFile )
{
bool retVal = false ;
vector < FuncInfo * > toCallNext ;
for ( auto it = current - > callsFrom . begin ( ) ; it ! = current - > callsFrom . end ( ) ; + + it )
{
auto itF = allFuncinfo . find ( * it ) ;
if ( itF = = allFuncinfo . end ( ) )
continue ;
if ( std : : find ( currentChainCalls . begin ( ) , currentChainCalls . end ( ) , itF - > second ) ! = currentChainCalls . end ( ) )
{
if ( itF - > second = = currentChainCalls [ 0 ] )
{
retVal = true ;
currentChainCalls . push_back ( itF - > second ) ;
const string & chain = printChainRec ( currentChainCalls ) ;
2025-02-09 20:48:06 +03:00
__spf_print ( 1 , " For function on line %d found recursive chain calls: %s \n " , currentChainCalls [ 0 ] - > linesNum . first , chain . c_str ( ) ) ;
2023-09-14 19:43:13 +03:00
wstring bufE , bufR ;
2025-02-09 20:48:06 +03:00
__spf_printToLongBuf ( bufE , L " Found recursive chain calls: %s, this function will be ignored " , to_wstring ( chain ) . c_str ( ) ) ;
2023-09-14 19:43:13 +03:00
__spf_printToLongBuf ( bufR , R46 , to_wstring ( chain ) . c_str ( ) ) ;
messagesForFile . push_back ( Messages ( NOTE , currentChainCalls [ 0 ] - > linesNum . first , bufR , bufE , 1014 ) ) ;
break ;
}
}
else
toCallNext . push_back ( itF - > second ) ;
}
if ( ! retVal )
{
for ( int i = 0 ; i < toCallNext . size ( ) & & ! retVal ; + + i )
{
currentChainCalls . push_back ( toCallNext [ i ] ) ;
retVal = retVal | | hasRecursionChain ( currentChainCalls , toCallNext [ i ] , allFuncinfo , messagesForFile ) ;
currentChainCalls . pop_back ( ) ;
}
}
return retVal ;
}
void checkForRecursion ( SgFile * file , map < string , vector < FuncInfo * > > & allFuncInfo , vector < Messages > & messagesForFile )
{
auto itCurrFuncs = allFuncInfo . find ( file - > filename ( ) ) ;
if ( itCurrFuncs = = allFuncInfo . end ( ) )
return ;
map < string , FuncInfo * > mapFuncInfo ;
createMapOfFunc ( allFuncInfo , mapFuncInfo ) ;
for ( int i = 0 ; i < itCurrFuncs - > second . size ( ) ; + + i )
{
2025-02-09 20:48:06 +03:00
__spf_print ( 1 , " run for func %s \n " , itCurrFuncs - > second [ i ] - > funcName . c_str ( ) ) ;
2023-09-14 19:43:13 +03:00
if ( hasRecursionChain ( { itCurrFuncs - > second [ i ] } , itCurrFuncs - > second [ i ] , mapFuncInfo , messagesForFile ) )
itCurrFuncs - > second [ i ] - > doNotAnalyze = true ;
}
}
void propagateWritesToArrays ( map < string , vector < FuncInfo * > > & allFuncInfo )
{
map < string , FuncInfo * > funcByName ;
createMapOfFunc ( allFuncInfo , funcByName ) ;
bool change = true ;
while ( change )
{
change = false ;
for ( auto & func : funcByName )
{
if ( func . second - > funcParams . countOfPars = = 0 )
continue ;
for ( int z = 0 ; z < func . second - > funcParams . countOfPars ; + + z )
{
if ( ( func . second - > funcParams . inout_types [ z ] & OUT_BIT ) = = 0 )
continue ;
for ( auto & callsTo : func . second - > callsTo )
{
map < string , int > parNames ;
for ( int p = 0 ; p < callsTo - > funcParams . countOfPars ; + + p )
parNames [ callsTo - > funcParams . identificators [ p ] ] = p ;
bool ok = callsTo - > funcPointer - > GetOriginal ( ) - > switchToFile ( ) ;
if ( ! ok )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
2023-11-05 13:08:57 +03:00
for ( auto & callFromInfo : callsTo - > callsFromDetailed )
2023-09-14 19:43:13 +03:00
{
2023-11-05 13:08:57 +03:00
auto & callFrom = callFromInfo . pointerDetailCallsFrom ;
2023-09-14 19:43:13 +03:00
if ( callFrom . second = = VAR_REF ) // pass procedure through parameter
continue ;
SgExpression * arg = NULL ;
if ( callFrom . second = = PROC_STAT )
{
SgCallStmt * call = ( SgCallStmt * ) callFrom . first ;
if ( call - > symbol ( ) - > identifier ( ) ! = func . second - > funcName )
continue ;
if ( z > = call - > numberOfArgs ( ) )
continue ;
arg = call - > arg ( z ) ;
}
else if ( callFrom . second = = FUNC_CALL )
{
SgFunctionCallExp * call = ( SgFunctionCallExp * ) callFrom . first ;
if ( call - > symbol ( ) - > identifier ( ) ! = func . second - > funcName )
continue ;
if ( z > = call - > numberOfArgs ( ) )
continue ;
arg = call - > arg ( z ) ;
}
if ( arg = = NULL )
{
if ( ( func . second - > funcParams . inout_types [ z ] & OPTIONAL_BIT ) ! = 0 )
continue ;
else
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
}
string argName = " " ;
if ( arg - > symbol ( ) )
argName = arg - > symbol ( ) - > identifier ( ) ;
auto it = parNames . find ( argName ) ;
if ( it ! = parNames . end ( ) & & ( ( callsTo - > funcParams . inout_types [ it - > second ] & OUT_BIT ) = = 0 ) )
{
change = true ;
callsTo - > funcParams . inout_types [ it - > second ] | = OUT_BIT ;
if ( ( func . second - > funcParams . inout_types [ z ] & IN_BIT ) ! = 0 )
callsTo - > funcParams . inout_types [ it - > second ] | = IN_BIT ;
}
}
}
}
}
}
}
//TODO: inmprove checker
void detectCopies ( map < string , vector < FuncInfo * > > & allFuncInfo )
{
map < string , FuncInfo * > mapOfFunc ;
createMapOfFunc ( allFuncInfo , mapOfFunc ) ;
for ( auto & byFile : allFuncInfo )
{
for ( auto & func : byFile . second )
{
string name = func - > funcName ;
auto offset = name . rfind ( " _spf_ " ) ;
if ( offset ! = string : : npos )
{
string orig = name . substr ( 0 , offset ) ;
auto it = mapOfFunc . find ( orig ) ;
if ( it ! = mapOfFunc . end ( ) )
it - > second - > fullCopiesOfThisFunction . push_back ( func ) ;
}
}
}
}
void fillInterfaceBlock ( map < string , vector < FuncInfo * > > & allFuncInfo )
{
map < string , FuncInfo * > mapOfFunc ;
createMapOfFunc ( allFuncInfo , mapOfFunc ) ;
for ( auto & byFile : allFuncInfo )
{
for ( auto & func : byFile . second )
2024-11-17 17:19:58 +03:00
{
2023-09-14 19:43:13 +03:00
for ( auto & interface : func - > interfaceBlocks )
{
auto itF = mapOfFunc . find ( interface . first ) ;
if ( itF = = mapOfFunc . end ( ) )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
set < string > namesToFind = { interface . first } ;
for ( auto & elem : itF - > second - > fullCopiesOfThisFunction )
namesToFind . insert ( elem - > funcName ) ;
for ( auto & elem : namesToFind )
{
auto isCalled = func - > callsFrom . find ( elem ) ;
if ( isCalled ! = func - > callsFrom . end ( ) )
{
interface . second = itF - > second ;
break ;
}
}
}
2024-11-17 17:19:58 +03:00
//filted interfaces
map < string , FuncInfo * > copy = func - > interfaceBlocks ;
func - > interfaceBlocks . clear ( ) ;
for ( auto & interface : func - > interfaceBlocks )
if ( interface . second )
func - > interfaceBlocks [ interface . first ] = interface . second ;
2023-09-14 19:43:13 +03:00
}
}
for ( auto & byFile : allFuncInfo )
{
for ( auto & func : byFile . second )
{
if ( ! func - > isInterface )
continue ;
if ( func - > interfaceSynonims . size ( ) = = 0 )
continue ;
for ( auto & syn : func - > interfaceSynonims )
{
auto itF = mapOfFunc . find ( syn . first ) ;
if ( itF = = mapOfFunc . end ( ) )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
syn . second = itF - > second ;
}
}
}
}
void removeDistrStateFromDeadFunctions ( const map < string , vector < FuncInfo * > > & allFuncInfo ,
const map < tuple < int , string , string > , pair < DIST : : Array * , DIST : : ArrayAccessInfo * > > & declaredArrays )
{
map < string , FuncInfo * > funcByName ;
createMapOfFunc ( allFuncInfo , funcByName ) ;
// remove distr state of arrays from dead functions
for ( auto & elem : declaredArrays )
{
DIST : : Array * array = elem . second . first ;
if ( array - > GetLocation ( ) . first = = DIST : : l_PARAMETER )
{
if ( array - > IsNotDistribute ( ) = = false )
{
auto declInfo = array - > GetDeclInfo ( ) ;
auto place = * declInfo . begin ( ) ;
if ( SgFile : : switchToFile ( place . first ) = = - 1 )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
SgStatement * st = SgStatement : : getStatementByFileAndLine ( place . first , place . second ) ;
checkNull ( st , convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
SgProgHedrStmt * hedr = isSgProgHedrStmt ( getFuncStat ( st ) ) ;
checkNull ( hedr , convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
const string funcName = hedr - > nameWithContains ( ) ;
auto it = funcByName . find ( funcName . c_str ( ) ) ;
if ( it = = funcByName . end ( ) )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( it - > second - > deadFunction )
array - > SetDistributeFlag ( DIST : : NO_DISTR ) ;
}
}
}
}
int getLvlCall ( FuncInfo * currF , int lvl , const string & func , const string & file , int line )
{
if ( currF - > funcName = = func )
return 0 ;
2023-11-05 13:08:57 +03:00
for ( auto & callsFromInfo : currF - > callsFromDetailed )
2023-09-14 19:43:13 +03:00
{
2023-11-05 13:08:57 +03:00
auto & callsFrom = callsFromInfo . detailCallsFrom ;
2023-09-14 19:43:13 +03:00
if ( callsFrom . first = = func & & callsFrom . second = = line & & currF - > fileName = = file )
return lvl ;
}
int whatLvl = - 1 ;
for ( auto & callsFrom : currF - > callsFromV )
{
int outLvl = getLvlCall ( callsFrom , lvl + 1 , func , file , line ) ;
if ( outLvl ! = - 1 )
{
whatLvl = outLvl ;
break ;
}
}
return whatLvl ;
}
void setInlineAttributeToCalls ( const map < string , FuncInfo * > & allFunctions ,
const map < string , set < pair < string , int > > > & inDataChains ,
const map < string , vector < SgStatement * > > & hiddenData )
{
set < pair < string , int > > pointsForShadowCopies ;
for ( auto & elem : allFunctions )
{
auto itNeed = inDataChains . find ( elem . first ) ;
const FuncInfo * curr = elem . second ;
set < pair < string , int > > needToInline ;
if ( itNeed ! = inDataChains . end ( ) )
needToInline = itNeed - > second ;
2023-11-05 13:08:57 +03:00
for ( int k = 0 ; k < curr - > callsFromDetailed . size ( ) ; + + k )
2023-09-14 19:43:13 +03:00
{
2023-11-05 13:08:57 +03:00
if ( needToInline . find ( curr - > callsFromDetailed [ k ] . detailCallsFrom ) = = needToInline . end ( ) & &
! isIntrinsicFunctionName ( curr - > callsFromDetailed [ k ] . detailCallsFrom . first . c_str ( ) ) )
2023-09-14 19:43:13 +03:00
{
2023-11-05 13:08:57 +03:00
pair < void * , int > detail = curr - > callsFromDetailed [ k ] . pointerDetailCallsFrom ;
2023-09-14 19:43:13 +03:00
if ( SgFile : : switchToFile ( curr - > fileName ) = = - 1 )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( detail . second = = PROC_STAT )
( ( SgStatement * ) detail . first ) - > addAttribute ( BOOL_VAL ) ;
else if ( detail . second = = FUNC_CALL )
{
//TODO: many functions in same statement
2023-11-05 13:08:57 +03:00
SgStatement * callSt = SgStatement : : getStatementByFileAndLine ( curr - > fileName , curr - > callsFromDetailed [ k ] . detailCallsFrom . second ) ;
2023-09-14 19:43:13 +03:00
if ( ! callSt )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
//((SgExpression*)detail.first)->addAttribute(BOOL_VAL);
callSt - > addAttribute ( BOOL_VAL ) ;
}
else
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
2023-11-05 13:08:57 +03:00
pointsForShadowCopies . insert ( make_pair ( curr - > fileName , curr - > callsFromDetailed [ k ] . detailCallsFrom . second ) ) ;
__spf_print ( 1 , " added attribute to '%s' <%s, %d> \n " , curr - > callsFromDetailed [ k ] . detailCallsFrom . first . c_str ( ) , curr - > fileName . c_str ( ) , curr - > callsFromDetailed [ k ] . detailCallsFrom . second ) ;
2023-09-14 19:43:13 +03:00
}
}
}
if ( pointsForShadowCopies . size ( ) )
{
for ( auto & byFile : hiddenData )
{
if ( SgFile : : switchToFile ( byFile . first ) = = - 1 )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
for ( auto & stF : byFile . second )
for ( auto st = stF ; st ! = stF - > lastNodeOfStmt ( ) ; st = st - > lexNext ( ) )
if ( pointsForShadowCopies . find ( make_pair ( st - > fileName ( ) , st - > lineNumber ( ) ) ) ! = pointsForShadowCopies . end ( ) )
{
st - > addAttribute ( BOOL_VAL ) ;
//__spf_print(1, " added attribute to shadow copy in file '%s' <%s %d>\n", byFile.first.c_str(), st->fileName(), st->lineNumber());
}
}
}
}
2025-04-13 17:24:49 +03:00
static json convertToJson ( const FuncInfo * currFunc ) {
json func ;
if ( currFunc )
{
func [ " funcName " ] = currFunc - > funcName ;
func [ " line " ] = currFunc - > linesNum . first ;
func [ " lineEnd " ] = currFunc - > linesNum . second ;
func [ " isMain " ] = ( int ) currFunc - > isMain ;
func [ " needToInline " ] = ( int ) currFunc - > needToInline ;
func [ " doNotInline " ] = ( int ) currFunc - > doNotInline ;
func [ " doNotAnalyze " ] = ( int ) currFunc - > doNotAnalyze ;
json func_pars = json : : array ( ) ;
for ( int z = 0 ; z < currFunc - > funcParams . countOfPars ; + + z )
{
json par ;
par [ " inoutType " ] = currFunc - > funcParams . inout_types [ z ] ;
par [ " identificator " ] = currFunc - > funcParams . identificators [ z ] ;
par [ " parameterT " ] = string ( paramNames [ currFunc - > funcParams . parametersT [ z ] ] ) ;
func_pars . push_back ( par ) ;
}
func [ " params " ] = func_pars ;
json calls_from = json : : array ( ) ;
for ( const auto & call_from : currFunc - > callsFromDetailed )
{
json call ;
call [ " line " ] = call_from . detailCallsFrom . second ;
call [ " funcName " ] = call_from . detailCallsFrom . first ;
calls_from . push_back ( call ) ;
}
func [ " callsFrom " ] = calls_from ;
}
return func ;
}
json convertToJson ( const map < string , vector < FuncInfo * > > & funcsByFileMap ) {
json loopsByFile = json : : array ( ) ;
for ( auto & byFile : funcsByFileMap )
{
json func ;
const string & file = byFile . first ;
json func_array = json : : array ( ) ;
for ( auto & func : byFile . second )
{
auto conv = convertToJson ( func ) ;
if ( ! conv . empty ( ) )
func_array . push_back ( conv ) ;
}
func [ " file " ] = file ;
func [ " functions " ] = func_array ;
loopsByFile . push_back ( func ) ;
}
json allFuncs ;
allFuncs [ " allFunctions " ] = loopsByFile ;
return allFuncs ;
}
2023-09-14 19:43:13 +03:00
# undef DEBUG