void PreAndPostOrderTraversal::preOrderVisit(SgNode* n) { SgFunctionDeclaration * dec = isSgFunctionDeclaration(n); if (dec != NULL) { cout << "Found function declaration " << dec->get_name().getString(); Sg_File_Info * start = dec->get_startOfConstruct(); Sg_File_Info * end = dec->get_endOfConstruct(); if(start->isCompilerGenerated()) { cout << ", which is compiler-generated" << endl; } else { cout << " in file " << start->get_raw_filename() << ", " << start->get_file_id() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl; } SgFunctionType * type = dec->get_type(); SgType * retType = type->get_return_type(); cout << "Return type: " << retType->unparseToString() << endl; SgFunctionParameterList * params = dec->get_parameterList(); SgInitializedNamePtrList & ptrList = params->get_args(); if(!ptrList.empty()) { cout << "Parameter types: "; for(SgInitializedNamePtrList::iterator j = ptrList.begin(); j != ptrList.end(); j++) { SgType * pType = (*j)->get_type(); cout << pType->unparseToString() << " "; } cout << endl; } cout << "Linkage: " << dec->get_linkage() << endl; cout << endl; } SgFunctionDefinition * def = isSgFunctionDefinition(n); if (def != NULL) { cout << "Found function definition " << def->get_declaration()->get_name().getString(); Sg_File_Info * start = def->get_startOfConstruct(); Sg_File_Info * end = def->get_endOfConstruct(); if(start->isCompilerGenerated()) { cout << ", which is compiler-generated" << endl; } else { cout << " in file " << start->get_raw_filename() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl; SgBasicBlock * body = def->get_body(); Sg_File_Info * bodyStart = body->get_startOfConstruct(); Sg_File_Info * bodyEnd = body->get_endOfConstruct(); cout << "Function body from line " << bodyStart->get_line() << ", col " << bodyStart->get_col() << " to line " << bodyEnd->get_line() << ", col " << bodyEnd->get_col() << endl; } cout << endl; } }
virtual void visit(SgNode *n) { SgDeclarationStatement *ds = isSgDeclarationStatement(n); SgFunctionDeclaration *fn = isSgFunctionDeclaration(n); if (!Doxygen::isRecognizedDeclaration(ds)) return; if (fn) { list<DoxygenComment *> *commentList = Doxygen::getCommentList(fn); bool isVoid = fn->get_type()->get_return_type()->variantT() == V_SgTypeVoid; for (list<DoxygenComment *>::iterator i = commentList->begin(); i != commentList->end(); ++i) { DoxygenComment *c = *i; if (isVoid) { c->attach(c->originalFile, c->originalFile->group("Functions returning void")); } else { c->attach(c->originalFile); } } } }
void SystemDependenceGraph::build() { boost::unordered_map<CFGVertex, Vertex> cfgVerticesToSdgVertices; boost::unordered_map<SgNode*, Vertex> astNodesToSdgVertices; //map<SgFunctionCallExp*, vector<SDGNode*> > funcCallToArgs; vector<CallSiteInfo> functionCalls; map<SgNode*, vector<Vertex> > actualInParameters; map<SgNode*, vector<Vertex> > actualOutParameters; map<SgNode*, Vertex> formalInParameters; map<SgNode*, Vertex> formalOutParameters; vector<SgFunctionDefinition*> funcDefs = SageInterface::querySubTree<SgFunctionDefinition>(project_, V_SgFunctionDefinition); foreach (SgFunctionDefinition* funcDef, funcDefs) { SgFunctionDeclaration* funcDecl = funcDef->get_declaration(); CFG* cfg = new CFG(funcDef, cfgNodefilter_); functionsToCFGs_[funcDecl] = cfg; // For each function, build an entry node for it. SDGNode* entry = new SDGNode(SDGNode::Entry); entry->astNode = funcDef; //entry->funcDef = funcDef; Vertex entryVertex = addVertex(entry); functionsToEntries_[funcDecl] = entryVertex; // Add all out formal parameters to SDG. const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); foreach (SgInitializedName* initName, formalArgs) { // If the parameter is passed by reference, create a formal-out node. if (isParaPassedByRef(initName->get_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); formalOutNode->astNode = initName; Vertex formalOutVertex = addVertex(formalOutNode); formalOutParameters[initName] = formalOutVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, formalOutVertex); } } // A vertex representing the returned value. Vertex returnVertex; // If the function returns something, build a formal-out node. if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); // Assign the function declaration to the AST node of this vertex to make // it possible to classify this node into the subgraph of this function. formalOutNode->astNode = funcDecl; returnVertex = addVertex(formalOutNode); formalOutParameters[funcDecl] = returnVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, returnVertex); } // Add all CFG vertices to SDG. foreach (CFGVertex cfgVertex, boost::vertices(*cfg)) { if (cfgVertex == cfg->getEntry() || cfgVertex == cfg->getExit()) continue; SgNode* astNode = (*cfg)[cfgVertex]->getNode(); // If this node is an initialized name and it is a parameter, make it // as a formal in node. SgInitializedName* initName = isSgInitializedName(astNode); if (initName && isSgFunctionParameterList(initName->get_parent())) { SDGNode* formalInNode = new SDGNode(SDGNode::FormalIn); formalInNode->astNode = initName; Vertex formalInVertex = addVertex(formalInNode); formalInParameters[initName] = formalInVertex; cfgVerticesToSdgVertices[cfgVertex] = formalInVertex; astNodesToSdgVertices[astNode] = formalInVertex; // Add a CD edge from call node to this formal-in node. addTrueCDEdge(entryVertex, formalInVertex); continue; } // Add a new node to SDG. SDGNode* newSdgNode = new SDGNode(SDGNode::ASTNode); //newSdgNode->cfgNode = (*cfg)[cfgVertex]; newSdgNode->astNode = astNode; Vertex sdgVertex = addVertex(newSdgNode); cfgVerticesToSdgVertices[cfgVertex] = sdgVertex; astNodesToSdgVertices[astNode] = sdgVertex; // Connect a vertex containing the return statement to the formal-out return vertex. if (isSgReturnStmt(astNode) || isSgReturnStmt(astNode->get_parent())) { SDGEdge* newEdge = new SDGEdge(SDGEdge::DataDependence); addEdge(sdgVertex, returnVertex, newEdge); } // If this CFG node contains a function call expression, extract its all parameters // and make them as actual-in nodes. if (SgFunctionCallExp* funcCallExpr = isSgFunctionCallExp(astNode)) { CallSiteInfo callInfo; callInfo.funcCall = funcCallExpr; callInfo.vertex = sdgVertex; // Change the node type. newSdgNode->type = SDGNode::FunctionCall; vector<SDGNode*> argsNodes; // Get the associated function declaration. SgFunctionDeclaration* funcDecl = funcCallExpr->getAssociatedFunctionDeclaration(); if (funcDecl == NULL) continue; ROSE_ASSERT(funcDecl); const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); SgExprListExp* args = funcCallExpr->get_args(); const SgExpressionPtrList& actualArgs = args->get_expressions(); if (formalArgs.size() != actualArgs.size()) { cout << "The following function has variadic arguments:\n"; cout << funcDecl->get_file_info()->get_filename() << endl; cout << funcDecl->get_name() << formalArgs.size() << " " << actualArgs.size() << endl; continue; } for (int i = 0, s = actualArgs.size(); i < s; ++i) { // Make sure that this parameter node is added to SDG then we // change its node type from normal AST node to a ActualIn arg. ROSE_ASSERT(astNodesToSdgVertices.count(actualArgs[i])); Vertex paraInVertex = astNodesToSdgVertices.at(actualArgs[i]); SDGNode* paraInNode = (*this)[paraInVertex]; paraInNode->type = SDGNode::ActualIn; actualInParameters[formalArgs[i]].push_back(paraInVertex); callInfo.inPara.push_back(paraInVertex); // Add a CD edge from call node to this actual-in node. addTrueCDEdge(sdgVertex, paraInVertex); // If the parameter is passed by reference, create a parameter-out node. if (isParaPassedByRef(formalArgs[i]->get_type())) { SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = actualArgs[i]; //argsNodes.push_back(paraInNode); // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[formalArgs[i]].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } } if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { // If this function returns a value, create a actual-out vertex. SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = funcCallExpr; // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[funcDecl].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); callInfo.isVoid = false; callInfo.returned = paraOutVertex; // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } functionCalls.push_back(callInfo); //funcCallToArgs[funcCallExpr] = argsNodes; } } // Add control dependence edges. addControlDependenceEdges(cfgVerticesToSdgVertices, *cfg, entryVertex); }
SgFunctionDeclaration * CudaOutliner::generateFunction ( SgBasicBlock* s, const string& func_name_str, ASTtools::VarSymSet_t& syms, MintHostSymToDevInitMap_t hostToDevVars, const ASTtools::VarSymSet_t& pdSyms, const ASTtools::VarSymSet_t& psyms, SgScopeStatement* scope) { //Create a function named 'func_name_str', with a parameter list from 'syms' //pdSyms specifies symbols which must use pointer dereferencing if replaced during outlining, //only used when -rose:outline:temp_variable is used //psyms are the symbols for OpenMP private variables, or dead variables (not live-in, not live-out) ROSE_ASSERT ( s && scope); ROSE_ASSERT(isSgGlobal(scope)); // step 1: perform necessary liveness and side effect analysis, if requested. // --------------------------------------------------------- std::set< SgInitializedName *> liveIns, liveOuts; // Collect read-only variables of the outlining target std::set<SgInitializedName*> readOnlyVars; if (Outliner::temp_variable||Outliner::enable_classic) { SgStatement* firstStmt = (s->get_statements())[0]; if (isSgForStatement(firstStmt)&& Outliner::enable_liveness) { LivenessAnalysis * liv = SageInterface::call_liveness_analysis (SageInterface::getProject()); SageInterface::getLiveVariables(liv, isSgForStatement(firstStmt), liveIns, liveOuts); } SageInterface::collectReadOnlyVariables(s,readOnlyVars); if (0)//Outliner::enable_debug) { cout<<" INFO:Mint: CudaOutliner::generateFunction()---Found "<<readOnlyVars.size()<<" read only variables..:"; for (std::set<SgInitializedName*>::const_iterator iter = readOnlyVars.begin(); iter!=readOnlyVars.end(); iter++) cout<<" "<<(*iter)->get_name().getString()<<" "; cout<<endl; cout<<"CudaOutliner::generateFunction() -----Found "<<liveOuts.size()<<" live out variables..:"; for (std::set<SgInitializedName*>::const_iterator iter = liveOuts.begin(); iter!=liveOuts.end(); iter++) cout<<" "<<(*iter)->get_name().getString()<<" "; cout<<endl; } } //step 2. Create function skeleton, 'func'. // ----------------------------------------- SgName func_name (func_name_str); SgFunctionParameterList *parameterList = buildFunctionParameterList(); SgType* func_Type = SgTypeVoid::createType (); SgFunctionDeclaration* func = createFuncSkeleton (func_name, func_Type ,parameterList, scope); //adds __global__ keyword func->get_functionModifier().setCudaKernel(); ROSE_ASSERT (func); // Liao, 4/15/2009 , enforce C-bindings for C++ outlined code // enable C code to call this outlined function // Only apply to C++ , pure C has trouble in recognizing extern "C" // Another way is to attach the function with preprocessing info: // #if __cplusplus // extern "C" // #endif // We don't choose it since the language linkage information is not explicit in AST if ( SageInterface::is_Cxx_language() || is_mixed_C_and_Cxx_language() \ || is_mixed_Fortran_and_Cxx_language() || is_mixed_Fortran_and_C_and_Cxx_language() ) { // Make function 'extern "C"' func->get_declarationModifier().get_storageModifier().setExtern(); func->set_linkage ("C"); } //step 3. Create the function body // ----------------------------------------- // Generate the function body by deep-copying 's'. SgBasicBlock* func_body = func->get_definition()->get_body(); ROSE_ASSERT (func_body != NULL); // This does a copy of the statements in "s" to the function body of the outlined function. ROSE_ASSERT(func_body->get_statements().empty() == true); // This calls AST copy on each statement in the SgBasicBlock, but not on the block, so the // symbol table is setup by AST copy mechanism and it is setup properly SageInterface::moveStatementsBetweenBlocks (s, func_body); if (Outliner::useNewFile) ASTtools::setSourcePositionAtRootAndAllChildrenAsTransformation(func_body); //step 4: variable handling, including: // ----------------------------------------- // create parameters of the outlined functions // add statements to unwrap the parameters if wrapping is requested // add repacking statements if necessary // replace variables to access to parameters, directly or indirectly // do not wrap parameters Outliner::enable_classic = true; functionParameterHandling(syms, hostToDevVars, pdSyms, psyms, readOnlyVars, liveOuts, func); ROSE_ASSERT (func != NULL); // Retest this... // Copied the similar fix from the rose outliner // Liao 2/6/2013. It is essential to rebuild function type after the parameter list is finalized. // The original function type was build using empty parameter list. SgType* stale_func_type = func->get_type(); func->set_type(buildFunctionType(func->get_type()->get_return_type(), buildFunctionParameterTypeList(func->get_parameterList()))); SgFunctionDeclaration* non_def_func = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration ()) ; ROSE_ASSERT (non_def_func != NULL); ROSE_ASSERT (stale_func_type == non_def_func->get_type()); non_def_func->set_type(func->get_type()); ROSE_ASSERT(func->get_definition()->get_body()->get_parent() == func->get_definition()); ROSE_ASSERT(scope->lookup_function_symbol(func->get_name())); return func; }
//searches for locations where types may be connected through assignment, passing as argument and returns //then passes the associated node along with the expression to link variables. int Analysis::variableSetAnalysis(SgProject* project, SgType* matchType, bool base){ RoseAst wholeAST(project); list<SgVariableDeclaration*> listOfGlobalVars = SgNodeHelper::listOfGlobalVars(project); if(listOfGlobalVars.size() > 0){ for(auto varDec : listOfGlobalVars){ SgInitializedName* initName = SgNodeHelper::getInitializedNameOfVariableDeclaration(varDec); if(!initName) continue; SgInitializer* init = initName->get_initializer(); if(!init) continue; SgType* keyType = initName->get_type(); if(!checkMatch(base, keyType, matchType)) continue; addToMap(varDec, varDec); if(!isArrayPointerType(keyType)) continue; SgExpression* exp = init; linkVariables(varDec, keyType, exp); } } list<SgFunctionDefinition*> listOfFunctionDefinitions = SgNodeHelper::listOfFunctionDefinitions(project); for(auto funDef : listOfFunctionDefinitions){ SgInitializedNamePtrList& initNameList = SgNodeHelper::getFunctionDefinitionFormalParameterList(funDef); SgFunctionDeclaration* funDec = funDef->get_declaration(); if(checkMatch(base, funDec->get_type()->get_return_type(), matchType)) addToMap(funDec, funDec); for(auto init : initNameList) if(checkMatch(base, init->get_type(), matchType)) addToMap(init, init); RoseAst ast(funDef); for(RoseAst::iterator i = ast.begin(); i!=ast.end(); i++){ SgNode* key = nullptr; SgType* keyType = nullptr; SgExpression* exp = nullptr; if(SgAssignOp* assignOp = isSgAssignOp(*i)){ SgExpression* lhs = assignOp->get_lhs_operand(); if(SgVarRefExp* varRef = isSgVarRefExp(lhs)){ keyType = varRef->get_type(); if(!isArrayPointerType(keyType)) continue; SgVariableSymbol* varSym = varRef->get_symbol(); key = varSym->get_declaration()->get_declaration(); } exp = assignOp->get_rhs_operand(); } else if(SgVariableDeclaration* varDec = isSgVariableDeclaration(*i)){ SgInitializedName* initName = SgNodeHelper::getInitializedNameOfVariableDeclaration(varDec); if(!initName) continue; if(checkMatch(base, matchType, initName->get_type())) addToMap(varDec, varDec); SgInitializer* init = initName->get_initializer(); if(!init) continue; keyType = initName->get_type(); if(!isArrayPointerType(keyType)) continue; key = initName->get_declaration(); exp = init; } else if(SgFunctionCallExp* callExp = isSgFunctionCallExp(*i)){ SgFunctionDefinition* funDef = SgNodeHelper::determineFunctionDefinition(callExp); if(!funDef) continue; SgInitializedNamePtrList& initNameList = SgNodeHelper::getFunctionDefinitionFormalParameterList(funDef); SgExpressionPtrList& expList = callExp->get_args()->get_expressions(); auto initIter = initNameList.begin(); auto expIter = expList.begin(); while(initIter != initNameList.end()){ if(isArrayPointerType((*initIter)->get_type())){ if(checkMatch(base, matchType, (*initIter)->get_type())) linkVariables((*initIter), (*initIter)->get_type(), (*expIter)); } ++initIter; ++expIter; } } else if(SgReturnStmt* ret = isSgReturnStmt(*i)){ exp = ret->get_expression(); keyType = exp->get_type(); if(!isArrayPointerType(keyType)) continue; key = funDec; } if(!checkMatch(base, keyType, matchType)) continue; if(key && keyType && exp) linkVariables(key, keyType, exp); } } for(auto i = setMap.begin(); i != setMap.end(); ++i){ bool intersect = false; set<SgNode*>* found = nullptr; for(auto j = listSets.begin(); j != listSets.end(); ++j){ intersect = setIntersect(*j, i->second); if((*j)->count(i->first)) intersect = true; if(found != nullptr && intersect){ inPlaceUnion(found, i->second); inPlaceUnion(found, *j); (found)->insert(i->first); j = listSets.erase(j); ++j; } else if(intersect){ inPlaceUnion(*j, i->second); (*j)->insert(i->first); found = *j; } } if(!intersect){ set<SgNode*>* copy = copySet(i->second); copy->insert(i->first); listSets.push_back(copy); } } return 0; }
void SimpleInstrumentation::visit ( SgNode* astNode ) { switch(astNode->variantT()) { case V_SgFunctionCallExp: { SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(astNode); SgExpression *function = functionCallExp->get_function(); ROSE_ASSERT(function); switch (function->variantT()) { case V_SgFunctionRefExp: { SgFunctionRefExp *functionRefExp = isSgFunctionRefExp(function); SgFunctionSymbol *symbol = functionRefExp->get_symbol(); ROSE_ASSERT(symbol != NULL); SgFunctionDeclaration *functionDeclaration = symbol->get_declaration(); ROSE_ASSERT(functionDeclaration != NULL); if (symbol == functionSymbol) { // Now we know that we have found the correct function call // (even in the presence of overloading or other forms of hidding) // Now fixup the symbol and type of the SgFunctionRefExp object to // reflect the new function to be called (after this we still have to // fixup the argument list in the SgFunctionCallExp. // We only want to build the decalration once (and insert it into the global scope) // after that we save the symbol and reuse it. if (newFunctionSymbol == NULL) { SgFunctionType* originalFunctionType = isSgFunctionType(functionSymbol->get_type()); ROSE_ASSERT(originalFunctionType != NULL); newFunctionSymbol = buildNewFunctionDeclaration (TransformationSupport::getStatement(astNode),originalFunctionType); } ROSE_ASSERT(newFunctionSymbol != NULL); ROSE_ASSERT(newFunctionSymbol->get_type() != NULL); functionRefExp->set_symbol(newFunctionSymbol); } break; } default: cerr<<"warning: unrecognized variant: "<<function->class_name(); } break; } case V_SgFunctionDeclaration: { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(astNode); string functionName = functionDeclaration->get_name().str(); if (functionName == "send") { SgFunctionType *functionType = functionDeclaration->get_type(); ROSE_ASSERT(functionType != NULL); bool foundFunction = false; if (functionType->get_return_type()->unparseToString() == "ssize_t") { SgTypePtrList & argumentList = functionType->get_arguments(); SgTypePtrList::iterator i = argumentList.begin(); if ( (*i++)->unparseToString() == "int" ) if ( (*i++)->unparseToString() == "const void *" ) if ( (*i++)->unparseToString() == "size_t" ) if ( (*i++)->unparseToString() == "int" ) foundFunction = true; } if (foundFunction == true) { // Now get the sysmbol using functionType SgScopeStatement *scope = functionDeclaration->get_scope(); ROSE_ASSERT(scope != NULL); functionSymbol = scope->lookup_function_symbol (functionName,functionType); } } break; } default: { // No other special cases } } }