void InstrumentationFunction::buildDeclaration(SgProject* project) { // ***************************************************** // Create the functionDeclaration // ***************************************************** Sg_File_Info * file_info = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); SgType *function_return_type = new SgTypeVoid(); type = new SgFunctionType(function_return_type, false); SgFunctionDeclaration *functionDeclaration = new SgFunctionDeclaration(file_info, name, type); // ******************************************************************** // Create the InitializedName for a parameter within the parameter list // ******************************************************************** /* SgName var1_name = "textString"; SgTypeChar * var1_type = new SgTypeChar(); SgPointerType *pointer_type = new SgPointerType(var1_type); SgInitializer * var1_initializer = NULL; SgInitializedName *var1_init_name = new SgInitializedName(var1_name, pointer_type, var1_initializer, NULL); // Insert argument in function parameter list ROSE_ASSERT(functionDeclaration != NULL); ROSE_ASSERT(functionDeclaration->get_parameterList() != NULL); ROSE_ASSERT(functionDeclaration->get_parameterList() != NULL); functionDeclaration->get_parameterList()->append_arg(var1_init_name); */ SgSourceFile* sourceFile = isSgSourceFile(project->get_fileList()[0]); ROSE_ASSERT(sourceFile != NULL); SgGlobal* globalScope = sourceFile->get_globalScope(); ROSE_ASSERT(globalScope != NULL); // Set the parent node in the AST (this could be done by the AstPostProcessing functionDeclaration->set_parent(globalScope); // Set the scope explicitly (since it could be different from the parent?) // This can't be done by the AstPostProcessing (unless we relax some constraints) functionDeclaration->set_scope(globalScope); // If it is not a forward declaration then the unparser will skip the ";" at the end (need to fix this better) functionDeclaration->setForward(); ROSE_ASSERT(functionDeclaration->isForward() == true); // Mark function as extern "C" functionDeclaration->get_declarationModifier().get_storageModifier().setExtern(); functionDeclaration->set_linkage("C"); // This mechanism could be improved! // Add function declaration to global scope globalScope->prepend_declaration(functionDeclaration); symbol = new SgFunctionSymbol(functionDeclaration); // All any modifications to be fixed up (parents etc) // AstPostProcessing(project); // This is not allowed and should be fixed! AstPostProcessing(globalScope); }
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; }
SgFunctionSymbol* SimpleInstrumentation::buildNewFunctionDeclaration ( SgStatement* statementLocation, SgFunctionType* previousFunctionType ) { // ***************************************************** // Create the functionDeclaration // ***************************************************** // Must mark the newly built node to be a part of a transformation so that it will be unparsed! Sg_File_Info * file_info = new Sg_File_Info(); ROSE_ASSERT(file_info != NULL); file_info->set_isPartOfTransformation(true); SgName function_name = "contest_call"; ROSE_ASSERT(previousFunctionType != NULL); SgFunctionDeclaration* functionDeclaration = new SgFunctionDeclaration(file_info, function_name, previousFunctionType); ROSE_ASSERT(functionDeclaration != NULL); ROSE_ASSERT(functionDeclaration->get_parameterList() != NULL); // ******************************************************************** // Create the InitializedName for a parameter within the parameter list // ******************************************************************** SgTypePtrList & argList = previousFunctionType->get_arguments(); SgTypePtrList::iterator i = argList.begin(); while ( i != argList.end() ) { SgName var_name = ""; SgInitializer* var_initializer = NULL; SgInitializedName *var_init_name = new SgInitializedName(var_name, *i, var_initializer, NULL); functionDeclaration->get_parameterList()->append_arg(var_init_name); i++; } // Add any additional function arguments here! Make sure that the function type is consistant. // Get the scope SgScopeStatement* scope = statementLocation->get_scope(); // Set the parent node in the AST (this could be done by the AstPostProcessing functionDeclaration->set_parent(scope); // Set the scope explicitly (since it could be different from the parent?) functionDeclaration->set_scope(scope); // If it is not a forward declaration then the unparser will skip the ";" at the end (need to fix this better) functionDeclaration->setForward(); ROSE_ASSERT(functionDeclaration->isForward() == true); // Mark function as extern "C" functionDeclaration->get_declarationModifier().get_storageModifier().setExtern(); functionDeclaration->set_linkage("C"); // This mechanism could be improved! bool inFront = true; SgGlobal* globalScope = TransformationSupport::getGlobalScope(statementLocation); SgFunctionDeclaration* functionDeclarationInGlobalScope = TransformationSupport::getFunctionDeclaration(statementLocation); ROSE_ASSERT(globalScope != NULL); ROSE_ASSERT(functionDeclarationInGlobalScope != NULL); globalScope->insert_statement(functionDeclarationInGlobalScope,functionDeclaration,inFront); SgFunctionSymbol* functionSymbol = new SgFunctionSymbol(functionDeclaration); ROSE_ASSERT(functionSymbol != NULL); ROSE_ASSERT(functionSymbol->get_type() != NULL); return functionSymbol; }