void assemblyOutput(char const *lineFormat, ...) { va_list args; va_start(args, lineFormat); char **buffer = getGlobalScope() ? &globalBuffer : &assemblyBuffer; char *buf1, *buf2; vasprintf(&buf1, lineFormat, args); asprintf(&buf2, "%s%s\n", *buffer, buf1); free(buf1); free(*buffer); *buffer = buf2; va_end(args); getGlobalScope() ? ++globalCount : ++linesCount; }
dereferencedSymbol_t createString(char const *value) { bool const oldGlobalScope = getGlobalScope(); setGlobalScope(true); int len = strlen(value) + 1; char *interningName; asprintf(&interningName, "__internedString__%s", value); dereferencedSymbol_t deref = getExistingSymbol(interningName, false); symbol_t *tab = deref.symbol; if(tab == &dummy) { tab = createArray(interningName, (varType_t){.indirectionCount = 0, .baseType = BT_CHAR, .constMask = 1}, len);
int main(int argc, char** argv) { //Parse command-line args ProgramOptions po(argc, argv); //Initialize the AST SgProject* project = new SgProject(argc, argv); ROSE_ASSERT(project); AstTests::runAllTests(project); //TODO switch on/off with command-line args //Set the folder containing the features string featureFolder = ""; bool defaultFeatures = po.getFeaturesFolder(featureFolder); if(!defaultFeatures) CallScheduler::setFeaturesFolder(featureFolder); //Loop through all partitioned kernels and add scheduling calls Rose_STL_Container<SgNode*> pragmas = querySubTree(project, V_SgPragmaDeclaration); Rose_STL_Container<SgNode*>::const_iterator pragmaIt = pragmas.begin(); SgPragmaDeclaration* pragma = NULL; SgFunctionDeclaration* funcDecl = NULL; SgStatement* stmt = NULL; for(pragmaIt = pragmas.begin(); pragmaIt != pragmas.end(); pragmaIt++) { pragma = isSgPragmaDeclaration(*pragmaIt); ROSE_ASSERT(pragma); PragmaParser pp(pragma); if(pp.isPopcornPragma() && pp.getPragmaType() == PARTITIONED) { stmt = getNextStatement(pragma); while(!isSgFunctionDeclaration(stmt)) stmt = getNextStatement(pragma); funcDecl = isSgFunctionDeclaration(stmt); ROSE_ASSERT(funcDecl); Pragmas pragmas(funcDecl); //Add scheduling calls CallScheduler cs(funcDecl, pragmas); cs.addSchedulerCalls(); //Insert the header //TODO this won't insert the header into files insertHeader(po.getSchedulerHeaderLocation(), PreprocessingInfo::after, false, getGlobalScope(funcDecl)); } } return backend(project); }
//! 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; }
int main(int argc, char** argv) { //Parse command-line options ProgramOptions po(argc, argv); //Initialize the AST SgProject* project = new SgProject(argc, argv); ROSE_ASSERT(project); AstTests::runAllTests(project); //TODO switch on/off with command-line args //Insert MM-wrapper header file string mmHeader = po.getMMWrapperHeaderLocation(); insertHeader(mmHeader, PreprocessingInfo::after, false, getGlobalScope(findMain(project))); //Initialize set of system headers & compiler generated vars RegisterPointers::initialize(); //Add calls to registers sizes of static variables RegisterVars rv(project, mmHeader); rv.registerStaticVars(); //Used to accumulate all global variables set<SgInitializedName*> globalVars; //Add wrapper calls to each function/sub-function so that all pointers are registered Rose_STL_Container<SgNode*> pragmas = querySubTree(project, V_SgPragmaDeclaration); Rose_STL_Container<SgNode*>::const_iterator pragmaIt; Rose_STL_Container<SgNode*> funcCalls = querySubTree(project, V_SgFunctionCallExp); SgPragmaDeclaration* pragma; SgStatement* stmt; SgFunctionDeclaration* funcDecl; for(pragmaIt = pragmas.begin(); pragmaIt != pragmas.end(); pragmaIt++) { pragma = isSgPragmaDeclaration(*pragmaIt); ROSE_ASSERT(pragma); PragmaParser pp(pragma); if(pp.isPopcornPragma() && pp.getPragmaType() == PARTITIONED) { //Get function declaration stmt = getNextStatement(pragma); while(!isSgFunctionDeclaration(stmt)) stmt = getNextStatement(stmt); funcDecl = isSgFunctionDeclaration(stmt); ROSE_ASSERT(funcDecl); Pragmas pragmas(funcDecl); //Save global variables saveGlobalVariables(pragmas.getGlobalInputs(), globalVars, pragmas.getFunction()->get_scope()); saveGlobalVariables(pragmas.getGlobalOutputs(), globalVars, pragmas.getFunction()->get_scope()); //Update call sites //TODO I don't think we need this anymore, since all sizes are //handled through the mm_wrapper interface //FunctionCallUpdater fcu(funcDecl, funcCalls); //fcu.updateDeclaration(); //fcu.updateSites(); } } //Register/unregister global variables RegisterVars::registerGlobalVars(globalVars); //Add call to initialize wrapper SgFunctionDeclaration* main = findMain(project); ROSE_ASSERT(main); FunctionCallUpdater::insertInitWrapperCall(main); return backend(project); }