// Build counter accumulation statement like chloads = chloads + chiterations * (2 * 8) // chloads is the counter name, chiterations is iteration_count_name, 2*8 is the per-iteration count expression. SgExprStatement* buildCounterAccumulationStmt (std::string counter_name, std::string iteration_count_name, SgExpression* count_exp_per_iteration, SgScopeStatement* scope) { assert (scope!= NULL); assert (count_exp_per_iteration != NULL); assert (counter_name.size()!=0); assert (iteration_count_name.size()!=0); SgVariableSymbol * chiterations_sym = lookupVariableSymbolInParentScopes(SgName(iteration_count_name), scope); assert (chiterations_sym!=NULL); SgVariableSymbol * counter_sym = lookupVariableSymbolInParentScopes(SgName(counter_name), scope); assert (counter_sym!=NULL); SgExprStatement* counter_acc_stmt = buildByteCalculationStmt (counter_sym, chiterations_sym, count_exp_per_iteration); return counter_acc_stmt; }
void CudaOutliner::setKernelParams(int dimension, SgStatement* func_call_stmt, SgScopeStatement* scope) { /* dim3 threads(chunksizeX, chunksizeY); int numBlocksX = n/ chunksizeX; int numBlocksY = n/ (chunksizeY*numRows); dim3 grid(numBlocksX, numBlocksY); */ SgInitializedName* arg1 = buildInitializedName(SgName("BLOCKDIM_X"), buildIntType()); SgInitializedName* arg2 = buildInitializedName(SgName("BLOCKDIM_Y"), buildIntType()); SgType* dim3_t = buildOpaqueType("dim3", scope); SgExprListExp* exprList = buildExprListExp(); //appendArg(exprList, arg1); //ppendArg(exprList, arg2); SgFunctionParameterList * paraList = buildFunctionParameterList(); appendArg(paraList, arg1); appendArg(paraList, arg2); SgMemberFunctionDeclaration * funcdecl = buildNondefiningMemberFunctionDeclaration ("threads", dim3_t, paraList); SgConstructorInitializer* constr = new SgConstructorInitializer(funcdecl, exprList, dim3_t, false, false, false, false ); string dimBlock = MintTools::generateBlockDimName(func_call_stmt); SgVariableDeclaration * dim_blocks_var_decl = buildVariableDeclaration(dimBlock, dim3_t, constr); /* string dimGrid = generateGridDimName(func_call_stmt); SgVariableDeclaration * dim_grid_var_decl = buildVariableDeclaration(dimGrid, dim3_t); */ cout<< dim_blocks_var_decl->unparseToString ()<< endl ; }
/* * Replace the op_par_loop with respective kernel function */ void OPSource::fixParLoops(SgNode *n) { SgName kernel_name; SgFunctionCallExp *fn = isSgFunctionCallExp(n); if(fn != NULL) { string fn_name = fn->getAssociatedFunctionDeclaration()->get_name().getString(); if(fn_name.compare("op_par_loop_2")==0 || fn_name.compare("op_par_loop_3")==0 || fn_name.compare("op_par_loop_4")==0 || fn_name.compare("op_par_loop_5")==0 || fn_name.compare("op_par_loop_6")==0 || fn_name.compare("op_par_loop_7")==0 || fn_name.compare("op_par_loop_8")==0 || fn_name.compare("op_par_loop_9")==0) { SgExprListExp* exprList = fn->get_args(); SgExpressionPtrList &exprs = exprList->get_expressions(); SgFunctionRefExp* varExp = isSgFunctionRefExp(exprs[0]); if(varExp != NULL) { kernel_name = varExp->get_symbol()->get_name(); } exprs.erase(exprs.begin()); SgExpressionPtrList::iterator it = exprs.begin() + op_par_loop_args::num_params - 1; for(; it != exprs.end(); it += op_argument::num_params) { *it = buildCastExp( *it, buildPointerType(SgClassType::createType( buildStructDeclaration("op_dat<void>"))) ); } // Inject Name exprs.insert(exprs.begin(), buildStringVal(kernel_name)); // Fetch the declaration SgName name = SgName("op_par_loop_") + kernel_name; SgFunctionDeclaration *funcDecl = cudaFunctionDeclarations[kernel_name]; if(funcDecl) { SgFunctionRefExp* ref = isSgFunctionRefExp(fn->get_function()); SgFunctionSymbol *symbol = ref->get_symbol(); symbol->set_declaration(funcDecl); ref->set_symbol(symbol); fn->set_function(ref); } } } }
SgSymbol * ClangToSageTranslator::GetSymbolFromSymbolTable(clang::NamedDecl * decl) { if (decl == NULL) return NULL; SgScopeStatement * scope = SageBuilder::topScopeStack(); SgName name(decl->getNameAsString()); #if DEBUG_SYMBOL_TABLE_LOOKUP std::cerr << "Lookup symbol for: " << name << std::endl; #endif if (name == "") { return NULL; } std::list<SgScopeStatement *>::reverse_iterator it; SgSymbol * sym = NULL; switch (decl->getKind()) { case clang::Decl::Typedef: { it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_typedef_symbol(name); it++; } break; } case clang::Decl::Var: case clang::Decl::ParmVar: { it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_variable_symbol(name); it++; } break; } case clang::Decl::Function: { SgType * tmp_type = buildTypeFromQualifiedType(((clang::FunctionDecl *)decl)->getType()); SgFunctionType * type = isSgFunctionType(tmp_type); ROSE_ASSERT(type); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_function_symbol(name, type); it++; } break; } case clang::Decl::Field: { SgClassDeclaration * sg_class_decl = isSgClassDeclaration(Traverse(((clang::FieldDecl *)decl)->getParent())); ROSE_ASSERT(sg_class_decl != NULL); if (sg_class_decl->get_definingDeclaration() == NULL) std::cerr << "Runtime Error: cannot find the definition of the class/struct associate to the field: " << name << std::endl; else { scope = isSgClassDeclaration(sg_class_decl->get_definingDeclaration())->get_definition(); // TODO: for C++, if 'scope' is in 'SageBuilder::ScopeStack': problem!!! // It means that we are currently building the class while (scope != NULL && sym == NULL) { sym = scope->lookup_variable_symbol(name); scope = scope->get_scope(); } } break; } case clang::Decl::CXXRecord: case clang::Decl::Record: { it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_class_symbol(name); it++; } break; } case clang::Decl::Label: { // Should not be reach as we use Traverse to retrieve Label (they are "terminal" statements) (it avoids the problem of forward use of label: goto before declaration) name = SgName(((clang::LabelDecl *)decl)->getStmt()->getName()); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_label_symbol(name); it++; } break; } case clang::Decl::EnumConstant: { name = SgName(((clang::EnumConstantDecl *)decl)->getName()); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_enum_field_symbol(name); it++; } break; } case clang::Decl::Enum: { name = SgName(((clang::EnumDecl *)decl)->getName()); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_enum_symbol(name); it++; } break; } default: std::cerr << "Runtime Error: Unknown type of Decl. (" << decl->getDeclKindName() << ")" << std::endl; } return sym; }
//A generic function to check if a loop has a tag statement prepended to it, asking for instrumentation //If so, the loop will be instrumented and the tag statement will be returned. // This function supports both C/C++ for loops and Fortran Do loops SgStatement* instrumentLoopForCounting(SgStatement* loop) { //get scope of the loop assert (loop != NULL); SgForStatement* forloop = isSgForStatement(loop); SgFortranDo* doloop = isSgFortranDo(loop); SgScopeStatement* scope = NULL; if (forloop) scope = forloop->get_scope(); else if (doloop) scope = doloop->get_scope(); else { cerr<<"Error in instrumentLoopForCounting(): Unrecognized loop type:"<< loop->class_name()<<endl; assert(false); } ROSE_ASSERT(scope != NULL); // Only for a do-loop which immediately follows chiterations = .. SgVariableSymbol * chiterations_sym = lookupVariableSymbolInParentScopes(SgName("chiterations"), isSgScopeStatement(loop)); if (chiterations_sym==NULL) return NULL; SgStatement* prev_stmt = getPreviousStatement(loop,false); // backwards search, skipping pragma declaration etc. while (prev_stmt!=NULL && !isAssignmentStmtOf (prev_stmt, chiterations_sym->get_declaration())) prev_stmt = getPreviousStatement(prev_stmt,false); if (prev_stmt == NULL) return NULL; // To support nested loops, we need to use unique chiterations variable for each loop // otherwise the value stored in inner loop will overwrite the iteration count for the outerloop. loop_id ++; // increment loop ID // insert size_t chiterations_id ; // Find the enclosing function declaration, including its derived instances like //isSgProcedureHeaderStatement, isSgProgramHeaderStatement, and isSgMemberFunctionDeclaration. SgFunctionDeclaration* func_decl = getEnclosingFunctionDeclaration (loop); ROSE_ASSERT (func_decl !=NULL); SgFunctionDefinition* func_def = func_decl->get_definition(); ROSE_ASSERT (func_def !=NULL); SgBasicBlock* func_body = func_def->get_body(); // insert a new variable declaration std::string new_iter_var_name = std::string("chiterations_") + StringUtility::numberToString(loop_id); SgVariableDeclaration* new_iter_var_decl = buildVariableDeclaration(new_iter_var_name, chiterations_sym->get_type(), NULL, func_body); SgStatement* last_decl = findLastDeclarationStatement(func_body); if (last_decl!=NULL) insertStatementAfter (last_decl, new_iter_var_decl, false); else prependStatement(new_iter_var_decl, func_body); // rewrite the assignment stmt's left hand variable to be the new symbol SgExpression* lhs = NULL; bool rt = isAssignmentStatement (prev_stmt, &lhs); ROSE_ASSERT (rt == true); ROSE_ASSERT (lhs != NULL); SgVarRefExp* var_ref = isSgVarRefExp (lhs); ROSE_ASSERT (var_ref != NULL); var_ref->set_symbol(getFirstVarSym (new_iter_var_decl)); SgStatement* loop_body = NULL; if (forloop) loop_body = forloop->get_loop_body(); else if (doloop) loop_body = doloop->get_body(); assert (loop_body != NULL); // count FP operations for each loop CountFPOperations (loop_body); //chflops=chflops+chiterations*n FPCounters* current_result = getFPCounters (loop_body); if (current_result->getTotalCount() >0) { SgExprStatement* stmt = buildCounterAccumulationStmt("chflops", new_iter_var_name , buildIntVal(current_result->getTotalCount()),scope); insertStatementAfter (loop, stmt); attachComment(stmt," aitool generated FLOPS counting statement ..."); } // Obtain per-iteration load/store bytes calculation expressions // excluding scalar types to match the manual version //CountLoadStoreBytes (SgLocatedNode* input, bool includeScalars = true, bool includeIntType = true); std::pair <SgExpression*, SgExpression*> load_store_count_pair = CountLoadStoreBytes (loop_body, false, true); // chstores=chstores+chiterations*8 if (load_store_count_pair.second!= NULL) { SgExprStatement* store_byte_stmt = buildCounterAccumulationStmt("chstores", new_iter_var_name, load_store_count_pair.second, scope); insertStatementAfter (loop, store_byte_stmt); attachComment(store_byte_stmt," aitool generated Stores counting statement ..."); } // handle loads stmt 2nd so it can be inserted as the first after the loop // build chloads=chloads+chiterations*2*8 if (load_store_count_pair.first != NULL) { SgExprStatement* load_byte_stmt = buildCounterAccumulationStmt("chloads", new_iter_var_name, load_store_count_pair.first, scope); insertStatementAfter (loop, load_byte_stmt); attachComment(load_byte_stmt," aitool generated Loads counting statement ..."); } return prev_stmt; } // end instrumentLoopForCounting()
//! Return an expression like 8*sizeof(int)+ 3*sizeof(float) + 5*sizeof(double) for a list of variables accessed (either read or write) // For array variable, we should only count a single element access, not the entire array size // Algorithm: // Iterate on each variable in the set // group them into buckets based on types, using a map<SgType*, int> to store this // Iterate the list of buckets to generate count*sizeof(type) + .. expression SgExpression* calculateBytes (std::set<SgInitializedName*>& name_set, SgScopeStatement* scope, bool isRead) { SgExpression* result = NULL; if (name_set.size()==0) return result; // the input is essentially the loop body, a scope statement ROSE_ASSERT (scope != NULL); // We need to record the associated loop info. SgStatement* loop= NULL; SgForStatement* forloop = isSgForStatement(scope->get_scope()); SgFortranDo* doloop = isSgFortranDo(scope->get_scope()); if (forloop) loop = forloop; else if (doloop) loop = doloop; else { cerr<<"Error in CountLoadStoreBytes (): input is not loop body type:"<< scope->class_name()<<endl; assert(false); } std::map<SgType* , int> type_based_counters; // get all processed variables by inner loops std::set<SgInitializedName*> processed_var_set; getVariablesProcessedByInnerLoops (scope, isRead, processed_var_set); // fill in the type-based counters std::set<SgInitializedName*>::iterator set_iter; for (set_iter = name_set.begin(); set_iter != name_set.end(); set_iter++) { SgInitializedName* init_name = *set_iter; // skip visited variable when processing inner loops // some global variables may be visited by another function // But we should count it when processing the current function! // // We group all references to a same variable into one reference for now // if a variable is considered when processing inner loops, the variable // will be skipped when processing outer loops. if (isRead) { // if inner loops already processed it, skip it if (processed_var_set.find(init_name) != processed_var_set.end()) continue; else LoopLoadVariables[loop].insert(init_name); } else { if (processed_var_set.find(init_name) != processed_var_set.end()) continue; else LoopStoreVariables[loop].insert(init_name); } // It is tricky here, TODO consider pointer, typedefs, reference, modifier types SgType* stripped_type = (*set_iter)->get_type()->stripTypedefsAndModifiers(); SgType* base_type = NULL; if (isScalarType(stripped_type)) base_type = stripped_type; else if (isSgArrayType(stripped_type)) { // we may have multi-dimensional arrays like int a[][][]; base_type = stripped_type; do { base_type = isSgArrayType(base_type)->get_base_type(); } while (isSgArrayType (base_type)); } else { cerr<<"Error in calculateBytes(). Unhandled stripped type:"<<stripped_type->class_name()<<endl; assert (false); } type_based_counters[base_type] ++; } // end for // use the type-based counters for byte calculation std::map<SgType* , int>::iterator citer; //It is possible now to have zero after filtering out redundant variables //assert (type_based_counters.size()>0); for (citer = type_based_counters.begin(); citer !=type_based_counters.end(); citer ++) { SgType* t = (*citer).first; // at this point, we should not have array types any more ROSE_ASSERT (isSgArrayType (t) == false); int count = (*citer).second; assert (t != NULL); assert (count>0); SgExpression* sizeof_exp = NULL; if (is_Fortran_language()) { #if 0 // this does not work. cannot find func symbol for sizeof() // In Fortran sizeof() is a function call, not SgSizeOfOp. // type name is a variable in the AST, // Too much trouble to build assert (scope !=NULL); // This does not work //SgFunctionSymbol* func_sym = lookupFunctionSymbolInParentScopes(SgName("sizeof"), scope); SgGlobal* gscope = getGlobalScope (scope); assert (gscope !=NULL); SgFunctionSymbol* func_sym = gscope->lookup_function_symbol(SgName("sizeof")); assert (func_sym!=NULL); SgVarRefExp* type_var = buildVarRefExp( t->unparseToString(), scope ); assert (type_var !=NULL); sizeof_exp = buildFunctionCallExp (func_sym, buildExprListExp(type_var)); #else // sizeof is not an operator in Fortran, there is no unparsing support for this // sizeof_exp = buildSizeOfOp(t); // Directly obtain an integer size value sizeof_exp = buildIntVal(getSizeOf(t)); #endif } else if (is_C_language() || is_C99_language() || is_Cxx_language()) { sizeof_exp = buildSizeOfOp(t); } else { cerr<<"Error in calculateBytes(). Unsupported programming language other than C/Cxx and Fortran. "<<endl; assert (false); } SgExpression* mop = buildMultiplyOp(buildIntVal(count), sizeof_exp); if (result == NULL) result = mop; else result = buildAddOp(result, mop); } return result; }
TEST(SageInterfaceTypeEquivalence, ConstVarIntLiteralArrayIsEqual){ ::SgGlobal *global = new SgGlobal(); // build assign-initializer, build variable declaration, build varrefexp ::SgBasicBlock* bb = SageBuilder::buildBasicBlock(); bb->set_parent(global); ::SgAssignInitializer* init = SageBuilder::buildAssignInitializer(SageBuilder::buildIntVal(42), SageBuilder::buildIntType()); ::SgVariableDeclaration* vDecl = isSgVariableDeclaration(SageBuilder::buildVariableDeclaration(SgName("refVar"), SageBuilder::buildConstType(SageBuilder::buildIntType()), init, bb)); // vDecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier().setConst(); ::SgVarRefExp* vRef = SageBuilder::buildVarRefExp(vDecl); ::SgArrayType* a_7 = SageBuilder::buildArrayType(SageBuilder::buildIntType(), vRef); ::SgArrayType* a_8 = SageBuilder::buildArrayType(SageBuilder::buildIntType(), vRef); bool tcRef = SageInterface::checkTypesAreEqual(a_7, a_8); EXPECT_EQ(tcRef, true); delete global; }
void flattenScopes(SgFunctionDefinition * fDef) { // * 3.3: find all variables in the function,give them a unique name and move them to the bgeinning of the function, this is allowed because this is for C only!!!. This would not work for classes which must be constructed // rename variables list<SgNode*> varDeclList=NodeQuery::querySubTree(fDef,V_SgInitializedName); for (list<SgNode*>::iterator varDecl=varDeclList.begin();varDecl!=varDeclList.end();varDecl++) { tring varName=isSgInitializedName(*varDecl)->get_name().getString(); char numberCString[255]; sprintf(numberCString,"%i",idNr); string newVarName=string("PML")+string(numberCString)+string("_")+varName; idNr++; isSgInitializedName(*varDecl)->set_name(SgName(newVarName.c_str())); } list<SgNode*> newDeclList; varDeclList.clear(); varDeclList=NodeQuery::querySubTree(procFuncVec[procNr],V_SgVariableDeclaration); // the move the variable declaration to the function begin and replace the old declaration site with a definition for (list<SgNode*>::iterator varDecl=varDeclList.begin();varDecl!=varDeclList.end();varDecl++) { SgVariableDeclaration * varDeclStmt=isSgVariableDeclaration(*varDecl); SgVariableDefinition * varDef=varDeclStmt->get_definition(); SgInitializedName *iniName=isSgInitializedName(varDef->get_vardefn()); if (iniName->get_initializer () !=NULL) { // cout <<"VarDecl >"<<iniName->get_name().getString()<<"< has initilizer >"<<iniName->get_initializer ()->unparseToString()<<"<"<<endl; // determine if it is safe to separate initializer from decl // for now true if (1) { Sg_File_Info * fi=Sg_File_Info::generateDefaultFileInfoForTransformationNode(); SgVarRefExp * varRef=new SgVarRefExp (Sg_File_Info::generateDefaultFileInfoForTransformationNode(),new SgVariableSymbol(iniName)); SgType * type=isSgAssignInitializer(iniName->get_initializer())->get_type (); SgAssignInitializer * sai=isSgAssignInitializer(iniName->get_initializer()); if (sai==NULL) { cerr<<"isSgAssignInitializer(iniName->get_initializer())=NULL"<<endl; exit(-1); } SgExpression *lhs,*rhs; lhs=varRef; rhs=sai->get_operand (); if (lhs==NULL) { cerr<<"lhs=NULL"<<endl; exit(-1); } if (rhs==NULL) { cerr<<"rhs=NULL"<<endl; exit(-1); } SgAssignOp * assignment=new SgAssignOp(Sg_File_Info::generateDefaultFileInfoForTransformationNode(),lhs,rhs); SgExprStatement * expr=new SgExprStatement(fi,assignment); if (expr==NULL) { cerr<<"construction of expr failed"<<endl; } isSgAssignInitializer(iniName->get_initializer ())->set_operand(NULL); free(iniName->get_initializer ()); iniName->set_initializer (NULL); // put the iniName in the list newDeclList.push_back(varDeclStmt); if (isSgStatement(varDeclStmt)==NULL) { cerr<<"isSgStatement(varDeclStmt)==NULL"<<endl; } LowLevelRewrite::replace(isSgStatement(varDeclStmt),isSgStatement(expr)); } } else { cout <<"VarDecl >"<<iniName->get_name().getString()<<"> is uninitialized"<<endl; newDeclList.push_back(varDeclStmt); LowLevelRewrite::remove(isSgStatement(varDeclStmt)); } } for (list<SgNode*>::iterator varDecl=newDeclList.begin();varDecl!=newDeclList.end();varDecl++) { fDef->prepend_statement(isSgStatement(*varDecl)); } return ; }
void CudaOutliner::functionParameterHandling(ASTtools::VarSymSet_t& syms, // regular (shared) parameters MintHostSymToDevInitMap_t hostToDevVars, const ASTtools::VarSymSet_t& pdSyms, // those must use pointer dereference const ASTtools::VarSymSet_t& pSyms, // private variables, handles dead variables (neither livein nor liveout) std::set<SgInitializedName*> & readOnlyVars, std::set<SgInitializedName*> & liveOutVars, SgFunctionDeclaration* func) // the outlined function { //ASTtools::VarSymSet_t syms; //std::copy(syms1.begin(), syms1.end(), std::inserter(syms,syms.begin())); VarSymRemap_t sym_remap; // variable remapping for regular(shared) variables VarSymRemap_t private_remap; // variable remapping for private/firstprivate/reduction variables ROSE_ASSERT (func); SgFunctionParameterList* params = func->get_parameterList (); ROSE_ASSERT (params); SgFunctionDefinition* def = func->get_definition (); ROSE_ASSERT (def); SgBasicBlock* body = def->get_body (); ROSE_ASSERT (body); // Place in which to put new outlined variable symbols. SgScopeStatement* args_scope = isSgScopeStatement (body); ROSE_ASSERT (args_scope); // For each variable symbol, create an equivalent function parameter. // Also create unpacking and repacking statements. int counter=0; // SgInitializedName* parameter1=NULL; // the wrapper parameter SgVariableDeclaration* local_var_decl = NULL; // handle OpenMP private variables/ or those which are neither live-in or live-out handlePrivateVariables(pSyms, body, private_remap); // -------------------------------------------------- // for each parameters passed to the outlined function // They include parameters for regular shared variables and // also the shared copies for firstprivate and reduction variables for (ASTtools::VarSymSet_t::reverse_iterator i = syms.rbegin ();i != syms.rend (); ++i) { // Basic information about the variable to be passed into the outlined function // Variable symbol name const SgInitializedName* i_name = (*i)->get_declaration (); ROSE_ASSERT (i_name); string name_str = i_name->get_name ().str (); SgName p_sg_name ( name_str); //SgType* i_type = i_name->get_type (); bool readOnly = false; if (readOnlyVars.find(const_cast<SgInitializedName*> (i_name)) != readOnlyVars.end()) readOnly = true; // step 1. Create parameters and insert it into the parameter list. // ---------------------------------------- SgInitializedName* p_init_name = NULL; SgVariableSymbol* host_sym= const_cast<SgVariableSymbol*> (*i); if(hostToDevVars.find(host_sym) != hostToDevVars.end() ){ //these are vector variables SgInitializedName* dev_name = hostToDevVars[host_sym]; p_init_name = createInitName (dev_name->get_name(), dev_name->get_type(), func, def); ROSE_ASSERT (p_init_name); prependArg(func->get_parameterList (),p_init_name); } else{ //scalar values p_init_name = createOneFunctionParameter(i_name, readOnly, func); } // step 2. Create unpacking/unwrapping statements, also record variables to be replaced // ---------------------------------------- // bool isPointerDeref = false; if (Outliner::enable_classic) { // classic methods use parameters directly, no unpacking is needed if (!readOnly) //read only variable should not have local variable declaration, using parameter directly // taking advantage of the same parameter names for readOnly variables // Let postprocessing to patch up symbols for them { // non-readonly variables need to be mapped to their parameters with different names (p__) // remapVarSyms() will use pointer dereferencing for all of them by default in C, // this is enough to mimic the classic outlining work //handleSharedVariables(*i, p_init_name, args_scope, sym_remap); //handleSharedVariables(*i, body, sym_remap); //Didem: I comment out this part because it uses pointer deferencing for all non-readonly variables. //recordSymRemap(*i,p_init_name, args_scope, sym_remap); } } else { local_var_decl = NULL; //createUnpackDecl (p_init_name, counter, isPointerDeref, i_name , NULL, body); ROSE_ASSERT (local_var_decl); prependStatement (local_var_decl,body); // regular and shared variables used the first local declaration recordSymRemap (*i, local_var_decl, args_scope, sym_remap); // transfer the value for firstprivate variables. } // step 3. Create and insert companion re-pack statement in the end of the function body // If necessary // ---------------------------------------- SgInitializedName* local_var_init = NULL; if (local_var_decl != NULL ) local_var_init = local_var_decl->get_decl_item (SgName (name_str.c_str ())); if (!SageInterface::is_Fortran_language() && !Outliner::enable_classic) ROSE_ASSERT(local_var_init!=NULL); SgExprStatement* pack_stmt = createPackStmt (local_var_init); if (pack_stmt) appendStatement (pack_stmt,body); counter ++; } //end for // variable substitution SgBasicBlock* func_body = func->get_definition()->get_body(); remapVarSyms (sym_remap, pdSyms, private_remap , func_body); }
void instr(SgProject* project, Rose_STL_Container<SgType*> types) { SgGlobal* global = SI::getFirstGlobalScope(project); std::string prefix("rtc_ti_"); //struct prefix std::string ti_type_str("struct rtc_typeinfo*"); SgType* ti_type = SB::buildOpaqueType(ti_type_str,global); //Insert declarations from the typechecking library. //void minalloc_check(unsigned long long addr) SgFunctionDeclaration* minalloc_check_decl = SB::buildNondefiningFunctionDeclaration( SgName("minalloc_check"), SgTypeVoid::createType(), SB::buildFunctionParameterList( SB::buildInitializedName("addr",SB::buildUnsignedLongLongType())), global,NULL); SI::prependStatement(minalloc_check_decl,global); //void typetracker_add(unsigned long long addr, struct rtc_typeinfo* ti); SgFunctionDeclaration* typetracker_add_decl = SB::buildNondefiningFunctionDeclaration( SgName("typetracker_add"), SgTypeVoid::createType(), SB::buildFunctionParameterList( SB::buildInitializedName("addr",SB::buildUnsignedLongLongType()), SB::buildInitializedName("ti",ti_type)), global,NULL); SI::prependStatement(typetracker_add_decl,global); //void setBaseType(rtc_typeinfo* ti, rtc_typeinfo* base) SgFunctionDeclaration* setBaseType_decl = SB::buildNondefiningFunctionDeclaration( SgName("setBaseType"), SgTypeVoid::createType(), SB::buildFunctionParameterList( SB::buildInitializedName("ti",ti_type), SB::buildInitializedName("base",ti_type)), global,NULL); SI::prependStatement(setBaseType_decl,global); //struct rtc_typeinfo* ti_init(const char* a, size_t sz, int c) SgFunctionDeclaration* ti_init_decl = SB::buildNondefiningFunctionDeclaration( SgName("ti_init"), ti_type, SB::buildFunctionParameterList( // SB::buildInitializedName("a",SB::buildPointerType(SB::buildConstType(SB::buildCharType()))), SB::buildInitializedName("a",SB::buildPointerType(SB::buildCharType())), // SB::buildInitializedName("sz", SB::buildOpaqueType("size_t",global)), SB::buildInitializedName("sz", SB::buildLongLongType()), SB::buildInitializedName("c", SB::buildIntType())), global,NULL); SI::prependStatement(ti_init_decl,global); //void traverseAndPrint() SgFunctionDeclaration* traverseAndPrint_decl = SB::buildNondefiningFunctionDeclaration( SgName("traverseAndPrint"),SgTypeVoid::createType(),SB::buildFunctionParameterList(),global,NULL); SI::prependStatement(traverseAndPrint_decl,global); //non-defining declaration of rtc_init_typeinfo SgName init_name("rtc_init_typeinfo"); SgFunctionDeclaration* init_nondef = SB::buildNondefiningFunctionDeclaration(init_name,SgTypeVoid::createType(),SB::buildFunctionParameterList(),global,NULL); SI::prependStatement(init_nondef,global); //call to rtc_init_typeinfo placed in main function. SgFunctionDeclaration* maindecl = SI::findMain(project); SgExprStatement* initcall = SB::buildFunctionCallStmt(init_name,SgTypeVoid::createType(),NULL,maindecl->get_definition()); maindecl->get_definition()->prepend_statement(initcall); //defining declaration of rtc_init_typeinfo SgFunctionDeclaration* init_definingDecl = new SgFunctionDeclaration(new Sg_File_Info(SI::getEnclosingFileNode(global)->getFileName()),init_name,init_nondef->get_type(),NULL); init_definingDecl->set_firstNondefiningDeclaration(init_nondef); SgFunctionDefinition* init_definition = new SgFunctionDefinition(new Sg_File_Info(SI::getEnclosingFileNode(global)->getFileName()),init_definingDecl,SB::buildBasicBlock()); init_definingDecl->set_definition(init_definition); SI::appendStatement(init_definingDecl,global); std::vector<std::string> lst; for(unsigned int index = 0; index < types.size(); index++) { SgType* ptr = types[index]; ptr = ptr->stripTypedefsAndModifiers(); if(!shouldInstrumentType(ptr)) continue; std::string nameStr = prefix + Util::getNameForType(ptr).getString(); if(!contains(lst,nameStr)) { SgVariableDeclaration* decl = SB::buildVariableDeclaration(nameStr,ti_type,NULL,global); SI::prependStatement(decl,global); lst.push_back(nameStr); } } for(unsigned int index = 0; index < types.size(); index++) { SgType* ptr = types[index]; ptr = ptr->stripTypedefsAndModifiers(); if(!shouldInstrumentType(ptr)) continue; std::string typeNameStr = Util::getNameForType(ptr).getString(); std::string structNameStr = prefix + Util::getNameForType(ptr).getString(); if(contains(lst,structNameStr)) { SgExpression* lhs; SgExpression* rhs; //In case of an anonymous struct or union, we create a local, named version of the declaration so we can know its size. SgClassDeclaration* altDecl = NULL; if(isSgNamedType(ptr) && isSgClassDeclaration(isSgNamedType(ptr)->get_declaration()) && isSgClassDeclaration(isSgNamedType(ptr)->get_declaration())->get_isUnNamed()) { SgClassDeclaration* originalDecl = isSgClassDeclaration(isSgNamedType(ptr)->get_declaration()->get_definingDeclaration()); SgName altDecl_name(typeNameStr + "_def"); altDecl = new SgClassDeclaration(new Sg_File_Info(SI::getEnclosingFileNode(global)->getFileName()),altDecl_name,originalDecl->get_class_type()); SgClassDefinition* altDecl_definition = SB::buildClassDefinition(altDecl); SgDeclarationStatementPtrList originalMembers = originalDecl->get_definition()->get_members(); for(SgDeclarationStatementPtrList::iterator it = originalMembers.begin(); it != originalMembers.end(); it++) { SgDeclarationStatement* member = *it; SgDeclarationStatement* membercpy = isSgDeclarationStatement(SI::copyStatement(member)); altDecl_definition->append_member(membercpy); } SgClassDeclaration* altDecl_nondef = new SgClassDeclaration(new Sg_File_Info(SI::getEnclosingFileNode(global)->getFileName()),altDecl_name,originalDecl->get_class_type()); altDecl_nondef->set_scope(global); altDecl->set_scope(global); altDecl->set_firstNondefiningDeclaration(altDecl_nondef); altDecl_nondef->set_firstNondefiningDeclaration(altDecl_nondef); altDecl->set_definingDeclaration(altDecl); altDecl_nondef->set_definingDeclaration(altDecl); SgClassType* altDecl_ct = SgClassType::createType(altDecl_nondef); altDecl->set_type(altDecl_ct); altDecl_nondef->set_type(altDecl_ct); altDecl->set_isUnNamed(false); altDecl_nondef->set_isUnNamed(false); altDecl_nondef->set_forward(true); SgSymbol* sym = new SgClassSymbol(altDecl_nondef); global->insert_symbol(altDecl_name, sym); altDecl->set_linkage("C"); altDecl_nondef->set_linkage("C"); ROSE_ASSERT(sym && sym->get_symbol_basis() == altDecl_nondef); ROSE_ASSERT(altDecl->get_definingDeclaration() == altDecl); ROSE_ASSERT(altDecl->get_firstNondefiningDeclaration() == altDecl_nondef); ROSE_ASSERT(altDecl->search_for_symbol_from_symbol_table() == sym); ROSE_ASSERT(altDecl->get_definition() == altDecl_definition); ROSE_ASSERT(altDecl->get_scope() == global && altDecl->get_scope() == altDecl_nondef->get_scope()); ROSE_ASSERT(altDecl_ct->get_declaration() == altDecl_nondef); //For some reason, this is not working... //global->append_statement(altDecl); //global->prepend_statement(altDecl_nondef); //SI::setOneSourcePositionForTransformation(altDecl); //SI::setOneSourcePositionForTransformation(altDecl_nondef); } SgType* baseType; if(isSgPointerType(ptr)) baseType = ptr->dereference(); else baseType = ptr->findBaseType(); baseType = baseType->stripTypedefsAndModifiers(); if(baseType == NULL || baseType == ptr) { //In this case, there is no base type. rhs = SB::buildFunctionCallExp(SgName("ti_init"),SgTypeVoid::createType(),SB::buildExprListExp( SB::buildStringVal(ptr->unparseToString()), ((altDecl == NULL && !isSgTypeVoid(ptr)) ? (SgExpression*) SB::buildSizeOfOp(types[index]) : (SgExpression*) SB::buildIntVal(-1)), SB::buildIntVal(getClassification(ptr)) ),init_definition); } else { //The type has a base type. std::string baseStructNameStr = prefix + Util::getNameForType(baseType).getString(); rhs = SB::buildFunctionCallExp(SgName("ti_init"),ti_type,SB::buildExprListExp( SB::buildStringVal(ptr->unparseToString()), ((altDecl == NULL && !isSgTypeVoid(ptr)) ? (SgExpression*) SB::buildSizeOfOp(types[index]) : (SgExpression*) SB::buildIntVal(-1)), SB::buildIntVal(getClassification(ptr)) ),init_definition); SgExprStatement* set_BT = SB::buildFunctionCallStmt(SgName("setBaseType"),ti_type,SB::buildExprListExp( SB::buildVarRefExp(structNameStr), SB::buildVarRefExp(baseStructNameStr)), init_definition); init_definition->append_statement(set_BT); } lhs = SB::buildVarRefExp(structNameStr); SgExprStatement* assignstmt = SB::buildAssignStatement(lhs,rhs); init_definition->prepend_statement(assignstmt); std::remove(lst.begin(),lst.end(),structNameStr); } } }