charmxi: fix indentation of array entry method call code
[charm.git] / src / xlat-i / xi-Entry.C
blob6dcc28f0fd2b27f9a01d816271804090dcebae0f
1 #include "xi-Entry.h"
2 #include "xi-Parameter.h"
3 #include "xi-Value.h"
4 #include "xi-SdagCollection.h"
5 #include "xi-Chare.h"
7 #include "sdag/constructs/When.h"
9 #include <list>
10 using std::list;
12 namespace xi {
14 extern int fortranMode;
15 extern int internalMode;
16 const char *python_doc;
18 XStr Entry::proxyName(void) {return container->proxyName();}
19 XStr Entry::indexName(void) {return container->indexName();}
21 void Entry::print(XStr& str)
23   if(isThreaded())
24     str << "threaded ";
25   if(isSync())
26     str << "sync ";
27   if(retType) {
28     retType->print(str);
29     str << " ";
30   }
31   str << name<<"(";
32   if(param)
33     param->print(str);
34   str << ")";
35   if(stacksize) {
36     str << " stacksize = ";
37     stacksize->print(str);
38   }
39   str << ";\n";
42 void Entry::check() {
43   if (!external) {
44     if (isConstructor() && retType && !retType->isVoid())
45       XLAT_ERROR_NOCOL("constructors cannot return a value",
46                        first_line_);
48     if (!isConstructor() && !retType)
49       XLAT_ERROR_NOCOL("non-constructor entry methods must specify a return type (probably void)",
50                        first_line_);
52     if (isConstructor() && (isSync() || isIget())) {
53       XLAT_ERROR_NOCOL("constructors cannot have the 'sync' attribute",
54                        first_line_);
55       attribs ^= SSYNC;
56     }
58     if (param->isCkArgMsgPtr() && (!isConstructor() || !container->isMainChare()))
59       XLAT_ERROR_NOCOL("CkArgMsg can only be used in mainchare's constructor",
60                        first_line_);
62     if (isExclusive() && isConstructor())
63       XLAT_ERROR_NOCOL("constructors cannot be 'exclusive'",
64                        first_line_);
66     if (isImmediate() && !container->isNodeGroup())
67       XLAT_ERROR_NOCOL("[immediate] entry methods are only allowed on 'nodegroup' types",
68                        first_line_);
70     if (isLocal() && (container->isChare() || container->isNodeGroup()))
71       XLAT_ERROR_NOCOL("[local] entry methods are only allowed on 'array' and 'group' types",
72                        first_line_);
73   }
75   if (!isThreaded() && stacksize)
76     XLAT_ERROR_NOCOL("the 'stacksize' attribute is only applicable to methods declared 'threaded'",
77                      first_line_);
79   if (retType && !isSync() && !isIget() && !isLocal() && !retType->isVoid())
80     XLAT_ERROR_NOCOL("non-void return type in a non-sync/non-local entry method\n"
81                      "To return non-void, you need to declare the method as [sync], which means it has blocking semantics,"
82                      " or [local].",
83                      first_line_);
85   if (!isLocal() && param)
86     param->checkParamList();
88   if (isPython() && !container->isPython())
89     XLAT_ERROR_NOCOL("python entry method declared in non-python chare",
90                      first_line_);
92   // check the parameter passed to the function, it must be only an integer
93   if (isPython() && (!param || param->next || !param->param->getType()->isBuiltin() || !((BuiltinType*)param->param->getType())->isInt()))
94     XLAT_ERROR_NOCOL("python entry methods take only one parameter, which is of type 'int'",
95                      first_line_);
97   if (isExclusive() && !container->isNodeGroup())
98       XLAT_ERROR_NOCOL("only nodegroup methods can be 'exclusive'",
99                        first_line_);
101   // (?) Check that every when statement has a corresponding entry method
102   // declaration. Otherwise, print all candidates tested (as in clang, gcc.)
103   if (isSdag()) {
104     list<CEntry*> whenEntryList;
105     sdagCon->generateEntryList(whenEntryList, NULL);
107     for (list<CEntry*>::iterator en = whenEntryList.begin(); en != whenEntryList.end(); ++en) {
108       container->lookforCEntry(*en);
109       (*en)->check();
110     }
111   }
114 void Entry::lookforCEntry(CEntry *centry)
116    // compare name
117    if (strcmp(name, *centry->entry) != 0) return;
119    centry->addCandidate(this);
121    // compare param
122    if (param && !centry->paramlist) return;
123    if (!param && centry->paramlist) return;
124    if (param && !(*param == *centry->paramlist)) return;
126    isWhenEntry = 1;
127    centry->decl_entry = this;
130 Entry::Entry(int l, int a, Type *r, const char *n, ParamList *p, Value *sz, SdagConstruct *sc, const char *e, int fl, int ll) :
131   attribs(a), retType(r), stacksize(sz), sdagCon(sc), name((char *)n), targs(0), intExpr(e), param(p), genClosureTypeName(0), genClosureTypeNameProxy(0), genClosureTypeNameProxyTemp(0), entryPtr(0), first_line_(fl), last_line_(ll)
133   line=l; container=NULL;
134   entryCount=-1;
135   isWhenEntry=0;
136   if (param && param->isMarshalled() && !isThreaded()) attribs|=SNOKEEP;
138   if (isPython()) pythonDoc = python_doc;
139   ParamList *plist = p;
140   while (plist != NULL) {
141     plist->entry = this;
142     if (plist->param) plist->param->entry = this;
143     plist = plist->next;
144   }
147 void Entry::setChare(Chare *c) {
148         Member::setChare(c);
149         // mainchare constructor parameter is not allowed
150         /* ****************** REMOVED 10/8/2002 ************************
151         if (isConstructor()&&container->isMainChare() && param != NULL)
152           if (!param->isCkArgMsgPtr())
153            die("MainChare Constructor doesn't allow parameter!", line);
154         Removed old treatment for CkArgMsg to allow argc, argv or void
155         constructors for mainchares.
156         * **************************************************************/
157         if (isConstructor() && param->isVoid()) {
158           if (container->isMainChare()) {
159             //Main chare always magically takes CkArgMsg
160             Type *t = new PtrType(new NamedType("CkArgMsg"));
161             param=new ParamList(new Parameter(line,t));
162             std::cerr << "Charmxi> " << line << ": Deprecation warning: mainchare constructors should explicitly take CkArgMsg* if that's how they're implemented.\n";
163           }
164           if (container->isArray()) {
165             Array *a = dynamic_cast<Array*>(c);
166             a->hasVoidConstructor = true;
167           }
168         }
170         entryCount=c->nextEntry();
172         //Make a special "callmarshall" method, for communication optimizations to use:
173         hasCallMarshall=param->isMarshalled() && !isThreaded() && !isSync() && !isExclusive() && !fortranMode;
174         if (isSdag())
175         {
176           container->setSdag(1);
178           list<CEntry*> whenEntryList;
179           sdagCon->generateEntryList(whenEntryList, NULL);
181           for (list<CEntry*>::iterator i = whenEntryList.begin(); i != whenEntryList.end(); ++i) {
182             container->lookforCEntry(*i);
183           }
184         }
187 void Entry::preprocessSDAG()
189   if (isSdag() || isWhenEntry) {
190     if (container->isNodeGroup())
191       {
192         attribs |= SLOCKED; // Make the method [exclusive] to preclude races on SDAG control structures
193       }
194   }
197 // "parameterType *msg" or "void".
198 // Suitable for use as the only parameter
199 XStr Entry::paramType(int withDefaultVals,int withEO,int useConst)
201   XStr str;
202   param->print(str,withDefaultVals,useConst);
203   if (withEO) str<<eo(withDefaultVals,!param->isVoid());
204   return str;
207 // "parameterType *msg," if there is a non-void parameter,
208 // else empty.  Suitable for use with another parameter following.
209 XStr Entry::paramComma(int withDefaultVals,int withEO)
211   XStr str;
212   if (!param->isVoid()) {
213     str << paramType(withDefaultVals,withEO);
214     str << ", ";
215   }
216   return str;
218 XStr Entry::eo(int withDefaultVals,int priorComma) {
219   XStr str;
220   if (param->isMarshalled()) {//FIXME: add options for void methods, too...
221     if (priorComma) str<<", ";
222     str<<"const CkEntryOptions *impl_e_opts";
223     if (withDefaultVals) str<<"=NULL";
224   }
225   return str;
228 void Entry::collectSdagCode(SdagCollection *sc)
230   if (isSdag()) {
231     sc->addNode(this);
232   }
235 XStr Entry::marshallMsg(void)
237   XStr ret;
238   XStr epName = epStr();
239   param->marshall(ret, epName);
240   return ret;
243 XStr Entry::epStr(bool isForRedn, bool templateCall)
245   XStr str;
246   if (isForRedn)
247     str<<"redn_wrapper_";
248   str << name << "_";
250   if (param->isMessage()) {
251     str<<param->getBaseName();
252     str.replace(':', '_');
253   }
254   else if (param->isVoid())
255     str<<"void";
256   else
257     str<<"marshall"<<entryCount;
259   if (tspec && templateCall) {
260     str << "< ";
261     tspec->genShort(str);
262     str << " >";
263   }
265   return str;
268 XStr Entry::epIdx(int fromProxy, bool isForRedn)
270   XStr str;
271   if (fromProxy) {
272     str << indexName()<<"::";
273     // If the chare is also templated, then we must avoid a parsing ambiguity
274     if (tspec)
275       str << "template ";
276   }
277   str << "idx_" << epStr(isForRedn, true) << "()";
278   return str;
281 XStr Entry::epRegFn(int fromProxy, bool isForRedn)
283   XStr str;
284   if (fromProxy)
285     str << indexName() << "::";
286   str << "reg_" << epStr(isForRedn, true) << "()";
287   return str;
290 XStr Entry::chareIdx(int fromProxy)
292   XStr str;
293   if (fromProxy)
294     str << indexName()<<"::";
295   str << "__idx";
296   return str;
299 XStr Entry::syncPreCall(void) {
300   XStr str;
301   if(retType->isVoid())
302     str << "  void *impl_msg_typed_ret = ";
303   else if(retType->isMessage()) 
304     str << "  "<< retType <<" impl_msg_typed_ret = ("<< retType <<")";
305   else
306     str << "  CkMarshallMsg *impl_msg_typed_ret = (CkMarshallMsg *)";
307   return str;
310 XStr Entry::syncPostCall(void) {
311   XStr str;
312   if(retType->isVoid())
313     str << "  CkFreeSysMsg(impl_msg_typed_ret); \n";
314   else if (!retType->isMessage()){
315       str <<"  char *impl_buf_ret=impl_msg_typed_ret->msgBuf; \n";
316       str <<"  PUP::fromMem implPS(impl_buf_ret); \n";
317       str <<"  "<<retType<<" retval; implPS|retval; \n";
318       str <<"  CkFreeMsg(impl_msg_typed_ret); \n";
319       str <<"  return retval; \n"; 
320   }
321   else{
322      str <<"  return impl_msg_typed_ret;\n";   
323   }
324   return str;
329 /*************************** Chare Entry Points ******************************/
331 void Entry::genChareDecl(XStr& str)
333   if(isConstructor()) {
334     genChareStaticConstructorDecl(str);
335   } else {
336     // entry method declaration
337     str << "    " << generateTemplateSpec(tspec) << "\n"
338         << "    " << retType << " " << name << "(" << paramType(1,1) << ");\n";
339   }
342 void Entry::genChareDefs(XStr& str)
344   if(isConstructor()) {
345     genChareStaticConstructorDefs(str);
346   } else {
347     XStr params; params<<epIdx()<<", impl_msg, &ckGetChareID()";
348     // entry method definition
349     XStr retStr; retStr<<retType;
350     str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<")\n";
351     str << "{\n  ckCheck();\n"<<marshallMsg();
352     if(isSync()) {
353       str <<  syncPreCall() << "CkRemoteCall("<<params<<");\n";
354       str << syncPostCall(); 
355     } else {//Regular, non-sync message
356       str << "  if (ckIsDelegated()) {\n";
357       str << "    int destPE=CkChareMsgPrep("<<params<<");\n";
358       str << "    if (destPE!=-1) ckDelegatedTo()->ChareSend(ckDelegatedPtr(),"<<params<<",destPE);\n";
359       str << "  }\n";
360       XStr opts;
361       opts << ",0";
362       if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
363       if (isInline())  opts << "+CK_MSG_INLINE";
364       str << "  else CkSendMsg("<<params<<opts<<");\n";
365     }
366     str << "}\n";
367   }
370 void Entry::genChareStaticConstructorDecl(XStr& str)
372   str << "    static CkChareID ckNew("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
373   str << "    static void ckNew("<<paramComma(1)<<"CkChareID* pcid, int onPE=CK_PE_ANY"<<eo(1)<<");\n";
374   if (!param->isVoid())
375     str << "    "<<container->proxyName(0)<<"("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
378 void Entry::genChareStaticConstructorDefs(XStr& str)
380   str << makeDecl("CkChareID",1)<<"::ckNew("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
381   str << "{\n"<<marshallMsg();
382   str << "  CkChareID impl_ret;\n";
383   str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
384   str << "  return impl_ret;\n";
385   str << "}\n";
387   str << makeDecl("void",1)<<"::ckNew("<<paramComma(0)<<"CkChareID* pcid, int impl_onPE"<<eo(0)<<")\n";
388   str << "{\n"<<marshallMsg();
389   str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, pcid, impl_onPE);\n";
390   str << "}\n";
392   if (!param->isVoid()) {
393     str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
394     str << "{\n"<<marshallMsg();
395     str << "  CkChareID impl_ret;\n";
396     str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
397     str << "  ckSetChareID(impl_ret);\n";
398     str << "}\n";
399   }
402 /***************************** Array Entry Points **************************/
404 void Entry::genArrayDecl(XStr& str)
406   if(isConstructor()) {
407     str << "    " << generateTemplateSpec(tspec) << "\n";
408     genArrayStaticConstructorDecl(str);
409   } else {
410     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
411     str << "    " << generateTemplateSpec(tspec) << "\n";
412     if(isIget())
413       str << "    "<<"CkFutureID"<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
414     else if(isLocal())
415       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<") ;\n";
416     else
417       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
418   }
421 void Entry::genArrayDefs(XStr& str)
423   if(isIget() && !container->isForElement()) return;
425   if (isConstructor())
426     genArrayStaticConstructorDefs(str);
427   else
428   {//Define array entry method
429     const char *ifNot="CkArray_IfNotThere_buffer";
430     if (isCreateHere()) ifNot="CkArray_IfNotThere_createhere";
431     if (isCreateHome()) ifNot="CkArray_IfNotThere_createhome";
433     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
435     XStr retStr; retStr<<retType;
436     if(isIget())
437       str << makeDecl("CkFutureID ",1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
438     else if(isLocal())
439       str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1,0)<<") \n";
440     else
441       str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
442     str << "{\n  ckCheck();\n";
443     XStr inlineCall;
444     if (!isNoTrace())
445       inlineCall << "    _TRACE_BEGIN_EXECUTE_DETAILED(0,ForArrayEltMsg,(" << epIdx()
446                  << "),CkMyPe(), 0, ((CkArrayIndex&)ckGetIndex()).getProjectionID(((CkGroupID)ckGetArrayID()).idx), obj);\n";
447     if(isAppWork())
448       inlineCall << "    _TRACE_BEGIN_APPWORK();\n";
449     inlineCall << "#if CMK_LBDB_ON\n"
450                << "    LDObjHandle objHandle;\n"
451                << "    int objstopped=0;\n"
452                << "    objHandle = obj->timingBeforeCall(&objstopped);\n"
453                << "#endif\n";
454     inlineCall <<
455       "#if CMK_CHARMDEBUG\n"
456       "    CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
457       "#endif\n";
458     inlineCall << "    ";
459     if (!retType->isVoid())
460       inlineCall << retType << " retValue = ";
461     inlineCall << "obj->" << name << "(";
462     param->unmarshall(inlineCall);
463     inlineCall << ");\n";
464     inlineCall <<
465       "#if CMK_CHARMDEBUG\n"
466       "    CpdAfterEp("<<epIdx()<<");\n"
467       "#endif\n";
468     inlineCall << "#if CMK_LBDB_ON\n    obj->timingAfterCall(objHandle,&objstopped);\n#endif\n";
469     if(isAppWork())
470       inlineCall << "    _TRACE_END_APPWORK();\n";
471     if (!isNoTrace()) inlineCall << "    _TRACE_END_EXECUTE();\n";
472     if (!retType->isVoid()) {
473       inlineCall << "    return retValue;\n";
474     } else {
475       inlineCall << "    return;\n";
476     }
478     XStr prepareMsg;
479     prepareMsg << marshallMsg();
480     prepareMsg << "  UsrToEnv(impl_msg)->setMsgtype(ForArrayEltMsg);\n";
481     prepareMsg << "  CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;\n";
482     prepareMsg << "  impl_amsg->array_setIfNotThere("<<ifNot<<");\n";
484     if (!isLocal()) {
485       if (isInline() && container->isForElement()) {
486         str << "  " << container->baseName() << " *obj = ckLocal();\n";
487         str << "  if (obj) {\n"
488             << inlineCall
489             << "  }\n";
490       }
491       str << prepareMsg;
492     } else {
493       str << "  "<< container->baseName() << " *obj = ckLocal();\n";
494       str << "#if CMK_ERROR_CHECKING\n";
495       str << "  if (obj==NULL) CkAbort(\"Trying to call a LOCAL entry method on a non-local element\");\n";
496       str << "#endif\n";
497       str << inlineCall;
498     }
499     if(isIget()) {
500             str << "  CkFutureID f=CkCreateAttachedFutureSend(impl_amsg,"<<epIdx()<<",ckGetArrayID(),ckGetIndex(),&CProxyElement_ArrayBase::ckSendWrapper);"<<"\n";
501     }
503     if(isSync()) {
504       str << syncPreCall() << "ckSendSync(impl_amsg, "<<epIdx()<<");\n";
505       str << syncPostCall(); 
506     }
507     else if (!isLocal())
508     {
509       XStr opts;
510       opts << ",0";
511       if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
512       if (isInline())  opts << "+CK_MSG_INLINE";
513       if(!isIget()) {
514       if (container->isForElement() || container->isForSection()) {
515         str << "  ckSend(impl_amsg, "<<epIdx()<<opts<<");\n";
516       }
517       else
518         str << "  ckBroadcast(impl_amsg, "<<epIdx()<<opts<<");\n";
519       }
520     }
521     if(isIget()) {
522             str << "  return f;\n";
523     }
524     str << "}\n";
525   }
528 void Entry::genArrayStaticConstructorDecl(XStr& str)
530   if (!container->isArray())
531     die("Internal error - array declarations called for on non-array Chare type");
533   if (container->getForWhom() == forIndividual)
534       str<< //Element insertion routine
535       "    void insert("<<paramComma(1,0)<<"int onPE=-1"<<eo(1)<<");";
536   else if (container->getForWhom() == forAll) {
537       //With options to specify size (including potentially empty, covering the param->isVoid() case)
538       str << "    static CkArrayID ckNew(" << paramComma(1,0) << "const CkArrayOptions &opts = CkArrayOptions()" << eo(1) << ");\n";
539       str << "    static void      ckNew(" << paramComma(1,0) << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb" << eo(1) << ");\n";
541       XStr dim = ((Array*)container)->dim();
542       if (dim == (const char*)"1D") {
543         str << "    static CkArrayID ckNew(" << paramComma(1,0) << "const int s1" << eo(1)<<");\n";
544         str << "    static void ckNew("      << paramComma(1,0) << "const int s1, CkCallback _ck_array_creation_cb" << eo(1) <<");\n";
545       } else if (dim == (const char*)"2D") {
546         str << "    static CkArrayID ckNew(" << paramComma(1,0) << "const int s1, const int s2"<<eo(1)<<");\n";
547         str << "    static void ckNew("      << paramComma(1,0) << "const int s1, const int s2, CkCallback _ck_array_creation_cb" << eo(1) <<");\n";
548       } else if (dim == (const char*)"3D") {
549         str << "    static CkArrayID ckNew(" << paramComma(1,0) << "const int s1, const int s2, const int s3" << eo(1)<<");\n";
550         str << "    static void ckNew("      << paramComma(1,0) << "const int s1, const int s2, const int s3, CkCallback _ck_array_creation_cb" << eo(1) <<");\n";
551       /*} else if (dim==(const char*)"4D") {
552         str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4"<<eo(1)<<");\n";
553       } else if (dim==(const char*)"5D") {
554         str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n";
555       } else if (dim==(const char*)"6D") {
556         str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5, const short s6"<<eo(1)<<");\n"; */
557       }
558   }
559   else if (container->getForWhom() == forSection) { }
562 void Entry::genArrayStaticConstructorDefs(XStr& str)
564   if (!container->isArray())
565     die("Internal error - array definitions called for on non-array Chare type");
567   if (container->getForWhom() == forIndividual)
568       str<<
569       makeDecl("void",1)<<"::insert("<<paramComma(0,0)<<"int onPE"<<eo(0)<<")\n"
570       "{ \n"<<marshallMsg()<<
571       "   UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
572       "   ckInsert((CkArrayMessage *)impl_msg,"<<epIdx()<<",onPE);\n}\n";
573   else if (container->getForWhom() == forAll) {
574     XStr syncPrototype, asyncPrototype, head, syncTail, asyncTail;
575     syncPrototype << makeDecl("CkArrayID", 1) << "::ckNew";
576     asyncPrototype << makeDecl("void", 1) << "::ckNew";
578     head << "{\n"
579          << marshallMsg();
581     syncTail << "  UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
582          << "  return ckCreateArray((CkArrayMessage *)impl_msg, "
583          << epIdx() << ", opts);\n"
584        "}\n";
586     asyncTail  << "  UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
587                << "  CkSendAsyncCreateArray(" << epIdx() << ", _ck_array_creation_cb, opts, impl_msg);\n"
588                << "}\n";
590     str << syncPrototype << "(" << paramComma(0) << "const CkArrayOptions &opts" << eo(0) << ")\n"
591         << head << syncTail;
592     str << asyncPrototype << "(" << paramComma(0) << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb"<< eo(0) << ")\n"
593         << head << asyncTail;
595     XStr dim = ((Array*)container)->dim();
596     XStr sizeParams, sizeArgs;
597     bool emit = true;
599     if (dim == (const char*)"1D") {
600       sizeParams << "const int s1";
601       sizeArgs << "s1";
602     } else if (dim == (const char*)"2D") {
603       sizeParams << "const int s1, const int s2";
604       sizeArgs << "s1, s2";
605     } else if (dim == (const char*)"3D") {
606       sizeParams << "const int s1, const int s2, const int s3";
607       sizeArgs << "s1, s2, s3";
608     }
609 #if 0
610     else if (dim==(const char*)"4D") {
611       sizeParams << "const short s1, const short s2, const short s3, const short s4";
612       sizeArgs << "s1, s2, s3, s4";
613     } else if (dim==(const char*)"5D") {
614       sizeParams << "const short s1, const short s2, const short s3, const short s4, "
615                  << "const short s5";
616       sizeArgs << "s1, s2, s3, s4, s5";
617     } else if (dim==(const char*)"6D") {
618       sizeParams << "const short s1, const short s2, const short s3, const short s4, "
619                  << "const short s5, const short s6";
620       sizeArgs << "s1, s2, s3, s4, s5, s6";
621     }
622 #endif
623     else {
624       emit = false;
625     }
627     if (emit) {
628       str << syncPrototype << "(" << paramComma(0) << sizeParams << eo(0) << ")\n"
629           << head << "  CkArrayOptions opts(" << sizeArgs << ");\n" << syncTail;
630       str << asyncPrototype << "(" << paramComma(0) << sizeParams << ", CkCallback _ck_array_creation_cb" << eo(0) << ")\n"
631           << head << "  CkArrayOptions opts(" << sizeArgs << ");\n" << asyncTail;
632     }
633   }
637 /******************************** Group Entry Points *********************************/
639 void Entry::genGroupDecl(XStr& str)
641   if(isConstructor()) {
642     str << "    " << generateTemplateSpec(tspec) << "\n";
643     genGroupStaticConstructorDecl(str);
644   } else {
645     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
646     str << "    " << generateTemplateSpec(tspec) << "\n";
647     if (isLocal())
648       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<");\n";
649     else
650       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1)<<");\n";
651     // entry method on multiple PEs declaration
652     if(!container->isForElement() && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
653       str << "    " << generateTemplateSpec(tspec) << "\n";
654       str << "    "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(1)<<");\n";
655       str << "    " << generateTemplateSpec(tspec) << "\n";
656       str << "    "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(1)<<");\n";
657     }
658   }
661 void Entry::genGroupDefs(XStr& str)
663   //Selects between NodeGroup and Group
664   char *node = (char *)(container->isNodeGroup()?"Node":"");
666   if(isConstructor()) {
667     genGroupStaticConstructorDefs(str);
668   } else {
669     int forElement=container->isForElement();
670     XStr params; params<<epIdx()<<", impl_msg";
671     XStr paramg; paramg<<epIdx()<<", impl_msg, ckGetGroupID()";
672     XStr parampg; parampg<<epIdx()<<", impl_msg, ckGetGroupPe(), ckGetGroupID()";
673     // append options parameter
674     XStr opts; opts<<",0";
675     if (isImmediate()) opts << "+CK_MSG_IMMEDIATE";
676     if (isInline())  opts << "+CK_MSG_INLINE";
677     if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
679     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
681     XStr retStr; retStr<<retType;
682     XStr msgTypeStr;
683     if (isLocal())
684       msgTypeStr<<paramType(0,1,0);
685     else
686       msgTypeStr<<paramType(0,1);
687     str << makeDecl(retStr,1)<<"::"<<name<<"("<<msgTypeStr<<")\n";
688     str << "{\n  ckCheck();\n";
689     if (!isLocal()) str <<marshallMsg();
691     if (isLocal()) {
692       XStr unmarshallStr; param->unmarshall(unmarshallStr);
693       str << "  "<<container->baseName()<<" *obj = ckLocalBranch();\n";
694       str << "  CkAssert(obj);\n";
695       if (!isNoTrace()) str << "  _TRACE_BEGIN_EXECUTE_DETAILED(0,ForBocMsg,("<<epIdx()<<"),CkMyPe(),0,NULL, NULL);\n";
696       if(isAppWork())
697         str << " _TRACE_BEGIN_APPWORK();\n";
698       str <<
699         "#if CMK_LBDB_ON\n"
700         "  // if there is a running obj being measured, stop it temporarily\n"
701         "  LDObjHandle objHandle;\n"
702         "  int objstopped = 0;\n"
703         "  LBDatabase *the_lbdb = (LBDatabase *)CkLocalBranch(_lbdb);\n"
704         "  if (the_lbdb->RunningObject(&objHandle)) {\n"
705         "    objstopped = 1;\n"
706         "    the_lbdb->ObjectStop(objHandle);\n"
707         "  }\n"
708         "#endif\n";
709       str <<
710         "#if CMK_CHARMDEBUG\n"
711         "  CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
712         "#endif\n  ";
713       if (!retType->isVoid()) str << retType << " retValue = ";
714       str << "obj->"<<name<<"("<<unmarshallStr<<");\n";
715       str << "#if CMK_CHARMDEBUG\n"
716         "  CpdAfterEp("<<epIdx()<<");\n"
717         "#endif\n";
718       str << "#if CMK_LBDB_ON\n"
719         "  if (objstopped) the_lbdb->ObjectStart(objHandle);\n"
720         "#endif\n";
721       if(isAppWork())
722         str << " _TRACE_END_APPWORK();\n";
723       if (!isNoTrace()) str << "  _TRACE_END_EXECUTE();\n";
724       if (!retType->isVoid()) str << "  return retValue;\n";
725     } else if(isSync()) {
726       str << syncPreCall() <<
727         "CkRemote"<<node<<"BranchCall("<<paramg<<", ckGetGroupPe());\n";
728       str << syncPostCall();
729     } else { // Non-sync, non-local entry method
730       if (forElement)
731       {// Send
732         str << "  if (ckIsDelegated()) {\n";
733         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
734         str << "     ckDelegatedTo()->"<<node<<"GroupSend(ckDelegatedPtr(),"<<parampg<<");\n";
735         str << "  } else CkSendMsg"<<node<<"Branch"<<"("<<parampg<<opts<<");\n";
736       }
737       else if (container->isForSection())
738       {// Multicast
739         str << "  if (ckIsDelegated()) {\n";
740         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
741         str << "     ckDelegatedTo()->"<<node<<"GroupSectionSend(ckDelegatedPtr(),"<<params<<", ckGetNumSections(), ckGetSectionIDs());\n";
742         str << "  } else {\n";
743         str << "    void *impl_msg_tmp = (ckGetNumSections()>1) ? CkCopyMsg((void **) &impl_msg) : impl_msg;\n";
744         str << "    for (int i=0; i<ckGetNumSections(); ++i) {\n";
745         str << "       impl_msg_tmp= (i<ckGetNumSections()-1) ? CkCopyMsg((void **) &impl_msg):impl_msg;\n";
746         str << "       CkSendMsg"<<node<<"BranchMulti("<<epIdx()<<", impl_msg_tmp, ckGetGroupIDn(i), ckGetNumElements(i), ckGetElements(i)"<<opts<<");\n";
747         str << "    }\n";
748         str << "  }\n";
749       }
750       else
751       {// Broadcast
752         str << "  if (ckIsDelegated()) {\n";
753         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
754         str << "     ckDelegatedTo()->"<<node<<"GroupBroadcast(ckDelegatedPtr(),"<<paramg<<");\n";
755         str << "  } else CkBroadcastMsg"<<node<<"Branch("<<paramg<<opts<<");\n";
756       }
757     }
758     str << "}\n";
760     // entry method on multiple PEs declaration
761     if(!forElement && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
762       str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(0)<<") {\n";
763       str << marshallMsg();
764       str << "  CkSendMsg"<<node<<"BranchMulti("<<paramg<<", npes, pes"<<opts<<");\n";
765       str << "}\n";
766       str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(0)<<") {\n";
767       str << marshallMsg();
768       str << "  CkSendMsg"<<node<<"BranchGroup("<<paramg<<", grp"<<opts<<");\n";
769       str << "}\n";
770     }
771   }
774 void Entry::genGroupStaticConstructorDecl(XStr& str)
776   if (container->isForElement()) return;
777   if (container->isForSection()) return;
779   str << "    static CkGroupID ckNew("<<paramType(1,1)<<");\n";
780   if (!param->isVoid()) {
781     str << "    "<<container->proxyName(0)<<"("<<paramType(1,1)<<");\n";
782   }
785 void Entry::genGroupStaticConstructorDefs(XStr& str)
787   if (container->isForElement()) return;
788   if (container->isForSection()) return;
790   //Selects between NodeGroup and Group
791   char *node = (char *)(container->isNodeGroup()?"Node":"");
792   str << makeDecl("CkGroupID",1)<<"::ckNew("<<paramType(0,1)<<")\n";
793   str << "{\n"<<marshallMsg();
794   str << "  UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
795   if (param->isMarshalled()) {
796     str << "  if (impl_e_opts)\n";
797     str << "    UsrToEnv(impl_msg)->setGroupDep(impl_e_opts->getGroupDepID());\n";
798   }
799   str << "  return CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg);\n";
800   str << "}\n";
802   if (!param->isVoid()) {
803     str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramType(0,1)<<")\n";
804     str << "{\n"<<marshallMsg();
805     str << "  UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
806     if (param->isMarshalled()) {
807       str << "  if (impl_e_opts)\n";
808       str << "    UsrToEnv(impl_msg)->setGroupDep(impl_e_opts->getGroupDepID());\n";
809     }
810     str << "  ckSetGroupID(CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg));\n";
811     str << "}\n";
812   }
815 /******************* Python Entry Point Code **************************/
816 void Entry::genPythonDecls(XStr& str) {
817   str <<"/* STATIC DECLS: "; print(str); str << " */\n";
818   if (isPython()) {
819     str << "PyObject *_Python_"<<container->baseName()<<"_"<<name<<"(PyObject *self, PyObject *arg);\n";
820   }
823 void Entry::genPythonDefs(XStr& str) {
824   str <<"/* DEFS: "; print(str); str << " */\n";
825   if (isPython()) {
827     str << "PyObject *_Python_"<<container->baseName()<<"_"<<name<<"(PyObject *self, PyObject *arg) {\n";
828     str << "  PyObject *dict = PyModule_GetDict(PyImport_AddModule(\"__main__\"));\n";
829     str << "  int pyNumber = PyInt_AsLong(PyDict_GetItemString(dict,\"__charmNumber__\"));\n";
830     str << "  PythonObject *pythonObj = (PythonObject *)PyLong_AsVoidPtr(PyDict_GetItemString(dict,\"__charmObject__\"));\n";
831     str << "  "<<container->baseName()<<" *object = static_cast<"<<container->baseName()<<" *>(pythonObj);\n";
832     str << "  object->pyWorkers[pyNumber].arg=arg;\n";
833     str << "  object->pyWorkers[pyNumber].result=&CtvAccess(pythonReturnValue);\n";
834     str << "  object->pyWorkers[pyNumber].pythread=PyThreadState_Get();\n";
835     str << "  CtvAccess(pythonReturnValue) = 0;\n";
837     str << "  //pyWorker->thisProxy."<<name<<"(pyNumber);\n";
838     str << "  object->"<<name<<"(pyNumber);\n";
840     str << "  //CthSuspend();\n";
842     str << "  if (CtvAccess(pythonReturnValue)) {\n";
843     str << "    return CtvAccess(pythonReturnValue);\n";
844     str << "  } else {\n";
845     str << "    Py_INCREF(Py_None); return Py_None;\n";
846     str << "  }\n";
847     str << "}\n";
848   }
851 void Entry::genPythonStaticDefs(XStr& str) {
852   if (isPython()) {
853     str << "  {\""<<name<<"\",_Python_"<<container->baseName()<<"_"<<name<<",METH_VARARGS},\n";
854   }
857 void Entry::genPythonStaticDocs(XStr& str) {
858   if (isPython()) {
859     str << "\n  \""<<name<<" -- \"";
860     if (pythonDoc) str <<(char*)pythonDoc;
861     str <<"\"\\\\n\"";
862   }
866 /******************* Accelerator (Accel) Entry Point Code ********************/
868 void Entry::genAccelFullParamList(XStr& str, int makeRefs) {
870   if (!isAccel()) return;
872   ParamList* curParam = NULL;
873   int isFirst = 1;
875   // Parameters (which are read only by default)
876   curParam = param;
877   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
878   while (curParam != NULL) {
880     if (!isFirst) { str << ", "; }
882     Parameter* param = curParam->param;
884     if (param->isArray()) {
885       str << param->getType()->getBaseName() << "* " << param->getName();
886     } else {
887       str << param->getType()->getBaseName() << " " << param->getName();
888     }
890     isFirst = 0;
891     curParam = curParam->next;
892   }
894   // Accel parameters
895   curParam = accelParam;
896   while (curParam != NULL) {
898     if (!isFirst) { str << ", "; }
900     Parameter* param = curParam->param;
901     int bufType = param->getAccelBufferType();
902     int needWrite = makeRefs && ((bufType == Parameter::ACCEL_BUFFER_TYPE_READWRITE) || (bufType == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY));
903     if (param->isArray()) {
904       str << param->getType()->getBaseName() << "* " << param->getName();
905     } else {
906       str << param->getType()->getBaseName() << ((needWrite) ? (" &") : (" ")) << param->getName();
907     }
909     isFirst = 0;
910     curParam = curParam->next;
911   }
913   // Implied object pointer
914   if (!isFirst) { str << ", "; }
915   str << container->baseName() << "* impl_obj";
918 void Entry::genAccelFullCallList(XStr& str) {
919   if (!isAccel()) return;
921   int isFirstFlag = 1;
923   // Marshalled parameters to entry method
924   ParamList* curParam = param;
925   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
926   while (curParam != NULL) {
927     if (!isFirstFlag) str << ", ";
928     isFirstFlag = 0;
929     str << curParam->param->getName();
930     curParam = curParam->next;
931   }
933   // General variables (prefix with "impl_obj->" for member variables of the current object)
934   curParam = accelParam;
935   while (curParam != NULL) {
936     if (!isFirstFlag) str << ", ";
937     isFirstFlag = 0;
938     str << (*(curParam->param->getAccelInstName()));
939     curParam = curParam->next;
940   }
942   // Implied object
943   if (!isFirstFlag) str << ", ";
944   isFirstFlag = 0;
945   str << "impl_obj";
948 void Entry::genAccelIndexWrapperDecl_general(XStr& str) {
949   str << "    static void _accelCall_general_" << epStr() << "(";
950   genAccelFullParamList(str, 1);
951   str << ");\n";
954 void Entry::genAccelIndexWrapperDef_general(XStr& str) {
955   str << makeDecl("void") << "::_accelCall_general_" << epStr() << "(";
956   genAccelFullParamList(str, 1);
957   str << ") {\n\n";
959   //// DMK - DEBUG
960   //str << "  // DMK - DEBUG\n";
961   //str << "  CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
962   //    << makeDecl("void") << "::_accelCall_general_" << epStr()
963   //    << "(...) - Called...\\n\");\n\n";
965   str << (*accelCodeBody);
967   str << "\n\n";
968   str << "  impl_obj->" << (*accelCallbackName) << "();\n";
969   str << "}\n";
972 void Entry::genAccelIndexWrapperDecl_spe(XStr& str) {
974   // Function to issue work request
975   str << "    static void _accelCall_spe_" << epStr() << "(";
976   genAccelFullParamList(str, 0);
977   str << ");\n";
979   // Callback function that is a member of CkIndex_xxx
980   str << "    static void _accelCall_spe_callback_" << epStr() << "(void* userPtr);\n";
983 // DMK - Accel Support
984 #if CMK_CELL != 0
985   #include "spert.h"
986 #endif
988 void Entry::genAccelIndexWrapperDef_spe(XStr& str) {
990   XStr containerType = container->baseName();
992   // Some blank space for readability
993   str << "\n\n";
996   ///// Generate struct that will be passed to callback function /////
998   str << "typedef struct __spe_callback_struct_" << epStr() << " {\n"
999       << "  " << containerType << "* impl_obj;\n"
1000       << "  WRHandle wrHandle;\n"
1001       << "  void* scalar_buf_ptr;\n";
1003   // Pointers for marshalled parameter buffers
1004   ParamList* curParam = param;
1005   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1006   while (curParam != NULL) {
1007     if (curParam->param->isArray()) {
1008       str << "  void* param_buf_ptr_" << curParam->param->getName() << ";\n";
1009     }
1010     curParam = curParam->next;
1011   }
1012   curParam = accelParam;
1013   while (curParam != NULL) {
1014     if (curParam->param->isArray()) {
1015       str << "  void* accelParam_buf_ptr_" << curParam->param->getName() << ";\n";
1016     }
1017     curParam = curParam->next;
1018   }
1020   str << "} SpeCallbackStruct_" << epStr() << ";\n\n";
1023   ///// Generate callback function /////
1025   str << "void _accelCall_spe_callback_" << container->baseName() << "_" << epStr() << "(void* userPtr) {\n"
1026       << "  " << container->indexName() << "::_accelCall_spe_callback_" << epStr() << "(userPtr);\n"
1027       << "}\n";
1029   str << makeDecl("void") << "::_accelCall_spe_callback_" << epStr() << "(void* userPtr) {\n";
1030   str << "  SpeCallbackStruct_" << epStr() << "* cbStruct = (SpeCallbackStruct_" << epStr() << "*)userPtr;\n";
1031   str << "  " << containerType << "* impl_obj = cbStruct->impl_obj;\n";
1033   // Write scalars that are 'out' or 'inout' from the scalar buffer back into memory
1035   if (accel_numScalars > 0) {
1037     // Get the pointer to the scalar buffer
1038     int dmaList_scalarBufIndex = 0;
1039     if (accel_dmaList_scalarNeedsWrite) {
1040       dmaList_scalarBufIndex += accel_dmaList_numReadOnly;
1041     }
1042     str << "  char* __scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n";
1044     // Parameters
1045     curParam = param;
1046     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1047     while (curParam != NULL) {
1048       if (!(curParam->param->isArray())) {
1049         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1050       }
1051       curParam = curParam->next;
1052     }
1054     // Read only accel parameters
1055     curParam = accelParam;
1056     while (curParam != NULL) {
1057       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1058         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1059       }
1060       curParam = curParam->next;
1061     }
1063     // Read write accel parameters
1064     curParam = accelParam;
1065     while (curParam != NULL) {
1066       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1067         str << "  " << (*(curParam->param->getAccelInstName())) << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1068         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1069       }
1070       curParam = curParam->next;
1071     }
1073     // Write only accel parameters
1074     curParam = accelParam;
1075     while (curParam != NULL) {
1076       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1077         str << "  " << (*(curParam->param->getAccelInstName())) << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1078         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1079       }
1080       curParam = curParam->next;
1081     }
1082   }
1084   // Call the callback function
1085   str << "  (cbStruct->impl_obj)->" << (*accelCallbackName) << "();\n";
1087   // Free memory
1088   str << "  if (cbStruct->scalar_buf_ptr != NULL) { free_aligned(cbStruct->scalar_buf_ptr); }\n";
1089   curParam = param;
1090   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1091   while (curParam != NULL) {
1092     if (curParam->param->isArray()) {
1093       str << "  if (cbStruct->param_buf_ptr_" << curParam->param->getName() << " != NULL) { "
1094           <<      "free_aligned(cbStruct->param_buf_ptr_" << curParam->param->getName() << "); "
1095           <<   "}\n";
1096     }
1097     curParam = curParam->next;
1098   }
1099   str << "  delete cbStruct;\n";
1101   str << "}\n\n";
1104   ///// Generate function to issue work request /////
1106   str << makeDecl("void") << "::_accelCall_spe_" << epStr() << "(";
1107   genAccelFullParamList(str, 0);
1108   str << ") {\n\n";
1110   //// DMK - DEBUG
1111   //str << "  // DMK - DEBUG\n"
1112   //    << "  CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
1113   //    << makeDecl("void") << "::_accelCall_spe_" << epStr()
1114   //    << "(...) - Called... (funcIndex:%d)\\n\", accel_spe_func_index__" << epStr() << ");\n\n";
1117   str << "  // Allocate a user structure to be passed to the callback function\n"
1118       << "  SpeCallbackStruct_" << epStr() << "* cbStruct = new SpeCallbackStruct_" << epStr() << ";\n"
1119       << "  cbStruct->impl_obj = impl_obj;\n"
1120       << "  cbStruct->wrHandle = INVALID_WRHandle;  // NOTE: Set actual value later...\n"
1121       << "  cbStruct->scalar_buf_ptr = NULL;\n";
1122   // Set all parameter buffer pointers in the callback structure to NULL
1123   curParam = param;
1124   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1125   while (curParam != NULL) {
1126     if (curParam->param->isArray()) {
1127       str << "  cbStruct->param_buf_ptr_" << curParam->param->getName() << " = NULL;\n";
1128     }
1129     curParam = curParam->next;
1130   }
1131   curParam = accelParam;
1132   while (curParam != NULL) {
1133     if (curParam->param->isArray()) {
1134       str << "  cbStruct->accelParam_buf_ptr_" << curParam->param->getName() << " = NULL;\n";
1135     }
1136     curParam = curParam->next;
1137   }
1138   str << "\n";
1141   // Create the DMA list
1142   int dmaList_curIndex = 0;
1143   int numDMAListEntries = accel_numArrays;
1144   if (accel_numScalars > 0) { numDMAListEntries++; }
1145   if (numDMAListEntries <= 0) {
1146     XLAT_ERROR_NOCOL("accel entry with no parameters",
1147                      first_line_);
1148   }
1150   // DMK - NOTE : TODO : FIXME - For now, force DMA lists to only be the static length or less.
1151   //   Fix this in the future to handle any length supported by hardware.  Also, for now,
1152   //   #if this check since non-Cell architectures do not have SPE_DMA_LIST_LENGTH defined and
1153   //   this code should not be called unless this is a Cell architecture.
1154   #if CMK_CELL != 0
1155   if (numDMAListEntries > SPE_DMA_LIST_LENGTH) {
1156     die("Accel entries do not support parameter lists of length > SPE_DMA_LIST_LENGTH yet... fix me...");
1157   }
1158   #endif
1160   // Do a pass of all the parameters, determine the size of all scalars (to pack them)
1161   if (accel_numScalars > 0) {
1162     str << "  // Create a single buffer to hold all the scalar values\n";
1163     str << "  int scalar_buf_len = 0;\n";
1164     curParam = param;
1165     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1166     while (curParam != NULL) {
1167       if (!(curParam->param->isArray())) {
1168         str << "  scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1169       }
1170       curParam = curParam->next;
1171     }
1172     curParam = accelParam;
1173     while (curParam != NULL) {
1174       if (!(curParam->param->isArray())) {
1175         str << "  scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1176       }
1177       curParam = curParam->next;
1178     }
1179     str << "  scalar_buf_len = ROUNDUP_128(scalar_buf_len);\n"
1180         << "  cbStruct->scalar_buf_ptr = malloc_aligned(scalar_buf_len, 128);\n"
1181         << "  char* scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n\n";
1182   }
1185   // Declare the DMA list
1186   str << "  // Declare and populate the DMA list for the work request\n";
1187   str << "  DMAListEntry dmaList[" << numDMAListEntries << "];\n\n";
1190   // Parameters: read only by default & arrays need to be copied since message will be deleted
1191   curParam = param;
1192   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1193   while (curParam != NULL) {
1195     // Check to see if the scalar buffer needs slipped into the dma list here
1196     if (accel_numScalars > 0) {
1197       if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1198           ((dmaList_curIndex == accel_dmaList_numReadOnly) && (accel_dmaList_scalarNeedsWrite))
1199          ) {
1201         str << "  /*** Scalar Buffer ***/\n"
1202             << "  dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1203             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1204         dmaList_curIndex++;
1205       }
1206     }
1208     // Add this parameter to the dma list (somehow)
1209     str << "  /*** Param: '" << curParam->param->getName() << "' ***/\n";
1210     if (curParam->param->isArray()) {
1211       str << "  {\n"
1212           << "    int bufSize = sizeof(" << curParam->param->getType()->getBaseName() << ") * (" << curParam->param->getArrayLen() << ");\n"
1213           << "    bufSize = ROUNDUP_128(bufSize);\n"
1214           << "    cbStruct->param_buf_ptr_" << curParam->param->getName() << " = malloc_aligned(bufSize, 128);\n"
1215           << "    memcpy(cbStruct->param_buf_ptr_" << curParam->param->getName() << ", " << curParam->param->getName() << ", bufSize);\n"
1216           << "    dmaList[" << dmaList_curIndex << "].size = bufSize;\n"
1217           << "    dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->param_buf_ptr_" << curParam->param->getName() << ");\n"
1218           << "  }\n";
1219       dmaList_curIndex++;
1220     } else {
1221       str << "  *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1222           << curParam->param->getName() << ";\n"
1223           << "  scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1224     }
1225     curParam = curParam->next;
1226     str << "\n";
1227   }
1229   // Read only accel params
1230   curParam = accelParam;
1231   while (curParam != NULL) {
1233     // Check to see if the scalar buffer needs slipped into the dma list here
1234     if (accel_numScalars > 0) {
1235       if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1236           ((dmaList_curIndex == accel_dmaList_numReadOnly) && (accel_dmaList_scalarNeedsWrite))
1237          ) {
1239         str << "  /*** Scalar Buffer ***/\n"
1240             << "  dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1241             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1242         dmaList_curIndex++;
1243       }
1244     }
1246     // Add this parameter
1247     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1248       str << "  /*** Accel Param: '" << curParam->param->getName() << " ("
1249           << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1250       if (curParam->param->isArray()) {
1251         str << "  dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1252             << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1253             << "(" << curParam->param->getArrayLen() << "));\n"
1254             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(" << (*(curParam->param->getAccelInstName())) << ");\n";
1255         dmaList_curIndex++;
1256       } else {
1257         str << "  *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1258             << (*(curParam->param->getAccelInstName())) << ";\n"
1259             << "  scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1260       }
1261       str << "\n";
1262     }
1264     curParam = curParam->next;
1265   }
1267   // Read/write accel params
1268   curParam = accelParam;
1269   while (curParam != NULL) {
1271     // Check to see if the scalar buffer needs slipped into the dma list here
1272     if (accel_numScalars > 0) {
1273       if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1274           ((dmaList_curIndex == accel_dmaList_numReadOnly) && (accel_dmaList_scalarNeedsWrite))
1275          ) {
1277         str << "  /*** Scalar Buffer ***/\n"
1278             << "  dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1279             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1280         dmaList_curIndex++;
1281       }
1282     }
1284     // Add this parameter
1285     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1286       str << "  /*** Accel Param: '" << curParam->param->getName() << " ("
1287           << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1288       if (curParam->param->isArray()) {
1289         str << "  dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1290             << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1291             << "(" << curParam->param->getArrayLen() << "));\n"
1292             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(" << (*(curParam->param->getAccelInstName())) << ");\n";
1293         dmaList_curIndex++;
1294       } else {
1295         str << "  *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1296             << (*(curParam->param->getAccelInstName())) << ";\n"
1297             << "  scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1298       }
1299       str << "\n";
1300     }
1302     curParam = curParam->next;
1303   }
1305   // Write only accel params
1306   curParam = accelParam;
1307   while (curParam != NULL) {
1309     // Add this parameter
1310     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1311       str << "  /*** Accel Param: '" << curParam->param->getName() << " ("
1312           << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1313       if (curParam->param->isArray()) {
1314         str << "  dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1315             << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1316             << "(" << curParam->param->getArrayLen() << "));\n"
1317             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(" << (*(curParam->param->getAccelInstName())) << ");\n";
1318         dmaList_curIndex++;
1319       } else {
1320         str << "  *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1321             << (*(curParam->param->getAccelInstName())) << ";\n"
1322             << "  scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1323       }
1324       str << "\n";
1325     }
1327     curParam = curParam->next;
1328   }
1330   str << "  // Issue the work request\n";
1331   str << "  cbStruct->wrHandle = sendWorkRequest_list(accel_spe_func_index__" << epStr() << ",\n"
1332       << "                                            0,\n"
1333       << "                                            dmaList,\n"
1334       << "                                            " << accel_dmaList_numReadOnly << ",\n"
1335       << "                                            " << accel_dmaList_numReadWrite << ",\n"
1336       << "                                            " << accel_dmaList_numWriteOnly << ",\n"
1337       << "                                            cbStruct,\n"
1338       << "                                            WORK_REQUEST_FLAGS_NONE,\n"
1339       << "                                            _accelCall_spe_callback_" << container->baseName() << "_" << epStr() << "\n"
1340       << "                                           );\n";
1342   str << "}\n\n";
1345   // Some blank space for readability
1346   str << "\n";
1349 int Entry::genAccels_spe_c_funcBodies(XStr& str) {
1351   // Make sure this is an accelerated entry method (just return if not)
1352   if (!isAccel()) { return 0; }
1354   // Declare the spe function
1355   str << "void __speFunc__" << indexName() << "__" << epStr() << "(DMAListEntry* dmaList) {\n";
1357   ParamList* curParam = NULL;
1358   int dmaList_curIndex = 0;
1360   // Identify the scalar buffer if there is one
1361   if (accel_numScalars > 0) {
1362     if (accel_dmaList_scalarNeedsWrite) {
1363       str << "  void* __scalar_buf_ptr = (void*)(dmaList[" << accel_dmaList_numReadOnly << "].ea);\n";
1364     } else {
1365       str << "  void* __scalar_buf_ptr = (void*)(dmaList[0].ea);\n";
1366       dmaList_curIndex++;
1367     }
1368     str << "  char* __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1369   }
1371   // Pull out all the parameters
1372   curParam = param;
1373   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1374   while (curParam != NULL) {
1375     if (curParam->param->isArray()) {
1376       str << "  " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1377       dmaList_curIndex++;
1378     } else {
1379       str << "  " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1380       str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1381     }
1382     curParam = curParam->next;
1383   }
1385   // Read only accel params
1386   curParam = accelParam;
1387   while (curParam != NULL) {
1388     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1389       if (curParam->param->isArray()) {
1390         str << "  " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1391         dmaList_curIndex++;
1392       } else {
1393         str << "  " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1394         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1395       }
1396     }
1397     curParam = curParam->next;
1398   }
1400   // Reset the dmaList_curIndex to the read-write portion of the dmaList
1401   dmaList_curIndex = accel_dmaList_numReadOnly;
1402   if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1403     dmaList_curIndex++;
1404   }
1406   // Read-write accel params
1407   curParam = accelParam;
1408   while (curParam != NULL) {
1409     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1410       if (curParam->param->isArray()) {
1411         str << "  " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1412         dmaList_curIndex++;
1413       } else {
1414         str << "  " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1415         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1416       }
1417     }
1418     curParam = curParam->next;
1419   }
1421   // Write only accel params
1422   curParam = accelParam;
1423   while (curParam != NULL) {
1424     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1425       if (curParam->param->isArray()) {
1426         str << "  " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1427         dmaList_curIndex++;
1428       } else {
1429         str << "  " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1430         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1431       }
1432     }
1433     curParam = curParam->next;
1434   }
1437   // Function body from the interface file
1438   str << "  {\n    " << (*accelCodeBody) << "\n  }\n";
1441   // Write the scalar values that are not read only back into the scalar buffer
1442   if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1444     str << "  __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1446     // Parameters
1447     curParam = param;
1448     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1449     while (curParam != NULL) {
1450       if (!(curParam->param->isArray())) {
1451         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1452       }
1453       curParam = curParam->next;
1454     }
1456     // Read only accel parameters
1457     curParam = accelParam;
1458     while (curParam != NULL) {
1459       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1460         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1461       }
1462       curParam = curParam->next;
1463     }
1465     // Read only accel parameters
1466     curParam = accelParam;
1467     while (curParam != NULL) {
1468       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1469         str << "  *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1470         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1471       }
1472       curParam = curParam->next;
1473     }
1475     // Read only accel parameters
1476     curParam = accelParam;
1477     while (curParam != NULL) {
1478       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1479         str << "  *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1480         str << "  __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1481       }
1482       curParam = curParam->next;
1483     }
1485   }
1487   str << "}\n\n\n";
1489   return 1;
1492 void Entry::genAccels_spe_c_regFuncs(XStr& str) {
1493   if (isAccel()) {
1494     str << "  funcLookupTable[curIndex  ].funcIndex = curIndex;\n"
1495         << "  funcLookupTable[curIndex++].funcPtr = __speFunc__" << indexName() << "__" << epStr() << ";\n";
1496   }
1499 void Entry::genAccels_ppe_c_regFuncs(XStr& str) {
1500   if (isAccel()) {
1501     str << "  " << indexName() << "::accel_spe_func_index__" << epStr() << " = curIndex++;\n";
1502   }
1506 /******************* Shared Entry Point Code **************************/
1507 void Entry::genIndexDecls(XStr& str)
1509   str << "    /* DECLS: "; print(str); str << "     */";
1511   XStr templateSpecLine;
1512   templateSpecLine << "\n    " << generateTemplateSpec(tspec);
1514   // Entry point index storage
1515   str << "\n    // Entry point registration at startup"
1516       << templateSpecLine
1517       << "\n    static int reg_" << epStr() << "();" ///< @note: Should this be generated as private?
1518       << "\n    // Entry point index lookup"
1519       << templateSpecLine
1520       << "\n    inline static int idx_" << epStr() << "() {"
1521       << "\n      static int epidx = " << epRegFn(0) << ";"
1522       << "\n      return epidx;"
1523       << "\n    }\n";
1525   if (!isConstructor()) {
1526     str << templateSpecLine
1527         << "\n    inline static int idx_" << name << "("
1528         << retType
1529         << " (" << container->baseName() << "::*)(";
1530     if (param)
1531       param->print(str);
1532     str << ") ) {"
1533         << "\n      return " << epIdx(0) << ";"
1534         << "\n    }\n\n";
1535   }
1537   // DMK - Accel Support - Also declare the function index for the Offload API call
1538   #if CMK_CELL != 0
1539     if (isAccel()) {
1540       str << "    static int accel_spe_func_index__" << epStr() << ";\n";
1541     }
1542   #endif
1544   // Index function, so user can find the entry point number
1545   str << templateSpecLine
1546       << "\n    static int ";
1547   if (isConstructor()) str <<"ckNew";
1548   else str <<name;
1549   str << "("<<paramType(1,0)<<") { return "<<epIdx(0)<<"; }";
1551   // DMK - Accel Support
1552   if (isAccel()) {
1553     genAccelIndexWrapperDecl_general(str);
1554     #if CMK_CELL != 0
1555       genAccelIndexWrapperDecl_spe(str);
1556     #endif
1557   }
1559   if (isReductionTarget()) {
1560       str << "\n    // Entry point registration at startup"
1561           << templateSpecLine
1562           << "\n    static int reg_"<< epStr(true) <<"();" ///< @note: Should this be generated as private?
1563           << "\n    // Entry point index lookup"
1564           << templateSpecLine
1565           << "\n    inline static int idx_" << epStr(true) << "() {"
1566           << "\n      static int epidx = "<< epRegFn(0, true) <<";"
1567           << "\n      return epidx;"
1568           << "\n    }"
1569           << templateSpecLine
1570           << "\n    static int " << "redn_wrapper_" << name
1571           << "(CkReductionMsg* impl_msg) { return " << epIdx(0, true) << "; }"
1572           << templateSpecLine
1573           << "\n    static void _call_" << epStr(true) << "(void* impl_msg, void* impl_obj_void);";
1574   }
1576   // call function declaration
1577   str << templateSpecLine
1578       << "\n    static void _call_" << epStr() << "(void* impl_msg, void* impl_obj);";
1579   str << templateSpecLine
1580       << "\n    static void _call_sdag_" << epStr() << "(void* impl_msg, void* impl_obj);";
1581   if(isThreaded()) {
1582     str  << templateSpecLine
1583          << "\n    static void _callthr_"<<epStr()<<"(CkThrCallArg *);";
1584   }
1585   if (hasCallMarshall) {
1586     str << templateSpecLine
1587         << "\n    static int _callmarshall_" << epStr()
1588         << "(char* impl_buf, void* impl_obj_void);";
1589   }
1590   if (param->isMarshalled()) {
1591     str << templateSpecLine
1592         << "\n    static void _marshallmessagepup_"<<epStr()<<"(PUP::er &p,void *msg);";
1593   }
1594   str << "\n";
1597 void Entry::genDecls(XStr& str)
1599   if (external)
1600     return;
1602   str << "/* DECLS: "; print(str); str << " */\n";
1604   if (isMigrationConstructor())
1605     {} //User cannot call the migration constructor
1606   else if(container->isGroup()) {
1607     genGroupDecl(str);
1608   } else if(container->isArray()) {
1609     if(!isIget())
1610       genArrayDecl(str);
1611     else if(container->isForElement())
1612       genArrayDecl(str);
1613   } else { // chare or mainchare
1614     genChareDecl(str);
1615   }
1618 void Entry::genClosureEntryDecls(XStr& str) {
1619   genClosure(str, false);
1622 void Entry::genClosureEntryDefs(XStr& str) {
1623   templateGuardBegin(tspec || container->isTemplated(), str);
1624   genClosure(str, true);
1625   templateGuardEnd(str);
1628 void Entry::genClosure(XStr& decls, bool isDef) {
1629   if (isConstructor() || (isLocal() && !sdagCon)) return;
1631   bool hasArray = false, isMessage = false;
1632   XStr messageType;
1633   int i = 0;
1634   XStr structure, toPup, alloc, getter, dealloc;
1635   for(ParamList* pl = param; pl != NULL; pl = pl->next, i++) {
1636     Parameter* sv = pl->param;
1638     if (XStr(sv->type->getBaseName()) == "CkArrayOptions") continue;
1640     structure << "      ";
1641     getter << "      ";
1643     if ((sv->isMessage() != 1) && (sv->isVoid() != 1)) {
1644        structure << sv->type << " ";
1645        getter << sv->type << " ";
1646        if (sv->isArray() != 0) {
1647          structure << "*";
1648          getter << "*";
1649        }
1651        if (sv->isArray() != 0) {
1652          hasArray = hasArray || true;
1653        } else {
1654          toPup << "        " << "__p | " << sv->name << ";\n";
1655          sv->podType = true;
1656        }
1658        if (sv->name != 0) {
1659          structure << sv->name << ";\n";
1660          getter << "& " << "getP" << i << "() { return " << sv->name << ";}\n";
1661        }
1663     }
1664     else if (sv->isVoid() != 1){
1665       if (sv->isMessage()) {
1666         isMessage = true;
1667         structure << sv->type << " " << sv->name << ";\n";
1668         toPup << "        " << "CkPupMessage(__p, (void**)&" << sv->name << ");\n";
1669         messageType << sv->type->deref();
1670       }
1671     }
1672   }
1674   structure << "\n";
1676   toPup << "        packClosure(__p);\n";
1678   XStr initCode;
1679   initCode << "        init();\n";
1681   if (hasArray) {
1682     structure << "      " << "CkMarshallMsg* _impl_marshall;\n";
1683     structure << "      " << "char* _impl_buf_in;\n";
1684     structure << "      " << "int _impl_buf_size;\n";
1685     dealloc << "        if (_impl_marshall) CmiFree(UsrToEnv(_impl_marshall));\n";
1687     initCode << "        _impl_marshall = 0;\n";
1688     initCode << "        _impl_buf_in = 0;\n";
1689     initCode << "        _impl_buf_size = 0;\n";
1691     toPup << "        __p | _impl_buf_size;\n";
1692     toPup << "        bool hasMsg = (_impl_marshall != 0); __p | hasMsg;\n";
1693     toPup << "        " << "if (hasMsg) CkPupMessage(__p, (void**)&" << "_impl_marshall" << ");\n";
1694     toPup << "        " << "else PUParray(__p, _impl_buf_in, _impl_buf_size);\n";
1695     toPup << "        if (__p.isUnpacking()) {\n";
1696     toPup << "          char *impl_buf = _impl_marshall ? _impl_marshall->msgBuf : _impl_buf_in;\n";
1697     param->beginUnmarshallSDAG(toPup);
1698     toPup << "        }\n";
1699   }
1701   // Generate code for ensuring we don't migrate active local closures
1702   if (isLocal()) {
1703     toPup.clear();
1704     toPup << "        CkAbort(\"Can\'t migrate while a local SDAG method is active.\");\n";
1705   }
1707   if (!isMessage) {
1708     genClosureTypeName = new XStr();
1709     genClosureTypeNameProxy = new XStr();
1710     *genClosureTypeNameProxy << "Closure_" << container->baseName() << "::";
1711     *genClosureTypeNameProxy << name << "_" << entryCount << "_closure";
1712     *genClosureTypeName << name << "_" << entryCount << "_closure";
1714     container->sdagPUPReg << "  PUPable_reg(SINGLE_ARG(" << *genClosureTypeNameProxy << "));\n";
1716     if (isDef) {
1717       if (container->isTemplated()) {
1718         decls << container->tspec(false) << "\n";
1719       }
1720       decls << generateTemplateSpec(tspec) << "\n";
1721       decls << "    struct " << *genClosureTypeNameProxy <<" : public SDAG::Closure" << " {\n";
1722       decls << structure << "\n";
1723       decls << "      " << *genClosureTypeName << "() {\n";
1724       decls << initCode;
1725       decls << "      }\n";
1726       decls << "      " << *genClosureTypeName << "(CkMigrateMessage*) {\n";
1727       decls << initCode;
1728       decls << "      }\n";
1729       decls << getter;
1730       decls << "      void pup(PUP::er& __p) {\n";
1731       decls << toPup;
1732       decls << "      }\n";
1733       decls << "      virtual ~" << *genClosureTypeName << "() {\n";
1734       decls << dealloc;
1735       decls << "      }\n";
1736       decls << "      " << ((container->isTemplated() || tspec) ? "PUPable_decl_template" : "PUPable_decl") << "(SINGLE_ARG(" << *genClosureTypeName;
1737       if (tspec) {
1738         decls << "<";
1739         tspec->genShort(decls);
1740         decls << ">";
1741       }
1742       decls << "));\n";
1743       decls << "    };\n";
1744     } else {
1745       decls << generateTemplateSpec(tspec) << "\n";
1746       decls << "    struct " <<  *genClosureTypeName << ";\n";
1747     }
1748   } else {
1749     genClosureTypeName = new XStr();
1750     genClosureTypeNameProxy = new XStr();
1751     *genClosureTypeNameProxy << messageType;
1752     *genClosureTypeName << messageType;
1753   }
1755   genClosureTypeNameProxyTemp = new XStr();
1756   *genClosureTypeNameProxyTemp << (container->isTemplated() ? "typename " : "") << genClosureTypeNameProxy;
1759 //This routine is only used in Entry::genDefs.
1760 // It ends the current procedure with a call to awaken another thread,
1761 // and defines the thread function to handle that call.
1762 XStr Entry::callThread(const XStr &procName,int prependEntryName)
1764   XStr str,procFull;
1765   procFull<<"_callthr_";
1766   if(prependEntryName) procFull<<name<<"_";
1767   procFull<<procName;
1769   str << "  CthThread tid = CthCreate((CthVoidFn)"<<procFull
1770    <<", new CkThrCallArg(impl_msg,impl_obj), "<<getStackSize()<<");\n";
1771   str << "  ((Chare *)impl_obj)->CkAddThreadListeners(tid,impl_msg);\n";
1772   // str << "  CkpvAccess(_traces)->CkAddThreadListeners(tid);\n";
1773 #if CMK_BIGSIM_CHARM
1774   str << "  BgAttach(tid);\n";
1775 #endif
1776   str << "  CthResume(tid);\n";
1777   str << "}\n";
1779   str << makeDecl("void")<<"::"<<procFull<<"(CkThrCallArg *impl_arg)\n";
1780   str << "{\n";\
1781   str << "  void *impl_msg = impl_arg->msg;\n";
1782   str << "  "<<container->baseName()<<" *impl_obj = ("<<container->baseName()<<" *) impl_arg->obj;\n";
1783   str << "  delete impl_arg;\n";
1784   return str;
1788   Generate the code to actually unmarshall the parameters and call
1789   the entry method.
1791 void Entry::genCall(XStr& str, const XStr &preCall, bool redn_wrapper, bool usesImplBuf)
1793   bool isArgcArgv=false;
1794   bool isMigMain=false;
1795   bool isSDAGGen = sdagCon || isWhenEntry;
1797   if (isConstructor() && container->isMainChare() &&
1798       (!param->isVoid()) && (!param->isCkArgMsgPtr())){
1799         if(param->isCkMigMsgPtr()) isMigMain = true;
1800         else isArgcArgv = true;
1801   } else {
1802     //Normal case: Unmarshall variables
1803     if (redn_wrapper) param->beginRednWrapperUnmarshall(str, isSDAGGen);
1804     else {
1805       if (isSDAGGen)
1806         param->beginUnmarshallSDAGCall(str, usesImplBuf);
1807       else
1808         param->beginUnmarshall(str);
1810       if (param->isVoid() && !isNoKeep())
1811         str<<"  CkFreeSysMsg(impl_msg);\n";
1812     }
1813   }
1815   str << preCall;
1816   if (!isConstructor() && fortranMode) {
1817     if (!container->isArray()) { // Currently, only arrays are supported
1818       cerr << (char *)container->baseName() << ": only chare arrays are currently supported\n";
1819       exit(1);
1820     }
1821     str << "/* FORTRAN */\n";
1822     XStr dim; dim << ((Array*)container)->dim();
1823     if (dim==(const char*)"1D")
1824       str << "  int index1 = impl_obj->thisIndex;\n";
1825     else if (dim==(const char*)"2D") {
1826       str << "  int index1 = impl_obj->thisIndex.x;\n";
1827       str << "  int index2 = impl_obj->thisIndex.y;\n";
1828     }
1829     else if (dim==(const char*)"3D") {
1830       str << "  int index1 = impl_obj->thisIndex.x;\n";
1831       str << "  int index2 = impl_obj->thisIndex.y;\n";
1832       str << "  int index3 = impl_obj->thisIndex.z;\n";
1833     }
1834     str << "  ::" << fortranify(name)
1835         << "((char **)(impl_obj->user_data), &index1";
1836     if (dim==(const char*)"2D" || dim==(const char*)"3D")
1837         str << ", &index2";
1838     if (dim==(const char*)"3D")
1839         str << ", &index3";
1840     if (!param->isVoid()) { str << ", "; param->unmarshallAddress(str); }
1841     str<<");\n";
1842     str << "/* FORTRAN END */\n";
1843   }
1845   // DMK : Accel Support
1846   else if (isAccel()) {
1848     #if CMK_CELL != 0
1849       str << "  if (1) {   // DMK : TODO : For now, hardcode the condition (i.e. for now, do not dynamically load-balance between host and accelerator)\n";
1850       str << "    _accelCall_spe_" << epStr() << "(";
1851       genAccelFullCallList(str);
1852       str << ");\n";
1853       str << "  } else {\n  ";
1854     #endif
1856     str << "  _accelCall_general_" << epStr() << "(";
1857     genAccelFullCallList(str);
1858     str << ");\n";
1860     #if CMK_CELL != 0
1861       str << "  }\n";
1862     #endif
1864   }
1866   else { //Normal case: call regular method
1867     if (isArgcArgv) str<<"  CkArgMsg *m=(CkArgMsg *)impl_msg;\n"; //Hack!
1869     if(isConstructor()) {//Constructor: call "new (obj) foo(parameters)"
1870         str << "  new (impl_obj) "<<container->baseName();
1871     } else {//Regular entry method: call "obj->bar(parameters)"
1872       str << "  impl_obj->" << (tspec ? "template " : "") << name;
1873       if (tspec) {
1874         str << "< ";
1875         tspec->genShort(str);
1876         str << " >";
1877       }
1878     }
1880     if (isArgcArgv) { //Extract parameters from CkArgMsg (should be parameter marshalled)
1881         str<<"(m->argc,m->argv);\n";
1882         str<<"  delete m;\n";
1883     }else if(isMigMain){
1884         str<<"((CkMigrateMessage*)impl_msg);\n";
1885     }
1886     else {//Normal case: unmarshall parameters (or just pass message)
1887       if (isSDAGGen) {
1888         str << "(";
1889         if (param->isMessage()) {
1890           param->unmarshall(str);
1891           //} else if (param->isVoid()) {
1892           // no parameter
1893         } else if (!param->isVoid()) {
1894           str << "genClosure";
1895         }
1896         str << ");\n";
1897         if (!param->isMessage() && !param->isVoid())
1898           str << "  genClosure->deref();\n";
1899       } else {
1900         str<<"("; param->unmarshall(str); str<<");\n";
1901       }
1902     }
1903   }
1906 void Entry::genDefs(XStr& str)
1908   if (external)
1909     return;
1910   XStr containerType=container->baseName();
1911   XStr preMarshall,preCall,postCall;
1913   templateGuardBegin(tspec || container->isTemplated(), str);
1914   str << "/* DEFS: "; print(str); str << " */\n";
1916   if(isMigrationConstructor())
1917     {} //User cannot call the migration constructor
1918   else if(container->isGroup()){
1919     genGroupDefs(str);
1920   } else if(container->isArray()) {
1921     genArrayDefs(str);
1922   } else
1923     genChareDefs(str);
1925   if (container->isMainChare() || container->isChare() || container->isForElement()) {
1926       if (isReductionTarget()) {
1927           XStr retStr; retStr<<retType;
1928           str << makeDecl(retStr);
1929           //str << retType << " " << indexName(); //makeDecl(retStr, 1)
1930           str << "::_call_" << epStr(true) << "(void* impl_msg, void* impl_obj_void)"
1931               << "\n{"
1932               << "\n  " << container->baseName() << "* impl_obj = static_cast<"
1933               << container->baseName() << "*> (impl_obj_void);\n"
1934               << "  char* impl_buf = (char*)((CkReductionMsg*)impl_msg)->getData();\n";
1935           XStr precall;
1936           genCall(str, precall, true, false);
1937           if (!(sdagCon || isWhenEntry))
1938             str << "  delete (CkReductionMsg*)impl_msg;\n}\n\n";
1939           else
1940             str << "  \n}\n\n";
1941       }
1942   }
1945   //Prevents repeated call and __idx definitions:
1946   if (container->getForWhom()!=forAll) {
1947     templateGuardEnd(str);
1948     return;
1949   }
1951   // Define the entry point registration functions
1952   str << "\n// Entry point registration function"
1953       << "\n" << makeDecl("int") << "::reg_" << epStr() << "() {"
1954       << "\n  int epidx = " << genRegEp() << ";";
1955   if (hasCallMarshall)
1956     str << "\n  CkRegisterMarshallUnpackFn(epidx, "
1957         << "_callmarshall_" << epStr(false, true) << ");";
1958   if (param->isMarshalled()) {
1959     str << "\n  CkRegisterMessagePupFn(epidx, "
1960         << "_marshallmessagepup_" << epStr(false, true) << ");\n";
1961   }
1962   else if (param->isMessage() && !isMigrationConstructor()) {
1963     str << "\n  CkRegisterMessagePupFn(epidx, (CkMessagePupFn)";
1964     param->param->getType()->deref()->print(str);
1965     str << "::ckDebugPup);";
1966   }
1967   str << "\n  return epidx;"
1968       << "\n}\n\n";
1970   if (isReductionTarget())
1971   {
1972     str << "\n// Redn wrapper registration function"
1973         << "\n" << makeDecl("int") << "::reg_"<< epStr(true) <<"() {"
1974         << "\n  return " << genRegEp(true) << ";"
1975         << "\n}\n\n";
1976   }
1978   // DMK - Accel Support
1979   #if CMK_CELL != 0
1980     if (isAccel()) {
1981       str << "int " << indexName() << "::" << "accel_spe_func_index__" << epStr() << "=0;\n";
1982     }
1983   #endif
1985   // Add special pre- and post- call code
1986   if(isSync() || isIget()) {
1987   //A synchronous method can return a value, and must finish before
1988   // the caller can proceed.
1989     preMarshall<< "  int impl_ref = CkGetRefNum(impl_msg), impl_src = CkGetSrcPe(impl_msg);\n";
1990     if(retType->isVoid() || retType->isMessage())
1991       preCall<< "  void *impl_retMsg=";
1992     if(retType->isVoid()) {
1993       preCall << "CkAllocSysMsg();\n  ";
1994     } else if(retType->isMessage()){
1995       preCall << "(void *) ";
1996     } else{
1997       preCall<< "  "<<retType<<" impl_ret_val= ";  
1998       postCall<<"  //Marshall: impl_ret_val\n";
1999       postCall<<"  int impl_ret_size=0;\n";
2000       postCall<<"  { //Find the size of the PUP'd data\n";
2001       postCall<<"    PUP::sizer implPS;\n";
2002       postCall<<"    implPS|impl_ret_val;\n";
2003       postCall<<"    impl_ret_size+=implPS.size();\n";
2004       postCall<<"  };\n";
2005       postCall<<"  CkMarshallMsg *impl_retMsg=CkAllocateMarshallMsg(impl_ret_size, NULL);\n";
2006       postCall<<"  { //Copy over the PUP'd data;\n";
2007       postCall<<"    PUP::toMem implPS((void *)impl_retMsg->msgBuf);\n";
2008       postCall<<"    implPS|impl_ret_val;\n";
2009       postCall<<"  };\n";
2010     }
2011     postCall << "  CkSendToFutureID(impl_ref, impl_retMsg, impl_src);\n";
2012   } else if(isExclusive()) {
2013   //An exclusive method
2014     preMarshall << "  if(CmiTryLock(impl_obj->__nodelock)) {\n"; /*Resend msg. if lock busy*/
2015     /******* DANGER-- RESEND CODE UNTESTED **********/
2016     if (param->isMarshalled()) {
2017       preMarshall << "    impl_msg = CkCopyMsg(&impl_msg);\n";
2018     }
2019     preMarshall << "    CkSendMsgNodeBranch("<<epIdx()<<",impl_msg,CkMyNode(),impl_obj->CkGetNodeGroupID());\n";
2020     preMarshall << "    return;\n";
2021     preMarshall << "  }\n";
2023     postCall << "  CmiUnlock(impl_obj->__nodelock);\n";
2024   }
2026   if (!isConstructor() && fortranMode) { // Fortran90
2027       str << "/* FORTRAN SECTION */\n";
2029       XStr dim; dim << ((Array*)container)->dim();
2030       // Declare the Fortran Entry Function
2031       // This is called from C++
2032       str << "extern \"C\" void " << fortranify(name) << "(char **, " << container->indexList();
2033       if (!param->isVoid()) { str << ", "; param->printAddress(str); }
2034       str << ");\n";
2036       // Define the Fortran interface function
2037       // This is called from Fortran to send the message to a chare.
2038       str << "extern \"C\" void "
2039         //<< container->proxyName() << "_"
2040           << fortranify("SendTo_", container->baseName(), "_", name)
2041           << "(long* aindex, " << container->indexList();
2042       if (!param->isVoid()) { str << ", "; param->printAddress(str); }
2043       str << ")\n";
2044       str << "{\n";
2045       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
2046       str << "\n";
2047       str << "  " << container->proxyName() << " h(*aid);\n";
2048       str << "  if (*index1 == -1) \n";
2049       str << "    h." << name << "(";
2050       if (!param->isVoid()) param->printValue(str);
2051       str << ");\n";
2052       str << "  else\n";
2053       if (dim==(const char*)"1D")
2054         str << "    h[*index1]." << name << "(";
2055       else if (dim==(const char*)"2D")
2056         str << "    h[CkArrayIndex2D(*index1, *index2)]." << name << "(";
2057       else if (dim==(const char*)"3D")
2058         str << "    h[CkArrayIndex3D(*index1, *index2, *index3)]." << name << "(";
2059       if (!param->isVoid()) param->printValue(str);
2060       str << ");\n";
2061       str << "}\n";
2062       str << "/* FORTRAN SECTION END */\n";
2063     }
2065   // DMK - Accel Support
2066   //   Create the wrapper function for the acceleration call
2067   //   TODO : FIXME : For now, just use the standard C++ code... create OffloadAPI wrappers later
2068   if (isAccel()) {
2069     genAccelIndexWrapperDef_general(str);
2070     #if CMK_CELL != 0
2071       genAccelIndexWrapperDef_spe(str);
2072     #endif
2073   }
2075   //Generate the call-method body
2076   str << makeDecl("void")<<"::_call_"<<epStr()<<"(void* impl_msg, void* impl_obj_void)\n";
2077   str << "{\n"
2078       << "  " << container->baseName() << "* impl_obj = static_cast<"
2079       << container->baseName() << " *>(impl_obj_void);\n";
2080   if (!isLocal()) {
2081     if(isThreaded()) str << callThread(epStr());
2082     str << preMarshall;
2083     if (param->isMarshalled()) {
2084       if (param->hasConditional()) str << "  MarshallMsg_"<<epStr()<<" *impl_msg_typed=(MarshallMsg_"<<epStr()<<" *)impl_msg;\n";
2085       else str << "  CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2086       str << "  char *impl_buf=impl_msg_typed->msgBuf;\n";
2087     }
2088     genCall(str, preCall, false, false);
2089     param->endUnmarshall(str);
2090     str << postCall;
2091     if(isThreaded() && param->isMarshalled()) str << "  delete impl_msg_typed;\n";
2092   } else {
2093     str << "  CkAbort(\"This method should never be called as it refers to a LOCAL entry method!\");\n";
2094   }
2095   str << "}\n";
2097   if (hasCallMarshall) {
2098     str << makeDecl("int") << "::_callmarshall_" << epStr()
2099         <<"(char* impl_buf, void* impl_obj_void) {\n";
2100     str << "  " << containerType << "* impl_obj = static_cast< " << containerType << " *>(impl_obj_void);\n";
2101     if (!isLocal()) {
2102       if (!param->hasConditional()) {
2103         genCall(str, preCall, false, true);
2104         /*FIXME: implP.size() is wrong if the parameter list contains arrays--
2105         need to add in the size of the arrays.
2106          */
2107         str << "  return implP.size();\n";
2108       } else {
2109         str << "  CkAbort(\"This method is not implemented for EPs using conditional packing\");\n";
2110         str << "  return 0;\n";
2111       }
2112     } else {
2113       str << "  CkAbort(\"This method should never be called as it refers to a LOCAL entry method!\");\n";
2114       str << "  return 0;\n";
2115     }
2116     str << "}\n";
2117   }
2118   if (param->isMarshalled()) {
2119      str << makeDecl("void")<<"::_marshallmessagepup_"<<epStr()<<"(PUP::er &implDestP,void *impl_msg) {\n";
2120      if (!isLocal()) {
2121        if (param->hasConditional()) str << "  MarshallMsg_"<<epStr()<<" *impl_msg_typed=(MarshallMsg_"<<epStr()<<" *)impl_msg;\n";
2122        else str << "  CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2123        str << "  char *impl_buf=impl_msg_typed->msgBuf;\n";
2124        param->beginUnmarshall(str);
2125        param->pupAllValues(str);
2126      } else {
2127        str << "  /*Fake pupping since we don't really have a message */\n";
2128        str << "  int n=0;\n";
2129        str << "  if (implDestP.hasComments()) implDestP.comment(\"LOCAL message\");\n";
2130        str << "  implDestP|n;\n";
2131      }
2132      str << "}\n";
2133   }
2135   // to match the registry, generate register call even if there is no SDAG code
2136   //if ((param->isMarshalled() || param->isVoid()) /* && (sdagCon || isWhenEntry) */)
2137   if ((param->isMarshalled() || param->isVoid()) && genClosureTypeNameProxy) {
2138     if (container->isTemplated())
2139       str << container->tspec(false);
2140     if (tspec) {
2141       str << "template <";
2142       tspec->genLong(str, false);
2143       str << "> ";
2144     }
2146     str << ((container->isTemplated() || tspec) ? "PUPable_def_template_nonInst" : "PUPable_def") << "(SINGLE_ARG(" << *genClosureTypeNameProxy;
2147     if (tspec) {
2148       str << "<";
2149       tspec->genShort(str);
2150       str << ">";
2151     }
2152     str << "))\n";
2153   }
2155   templateGuardEnd(str);
2158 XStr Entry::genRegEp(bool isForRedn)
2160   XStr str;
2161   str << "CkRegisterEp(\"";
2162   if (isForRedn)
2163       str << "redn_wrapper_" << name << "(CkReductionMsg *impl_msg)\",\n";
2164   else
2165       str << name << "("<<paramType(0)<<")\",\n";
2166   str << "      _call_" << epStr(isForRedn, true);
2167   str << ", ";
2168   /* messageIdx: */
2169   if (param->isMarshalled()) {
2170     if (param->hasConditional())  str<<"MarshallMsg_"<<epStr()<<"::__idx";
2171     else str<<"CkMarshallMsg::__idx";
2172   } else if(!param->isVoid() && !isMigrationConstructor()) {
2173     param->genMsgProxyName(str);
2174     str <<"::__idx";
2175   } else if (isForRedn) {
2176     str << "CMessage_CkReductionMsg::__idx";
2177   } else {
2178     str << "0";
2179   }
2180   /* chareIdx */
2181   str << ", __idx";
2182   /* attributes */
2183   str << ", 0";
2184   // reductiontarget variants should not be nokeep. The actual ep will be
2185   // parameter marshalled (and hence flagged as nokeep), but we'll delete the
2186   // CkReductionMsg in generated code, not runtime code. (so that we can cast
2187   // it to CkReductionMsg not CkMarshallMsg)
2188   if ( !isForRedn && (attribs & SNOKEEP) ) str << "+CK_EP_NOKEEP";
2189   if (attribs & SNOTRACE) str << "+CK_EP_TRACEDISABLE";
2190   if (attribs & SIMMEDIATE) str << "+CK_EP_TRACEDISABLE";
2191   if (attribs & SAPPWORK) str << "+CK_EP_APPWORK";
2193   /*MEICHAO*/
2194   if (attribs & SMEM) str << "+CK_EP_MEMCRITICAL";
2195   
2196   if (internalMode) str << "+CK_EP_INTRINSIC";
2197   str << ")";
2198   return str;
2201 void Entry::genReg(XStr& str)
2203   if (tspec)
2204     return;
2206   if (external) {
2207     str << "  CkIndex_" << label << "::idx_" << name;
2208     if (targs)
2209         str << "< " << targs << " >";
2210     str << "( static_cast< "
2211         << retType << " (" << label << "::*)(" << paramType(0,0) << ") >(NULL) );\n";
2212     return;
2213   }
2215   str << "  // REG: "<<*this;
2216   str << "  " << epIdx(0) << ";\n";
2217   if (isReductionTarget())
2218     str << "  " << epIdx(0, true) << ";\n";
2219   if (isConstructor()) {
2220     if(container->isMainChare() && !isMigrationConstructor())
2221       str << "  CkRegisterMainChare(__idx, "<<epIdx(0)<<");\n";
2222     if(param->isVoid())
2223       str << "  CkRegisterDefaultCtor(__idx, "<<epIdx(0)<<");\n";
2224     if(isMigrationConstructor())
2225       str << "  CkRegisterMigCtor(__idx, "<<epIdx(0)<<");\n";
2226   }
2229 void Entry::preprocess() {
2230   ParamList *pl = param;
2231   if (pl != NULL && pl->hasConditional()) {
2232     XStr str;
2233     str << "MarshallMsg_" << epStr();
2234     NamedType *nt = new NamedType(strdup(str));
2235     MsgVar *var = new MsgVar(new BuiltinType("char"), "msgBuf", 0, 1);
2236     MsgVarList *list = new MsgVarList(var);
2237     do {
2238       if (pl->param->isConditional()) {
2239         var = new MsgVar(pl->param->getType(), pl->param->getName(), 1, 0);
2240         list = new MsgVarList(var, list);
2241       }
2242     } while (NULL!=(pl=pl->next));
2243     Message *m = new Message(-1, nt, list);
2244     m->setModule(container->containerModule);
2245     container->containerModule->prependConstruct(m);
2246   }
2248   // DMK - Accel Support
2249   // Count the total number of scalar and array parameters if this is an accelerated entry
2250   accel_numScalars = 0;
2251   accel_numArrays = 0;
2252   accel_dmaList_numReadOnly = 0;
2253   accel_dmaList_numReadWrite = 0;
2254   accel_dmaList_numWriteOnly = 0;
2255   accel_dmaList_scalarNeedsWrite = 0;
2256   if (isAccel()) {
2257     ParamList* curParam = param;
2258     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
2259     while (curParam != NULL) {
2260       if (curParam->param->isArray()) {
2261         accel_numArrays++;
2262         accel_dmaList_numReadOnly++;
2263       } else {
2264         accel_numScalars++;
2265       }
2266       curParam = curParam->next;
2267     }
2268     curParam = accelParam;
2269     while (curParam != NULL) {
2270       if (curParam->param->isArray()) {
2271         accel_numArrays++;
2272         switch (curParam->param->getAccelBufferType()) {
2273           case Parameter::ACCEL_BUFFER_TYPE_READWRITE:  accel_dmaList_numReadWrite++;  break;
2274           case Parameter::ACCEL_BUFFER_TYPE_READONLY:   accel_dmaList_numReadOnly++;   break;
2275           case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY:  accel_dmaList_numWriteOnly++;  break;
2276           default:     XLAT_ERROR_NOCOL("unknown accel param type", first_line_);      break;
2277         }
2278       } else {
2279         accel_numScalars++;
2280         switch (curParam->param->getAccelBufferType()) {
2281           case Parameter::ACCEL_BUFFER_TYPE_READWRITE:  accel_dmaList_scalarNeedsWrite++;  break;
2282           case Parameter::ACCEL_BUFFER_TYPE_READONLY:                                      break;
2283           case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY:  accel_dmaList_scalarNeedsWrite++;  break;
2284           default:     XLAT_ERROR_NOCOL("unknown accel param type", first_line_);          break;
2285         }
2286       }
2287       curParam = curParam->next;
2288     }
2289     if (accel_numScalars > 0) {
2290       if (accel_dmaList_scalarNeedsWrite) {
2291         accel_dmaList_numReadWrite++;
2292       } else {
2293         accel_dmaList_numReadOnly++;
2294       }
2295     }
2296   }
2300 int Entry::paramIsMarshalled(void) {
2301     return param->isMarshalled();
2304 int Entry::getStackSize(void) {
2305     return (stacksize ? stacksize->getIntVal() : 0);
2308 void Entry::setAccelParam(ParamList* apl) { accelParam = apl; }
2309 void Entry::setAccelCodeBody(XStr* acb) { accelCodeBody = acb; }
2310 void Entry::setAccelCallbackName(XStr* acbn) { accelCallbackName = acbn; }
2312 int Entry::isThreaded(void) { return (attribs & STHREADED); }
2313 int Entry::isSync(void) { return (attribs & SSYNC); }
2314 int Entry::isIget(void) { return (attribs & SIGET); }
2315 int Entry::isConstructor(void) { return !strcmp(name, container->baseName(0).get_string());}
2316 bool Entry::isMigrationConstructor() { return isConstructor() && (attribs & SMIGRATE); }
2317 int Entry::isExclusive(void) { return (attribs & SLOCKED); }
2318 int Entry::isImmediate(void) { return (attribs & SIMMEDIATE); }
2319 int Entry::isSkipscheduler(void) { return (attribs & SSKIPSCHED); }
2320 int Entry::isInline(void) { return attribs & SINLINE; }
2321 int Entry::isLocal(void) { return attribs & SLOCAL; }
2322 int Entry::isCreate(void) { return (attribs & SCREATEHERE)||(attribs & SCREATEHOME); }
2323 int Entry::isCreateHome(void) { return (attribs & SCREATEHOME); }
2324 int Entry::isCreateHere(void) { return (attribs & SCREATEHERE); }
2325 int Entry::isPython(void) { return (attribs & SPYTHON); }
2326 int Entry::isNoTrace(void) { return (attribs & SNOTRACE); }
2327 int Entry::isAppWork(void) { return (attribs & SAPPWORK); }
2328 int Entry::isNoKeep(void) { return (attribs & SNOKEEP); }
2329 int Entry::isSdag(void) { return (sdagCon!=0); }
2331 // DMK - Accel support
2332 int Entry::isAccel(void) { return (attribs & SACCEL); }
2334 int Entry::isMemCritical(void) { return (attribs & SMEM); }
2335 int Entry::isReductionTarget(void) { return (attribs & SREDUCE); }
2337 char *Entry::getEntryName() { return name; }
2338 int Entry::getLine() { return line; }
2340 }   // namespace xi