Line data Source code
1 : /** 2 : * \file Transform/GenerateCall.cc 3 : * 4 : * \brief Given the outlined-function, this routine generates the 5 : * actual function call. 6 : */ 7 : // tps (01/14/2010) : Switching from rose.h to sage3. 8 : #include "sage3basic.h" 9 : #include "sageBuilder.h" 10 : #include <iostream> 11 : #include <string> 12 : #include <sstream> 13 : 14 : 15 : #include "Outliner.hh" 16 : #include "ASTtools.hh" 17 : #include "VarSym.hh" 18 : #include "StmtRewrite.hh" 19 : #include "Outliner.hh" 20 : 21 : // ===================================================================== 22 : 23 : using namespace std; 24 : 25 : // ===================================================================== 26 : 27 : 28 : //Generate a parameter list for a function call: 29 : // The caller of this function should analyze (figure out) exactly which form to use . 30 : // This function only takes care of the actual transformation. 31 : // 32 : //const ASTtools::VarSymSet_t& syms: a set of variables to be used in the parameter list 33 : // each input variable in the syms will be converted to a function parameter either using its original form (a) or addressOf form (&a) 34 : //std::set<SgInitializedName*> varUsingOriginalType: 35 : // indicate if some of the syms should using original types: passed by value (original type) for scalar, in C/C++; arrays for 36 : // syms - varUsingOriginalType==> the rest will be variables using address of (&A): passed-by-reference: original type for arrays or address of for others 37 0 : void Outliner::appendIndividualFunctionCallArgs (const ASTtools::VarSymSet_t& syms, const std::set<SgInitializedName*> varUsingOriginalType, SgExprListExp* e_list) 38 : { 39 0 : for (ASTtools::VarSymSet_t::const_iterator i = syms.begin (); 40 0 : i != syms.end (); ++i) 41 : { 42 0 : bool using_orig_type=false; 43 0 : SgInitializedName* iname = (*i)->get_declaration(); 44 0 : if (iname) 45 0 : if (varUsingOriginalType.find(iname)!=varUsingOriginalType.end()) 46 0 : using_orig_type = true; 47 : 48 : // Create variable reference to pass to the function. 49 0 : SgVarRefExp* v_ref = SageBuilder::buildVarRefExp (const_cast<SgVariableSymbol *> (*i)); 50 0 : ROSE_ASSERT (v_ref); 51 : // Liao, 12/14/2007 Pass by reference is default behavior for Fortran 52 0 : if (SageInterface::is_Fortran_language()) 53 0 : e_list->append_expression(v_ref); 54 : else // C/C++ call convention 55 : { 56 : // Construct actual function argument. //TODO: consider array types, they can only be passed by reference, no further addressing/de-referencing is needed 57 0 : SgExpression* i_arg=NULL; 58 0 : if (Outliner::enable_classic && using_orig_type ) // TODO expand to the default case also: using local declaration for transfer parameters 59 : // if (using_orig_type ) // using a 60 : { // classic translation, read only variable, pass by value directly 61 : i_arg = v_ref; 62 : } 63 : else // conservatively always use &a for the default case (no wrapper, none classic) 64 : { 65 0 : i_arg = SageBuilder::buildAddressOfOp (v_ref); 66 : } 67 0 : ROSE_ASSERT (i_arg); 68 0 : e_list->append_expression (i_arg); 69 : } //end if 70 : } // end for 71 0 : } 72 : 73 : // Append a single wrapper argument for a call to the outlined function 74 : // 75 : // ASTtools::VarSymSet_t& syms: original list of variables to be passed to the outlined function 76 : // std::string arg_name: name for the wrapper argument enclosing all syms 77 : // SgExprListExp* e_list: parameter list to be expanded 78 : // SgScopeStatement* scope : scope of the function call to be inserted into 79 : static 80 : void 81 0 : appendSingleWrapperArgument(const ASTtools::VarSymSet_t& syms, std::string arg_name, SgExprListExp* e_list, SgScopeStatement* scope) 82 : { 83 0 : if (!e_list) 84 : return; 85 0 : if ((Outliner::useParameterWrapper|| Outliner::useStructureWrapper) && (syms.size()>0)) 86 : { 87 0 : ROSE_ASSERT(scope!=NULL); 88 0 : if (Outliner::useStructureWrapper) 89 : { 90 : //using &_out_argv as a wrapper 91 0 : SageInterface::appendExpression(e_list,SageBuilder::buildAddressOfOp(SageBuilder::buildVarRefExp(arg_name ,scope))); 92 : } 93 : else // using array of pointers wrapper 94 : { 95 : // using void * __out_argv[n] as a wrapper 96 0 : SageInterface::appendExpression(e_list,SageBuilder::buildVarRefExp(arg_name ,scope)); 97 : } 98 : } 99 0 : else if ((Outliner::useStructureWrapper|| Outliner::useParameterWrapper) && (syms.size() ==0)) 100 : { 101 : // TODO: move this outside of outliner since it is OpenMP-specific 102 : //For OpenMP lowering, we have to have a void * parameter even if there is no need to pass any parameters 103 : //in order to match the gomp runtime lib 's function prototype for function pointers 104 0 : SgFile* cur_file = SageInterface::getEnclosingFileNode(scope); 105 0 : ROSE_ASSERT (cur_file != NULL); 106 : //if (cur_file->get_openmp_lowering ()) 107 0 : { 108 0 : SageInterface::appendExpression(e_list, SageBuilder::buildIntVal(0)); 109 : } 110 : } 111 : #if 0 112 : else 113 : { 114 : cerr<<"Error. unreachable branch reached in GenerateCall.cc: appendSingleWrapperArgument()"<<endl; 115 : ROSE_ASSERT (false); 116 : } 117 : #endif 118 : } 119 : 120 : 121 : 122 : #if 0 123 : //! Convert the given set of variable symbols into function call arguments. 124 : // This is used for generating the function call to the outlined function. 125 : // syms: all variables to be passed into/out the outlined function 126 : // varsUsingOriginalType: only used in C/C++ outlining without any wrapper parameter: decide if a parameter should use original form (a) or addressOf form (&a) 127 : // 128 : // We have two major cases 129 : // Using parameter wrapping: useParameterWrapper (array) vs. useStructureWrapper 130 : // Without using parameter wrapping: each variable is an individual function argument 131 : static 132 : void 133 : appendArgs (const ASTtools::VarSymSet_t& syms, std::set<SgInitializedName*> varsUsingOriginalType, std::string arg_name, SgExprListExp* e_list, SgScopeStatement* scope) 134 : { 135 : if (!e_list) 136 : return; 137 : if ((Outliner::useParameterWrapper|| Outliner::useStructureWrapper) && (syms.size()>0)) 138 : { 139 : ROSE_ASSERT(scope!=NULL); 140 : if (Outliner::useStructureWrapper) 141 : { 142 : //using &_out_argv as a wrapper 143 : SageInterface::appendExpression(e_list,SageBuilder::buildAddressOfOp(SageBuilder::buildVarRefExp(arg_name ,scope))); 144 : } 145 : else 146 : { 147 : // using void * __out_argv[n] as a wrapper 148 : SageInterface::appendExpression(e_list,SageBuilder::buildVarRefExp(arg_name ,scope)); 149 : } 150 : 151 : return; 152 : } 153 : else if (Outliner::useStructureWrapper && (syms.size() ==0)) 154 : { 155 : // TODO: move this outside of outliner since it is OpenMP-specific 156 : //For OpenMP lowering, we have to have a void * parameter even if there is no need to pass any parameters 157 : //in order to match the gomp runtime lib 's function prototype for function pointers 158 : SgFile* cur_file = SageInterface::getEnclosingFileNode(scope); 159 : ROSE_ASSERT (cur_file != NULL); 160 : if (cur_file->get_openmp_lowering ()) 161 : { 162 : SageInterface::appendExpression(e_list, SageBuilder::buildIntVal(0)); 163 : } 164 : } 165 : else // no parameter wrapping, a parameter for each variable 166 : { 167 : appendIndividualFunctionCallArgs (syms,varsUsingOriginalType,e_list); 168 : } 169 : } 170 : 171 : #endif 172 : // ===================================================================== 173 : 174 : //! Generate a call to the outlined function 175 : // We have two ways to generate the corresponding parameter lists 176 : // Choice 1: each variable is converted to a function parameter. 177 : // varsUsingOriginalForm: is used to decide if original form (a) should be used, the rest should use addressOf form (&a) 178 : // wrapper_name: is irrelevant in this case 179 : // Choice 2: all variables are wrapped into a single parameter 180 : // wrapper_name: is the name of the wrapper parameter 181 : // varsUsingOriginalForm: is irrelevant in this choice 182 : SgStatement * 183 0 : Outliner::generateCall (SgFunctionDeclaration* out_func, // the outlined function we want to call 184 : const ASTtools::VarSymSet_t& syms, // variables for generating function arguments 185 : const std::set<SgInitializedName*> varsUsingOriginalForm, // used to the classic outlining without wrapper: using a (originalForm) vs. &a 186 : std::string wrapper_name, // when parameter wrapping is used, provide wrapper argument's name 187 : SgScopeStatement* scope) // the scope in which we insert the function call 188 : { 189 : // Create a reference to the function. 190 0 : SgGlobal* glob_scope = TransformationSupport::getGlobalScope(scope); 191 0 : ROSE_ASSERT(glob_scope != NULL); 192 0 : SgFunctionSymbol* func_symbol = glob_scope->lookup_function_symbol(out_func->get_name()); 193 0 : if (func_symbol == NULL) 194 : { 195 0 : printf("Failed to find a function symbol in %p for function %s\n", glob_scope, out_func->get_name().getString().c_str()); 196 0 : ROSE_ASSERT(func_symbol != NULL); 197 : } 198 0 : ROSE_ASSERT (func_symbol); 199 : 200 : // Create an argument list. 201 0 : SgExprListExp* exp_list_exp = SageBuilder::buildExprListExp(); 202 0 : ROSE_ASSERT (exp_list_exp); 203 : //appendArgs (syms, readOnlyVars, wrapper_name, exp_list_exp,scope); 204 0 : if (Outliner::useParameterWrapper|| Outliner::useStructureWrapper) 205 0 : appendSingleWrapperArgument (syms, wrapper_name,exp_list_exp,scope); 206 : else 207 0 : appendIndividualFunctionCallArgs (syms, varsUsingOriginalForm, exp_list_exp); 208 : 209 : // Generate the actual call. 210 0 : SgFunctionCallExp* func_call_expr = SageBuilder::buildFunctionCallExp(func_symbol,exp_list_exp); 211 0 : ROSE_ASSERT (func_call_expr); 212 : 213 0 : SgExprStatement *func_call_stmt = SageBuilder::buildExprStatement (func_call_expr); 214 0 : ROSE_ASSERT (func_call_stmt); 215 : 216 0 : return func_call_stmt; 217 : } 218 : 219 : // eof